mirror of
https://git.proxmox.com/git/rustc
synced 2025-05-29 09:22:35 +00:00
Imported Upstream version 1.5.0+dfsg1
This commit is contained in:
parent
e9174d1eb2
commit
b039eaaf8a
180
AUTHORS.txt
180
AUTHORS.txt
@ -9,7 +9,9 @@ Aaron Todd <github@opprobrio.us>
|
||||
Aaron Turon <aturon@mozilla.com>
|
||||
Aaron Weiss <aaronweiss74@gmail.com>
|
||||
Abhishek Chanda <abhishek.becs@gmail.com>
|
||||
Adam Badawy <adambada@buffalo.edu>
|
||||
Adam Bozanich <adam.boz@gmail.com>
|
||||
Adam Crume <adamcrume@gmail.com>
|
||||
Adam Heins <mail@adamheins.com>
|
||||
Adam Jacob <adam@opscode.com>
|
||||
Adam Roben <adam@roben.org>
|
||||
@ -30,8 +32,10 @@ Alan Cutter <alancutter@chromium.org>
|
||||
Alan Williams <mralert@gmail.com>
|
||||
Aleksander Balicki <balicki.aleksander@gmail.com>
|
||||
Aleksandr Koshlo <sash7ko@gmail.com>
|
||||
Aleksey Kladov <aleksey.kladov@gmail.com>
|
||||
Alexander Artemenko <svetlyak.40wt@gmail.com>
|
||||
Alexander Bliskovsky <alexander.bliskovsky@gmail.com>
|
||||
Alexander Bulaev <aleks.bulaev@gmail.com>
|
||||
Alexander Campbell <alexanderhcampbell@gmail.com>
|
||||
Alexander Chernyakhovsky <achernya@mit.edu>
|
||||
Alexander Korolkov <alexander.korolkov@gmail.com>
|
||||
@ -42,19 +46,25 @@ Alexandre Gagnon <alxgnon@gmail.com>
|
||||
Alexandros Tasos <sdi1100085@di.uoa.gr>
|
||||
Alex Burka <durka42+github@gmail.com>
|
||||
Alex Crichton <alex@alexcrichton.com>
|
||||
AlexDenisov <1101.debian@gmail.com>
|
||||
Alexei Sholik <alcosholik@gmail.com>
|
||||
Alex Gaynor <alex.gaynor@gmail.com>
|
||||
Alexis Beingessner <a.beingessner@gmail.com>
|
||||
Alex Lyon <arcterus@mail.com>
|
||||
Alex Newman <posix4e@gmail.com>
|
||||
Alex Ozdemir <aozdemir@hmc.edu>
|
||||
Alex Quach <alex@clinkle.com>
|
||||
Alex Rønne Petersen <alex@lycus.org>
|
||||
Alex Stokes <r.alex.stokes@gmail.com>
|
||||
Alex Whitney <aw1209@ic.ac.uk>
|
||||
Alfie John <alfie@alfie.wtf>
|
||||
Alfie John <alfiej@fastmail.fm>
|
||||
Alisdair Owens <awo101@zepler.net>
|
||||
Ali Smesseim <smesseim.ali@gmail.com>
|
||||
Aljaž "g5pw" Srebrnič <a2piratesoft@gmail.com>
|
||||
Amanieu d'Antras <amanieu@gmail.com>
|
||||
Amit Aryeh Levy <amit@amitlevy.com>
|
||||
Amit Saha <amitsaha@users.noreply.github.com>
|
||||
Amol Mundayoor <amol.com@gmail.com>
|
||||
Amy Unger <amy.e.unger@gmail.com>
|
||||
Anatoly Ikorsky <aikorsky@gmail.com>
|
||||
@ -65,7 +75,9 @@ Andreas Gal <gal@mozilla.com>
|
||||
Andreas Martens <andreasm@fastmail.fm>
|
||||
Andreas Neuhaus <zargony@zargony.com>
|
||||
Andreas Ots <andreasots@gmail.com>
|
||||
Andreas Sommer <andreas.sommer87@googlemail.com>
|
||||
Andreas Tolfsen <ato@mozilla.com>
|
||||
Andre Bogus <bogusandre@gmail.com>
|
||||
Andrei Formiga <archimedes_siracusa@hotmail.com>
|
||||
Andrei Oprea <andrei.br92@gmail.com>
|
||||
Andrew Barchuk <raindev@icloud.com>
|
||||
@ -82,14 +94,18 @@ Andrew Poelstra <asp11@sfu.ca>
|
||||
Andrew Seidl <dev@aas.io>
|
||||
Andrew Straw <strawman@astraw.com>
|
||||
Andrew Wagner <drewm1980@gmail.com>
|
||||
androm3da <brian.cain@gmail.com>
|
||||
Andrzej Janik <vosen@vosen.pl>
|
||||
Andy Caldwell <andrew.caldwell@metaswitch.com>
|
||||
Andy Grover <agrover@redhat.com>
|
||||
angelsl <hidingfromhidden@gmail.com>
|
||||
Angus Lees <gus@inodes.org>
|
||||
Anthony Juckel <ajuckel@gmail.com>
|
||||
Anton Löfgren <anton.lofgren@gmail.com>
|
||||
Antti Keränen <detegr@gmail.com>
|
||||
aochagavia <aochagavia92@gmail.com>
|
||||
Aram Visser <aramvisser@gmail.com>
|
||||
arcnmx <arcnmx@users.noreply.github.com>
|
||||
Arcterus <Arcterus@mail.com>
|
||||
Areski Belaid <areski@gmail.com>
|
||||
Ariel Ben-Yehuda <arielb1@mail.tau.ac.il>
|
||||
@ -99,9 +115,11 @@ Armin Preiml <apreiml@strohwolke.at>
|
||||
Armin Ronacher <armin.ronacher@active-4.com>
|
||||
Arpad Borsos <arpad.borsos@googlemail.com>
|
||||
Artem <artemciy@gmail.com>
|
||||
Artem Shitov <artemshitov@yandex-team.ru>
|
||||
Arthur Liao <arthurtw8@gmail.com>
|
||||
arthurprs <arthurprs@gmail.com>
|
||||
arturo <arturo@openframeworks.cc>
|
||||
Ashkan Kiani <ashkan.k.kiani@gmail.com>
|
||||
Ashok Gautham <ScriptDevil@gmail.com>
|
||||
Augusto Hack <hack.augusto@gmail.com>
|
||||
auREAX <mark@xn--hwg34fba.ws>
|
||||
@ -113,8 +131,11 @@ Avdi Grimm <avdi@avdi.org>
|
||||
awlnx <alecweber1994@gmail.com>
|
||||
Axel Viala <axel.viala@darnuria.eu>
|
||||
Aydin Kim <ladinjin@hanmail.net>
|
||||
b1nd <clint.ryan3@gmail.com>
|
||||
bachm <Ab@vapor.com>
|
||||
Barosl LEE <github@barosl.com>
|
||||
Barosl Lee <vcs@barosl.com>
|
||||
Bastien Dejean <nihilhill@gmail.com>
|
||||
bcoopers <coopersmithbrian@gmail.com>
|
||||
Ben Alpert <ben@benalpert.com>
|
||||
benaryorg <binary@benary.org>
|
||||
@ -133,19 +154,24 @@ Benjamin Peterson <benjamin@python.org>
|
||||
Ben Kelly <ben@wanderview.com>
|
||||
Ben Noordhuis <info@bnoordhuis.nl>
|
||||
Ben Sago <ogham@users.noreply.github.com>
|
||||
benshu <benshu@benshu.de>
|
||||
Ben S <ogham@users.noreply.github.com>
|
||||
Ben Striegel <ben.striegel@gmail.com>
|
||||
Bhargav Patel <bhargavrpatel@users.noreply.github.com>
|
||||
Bheesham Persaud <bheesham123@hotmail.com>
|
||||
Bilal Husain <bilal@bilalhusain.com>
|
||||
Bill Fallon <bill.fallon@robos.li>
|
||||
Bill Myers <bill_myers@outlook.com>
|
||||
billpmurphy <billpmurphy92@gmail.com>
|
||||
Bill Wendling <wendling@apple.com>
|
||||
Birunthan Mohanathas <birunthan@mohanathas.com>
|
||||
Björn Steinbrink <bsteinbr@gmail.com>
|
||||
blackbeam <aikorsky@gmail.com>
|
||||
blake2-ppc <ulrik.sverdrup@gmail.com>
|
||||
Blake Loring <Blake.Loring@ig.com>
|
||||
bluss <bluss>
|
||||
bluss <bluss@users.noreply.github.com>
|
||||
Boris Egorov <egorov@linux.com>
|
||||
bombless <bombless@126.com>
|
||||
Boris Egorov <jightuse@gmail.com>
|
||||
bors <bors@rust-lang.org>
|
||||
Bouke van der Bijl <boukevanderbijl@gmail.com>
|
||||
Brad King <brad.king@kitware.com>
|
||||
@ -169,10 +195,14 @@ Brian Leibig <brian@brianleibig.com>
|
||||
Brian Quinlan <brian@sweetapp.com>
|
||||
Brody Holden <brody.holden.r@gmail.com>
|
||||
Bruno de Oliveira Abinader <bruno.d@partner.samsung.com>
|
||||
Bruno Tavares <connect+github@bltavares.com>
|
||||
Bryan Dunsmore <dunsmoreb@gmail.com>
|
||||
Bryce Van Dyk <bryce@vandyk.net.nz>
|
||||
Byron Williams <byron@112percent.com>
|
||||
Cadence Marseille <cadencemarseille@gmail.com>
|
||||
caipre <platt.nicholas@gmail.com>
|
||||
Caitlin Potter <snowball@defpixel.com>
|
||||
Cameron Sun <cameron.csun@gmail.com>
|
||||
Cameron Zwarich <zwarich@mozilla.com>
|
||||
Camille Roussel <camille@rousselfamily.com>
|
||||
Camille TJHOA <camille.tjhoa@outlook.com>
|
||||
@ -180,18 +210,25 @@ Cam Jackson <camjackson89@gmail.com>
|
||||
Carl-Anton Ingmarsson <mail@carlanton.se>
|
||||
Carl Lerche <me@carllerche.com>
|
||||
Carlos Galarza <carloslfu@gmail.com>
|
||||
Carlos Liam <carlos@aarzee.me>
|
||||
Carlos <toqueteos@gmail.com>
|
||||
Carol (Nichols || Goulding) <carol.nichols@gmail.com>
|
||||
Carol Willing <carolcode@willingconsulting.com>
|
||||
Carter Hinsley <carterhinsley@gmail.com>
|
||||
Carter Tazio Schonwald <carter.schonwald@gmail.com>
|
||||
CarVac <c.lo.to.da.down.lo@gmail.com>
|
||||
Caspar Krieger <caspar@asparck.com>
|
||||
Cesar Eduardo Barros <cesarb@cesarb.eti.br>
|
||||
Charlotte Spencer <charlottelaspencer@gmail.com>
|
||||
Chase Southwood <chase.southwood@gmail.com>
|
||||
Ches Martin <ches@whiskeyandgrits.net>
|
||||
chitra
|
||||
chitra <bogus>
|
||||
Chloe <5paceToast@users.noreply.github.com>
|
||||
Chris C Cerami <chrisccerami@users.noreply.github.com>
|
||||
Chris Double <chris.double@double.co.nz>
|
||||
Chris Drake <cjdrake@gmail.com>
|
||||
Chris Hellmuth <chellmuth@gmail.com>
|
||||
Chris Krycho <chris@krycho.com>
|
||||
Chris Morgan <me@chrismorgan.info>
|
||||
Chris Nixon <chris.nixon@sigma.me.uk>
|
||||
Chris Peterson <cpeterson@mozilla.com>
|
||||
@ -205,6 +242,7 @@ Christian Weinz <christian@madez.de>
|
||||
Christoph Burgdorf <christoph.burgdorf@bvsn.org>
|
||||
Christopher Bergqvist <spambox0@digitalpoetry.se>
|
||||
Christopher Chambers <chris.chambers@peanutcode.com>
|
||||
christopherdumas <christopherdumas@me.com>
|
||||
Christopher Kendell <ckendell@outlook.com>
|
||||
Chris Wong <lambda.fairy@gmail.com>
|
||||
chromatic <chromatic@wgz.org>
|
||||
@ -220,18 +258,25 @@ Cole Mickens <cole.mickens@gmail.com>
|
||||
Cole Reynolds <cpjreynolds@gmail.com>
|
||||
Colin Davidson <colrdavidson@gmail.com>
|
||||
Colin Sherratt <colin.sherratt@gmail.com>
|
||||
Colin Wallace <wallacoloo@gmail.com>
|
||||
Colin Walters <walters@verbum.org>
|
||||
comex <comexk@gmail.com>
|
||||
Conrad Kleinespel <conradk@conradk.com>
|
||||
corentih <corentin.henry@alcatel-lucent.com>
|
||||
Corentin Henry <corentinhenry@gmail.com>
|
||||
Corey Farwell <coreyf+rust@rwell.org>
|
||||
Corey Ford <corey@coreyford.name>
|
||||
Corey Richardson <corey@octayn.net>
|
||||
Cornel Punga <cornel.punga@gmail.com>
|
||||
Craig Hills <chills@gmail.com>
|
||||
crhino <piraino.chris@gmail.com>
|
||||
Cristian Kubis <cristian.kubis@tsunix.de>
|
||||
Cristi Burcă <scribu@gmail.com>
|
||||
Cristi Cobzarenco <cristi.cobzarenco@gmail.com>
|
||||
critiqjo <john.ch.fr@gmail.com>
|
||||
Cruz Julian Bishop <cruzjbishop@gmail.com>
|
||||
Daan Rijks <daanrijks@gmail.com>
|
||||
Dabo Ross <daboross@daboross.net>
|
||||
Damian Gryski <damian@gryski.com>
|
||||
Damien Grassart <damien@grassart.com>
|
||||
Damien Radtke <dradtke@channeliq.com>
|
||||
@ -242,11 +287,13 @@ Dan Callahan <dan.callahan@gmail.com>
|
||||
Dan Connolly <dckc@madmode.com>
|
||||
Daniel Albert <albert_daniel@t-online.de>
|
||||
Daniel Brooks <db48x@db48x.net>
|
||||
Daniel Carral <dan@dcarral.org>
|
||||
Daniel Fagnan <dnfagnan@gmail.com>
|
||||
Daniel Farina <daniel@fdr.io>
|
||||
Daniel Griffen <daniel@dgriffen.com>
|
||||
Daniel Grunwald <daniel@danielgrunwald.de>
|
||||
Daniel Hofstetter <daniel.hofstetter@42dh.com>
|
||||
Daniel Keep <daniel.keep@gmail.com>
|
||||
Daniel Lobato García <elobatocs@gmail.com>
|
||||
Daniel Luz <dev@mernen.com>
|
||||
Daniel MacDougall <dmacdougall@gmail.com>
|
||||
@ -255,9 +302,12 @@ Daniel Patterson <dbp@riseup.net>
|
||||
Daniel Raloff <draloff@side2.com>
|
||||
Daniel Ralston <Wubbulous@gmail.com>
|
||||
Daniel Ramos <dan@daramos.com>
|
||||
Daniel Rollins <drollins@financialforce.com>
|
||||
Daniel Rosenwasser <DanielRosenwasser@gmail.com>
|
||||
Daniel Trebbien <dtrebbien@gmail.com>
|
||||
Daniel Ursache Dogariu <contact@danniel.net>
|
||||
Daniil Smirnov <danslapman@gmail.com>
|
||||
Danilo Bargen <mail@dbrgn.ch>
|
||||
Dan Luu <danluu@gmail.com>
|
||||
Dan Schatzberg <schatzberg.dan@gmail.com>
|
||||
Dan W. <1danwade@gmail.com>
|
||||
@ -265,11 +315,13 @@ Dan Yang <dsyang@fb.com>
|
||||
Darin Morrison <darinmorrison+git@gmail.com>
|
||||
darkf <lw9k123@gmail.com>
|
||||
Darrell Hamilton <darrell.noice@gmail.com>
|
||||
Dato Simó <dato@net.com.org.es>
|
||||
Dave Herman <dherman@mozilla.com>
|
||||
Dave Hodder <dmh@dmh.org.uk>
|
||||
Dave Huseby <dhuseby@mozilla.com>
|
||||
David Campbell <dcampbell24@gmail.com>
|
||||
David Creswick <dcrewi@gyrae.net>
|
||||
David Elliott <david@gophilosophie.com>
|
||||
David Forsythe <dforsythe@gmail.com>
|
||||
David Halperin <halperin.dr@gmail.com>
|
||||
David King <dave@davbo.org>
|
||||
@ -279,17 +331,21 @@ David Manescu <david.manescu@gmail.com>
|
||||
David Rajchenbach-Teller <dteller@mozilla.com>
|
||||
David Reid <dreid@dreid.org>
|
||||
David Renshaw <dwrenshaw@gmail.com>
|
||||
David Ripton <dripton@ripton.net>
|
||||
David Ross <daboross@daboross.net>
|
||||
David Stygstra <david.stygstra@gmail.com>
|
||||
David Szotten <davidszotten@gmail.com>
|
||||
David Vazgenovich Shakaryan <dvshakaryan@gmail.com>
|
||||
David Voit <david.voit@gmail.com>
|
||||
Davis Silverman <sinistersnare@gmail.com>
|
||||
defuz <defuz.net@gmail.com>
|
||||
Denis Defreyne <denis.defreyne@stoneship.org>
|
||||
DenisKolodin <DenisKolodin@gmail.com>
|
||||
Derecho <derecho@sector5d.org>
|
||||
Derek Chiang <derekchiang93@gmail.com>
|
||||
Derek Guenther <dguenther9@gmail.com>
|
||||
Derek Harland <derek.harland@finq.co.nz>
|
||||
Devon Hollowood <devonhollowood@gmail.com>
|
||||
dgoon <dgoon@dgoon.net>
|
||||
diaphore <diaphore@gmail.com>
|
||||
Diego Giagio <diego@giagio.com>
|
||||
@ -311,10 +367,13 @@ Dmitry Vasiliev <dima@hlabs.org>
|
||||
Dominick Allen <dominick.allen1989@gmail.com>
|
||||
Dominic van Berkel <dominic@baudvine.net>
|
||||
Dominik Inführ <dominik.infuehr@gmail.com>
|
||||
Dongie Agnir <dongie.agnir@gmail.com>
|
||||
Dong Zhou <dong.zhou.08@gmail.com>
|
||||
Do Nhat Minh <mrordinaire@gmail.com>
|
||||
donkopotamus <general@chocolate-fish.com>
|
||||
Donovan Preston <donovanpreston@gmail.com>
|
||||
Don Petersen <don@donpetersen.net>
|
||||
Doug Goldstein <cardoe@cardoe.com>
|
||||
Douglas Young <rcxdude@gmail.com>
|
||||
Drew Crawford <drew@sealedabstract.com>
|
||||
Drew Willcoxon <adw@mozilla.com>
|
||||
@ -322,8 +381,10 @@ Duane Edwards <mail@duaneedwards.net>
|
||||
Duncan Regan <duncanregan@gmail.com>
|
||||
Dylan Braithwaite <dylanbraithwaite1@gmail.com>
|
||||
Dylan Ede <dylanede@googlemail.com>
|
||||
Dylan McKay <dylanmckay34@gmail.com>
|
||||
Dzmitry Malyshau <kvarkus@gmail.com>
|
||||
Earl St Sauver <estsauver@gmail.com>
|
||||
ebadf <brian.cain@gmail.com>
|
||||
econoplas <econoplas@gmail.com>
|
||||
Eduard Bopp <eduard.bopp@aepsil0n.de>
|
||||
Eduard Burtescu <edy.burt@gmail.com>
|
||||
@ -339,12 +400,14 @@ Elliott Slaughter <elliottslaughter@gmail.com>
|
||||
Elly Fong-Jones <elly@leptoquark.net>
|
||||
elszben <notgonna@tellyou>
|
||||
emanueLczirai <emanueLczirai@cryptoLab.net>
|
||||
Emanuel Czirai <zazdxscf@gmail.com>
|
||||
Emanuel Rylke <ema-fox@web.de>
|
||||
Emeliov Dmitrii <demelev1990@gmail.com>
|
||||
Emilio Cobos Álvarez <ecoal95@gmail.com>
|
||||
Emily Dunham <edunham@mozilla.com>
|
||||
Eric Allen <ericpallen@gmail.com>
|
||||
Eric Biggers <ebiggers3@gmail.com>
|
||||
Eric Findlay <e.findlay@protonmail.com>
|
||||
Eric Holk <eric.holk@gmail.com>
|
||||
Eric Holmes <eric@ejholmes.net>
|
||||
Eric Kidd <git@randomhacks.net>
|
||||
@ -354,6 +417,7 @@ Eric Martin <e.a.martin1337@gmail.com>
|
||||
Eric Platon <eric.platon@waku-waku.ne.jp>
|
||||
Eric Reed <ecreed@cs.washington.edu>
|
||||
Eric Ye <me@ericye16.com>
|
||||
Erik Davidson <erik@erikd.org>
|
||||
Erik Lyon <elyon001@local.fake>
|
||||
Erik Michaels-Ober <sferik@gmail.com>
|
||||
Erik Price <erik.price16@gmail.com>
|
||||
@ -366,8 +430,9 @@ Eunchong Yu <kroisse@gmail.com>
|
||||
Eunji Jeong <eun-ji.jeong@samsung.com>
|
||||
Evan Klitzke <evan@eklitzke.org>
|
||||
Evan McClanahan <evan@evanmcc.com>
|
||||
Evgeny Sologubov
|
||||
Evgeny Sologubov <bogus>
|
||||
Fabian Deutsch <fabian.deutsch@gmx.de>
|
||||
Fabiano Beselga <fabianobeselga@gmail.com>
|
||||
Fabrice Desré <fabrice@desre.org>
|
||||
FakeKane <andrewyli@gmail.com>
|
||||
Falco Hirschenberger <falco.hirschenberger@gmail.com>
|
||||
@ -378,7 +443,7 @@ Felix S. Klock II <pnkfelix@pnkfx.org>
|
||||
fenduru <fenduru@users.noreply.github.com>
|
||||
Fenhl <fenhl@fenhl.net>
|
||||
Filip Szczepański <jazz2rulez@gmail.com>
|
||||
Flaper Fesp <flaper87@gmail.com>
|
||||
Flavio Percoco <flaper87@gmail.com>
|
||||
flo-l <lacknerflo@gmail.com>
|
||||
Florian Gilcher <florian.gilcher@asquera.de>
|
||||
Florian Hahn <flo@fhahn.com>
|
||||
@ -418,11 +483,13 @@ Germano Gabbianelli <tyrion@users.noreply.github.com>
|
||||
Gil Cottle <rc@redtown.org>
|
||||
Gioele Barabucci <gioele@svario.it>
|
||||
github-monoculture <eocene@gmx.com>
|
||||
GlacJAY <glacjay@gmail.com>
|
||||
Gleb Kozyrev <gleb@gkoz.com>
|
||||
glendc <decauwsemaecker.glen@gmail.com>
|
||||
Glenn Willen <gwillen@nerdnet.org>
|
||||
Gonçalo Cabrita <_@gmcabrita.com>
|
||||
Grahame Bowland <grahame@angrygoats.net>
|
||||
Graham Fawcett <graham.fawcett@gmail.com>
|
||||
Graham Fawcett <fawcett@uwindsor.ca>
|
||||
Graydon Hoare <graydon@pobox.com>
|
||||
Greg Chapple <gregchapple1@gmail.com>
|
||||
Grigoriy <ohaistarlight@gmail.com>
|
||||
@ -447,6 +514,7 @@ Honza Strnad <hanny.strnad@gmail.com>
|
||||
Huachao Huang <huachao.huang@gmail.com>
|
||||
Hugo Jobling <hello@thisishugo.com>
|
||||
Hugo van der Wijst <hugo@wij.st>
|
||||
Hunan Rostomyan <hunan131@gmail.com>
|
||||
Huon Wilson <dbau.pp+github@gmail.com>
|
||||
Hyeon Kim <simnalamburt@gmail.com>
|
||||
Ian Connolly <iconnolly@mozilla.com>
|
||||
@ -454,22 +522,30 @@ Ian Daniher <it.daniher@gmail.com>
|
||||
Ian D. Bollinger <ian.bollinger@gmail.com>
|
||||
Ignacio Corderi <icorderi@msn.com>
|
||||
Igor Bukanov <igor@mir2.org>
|
||||
Igor Shuvalov <i.s.shuvalov@gmail.com>
|
||||
Igor Strebezhev <xamgore@ya.ru>
|
||||
Ilya Dmitrichenko <ilya@xively.com>
|
||||
Ilyong Cho <ilyoan@gmail.com>
|
||||
Ingo Blechschmidt <iblech@web.de>
|
||||
inrustwetrust <inrustwetrust@users.noreply.github.com>
|
||||
Irving A.J. Rivas Z. <axel.rivas@gmail.com>
|
||||
Isaac Aggrey <isaac.aggrey@gmail.com>
|
||||
Isaac Dupree <antispam@idupree.com>
|
||||
Isaac Ge <acgtyrant@gmail.com>
|
||||
Ivan Enderlin <ivan.enderlin@hoa-project.net>
|
||||
Ivan Ivaschenko <defuz.net@gmail.com>
|
||||
Ivan Jager <aij+git@mrph.org>
|
||||
Ivan Kozik <ivan@ludios.org>
|
||||
Ivano Coppola <rgbfirefox@gmail.com>
|
||||
Ivan Petkov <ivanppetkov@gmail.com>
|
||||
Ivan Radanov Ivanov <ivanradanov@yahoo.co.uk>
|
||||
Ivan Stankovic <pokemon@fly.srk.fer.hr>
|
||||
Ivan Ukhov <ivan.ukhov@gmail.com>
|
||||
Iven Hsu <ivenvd@gmail.com>
|
||||
Jack Fransham <moonfudgeman@hotmail.co.uk>
|
||||
Jack Heizer <jack.heizer@gmail.com>
|
||||
Jack Moffitt <jack@metajack.im>
|
||||
Jack Wilson <jack.wilson.v@gmail.com>
|
||||
Jacob Edelman <edelman.jd@gmail.com>
|
||||
Jacob Harris Cryer Kragh <jhckragh@gmail.com>
|
||||
Jacob Hegna <jacobhegna@gmail.com>
|
||||
@ -481,14 +557,18 @@ Jake Hickey <empty@cqdr.es>
|
||||
Jake Kaufman <theevocater@gmail.com>
|
||||
Jake Kerr <kodafox@gmail.com>
|
||||
Jake Scott <jake.net@gmail.com>
|
||||
Jake Shadle <jake.shadle@frostbite.com>
|
||||
Jake Worth <jakeworth82@gmail.com>
|
||||
Jakub Bukaj <jakub@jakub.cc>
|
||||
Jakub Vrána <jakub@vrana.cz>
|
||||
Jakub Wieczorek <jakubw@jakubw.net>
|
||||
James Bell <james.bell@gmail.com>
|
||||
James Deng <cnjamesdeng@gmail.com>
|
||||
James Hurst <jamesrhurst@users.noreply.github.com>
|
||||
James Lal <james@lightsofapollo.com>
|
||||
James Laverack <james@jameslaverack.com>
|
||||
jamesluke <jamesluke@users.noreply.github.com>
|
||||
James McGlashan <github@darkfox.id.au>
|
||||
James Miller <bladeon@gmail.com>
|
||||
James Perry <james.austin.perry@gmail.com>
|
||||
James Rowe <jroweboy@gmail.com>
|
||||
@ -518,6 +598,7 @@ Jay True <glacjay@gmail.com>
|
||||
J Bailey <jj2baile@uwaterloo.ca>
|
||||
jbranchaud <jbranchaud@gmail.com>
|
||||
J.C. Moyer <jmoyer1992@gmail.com>
|
||||
Jean Maillard <jeanm@users.noreply.github.com>
|
||||
Jeaye <jeaye@arrownext.com>
|
||||
Jed Davis <jld@panix.com>
|
||||
Jed Estep <aje@jhu.edu>
|
||||
@ -527,6 +608,7 @@ Jeff Belgum <jeffbelgum@gmail.com>
|
||||
Jeff Muizelaar <jmuizelaar@mozilla.com>
|
||||
Jeff Olson <olson.jeffery@gmail.com>
|
||||
Jeff Parsons <jeffdougson@gmail.com>
|
||||
Jeffrey Seyfried <jeffrey.seyfried@gmail.com>
|
||||
Jeffrey Yasskin <jyasskin@gmail.com>
|
||||
Jelte Fennema <github-tech@jeltef.nl>
|
||||
Jens Nockert <jens@nockert.se>
|
||||
@ -539,10 +621,11 @@ Jesse Ray <jesse@localhost.localdomain>
|
||||
Jesse Ruderman <jruderman@gmail.com>
|
||||
Jessy Diamond Exum <jessy.diamondman@gmail.com>
|
||||
Jesús Espino <jespinog@gmail.com>
|
||||
Jethro Beekman <jethro@jbeekman.nl>
|
||||
jethrogb <github@jbeekman.nl>
|
||||
Jexell <Jexell@users.noreply.github.com>
|
||||
Jihyeok Seo <me@limeburst.net>
|
||||
Jihyun Yu <j.yu@navercorp.com>
|
||||
Jihyun Yu <jihyun@nclab.kaist.ac.kr>
|
||||
Jim Apple <jbapple+rust@google.com>
|
||||
Jim Blandy <jimb@red-bean.com>
|
||||
Jimmie Elvenmark <flugsio@gmail.com>
|
||||
@ -554,13 +637,14 @@ J. J. Weber <jjweber@gmail.com>
|
||||
jmgrosen <jmgrosen@gmail.com>
|
||||
jmu303 <muj@bc.edu>
|
||||
João Oliveira <hello@jxs.pt>
|
||||
joaoxsouls <joaoxsouls@gmail.com>
|
||||
Joe Pletcher <joepletcher@gmail.com>
|
||||
Joe Schafer <joe@jschaf.com>
|
||||
Johannes Hoff <johshoff@gmail.com>
|
||||
Johannes Löthberg <johannes@kyriasis.com>
|
||||
Johannes Muenzel <jmuenzel@gmail.com>
|
||||
Johannes Oertel <johannes.oertel@uni-due.de>
|
||||
Johann Hofmann <git@johann-hofmann.com>
|
||||
Johann Hofmann <mail@johann-hofmann.com>
|
||||
Johann Tuffe <tafia973@gmail.com>
|
||||
John Albietz <inthecloud247@gmail.com>
|
||||
John Barker <jebarker@gmail.com>
|
||||
@ -575,10 +659,12 @@ John Louis Walker <injyuw@gmail.com>
|
||||
John Schmidt <john.schmidt.h@gmail.com>
|
||||
John Simon <john@johnsoft.com>
|
||||
John Talling <inrustwetrust@users.noreply.github.com>
|
||||
John Thomas <thomas07@vt.edu>
|
||||
John Van Enk <vanenkj@gmail.com>
|
||||
John Zhang <john@zhang.io>
|
||||
joliv <joliv@users.noreply.github.com>
|
||||
Jonas Hietala <tradet.h@gmail.com>
|
||||
Jonas Schievink <jonas@schievink.net>
|
||||
Jonathan Bailey <jbailey@mozilla.com>
|
||||
Jonathan Boyett <jonathan@failingservers.com>
|
||||
Jonathan Hansford <dangthrimble@hansfords.net>
|
||||
@ -593,25 +679,32 @@ Joonas Javanainen <joonas.javanainen@gmail.com>
|
||||
Jordan Humphreys <mrsweaters@users.noreply.github.com>
|
||||
Jordan Woehr <jordanwoehr@gmail.com>
|
||||
Jordi Boggiano <j.boggiano@seld.be>
|
||||
Jorge Aparicio <japaricious@gmail.com>
|
||||
Jorge Aparicio <japaric@linux.com>
|
||||
Jorge Israel Peña <jorge.israel.p@gmail.com>
|
||||
Joris Rehm <joris.rehm@wakusei.fr>
|
||||
Jormundir <Chaseph@gmail.com>
|
||||
Jørn Lode <jlode90@gmail.com>
|
||||
Jose Narvaez <jnarvaez@zendesk.com>
|
||||
Joseph Caudle <joseph@josephcaudle.com>
|
||||
Joseph Crail <jbcrail@gmail.com>
|
||||
Joseph Martin <pythoner6@gmail.com>
|
||||
Joseph Rushton Wakeling <joe@webdrake.net>
|
||||
Josh Austin <josh.austin@gmail.com>
|
||||
Josh Haberman <jhaberman@gmail.com>
|
||||
Josh Matthews <josh@joshmatthews.net>
|
||||
Josh Stone <cuviper@gmail.com>
|
||||
Josh Triplett <josh@joshtriplett.org>
|
||||
Joshua Clark <joshua.clark@txstate.edu>
|
||||
Joshua Holmer <holmerj@uindy.edu>
|
||||
Joshua Landau <joshua@landau.ws>
|
||||
Joshua Wise <joshua@joshuawise.com>
|
||||
Joshua Yanovski <pythonesque@gmail.com>
|
||||
jotomicron <jotomicron@gmail.com>
|
||||
JP-Ellis <coujellis@gmail.com>
|
||||
JP Sugarbroad <jpsugar@google.com>
|
||||
jrburke <jrburke@gmail.com>
|
||||
jrincayc <jrincayc@users.noreply.github.com>
|
||||
J. Ryan Stinnett <jryans@gmail.com>
|
||||
Julia Evans <julia@jvns.ca>
|
||||
Julian Orth <ju.orth@gmail.com>
|
||||
Julian Viereck <julian.viereck@gmail.com>
|
||||
@ -640,12 +733,15 @@ Kevin Murphy <kemurphy.cmu@gmail.com>
|
||||
Kevin Rauwolf <sweetpea-git@tentacle.net>
|
||||
Kevin Walter <kevin.walter.private@googlemail.com>
|
||||
Kevin Yap <me@kevinyap.ca>
|
||||
Kevin Yeh <kevinyeah@utexas.edu>
|
||||
kgv <mail@kgv.name>
|
||||
kickinbahk <kickinbahk@gmail.com>
|
||||
Kieran Hunt <kieran.hunt92@gmail.com>
|
||||
Kiet Tran <ktt3ja@gmail.com>
|
||||
Kim Røen <kim@pam.no>
|
||||
kjpgit <kjpgit@users.noreply.github.com>
|
||||
klutzy <klutzytheklutzy@gmail.com>
|
||||
Kohei Hasegawa <ameutau@gmail.com>
|
||||
KokaKiwi <kokakiwi+rust@kokakiwi.net>
|
||||
korenchkin <korenchkin2@gmail.com>
|
||||
Kornel Lesiński <kornel@geekhood.net>
|
||||
@ -657,6 +753,8 @@ Kubilay Kocak <koobs@users.noreply.github.com>
|
||||
kulakowski <george.kulakowski@gmail.com>
|
||||
kwantam <kwantam@gmail.com>
|
||||
Kyeongwoon Lee <kyeongwoon.lee@samsung.com>
|
||||
Kyle Mayes <kyle@mayeses.com>
|
||||
Kyle Robinson Young <kyle@dontkry.com>
|
||||
Lai Jiangshan <laijs@cn.fujitsu.com>
|
||||
Lars Bergstrom <lbergstrom@mozilla.com>
|
||||
Laurence Tratt <laurie@tratt.net>
|
||||
@ -666,6 +764,7 @@ Lawrence Velázquez <larryv@alum.mit.edu>
|
||||
Leah Hanson <astrieanna@gmail.com>
|
||||
Lee Aronson <lee@libertad.ucsd.edu>
|
||||
Lee Jeffery <leejeffery@gmail.com>
|
||||
Lee Jenkins <cljenkins9@gmail.com>
|
||||
Lee Wondong <wdlee91@gmail.com>
|
||||
Leif Arne Storset <leifarne@storset.net>
|
||||
LemmingAvalanche <haugsbakk@yahoo.no>
|
||||
@ -678,6 +777,7 @@ Liam Monahan <liam@monahan.io>
|
||||
Liigo Zhuang <com.liigo@gmail.com>
|
||||
Lindsey Kuper <lindsey@composition.al>
|
||||
Lionel Flandrin <lionel.flandrin@parrot.com>
|
||||
llogiq <bogusandre@gmail.com>
|
||||
Logan Chien <tzuhsiang.chien@gmail.com>
|
||||
Loïc Damien <loic.damien@dzamlo.ch>
|
||||
Lorenz <lorenzb@student.ethz.ch>
|
||||
@ -701,7 +801,10 @@ Makoto Kato <m_kato@ga2.so-net.ne.jp>
|
||||
Makoto Nakashima <makoto.nksm+github@gmail.com>
|
||||
Manish Goregaokar <manishsmail@gmail.com>
|
||||
Manuel Hoffmann <manuel@polythematik.de>
|
||||
Marc-Antoine Perennou <Marc-Antoine@Perennou.com>
|
||||
marcell <marcell.pardavi@gmail.com>
|
||||
Marcello Seri <marcello.seri@gmail.com>
|
||||
Marcell Pardavi <marcell.pardavi@gmail.com>
|
||||
Marcel Müller <neikos@neikos.email>
|
||||
Marcel Rodrigues <marcelgmr@gmail.com>
|
||||
Marcus Klaas <mail@marcusklaas.nl>
|
||||
@ -712,6 +815,7 @@ Mário Feroldi <thelost-t@live.com>
|
||||
Mark Buer <mark.buer@booktrack.com>
|
||||
Mark Lacey <641@rudkx.com>
|
||||
Mark Mossberg <mark.mossberg@gmail.com>
|
||||
Marko Lalic <marko.lalic@gmail.com>
|
||||
Mark Rowe <mrowe@bdash.net.nz>
|
||||
Mark Sinclair <mark.edward.x@gmail.com>
|
||||
Markus Siemens <siemens1993@gmail.com>
|
||||
@ -721,9 +825,11 @@ Mark Vian <mrv.caseus@gmail.com>
|
||||
Martin DeMello <martindemello@gmail.com>
|
||||
Martin Olsson <martin@minimum.se>
|
||||
Martin Pool <mbp@sourcefrog.net>
|
||||
Martin Wernstål <m4rw3r@gmail.com>
|
||||
Marti Raudsepp <marti@juffo.org>
|
||||
Marvin Löbel <loebel.marvin@gmail.com>
|
||||
masklinn <github.com@masklinn.net>
|
||||
Matěj Grabovský <mgrabovsky@yahoo.com>
|
||||
Matej Lach <matej.lach@gmail.com>
|
||||
Mateusz Czapliński <czapkofan@gmail.com>
|
||||
Mathieu David <mathieudavid@mathieudavid.org>
|
||||
@ -740,7 +846,9 @@ Matthew Auld <matthew.auld@intel.com>
|
||||
Matthew Iselin <matthew@theiselins.net>
|
||||
Matthew McPherrin <matthew@mcpherrin.ca>
|
||||
Matthew O'Connor <thegreendragon@gmail.com>
|
||||
Matthias Bussonnier <bussonniermatthias@gmail.com>
|
||||
Matthias Einwag <matthias.einwag@live.com>
|
||||
Matthias Kauer <mk.software@zuez.org>
|
||||
Matthijs Hofstra <thiezz@gmail.com>
|
||||
Matthijs van der Vleuten <git@zr40.nl>
|
||||
Matt McPherrin <git@mcpherrin.ca>
|
||||
@ -762,15 +870,18 @@ Michael Alexander <beefsack@gmail.com>
|
||||
Michael Arntzenius <daekharel@gmail.com>
|
||||
Michael Bebenita <mbebenita@mozilla.com>
|
||||
Michael Budde <mbudde@gmail.com>
|
||||
Michael Choate <choatemd@miamioh.edu>
|
||||
Michael Dagitses <dagitses@google.com>
|
||||
Michael Darakananda <pongad@gmail.com>
|
||||
Michael Fairley <michaelfairley@gmail.com>
|
||||
Michael Gehring <mg@ebfe.org>
|
||||
Michael Howell <michael@notriddle.com>
|
||||
Michael Kainer <kaini1123@gmail.com>
|
||||
Michael Layzell <michael@thelayzells.com>
|
||||
Michael Letterle <michael.letterle@gmail.com>
|
||||
Michael Macias <zaeleus@gmail.com>
|
||||
Michael Matuzak <mmatuzak@gmail.com>
|
||||
Michael McConville <mmcconville@mykolab.com>
|
||||
Michael Neumann <mneumann@ntecs.de>
|
||||
Michael Pankov <work@michaelpankov.com>
|
||||
Michael Park <mcypark@gmail.com>
|
||||
@ -790,10 +901,12 @@ Mickaël Raybaud-Roig <raybaudroigm@gmail.com>
|
||||
Mickaël Salaün <mic@digikod.net>
|
||||
Mick Koch <kchmck@gmail.com>
|
||||
midinastasurazz <mpavlovsky@gmail.com>
|
||||
Mihaly Barasz <klao@nilcons.com>
|
||||
Mihnea Dobrescu-Balaur <mihnea@linux.com>
|
||||
Mike Boutin <mike.boutin@gmail.com>
|
||||
Mike Dilger <mike@efx.co.nz>
|
||||
Mike English <mike.english@atomicobject.com>
|
||||
Mike Marcacci <mike.marcacci@gmail.com>
|
||||
Mike Pedersen <noctune9@gmail.com>
|
||||
Mike Robinson <mikeprobinsonuk@gmail.com>
|
||||
Mike Sampson <mike@sambodata.com>
|
||||
@ -814,6 +927,7 @@ nathan dotz <nathan.dotz@gmail.com>
|
||||
Nathan Froyd <froydnj@gmail.com>
|
||||
Nathaniel Herman <nherman@post.harvard.edu>
|
||||
Nathaniel Theis <nttheis@gmail.com>
|
||||
Nathan Kleyn <nathan@nathankleyn.com>
|
||||
Nathan Long <nathanmlong@gmail.com>
|
||||
Nathan Stoddard <nstodda@purdue.edu>
|
||||
Nathan Typanski <ntypanski@gmail.com>
|
||||
@ -822,9 +936,11 @@ Nathan Zadoks <nathan@nathan7.eu>
|
||||
Neil Pankey <npankey@gmail.com>
|
||||
Nelo Onyiah <nelo.onyiah@gmail.com>
|
||||
Nelson Chen <crazysim@gmail.com>
|
||||
nham <hamann.nick@gmail.com>
|
||||
NiccosSystem <niccossystem@gmail.com>
|
||||
Nicholas Bishop <nicholasbishop@gmail.com>
|
||||
Nicholas Mazzuca <npmazzuca@gmail.com>
|
||||
Nicholas Seckar <nseckar@gmail.com>
|
||||
Nick Cameron <ncameron@mozilla.com>
|
||||
Nick Desaulniers <ndesaulniers@mozilla.com>
|
||||
Nick Fitzgerald <fitzgen@gmail.com>
|
||||
@ -839,9 +955,11 @@ Niels langager Ellegaard <niels.ellegaard@gmail.com>
|
||||
Nif Ward <nif.ward@gmail.com>
|
||||
Nikita Pekin <contact@nikitapek.in>
|
||||
Niklas Koep <niklas.koep@gmail.com>
|
||||
Nikolay Kondratyev <nkondratyev@yandex.ru>
|
||||
Niko Matsakis <niko@alum.mit.edu>
|
||||
Nils Liberg <nils@nilsliberg.se>
|
||||
Nils Winter <nils.winter@gmail.com>
|
||||
Niranjan Padmanabhan <niranjan.padmanabhan@cloudera.com>
|
||||
noam <noam@clusterfoo.com>
|
||||
Noam Yorav-Raphael <noamraph@gmail.com>
|
||||
NODA, Kai <nodakai@gmail.com>
|
||||
@ -849,25 +967,31 @@ Noufal Ibrahim <noufal@nibrahim.net.in>
|
||||
novalis <novalis@novalis.org>
|
||||
nsf <no.smile.face@gmail.com>
|
||||
nwin <nwin@users.noreply.github.com>
|
||||
nxnfufunezn <nxnfufunezn@gmail.com>
|
||||
Oak <White-Oak@users.noreply.github.com>
|
||||
OGINO Masanori <masanori.ogino@gmail.com>
|
||||
OlegTsyba <idethrone1@gmail.com>
|
||||
Oliver Schneider <git1984941651981@oli-obk.de>
|
||||
Ole Krüger <ole@kru.gr>
|
||||
Oliver Middleton <olliemail27@gmail.com>
|
||||
Oliver Schneider <oliver.schneider@kit.edu>
|
||||
Olivier Saut <osaut@airpost.net>
|
||||
olivren <o.renaud@gmx.fr>
|
||||
Olle Jonsson <olle.jonsson@gmail.com>
|
||||
olombard <lombard-olivier@bbox.fr>
|
||||
Or Brostovski <tohava@gmail.com>
|
||||
Oren Hazi <oren.hazi@gmail.com>
|
||||
Ori Avtalion <ori@avtalion.name>
|
||||
Or Neeman <oneeman@gmail.com>
|
||||
Orphée Lafond-Lummis <o@orftz.com>
|
||||
Orpheus Lummis <o@orpheuslummis.com>
|
||||
osa1 <omeragacan@gmail.com>
|
||||
O S K Chaitanya <osk@medhas.org>
|
||||
Overmind JIANG <p90eri@gmail.com>
|
||||
Ožbolt Menegatti <ozbolt.menegatti@gmail.com>
|
||||
P1start <rewi-github@whanau.org>
|
||||
Pablo Brasero <pablo@pablobm.com>
|
||||
Palmer Cox <p@lmercox.com>
|
||||
panicbit <panicbit.dev@gmail.com>
|
||||
Paolo Falabella <paolo.falabella@gmail.com>
|
||||
Parker Moore <parkrmoore@gmail.com>
|
||||
Pascal Hertleif <killercup@gmail.com>
|
||||
@ -876,6 +1000,7 @@ Patrick Walton <pcwalton@mimiga.net>
|
||||
Patrick Yevsukov <patrickyevsukov@users.noreply.github.com>
|
||||
Patrik Kårlin <patrik.karlin@gmail.com>
|
||||
Paul ADENOT <paul@paul.cx>
|
||||
Paul A. Jungwirth <pj@illuminatedcomputing.com>
|
||||
Paul Banks <banks@banksdesigns.co.uk>
|
||||
Paul Collier <paul@paulcollier.ca>
|
||||
Paul Collins <paul@ondioline.org>
|
||||
@ -898,6 +1023,7 @@ Peter Elmers <peter.elmers@yahoo.com>
|
||||
Peter Hull <peterhull90@gmail.com>
|
||||
Peter Marheine <peter@taricorp.net>
|
||||
Peter Minten <peter@pminten.nl>
|
||||
Peter Reid <peter.d.reid@gmail.com>
|
||||
Peter Schuller <peter.schuller@infidyne.com>
|
||||
Peter Williams <peter@newton.cx>
|
||||
Peter Zotov <whitequark@whitequark.org>
|
||||
@ -907,8 +1033,11 @@ Phil Dawes <phil@phildawes.net>
|
||||
Philip Munksgaard <pmunksgaard@gmail.com>
|
||||
Philipp Brüschweiler <blei42@gmail.com>
|
||||
Philipp Gesang <phg42.2a@gmail.com>
|
||||
Philipp Matthias Schäfer <philipp.matthias.schaefer@posteo.de>
|
||||
Philipp Oppermann <dev@phil-opp.com>
|
||||
Phil Ruffwind <rf@rufflewind.com>
|
||||
Pierre Baillet <pierre@baillet.name>
|
||||
pierzchalski <e.a.pierzchalski@gmail.com>
|
||||
Piotr Czarnecki <pioczarn@gmail.com>
|
||||
Piotr Jawniak <sawyer47@gmail.com>
|
||||
Piotr Szotkowski <chastell@chastell.net>
|
||||
@ -916,10 +1045,12 @@ Piotr Zolnierek <pz@anixe.pl>
|
||||
Poga Po <poga.bahamut@gmail.com>
|
||||
posixphreak <posixphreak@gmail.com>
|
||||
Potpourri <pot_pourri@mail.ru>
|
||||
Pradeep Kumar <gohanpra@gmail.com>
|
||||
Prudhvi Krishna Surapaneni <me@prudhvi.net>
|
||||
Przemysław Wesołek <jest@go.art.pl>
|
||||
Pyfisch <pyfisch@gmail.com>
|
||||
Pyry Kontio <pyry.kontio@drasa.eu>
|
||||
Pythoner6 <pythoner6@gmail.com>
|
||||
Q.P.Liu <qpliu@yahoo.com>
|
||||
qwitwa <qwitwa@gmail.com>
|
||||
Rafael Ávila de Espíndola <respindola@mozilla.com>
|
||||
@ -933,6 +1064,7 @@ Raphael Catolino <raphael.catolino@gmail.com>
|
||||
Raphael Nestler <raphael.nestler@gmail.com>
|
||||
Raphael Speyer <rspeyer@gmail.com>
|
||||
Raul Gutierrez S <rgs@itevenworks.net>
|
||||
Ravi Shankar <wafflespeanut@gmail.com>
|
||||
Ray Clanan <rclanan@utopianconcept.com>
|
||||
ray glover <ray@rayglover.net>
|
||||
reedlepee <reedlepee123@gmail.com>
|
||||
@ -942,20 +1074,25 @@ Rémi Audebert <halfr@lse.epita.fr>
|
||||
Remi Rampin <remirampin@gmail.com>
|
||||
Renato Alves <alves.rjc@gmail.com>
|
||||
Renato Riccieri Santos Zannon <renato@rrsz.com.br>
|
||||
Renato Zannon <renato@rrsz.com.br>
|
||||
Reuben Morais <reuben.morais@gmail.com>
|
||||
reus <reusee@ymail.com>
|
||||
Reza Akhavan <reza@akhavan.me>
|
||||
Ricardo Martins <ricardo@scarybox.net>
|
||||
Ricardo M. Correia <rcorreia@wizy.org>
|
||||
Ricardo Signes <rjbs@cpan.org>
|
||||
Richard Diamond <wichard@vitalitystudios.com>
|
||||
Rich Lane <rlane@club.cc.cmu.edu>
|
||||
Richo Healey <richo@psych0tik.net>
|
||||
Rick Waldron <waldron.rick@gmail.com>
|
||||
Ricky Taylor <rickytaylor26@gmail.com>
|
||||
Rizky Luthfianto <mrluthfianto@gmail.com>
|
||||
rjz <rj@rjzaworski.com>
|
||||
Rob Arnold <robarnold@cs.cmu.edu>
|
||||
Robert Buonpastore <robert.buonpastore@gmail.com>
|
||||
Robert Clipsham <robert@octarineparrot.com>
|
||||
Robert Foss <dev@robertfoss.se>
|
||||
Robert Gardner <rhg259@nyu.edu>
|
||||
Robert Gawdzik <rgawdzik@hotmail.com>
|
||||
Robert Irelan <rirelan@gmail.com>
|
||||
Robert Knight <robertknight@gmail.com>
|
||||
@ -973,6 +1110,7 @@ Ron Dahlgren <ronald.dahlgren@gmail.com>
|
||||
Rory O’Kane <rory@roryokane.com>
|
||||
Roy Crihfield <rscrihf@gmail.com>
|
||||
Roy Frostig <rfrostig@mozilla.com>
|
||||
Ruby <hi@ruby.sh>
|
||||
Rüdiger Sonderfeld <ruediger@c-plusplus.de>
|
||||
rundrop1 <rundrop1@zoho.com>
|
||||
Russell Johnston <rpjohnst@gmail.com>
|
||||
@ -986,6 +1124,7 @@ Ryan Riginding <marc.riginding@gmail.com>
|
||||
Ryan Scheel <ryan.havvy@gmail.com>
|
||||
Ryman <haqkrs@gmail.com>
|
||||
らいどっと <ryogo.yoshimura@gmail.com>
|
||||
Ryo Munakata <afpacket@gmail.com>
|
||||
Sae-bom Kim <sae-bom.kim@samsung.com>
|
||||
Salem Talha <salem.a.talha@gmail.com>
|
||||
saml <saml@users.noreply.github.com>
|
||||
@ -1011,14 +1150,17 @@ Sean Patrick Santos <SeanPatrickSantos@gmail.com>
|
||||
Sean Stangl <sstangl@mozilla.com>
|
||||
Sean T Allen <sean@monkeysnatchbanana.com>
|
||||
Sebastian Gesemann <s.gesemann@gmail.com>
|
||||
Sebastian Hahn <sebastian@torproject.org>
|
||||
Sebastian N. Fernandez <cachobot@gmail.com>
|
||||
Sebastian Rasmussen <sebras@gmail.com>
|
||||
Sebastian Wicki <gandro@gmx.net>
|
||||
Sebastian Zaha <sebastian.zaha@gmail.com>
|
||||
Sébastien Chauvel <eichi237@mailoo.org>
|
||||
Sébastien Crozet <developer@crozet.re>
|
||||
Sébastien Marie <semarie@users.noreply.github.com>
|
||||
Sebastien Martini <seb@dbzteam.org>
|
||||
Sébastien Paolacci <sebastien.paolacci@gmail.com>
|
||||
Seeker14491 <seeker14491@gmail.com>
|
||||
Seonghyun Kim <sh8281.kim@samsung.com>
|
||||
Seo Sanghyeon <sanxiyn@gmail.com>
|
||||
Sergio Benitez <sbenitez@mit.edu>
|
||||
@ -1033,12 +1175,14 @@ SiegeLord <slabode@aim.com>
|
||||
Simonas Kazlauskas <git@kazlauskas.me>
|
||||
Simon Barber-Dueck <sbarberdueck@gmail.com>
|
||||
Simon Kern <simon.kern@rwth-aachen.de>
|
||||
Simon Mazur <semmaz.box@gmail.com>
|
||||
Simon Persson <simon@flaskpost.org>
|
||||
Simon Sapin <simon@exyr.org>
|
||||
Simon Wollwage <mail.wollwage@gmail.com>
|
||||
simplex <theemptystring@gmail.com>
|
||||
Sindre Johansen <sindre@sindrejohansen.no>
|
||||
sinkuu <sinkuupump@gmail.com>
|
||||
skeleten <janpelle.thomson@stud.tu-darmstadt.de>
|
||||
Skyler <skyler.lipthay@gmail.com>
|
||||
smenardpw <sebastien@knoglr.com>
|
||||
Son <leson.phung@gmail.com>
|
||||
@ -1047,6 +1191,7 @@ S Pradeep Kumar <gohanpra@gmail.com>
|
||||
Squeaky <squeaky_pl@gmx.com>
|
||||
startling <tdixon51793@gmail.com>
|
||||
Stefan Bucur <stefan.bucur@epfl.ch>
|
||||
Stefan O'Rear <stefanor@cox.net>
|
||||
Stefan Plantikow <stefan.plantikow@googlemail.com>
|
||||
Stepan Koltsov <stepan.koltsov@gmail.com>
|
||||
Sterling Greene <sterling.greene@gmail.com>
|
||||
@ -1072,7 +1217,9 @@ Taras Shpot <mrshpot@gmail.com>
|
||||
tav <tav@espians.com>
|
||||
Taylor Hutchison <seanthutchison@gmail.com>
|
||||
Ted Horst <ted.horst@earthlink.net>
|
||||
Ted Mielczarek <ted@mielczarek.org>
|
||||
Tero Hänninen <lgvz@users.noreply.github.com>
|
||||
Tero Hänninen <tejohann@kapsi.fi>
|
||||
th0114nd <th0114nd@gmail.com>
|
||||
Thad Guidry <thadguidry@gmail.com>
|
||||
Theo Belaire <theo.belaire@gmail.com>
|
||||
@ -1092,8 +1239,11 @@ Till Hoeppner <till@hoeppner.ws>
|
||||
Tim Brooks <brooks@cern.ch>
|
||||
Tim Chevalier <chevalier@alum.wellesley.edu>
|
||||
Tim Cuthbertson <tim@gfxmonk.net>
|
||||
Tim Dumol <tim@timdumol.com>
|
||||
Tim JIANG <p90eri@gmail.com>
|
||||
Tim Joseph Dumol <tim@timdumol.com>
|
||||
Tim Kuehn <tkuehn@cmu.edu>
|
||||
Tim Neumann <mail@timnn.me>
|
||||
Timon Rapp <timon@zaeda.net>
|
||||
Timothée Ravier <tim@siosm.fr>
|
||||
Tim Parenti <timparenti@gmail.com>
|
||||
@ -1131,6 +1281,7 @@ tynopex <tynopex@users.noreply.github.com>
|
||||
Ty Overby <ty@pre-alpha.com>
|
||||
Ulrik Sverdrup <bluss@users.noreply.github.com>
|
||||
Ulysse Carion <ulysse@ulysse.io>
|
||||
U-NOV2010\eugals <bogus>
|
||||
User Jyyou <jyyou@plaslab.cs.nctu.edu.tw>
|
||||
Utkarsh Kukreti <utkarshkukreti@gmail.com>
|
||||
Uwe Dauernheim <uwe@dauernheim.net>
|
||||
@ -1138,6 +1289,7 @@ Vadim Chugunov <vadimcn@gmail.com>
|
||||
Vadim Petrochenkov <vadim.petrochenkov@gmail.com>
|
||||
Valentin Tsatskin <vtsatskin@mozilla.com>
|
||||
Valerii Hiora <valerii.hiora@gmail.com>
|
||||
Viacheslav Chimishuk <Viacheslav.Chemishuk@keystonett.com>
|
||||
Victor Berger <victor.berger@m4x.org>
|
||||
Victor van den Elzen <victor.vde@gmail.com>
|
||||
Victory <git@dfhu.org>
|
||||
@ -1157,6 +1309,7 @@ Vladimir Rutsky <rutsky@users.noreply.github.com>
|
||||
Vladimir Smola <smola.vladimir@gmail.com>
|
||||
Vojtech Kral <vojtech@kral.hk>
|
||||
Volker Mische <volker.mische@gmail.com>
|
||||
w00ns <w00ns@w00ns.top>
|
||||
Wade Mealing <wmealing@gmail.com>
|
||||
Wangshan Lu <wisagan@gmail.com>
|
||||
WebeWizard <webewizard@gmail.com>
|
||||
@ -1173,10 +1326,16 @@ Will Hipschman <whipsch@gmail.com>
|
||||
William Throwe <wtt6@cornell.edu>
|
||||
William Ting <io@williamting.com>
|
||||
Willson Mock <willson.mock@gmail.com>
|
||||
Will Speak <lithiumflame@gmail.com>
|
||||
Will <will@glozer.net>
|
||||
Willy Aguirre <marti1125@gmail.com>
|
||||
Without Boats <woboats@gmail.com>
|
||||
Wojciech Ogrodowczyk <github@haikuco.de>
|
||||
wonyong kim <wonyong.kim@samsung.com>
|
||||
xales <xales@naveria.com>
|
||||
Xavier Shay <xavier@rhnh.net>
|
||||
xd1le <elisp.vim@gmail.com>
|
||||
Xiao Chuan Yu <xcyu.se@gmail.com>
|
||||
Xuefeng Wu <benewu@gmail.com>
|
||||
XuefengWu <benewu@gmail.com>
|
||||
Xuefeng Wu <xfwu@thoughtworks.com>
|
||||
@ -1187,6 +1346,7 @@ Yazhong Liu <yorkiefixer@gmail.com>
|
||||
Yehuda Katz <wycats@gmail.com>
|
||||
Yongqian Li <yongqli@kerrmetric.com>
|
||||
York Xiang <bombless@126.com>
|
||||
Yoshito Komatsu <ykomatsu@akaumigame.org>
|
||||
Young-il Choi <duddlf.choi@samsung.com>
|
||||
Youngmin Yoo <youngmin.yoo@samsung.com>
|
||||
Youngsoo Son <ysson83@gmail.com>
|
||||
|
@ -149,6 +149,11 @@ To find documentation-related issues, sort by the [A-docs label][adocs].
|
||||
|
||||
[adocs]: https://github.com/rust-lang/rust/issues?q=is%3Aopen+is%3Aissue+label%3AA-docs
|
||||
|
||||
In many cases, you don't need a full `make doc`. You can use `rustdoc` directly
|
||||
to check small fixes. For example, `rustdoc src/doc/reference.md` will render
|
||||
reference to `doc/reference.html`. The CSS might be messed up, but you can
|
||||
verify that HTML is right.
|
||||
|
||||
## Issue Triage
|
||||
|
||||
Sometimes, an issue will stay open, even though the bug has been fixed. And
|
||||
@ -221,18 +226,19 @@ are:
|
||||
* The [Rust Internals forum][rif], a place to ask questions and
|
||||
discuss Rust's internals
|
||||
* The [generated documentation for rust's compiler][gdfrustc]
|
||||
* The [rust referance][rr], even though it doesn't specifically talk about Rust's internals, its a great reasource nontheless
|
||||
* The [rust reference][rr], even though it doesn't specifically talk about Rust's internals, it's a great resource nonetheless
|
||||
* Although out of date, [Tom Lee's great blog article][tlgba] is very helpful
|
||||
* [rustaceans.org][ro] is helpful, but mostly dedicated to IRC
|
||||
* The [Rust Compiler Testing Docs][rctd]
|
||||
* For @bors, [this cheetsheat][cheetsheat] is helpful (Remember to replace `@homu` with `@bors` in the commands that you use.)
|
||||
* **Google**!
|
||||
* For @bors, [this cheat sheet][cheatsheet] is helpful (Remember to replace `@homu` with `@bors` in the commands that you use.)
|
||||
* **Google!** ([search only in Rust Documentation][gsearchdocs] to find types, traits, etc. quickly)
|
||||
* Don't be afraid to ask! The Rust community is friendly and helpful.
|
||||
|
||||
[gdfrustc]: http://manishearth.github.io/rust-internals-docs/rustc/
|
||||
[gsearchdocs]: https://www.google.de/search?q=site:doc.rust-lang.org+your+query+here
|
||||
[rif]: http://internals.rust-lang.org
|
||||
[rr]: https://doc.rust-lang.org/book/README.html
|
||||
[tlgba]: http://tomlee.co/2014/04/03/a-more-detailed-tour-of-the-rust-compiler/
|
||||
[ro]: http://www.rustaceans.org/
|
||||
[rctd]: ./COMPILER_TESTS.md
|
||||
[cheetsheat]: http://buildbot.rust-lang.org/homu/
|
||||
[cheatsheet]: http://buildbot.rust-lang.org/homu/
|
||||
|
@ -26,7 +26,7 @@
|
||||
#
|
||||
# * check - Run the complete test suite
|
||||
#
|
||||
# * clean - Clean the build repertory. It is advised to run this
|
||||
# * clean - Clean the build repository. It is advised to run this
|
||||
# command if you want to build Rust again, after an update
|
||||
# of the git repository.
|
||||
#
|
||||
|
10
README.md
10
README.md
@ -72,6 +72,9 @@ Read ["Installing Rust"] from [The Book].
|
||||
$ pacman -S mingw-w64-i686-toolchain
|
||||
$ pacman -S mingw-w64-x86_64-toolchain
|
||||
|
||||
# Make git available in MSYS2 (if not already available on path)
|
||||
$ pacman -S git
|
||||
|
||||
$ pacman -S base-devel
|
||||
```
|
||||
|
||||
@ -84,6 +87,13 @@ Read ["Installing Rust"] from [The Book].
|
||||
$ ./configure
|
||||
$ make && make install
|
||||
```
|
||||
> ***Note:*** gcc versions >= 5 currently have issues building LLVM on Windows
|
||||
> resulting in a segmentation fault when building Rust. In order to avoid this
|
||||
> it may be necessary to obtain an earlier version of gcc such as 4.9.x.
|
||||
> Installers for earlier Windows builds of gcc are available at the
|
||||
> [Mingw-Builds] project. For more information on this see issue #28260.
|
||||
|
||||
[Mingw-Builds]: http://sourceforge.net/projects/mingw-w64/
|
||||
|
||||
## Building Documentation
|
||||
|
||||
|
276
RELEASES.md
276
RELEASES.md
@ -1,5 +1,223 @@
|
||||
Version 1.4.0 (October 2015)
|
||||
============================
|
||||
Version 1.5.0 (2015-12-10)
|
||||
==========================
|
||||
|
||||
* ~700 changes, numerous bugfixes
|
||||
|
||||
Highlights
|
||||
----------
|
||||
|
||||
* Stabilized APIs:
|
||||
[`BinaryHeap::from`], [`BinaryHeap::into_sorted_vec`],
|
||||
[`BinaryHeap::into_vec`], [`Condvar::wait_timeout`],
|
||||
[`FileTypeExt::is_block_device`], [`FileTypeExt::is_char_device`],
|
||||
[`FileTypeExt::is_fifo`], [`FileTypeExt::is_socket`],
|
||||
[`FileTypeExt`], [`Formatter::alternate`], [`Formatter::fill`],
|
||||
[`Formatter::precision`], [`Formatter::sign_aware_zero_pad`],
|
||||
[`Formatter::sign_minus`], [`Formatter::sign_plus`],
|
||||
[`Formatter::width`], [`Iterator::cmp`], [`Iterator::eq`],
|
||||
[`Iterator::ge`], [`Iterator::gt`], [`Iterator::le`],
|
||||
[`Iterator::lt`], [`Iterator::ne`], [`Iterator::partial_cmp`],
|
||||
[`Path::canonicalize`], [`Path::exists`], [`Path::is_dir`],
|
||||
[`Path::is_file`], [`Path::metadata`], [`Path::read_dir`],
|
||||
[`Path::read_link`], [`Path::symlink_metadata`],
|
||||
[`Utf8Error::valid_up_to`], [`Vec::resize`],
|
||||
[`VecDeque::as_mut_slices`], [`VecDeque::as_slices`],
|
||||
[`VecDeque::insert`], [`VecDeque::shrink_to_fit`],
|
||||
[`VecDeque::swap_remove_back`], [`VecDeque::swap_remove_front`],
|
||||
[`slice::split_first_mut`], [`slice::split_first`],
|
||||
[`slice::split_last_mut`], [`slice::split_last`],
|
||||
[`char::from_u32_unchecked`], [`fs::canonicalize`],
|
||||
[`str::MatchIndices`], [`str::RMatchIndices`],
|
||||
[`str::match_indices`], [`str::rmatch_indices`],
|
||||
[`str::slice_mut_unchecked`], [`string::ParseError`].
|
||||
* Rust applications hosted on crates.io can be installed locally to
|
||||
`~/.cargo/bin` with the [`cargo install`] command. Among other
|
||||
things this makes it easier to augment Cargo with new subcommands:
|
||||
when a binary named e.g. `cargo-foo` is found in `$PATH` it can be
|
||||
invoked as `cargo foo`.
|
||||
* Crates with wildcard (`*`) dependencies will [emit warnings when
|
||||
published][1.5w]. In 1.6 it will no longer be possible to publish
|
||||
crates with wildcard dependencies.
|
||||
|
||||
Breaking Changes
|
||||
----------------
|
||||
|
||||
* The rules determining when a particular lifetime must outlive
|
||||
a particular value (known as '[dropck]') have been [modified
|
||||
to not rely on parametricity][1.5p].
|
||||
* [Implementations of `AsRef` and `AsMut` were added to `Box`, `Rc`,
|
||||
and `Arc`][1.5a]. Because these smart pointer types implement
|
||||
`Deref`, this causes breakage in cases where the interior type
|
||||
contains methods of the same name.
|
||||
* [Correct a bug in Rc/Arc][1.5c] that caused [dropck] to be unaware
|
||||
that they could drop their content. Soundness fix.
|
||||
* All method invocations are [properly checked][1.5wf1] for
|
||||
[well-formedness][1.5wf2]. Soundness fix.
|
||||
* Traits whose supertraits contain `Self` are [not object
|
||||
safe][1.5o]. Soundness fix.
|
||||
* Target specifications support a [`no_default_libraries`][1.5nd]
|
||||
setting that controls whether `-nodefaultlibs` is passed to the
|
||||
linker, and in turn the `is_like_windows` setting no longer affects
|
||||
the `-nodefaultlibs` flag.
|
||||
* `#[derive(Show)]`, long-deprecated, [has been removed][1.5ds].
|
||||
* The `#[inline]` and `#[repr]` attributes [can only appear
|
||||
in valid locations][1.5at].
|
||||
* Native libraries linked from the local crate are [passed to
|
||||
the linker before native libraries from upstream crates][1.5nl].
|
||||
* Two rarely-used attributes, `#[no_debug]` and
|
||||
`#[omit_gdb_pretty_printer_section]` [are feature gated][1.5fg].
|
||||
* Negation of unsigned integers, which has been a warning for
|
||||
several releases, [is now behind a feature gate and will
|
||||
generate errors][1.5nu].
|
||||
* The parser accidentally accepted visibility modifiers on
|
||||
enum variants, a bug [which has been fixed][1.5ev].
|
||||
* [A bug was fixed that allowed `use` statements to import unstable
|
||||
features][1.5use].
|
||||
|
||||
Language
|
||||
--------
|
||||
|
||||
* When evaluating expressions at compile-time that are not
|
||||
compile-time constants (const-evaluating expressions in non-const
|
||||
contexts), incorrect code such as overlong bitshifts and arithmetic
|
||||
overflow will [generate a warning instead of an error][1.5ce],
|
||||
delaying the error until runtime. This will allow the
|
||||
const-evaluator to be expanded in the future backwards-compatibly.
|
||||
* The `improper_ctypes` lint [no longer warns about using `isize` and
|
||||
`usize` in FFI][1.5ict].
|
||||
|
||||
Libraries
|
||||
---------
|
||||
|
||||
* `Arc<T>` and `Rc<T>` are [covariant with respect to `T` instead of
|
||||
invariant][1.5c].
|
||||
* `Default` is [implemented for mutable slices][1.5d].
|
||||
* `FromStr` is [implemented for `SockAddrV4` and `SockAddrV6`][1.5s].
|
||||
* There are now `From` conversions [between floating point
|
||||
types][1.5f] where the conversions are lossless.
|
||||
* Thera are now `From` conversions [between integer types][1.5i] where
|
||||
the conversions are lossless.
|
||||
* [`fs::Metadata` implements `Clone`][1.5fs].
|
||||
* The `parse` method [accepts a leading "+" when parsing
|
||||
integers][1.5pi].
|
||||
* [`AsMut` is implemented for `Vec`][1.5am].
|
||||
* The `clone_from` implementations for `String` and `BinaryHeap` [have
|
||||
been optimized][1.5cf] and no longer rely on the default impl.
|
||||
* The `extern "Rust"`, `extern "C"`, `unsafe extern "Rust"` and
|
||||
`unsafe extern "C"` function types now [implement `Clone`,
|
||||
`PartialEq`, `Eq`, `PartialOrd`, `Ord`, `Hash`, `fmt::Pointer`, and
|
||||
`fmt::Debug` for up to 12 arguments][1.5fp].
|
||||
* [Dropping `Vec`s is much faster in unoptimized builds when the
|
||||
element types don't implement `Drop`][1.5dv].
|
||||
* A bug that caused in incorrect behavior when [combining `VecDeque`
|
||||
with zero-sized types][1.5vdz] was resolved.
|
||||
* [`PartialOrd` for slices is faster][1.5po].
|
||||
|
||||
Miscellaneous
|
||||
-------------
|
||||
|
||||
* [Crate metadata size was reduced by 20%][1.5md].
|
||||
* [Improvements to code generation reduced the size of libcore by 3.3
|
||||
MB and rustc's memory usage by 18MB][1.5m].
|
||||
* [Improvements to deref translation increased performance in
|
||||
unoptimized builds][1.5dr].
|
||||
* Various errors in trait resolution [are deduplicated to only be
|
||||
reported once][1.5te].
|
||||
* Rust has preliminary [support for rumprun kernels][1.5rr].
|
||||
* Rust has preliminary [support for NetBSD on amd64][1.5na].
|
||||
|
||||
[1.5use]: https://github.com/rust-lang/rust/pull/28364
|
||||
[1.5po]: https://github.com/rust-lang/rust/pull/28436
|
||||
[1.5ev]: https://github.com/rust-lang/rust/pull/28442
|
||||
[1.5nu]: https://github.com/rust-lang/rust/pull/28468
|
||||
[1.5dr]: https://github.com/rust-lang/rust/pull/28491
|
||||
[1.5vdz]: https://github.com/rust-lang/rust/pull/28494
|
||||
[1.5md]: https://github.com/rust-lang/rust/pull/28521
|
||||
[1.5fg]: https://github.com/rust-lang/rust/pull/28522
|
||||
[1.5dv]: https://github.com/rust-lang/rust/pull/28531
|
||||
[1.5na]: https://github.com/rust-lang/rust/pull/28543
|
||||
[1.5fp]: https://github.com/rust-lang/rust/pull/28560
|
||||
[1.5rr]: https://github.com/rust-lang/rust/pull/28593
|
||||
[1.5cf]: https://github.com/rust-lang/rust/pull/28602
|
||||
[1.5nl]: https://github.com/rust-lang/rust/pull/28605
|
||||
[1.5te]: https://github.com/rust-lang/rust/pull/28645
|
||||
[1.5at]: https://github.com/rust-lang/rust/pull/28650
|
||||
[1.5am]: https://github.com/rust-lang/rust/pull/28663
|
||||
[1.5m]: https://github.com/rust-lang/rust/pull/28778
|
||||
[1.5ict]: https://github.com/rust-lang/rust/pull/28779
|
||||
[1.5a]: https://github.com/rust-lang/rust/pull/28811
|
||||
[1.5pi]: https://github.com/rust-lang/rust/pull/28826
|
||||
[1.5ce]: https://github.com/rust-lang/rfcs/blob/master/text/1229-compile-time-asserts.md
|
||||
[1.5p]: https://github.com/rust-lang/rfcs/blob/master/text/1238-nonparametric-dropck.md
|
||||
[1.5i]: https://github.com/rust-lang/rust/pull/28921
|
||||
[1.5fs]: https://github.com/rust-lang/rust/pull/29021
|
||||
[1.5f]: https://github.com/rust-lang/rust/pull/29129
|
||||
[1.5ds]: https://github.com/rust-lang/rust/pull/29148
|
||||
[1.5s]: https://github.com/rust-lang/rust/pull/29190
|
||||
[1.5d]: https://github.com/rust-lang/rust/pull/29245
|
||||
[1.5o]: https://github.com/rust-lang/rust/pull/29259
|
||||
[1.5nd]: https://github.com/rust-lang/rust/pull/28578
|
||||
[1.5wf2]: https://github.com/rust-lang/rfcs/blob/master/text/1214-projections-lifetimes-and-wf.md
|
||||
[1.5wf1]: https://github.com/rust-lang/rust/pull/28669
|
||||
[dropck]: https://doc.rust-lang.org/nightly/nomicon/dropck.html
|
||||
[1.5c]: https://github.com/rust-lang/rust/pull/29110
|
||||
[1.5w]: https://github.com/rust-lang/rfcs/blob/master/text/1241-no-wildcard-deps.md
|
||||
[`cargo install`]: https://github.com/rust-lang/rfcs/blob/master/text/1200-cargo-install.md
|
||||
[`BinaryHeap::from`]: http://doc.rust-lang.org/nightly/std/convert/trait.From.html#method.from
|
||||
[`BinaryHeap::into_sorted_vec`]: http://doc.rust-lang.org/nightly/std/collections/struct.BinaryHeap.html#method.into_sorted_vec
|
||||
[`BinaryHeap::into_vec`]: http://doc.rust-lang.org/nightly/std/collections/struct.BinaryHeap.html#method.into_vec
|
||||
[`Condvar::wait_timeout`]: http://doc.rust-lang.org/nightly/std/sync/struct.Condvar.html#method.wait_timeout
|
||||
[`FileTypeExt::is_block_device`]: http://doc.rust-lang.org/nightly/std/os/unix/fs/trait.FileTypeExt.html#tymethod.is_block_device
|
||||
[`FileTypeExt::is_char_device`]: http://doc.rust-lang.org/nightly/std/os/unix/fs/trait.FileTypeExt.html#tymethod.is_char_device
|
||||
[`FileTypeExt::is_fifo`]: http://doc.rust-lang.org/nightly/std/os/unix/fs/trait.FileTypeExt.html#tymethod.is_fifo
|
||||
[`FileTypeExt::is_socket`]: http://doc.rust-lang.org/nightly/std/os/unix/fs/trait.FileTypeExt.html#tymethod.is_socket
|
||||
[`FileTypeExt`]: http://doc.rust-lang.org/nightly/std/os/unix/fs/trait.FileTypeExt.html
|
||||
[`Formatter::alternate`]: http://doc.rust-lang.org/nightly/core/fmt/struct.Formatter.html#method.alternate
|
||||
[`Formatter::fill`]: http://doc.rust-lang.org/nightly/core/fmt/struct.Formatter.html#method.fill
|
||||
[`Formatter::precision`]: http://doc.rust-lang.org/nightly/core/fmt/struct.Formatter.html#method.precision
|
||||
[`Formatter::sign_aware_zero_pad`]: http://doc.rust-lang.org/nightly/core/fmt/struct.Formatter.html#method.sign_aware_zero_pad
|
||||
[`Formatter::sign_minus`]: http://doc.rust-lang.org/nightly/core/fmt/struct.Formatter.html#method.sign_minus
|
||||
[`Formatter::sign_plus`]: http://doc.rust-lang.org/nightly/core/fmt/struct.Formatter.html#method.sign_plus
|
||||
[`Formatter::width`]: http://doc.rust-lang.org/nightly/core/fmt/struct.Formatter.html#method.width
|
||||
[`Iterator::cmp`]: http://doc.rust-lang.org/nightly/core/iter/trait.Iterator.html#method.cmp
|
||||
[`Iterator::eq`]: http://doc.rust-lang.org/nightly/core/iter/trait.Iterator.html#method.eq
|
||||
[`Iterator::ge`]: http://doc.rust-lang.org/nightly/core/iter/trait.Iterator.html#method.ge
|
||||
[`Iterator::gt`]: http://doc.rust-lang.org/nightly/core/iter/trait.Iterator.html#method.gt
|
||||
[`Iterator::le`]: http://doc.rust-lang.org/nightly/core/iter/trait.Iterator.html#method.le
|
||||
[`Iterator::lt`]: http://doc.rust-lang.org/nightly/core/iter/trait.Iterator.html#method.lt
|
||||
[`Iterator::ne`]: http://doc.rust-lang.org/nightly/core/iter/trait.Iterator.html#method.ne
|
||||
[`Iterator::partial_cmp`]: http://doc.rust-lang.org/nightly/core/iter/trait.Iterator.html#method.partial_cmp
|
||||
[`Path::canonicalize`]: http://doc.rust-lang.org/nightly/std/path/struct.Path.html#method.canonicalize
|
||||
[`Path::exists`]: http://doc.rust-lang.org/nightly/std/path/struct.Path.html#method.exists
|
||||
[`Path::is_dir`]: http://doc.rust-lang.org/nightly/std/path/struct.Path.html#method.is_dir
|
||||
[`Path::is_file`]: http://doc.rust-lang.org/nightly/std/path/struct.Path.html#method.is_file
|
||||
[`Path::metadata`]: http://doc.rust-lang.org/nightly/std/path/struct.Path.html#method.metadata
|
||||
[`Path::read_dir`]: http://doc.rust-lang.org/nightly/std/path/struct.Path.html#method.read_dir
|
||||
[`Path::read_link`]: http://doc.rust-lang.org/nightly/std/path/struct.Path.html#method.read_link
|
||||
[`Path::symlink_metadata`]: http://doc.rust-lang.org/nightly/std/path/struct.Path.html#method.symlink_metadata
|
||||
[`Utf8Error::valid_up_to`]: http://doc.rust-lang.org/nightly/core/str/struct.Utf8Error.html#method.valid_up_to
|
||||
[`Vec::resize`]: http://doc.rust-lang.org/nightly/std/vec/struct.Vec.html#method.resize
|
||||
[`VecDeque::as_mut_slices`]: http://doc.rust-lang.org/nightly/std/collections/struct.VecDeque.html#method.as_mut_slices
|
||||
[`VecDeque::as_slices`]: http://doc.rust-lang.org/nightly/std/collections/struct.VecDeque.html#method.as_slices
|
||||
[`VecDeque::insert`]: http://doc.rust-lang.org/nightly/std/collections/struct.VecDeque.html#method.insert
|
||||
[`VecDeque::shrink_to_fit`]: http://doc.rust-lang.org/nightly/std/collections/struct.VecDeque.html#method.shrink_to_fit
|
||||
[`VecDeque::swap_remove_back`]: http://doc.rust-lang.org/nightly/std/collections/struct.VecDeque.html#method.swap_remove_back
|
||||
[`VecDeque::swap_remove_front`]: http://doc.rust-lang.org/nightly/std/collections/struct.VecDeque.html#method.swap_remove_front
|
||||
[`slice::split_first_mut`]: http://doc.rust-lang.org/nightly/std/primitive.slice.html#method.split_first_mut
|
||||
[`slice::split_first`]: http://doc.rust-lang.org/nightly/std/primitive.slice.html#method.split_first
|
||||
[`slice::split_last_mut`]: http://doc.rust-lang.org/nightly/std/primitive.slice.html#method.split_last_mut
|
||||
[`slice::split_last`]: http://doc.rust-lang.org/nightly/std/primitive.slice.html#method.split_last
|
||||
[`char::from_u32_unchecked`]: http://doc.rust-lang.org/nightly/std/char/fn.from_u32_unchecked.html
|
||||
[`fs::canonicalize`]: http://doc.rust-lang.org/nightly/std/fs/fn.canonicalize.html
|
||||
[`str::MatchIndices`]: http://doc.rust-lang.org/nightly/std/str/struct.MatchIndices.html
|
||||
[`str::RMatchIndices`]: http://doc.rust-lang.org/nightly/std/str/struct.RMatchIndices.html
|
||||
[`str::match_indices`]: http://doc.rust-lang.org/nightly/std/primitive.str.html#method.match_indices
|
||||
[`str::rmatch_indices`]: http://doc.rust-lang.org/nightly/std/primitive.str.html#method.rmatch_indices
|
||||
[`str::slice_mut_unchecked`]: http://doc.rust-lang.org/nightly/std/primitive.str.html#method.slice_mut_unchecked
|
||||
[`string::ParseError`]: http://doc.rust-lang.org/nightly/std/string/enum.ParseError.html
|
||||
|
||||
Version 1.4.0 (2015-10-29)
|
||||
==========================
|
||||
|
||||
* ~1200 changes, numerous bugfixes
|
||||
|
||||
@ -20,6 +238,12 @@ Breaking Changes
|
||||
* [The `str::lines` and `BufRead::lines` iterators treat `\r\n` as
|
||||
line breaks in addition to `\n`][crlf].
|
||||
* [Loans of `'static` lifetime extend to the end of a function][stat].
|
||||
* [`str::parse` no longer introduces avoidable rounding error when
|
||||
parsing floating point numbers. Together with earlier changes to
|
||||
float formatting/output, "round trips" like f.to_string().parse()
|
||||
now preserve the value of f exactly. Additionally, leading plus
|
||||
signs are now accepted][fp3].
|
||||
|
||||
|
||||
Language
|
||||
--------
|
||||
@ -68,19 +292,22 @@ Libraries
|
||||
prelude][pr].
|
||||
* [`Extend<String>` and `FromIterator<String` are both implemented for
|
||||
`String`][es].
|
||||
* [`IntoIterator` is implemented for `Option<&T>` and
|
||||
`Result<&T>`][into].
|
||||
* [`IntoIterator` is implemented for references to `Option` and
|
||||
`Result`][into2].
|
||||
* [`HashMap` and `HashSet` implement `Extend<&T>` where `T:
|
||||
Copy`][ext] as part of [RFC 839].
|
||||
Copy`][ext] as part of [RFC 839]. This will cause type inferance
|
||||
breakage in rare situations.
|
||||
* [`BinaryHeap` implements `Debug`][bh2].
|
||||
* [`Borrow` and `BorrowMut` are implemented for fixed-size
|
||||
arrays][bm].
|
||||
* [`extern fn`s of with the "Rust" and "C" ABIs implement common
|
||||
* [`extern fn`s with the "Rust" and "C" ABIs implement common
|
||||
traits including `Eq`, `Ord`, `Debug`, `Hash`][fp].
|
||||
* [String comparison is faster][faststr].
|
||||
* `&mut T` where `T: Write` [also implements `Write`][mutw].
|
||||
* [A stable regression in `VecDec::push_back` that caused panics for
|
||||
zero-sized types was fixed][vd].
|
||||
* `&mut T` where `T: std::fmt::Write` [also implements
|
||||
`std::fmt::Write`][mutw].
|
||||
* [A stable regression in `VecDeque::push_back` and other
|
||||
capicity-altering methods that caused panics for zero-sized types
|
||||
was fixed][vd].
|
||||
* [Function pointers implement traits for up to 12 parameters][fp2].
|
||||
|
||||
Miscellaneous
|
||||
@ -151,8 +378,9 @@ Miscellaneous
|
||||
[ffi]: https://github.com/rust-lang/rust/pull/28779
|
||||
[fp]: https://github.com/rust-lang/rust/pull/28268
|
||||
[fp2]: https://github.com/rust-lang/rust/pull/28560
|
||||
[fp3]: https://github.com/rust-lang/rust/pull/27307
|
||||
[i]: https://github.com/rust-lang/rust/pull/27451
|
||||
[into]: https://github.com/rust-lang/rust/pull/28039
|
||||
[into2]: https://github.com/rust-lang/rust/pull/28039
|
||||
[it]: https://github.com/rust-lang/rust/pull/27652
|
||||
[mm]: https://github.com/rust-lang/rust/pull/27338
|
||||
[mutw]: https://github.com/rust-lang/rust/pull/28368
|
||||
@ -802,7 +1030,7 @@ Misc
|
||||
[path-normalize]: https://github.com/rust-lang/rust/pull/23229
|
||||
|
||||
|
||||
Version 1.0.0-alpha.2 (February 2015)
|
||||
Version 1.0.0-alpha.2 (2015-02-20)
|
||||
=====================================
|
||||
|
||||
* ~1300 changes, numerous bugfixes
|
||||
@ -901,7 +1129,7 @@ Version 1.0.0-alpha.2 (February 2015)
|
||||
[un]: https://github.com/rust-lang/rust/pull/22256
|
||||
|
||||
|
||||
Version 1.0.0-alpha (January 2015)
|
||||
Version 1.0.0-alpha (2015-01-09)
|
||||
==================================
|
||||
|
||||
* ~2400 changes, numerous bugfixes
|
||||
@ -1088,7 +1316,7 @@ Version 1.0.0-alpha (January 2015)
|
||||
[rbe]: http://rustbyexample.com/
|
||||
|
||||
|
||||
Version 0.12.0 (October 2014)
|
||||
Version 0.12.0 (2014-10-09)
|
||||
=============================
|
||||
|
||||
* ~1900 changes, numerous bugfixes
|
||||
@ -1211,7 +1439,7 @@ Version 0.12.0 (October 2014)
|
||||
kernels and distributions, built on CentOS 5.10.
|
||||
|
||||
|
||||
Version 0.11.0 (July 2014)
|
||||
Version 0.11.0 (2014-07-02)
|
||||
==========================
|
||||
|
||||
* ~1700 changes, numerous bugfixes
|
||||
@ -1344,7 +1572,7 @@ Version 0.11.0 (July 2014)
|
||||
greatly improved.
|
||||
|
||||
|
||||
Version 0.10 (April 2014)
|
||||
Version 0.10 (2014-04-03)
|
||||
=========================
|
||||
|
||||
* ~1500 changes, numerous bugfixes
|
||||
@ -1511,7 +1739,7 @@ Version 0.10 (April 2014)
|
||||
directory.
|
||||
|
||||
|
||||
Version 0.9 (January 2014)
|
||||
Version 0.9 (2014-01-09)
|
||||
==========================
|
||||
|
||||
* ~1800 changes, numerous bugfixes
|
||||
@ -1677,7 +1905,7 @@ Version 0.9 (January 2014)
|
||||
build tools.
|
||||
|
||||
|
||||
Version 0.8 (September 2013)
|
||||
Version 0.8 (2013-09-26)
|
||||
============================
|
||||
|
||||
* ~2200 changes, numerous bugfixes
|
||||
@ -1833,7 +2061,7 @@ Version 0.8 (September 2013)
|
||||
still invoked through the normal `rustdoc` command.
|
||||
|
||||
|
||||
Version 0.7 (July 2013)
|
||||
Version 0.7 (2013-07-03)
|
||||
=======================
|
||||
|
||||
* ~2000 changes, numerous bugfixes
|
||||
@ -1950,7 +2178,7 @@ Version 0.7 (July 2013)
|
||||
* Improvements to rustpkg (see the detailed release notes).
|
||||
|
||||
|
||||
Version 0.6 (April 2013)
|
||||
Version 0.6 (2013-04-03)
|
||||
========================
|
||||
|
||||
* ~2100 changes, numerous bugfixes
|
||||
@ -2053,7 +2281,7 @@ Version 0.6 (April 2013)
|
||||
* Inline assembler supported by new asm!() syntax extension.
|
||||
|
||||
|
||||
Version 0.5 (December 2012)
|
||||
Version 0.5 (2012-12-21)
|
||||
===========================
|
||||
|
||||
* ~900 changes, numerous bugfixes
|
||||
@ -2110,7 +2338,7 @@ Version 0.5 (December 2012)
|
||||
* License changed from MIT to dual MIT/APL2
|
||||
|
||||
|
||||
Version 0.4 (October 2012)
|
||||
Version 0.4 (2012-10-15)
|
||||
==========================
|
||||
|
||||
* ~2000 changes, numerous bugfixes
|
||||
@ -2166,7 +2394,7 @@ Version 0.4 (October 2012)
|
||||
* All hash functions and tables converted to secure, randomized SipHash
|
||||
|
||||
|
||||
Version 0.3 (July 2012)
|
||||
Version 0.3 (2012-07-12)
|
||||
========================
|
||||
|
||||
* ~1900 changes, numerous bugfixes
|
||||
@ -2225,7 +2453,7 @@ Version 0.3 (July 2012)
|
||||
* Cargo automatically resolves dependencies
|
||||
|
||||
|
||||
Version 0.2 (March 2012)
|
||||
Version 0.2 (2012-03-29)
|
||||
=========================
|
||||
|
||||
* >1500 changes, numerous bugfixes
|
||||
@ -2266,7 +2494,7 @@ Version 0.2 (March 2012)
|
||||
* Extensive cleanup, regularization in libstd, libcore
|
||||
|
||||
|
||||
Version 0.1 (January 20, 2012)
|
||||
Version 0.1 (2012-01-20)
|
||||
===============================
|
||||
|
||||
* Most language features work, including:
|
||||
|
41
configure
vendored
41
configure
vendored
@ -578,6 +578,7 @@ opt ccache 0 "invoke gcc/clang via ccache to reuse object files between builds"
|
||||
opt local-rust 0 "use an installed rustc rather than downloading a snapshot"
|
||||
opt llvm-static-stdcpp 0 "statically link to libstdc++ for LLVM"
|
||||
opt rpath 0 "build rpaths into rustc itself"
|
||||
opt stage0-landing-pads 1 "enable landing pads during bootstrap with stage0"
|
||||
# This is used by the automation to produce single-target nightlies
|
||||
opt dist-host-only 0 "only install bins for the host architecture"
|
||||
opt inject-std-version 1 "inject the current compiler version of libstd into programs"
|
||||
@ -766,8 +767,6 @@ probe CFG_ANTLR4 antlr4
|
||||
probe CFG_GRUN grun
|
||||
probe CFG_FLEX flex
|
||||
probe CFG_BISON bison
|
||||
probe CFG_PANDOC pandoc
|
||||
probe CFG_XELATEX xelatex
|
||||
probe CFG_GDB gdb
|
||||
probe CFG_LLDB lldb
|
||||
|
||||
@ -826,26 +825,6 @@ step_msg "looking for target specific programs"
|
||||
|
||||
probe CFG_ADB adb
|
||||
|
||||
if [ -n "$CFG_PANDOC" ]
|
||||
then
|
||||
# Extract "MAJOR MINOR" from Pandoc's version number
|
||||
PV_MAJOR_MINOR=$(pandoc --version | grep '^pandoc' |
|
||||
sed -E 's/pandoc(.exe)? ([0-9]+)\.([0-9]+).*/\2 \3/')
|
||||
|
||||
MIN_PV_MAJOR="1"
|
||||
MIN_PV_MINOR="9"
|
||||
|
||||
# these patterns are shell globs, *not* regexps
|
||||
PV_MAJOR=${PV_MAJOR_MINOR% *}
|
||||
PV_MINOR=${PV_MAJOR_MINOR#* }
|
||||
|
||||
if [ "$PV_MAJOR" -lt "$MIN_PV_MAJOR" ] || [ "$PV_MINOR" -lt "$MIN_PV_MINOR" ]
|
||||
then
|
||||
step_msg "pandoc $PV_MAJOR.$PV_MINOR is too old. Need at least $MIN_PV_MAJOR.$MIN_PV_MINOR. Disabling"
|
||||
BAD_PANDOC=1
|
||||
fi
|
||||
fi
|
||||
|
||||
BIN_SUF=
|
||||
if [ "$CFG_OSTYPE" = "pc-windows-gnu" ] || [ "$CFG_OSTYPE" = "pc-windows-msvc" ]
|
||||
then
|
||||
@ -1095,6 +1074,12 @@ envopt CPP
|
||||
envopt CFLAGS
|
||||
envopt CXXFLAGS
|
||||
|
||||
# stdc++ name in use
|
||||
# used to manage non-standard name (on OpenBSD for example)
|
||||
program_transform_name=$($CFG_CC -v 2>&1 | sed -n "s/.*--program-transform-name='\([^']*\)'.*/\1/p")
|
||||
CFG_STDCPP_NAME=$(echo "stdc++" | sed "${program_transform_name}")
|
||||
putvar CFG_STDCPP_NAME
|
||||
|
||||
# a little post-processing of various config values
|
||||
CFG_PREFIX=${CFG_PREFIX%/}
|
||||
CFG_MANDIR=${CFG_MANDIR%/}
|
||||
@ -1289,6 +1274,12 @@ $ pacman -R cmake && pacman -S mingw-w64-x86_64-cmake
|
||||
putvar CFG_MSVC_LIB_PATH_${bits}
|
||||
;;
|
||||
|
||||
*-rumprun-netbsd)
|
||||
step_msg "targeting rumprun-netbsd, disabling jemalloc"
|
||||
CFG_DISABLE_JEMALLOC=1
|
||||
putvar CFG_DISABLE_JEMALLOC
|
||||
;;
|
||||
|
||||
*)
|
||||
;;
|
||||
esac
|
||||
@ -1763,12 +1754,6 @@ then
|
||||
fi
|
||||
|
||||
|
||||
if [ -n $BAD_PANDOC ]
|
||||
then
|
||||
CFG_PANDOC=
|
||||
putvar CFG_PANDOC
|
||||
fi
|
||||
|
||||
putvar CFG_LLVM_SRC_DIR
|
||||
|
||||
for t in $CFG_HOST
|
||||
|
@ -53,7 +53,9 @@ Comma separated list of types of crates for the compiler to emit.
|
||||
Specify the name of the crate being built.
|
||||
.TP
|
||||
\fB\-\-emit\fR [asm|llvm\-bc|llvm\-ir|obj|link|dep\-info]
|
||||
Configure the output that \fBrustc\fR will produce.
|
||||
Configure the output that \fBrustc\fR will produce. Each option may also be of
|
||||
the form KIND=PATH to specify the explicit output location for that particular
|
||||
emission kind.
|
||||
.TP
|
||||
\fB\-\-print\fR [crate\-name|file\-names|sysroot]
|
||||
Comma separated list of compiler information to print on stdout.
|
||||
@ -66,7 +68,8 @@ Equivalent to \fI\-C\ opt\-level=2\fR.
|
||||
.TP
|
||||
\fB\-o\fR \fIFILENAME\fR
|
||||
Write output to \fIFILENAME\fR.
|
||||
Ignored if multiple \fI\-\-emit\fR outputs are specified.
|
||||
Ignored if multiple \fI\-\-emit\fR outputs are specified which don't have an
|
||||
explicit path otherwise.
|
||||
.TP
|
||||
\fB\-\-out\-dir\fR \fIDIR\fR
|
||||
Write output to compiler\[hy]chosen filename in \fIDIR\fR.
|
||||
|
@ -7,8 +7,8 @@ CFG_LIB_NAME_mips-unknown-linux-gnu=lib$(1).so
|
||||
CFG_STATIC_LIB_NAME_mips-unknown-linux-gnu=lib$(1).a
|
||||
CFG_LIB_GLOB_mips-unknown-linux-gnu=lib$(1)-*.so
|
||||
CFG_LIB_DSYM_GLOB_mips-unknown-linux-gnu=lib$(1)-*.dylib.dSYM
|
||||
CFG_JEMALLOC_CFLAGS_mips-unknown-linux-gnu := -mips32r2 -msoft-float -mabi=32 -mno-compact-eh $(CFLAGS)
|
||||
CFG_GCCISH_CFLAGS_mips-unknown-linux-gnu := -Wall -g -fPIC -mips32r2 -msoft-float -mabi=32 -mno-compact-eh $(CFLAGS)
|
||||
CFG_JEMALLOC_CFLAGS_mips-unknown-linux-gnu := -mips32r2 -msoft-float -mabi=32 $(CFLAGS)
|
||||
CFG_GCCISH_CFLAGS_mips-unknown-linux-gnu := -Wall -g -fPIC -mips32r2 -msoft-float -mabi=32 $(CFLAGS)
|
||||
CFG_GCCISH_CXXFLAGS_mips-unknown-linux-gnu := -fno-rtti $(CXXFLAGS)
|
||||
CFG_GCCISH_LINK_FLAGS_mips-unknown-linux-gnu := -shared -fPIC -g -mips32r2 -msoft-float -mabi=32
|
||||
CFG_GCCISH_DEF_FLAG_mips-unknown-linux-gnu := -Wl,--export-dynamic,--dynamic-list=
|
||||
@ -20,5 +20,5 @@ CFG_UNIXY_mips-unknown-linux-gnu := 1
|
||||
CFG_LDPATH_mips-unknown-linux-gnu :=
|
||||
CFG_RUN_mips-unknown-linux-gnu=
|
||||
CFG_RUN_TARG_mips-unknown-linux-gnu=
|
||||
RUSTC_FLAGS_mips-unknown-linux-gnu := -C target-cpu=mips32r2 -C target-feature="+mips32r2,+o32" -C soft-float
|
||||
RUSTC_FLAGS_mips-unknown-linux-gnu := -C target-cpu=mips32r2 -C target-feature="+mips32r2" -C soft-float
|
||||
CFG_GNU_TRIPLE_mips-unknown-linux-gnu := mips-unknown-linux-gnu
|
||||
|
@ -1,8 +1,8 @@
|
||||
# mipsel-unknown-linux-gnu configuration
|
||||
CC_mipsel-unknown-linux-gnu=mipsel-unknown-linux-gnu-gcc
|
||||
CXX_mipsel-unknown-linux-gnu=mipsel-unknown-linux-gnu-g++
|
||||
CPP_mipsel-unknown-linux-gnu=mipsel-unknown-linux-gnu-gcc
|
||||
AR_mipsel-unknown-linux-gnu=mipsel-unknown-linux-gnu-ar
|
||||
CC_mipsel-unknown-linux-gnu=mipsel-linux-gnu-gcc
|
||||
CXX_mipsel-unknown-linux-gnu=mipsel-linux-gnu-g++
|
||||
CPP_mipsel-unknown-linux-gnu=mipsel-linux-gnu-gcc
|
||||
AR_mipsel-unknown-linux-gnu=mipsel-linux-gnu-ar
|
||||
CFG_LIB_NAME_mipsel-unknown-linux-gnu=lib$(1).so
|
||||
CFG_STATIC_LIB_NAME_mipsel-unknown-linux-gnu=lib$(1).a
|
||||
CFG_LIB_GLOB_mipsel-unknown-linux-gnu=lib$(1)-*.so
|
||||
@ -20,5 +20,5 @@ CFG_UNIXY_mipsel-unknown-linux-gnu := 1
|
||||
CFG_LDPATH_mipsel-unknown-linux-gnu :=
|
||||
CFG_RUN_mipsel-unknown-linux-gnu=
|
||||
CFG_RUN_TARG_mipsel-unknown-linux-gnu=
|
||||
RUSTC_FLAGS_mipsel-unknown-linux-gnu := -C target-cpu=mips32 -C target-feature="+mips32,+o32"
|
||||
RUSTC_FLAGS_mipsel-unknown-linux-gnu := -C target-cpu=mips32 -C target-feature="+mips32"
|
||||
CFG_GNU_TRIPLE_mipsel-unknown-linux-gnu := mipsel-unknown-linux-gnu
|
||||
|
24
mk/cfg/x86_64-rumprun-netbsd.mk
Normal file
24
mk/cfg/x86_64-rumprun-netbsd.mk
Normal file
@ -0,0 +1,24 @@
|
||||
# x86_64-rumprun-netbsd configuration
|
||||
CROSS_PREFIX_x86_64-rumprun-netbsd=x86_64-rumprun-netbsd-
|
||||
CC_x86_64-rumprun-netbsd=gcc
|
||||
CXX_x86_64-rumprun-netbsd=g++
|
||||
CPP_x86_64-rumprun-netbsd=gcc -E
|
||||
AR_x86_64-rumprun-netbsd=ar
|
||||
CFG_INSTALL_ONLY_RLIB_x86_64-rumprun-netbsd = 1
|
||||
CFG_LIB_NAME_x86_64-rumprun-netbsd=lib$(1).so
|
||||
CFG_STATIC_LIB_NAME_x86_64-rumprun-netbsd=lib$(1).a
|
||||
CFG_LIB_GLOB_x86_64-rumprun-netbsd=lib$(1)-*.so
|
||||
CFG_JEMALLOC_CFLAGS_x86_64-rumprun-netbsd := -m64
|
||||
CFG_GCCISH_CFLAGS_x86_64-rumprun-netbsd := -Wall -Werror -g -fPIC -m64
|
||||
CFG_GCCISH_CXXFLAGS_x86_64-rumprun-netbsd :=
|
||||
CFG_GCCISH_LINK_FLAGS_x86_64-rumprun-netbsd :=
|
||||
CFG_GCCISH_DEF_FLAG_x86_64-rumprun-netbsd :=
|
||||
CFG_LLC_FLAGS_x86_64-rumprun-netbsd :=
|
||||
CFG_INSTALL_NAME_x86_64-rumprun-netbsd =
|
||||
CFG_EXE_SUFFIX_x86_64-rumprun-netbsd =
|
||||
CFG_WINDOWSY_x86_64-rumprun-netbsd :=
|
||||
CFG_UNIXY_x86_64-rumprun-netbsd := 1
|
||||
CFG_LDPATH_x86_64-rumprun-netbsd :=
|
||||
CFG_RUN_x86_64-rumprun-netbsd=$(2)
|
||||
CFG_RUN_TARG_x86_64-rumprun-netbsd=$(call CFG_RUN_x86_64-rumprun-netbsd,,$(2))
|
||||
CFG_GNU_TRIPLE_x86_64-rumprun-netbsd := x86_64-rumprun-netbsd
|
@ -1,4 +1,5 @@
|
||||
# x86_64-unknown-netbsd configuration
|
||||
CROSS_PREFIX_x86_64-unknown-netbsd=x86_64-unknown-netbsd-
|
||||
CC_x86_64-unknown-netbsd=$(CC)
|
||||
CXX_x86_64-unknown-netbsd=$(CXX)
|
||||
CPP_x86_64-unknown-netbsd=$(CPP)
|
||||
|
68
mk/crates.mk
68
mk/crates.mk
@ -61,51 +61,55 @@ HOST_CRATES := syntax $(RUSTC_CRATES) rustdoc fmt_macros
|
||||
TOOLS := compiletest rustdoc rustc rustbook error-index-generator
|
||||
|
||||
DEPS_core :=
|
||||
DEPS_libc := core
|
||||
DEPS_rustc_unicode := core
|
||||
DEPS_alloc := core libc alloc_system
|
||||
DEPS_alloc_system := core libc
|
||||
DEPS_collections := core alloc rustc_unicode
|
||||
DEPS_libc := core
|
||||
DEPS_rand := core
|
||||
DEPS_rustc_bitflags := core
|
||||
DEPS_rustc_unicode := core
|
||||
|
||||
DEPS_std := core libc rand alloc collections rustc_unicode \
|
||||
native:rust_builtin native:backtrace \
|
||||
alloc_system
|
||||
DEPS_arena := std
|
||||
DEPS_glob := std
|
||||
DEPS_flate := std native:miniz
|
||||
DEPS_fmt_macros = std
|
||||
DEPS_getopts := std
|
||||
DEPS_graphviz := std
|
||||
DEPS_log := std
|
||||
DEPS_num := std
|
||||
DEPS_rbml := std log serialize
|
||||
DEPS_serialize := std log
|
||||
DEPS_term := std log
|
||||
DEPS_test := std getopts serialize rbml term native:rust_test_helpers
|
||||
|
||||
DEPS_syntax := std term serialize log fmt_macros arena libc rustc_bitflags
|
||||
|
||||
DEPS_rustc := syntax flate arena serialize getopts rbml rustc_front\
|
||||
log graphviz rustc_llvm rustc_back rustc_data_structures
|
||||
DEPS_rustc_back := std syntax rustc_llvm rustc_front flate log libc
|
||||
DEPS_rustc_borrowck := rustc rustc_front log graphviz syntax
|
||||
DEPS_rustc_data_structures := std log serialize
|
||||
DEPS_rustc_driver := arena flate getopts graphviz libc rustc rustc_back rustc_borrowck \
|
||||
rustc_typeck rustc_mir rustc_resolve log syntax serialize rustc_llvm \
|
||||
rustc_trans rustc_privacy rustc_lint rustc_front
|
||||
|
||||
DEPS_rustc_trans := arena flate getopts graphviz libc rustc rustc_back \
|
||||
log syntax serialize rustc_llvm rustc_front rustc_platform_intrinsics
|
||||
DEPS_rustc_mir := rustc rustc_front syntax
|
||||
DEPS_rustc_typeck := rustc syntax rustc_front rustc_platform_intrinsics
|
||||
DEPS_rustc_borrowck := rustc rustc_front log graphviz syntax
|
||||
DEPS_rustc_resolve := rustc rustc_front log syntax
|
||||
DEPS_rustc_privacy := rustc rustc_front log syntax
|
||||
DEPS_rustc_lint := rustc log syntax
|
||||
DEPS_rustc := syntax flate arena serialize getopts rbml \
|
||||
log graphviz rustc_llvm rustc_back rustc_data_structures
|
||||
DEPS_rustc_llvm := native:rustllvm libc std rustc_bitflags
|
||||
DEPS_rustc_platform_intrinsics := rustc rustc_llvm
|
||||
DEPS_rustc_back := std syntax rustc_llvm rustc_front flate log libc
|
||||
DEPS_rustc_front := std syntax log serialize
|
||||
DEPS_rustc_data_structures := std log serialize
|
||||
DEPS_rustc_lint := rustc log syntax
|
||||
DEPS_rustc_llvm := native:rustllvm libc std rustc_bitflags
|
||||
DEPS_rustc_mir := rustc rustc_front syntax
|
||||
DEPS_rustc_resolve := rustc rustc_front log syntax
|
||||
DEPS_rustc_platform_intrinsics := rustc rustc_llvm
|
||||
DEPS_rustc_privacy := rustc rustc_front log syntax
|
||||
DEPS_rustc_trans := arena flate getopts graphviz libc rustc rustc_back \
|
||||
log syntax serialize rustc_llvm rustc_front rustc_platform_intrinsics
|
||||
DEPS_rustc_typeck := rustc syntax rustc_front rustc_platform_intrinsics
|
||||
|
||||
DEPS_rustdoc := rustc rustc_driver native:hoedown serialize getopts \
|
||||
test rustc_lint rustc_front
|
||||
DEPS_rustc_bitflags := core
|
||||
DEPS_flate := std native:miniz
|
||||
DEPS_arena := std
|
||||
DEPS_graphviz := std
|
||||
DEPS_glob := std
|
||||
DEPS_serialize := std log
|
||||
DEPS_rbml := std log serialize
|
||||
DEPS_term := std log
|
||||
DEPS_getopts := std
|
||||
DEPS_collections := core alloc rustc_unicode
|
||||
DEPS_num := std
|
||||
DEPS_test := std getopts serialize rbml term native:rust_test_helpers
|
||||
DEPS_rand := core
|
||||
DEPS_log := std
|
||||
DEPS_fmt_macros = std
|
||||
DEPS_alloc_system := core libc
|
||||
|
||||
|
||||
TOOL_DEPS_compiletest := test getopts
|
||||
TOOL_DEPS_rustdoc := rustdoc
|
||||
|
117
mk/dist.mk
117
mk/dist.mk
@ -21,6 +21,7 @@
|
||||
# * dist-docs - Stage docs for upload
|
||||
|
||||
PKG_NAME := $(CFG_PACKAGE_NAME)
|
||||
STD_PKG_NAME := rust-std-$(CFG_PACKAGE_VERS)
|
||||
DOC_PKG_NAME := rust-docs-$(CFG_PACKAGE_VERS)
|
||||
MINGW_PKG_NAME := rust-mingw-$(CFG_PACKAGE_VERS)
|
||||
|
||||
@ -77,6 +78,7 @@ $(PKG_TAR): $(PKG_FILES)
|
||||
-C $(S) \
|
||||
--exclude-vcs \
|
||||
--exclude=*~ \
|
||||
--exclude=*.pyc \
|
||||
--exclude=*/llvm/test/*/*.ll \
|
||||
--exclude=*/llvm/test/*/*.td \
|
||||
--exclude=*/llvm/test/*/*.s \
|
||||
@ -111,19 +113,25 @@ distcheck-tar-src: dist-tar-src
|
||||
# Unix binary installer tarballs
|
||||
######################################################################
|
||||
|
||||
define DEF_INSTALLER
|
||||
define DEF_START_INSTALLER
|
||||
dist-install-dir-$(1)-%: PREPARE_DIR_CMD=$(DEFAULT_PREPARE_DIR_CMD)
|
||||
dist-install-dir-$(1)-%: PREPARE_BIN_CMD=$(DEFAULT_PREPARE_BIN_CMD)
|
||||
dist-install-dir-$(1)-%: PREPARE_LIB_CMD=$(DEFAULT_PREPARE_LIB_CMD)
|
||||
dist-install-dir-$(1)-%: PREPARE_MAN_CMD=$(DEFAULT_PREPARE_MAN_CMD)
|
||||
dist-install-dir-$(1)-%: PREPARE_CLEAN=true
|
||||
|
||||
$$(eval $$(call DEF_PREPARE,dir-$(1)))
|
||||
endef
|
||||
|
||||
dist-install-dir-$(1): PREPARE_HOST=$(1)
|
||||
dist-install-dir-$(1): PREPARE_TARGETS=$(2)
|
||||
dist-install-dir-$(1): PREPARE_DEST_DIR=tmp/dist/$$(PKG_NAME)-$(1)-image
|
||||
dist-install-dir-$(1): PREPARE_DIR_CMD=$(DEFAULT_PREPARE_DIR_CMD)
|
||||
dist-install-dir-$(1): PREPARE_BIN_CMD=$(DEFAULT_PREPARE_BIN_CMD)
|
||||
dist-install-dir-$(1): PREPARE_LIB_CMD=$(DEFAULT_PREPARE_LIB_CMD)
|
||||
dist-install-dir-$(1): PREPARE_MAN_CMD=$(DEFAULT_PREPARE_MAN_CMD)
|
||||
dist-install-dir-$(1): PREPARE_CLEAN=true
|
||||
dist-install-dir-$(1): prepare-base-dir-$(1) docs
|
||||
$(foreach target,$(CFG_TARGET),\
|
||||
$(eval $(call DEF_START_INSTALLER,$(target))))
|
||||
|
||||
define DEF_INSTALLER
|
||||
|
||||
dist-install-dir-$(1)-host: PREPARE_HOST=$(1)
|
||||
dist-install-dir-$(1)-host: PREPARE_TARGETS=$(2)
|
||||
dist-install-dir-$(1)-host: PREPARE_DEST_DIR=tmp/dist/$$(PKG_NAME)-$(1)-image
|
||||
dist-install-dir-$(1)-host: prepare-base-dir-$(1)-host docs
|
||||
$$(Q)mkdir -p $$(PREPARE_DEST_DIR)/share/doc/rust
|
||||
$$(Q)$$(PREPARE_MAN_CMD) $$(S)COPYRIGHT $$(PREPARE_DEST_DIR)/share/doc/rust
|
||||
$$(Q)$$(PREPARE_MAN_CMD) $$(S)LICENSE-APACHE $$(PREPARE_DEST_DIR)/share/doc/rust
|
||||
@ -140,14 +148,27 @@ prepare-overlay-$(1):
|
||||
# This tiny morsel of metadata is used by rust-packaging
|
||||
$$(Q)echo "$(CFG_VERSION)" > tmp/dist/$$(PKG_NAME)-$(1)-overlay/version
|
||||
|
||||
dist/$$(PKG_NAME)-$(1).tar.gz: dist-install-dir-$(1) prepare-overlay-$(1)
|
||||
dist/$$(PKG_NAME)-$(1).tar.gz: dist-install-dir-$(1)-host prepare-overlay-$(1)
|
||||
@$(call E, build: $$@)
|
||||
# Copy essential gcc components into installer
|
||||
ifdef CFG_WINDOWSY_$(1)
|
||||
ifeq ($$(findstring gnu,$(1)),gnu)
|
||||
# On a MinGW target we've got a few runtime DLL dependencies that we need
|
||||
# to include. THe first argument to `make-win-dist` is where to put these DLLs
|
||||
# (the image we're creating) and the second argument is a junk directory to
|
||||
# ignore all the other MinGW stuff the script creates.
|
||||
ifeq ($$(findstring pc-windows-gnu,$(1)),pc-windows-gnu)
|
||||
$$(Q)rm -Rf tmp/dist/win-rust-gcc-$(1)
|
||||
$$(Q)$$(CFG_PYTHON) $$(S)src/etc/make-win-dist.py tmp/dist/$$(PKG_NAME)-$(1)-image tmp/dist/win-rust-gcc-$(1) $(1)
|
||||
$$(Q)cp -r $$(S)src/etc/third-party tmp/dist/$$(PKG_NAME)-$(1)-image/share/doc/
|
||||
$$(Q)$$(CFG_PYTHON) $$(S)src/etc/make-win-dist.py \
|
||||
tmp/dist/$$(PKG_NAME)-$(1)-image \
|
||||
tmp/dist/win-rust-gcc-$(1) $(1)
|
||||
endif
|
||||
# On 32-bit MinGW we're always including a DLL which needs some extra licenses
|
||||
# to distribute. On 64-bit MinGW we don't actually distribute anything requiring
|
||||
# us to distribute a license but it's likely that the install will *also*
|
||||
# include the rust-mingw package down below, which also need licenses, so to be
|
||||
# safe we just inlude it here in all MinGW packages.
|
||||
ifdef CFG_WINDOWSY_$(1)
|
||||
ifeq ($$(findstring $(1),gnu),gnu)
|
||||
$$(Q)cp -r $$(S)src/etc/third-party \
|
||||
tmp/dist/$$(PKG_NAME)-$(1)-image/share/doc/
|
||||
endif
|
||||
endif
|
||||
$$(Q)$$(S)src/rust-installer/gen-installer.sh \
|
||||
@ -182,11 +203,16 @@ dist/$$(DOC_PKG_NAME)-$(1).tar.gz: dist-doc-install-dir-$(1)
|
||||
--bulk-dirs=share/doc/rust/html
|
||||
$$(Q)rm -R tmp/dist/$$(DOC_PKG_NAME)-$(1)-image
|
||||
|
||||
# Creates the rust-mingw package, and the first argument to make-win-dist is a
|
||||
# "temporary directory" which is just thrown away (this contains the runtime
|
||||
# DLLs included in the rustc package above) and the second argument is where to
|
||||
# place all the MinGW components (which is what we want).
|
||||
dist-mingw-install-dir-$(1):
|
||||
$$(Q)mkdir -p tmp/dist/rust-mingw-tmp-$(1)-image
|
||||
$$(Q)rm -Rf tmp/dist/$$(MINGW_PKG_NAME)-$(1)-image
|
||||
$$(Q)$$(CFG_PYTHON) $$(S)src/etc/make-win-dist.py \
|
||||
tmp/dist/rust-mingw-tmp-$(1)-image tmp/dist/$$(MINGW_PKG_NAME)-$(1)-image $(1)
|
||||
tmp/dist/rust-mingw-tmp-$(1)-image \
|
||||
tmp/dist/$$(MINGW_PKG_NAME)-$(1)-image $(1)
|
||||
|
||||
dist/$$(MINGW_PKG_NAME)-$(1).tar.gz: dist-mingw-install-dir-$(1)
|
||||
@$(call E, build: $$@)
|
||||
@ -204,15 +230,52 @@ dist/$$(MINGW_PKG_NAME)-$(1).tar.gz: dist-mingw-install-dir-$(1)
|
||||
|
||||
endef
|
||||
|
||||
ifneq ($(CFG_ENABLE_DIST_HOST_ONLY),)
|
||||
$(foreach host,$(CFG_HOST),\
|
||||
$(eval $(call DEF_INSTALLER,$(host),$(host))))
|
||||
else
|
||||
$(foreach host,$(CFG_HOST),\
|
||||
$(eval $(call DEF_INSTALLER,$(host),$(CFG_TARGET))))
|
||||
endif
|
||||
# $(1) - host
|
||||
# $(2) - target
|
||||
define DEF_INSTALLER_TARGETS
|
||||
|
||||
dist-install-dirs: $(foreach host,$(CFG_HOST),dist-install-dir-$(host))
|
||||
dist-install-dir-$(2)-target: PREPARE_HOST=$(1)
|
||||
dist-install-dir-$(2)-target: PREPARE_TARGETS=$(2)
|
||||
dist-install-dir-$(2)-target: PREPARE_DEST_DIR=tmp/dist/$$(STD_PKG_NAME)-$(2)-image
|
||||
dist-install-dir-$(2)-target: prepare-base-dir-$(2)-target
|
||||
|
||||
dist/$$(STD_PKG_NAME)-$(2).tar.gz: dist-install-dir-$(2)-target
|
||||
@$$(call E, build: $$@)
|
||||
$$(Q)$$(S)src/rust-installer/gen-installer.sh \
|
||||
--product-name=Rust \
|
||||
--rel-manifest-dir=rustlib \
|
||||
--success-message=std-is-standing-at-the-ready. \
|
||||
--image-dir=tmp/dist/$$(STD_PKG_NAME)-$(2)-image \
|
||||
--work-dir=tmp/dist \
|
||||
--output-dir=dist \
|
||||
--package-name=$$(STD_PKG_NAME)-$(2) \
|
||||
--component-name=rust-std-$(2) \
|
||||
--legacy-manifest-dirs=rustlib,cargo
|
||||
$$(Q)rm -R tmp/dist/$$(STD_PKG_NAME)-$(2)-image
|
||||
endef
|
||||
|
||||
$(foreach host,$(CFG_HOST),\
|
||||
$(eval $(call DEF_INSTALLER,$(host))))
|
||||
|
||||
# When generating packages for the standard library, we've actually got a lot of
|
||||
# artifacts to choose from. Each of the CFG_HOST compilers will have a copy of
|
||||
# the standard library for each CFG_TARGET, but we only want to generate one
|
||||
# standard library package. As a result, for each entry in CFG_TARGET we need to
|
||||
# pick a CFG_HOST to get the standard library from.
|
||||
#
|
||||
# In theory it doesn't actually matter what host we choose as it should be the
|
||||
# case that all hosts produce the same set of libraries for a target (regardless
|
||||
# of the host itself). Currently there is a bug in the compiler, however, which
|
||||
# means this is not the case (see #29228 and #29235). To solve the first of
|
||||
# those bugs, we prefer to select a standard library from the host it was
|
||||
# generated from, allowing plugins to work in more situations.
|
||||
#
|
||||
# For all CFG_TARGET entries in CFG_HOST, however, we just pick CFG_BUILD as the
|
||||
# host we slurp up a standard library from.
|
||||
$(foreach host,$(CFG_HOST),\
|
||||
$(eval $(call DEF_INSTALLER_TARGETS,$(host),$(host))))
|
||||
$(foreach target,$(filter-out $(CFG_HOST),$(CFG_TARGET)),\
|
||||
$(eval $(call DEF_INSTALLER_TARGETS,$(CFG_BUILD),$(target))))
|
||||
|
||||
ifdef CFG_WINDOWSY_$(CFG_BUILD)
|
||||
define BUILD_MINGW_TARBALL
|
||||
@ -229,7 +292,9 @@ ifeq ($(CFG_DISABLE_DOCS),)
|
||||
MAYBE_DOC_TARBALLS=$(foreach host,$(CFG_HOST),dist/$(DOC_PKG_NAME)-$(host).tar.gz)
|
||||
endif
|
||||
|
||||
dist-tar-bins: $(foreach host,$(CFG_HOST),dist/$(PKG_NAME)-$(host).tar.gz) \
|
||||
dist-tar-bins: \
|
||||
$(foreach host,$(CFG_HOST),dist/$(PKG_NAME)-$(host).tar.gz) \
|
||||
$(foreach target,$(CFG_TARGET),dist/$(STD_PKG_NAME)-$(target).tar.gz) \
|
||||
$(MAYBE_DOC_TARBALLS) $(MAYBE_MINGW_TARBALLS)
|
||||
|
||||
# Just try to run the compiler for the build host
|
||||
|
@ -58,17 +58,17 @@ check-lexer: $(BG) $(BG)RustLexer.class check-build-lexer-verifier
|
||||
$(Q)$(SG)check.sh $(S) "$(BG)" \
|
||||
"$(CFG_GRUN)" "$(BG)verify" "$(BG)RustLexer.tokens"
|
||||
else
|
||||
$(info cfg: grun not available, skipping lexer test...)
|
||||
$(info cfg: lexer tooling not available, skipping lexer test...)
|
||||
check-lexer:
|
||||
|
||||
endif
|
||||
else
|
||||
$(info cfg: antlr4 not available, skipping lexer test...)
|
||||
$(info cfg: lexer tooling not available, skipping lexer test...)
|
||||
check-lexer:
|
||||
|
||||
endif
|
||||
else
|
||||
$(info cfg: javac not available, skipping lexer test...)
|
||||
$(info cfg: lexer tooling not available, skipping lexer test...)
|
||||
check-lexer:
|
||||
|
||||
endif
|
||||
|
@ -8,6 +8,12 @@
|
||||
# option. This file may not be copied, modified, or distributed
|
||||
# except according to those terms.
|
||||
|
||||
RUN_INSALLER = cd tmp/empty_dir && \
|
||||
sh ../../tmp/dist/$(1)/install.sh \
|
||||
--prefix="$(DESTDIR)$(CFG_PREFIX)" \
|
||||
--libdir="$(DESTDIR)$(CFG_LIBDIR)" \
|
||||
--mandir="$(DESTDIR)$(CFG_MANDIR)"
|
||||
|
||||
install:
|
||||
ifeq (root user, $(USER) $(patsubst %,user,$(SUDO_USER)))
|
||||
# Build the dist as the original user
|
||||
@ -16,9 +22,11 @@ else
|
||||
$(Q)$(MAKE) prepare_install
|
||||
endif
|
||||
ifeq ($(CFG_DISABLE_DOCS),)
|
||||
$(Q)cd tmp/empty_dir && sh ../../tmp/dist/$(DOC_PKG_NAME)-$(CFG_BUILD)/install.sh --prefix="$(DESTDIR)$(CFG_PREFIX)" --libdir="$(DESTDIR)$(CFG_LIBDIR)" --mandir="$(DESTDIR)$(CFG_MANDIR)"
|
||||
$(Q)$(call RUN_INSALLER,$(DOC_PKG_NAME)-$(CFG_BUILD)) --disable-ldconfig
|
||||
endif
|
||||
$(Q)cd tmp/empty_dir && sh ../../tmp/dist/$(PKG_NAME)-$(CFG_BUILD)/install.sh --prefix="$(DESTDIR)$(CFG_PREFIX)" --libdir="$(DESTDIR)$(CFG_LIBDIR)" --mandir="$(DESTDIR)$(CFG_MANDIR)"
|
||||
$(Q)$(foreach target,$(CFG_TARGET),\
|
||||
($(call RUN_INSALLER,$(STD_PKG_NAME)-$(target)) --disable-ldconfig);)
|
||||
$(Q)$(call RUN_INSALLER,$(PKG_NAME)-$(CFG_BUILD))
|
||||
# Remove tmp files because it's a decent amount of disk space
|
||||
$(Q)rm -R tmp/dist
|
||||
|
||||
@ -32,9 +40,11 @@ else
|
||||
$(Q)$(MAKE) prepare_uninstall
|
||||
endif
|
||||
ifeq ($(CFG_DISABLE_DOCS),)
|
||||
$(Q)cd tmp/empty_dir && sh ../../tmp/dist/$(DOC_PKG_NAME)-$(CFG_BUILD)/install.sh --uninstall --prefix="$(DESTDIR)$(CFG_PREFIX)" --libdir="$(DESTDIR)$(CFG_LIBDIR)" --mandir="$(DESTDIR)$(CFG_MANDIR)"
|
||||
$(Q)$(call RUN_INSALLER,$(DOC_PKG_NAME)-$(CFG_BUILD)) --uninstall
|
||||
endif
|
||||
$(Q)cd tmp/empty_dir && sh ../../tmp/dist/$(PKG_NAME)-$(CFG_BUILD)/install.sh --uninstall --prefix="$(DESTDIR)$(CFG_PREFIX)" --libdir="$(DESTDIR)$(CFG_LIBDIR)" --mandir="$(DESTDIR)$(CFG_MANDIR)"
|
||||
$(Q)$(call RUN_INSALLER,$(PKG_NAME)-$(CFG_BUILD)) --uninstall
|
||||
$(Q)$(foreach target,$(CFG_TARGET),\
|
||||
($(call RUN_INSALLER,$(STD_PKG_NAME)-$(target)) --uninstall);)
|
||||
# Remove tmp files because it's a decent amount of disk space
|
||||
$(Q)rm -R tmp/dist
|
||||
|
||||
|
@ -73,7 +73,7 @@ $$(LLVM_STAMP_$(1)): $(S)src/rustllvm/llvm-auto-clean-trigger
|
||||
|
||||
ifeq ($$(CFG_ENABLE_LLVM_STATIC_STDCPP),1)
|
||||
LLVM_STDCPP_RUSTFLAGS_$(1) = -L "$$(dir $$(shell $$(CC_$(1)) $$(CFG_GCCISH_CFLAGS_$(1)) \
|
||||
-print-file-name=libstdc++.a))"
|
||||
-print-file-name=lib$(CFG_STDCPP_NAME).a))"
|
||||
else
|
||||
LLVM_STDCPP_RUSTFLAGS_$(1) =
|
||||
endif
|
||||
@ -83,7 +83,7 @@ endif
|
||||
LLVM_LINKAGE_PATH_$(1):=$$(abspath $$(RT_OUTPUT_DIR_$(1))/llvmdeps.rs)
|
||||
$$(LLVM_LINKAGE_PATH_$(1)): $(S)src/etc/mklldeps.py $$(LLVM_CONFIG_$(1))
|
||||
$(Q)$(CFG_PYTHON) "$$<" "$$@" "$$(LLVM_COMPONENTS)" "$$(CFG_ENABLE_LLVM_STATIC_STDCPP)" \
|
||||
$$(LLVM_CONFIG_$(1))
|
||||
$$(LLVM_CONFIG_$(1)) "$(CFG_STDCPP_NAME)"
|
||||
endef
|
||||
|
||||
$(foreach host,$(CFG_HOST), \
|
||||
|
25
mk/main.mk
25
mk/main.mk
@ -13,12 +13,12 @@
|
||||
######################################################################
|
||||
|
||||
# The version number
|
||||
CFG_RELEASE_NUM=1.4.0
|
||||
CFG_RELEASE_NUM=1.5.0
|
||||
|
||||
# An optional number to put after the label, e.g. '.2' -> '-beta.2'
|
||||
# NB Make sure it starts with a dot to conform to semver pre-release
|
||||
# versions (section 9)
|
||||
CFG_PRERELEASE_VERSION=.4
|
||||
CFG_PRERELEASE_VERSION=.5
|
||||
|
||||
# Append a version-dependent hash to each library, so we can install different
|
||||
# versions in the same place
|
||||
@ -132,7 +132,11 @@ endif
|
||||
|
||||
ifdef CFG_ENABLE_DEBUGINFO
|
||||
$(info cfg: enabling debuginfo (CFG_ENABLE_DEBUGINFO))
|
||||
CFG_RUSTC_FLAGS += -g
|
||||
# FIXME: Re-enable -g in stage0 after new snapshot
|
||||
#CFG_RUSTC_FLAGS += -g
|
||||
RUSTFLAGS_STAGE1 += -g
|
||||
RUSTFLAGS_STAGE2 += -g
|
||||
RUSTFLAGS_STAGE3 += -g
|
||||
endif
|
||||
|
||||
ifdef SAVE_TEMPS
|
||||
@ -170,19 +174,10 @@ RUST_LIB_FLAGS_ST3 += -C prefer-dynamic
|
||||
|
||||
# Landing pads require a lot of codegen. We can get through bootstrapping faster
|
||||
# by not emitting them.
|
||||
RUSTFLAGS_STAGE0 += -Z no-landing-pads
|
||||
|
||||
# Enable MIR to "always build" for crates where this works. This is
|
||||
# just temporary while MIR is being actively built up -- it's just a
|
||||
# poor man's unit testing infrastructure. Anyway we only want this for
|
||||
# stage1/stage2.
|
||||
define ADD_MIR_FLAG
|
||||
RUSTFLAGS1_$(1) += -Z always-build-mir
|
||||
RUSTFLAGS2_$(1) += -Z always-build-mir
|
||||
endef
|
||||
$(foreach crate,$(TARGET_CRATES),$(eval $(call ADD_MIR_FLAG,$(crate))))
|
||||
$(foreach crate,$(RUSTC_CRATES),$(eval $(call ADD_MIR_FLAG,$(crate))))
|
||||
$(foreach crate,$(HOST_CRATES),$(eval $(call ADD_MIR_FLAG,$(crate))))
|
||||
ifdef CFG_DISABLE_STAGE0_LANDING_PADS
|
||||
RUSTFLAGS_STAGE0 += -Z no-landing-pads
|
||||
endif
|
||||
|
||||
# platform-specific auto-configuration
|
||||
include $(CFG_SRC_DIR)mk/platform.mk
|
||||
|
@ -208,6 +208,14 @@ define CFG_MAKE_TOOLCHAIN
|
||||
|
||||
ifeq ($$(findstring $(HOST_$(1)),arm aarch64 mips mipsel powerpc),)
|
||||
|
||||
# On OpenBSD, we need to pass the path of libstdc++.so to the linker
|
||||
# (use path of libstdc++.a which is a known name for the same path)
|
||||
ifeq ($(OSTYPE_$(1)),unknown-openbsd)
|
||||
RUSTC_FLAGS_$(1)=-L "$$(dir $$(shell $$(CC_$(1)) $$(CFG_GCCISH_CFLAGS_$(1)) \
|
||||
-print-file-name=lib$(CFG_STDCPP_NAME).a))" \
|
||||
$(RUSTC_FLAGS_$(1))
|
||||
endif
|
||||
|
||||
# On Bitrig, we need the relocation model to be PIC for everything
|
||||
ifeq (,$(filter $(OSTYPE_$(1)),bitrig))
|
||||
LLVM_MC_RELOCATION_MODEL="pic"
|
||||
|
@ -185,16 +185,16 @@ INSTALL_DEBUGGER_SCRIPT_COMMANDS=$(if $(findstring windows,$(1)),\
|
||||
|
||||
define DEF_PREPARE
|
||||
|
||||
prepare-base-$(1): PREPARE_SOURCE_DIR=$$(PREPARE_HOST)/stage$$(PREPARE_STAGE)
|
||||
prepare-base-$(1): PREPARE_SOURCE_BIN_DIR=$$(PREPARE_SOURCE_DIR)/bin
|
||||
prepare-base-$(1): PREPARE_SOURCE_LIB_DIR=$$(PREPARE_SOURCE_DIR)/$$(CFG_LIBDIR_RELATIVE)
|
||||
prepare-base-$(1): PREPARE_SOURCE_MAN_DIR=$$(S)/man
|
||||
prepare-base-$(1): PREPARE_DEST_BIN_DIR=$$(PREPARE_DEST_DIR)/bin
|
||||
prepare-base-$(1): PREPARE_DEST_LIB_DIR=$$(PREPARE_DEST_DIR)/$$(CFG_LIBDIR_RELATIVE)
|
||||
prepare-base-$(1): PREPARE_DEST_MAN_DIR=$$(PREPARE_DEST_DIR)/share/man/man1
|
||||
prepare-base-$(1): prepare-everything-$(1)
|
||||
prepare-base-$(1)-%: PREPARE_SOURCE_DIR=$$(PREPARE_HOST)/stage$$(PREPARE_STAGE)
|
||||
prepare-base-$(1)-%: PREPARE_SOURCE_BIN_DIR=$$(PREPARE_SOURCE_DIR)/bin
|
||||
prepare-base-$(1)-%: PREPARE_SOURCE_LIB_DIR=$$(PREPARE_SOURCE_DIR)/$$(CFG_LIBDIR_RELATIVE)
|
||||
prepare-base-$(1)-%: PREPARE_SOURCE_MAN_DIR=$$(S)/man
|
||||
prepare-base-$(1)-%: PREPARE_DEST_BIN_DIR=$$(PREPARE_DEST_DIR)/bin
|
||||
prepare-base-$(1)-%: PREPARE_DEST_LIB_DIR=$$(PREPARE_DEST_DIR)/$$(CFG_LIBDIR_RELATIVE)
|
||||
prepare-base-$(1)-%: PREPARE_DEST_MAN_DIR=$$(PREPARE_DEST_DIR)/share/man/man1
|
||||
|
||||
prepare-everything-$(1): prepare-host-$(1) prepare-targets-$(1) prepare-debugger-scripts-$(1)
|
||||
prepare-base-$(1)-target: prepare-target-$(1)
|
||||
prepare-base-$(1)-host: prepare-host-$(1) prepare-debugger-scripts-$(1)
|
||||
|
||||
prepare-host-$(1): prepare-host-tools-$(1)
|
||||
|
||||
@ -222,7 +222,7 @@ $$(foreach lib,$$(CRATES), \
|
||||
$$(foreach host,$$(CFG_HOST), \
|
||||
$$(eval $$(call DEF_PREPARE_HOST_LIB,$$(lib),$$(PREPARE_STAGE),$$(host),$(1)))))
|
||||
|
||||
prepare-targets-$(1): \
|
||||
prepare-target-$(1): \
|
||||
$$(foreach host,$$(CFG_HOST), \
|
||||
$$(foreach target,$$(CFG_TARGET), \
|
||||
prepare-target-$$(target)-host-$$(host)-$$(PREPARE_STAGE)-$(1)))
|
||||
|
@ -1046,6 +1046,10 @@ $$(call TEST_OK_FILE,$(1),$(2),$(3),rmake): \
|
||||
$$(RMAKE_TESTS:%=$(3)/test/run-make/%-$(1)-T-$(2)-H-$(3).ok)
|
||||
@touch $$@
|
||||
|
||||
$(3)/test/run-make/%-$(1)-T-$(2)-H-$(3).ok: \
|
||||
export INCLUDE := $$(CFG_MSVC_INCLUDE_PATH_$$(HOST_$(3)))
|
||||
$(3)/test/run-make/%-$(1)-T-$(2)-H-$(3).ok: \
|
||||
export LIB := $$(CFG_MSVC_LIB_PATH_$$(HOST_$(3)))
|
||||
$(3)/test/run-make/%-$(1)-T-$(2)-H-$(3).ok: \
|
||||
$(S)src/test/run-make/%/Makefile \
|
||||
$$(CSREQ$(1)_T_$(2)_H_$(3))
|
||||
@ -1056,7 +1060,7 @@ $(3)/test/run-make/%-$(1)-T-$(2)-H-$(3).ok: \
|
||||
$$(MAKE) \
|
||||
$$(HBIN$(1)_H_$(3))/rustc$$(X_$(3)) \
|
||||
$(3)/test/run-make/$$* \
|
||||
$$(CC_$(3)) \
|
||||
'$$(CC_$(3))' \
|
||||
"$$(CFG_GCCISH_CFLAGS_$(3))" \
|
||||
$$(HBIN$(1)_H_$(3))/rustdoc$$(X_$(3)) \
|
||||
"$$(TESTNAME)" \
|
||||
@ -1064,7 +1068,8 @@ $(3)/test/run-make/%-$(1)-T-$(2)-H-$(3).ok: \
|
||||
"$$(LD_LIBRARY_PATH_ENV_HOSTDIR$(1)_T_$(2)_H_$(3))" \
|
||||
"$$(LD_LIBRARY_PATH_ENV_TARGETDIR$(1)_T_$(2)_H_$(3))" \
|
||||
$(1) \
|
||||
$$(S)
|
||||
$$(S) \
|
||||
$(3)
|
||||
@touch -r $$@.start_time $$@ && rm $$@.start_time
|
||||
else
|
||||
# FIXME #11094 - The above rule doesn't work right for multiple targets
|
||||
|
@ -13,9 +13,7 @@
|
||||
#![feature(box_syntax)]
|
||||
#![feature(dynamic_lib)]
|
||||
#![feature(libc)]
|
||||
#![feature(path_ext)]
|
||||
#![feature(rustc_private)]
|
||||
#![feature(slice_splits)]
|
||||
#![feature(str_char)]
|
||||
#![feature(test)]
|
||||
#![feature(vec_push_all)]
|
||||
@ -92,7 +90,7 @@ pub fn parse_config(args: Vec<String> ) -> Config {
|
||||
optflag("h", "help", "show this message"));
|
||||
|
||||
let (argv0, args_) = args.split_first().unwrap();
|
||||
if args[1] == "-h" || args[1] == "--help" {
|
||||
if args.len() == 1 || args[1] == "-h" || args[1] == "--help" {
|
||||
let message = format!("Usage: {} [OPTIONS] [TESTNAME...]", argv0);
|
||||
println!("{}", getopts::usage(&message, &groups));
|
||||
println!("");
|
||||
@ -348,7 +346,7 @@ fn extract_gdb_version(full_version_line: Option<String>) -> Option<String> {
|
||||
if !full_version_line.trim().is_empty() => {
|
||||
let full_version_line = full_version_line.trim();
|
||||
|
||||
// used to be a regex "(^|[^0-9])([0-9]\.[0-9])([^0-9]|$)"
|
||||
// used to be a regex "(^|[^0-9])([0-9]\.[0-9]+)"
|
||||
for (pos, c) in full_version_line.char_indices() {
|
||||
if !c.is_digit(10) { continue }
|
||||
if pos + 2 >= full_version_line.len() { continue }
|
||||
@ -357,11 +355,12 @@ fn extract_gdb_version(full_version_line: Option<String>) -> Option<String> {
|
||||
if pos > 0 && full_version_line.char_at_reverse(pos).is_digit(10) {
|
||||
continue
|
||||
}
|
||||
if pos + 3 < full_version_line.len() &&
|
||||
full_version_line.char_at(pos + 3).is_digit(10) {
|
||||
continue
|
||||
let mut end = pos + 3;
|
||||
while end < full_version_line.len() &&
|
||||
full_version_line.char_at(end).is_digit(10) {
|
||||
end += 1;
|
||||
}
|
||||
return Some(full_version_line[pos..pos+3].to_owned());
|
||||
return Some(full_version_line[pos..end].to_owned());
|
||||
}
|
||||
println!("Could not extract GDB version from line '{}'",
|
||||
full_version_line);
|
||||
|
@ -8,6 +8,8 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
#![allow(deprecated)]
|
||||
|
||||
use std::dynamic_lib::DynamicLibrary;
|
||||
use std::io::prelude::*;
|
||||
use std::path::PathBuf;
|
||||
|
@ -1669,8 +1669,7 @@ fn compile_test_and_save_ir(config: &Config, props: &TestProps,
|
||||
// FIXME (#9639): This needs to handle non-utf8 paths
|
||||
let mut link_args = vec!("-L".to_owned(),
|
||||
aux_dir.to_str().unwrap().to_owned());
|
||||
let llvm_args = vec!("--emit=llvm-ir".to_owned(),
|
||||
"--crate-type=lib".to_owned());
|
||||
let llvm_args = vec!("--emit=llvm-ir".to_owned(),);
|
||||
link_args.extend(llvm_args);
|
||||
let args = make_compile_args(config,
|
||||
props,
|
||||
|
@ -2,9 +2,10 @@
|
||||
|
||||
## Building
|
||||
|
||||
To generate all the docs, just run `make docs` from the root of the repository.
|
||||
This will convert the distributed Markdown docs to HTML and generate HTML doc
|
||||
for the 'std' and 'extra' libraries.
|
||||
To generate all the docs, follow the "Building Documentation" instructions in
|
||||
the README in the root of the repository. This will convert the distributed
|
||||
Markdown docs to HTML and generate HTML doc for the books, 'std' and 'extra'
|
||||
libraries.
|
||||
|
||||
To generate HTML documentation from one source file/crate, do something like:
|
||||
|
||||
|
@ -76,7 +76,7 @@ Cleanup through RAII-style destructors is more likely to work than in catch bloc
|
||||
|
||||
## Why aren't modules type-parametric?
|
||||
|
||||
We want to maintain the option to parametrize at runtime. We may eventually change this limitation, but initially this is how type parameters were implemented.
|
||||
We want to maintain the option to parameterize at runtime. We may eventually change this limitation, but initially this is how type parameters were implemented.
|
||||
|
||||
## Why aren't values type-parametric? Why only items?
|
||||
|
||||
|
@ -22,7 +22,7 @@ Existing languages at this level of abstraction and efficiency are unsatisfactor
|
||||
|
||||
# Is any part of this thing production-ready?
|
||||
|
||||
No. Feel free to play around, but don't expect completeness or stability yet. Expect incompleteness and breakage.
|
||||
Yes!
|
||||
|
||||
# Is this a completely Mozilla-planned and orchestrated thing?
|
||||
|
||||
|
@ -9,7 +9,7 @@ provides only one kind of material:
|
||||
|
||||
This document does not serve as an introduction to the language. Background
|
||||
familiarity with the language is assumed. A separate [guide] is available to
|
||||
help acquire such background familiarity.
|
||||
help acquire such background.
|
||||
|
||||
This document also does not serve as a reference to the [standard] library
|
||||
included in the language distribution. Those libraries are documented
|
||||
@ -258,8 +258,8 @@ symbol : "::" | "->"
|
||||
| ',' | ';' ;
|
||||
```
|
||||
|
||||
Symbols are a general class of printable [token](#tokens) that play structural
|
||||
roles in a variety of grammar productions. They are catalogued here for
|
||||
Symbols are a general class of printable [tokens](#tokens) that play structural
|
||||
roles in a variety of grammar productions. They are cataloged here for
|
||||
completeness as the set of remaining miscellaneous printable tokens that do not
|
||||
otherwise appear as [unary operators](#unary-operator-expressions), [binary
|
||||
operators](#binary-operator-expressions), or [keywords](#keywords).
|
||||
@ -436,7 +436,7 @@ meta_seq : meta_item [ ',' meta_seq ] ? ;
|
||||
## Statements
|
||||
|
||||
```antlr
|
||||
stmt : decl_stmt | expr_stmt ;
|
||||
stmt : decl_stmt | expr_stmt | ';' ;
|
||||
```
|
||||
|
||||
### Declaration statements
|
||||
@ -773,7 +773,7 @@ bound := path | lifetime
|
||||
|
||||
## Type kinds
|
||||
|
||||
**FIXME:** this this probably not relevant to the grammar...
|
||||
**FIXME:** this is probably not relevant to the grammar...
|
||||
|
||||
# Memory and concurrency models
|
||||
|
||||
|
@ -98,3 +98,4 @@ languages:
|
||||
- [Korean](https://github.com/rust-kr/doc.rust-kr.org)
|
||||
- [Chinese](https://github.com/KaiserY/rust-book-chinese)
|
||||
- [Spanish](https://goyox86.github.io/elpr)
|
||||
- [German](https://panicbit.github.io/rustbook-de)
|
||||
|
@ -1,11 +1,11 @@
|
||||
% Atomics
|
||||
|
||||
Rust pretty blatantly just inherits C11's memory model for atomics. This is not
|
||||
due this model being particularly excellent or easy to understand. Indeed, this
|
||||
model is quite complex and known to have [several flaws][C11-busted]. Rather, it
|
||||
is a pragmatic concession to the fact that *everyone* is pretty bad at modeling
|
||||
atomics. At very least, we can benefit from existing tooling and research around
|
||||
C.
|
||||
due to this model being particularly excellent or easy to understand. Indeed,
|
||||
this model is quite complex and known to have [several flaws][C11-busted].
|
||||
Rather, it is a pragmatic concession to the fact that *everyone* is pretty bad
|
||||
at modeling atomics. At very least, we can benefit from existing tooling and
|
||||
research around C.
|
||||
|
||||
Trying to fully explain the model in this book is fairly hopeless. It's defined
|
||||
in terms of madness-inducing causality graphs that require a full book to
|
||||
|
@ -52,7 +52,7 @@ For numeric casts, there are quite a few cases to consider:
|
||||
* zero-extend if the source is unsigned
|
||||
* sign-extend if the source is signed
|
||||
* casting from a float to an integer will round the float towards zero
|
||||
* **[NOTE: currently this will cause Undefined Behaviour if the rounded
|
||||
* **[NOTE: currently this will cause Undefined Behavior if the rounded
|
||||
value cannot be represented by the target integer type][float-int]**.
|
||||
This includes Inf and NaN. This is a bug and will be fixed.
|
||||
* casting from an integer to float will produce the floating point
|
||||
@ -61,7 +61,7 @@ For numeric casts, there are quite a few cases to consider:
|
||||
* casting from an f32 to an f64 is perfect and lossless
|
||||
* casting from an f64 to an f32 will produce the closest possible value
|
||||
(rounding strategy unspecified)
|
||||
* **[NOTE: currently this will cause Undefined Behaviour if the value
|
||||
* **[NOTE: currently this will cause Undefined Behavior if the value
|
||||
is finite but larger or smaller than the largest or smallest finite
|
||||
value representable by f32][float-float]**. This is a bug and will
|
||||
be fixed.
|
||||
|
@ -1,4 +1,4 @@
|
||||
% Concurrency and Paralellism
|
||||
% Concurrency and Parallelism
|
||||
|
||||
Rust as a language doesn't *really* have an opinion on how to do concurrency or
|
||||
parallelism. The standard library exposes OS threads and blocking sys-calls
|
||||
|
@ -17,7 +17,7 @@ boilerplate" to drop children. If a struct has no special logic for being
|
||||
dropped other than dropping its children, then it means `Drop` doesn't need to
|
||||
be implemented at all!
|
||||
|
||||
**There is no stable way to prevent this behaviour in Rust 1.0.**
|
||||
**There is no stable way to prevent this behavior in Rust 1.0.**
|
||||
|
||||
Note that taking `&mut self` means that even if you could suppress recursive
|
||||
Drop, Rust will prevent you from e.g. moving fields out of self. For most types,
|
||||
@ -53,7 +53,7 @@ impl<T> Drop for Box<T> {
|
||||
|
||||
and this works fine because when Rust goes to drop the `ptr` field it just sees
|
||||
a [Unique] that has no actual `Drop` implementation. Similarly nothing can
|
||||
use-after-free the `ptr` because when drop exits, it becomes inacessible.
|
||||
use-after-free the `ptr` because when drop exits, it becomes inaccessible.
|
||||
|
||||
However this wouldn't work:
|
||||
|
||||
@ -101,7 +101,7 @@ After we deallocate the `box`'s ptr in SuperBox's destructor, Rust will
|
||||
happily proceed to tell the box to Drop itself and everything will blow up with
|
||||
use-after-frees and double-frees.
|
||||
|
||||
Note that the recursive drop behaviour applies to all structs and enums
|
||||
Note that the recursive drop behavior applies to all structs and enums
|
||||
regardless of whether they implement Drop. Therefore something like
|
||||
|
||||
```rust
|
||||
|
@ -40,7 +40,7 @@ y = x; // y was init; Drop y, overwrite it, and make x uninit!
|
||||
// x goes out of scope; x was uninit; do nothing.
|
||||
```
|
||||
|
||||
Similarly, branched code where all branches have the same behaviour with respect
|
||||
Similarly, branched code where all branches have the same behavior with respect
|
||||
to initialization has static drop semantics:
|
||||
|
||||
```rust
|
||||
|
@ -6,7 +6,7 @@ interacted with the *outlives* relationship in an inclusive manner. That is,
|
||||
when we talked about `'a: 'b`, it was ok for `'a` to live *exactly* as long as
|
||||
`'b`. At first glance, this seems to be a meaningless distinction. Nothing ever
|
||||
gets dropped at the same time as another, right? This is why we used the
|
||||
following desugarring of `let` statements:
|
||||
following desugaring of `let` statements:
|
||||
|
||||
```rust,ignore
|
||||
let x;
|
||||
@ -115,13 +115,163 @@ section:
|
||||
**For a generic type to soundly implement drop, its generics arguments must
|
||||
strictly outlive it.**
|
||||
|
||||
This rule is sufficient but not necessary to satisfy the drop checker. That is,
|
||||
if your type obeys this rule then it's definitely sound to drop. However
|
||||
there are special cases where you can fail to satisfy this, but still
|
||||
successfully pass the borrow checker. These are the precise rules that are
|
||||
currently up in the air.
|
||||
Obeying this rule is (usually) necessary to satisfy the borrow
|
||||
checker; obeying it is sufficient but not necessary to be
|
||||
sound. That is, if your type obeys this rule then it's definitely
|
||||
sound to drop.
|
||||
|
||||
The reason that it is not always necessary to satisfy the above rule
|
||||
is that some Drop implementations will not access borrowed data even
|
||||
though their type gives them the capability for such access.
|
||||
|
||||
For example, this variant of the above `Inspector` example will never
|
||||
accessed borrowed data:
|
||||
|
||||
```rust,ignore
|
||||
struct Inspector<'a>(&'a u8, &'static str);
|
||||
|
||||
impl<'a> Drop for Inspector<'a> {
|
||||
fn drop(&mut self) {
|
||||
println!("Inspector(_, {}) knows when *not* to inspect.", self.1);
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let (inspector, days);
|
||||
days = Box::new(1);
|
||||
inspector = Inspector(&days, "gadget");
|
||||
// Let's say `days` happens to get dropped first.
|
||||
// Even when Inspector is dropped, its destructor will not access the
|
||||
// borrowed `days`.
|
||||
}
|
||||
```
|
||||
|
||||
Likewise, this variant will also never access borrowed data:
|
||||
|
||||
```rust,ignore
|
||||
use std::fmt;
|
||||
|
||||
struct Inspector<T: fmt::Display>(T, &'static str);
|
||||
|
||||
impl<T: fmt::Display> Drop for Inspector<T> {
|
||||
fn drop(&mut self) {
|
||||
println!("Inspector(_, {}) knows when *not* to inspect.", self.1);
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let (inspector, days): (Inspector<&u8>, Box<u8>);
|
||||
days = Box::new(1);
|
||||
inspector = Inspector(&days, "gadget");
|
||||
// Let's say `days` happens to get dropped first.
|
||||
// Even when Inspector is dropped, its destructor will not access the
|
||||
// borrowed `days`.
|
||||
}
|
||||
```
|
||||
|
||||
However, *both* of the above variants are rejected by the borrow
|
||||
checker during the analysis of `fn main`, saying that `days` does not
|
||||
live long enough.
|
||||
|
||||
The reason is that the borrow checking analysis of `main` does not
|
||||
know about the internals of each Inspector's Drop implementation. As
|
||||
far as the borrow checker knows while it is analyzing `main`, the body
|
||||
of an inspector's destructor might access that borrowed data.
|
||||
|
||||
Therefore, the drop checker forces all borrowed data in a value to
|
||||
strictly outlive that value.
|
||||
|
||||
# An Escape Hatch
|
||||
|
||||
The precise rules that govern drop checking may be less restrictive in
|
||||
the future.
|
||||
|
||||
The current analysis is deliberately conservative and trivial; it forces all
|
||||
borrowed data in a value to outlive that value, which is certainly sound.
|
||||
|
||||
Future versions of the language may make the analysis more precise, to
|
||||
reduce the number of cases where sound code is rejected as unsafe.
|
||||
This would help address cases such as the two Inspectors above that
|
||||
know not to inspect during destruction.
|
||||
|
||||
In the meantime, there is an unstable attribute that one can use to
|
||||
assert (unsafely) that a generic type's destructor is *guaranteed* to
|
||||
not access any expired data, even if its type gives it the capability
|
||||
to do so.
|
||||
|
||||
That attribute is called `unsafe_destructor_blind_to_params`.
|
||||
To deploy it on the Inspector example from above, we would write:
|
||||
|
||||
```rust,ignore
|
||||
struct Inspector<'a>(&'a u8, &'static str);
|
||||
|
||||
impl<'a> Drop for Inspector<'a> {
|
||||
#[unsafe_destructor_blind_to_params]
|
||||
fn drop(&mut self) {
|
||||
println!("Inspector(_, {}) knows when *not* to inspect.", self.1);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
This attribute has the word `unsafe` in it because the compiler is not
|
||||
checking the implicit assertion that no potentially expired data
|
||||
(e.g. `self.0` above) is accessed.
|
||||
|
||||
It is sometimes obvious that no such access can occur, like the case above.
|
||||
However, when dealing with a generic type parameter, such access can
|
||||
occur indirectly. Examples of such indirect access are:
|
||||
|
||||
* invoking a callback,
|
||||
* via a trait method call.
|
||||
|
||||
(Future changes to the language, such as impl specialization, may add
|
||||
other avenues for such indirect access.)
|
||||
|
||||
Here is an example of invoking a callback:
|
||||
|
||||
```rust,ignore
|
||||
struct Inspector<T>(T, &'static str, Box<for <'r> fn(&'r T) -> String>);
|
||||
|
||||
impl<T> Drop for Inspector<T> {
|
||||
fn drop(&mut self) {
|
||||
// The `self.2` call could access a borrow e.g. if `T` is `&'a _`.
|
||||
println!("Inspector({}, {}) unwittingly inspects expired data.",
|
||||
(self.2)(&self.0), self.1);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Here is an example of a trait method call:
|
||||
|
||||
```rust,ignore
|
||||
use std::fmt;
|
||||
|
||||
struct Inspector<T: fmt::Display>(T, &'static str);
|
||||
|
||||
impl<T: fmt::Display> Drop for Inspector<T> {
|
||||
fn drop(&mut self) {
|
||||
// There is a hidden call to `<T as Display>::fmt` below, which
|
||||
// could access a borrow e.g. if `T` is `&'a _`
|
||||
println!("Inspector({}, {}) unwittingly inspects expired data.",
|
||||
self.0, self.1);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
And of course, all of these accesses could be further hidden within
|
||||
some other method invoked by the destructor, rather than being written
|
||||
directly within it.
|
||||
|
||||
In all of the above cases where the `&'a u8` is accessed in the
|
||||
destructor, adding the `#[unsafe_destructor_blind_to_params]`
|
||||
attribute makes the type vulnerable to misuse that the borrower
|
||||
checker will not catch, inviting havoc. It is better to avoid adding
|
||||
the attribute.
|
||||
|
||||
# Is that all about drop checker?
|
||||
|
||||
It turns out that when writing unsafe code, we generally don't need to
|
||||
worry at all about doing the right thing for the drop checker. However there
|
||||
is one special case that you need to worry about, which we will look at in
|
||||
the next section.
|
||||
|
||||
|
@ -20,7 +20,7 @@ information that "completes" them (more on this below).
|
||||
There are two major DSTs exposed by the language: trait objects, and slices.
|
||||
|
||||
A trait object represents some type that implements the traits it specifies.
|
||||
The exact original type is *erased* in favour of runtime reflection
|
||||
The exact original type is *erased* in favor of runtime reflection
|
||||
with a vtable containing all the information necessary to use the type.
|
||||
This is the information that completes a trait object: a pointer to its vtable.
|
||||
|
||||
@ -128,7 +128,7 @@ But neither of these tricks work today, so all Void types get you is
|
||||
the ability to be confident that certain situations are statically impossible.
|
||||
|
||||
One final subtle detail about empty types is that raw pointers to them are
|
||||
actually valid to construct, but dereferencing them is Undefined Behaviour
|
||||
actually valid to construct, but dereferencing them is Undefined Behavior
|
||||
because that doesn't actually make sense. That is, you could model C's `void *`
|
||||
type with `*const Void`, but this doesn't necessarily gain anything over using
|
||||
e.g. `*const ()`, which *is* safe to randomly dereference.
|
||||
|
@ -90,16 +90,16 @@ let mut vec = vec![Box::new(0); 4];
|
||||
println!("{}", vec[0]);
|
||||
```
|
||||
|
||||
This is pretty clearly Not Good. Unfortunately, we're kind've stuck between a
|
||||
This is pretty clearly Not Good. Unfortunately, we're kind of stuck between a
|
||||
rock and a hard place: maintaining consistent state at every step has an
|
||||
enormous cost (and would negate any benefits of the API). Failing to maintain
|
||||
consistent state gives us Undefined Behaviour in safe code (making the API
|
||||
consistent state gives us Undefined Behavior in safe code (making the API
|
||||
unsound).
|
||||
|
||||
So what can we do? Well, we can pick a trivially consistent state: set the Vec's
|
||||
len to be 0 when we start the iteration, and fix it up if necessary in the
|
||||
destructor. That way, if everything executes like normal we get the desired
|
||||
behaviour with minimal overhead. But if someone has the *audacity* to
|
||||
behavior with minimal overhead. But if someone has the *audacity* to
|
||||
mem::forget us in the middle of the iteration, all that does is *leak even more*
|
||||
(and possibly leave the Vec in an unexpected but otherwise consistent state).
|
||||
Since we've accepted that mem::forget is safe, this is definitely safe. We call
|
||||
@ -135,7 +135,7 @@ impl<T> Rc<T> {
|
||||
fn new(data: T) -> Self {
|
||||
unsafe {
|
||||
// Wouldn't it be nice if heap::allocate worked like this?
|
||||
let ptr = heap::allocate<RcBox<T>>();
|
||||
let ptr = heap::allocate::<RcBox<T>>();
|
||||
ptr::write(ptr, RcBox {
|
||||
data: data,
|
||||
ref_count: 1,
|
||||
@ -248,4 +248,4 @@ let mut data = Box::new(0);
|
||||
```
|
||||
|
||||
Dang. Here the destructor running was pretty fundamental to the API, and it had
|
||||
to be scrapped in favour of a completely different design.
|
||||
to be scrapped in favor of a completely different design.
|
||||
|
@ -78,4 +78,4 @@ TODO: other common problems? SEME regions stuff, mostly?
|
||||
|
||||
|
||||
|
||||
[ex2]: lifetimes.html#example-2:-aliasing-a-mutable-reference
|
||||
[ex2]: lifetimes.html#example-aliasing-a-mutable-reference
|
||||
|
@ -195,7 +195,7 @@ println!("{}", x);
|
||||
|
||||
The problem here is is bit more subtle and interesting. We want Rust to
|
||||
reject this program for the following reason: We have a live shared reference `x`
|
||||
to a descendent of `data` when we try to take a mutable reference to `data`
|
||||
to a descendant of `data` when we try to take a mutable reference to `data`
|
||||
to `push`. This would create an aliased mutable reference, which would
|
||||
violate the *second* rule of references.
|
||||
|
||||
|
@ -26,7 +26,7 @@ do some really crazy unsafe things.
|
||||
|
||||
Safe Rust is the *true* Rust programming language. If all you do is write Safe
|
||||
Rust, you will never have to worry about type-safety or memory-safety. You will
|
||||
never endure a null or dangling pointer, or any of that Undefined Behaviour
|
||||
never endure a null or dangling pointer, or any of that Undefined Behavior
|
||||
nonsense.
|
||||
|
||||
*That's totally awesome.*
|
||||
@ -52,11 +52,11 @@ The only things that are different in Unsafe Rust are that you can:
|
||||
* Mutate statics
|
||||
|
||||
That's it. The reason these operations are relegated to Unsafe is that misusing
|
||||
any of these things will cause the ever dreaded Undefined Behaviour. Invoking
|
||||
Undefined Behaviour gives the compiler full rights to do arbitrarily bad things
|
||||
to your program. You definitely *should not* invoke Undefined Behaviour.
|
||||
any of these things will cause the ever dreaded Undefined Behavior. Invoking
|
||||
Undefined Behavior gives the compiler full rights to do arbitrarily bad things
|
||||
to your program. You definitely *should not* invoke Undefined Behavior.
|
||||
|
||||
Unlike C, Undefined Behaviour is pretty limited in scope in Rust. All the core
|
||||
Unlike C, Undefined Behavior is pretty limited in scope in Rust. All the core
|
||||
language cares about is preventing the following things:
|
||||
|
||||
* Dereferencing null or dangling pointers
|
||||
@ -71,9 +71,9 @@ language cares about is preventing the following things:
|
||||
* Unwinding into another language
|
||||
* Causing a [data race][race]
|
||||
|
||||
That's it. That's all the causes of Undefined Behaviour baked into Rust. Of
|
||||
That's it. That's all the causes of Undefined Behavior baked into Rust. Of
|
||||
course, unsafe functions and traits are free to declare arbitrary other
|
||||
constraints that a program must maintain to avoid Undefined Behaviour. However,
|
||||
constraints that a program must maintain to avoid Undefined Behavior. However,
|
||||
generally violations of these constraints will just transitively lead to one of
|
||||
the above problems. Some additional constraints may also derive from compiler
|
||||
intrinsics that make special assumptions about how code can be optimized.
|
||||
|
@ -19,8 +19,8 @@ kept in mind. Due to its dual purpose as "for FFI" and "for layout control",
|
||||
`repr(C)` can be applied to types that will be nonsensical or problematic if
|
||||
passed through the FFI boundary.
|
||||
|
||||
* ZSTs are still zero-sized, even though this is not a standard behaviour in
|
||||
C, and is explicitly contrary to the behaviour of an empty type in C++, which
|
||||
* ZSTs are still zero-sized, even though this is not a standard behavior in
|
||||
C, and is explicitly contrary to the behavior of an empty type in C++, which
|
||||
still consumes a byte of space.
|
||||
|
||||
* DSTs, tuples, and tagged unions are not a concept in C and as such are never
|
||||
@ -65,7 +65,7 @@ compiler might be able to paper over alignment issues with shifts and masks.
|
||||
However if you take a reference to a packed field, it's unlikely that the
|
||||
compiler will be able to emit code to avoid an unaligned load.
|
||||
|
||||
**[As of Rust 1.0 this can cause undefined behaviour.][ub loads]**
|
||||
**[As of Rust 1.0 this can cause undefined behavior.][ub loads]**
|
||||
|
||||
`repr(packed)` is not to be used lightly. Unless you have extreme requirements,
|
||||
this should not be used.
|
||||
|
@ -64,4 +64,3 @@ does in fact live as long as we needed. However it was *changed* while we had
|
||||
a reference into it. This is why Rust requires any references to freeze the
|
||||
referent and its owners.
|
||||
|
||||
|
||||
|
@ -6,7 +6,7 @@ Safe Rust guarantees an absence of data races, which are defined as:
|
||||
* one of them is a write
|
||||
* one of them is unsynchronized
|
||||
|
||||
A data race has Undefined Behaviour, and is therefore impossible to perform
|
||||
A data race has Undefined Behavior, and is therefore impossible to perform
|
||||
in Safe Rust. Data races are *mostly* prevented through rust's ownership system:
|
||||
it's impossible to alias a mutable reference, so it's impossible to perform a
|
||||
data race. Interior mutability makes this more complicated, which is largely why
|
||||
@ -53,7 +53,7 @@ thread::spawn(move || {
|
||||
// bounds checked, and there's no chance of the value getting changed
|
||||
// in the middle. However our program may panic if the thread we spawned
|
||||
// managed to increment before this ran. A race condition because correct
|
||||
// program execution (panicing is rarely correct) depends on order of
|
||||
// program execution (panicking is rarely correct) depends on order of
|
||||
// thread execution.
|
||||
println!("{}", data[idx.load(Ordering::SeqCst)]);
|
||||
```
|
||||
|
@ -6,7 +6,7 @@ value of alignment `n` must only be stored at an address that is a multiple of
|
||||
`n`. So alignment 2 means you must be stored at an even address, and 1 means
|
||||
that you can be stored anywhere. Alignment is at least 1, and always a power of
|
||||
2. Most primitives are generally aligned to their size, although this is
|
||||
platform-specific behaviour. In particular, on x86 `u64` and `f64` may be only
|
||||
platform-specific behavior. In particular, on x86 `u64` and `f64` may be only
|
||||
aligned to 32 bits.
|
||||
|
||||
A type's size must always be a multiple of its alignment. This ensures that an
|
||||
@ -151,4 +151,4 @@ use fairly elaborate algorithms to cache bits throughout nested types with
|
||||
special constrained representations. As such it is *especially* desirable that
|
||||
we leave enum layout unspecified today.
|
||||
|
||||
[dst]: exotic-sizes.html#dynamically-sized-types-(dsts)
|
||||
[dst]: exotic-sizes.html#dynamically-sized-types-dsts
|
||||
|
@ -41,8 +41,8 @@ Some examples of unsafe functions:
|
||||
|
||||
* `slice::get_unchecked` will perform unchecked indexing, allowing memory
|
||||
safety to be freely violated.
|
||||
* `ptr::offset` is an intrinsic that invokes Undefined Behaviour if it is
|
||||
not "in bounds" as defined by LLVM.
|
||||
* every raw pointer to sized type has intrinsic `offset` method that invokes
|
||||
Undefined Behavior if it is not "in bounds" as defined by LLVM.
|
||||
* `mem::transmute` reinterprets some value as having the given type,
|
||||
bypassing type safety in arbitrary ways. (see [conversions] for details)
|
||||
* All FFI functions are `unsafe` because they can do arbitrary things.
|
||||
@ -59,9 +59,9 @@ As of Rust 1.0 there are exactly two unsafe traits:
|
||||
The need for unsafe traits boils down to the fundamental property of safe code:
|
||||
|
||||
**No matter how completely awful Safe code is, it can't cause Undefined
|
||||
Behaviour.**
|
||||
Behavior.**
|
||||
|
||||
This means that Unsafe Rust, **the royal vanguard of Undefined Behaviour**, has to be
|
||||
This means that Unsafe Rust, **the royal vanguard of Undefined Behavior**, has to be
|
||||
*super paranoid* about generic safe code. To be clear, Unsafe Rust is totally free to trust
|
||||
specific safe code. Anything else would degenerate into infinite spirals of
|
||||
paranoid despair. In particular it's generally regarded as ok to trust the standard library
|
||||
|
@ -15,7 +15,7 @@ implement, and other unsafe code can assume that they are correctly
|
||||
implemented. Since they're *marker traits* (they have no associated items like
|
||||
methods), correctly implemented simply means that they have the intrinsic
|
||||
properties an implementor should have. Incorrectly implementing Send or Sync can
|
||||
cause Undefined Behaviour.
|
||||
cause Undefined Behavior.
|
||||
|
||||
Send and Sync are also automatically derived traits. This means that, unlike
|
||||
every other trait, if a type is composed entirely of Send or Sync types, then it
|
||||
|
@ -8,7 +8,7 @@ horribly unsafe thing you can do in Rust. The railguards here are dental floss.
|
||||
|
||||
`mem::transmute<T, U>` takes a value of type `T` and reinterprets it to have
|
||||
type `U`. The only restriction is that the `T` and `U` are verified to have the
|
||||
same size. The ways to cause Undefined Behaviour with this are mind boggling.
|
||||
same size. The ways to cause Undefined Behavior with this are mind boggling.
|
||||
|
||||
* First and foremost, creating an instance of *any* type with an invalid state
|
||||
is going to cause arbitrary chaos that can't really be predicted.
|
||||
@ -26,7 +26,7 @@ same size. The ways to cause Undefined Behaviour with this are mind boggling.
|
||||
`mem::transmute_copy<T, U>` somehow manages to be *even more* wildly unsafe than
|
||||
this. It copies `size_of<U>` bytes out of an `&T` and interprets them as a `U`.
|
||||
The size check that `mem::transmute` has is gone (as it may be valid to copy
|
||||
out a prefix), though it is Undefined Behaviour for `U` to be larger than `T`.
|
||||
out a prefix), though it is Undefined Behavior for `U` to be larger than `T`.
|
||||
|
||||
Also of course you can get most of the functionality of these functions using
|
||||
pointer casts.
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
Unsafe code can often end up producing references or lifetimes out of thin air.
|
||||
Such lifetimes come into the world as *unbounded*. The most common source of this
|
||||
is derefencing a raw pointer, which produces a reference with an unbounded lifetime.
|
||||
is dereferencing a raw pointer, which produces a reference with an unbounded lifetime.
|
||||
Such a lifetime becomes as big as context demands. This is in fact more powerful
|
||||
than simply becoming `'static`, because for instance `&'static &'a T`
|
||||
will fail to typecheck, but the unbound lifetime will perfectly mold into
|
||||
@ -10,7 +10,7 @@ will fail to typecheck, but the unbound lifetime will perfectly mold into
|
||||
lifetime can be regarded as `'static`.
|
||||
|
||||
Almost no reference is `'static`, so this is probably wrong. `transmute` and
|
||||
`transmute_copy` are the two other primary offenders. One should endeavour to
|
||||
`transmute_copy` are the two other primary offenders. One should endeavor to
|
||||
bound an unbounded lifetime as quick as possible, especially across function
|
||||
boundaries.
|
||||
|
||||
|
@ -38,7 +38,7 @@ dropping the old value: `write`, `copy`, and `copy_nonoverlapping`.
|
||||
(this is equivalent to memcpy -- note that the argument order is reversed!)
|
||||
|
||||
It should go without saying that these functions, if misused, will cause serious
|
||||
havoc or just straight up Undefined Behaviour. The only things that these
|
||||
havoc or just straight up Undefined Behavior. The only things that these
|
||||
functions *themselves* require is that the locations you want to read and write
|
||||
are allocated. However the ways writing arbitrary bits to arbitrary
|
||||
locations of memory can break things are basically uncountable!
|
||||
|
@ -4,7 +4,7 @@ All runtime-allocated memory in a Rust program begins its life as
|
||||
*uninitialized*. In this state the value of the memory is an indeterminate pile
|
||||
of bits that may or may not even reflect a valid state for the type that is
|
||||
supposed to inhabit that location of memory. Attempting to interpret this memory
|
||||
as a value of *any* type will cause Undefined Behaviour. Do Not Do This.
|
||||
as a value of *any* type will cause Undefined Behavior. Do Not Do This.
|
||||
|
||||
Rust provides mechanisms to work with uninitialized memory in checked (safe) and
|
||||
unchecked (unsafe) ways.
|
@ -42,7 +42,7 @@ should only panic for programming errors or *extreme* problems.
|
||||
|
||||
Rust's unwinding strategy is not specified to be fundamentally compatible
|
||||
with any other language's unwinding. As such, unwinding into Rust from another
|
||||
language, or unwinding into another language from Rust is Undefined Behaviour.
|
||||
language, or unwinding into another language from Rust is Undefined Behavior.
|
||||
You must *absolutely* catch any panics at the FFI boundary! What you do at that
|
||||
point is up to you, but *something* must be done. If you fail to do this,
|
||||
at best, your application will crash and burn. At worst, your application *won't*
|
||||
|
@ -93,7 +93,7 @@ pub struct Vec<T> {
|
||||
If you don't care about the null-pointer optimization, then you can use the
|
||||
stable code. However we will be designing the rest of the code around enabling
|
||||
the optimization. In particular, `Unique::new` is unsafe to call, because
|
||||
putting `null` inside of it is Undefined Behaviour. Our stable Unique doesn't
|
||||
putting `null` inside of it is Undefined Behavior. Our stable Unique doesn't
|
||||
need `new` to be unsafe because it doesn't make any interesting guarantees about
|
||||
its contents.
|
||||
|
||||
|
@ -34,7 +34,7 @@ Easy! How about `pop`? Although this time the index we want to access is
|
||||
initialized, Rust won't just let us dereference the location of memory to move
|
||||
the value out, because that would leave the memory uninitialized! For this we
|
||||
need `ptr::read`, which just copies out the bits from the target address and
|
||||
intrprets it as a value of type T. This will leave the memory at this address
|
||||
interprets it as a value of type T. This will leave the memory at this address
|
||||
logically uninitialized, even though there is in fact a perfectly good instance
|
||||
of T there.
|
||||
|
||||
|
@ -1,11 +1,11 @@
|
||||
% Handling Zero-Sized Types
|
||||
|
||||
It's time. We're going to fight the spectre that is zero-sized types. Safe Rust
|
||||
It's time. We're going to fight the specter that is zero-sized types. Safe Rust
|
||||
*never* needs to care about this, but Vec is very intensive on raw pointers and
|
||||
raw allocations, which are exactly the two things that care about
|
||||
zero-sized types. We need to be careful of two things:
|
||||
|
||||
* The raw allocator API has undefined behaviour if you pass in 0 for an
|
||||
* The raw allocator API has undefined behavior if you pass in 0 for an
|
||||
allocation size.
|
||||
* raw pointer offsets are no-ops for zero-sized types, which will break our
|
||||
C-style pointer iterator.
|
||||
|
@ -76,8 +76,16 @@ An identifier is any nonempty Unicode[^non_ascii_idents] string of the following
|
||||
[^non_ascii_idents]: Non-ASCII characters in identifiers are currently feature
|
||||
gated. This is expected to improve soon.
|
||||
|
||||
- The first character has property `XID_start`
|
||||
- The remaining characters have property `XID_continue`
|
||||
Either
|
||||
|
||||
* The first character has property `XID_start`
|
||||
* The remaining characters have property `XID_continue`
|
||||
|
||||
Or
|
||||
|
||||
* The first character is `_`
|
||||
* The identifier is more than one character, `_` alone is not an identifier
|
||||
* The remaining characters have property `XID_continue`
|
||||
|
||||
that does _not_ occur in the set of [keywords][keywords].
|
||||
|
||||
@ -410,11 +418,14 @@ The two values of the boolean type are written `true` and `false`.
|
||||
|
||||
### Symbols
|
||||
|
||||
Symbols are a general class of printable [token](#tokens) that play structural
|
||||
roles in a variety of grammar productions. They are catalogued here for
|
||||
completeness as the set of remaining miscellaneous printable tokens that do not
|
||||
Symbols are a general class of printable [tokens](#tokens) that play structural
|
||||
roles in a variety of grammar productions. They are a
|
||||
set of remaining miscellaneous printable tokens that do not
|
||||
otherwise appear as [unary operators](#unary-operator-expressions), [binary
|
||||
operators](#binary-operator-expressions), or [keywords][keywords].
|
||||
They are catalogued in [the Symbols section][symbols] of the Grammar document.
|
||||
|
||||
[symbols]: grammar.html#symbols
|
||||
|
||||
|
||||
## Paths
|
||||
@ -586,8 +597,8 @@ Rust syntax is restricted in two ways:
|
||||
# Crates and source files
|
||||
|
||||
Although Rust, like any other language, can be implemented by an interpreter as
|
||||
well as a compiler, the only existing implementation is a compiler —
|
||||
from now on referred to as *the* Rust compiler — and the language has
|
||||
well as a compiler, the only existing implementation is a compiler,
|
||||
and the language has
|
||||
always been designed to be compiled. For these reasons, this section assumes a
|
||||
compiler.
|
||||
|
||||
@ -674,7 +685,7 @@ There are several kinds of item:
|
||||
* [modules](#modules)
|
||||
* [functions](#functions)
|
||||
* [type definitions](grammar.html#type-definitions)
|
||||
* [structures](#structures)
|
||||
* [structs](#structs)
|
||||
* [enumerations](#enumerations)
|
||||
* [constant items](#constant-items)
|
||||
* [static items](#static-items)
|
||||
@ -881,7 +892,7 @@ mod foo {
|
||||
}
|
||||
|
||||
use foo::example::iter; // good: foo is at crate root
|
||||
// use example::iter; // bad: core is not at the crate root
|
||||
// use example::iter; // bad: example is not at the crate root
|
||||
use self::baz::foobaz; // good: self refers to module 'foo'
|
||||
use foo::bar::foobar; // good: foo is at crate root
|
||||
|
||||
@ -900,9 +911,10 @@ fn main() {}
|
||||
|
||||
### Functions
|
||||
|
||||
A _function item_ defines a sequence of [statements](#statements) and an
|
||||
optional final [expression](#expressions), along with a name and a set of
|
||||
parameters. Functions are declared with the keyword `fn`. Functions declare a
|
||||
A _function item_ defines a sequence of [statements](#statements) and a
|
||||
final [expression](#expressions), along with a name and a set of
|
||||
parameters. Other than a name, all these are optional.
|
||||
Functions are declared with the keyword `fn`. Functions may declare a
|
||||
set of *input* [*variables*](#variables) as parameters, through which the caller
|
||||
passes arguments into the function, and the *output* [*type*](#types)
|
||||
of the value the function will return to its caller on completion.
|
||||
@ -921,7 +933,7 @@ An example of a function:
|
||||
|
||||
```
|
||||
fn add(x: i32, y: i32) -> i32 {
|
||||
return x + y;
|
||||
x + y
|
||||
}
|
||||
```
|
||||
|
||||
@ -975,99 +987,6 @@ The type parameters can also be explicitly supplied in a trailing
|
||||
there is not sufficient context to determine the type parameters. For example,
|
||||
`mem::size_of::<u32>() == 4`.
|
||||
|
||||
#### Unsafety
|
||||
|
||||
Unsafe operations are those that potentially violate the memory-safety
|
||||
guarantees of Rust's static semantics.
|
||||
|
||||
The following language level features cannot be used in the safe subset of
|
||||
Rust:
|
||||
|
||||
- Dereferencing a [raw pointer](#pointer-types).
|
||||
- Reading or writing a [mutable static variable](#mutable-statics).
|
||||
- Calling an unsafe function (including an intrinsic or foreign function).
|
||||
|
||||
##### Unsafe functions
|
||||
|
||||
Unsafe functions are functions that are not safe in all contexts and/or for all
|
||||
possible inputs. Such a function must be prefixed with the keyword `unsafe` and
|
||||
can only be called from an `unsafe` block or another `unsafe` function.
|
||||
|
||||
##### Unsafe blocks
|
||||
|
||||
A block of code can be prefixed with the `unsafe` keyword, to permit calling
|
||||
`unsafe` functions or dereferencing raw pointers within a safe function.
|
||||
|
||||
When a programmer has sufficient conviction that a sequence of potentially
|
||||
unsafe operations is actually safe, they can encapsulate that sequence (taken
|
||||
as a whole) within an `unsafe` block. The compiler will consider uses of such
|
||||
code safe, in the surrounding context.
|
||||
|
||||
Unsafe blocks are used to wrap foreign libraries, make direct use of hardware
|
||||
or implement features not directly present in the language. For example, Rust
|
||||
provides the language features necessary to implement memory-safe concurrency
|
||||
in the language but the implementation of threads and message passing is in the
|
||||
standard library.
|
||||
|
||||
Rust's type system is a conservative approximation of the dynamic safety
|
||||
requirements, so in some cases there is a performance cost to using safe code.
|
||||
For example, a doubly-linked list is not a tree structure and can only be
|
||||
represented with reference-counted pointers in safe code. By using `unsafe`
|
||||
blocks to represent the reverse links as raw pointers, it can be implemented
|
||||
with only boxes.
|
||||
|
||||
##### Behavior considered undefined
|
||||
|
||||
The following is a list of behavior which is forbidden in all Rust code,
|
||||
including within `unsafe` blocks and `unsafe` functions. Type checking provides
|
||||
the guarantee that these issues are never caused by safe code.
|
||||
|
||||
* Data races
|
||||
* Dereferencing a null/dangling raw pointer
|
||||
* Reads of [undef](http://llvm.org/docs/LangRef.html#undefined-values)
|
||||
(uninitialized) memory
|
||||
* Breaking the [pointer aliasing
|
||||
rules](http://llvm.org/docs/LangRef.html#pointer-aliasing-rules)
|
||||
with raw pointers (a subset of the rules used by C)
|
||||
* `&mut` and `&` follow LLVM’s scoped [noalias] model, except if the `&T`
|
||||
contains an `UnsafeCell<U>`. Unsafe code must not violate these aliasing
|
||||
guarantees.
|
||||
* Mutating non-mutable data (that is, data reached through a shared reference or
|
||||
data owned by a `let` binding), unless that data is contained within an `UnsafeCell<U>`.
|
||||
* Invoking undefined behavior via compiler intrinsics:
|
||||
* Indexing outside of the bounds of an object with `std::ptr::offset`
|
||||
(`offset` intrinsic), with
|
||||
the exception of one byte past the end which is permitted.
|
||||
* Using `std::ptr::copy_nonoverlapping_memory` (`memcpy32`/`memcpy64`
|
||||
intrinsics) on overlapping buffers
|
||||
* Invalid values in primitive types, even in private fields/locals:
|
||||
* Dangling/null references or boxes
|
||||
* A value other than `false` (0) or `true` (1) in a `bool`
|
||||
* A discriminant in an `enum` not included in the type definition
|
||||
* A value in a `char` which is a surrogate or above `char::MAX`
|
||||
* Non-UTF-8 byte sequences in a `str`
|
||||
* Unwinding into Rust from foreign code or unwinding from Rust into foreign
|
||||
code. Rust's failure system is not compatible with exception handling in
|
||||
other languages. Unwinding must be caught and handled at FFI boundaries.
|
||||
|
||||
[noalias]: http://llvm.org/docs/LangRef.html#noalias
|
||||
|
||||
##### Behavior not considered unsafe
|
||||
|
||||
This is a list of behavior not considered *unsafe* in Rust terms, but that may
|
||||
be undesired.
|
||||
|
||||
* Deadlocks
|
||||
* Leaks of memory and other resources
|
||||
* Exiting without calling destructors
|
||||
* Integer overflow
|
||||
- Overflow is considered "unexpected" behavior and is always user-error,
|
||||
unless the `wrapping` primitives are used. In non-optimized builds, the compiler
|
||||
will insert debug checks that panic on overflow, but in optimized builds overflow
|
||||
instead results in wrapped values. See [RFC 560] for the rationale and more details.
|
||||
|
||||
[RFC 560]: https://github.com/rust-lang/rfcs/blob/master/text/0560-integer-overflow.md
|
||||
|
||||
#### Diverging functions
|
||||
|
||||
A special kind of function can be declared with a `!` character where the
|
||||
@ -1155,9 +1074,9 @@ type Point = (u8, u8);
|
||||
let p: Point = (41, 68);
|
||||
```
|
||||
|
||||
### Structures
|
||||
### Structs
|
||||
|
||||
A _structure_ is a nominal [structure type](#structure-types) defined with the
|
||||
A _struct_ is a nominal [struct type](#struct-types) defined with the
|
||||
keyword `struct`.
|
||||
|
||||
An example of a `struct` item and its use:
|
||||
@ -1168,7 +1087,7 @@ let p = Point {x: 10, y: 11};
|
||||
let px: i32 = p.x;
|
||||
```
|
||||
|
||||
A _tuple structure_ is a nominal [tuple type](#tuple-types), also defined with
|
||||
A _tuple struct_ is a nominal [tuple type](#tuple-types), also defined with
|
||||
the keyword `struct`. For example:
|
||||
|
||||
```
|
||||
@ -1177,15 +1096,26 @@ let p = Point(10, 11);
|
||||
let px: i32 = match p { Point(x, _) => x };
|
||||
```
|
||||
|
||||
A _unit-like struct_ is a structure without any fields, defined by leaving off
|
||||
the list of fields entirely. Such types will have a single value. For example:
|
||||
A _unit-like struct_ is a struct without any fields, defined by leaving off
|
||||
the list of fields entirely. Such a struct implicitly defines a constant of
|
||||
its type with the same name. For example:
|
||||
|
||||
```
|
||||
# #![feature(braced_empty_structs)]
|
||||
struct Cookie;
|
||||
let c = [Cookie, Cookie, Cookie, Cookie];
|
||||
let c = [Cookie, Cookie {}, Cookie, Cookie {}];
|
||||
```
|
||||
|
||||
The precise memory layout of a structure is not specified. One can specify a
|
||||
is equivalent to
|
||||
|
||||
```
|
||||
# #![feature(braced_empty_structs)]
|
||||
struct Cookie {}
|
||||
const Cookie: Cookie = Cookie {};
|
||||
let c = [Cookie, Cookie {}, Cookie, Cookie {}];
|
||||
```
|
||||
|
||||
The precise memory layout of a struct is not specified. One can specify a
|
||||
particular layout using the [`repr` attribute](#ffi-attributes).
|
||||
|
||||
### Enumerations
|
||||
@ -1508,11 +1438,11 @@ struct Foo;
|
||||
|
||||
trait Shape { fn area(&self) -> f64; }
|
||||
trait Circle : Shape { fn radius(&self) -> f64; }
|
||||
# impl Shape for Foo {
|
||||
# fn area(&self) -> f64 {
|
||||
# 0.0
|
||||
# }
|
||||
# }
|
||||
impl Shape for Foo {
|
||||
fn area(&self) -> f64 {
|
||||
0.0
|
||||
}
|
||||
}
|
||||
impl Circle for Foo {
|
||||
fn radius(&self) -> f64 {
|
||||
println!("calling area: {}", self.area());
|
||||
@ -1590,11 +1520,11 @@ impl Shape for Circle {
|
||||
```
|
||||
|
||||
It is possible to define an implementation without referring to a trait. The
|
||||
methods in such an implementation can only be used as direct calls on the
|
||||
values of the type that the implementation targets. In such an implementation,
|
||||
the trait type and `for` after `impl` are omitted. Such implementations are
|
||||
limited to nominal types (enums, structs), and the implementation must appear
|
||||
in the same crate as the `self` type:
|
||||
methods in such an implementation can only be used as direct calls on the values
|
||||
of the type that the implementation targets. In such an implementation, the
|
||||
trait type and `for` after `impl` are omitted. Such implementations are limited
|
||||
to nominal types (enums, structs, trait objects), and the implementation must
|
||||
appear in the same crate as the `self` type:
|
||||
|
||||
```
|
||||
struct Point {x: i32, y: i32}
|
||||
@ -1977,7 +1907,7 @@ On `struct`s:
|
||||
list of names `#[macro_use(foo, bar)]` restricts the import to just those
|
||||
macros named. The `extern crate` must appear at the crate root, not inside
|
||||
`mod`, which ensures proper function of the [`$crate` macro
|
||||
variable](book/macros.html#the-variable-$crate).
|
||||
variable](book/macros.html#the-variable-crate).
|
||||
|
||||
- `macro_reexport` on an `extern crate` — re-export the named macros.
|
||||
|
||||
@ -1987,7 +1917,7 @@ On `struct`s:
|
||||
link it into the output.
|
||||
|
||||
See the [macros section of the
|
||||
book](book/macros.html#scoping-and-macro-import/export) for more information on
|
||||
book](book/macros.html#scoping-and-macro-importexport) for more information on
|
||||
macro scope.
|
||||
|
||||
|
||||
@ -2002,6 +1932,20 @@ macro scope.
|
||||
- `simd` - on certain tuple structs, derive the arithmetic operators, which
|
||||
lower to the target's SIMD instructions, if any; the `simd` feature gate
|
||||
is necessary to use this attribute.
|
||||
- `unsafe_destructor_blind_to_params` - on `Drop::drop` method, asserts that the
|
||||
destructor code (and all potential specializations of that code) will
|
||||
never attempt to read from nor write to any references with lifetimes
|
||||
that come in via generic parameters. This is a constraint we cannot
|
||||
currently express via the type system, and therefore we rely on the
|
||||
programmer to assert that it holds. Adding this to a Drop impl causes
|
||||
the associated destructor to be considered "uninteresting" by the
|
||||
Drop-Check rule, and thus it can help sidestep data ordering
|
||||
constraints that would otherwise be introduced by the Drop-Check
|
||||
rule. Such sidestepping of the constraints, if done incorrectly, can
|
||||
lead to undefined behavior (in the form of reading or writing to data
|
||||
outside of its dynamic extent), and thus this attribute has the word
|
||||
"unsafe" in its name. To use this, the
|
||||
`unsafe_destructor_blind_to_params` feature gate must be enabled.
|
||||
- `unsafe_no_drop_flag` - on structs, remove the flag that prevents
|
||||
destructors from being run twice. Destructors might be run multiple times on
|
||||
the same object with this attribute. To use this, the `unsafe_no_drop_flag` feature
|
||||
@ -2081,6 +2025,8 @@ The following configurations must be defined by the implementation:
|
||||
* `target_pointer_width = "..."` - Target pointer width in bits. This is set
|
||||
to `"32"` for targets with 32-bit pointers, and likewise set to `"64"` for
|
||||
64-bit pointers.
|
||||
* `target_vendor = "..."` - Vendor of the target, for example `apple`, `pc`, or
|
||||
simply `"unknown"`.
|
||||
* `test` - Enabled when compiling the test harness (using the `--test` flag).
|
||||
* `unix` - See `target_family`.
|
||||
* `windows` - See `target_family`.
|
||||
@ -2257,7 +2203,7 @@ The currently implemented features of the reference compiler are:
|
||||
* `advanced_slice_patterns` - See the [match expressions](#match-expressions)
|
||||
section for discussion; the exact semantics of
|
||||
slice patterns are subject to change, so some types
|
||||
are still unstable.
|
||||
are still unstable.
|
||||
|
||||
* `slice_patterns` - OK, actually, slice patterns are just scary and
|
||||
completely unstable.
|
||||
@ -2278,6 +2224,9 @@ The currently implemented features of the reference compiler are:
|
||||
* `box_syntax` - Allows use of `box` expressions, the exact semantics of which
|
||||
is subject to change.
|
||||
|
||||
* `cfg_target_vendor` - Allows conditional compilation using the `target_vendor`
|
||||
matcher which is subject to change.
|
||||
|
||||
* `concat_idents` - Allows use of the `concat_idents` macro, which is in many
|
||||
ways insufficient for concatenating identifiers, and may be
|
||||
removed entirely for something more wholesome.
|
||||
@ -2411,6 +2360,7 @@ The currently implemented features of the reference compiler are:
|
||||
terms of encapsulation).
|
||||
* - `default_type_parameter_fallback` - Allows type parameter defaults to
|
||||
influence type inference.
|
||||
* - `braced_empty_structs` - Allows use of empty structs and enum variants with braces.
|
||||
|
||||
If a feature is promoted to a language feature, then all existing programs will
|
||||
start to receive compilation warnings about `#![feature]` directives which enabled
|
||||
@ -2454,7 +2404,7 @@ items.
|
||||
|
||||
An _item declaration statement_ has a syntactic form identical to an
|
||||
[item](#items) declaration within a module. Declaring an item — a
|
||||
function, enumeration, structure, type, static, trait, implementation or module
|
||||
function, enumeration, struct, type, static, trait, implementation or module
|
||||
— locally within a statement block is simply a way of restricting its
|
||||
scope to a narrow region containing all of its uses; it is otherwise identical
|
||||
in meaning to declaring the item outside the statement block.
|
||||
@ -2560,7 +2510,7 @@ Here are some examples:
|
||||
#### Moved and copied types
|
||||
|
||||
When a [local variable](#variables) is used as an
|
||||
[rvalue](#lvalues,-rvalues-and-temporaries), the variable will be copied
|
||||
[rvalue](#lvalues-rvalues-and-temporaries), the variable will be copied
|
||||
if its type implements `Copy`. All others are moved.
|
||||
|
||||
### Literal expressions
|
||||
@ -2579,7 +2529,7 @@ value, or the unit value.
|
||||
### Path expressions
|
||||
|
||||
A [path](#paths) used as an expression context denotes either a local variable
|
||||
or an item. Path expressions are [lvalues](#lvalues,-rvalues-and-temporaries).
|
||||
or an item. Path expressions are [lvalues](#lvalues-rvalues-and-temporaries).
|
||||
|
||||
### Tuple expressions
|
||||
|
||||
@ -2599,26 +2549,26 @@ comma:
|
||||
(0); // zero in parentheses
|
||||
```
|
||||
|
||||
### Structure expressions
|
||||
### Struct expressions
|
||||
|
||||
There are several forms of structure expressions. A _structure expression_
|
||||
consists of the [path](#paths) of a [structure item](#structures), followed by
|
||||
There are several forms of struct expressions. A _struct expression_
|
||||
consists of the [path](#paths) of a [struct item](#structs), followed by
|
||||
a brace-enclosed list of one or more comma-separated name-value pairs,
|
||||
providing the field values of a new instance of the structure. A field name
|
||||
providing the field values of a new instance of the struct. A field name
|
||||
can be any identifier, and is separated from its value expression by a colon.
|
||||
The location denoted by a structure field is mutable if and only if the
|
||||
enclosing structure is mutable.
|
||||
The location denoted by a struct field is mutable if and only if the
|
||||
enclosing struct is mutable.
|
||||
|
||||
A _tuple structure expression_ consists of the [path](#paths) of a [structure
|
||||
item](#structures), followed by a parenthesized list of one or more
|
||||
comma-separated expressions (in other words, the path of a structure item
|
||||
followed by a tuple expression). The structure item must be a tuple structure
|
||||
A _tuple struct expression_ consists of the [path](#paths) of a [struct
|
||||
item](#structs), followed by a parenthesized list of one or more
|
||||
comma-separated expressions (in other words, the path of a struct item
|
||||
followed by a tuple expression). The struct item must be a tuple struct
|
||||
item.
|
||||
|
||||
A _unit-like structure expression_ consists only of the [path](#paths) of a
|
||||
[structure item](#structures).
|
||||
A _unit-like struct expression_ consists only of the [path](#paths) of a
|
||||
[struct item](#structs).
|
||||
|
||||
The following are examples of structure expressions:
|
||||
The following are examples of struct expressions:
|
||||
|
||||
```
|
||||
# struct Point { x: f64, y: f64 }
|
||||
@ -2631,14 +2581,14 @@ let u = game::User {name: "Joe", age: 35, score: 100_000};
|
||||
some_fn::<Cookie>(Cookie);
|
||||
```
|
||||
|
||||
A structure expression forms a new value of the named structure type. Note
|
||||
that for a given *unit-like* structure type, this will always be the same
|
||||
A struct expression forms a new value of the named struct type. Note
|
||||
that for a given *unit-like* struct type, this will always be the same
|
||||
value.
|
||||
|
||||
A structure expression can terminate with the syntax `..` followed by an
|
||||
A struct expression can terminate with the syntax `..` followed by an
|
||||
expression to denote a functional update. The expression following `..` (the
|
||||
base) must have the same structure type as the new structure type being formed.
|
||||
The entire expression denotes the result of constructing a new structure (with
|
||||
base) must have the same struct type as the new struct type being formed.
|
||||
The entire expression denotes the result of constructing a new struct (with
|
||||
the same type as the base expression) with the given values for the fields that
|
||||
were explicitly specified and the values in the base expression for all other
|
||||
fields.
|
||||
@ -2684,7 +2634,7 @@ the left-hand-side expression is an indirect [trait object](#trait-objects).
|
||||
A _field expression_ consists of an expression followed by a single dot and an
|
||||
identifier, when not immediately followed by a parenthesized expression-list
|
||||
(the latter is a [method call expression](#method-call-expressions)). A field
|
||||
expression denotes a field of a [structure](#structure-types).
|
||||
expression denotes a field of a [struct](#struct-types).
|
||||
|
||||
```{.ignore .field}
|
||||
mystruct.myfield;
|
||||
@ -2692,7 +2642,7 @@ foo().x;
|
||||
(Struct {a: 10, b: 20}).a;
|
||||
```
|
||||
|
||||
A field access is an [lvalue](#lvalues,-rvalues-and-temporaries) referring to
|
||||
A field access is an [lvalue](#lvalues-rvalues-and-temporaries) referring to
|
||||
the value of that field. When the type providing the field inherits mutability,
|
||||
it can be [assigned](#assignment-expressions) to.
|
||||
|
||||
@ -2703,7 +2653,7 @@ fewer autoderefs to more.
|
||||
|
||||
### Array expressions
|
||||
|
||||
An [array](#array,-and-slice-types) _expression_ is written by enclosing zero
|
||||
An [array](#array-and-slice-types) _expression_ is written by enclosing zero
|
||||
or more comma-separated expressions of uniform type in square brackets.
|
||||
|
||||
In the `[expr ';' expr]` form, the expression after the `';'` must be a
|
||||
@ -2719,9 +2669,9 @@ constant expression that can be evaluated at compile time, such as a
|
||||
|
||||
### Index expressions
|
||||
|
||||
[Array](#array,-and-slice-types)-typed expressions can be indexed by
|
||||
[Array](#array-and-slice-types)-typed expressions can be indexed by
|
||||
writing a square-bracket-enclosed expression (the index) after them. When the
|
||||
array is mutable, the resulting [lvalue](#lvalues,-rvalues-and-temporaries) can
|
||||
array is mutable, the resulting [lvalue](#lvalues-rvalues-and-temporaries) can
|
||||
be assigned to.
|
||||
|
||||
Indices are zero-based, and may be of any integral type. Vector access is
|
||||
@ -2762,7 +2712,7 @@ The following expressions are equivalent.
|
||||
let x = std::ops::Range {start: 0, end: 10};
|
||||
let y = 0..10;
|
||||
|
||||
assert_eq!(x,y);
|
||||
assert_eq!(x, y);
|
||||
```
|
||||
|
||||
### Unary operator expressions
|
||||
@ -2775,7 +2725,7 @@ before the expression they apply to.
|
||||
* `*`
|
||||
: Dereference. When applied to a [pointer](#pointer-types) it denotes the
|
||||
pointed-to location. For pointers to mutable locations, the resulting
|
||||
[lvalue](#lvalues,-rvalues-and-temporaries) can be assigned to.
|
||||
[lvalue](#lvalues-rvalues-and-temporaries) can be assigned to.
|
||||
On non-pointer types, it calls the `deref` method of the `std::ops::Deref`
|
||||
trait, or the `deref_mut` method of the `std::ops::DerefMut` trait (if
|
||||
implemented by the type and required for an outer expression that will or
|
||||
@ -2916,8 +2866,8 @@ surprising side-effects on the dynamic execution semantics.
|
||||
#### Assignment expressions
|
||||
|
||||
An _assignment expression_ consists of an
|
||||
[lvalue](#lvalues,-rvalues-and-temporaries) expression followed by an equals
|
||||
sign (`=`) and an [rvalue](#lvalues,-rvalues-and-temporaries) expression.
|
||||
[lvalue](#lvalues-rvalues-and-temporaries) expression followed by an equals
|
||||
sign (`=`) and an [rvalue](#lvalues-rvalues-and-temporaries) expression.
|
||||
|
||||
Evaluating an assignment expression [either copies or
|
||||
moves](#moved-and-copied-types) its right-hand operand to its left-hand
|
||||
@ -3035,10 +2985,10 @@ A `loop` expression may optionally have a _label_. The label is written as
|
||||
a lifetime preceding the loop expression, as in `'foo: loop{ }`. If a
|
||||
label is present, then labeled `break` and `continue` expressions nested
|
||||
within this loop may exit out of this loop or return control to its head.
|
||||
See [Break expressions](#break-expressions) and [Continue
|
||||
See [break expressions](#break-expressions) and [continue
|
||||
expressions](#continue-expressions).
|
||||
|
||||
### Break expressions
|
||||
### `break` expressions
|
||||
|
||||
A `break` expression has an optional _label_. If the label is absent, then
|
||||
executing a `break` expression immediately terminates the innermost loop
|
||||
@ -3046,7 +2996,7 @@ enclosing it. It is only permitted in the body of a loop. If the label is
|
||||
present, then `break 'foo` terminates the loop with label `'foo`, which need not
|
||||
be the innermost label enclosing the `break` expression, but must enclose it.
|
||||
|
||||
### Continue expressions
|
||||
### `continue` expressions
|
||||
|
||||
A `continue` expression has an optional _label_. If the label is absent, then
|
||||
executing a `continue` expression immediately terminates the current iteration
|
||||
@ -3059,7 +3009,7 @@ innermost label enclosing the `break` expression, but must enclose it.
|
||||
|
||||
A `continue` expression is only permitted in the body of a loop.
|
||||
|
||||
### While loops
|
||||
### `while` loops
|
||||
|
||||
A `while` loop begins by evaluating the boolean loop conditional expression.
|
||||
If the loop conditional expression evaluates to `true`, the loop body block
|
||||
@ -3082,12 +3032,12 @@ Like `loop` expressions, `while` loops can be controlled with `break` or
|
||||
loops](#infinite-loops), [break expressions](#break-expressions), and
|
||||
[continue expressions](#continue-expressions) for more information.
|
||||
|
||||
### For expressions
|
||||
### `for` expressions
|
||||
|
||||
A `for` expression is a syntactic construct for looping over elements provided
|
||||
by an implementation of `std::iter::IntoIterator`.
|
||||
|
||||
An example of a for loop over the contents of an array:
|
||||
An example of a `for` loop over the contents of an array:
|
||||
|
||||
```
|
||||
# type Foo = i32;
|
||||
@ -3117,7 +3067,7 @@ Like `loop` expressions, `for` loops can be controlled with `break` or
|
||||
loops](#infinite-loops), [break expressions](#break-expressions), and
|
||||
[continue expressions](#continue-expressions) for more information.
|
||||
|
||||
### If expressions
|
||||
### `if` expressions
|
||||
|
||||
An `if` expression is a conditional branch in program control. The form of an
|
||||
`if` expression is a condition expression, followed by a consequent block, any
|
||||
@ -3129,11 +3079,11 @@ evaluates to `false`, the consequent block is skipped and any subsequent `else
|
||||
if` condition is evaluated. If all `if` and `else if` conditions evaluate to
|
||||
`false` then any `else` block is executed.
|
||||
|
||||
### Match expressions
|
||||
### `match` expressions
|
||||
|
||||
A `match` expression branches on a *pattern*. The exact form of matching that
|
||||
occurs depends on the pattern. Patterns consist of some combination of
|
||||
literals, destructured arrays or enum constructors, structures and tuples,
|
||||
literals, destructured arrays or enum constructors, structs and tuples,
|
||||
variable binding specifications, wildcards (`..`), and placeholders (`_`). A
|
||||
`match` expression has a *head expression*, which is the value to compare to
|
||||
the patterns. The type of the patterns must equal the type of the head
|
||||
@ -3144,7 +3094,7 @@ stands for a *single* data field, whereas a wildcard `..` stands for *all* the
|
||||
fields of a particular variant.
|
||||
|
||||
A `match` behaves differently depending on whether or not the head expression
|
||||
is an [lvalue or an rvalue](#lvalues,-rvalues-and-temporaries). If the head
|
||||
is an [lvalue or an rvalue](#lvalues-rvalues-and-temporaries). If the head
|
||||
expression is an rvalue, it is first evaluated into a temporary location, and
|
||||
the resulting value is sequentially compared to the patterns in the arms until
|
||||
a match is found. The first arm with a matching pattern is chosen as the branch
|
||||
@ -3235,7 +3185,7 @@ let message = match maybe_digit {
|
||||
};
|
||||
```
|
||||
|
||||
### If let expressions
|
||||
### `if let` expressions
|
||||
|
||||
An `if let` expression is semantically identical to an `if` expression but in place
|
||||
of a condition expression it expects a refutable let statement. If the value of the
|
||||
@ -3256,7 +3206,7 @@ if let ("Ham", b) = dish {
|
||||
}
|
||||
```
|
||||
|
||||
### While let loops
|
||||
### `while let` loops
|
||||
|
||||
A `while let` loop is semantically identical to a `while` loop but in place of a
|
||||
condition expression it expects a refutable let statement. If the value of the
|
||||
@ -3264,7 +3214,7 @@ expression on the right hand side of the let statement matches the pattern, the
|
||||
loop body block executes and control returns to the pattern matching statement.
|
||||
Otherwise, the while expression completes.
|
||||
|
||||
### Return expressions
|
||||
### `return` expressions
|
||||
|
||||
Return expressions are denoted with the keyword `return`. Evaluating a `return`
|
||||
expression moves its argument into the designated output location for the
|
||||
@ -3403,17 +3353,17 @@ As you can see, the `vec!` macro allows you to create a `Vec<T>` easily. The
|
||||
All in-bounds elements of arrays and slices are always initialized, and access
|
||||
to an array or slice is always bounds-checked.
|
||||
|
||||
### Structure types
|
||||
### Struct types
|
||||
|
||||
A `struct` *type* is a heterogeneous product of other types, called the
|
||||
*fields* of the type.[^structtype]
|
||||
|
||||
[^structtype]: `struct` types are analogous to `struct` types in C,
|
||||
the *record* types of the ML family,
|
||||
or the *structure* types of the Lisp family.
|
||||
or the *struct* types of the Lisp family.
|
||||
|
||||
New instances of a `struct` can be constructed with a [struct
|
||||
expression](#structure-expressions).
|
||||
expression](#struct-expressions).
|
||||
|
||||
The memory layout of a `struct` is undefined by default to allow for compiler
|
||||
optimizations like field reordering, but it can be fixed with the
|
||||
@ -3423,14 +3373,14 @@ have the same memory layout.
|
||||
|
||||
The fields of a `struct` may be qualified by [visibility
|
||||
modifiers](#visibility-and-privacy), to allow access to data in a
|
||||
structure outside a module.
|
||||
struct outside a module.
|
||||
|
||||
A _tuple struct_ type is just like a structure type, except that the fields are
|
||||
A _tuple struct_ type is just like a struct type, except that the fields are
|
||||
anonymous.
|
||||
|
||||
A _unit-like struct_ type is like a structure type, except that it has no
|
||||
fields. The one value constructed by the associated [structure
|
||||
expression](#structure-expressions) is the only value that inhabits such a
|
||||
A _unit-like struct_ type is like a struct type, except that it has no
|
||||
fields. The one value constructed by the associated [struct
|
||||
expression](#struct-expressions) is the only value that inhabits such a
|
||||
type.
|
||||
|
||||
### Enumerated types
|
||||
@ -3457,13 +3407,13 @@ named reference to an [`enum` item](#enumerations).
|
||||
### Recursive types
|
||||
|
||||
Nominal types — [enumerations](#enumerated-types) and
|
||||
[structures](#structure-types) — may be recursive. That is, each `enum`
|
||||
[structs](#struct-types) — may be recursive. That is, each `enum`
|
||||
constructor or `struct` field may refer, directly or indirectly, to the
|
||||
enclosing `enum` or `struct` type itself. Such recursion has restrictions:
|
||||
|
||||
* Recursive types must include a nominal type in the recursion
|
||||
(not mere [type definitions](grammar.html#type-definitions),
|
||||
or other structural types such as [arrays](#array,-and-slice-types) or [tuples](#tuple-types)).
|
||||
or other structural types such as [arrays](#array-and-slice-types) or [tuples](#tuple-types)).
|
||||
* A recursive `enum` item must have at least one non-recursive constructor
|
||||
(in order to give the recursion a basis case).
|
||||
* The size of a recursive type must be finite;
|
||||
@ -3485,7 +3435,7 @@ let a: List<i32> = List::Cons(7, Box::new(List::Cons(13, Box::new(List::Nil))));
|
||||
### Pointer types
|
||||
|
||||
All pointers in Rust are explicit first-class values. They can be copied,
|
||||
stored into data structures, and returned from functions. There are two
|
||||
stored into data structs, and returned from functions. There are two
|
||||
varieties of pointer in Rust:
|
||||
|
||||
* References (`&`)
|
||||
@ -3759,7 +3709,7 @@ repeated sub-expression is a coercion site for coercion to type `U`.
|
||||
Each sub-expression is a coercion site to the respective type, e.g. the
|
||||
zeroth sub-expression is a coercion site to type `U_0`.
|
||||
|
||||
* Parenthesised sub-expressions (`(e)`): if the expression has type `U`, then
|
||||
* Parenthesized sub-expressions (`(e)`): if the expression has type `U`, then
|
||||
the sub-expression is a coercion site to `U`.
|
||||
|
||||
* Blocks: if a block has type `U`, then the last expression in the block (if
|
||||
@ -3885,7 +3835,7 @@ references to boxes are dropped.
|
||||
### Variables
|
||||
|
||||
A _variable_ is a component of a stack frame, either a named function parameter,
|
||||
an anonymous [temporary](#lvalues,-rvalues-and-temporaries), or a named local
|
||||
an anonymous [temporary](#lvalues-rvalues-and-temporaries), or a named local
|
||||
variable.
|
||||
|
||||
A _local variable_ (or *stack-local* allocation) holds a value directly,
|
||||
@ -3919,11 +3869,11 @@ initialized; this is enforced by the compiler.
|
||||
The Rust compiler supports various methods to link crates together both
|
||||
statically and dynamically. This section will explore the various methods to
|
||||
link Rust crates together, and more information about native libraries can be
|
||||
found in the [ffi section of the book][ffi].
|
||||
found in the [FFI section of the book][ffi].
|
||||
|
||||
In one session of compilation, the compiler can generate multiple artifacts
|
||||
through the usage of either command line flags or the `crate_type` attribute.
|
||||
If one or more command line flag is specified, all `crate_type` attributes will
|
||||
If one or more command line flags are specified, all `crate_type` attributes will
|
||||
be ignored in favor of only building the artifacts specified by command line.
|
||||
|
||||
* `--crate-type=bin`, `#[crate_type = "bin"]` - A runnable executable will be
|
||||
@ -3969,7 +3919,7 @@ Note that these outputs are stackable in the sense that if multiple are
|
||||
specified, then the compiler will produce each form of output at once without
|
||||
having to recompile. However, this only applies for outputs specified by the
|
||||
same method. If only `crate_type` attributes are specified, then they will all
|
||||
be built, but if one or more `--crate-type` command line flag is specified,
|
||||
be built, but if one or more `--crate-type` command line flags are specified,
|
||||
then only those outputs will be built.
|
||||
|
||||
With all these different kinds of outputs, if crate A depends on crate B, then
|
||||
@ -4024,9 +3974,98 @@ In general, `--crate-type=bin` or `--crate-type=lib` should be sufficient for
|
||||
all compilation needs, and the other options are just available if more
|
||||
fine-grained control is desired over the output format of a Rust crate.
|
||||
|
||||
# Appendix: Rationales and design trade-offs
|
||||
# Unsafety
|
||||
|
||||
*TODO*.
|
||||
Unsafe operations are those that potentially violate the memory-safety
|
||||
guarantees of Rust's static semantics.
|
||||
|
||||
The following language level features cannot be used in the safe subset of
|
||||
Rust:
|
||||
|
||||
- Dereferencing a [raw pointer](#pointer-types).
|
||||
- Reading or writing a [mutable static variable](#mutable-statics).
|
||||
- Calling an unsafe function (including an intrinsic or foreign function).
|
||||
|
||||
## Unsafe functions
|
||||
|
||||
Unsafe functions are functions that are not safe in all contexts and/or for all
|
||||
possible inputs. Such a function must be prefixed with the keyword `unsafe` and
|
||||
can only be called from an `unsafe` block or another `unsafe` function.
|
||||
|
||||
## Unsafe blocks
|
||||
|
||||
A block of code can be prefixed with the `unsafe` keyword, to permit calling
|
||||
`unsafe` functions or dereferencing raw pointers within a safe function.
|
||||
|
||||
When a programmer has sufficient conviction that a sequence of potentially
|
||||
unsafe operations is actually safe, they can encapsulate that sequence (taken
|
||||
as a whole) within an `unsafe` block. The compiler will consider uses of such
|
||||
code safe, in the surrounding context.
|
||||
|
||||
Unsafe blocks are used to wrap foreign libraries, make direct use of hardware
|
||||
or implement features not directly present in the language. For example, Rust
|
||||
provides the language features necessary to implement memory-safe concurrency
|
||||
in the language but the implementation of threads and message passing is in the
|
||||
standard library.
|
||||
|
||||
Rust's type system is a conservative approximation of the dynamic safety
|
||||
requirements, so in some cases there is a performance cost to using safe code.
|
||||
For example, a doubly-linked list is not a tree structure and can only be
|
||||
represented with reference-counted pointers in safe code. By using `unsafe`
|
||||
blocks to represent the reverse links as raw pointers, it can be implemented
|
||||
with only boxes.
|
||||
|
||||
## Behavior considered undefined
|
||||
|
||||
The following is a list of behavior which is forbidden in all Rust code,
|
||||
including within `unsafe` blocks and `unsafe` functions. Type checking provides
|
||||
the guarantee that these issues are never caused by safe code.
|
||||
|
||||
* Data races
|
||||
* Dereferencing a null/dangling raw pointer
|
||||
* Reads of [undef](http://llvm.org/docs/LangRef.html#undefined-values)
|
||||
(uninitialized) memory
|
||||
* Breaking the [pointer aliasing
|
||||
rules](http://llvm.org/docs/LangRef.html#pointer-aliasing-rules)
|
||||
with raw pointers (a subset of the rules used by C)
|
||||
* `&mut` and `&` follow LLVM’s scoped [noalias] model, except if the `&T`
|
||||
contains an `UnsafeCell<U>`. Unsafe code must not violate these aliasing
|
||||
guarantees.
|
||||
* Mutating non-mutable data (that is, data reached through a shared reference or
|
||||
data owned by a `let` binding), unless that data is contained within an `UnsafeCell<U>`.
|
||||
* Invoking undefined behavior via compiler intrinsics:
|
||||
* Indexing outside of the bounds of an object with `std::ptr::offset`
|
||||
(`offset` intrinsic), with
|
||||
the exception of one byte past the end which is permitted.
|
||||
* Using `std::ptr::copy_nonoverlapping_memory` (`memcpy32`/`memcpy64`
|
||||
intrinsics) on overlapping buffers
|
||||
* Invalid values in primitive types, even in private fields/locals:
|
||||
* Dangling/null references or boxes
|
||||
* A value other than `false` (0) or `true` (1) in a `bool`
|
||||
* A discriminant in an `enum` not included in the type definition
|
||||
* A value in a `char` which is a surrogate or above `char::MAX`
|
||||
* Non-UTF-8 byte sequences in a `str`
|
||||
* Unwinding into Rust from foreign code or unwinding from Rust into foreign
|
||||
code. Rust's failure system is not compatible with exception handling in
|
||||
other languages. Unwinding must be caught and handled at FFI boundaries.
|
||||
|
||||
[noalias]: http://llvm.org/docs/LangRef.html#noalias
|
||||
|
||||
## Behavior not considered unsafe
|
||||
|
||||
This is a list of behavior not considered *unsafe* in Rust terms, but that may
|
||||
be undesired.
|
||||
|
||||
* Deadlocks
|
||||
* Leaks of memory and other resources
|
||||
* Exiting without calling destructors
|
||||
* Integer overflow
|
||||
- Overflow is considered "unexpected" behavior and is always user-error,
|
||||
unless the `wrapping` primitives are used. In non-optimized builds, the compiler
|
||||
will insert debug checks that panic on overflow, but in optimized builds overflow
|
||||
instead results in wrapped values. See [RFC 560] for the rationale and more details.
|
||||
|
||||
[RFC 560]: https://github.com/rust-lang/rfcs/blob/master/text/0560-integer-overflow.md
|
||||
|
||||
# Appendix: Influences
|
||||
|
||||
@ -4036,7 +4075,7 @@ that have since been removed):
|
||||
|
||||
* SML, OCaml: algebraic data types, pattern matching, type inference,
|
||||
semicolon statement separation
|
||||
* C++: references, RAII, smart pointers, move semantics, monomorphisation,
|
||||
* C++: references, RAII, smart pointers, move semantics, monomorphization,
|
||||
memory model
|
||||
* ML Kit, Cyclone: region based memory management
|
||||
* Haskell (GHC): typeclasses, type families
|
||||
|
@ -338,14 +338,17 @@ table th {
|
||||
|
||||
.rusttest { display: none; }
|
||||
pre.rust { position: relative; }
|
||||
.test-arrow {
|
||||
a.test-arrow {
|
||||
display: inline-block;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 10px;
|
||||
font-size: 150%;
|
||||
-webkit-transform: scaleX(-1);
|
||||
transform: scaleX(-1);
|
||||
|
||||
background-color: #4e8bca;
|
||||
color: #f5f5f5;
|
||||
padding: 5px 10px 5px 10px;
|
||||
border-radius: 5px;
|
||||
font-size: 130%;
|
||||
top: 5px;
|
||||
right: 5px;
|
||||
}
|
||||
|
||||
.unstable-feature {
|
||||
|
@ -48,7 +48,3 @@
|
||||
* [Testing](testing/README.md)
|
||||
* [Unit testing](testing/unit.md)
|
||||
* [FFI, platform-specific code](platform.md)
|
||||
* [APIs for a changing Rust](changing/README.md)
|
||||
* [Pre-1.0 changes](changing/pre-1-0.md)
|
||||
* [Post-1.0 changes](changing/post-1-0.md)
|
||||
* [Timing unclear](changing/unclear.md)
|
||||
|
@ -1,5 +0,0 @@
|
||||
% API design for a changing Rust
|
||||
|
||||
A number of planned Rust features will drastically affect the API design
|
||||
story. This section collects some of the biggest features with concrete examples
|
||||
of how the API will change.
|
@ -1,12 +0,0 @@
|
||||
% Post-1.0 changes
|
||||
|
||||
### Higher-kinded types
|
||||
|
||||
* A trait encompassing both `Iterable<T>` for some fixed `T` and
|
||||
`FromIterator<U>` for _all_ `U` (where HKT comes in). The train
|
||||
could provide e.g. a default `map` method producing the same kind of
|
||||
the container, but with a new type parameter.
|
||||
|
||||
* **Monadic-generic programming**? Can we add this without deprecating
|
||||
huge swaths of the API (including `Option::map`, `option::collect`,
|
||||
`result::collect`, `try!` etc.
|
@ -1,17 +0,0 @@
|
||||
% Pre-1.0 changes
|
||||
|
||||
### `std` facade
|
||||
|
||||
We should revisit some APIs in `libstd` now that the facade effort is complete.
|
||||
|
||||
For example, the treatment of environment variables in the new
|
||||
`Command` API is waiting on access to hashtables before being
|
||||
approved.
|
||||
|
||||
### Trait reform
|
||||
|
||||
Potential for standard conversion traits (`to`, `into`, `as`).
|
||||
|
||||
Probably many other opportunities here.
|
||||
|
||||
### Unboxed closures
|
@ -1,28 +0,0 @@
|
||||
% Changes with unclear timing
|
||||
|
||||
### Associated items
|
||||
|
||||
* Many traits that currently take type parameters should instead use associated
|
||||
types; this will _drastically_ simplify signatures in some cases.
|
||||
|
||||
* Associated constants would be useful in a few places, e.g. traits for
|
||||
numerics, traits for paths.
|
||||
|
||||
### Anonymous, unboxed return types (aka `impl Trait` types)
|
||||
|
||||
* See https://github.com/rust-lang/rfcs/pull/105
|
||||
|
||||
* Could affect API design in several places, e.g. the `Iterator` trait.
|
||||
|
||||
### Default type parameters
|
||||
|
||||
We are already using this in a few places (e.g. `HashMap`), but it's
|
||||
feature-gated.
|
||||
|
||||
### Compile-time function evaluation (CTFE)
|
||||
|
||||
https://github.com/mozilla/rust/issues/11621
|
||||
|
||||
### Improved constant folding
|
||||
|
||||
https://github.com/rust-lang/rust/issues/7834
|
@ -57,7 +57,7 @@ fn write_info(info: &Info) -> Result<(), IoError> {
|
||||
```
|
||||
|
||||
See
|
||||
[the `result` module documentation](https://doc.rust-lang.org/stable/std/result/index.html#the-try!-macro)
|
||||
[the `result` module documentation](https://doc.rust-lang.org/stable/std/result/index.html#the-try-macro)
|
||||
for more details.
|
||||
|
||||
### The `Result`-`impl` pattern [FIXME]
|
||||
|
@ -17,12 +17,12 @@ Organize module headers as follows:
|
||||
Avoid using `#[path="..."]` directives; make the file system and
|
||||
module hierarchy match, instead.
|
||||
|
||||
### Use the module hirearchy to organize APIs into coherent sections. [FIXME]
|
||||
### Use the module hierarchy to organize APIs into coherent sections. [FIXME]
|
||||
|
||||
> **[FIXME]** Flesh this out with examples; explain what a "coherent
|
||||
> section" is with examples.
|
||||
>
|
||||
> The module hirearchy defines both the public and internal API of your module.
|
||||
> The module hierarchy defines both the public and internal API of your module.
|
||||
> Breaking related functionality into submodules makes it understandable to both
|
||||
> users and contributors to the module.
|
||||
|
||||
@ -82,7 +82,7 @@ io/mod.rs
|
||||
```
|
||||
|
||||
While it is possible to define all of `io` within a single directory,
|
||||
mirroring the module hirearchy in the directory structure makes
|
||||
mirroring the module hierarchy in the directory structure makes
|
||||
submodules of `io::net` easier to find.
|
||||
|
||||
### Consider top-level definitions or reexports. [FIXME: needs RFC]
|
||||
@ -104,13 +104,13 @@ while
|
||||
[`TcpStream`](https://doc.rust-lang.org/std/io/net/tcp/struct.TcpStream.html)
|
||||
is defined in `io/net/tcp.rs` and reexported in the `io` module.
|
||||
|
||||
### Use internal module hirearchies for organization. [FIXME: needs RFC]
|
||||
### Use internal module hierarchies for organization. [FIXME: needs RFC]
|
||||
|
||||
> **[FIXME]**
|
||||
> - Referencing internal modules from the standard library is subject to
|
||||
> becoming outdated.
|
||||
|
||||
Internal module hirearchies (i.e., private submodules) may be used to
|
||||
Internal module hierarchies (i.e., private submodules) may be used to
|
||||
hide implementation details that are not part of the module's API.
|
||||
|
||||
For example, in [`std::io`](https://doc.rust-lang.org/std/io/), `mod mem`
|
||||
|
@ -9,18 +9,18 @@ applicable, common traits.
|
||||
|
||||
To see why, consider the following situation:
|
||||
|
||||
* Crate `std` defines trait `Show`.
|
||||
* Crate `url` defines type `Url`, without implementing `Show`.
|
||||
* Crate `std` defines trait `Debug`.
|
||||
* Crate `url` defines type `Url`, without implementing `Debug`.
|
||||
* Crate `webapp` imports from both `std` and `url`,
|
||||
|
||||
There is no way for `webapp` to add `Show` to `url`, since it defines neither.
|
||||
There is no way for `webapp` to add `Debug` to `url`, since it defines neither.
|
||||
(Note: the newtype pattern can provide an efficient, but inconvenient
|
||||
workaround; see [newtype for views](../types/newtype.md))
|
||||
|
||||
The most important common traits to implement from `std` are:
|
||||
|
||||
```rust
|
||||
Clone, Show, Hash, Eq
|
||||
Clone, Debug, Hash, Eq
|
||||
```
|
||||
|
||||
#### When safe, derive or otherwise implement `Send` and `Share`. [FIXME]
|
||||
|
@ -27,7 +27,7 @@ explicitly implement to be used by this generic function.
|
||||
* _Inference_. Since the type parameters to generic functions can usually be
|
||||
inferred, generic functions can help cut down on verbosity in code where
|
||||
explicit conversions or other method calls would usually be necessary. See the
|
||||
[overloading/implicits use case](#use-case:-limited-overloading-and/or-implicit-conversions)
|
||||
[overloading/implicits use case](#use-case-limited-overloading-andor-implicit-conversions)
|
||||
below.
|
||||
* _Precise types_. Because generics give a _name_ to the specific type
|
||||
implementing a trait, it is possible to be precise about places where that
|
||||
@ -51,7 +51,7 @@ explicitly implement to be used by this generic function.
|
||||
a `Vec<T>` contains elements of a single concrete type (and, indeed, the
|
||||
vector representation is specialized to lay these out in line). Sometimes
|
||||
heterogeneous collections are useful; see
|
||||
[trait objects](#use-case:-trait-objects) below.
|
||||
[trait objects](#use-case-trait-objects) below.
|
||||
* _Signature verbosity_. Heavy use of generics can bloat function signatures.
|
||||
**[Ed. note]** This problem may be mitigated by some language improvements; stay tuned.
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
> **[FIXME]** We probably want to discourage this, at least when used in a way
|
||||
> that is publicly exposed.
|
||||
|
||||
Traits that provide default implmentations for function can provide code reuse
|
||||
Traits that provide default implementations for function can provide code reuse
|
||||
across types. For example, a `print` method can be defined across multiple
|
||||
types as follows:
|
||||
|
||||
|
@ -85,3 +85,20 @@ Use inner doc comments _only_ to document crates and file-level modules:
|
||||
//!
|
||||
//! The core library is a something something...
|
||||
```
|
||||
|
||||
### Explain context.
|
||||
|
||||
Rust doesn't have special constructors, only functions that return new
|
||||
instances. These aren't visible in the automatically generated documentation
|
||||
for a type, so you should specifically link to them:
|
||||
|
||||
``` rust
|
||||
/// An iterator that yields `None` forever after the underlying iterator
|
||||
/// yields `None` once.
|
||||
///
|
||||
/// These can be created through
|
||||
/// [`iter.fuse()`](trait.Iterator.html#method.fuse).
|
||||
pub struct Fuse<I> {
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
@ -9,9 +9,8 @@ requirements, and writing low-level code, like device drivers and operating
|
||||
systems. It improves on current languages targeting this space by having a
|
||||
number of compile-time safety checks that produce no runtime overhead, while
|
||||
eliminating all data races. Rust also aims to achieve ‘zero-cost abstractions’
|
||||
even though some of these abstractions feel like those of a high-level
|
||||
language. Even then, Rust still allows precise control like a low-level
|
||||
language would.
|
||||
even though some of these abstractions feel like those of a high-level language.
|
||||
Even then, Rust still allows precise control like a low-level language would.
|
||||
|
||||
[rust]: https://www.rust-lang.org
|
||||
|
||||
@ -34,15 +33,15 @@ is the first. After this:
|
||||
[gl]: glossary.html
|
||||
[bi]: bibliography.html
|
||||
|
||||
After reading this introduction, you’ll want to dive into either ‘Learn Rust’
|
||||
or ‘Syntax and Semantics’, depending on your preference: ‘Learn Rust’ if you
|
||||
want to dive in with a project, or ‘Syntax and Semantics’ if you prefer to
|
||||
start small, and learn a single concept thoroughly before moving onto the next.
|
||||
After reading this introduction, you’ll want to dive into either ‘Learn Rust’ or
|
||||
‘Syntax and Semantics’, depending on your preference: ‘Learn Rust’ if you want
|
||||
to dive in with a project, or ‘Syntax and Semantics’ if you prefer to start
|
||||
small, and learn a single concept thoroughly before moving onto the next.
|
||||
Copious cross-linking connects these parts together.
|
||||
|
||||
### Contributing
|
||||
|
||||
The source files from which this book is generated can be found on Github:
|
||||
The source files from which this book is generated can be found on GitHub:
|
||||
[github.com/rust-lang/rust/tree/master/src/doc/trpl](https://github.com/rust-lang/rust/tree/master/src/doc/trpl)
|
||||
|
||||
## A brief introduction to Rust
|
||||
@ -76,11 +75,11 @@ type inference to balance out the power of static typing with the verbosity of
|
||||
annotating types.
|
||||
|
||||
Rust prefers stack allocation to heap allocation: `x` is placed directly on the
|
||||
stack. However, the `Vec<T>` type allocates space for the elements of the
|
||||
vector on the heap. If you’re not familiar with this distinction, you can
|
||||
ignore it for now, or check out [‘The Stack and the Heap’][heap]. As a systems
|
||||
programming language, Rust gives you the ability to control how your memory is
|
||||
allocated, but when we’re getting started, it’s less of a big deal.
|
||||
stack. However, the `Vec<T>` type allocates space for the elements of the vector
|
||||
on the heap. If you’re not familiar with this distinction, you can ignore it for
|
||||
now, or check out [‘The Stack and the Heap’][heap]. As a systems programming
|
||||
language, Rust gives us the ability to control how our memory is allocated, but
|
||||
when we’re getting started, it’s less of a big deal.
|
||||
|
||||
[var]: variable-bindings.html
|
||||
[macro]: macros.html
|
||||
@ -90,10 +89,10 @@ Earlier, we mentioned that ‘ownership’ is the key new concept in Rust. In Ru
|
||||
parlance, `x` is said to ‘own’ the vector. This means that when `x` goes out of
|
||||
scope, the vector’s memory will be de-allocated. This is done deterministically
|
||||
by the Rust compiler, rather than through a mechanism such as a garbage
|
||||
collector. In other words, in Rust, you don’t call functions like `malloc` and
|
||||
`free` yourself: the compiler statically determines when you need to allocate
|
||||
or deallocate memory, and inserts those calls itself. To err is to be human,
|
||||
but compilers never forget.
|
||||
collector. In other words, in Rust, we don’t call functions like `malloc` and
|
||||
`free` ourselves: the compiler statically determines when we need to allocate or
|
||||
deallocate memory, and inserts those calls itself. To err is to be human, but
|
||||
compilers never forget.
|
||||
|
||||
Let’s add another line to our example:
|
||||
|
||||
@ -105,13 +104,13 @@ fn main() {
|
||||
}
|
||||
```
|
||||
|
||||
We’ve introduced another binding, `y`. In this case, `y` is a ‘reference’ to
|
||||
the first element of the vector. Rust’s references are similar to pointers in
|
||||
other languages, but with additional compile-time safety checks. References
|
||||
interact with the ownership system by [‘borrowing’][borrowing] what they point
|
||||
to, rather than owning it. The difference is, when the reference goes out of
|
||||
scope, it will not deallocate the underlying memory. If it did, we’d
|
||||
de-allocate twice, which is bad!
|
||||
We’ve introduced another binding, `y`. In this case, `y` is a ‘reference’ to the
|
||||
first element of the vector. Rust’s references are similar to pointers in other
|
||||
languages, but with additional compile-time safety checks. References interact
|
||||
with the ownership system by [‘borrowing’][borrowing] what they point to, rather
|
||||
than owning it. The difference is, when the reference goes out of scope, it
|
||||
won't deallocate the underlying memory. If it did, we’d de-allocate twice, which
|
||||
is bad!
|
||||
|
||||
[borrowing]: references-and-borrowing.html
|
||||
|
||||
@ -147,7 +146,7 @@ fn main() {
|
||||
|
||||
Whew! The Rust compiler gives quite detailed errors at times, and this is one
|
||||
of those times. As the error explains, while we made our binding mutable, we
|
||||
still cannot call `push`. This is because we already have a reference to an
|
||||
still can't call `push`. This is because we already have a reference to an
|
||||
element of the vector, `y`. Mutating something while another reference exists
|
||||
is dangerous, because we may invalidate the reference. In this specific case,
|
||||
when we create the vector, we may have only allocated space for two elements.
|
||||
|
@ -68,5 +68,7 @@
|
||||
* [Box Syntax and Patterns](box-syntax-and-patterns.md)
|
||||
* [Slice Patterns](slice-patterns.md)
|
||||
* [Associated Constants](associated-constants.md)
|
||||
* [Custom Allocators](custom-allocators.md)
|
||||
* [Glossary](glossary.md)
|
||||
* [Syntax Index](syntax-index.md)
|
||||
* [Bibliography](bibliography.md)
|
||||
|
@ -26,7 +26,7 @@ shells out to the system linker (`gcc` on most systems, `link.exe` on MSVC),
|
||||
so it makes sense to provide extra command line
|
||||
arguments, but this will not always be the case. In the future `rustc` may use
|
||||
LLVM directly to link native libraries, in which case `link_args` will have no
|
||||
meaning. You can achieve the same effect as the `link-args` attribute with the
|
||||
meaning. You can achieve the same effect as the `link_args` attribute with the
|
||||
`-C link-args` argument to `rustc`.
|
||||
|
||||
It is highly recommended to *not* use this attribute, and rather use the more
|
||||
@ -71,7 +71,7 @@ Dynamic linking on Linux can be undesirable if you wish to use new library
|
||||
features on old systems or target systems which do not have the required
|
||||
dependencies for your program to run.
|
||||
|
||||
Static linking is supported via an alternative `libc`, `musl`. You can compile
|
||||
Static linking is supported via an alternative `libc`, [`musl`](http://www.musl-libc.org). You can compile
|
||||
your own version of Rust with `musl` enabled and install it into a custom
|
||||
directory with the instructions below:
|
||||
|
||||
@ -94,8 +94,6 @@ $ # Build libunwind.a
|
||||
$ curl -O http://llvm.org/releases/3.7.0/llvm-3.7.0.src.tar.xz
|
||||
$ tar xf llvm-3.7.0.src.tar.xz
|
||||
$ cd llvm-3.7.0.src/projects/
|
||||
llvm-3.7.0.src/projects $ curl http://llvm.org/releases/3.7.0/libcxxabi-3.7.0.src.tar.xz | tar xJf -
|
||||
llvm-3.7.0.src/projects $ mv libcxxabi-3.7.0.src libcxxabi
|
||||
llvm-3.7.0.src/projects $ curl http://llvm.org/releases/3.7.0/libunwind-3.7.0.src.tar.xz | tar xJf -
|
||||
llvm-3.7.0.src/projects $ mv libunwind-3.7.0.src libunwind
|
||||
llvm-3.7.0.src/projects $ mkdir libunwind/build
|
||||
|
@ -48,7 +48,7 @@ Systems Level
|
||||
Language](http://www.cs.indiana.edu/~eholk/papers/hips2013.pdf). Early GPU work by Eric Holk.
|
||||
* [Parallel closures: a new twist on an old
|
||||
idea](https://www.usenix.org/conference/hotpar12/parallel-closures-new-twist-old-idea)
|
||||
- not exactly about rust, but by nmatsakis
|
||||
- not exactly about Rust, but by nmatsakis
|
||||
* [Patina: A Formalization of the Rust Programming
|
||||
Language](ftp://ftp.cs.washington.edu/tr/2015/03/UW-CSE-15-03-02.pdf). Early
|
||||
formalization of a subset of the type system, by Eric Reed.
|
||||
@ -61,8 +61,9 @@ Language](http://www.cs.indiana.edu/~eholk/papers/hips2013.pdf). Early GPU work
|
||||
Rust](http://scialex.github.io/reenix.pdf). Undergrad paper by Alex
|
||||
Light.
|
||||
* [Evaluation of performance and productivity metrics of potential
|
||||
programming languages in the HPC environment](). Bachelor's thesis by
|
||||
Florian Wilkens. Compares C, Go and Rust.
|
||||
programming languages in the HPC environment]
|
||||
(http://octarineparrot.com/assets/mrfloya-thesis-ba.pdf).
|
||||
Bachelor's thesis by Florian Wilkens. Compares C, Go and Rust.
|
||||
* [Nom, a byte oriented, streaming, zero copy, parser combinators library
|
||||
in Rust](http://spw15.langsec.org/papers/couprie-nom.pdf). By
|
||||
Geoffroy Couprie, research for VLC.
|
||||
@ -78,3 +79,4 @@ Language](http://www.cs.indiana.edu/~eholk/papers/hips2013.pdf). Early GPU work
|
||||
* [Session Types for
|
||||
Rust](http://munksgaard.me/papers/laumann-munksgaard-larsen.pdf). Philip
|
||||
Munksgaard's master's thesis. Research for Servo.
|
||||
* [Ownership is Theft: Experiences Building an Embedded OS in Rust - Amit Levy, et. al.](http://amitlevy.com/papers/tock-plos2015.pdf)
|
||||
|
@ -82,7 +82,7 @@ unsafe {
|
||||
with:
|
||||
|
||||
```text
|
||||
error: transmute called on types with different sizes: [u8; 4] (32 bits) to u64
|
||||
error: transmute called with differently sized types: [u8; 4] (32 bits) to u64
|
||||
(64 bits)
|
||||
```
|
||||
|
||||
|
@ -204,7 +204,7 @@ borrow checker. Generally we know that such mutations won't happen in a nested f
|
||||
to check.
|
||||
|
||||
For large, complicated programs, it becomes useful to put some things in `RefCell`s to make things
|
||||
simpler. For example, a lot of the maps in [the `ctxt` struct][ctxt] in the rust compiler internals
|
||||
simpler. For example, a lot of the maps in [the `ctxt` struct][ctxt] in the Rust compiler internals
|
||||
are inside this wrapper. These are only modified once (during creation, which is not right after
|
||||
initialization) or a couple of times in well-separated places. However, since this struct is
|
||||
pervasively used everywhere, juggling mutable and immutable pointers would be hard (perhaps
|
||||
@ -321,7 +321,7 @@ there's a lot of concurrent access happening.
|
||||
|
||||
# Composition
|
||||
|
||||
A common gripe when reading Rust code is with types like `Rc<RefCell<Vec<T>>>` (or even more more
|
||||
A common gripe when reading Rust code is with types like `Rc<RefCell<Vec<T>>>` (or even more
|
||||
complicated compositions of such types). It's not always clear what the composition does, or why the
|
||||
author chose one like this (and when one should be using such a composition in one's own code)
|
||||
|
||||
|
@ -1,9 +1,10 @@
|
||||
% Closures
|
||||
|
||||
Rust not only has named functions, but anonymous functions as well. Anonymous
|
||||
functions that have an associated environment are called ‘closures’, because they
|
||||
close over an environment. Rust has a really great implementation of them, as
|
||||
we’ll see.
|
||||
Sometimes it is useful to wrap up a function and _free variables_ for better
|
||||
clarity and reuse. The free variables that can be used come from the
|
||||
enclosing scope and are ‘closed over’ when used in the function. From this, we
|
||||
get the name ‘closures’ and Rust provides a really great implementation of
|
||||
them, as we’ll see.
|
||||
|
||||
# Syntax
|
||||
|
||||
@ -34,7 +35,7 @@ assert_eq!(4, plus_two(2));
|
||||
```
|
||||
|
||||
You’ll notice a few things about closures that are a bit different from regular
|
||||
functions defined with `fn`. The first is that we did not need to
|
||||
named functions defined with `fn`. The first is that we did not need to
|
||||
annotate the types of arguments the closure takes or the values it returns. We
|
||||
can:
|
||||
|
||||
@ -44,14 +45,15 @@ let plus_one = |x: i32| -> i32 { x + 1 };
|
||||
assert_eq!(2, plus_one(1));
|
||||
```
|
||||
|
||||
But we don’t have to. Why is this? Basically, it was chosen for ergonomic reasons.
|
||||
While specifying the full type for named functions is helpful with things like
|
||||
documentation and type inference, the types of closures are rarely documented
|
||||
since they’re anonymous, and they don’t cause the kinds of error-at-a-distance
|
||||
problems that inferring named function types can.
|
||||
But we don’t have to. Why is this? Basically, it was chosen for ergonomic
|
||||
reasons. While specifying the full type for named functions is helpful with
|
||||
things like documentation and type inference, the full type signatures of
|
||||
closures are rarely documented since they’re anonymous, and they don’t cause
|
||||
the kinds of error-at-a-distance problems that inferring named function types
|
||||
can.
|
||||
|
||||
The second is that the syntax is similar, but a bit different. I’ve added spaces
|
||||
here for easier comparison:
|
||||
The second is that the syntax is similar, but a bit different. I’ve added
|
||||
spaces here for easier comparison:
|
||||
|
||||
```rust
|
||||
fn plus_one_v1 (x: i32) -> i32 { x + 1 }
|
||||
@ -63,8 +65,8 @@ Small differences, but they’re similar.
|
||||
|
||||
# Closures and their environment
|
||||
|
||||
Closures are called such because they ‘close over their environment’. It
|
||||
looks like this:
|
||||
The environment for a closure can include bindings from its enclosing scope in
|
||||
addition to parameters and local bindings. It looks like this:
|
||||
|
||||
```rust
|
||||
let num = 5;
|
||||
@ -197,9 +199,10 @@ frame. Without `move`, a closure may be tied to the stack frame that created
|
||||
it, while a `move` closure is self-contained. This means that you cannot
|
||||
generally return a non-`move` closure from a function, for example.
|
||||
|
||||
But before we talk about taking and returning closures, we should talk some more
|
||||
about the way that closures are implemented. As a systems language, Rust gives
|
||||
you tons of control over what your code does, and closures are no different.
|
||||
But before we talk about taking and returning closures, we should talk some
|
||||
more about the way that closures are implemented. As a systems language, Rust
|
||||
gives you tons of control over what your code does, and closures are no
|
||||
different.
|
||||
|
||||
# Closure implementation
|
||||
|
||||
@ -288,9 +291,9 @@ isn’t interesting. The next part is:
|
||||
# some_closure(1) }
|
||||
```
|
||||
|
||||
Because `Fn` is a trait, we can bound our generic with it. In this case, our closure
|
||||
takes a `i32` as an argument and returns an `i32`, and so the generic bound we use
|
||||
is `Fn(i32) -> i32`.
|
||||
Because `Fn` is a trait, we can bound our generic with it. In this case, our
|
||||
closure takes a `i32` as an argument and returns an `i32`, and so the generic
|
||||
bound we use is `Fn(i32) -> i32`.
|
||||
|
||||
There’s one other key point here: because we’re bounding a generic with a
|
||||
trait, this will get monomorphized, and therefore, we’ll be doing static
|
||||
@ -411,8 +414,9 @@ fn factory() -> &(Fn(i32) -> i32) {
|
||||
```
|
||||
|
||||
Right. Because we have a reference, we need to give it a lifetime. But
|
||||
our `factory()` function takes no arguments, so elision doesn’t kick in
|
||||
here. What lifetime can we choose? `'static`:
|
||||
our `factory()` function takes no arguments, so
|
||||
[elision](lifetimes.html#lifetime-elision) doesn’t kick in here. Then what
|
||||
choices do we have? Try `'static`:
|
||||
|
||||
```rust,ignore
|
||||
fn factory() -> &'static (Fn(i32) -> i32) {
|
||||
@ -432,7 +436,7 @@ But we get another error:
|
||||
```text
|
||||
error: mismatched types:
|
||||
expected `&'static core::ops::Fn(i32) -> i32`,
|
||||
found `[closure <anon>:7:9: 7:20]`
|
||||
found `[closure@<anon>:7:9: 7:20]`
|
||||
(expected &-ptr,
|
||||
found closure) [E0308]
|
||||
|x| x + num
|
||||
@ -441,21 +445,17 @@ error: mismatched types:
|
||||
```
|
||||
|
||||
This error is letting us know that we don’t have a `&'static Fn(i32) -> i32`,
|
||||
we have a `[closure <anon>:7:9: 7:20]`. Wait, what?
|
||||
we have a `[closure@<anon>:7:9: 7:20]`. Wait, what?
|
||||
|
||||
Because each closure generates its own environment `struct` and implementation
|
||||
of `Fn` and friends, these types are anonymous. They exist just solely for
|
||||
this closure. So Rust shows them as `closure <anon>`, rather than some
|
||||
this closure. So Rust shows them as `closure@<anon>`, rather than some
|
||||
autogenerated name.
|
||||
|
||||
But why doesn’t our closure implement `&'static Fn`? Well, as we discussed before,
|
||||
closures borrow their environment. And in this case, our environment is based
|
||||
on a stack-allocated `5`, the `num` variable binding. So the borrow has a lifetime
|
||||
of the stack frame. So if we returned this closure, the function call would be
|
||||
over, the stack frame would go away, and our closure is capturing an environment
|
||||
of garbage memory!
|
||||
|
||||
So what to do? This _almost_ works:
|
||||
The error also points out that the return type is expected to be a reference,
|
||||
but what we are trying to return is not. Further, we cannot directly assign a
|
||||
`'static` lifetime to an object. So we'll take a different approach and return
|
||||
a ‘trait object’ by `Box`ing up the `Fn`. This _almost_ works:
|
||||
|
||||
```rust,ignore
|
||||
fn factory() -> Box<Fn(i32) -> i32> {
|
||||
@ -471,7 +471,7 @@ assert_eq!(6, answer);
|
||||
# }
|
||||
```
|
||||
|
||||
We use a trait object, by `Box`ing up the `Fn`. There’s just one last problem:
|
||||
There’s just one last problem:
|
||||
|
||||
```text
|
||||
error: closure may outlive the current function, but it borrows `num`,
|
||||
@ -480,8 +480,12 @@ Box::new(|x| x + num)
|
||||
^~~~~~~~~~~
|
||||
```
|
||||
|
||||
We still have a reference to the parent stack frame. With one last fix, we can
|
||||
make this work:
|
||||
Well, as we discussed before, closures borrow their environment. And in this
|
||||
case, our environment is based on a stack-allocated `5`, the `num` variable
|
||||
binding. So the borrow has a lifetime of the stack frame. So if we returned
|
||||
this closure, the function call would be over, the stack frame would go away,
|
||||
and our closure is capturing an environment of garbage memory! With one last
|
||||
fix, we can make this work:
|
||||
|
||||
```rust
|
||||
fn factory() -> Box<Fn(i32) -> i32> {
|
||||
|
@ -170,13 +170,25 @@ starting point for an improved quasiquote as an ordinary plugin library.
|
||||
|
||||
Plugins can extend [Rust's lint
|
||||
infrastructure](../reference.html#lint-check-attributes) with additional checks for
|
||||
code style, safety, etc. You can see
|
||||
[`src/test/auxiliary/lint_plugin_test.rs`](https://github.com/rust-lang/rust/blob/master/src/test/auxiliary/lint_plugin_test.rs)
|
||||
for a full example, the core of which is reproduced here:
|
||||
code style, safety, etc. Now let's write a plugin [`lint_plugin_test.rs`](https://github.com/rust-lang/rust/blob/master/src/test/auxiliary/lint_plugin_test.rs)
|
||||
that warns about any item named `lintme`.
|
||||
|
||||
```ignore
|
||||
declare_lint!(TEST_LINT, Warn,
|
||||
"Warn about items named 'lintme'");
|
||||
#![feature(plugin_registrar)]
|
||||
#![feature(box_syntax, rustc_private)]
|
||||
|
||||
extern crate syntax;
|
||||
|
||||
// Load rustc as a plugin to get macros
|
||||
#[macro_use]
|
||||
extern crate rustc;
|
||||
|
||||
use rustc::lint::{EarlyContext, LintContext, LintPass, EarlyLintPass,
|
||||
EarlyLintPassObject, LintArray};
|
||||
use rustc::plugin::Registry;
|
||||
use syntax::ast;
|
||||
|
||||
declare_lint!(TEST_LINT, Warn, "Warn about items named 'lintme'");
|
||||
|
||||
struct Pass;
|
||||
|
||||
@ -184,9 +196,11 @@ impl LintPass for Pass {
|
||||
fn get_lints(&self) -> LintArray {
|
||||
lint_array!(TEST_LINT)
|
||||
}
|
||||
}
|
||||
|
||||
fn check_item(&mut self, cx: &Context, it: &ast::Item) {
|
||||
if it.ident.name == "lintme" {
|
||||
impl EarlyLintPass for Pass {
|
||||
fn check_item(&mut self, cx: &EarlyContext, it: &ast::Item) {
|
||||
if it.ident.name.as_str() == "lintme" {
|
||||
cx.span_lint(TEST_LINT, it.span, "item is named 'lintme'");
|
||||
}
|
||||
}
|
||||
@ -194,7 +208,7 @@ impl LintPass for Pass {
|
||||
|
||||
#[plugin_registrar]
|
||||
pub fn plugin_registrar(reg: &mut Registry) {
|
||||
reg.register_lint_pass(box Pass as LintPassObject);
|
||||
reg.register_early_lint_pass(box Pass as EarlyLintPassObject);
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -26,8 +26,8 @@ to help us make sense of code that can possibly be concurrent.
|
||||
### `Send`
|
||||
|
||||
The first trait we're going to talk about is
|
||||
[`Send`](../std/marker/trait.Send.html). When a type `T` implements `Send`, it indicates
|
||||
to the compiler that something of this type is able to have ownership transferred
|
||||
[`Send`](../std/marker/trait.Send.html). When a type `T` implements `Send`, it
|
||||
indicates that something of this type is able to have ownership transferred
|
||||
safely between threads.
|
||||
|
||||
This is important to enforce certain restrictions. For example, if we have a
|
||||
@ -35,20 +35,28 @@ channel connecting two threads, we would want to be able to send some data
|
||||
down the channel and to the other thread. Therefore, we'd ensure that `Send` was
|
||||
implemented for that type.
|
||||
|
||||
In the opposite way, if we were wrapping a library with FFI that isn't
|
||||
In the opposite way, if we were wrapping a library with [FFI][ffi] that isn't
|
||||
threadsafe, we wouldn't want to implement `Send`, and so the compiler will help
|
||||
us enforce that it can't leave the current thread.
|
||||
|
||||
[ffi]: ffi.html
|
||||
|
||||
### `Sync`
|
||||
|
||||
The second of these traits is called [`Sync`](../std/marker/trait.Sync.html).
|
||||
When a type `T` implements `Sync`, it indicates to the compiler that something
|
||||
When a type `T` implements `Sync`, it indicates that something
|
||||
of this type has no possibility of introducing memory unsafety when used from
|
||||
multiple threads concurrently.
|
||||
multiple threads concurrently through shared references. This implies that
|
||||
types which don't have [interior mutability](mutability.html) are inherently
|
||||
`Sync`, which includes simple primitive types (like `u8`) and aggregate types
|
||||
containing them.
|
||||
|
||||
For example, sharing immutable data with an atomic reference count is
|
||||
threadsafe. Rust provides a type like this, `Arc<T>`, and it implements `Sync`,
|
||||
so it is safe to share between threads.
|
||||
For sharing references across threads, Rust provides a wrapper type called
|
||||
`Arc<T>`. `Arc<T>` implements `Send` and `Sync` if and only if `T` implements
|
||||
both `Send` and `Sync`. For example, an object of type `Arc<RefCell<U>>` cannot
|
||||
be transferred across threads because
|
||||
[`RefCell`](choosing-your-guarantees.html#refcellt) does not implement
|
||||
`Sync`, consequently `Arc<RefCell<U>>` would not implement `Send`.
|
||||
|
||||
These two traits allow you to use the type system to make strong guarantees
|
||||
about the properties of your code under concurrency. Before we demonstrate
|
||||
@ -70,7 +78,7 @@ fn main() {
|
||||
}
|
||||
```
|
||||
|
||||
The `thread::spawn()` method accepts a closure, which is executed in a
|
||||
The `thread::spawn()` method accepts a [closure](closures.html), which is executed in a
|
||||
new thread. It returns a handle to the thread, that can be used to
|
||||
wait for the child thread to finish and extract its result:
|
||||
|
||||
@ -142,7 +150,7 @@ owners!
|
||||
So, we need some type that lets us have more than one reference to a value and
|
||||
that we can share between threads, that is it must implement `Sync`.
|
||||
|
||||
We'll use `Arc<T>`, rust's standard atomic reference count type, which
|
||||
We'll use `Arc<T>`, Rust's standard atomic reference count type, which
|
||||
wraps a value up with some extra runtime bookkeeping which allows us to
|
||||
share the ownership of the value between multiple references at the same time.
|
||||
|
||||
@ -189,7 +197,7 @@ our value if it's immutable, but we want to be able to mutate it, so we need
|
||||
something else to persuade the borrow checker we know what we're doing.
|
||||
|
||||
It looks like we need some type that allows us to safely mutate a shared value,
|
||||
for example a type that that can ensure only one thread at a time is able to
|
||||
for example a type that can ensure only one thread at a time is able to
|
||||
mutate the value inside it at any one time.
|
||||
|
||||
For that, we can use the `Mutex<T>` type!
|
||||
@ -215,29 +223,18 @@ fn main() {
|
||||
}
|
||||
```
|
||||
|
||||
Note that the value of `i` is bound (copied) to the closure and not shared
|
||||
among the threads.
|
||||
|
||||
If we'd tried to use `Mutex<T>` without wrapping it in an `Arc<T>` we would have
|
||||
seen another error like:
|
||||
|
||||
```text
|
||||
error: the trait `core::marker::Send` is not implemented for the type `std::sync::mutex::MutexGuard<'_, collections::vec::Vec<u32>>` [E0277]
|
||||
thread::spawn(move || {
|
||||
^~~~~~~~~~~~~
|
||||
note: `std::sync::mutex::MutexGuard<'_, collections::vec::Vec<u32>>` cannot be sent between threads safely
|
||||
thread::spawn(move || {
|
||||
^~~~~~~~~~~~~
|
||||
```
|
||||
|
||||
You see, [`Mutex`](../std/sync/struct.Mutex.html) has a
|
||||
[`lock`](../std/sync/struct.Mutex.html#method.lock)
|
||||
method which has this signature:
|
||||
Also note that [`lock`](../std/sync/struct.Mutex.html#method.lock) method of
|
||||
[`Mutex`](../std/sync/struct.Mutex.html) has this signature:
|
||||
|
||||
```ignore
|
||||
fn lock(&self) -> LockResult<MutexGuard<T>>
|
||||
```
|
||||
|
||||
and because `Send` is not implemented for `MutexGuard<T>`, we couldn't have
|
||||
transferred the guard across thread boundaries on it's own.
|
||||
and because `Send` is not implemented for `MutexGuard<T>`, the guard cannot
|
||||
cross thread boundaries, ensuring thread-locality of lock acquire and release.
|
||||
|
||||
Let's examine the body of the thread more closely:
|
||||
|
||||
@ -317,22 +314,24 @@ use std::sync::mpsc;
|
||||
fn main() {
|
||||
let (tx, rx) = mpsc::channel();
|
||||
|
||||
for _ in 0..10 {
|
||||
for i in 0..10 {
|
||||
let tx = tx.clone();
|
||||
|
||||
thread::spawn(move || {
|
||||
let answer = 42;
|
||||
let answer = i * i;
|
||||
|
||||
tx.send(answer);
|
||||
});
|
||||
}
|
||||
|
||||
rx.recv().ok().expect("Could not receive answer");
|
||||
for _ in 0..10 {
|
||||
println!("{}", rx.recv().unwrap());
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
A `u32` is `Send` because we can make a copy. So we create a thread, ask it to calculate
|
||||
the answer, and then it `send()`s us the answer over the channel.
|
||||
Here we create 10 threads, asking each to calculate the square of a number (`i`
|
||||
at the time of `spawn()`), and then `send()` back the answer over the channel.
|
||||
|
||||
|
||||
## Panics
|
||||
|
@ -34,7 +34,7 @@ These can nest arbitrarily:
|
||||
As for how to enable or disable these switches, if you’re using Cargo,
|
||||
they get set in the [`[features]` section][features] of your `Cargo.toml`:
|
||||
|
||||
[features]: http://doc.crates.io/manifest.html#the-%5Bfeatures%5D-section
|
||||
[features]: http://doc.crates.io/manifest.html#the-features-section
|
||||
|
||||
```toml
|
||||
[features]
|
||||
|
@ -563,8 +563,8 @@ What's going on here?
|
||||
First, both `extern crate` and `use` allow renaming the thing that is being
|
||||
imported. So the crate is still called "phrases", but here we will refer
|
||||
to it as "sayings". Similarly, the first `use` statement pulls in the
|
||||
`japanese::farewells` module from the crate, but makes it available as
|
||||
`jp_farewells` as opposed to simply `farewells`. This can help to avoid
|
||||
`japanese::greetings` module from the crate, but makes it available as
|
||||
`ja_greetings` as opposed to simply `greetings`. This can help to avoid
|
||||
ambiguity when importing similarly-named items from different places.
|
||||
|
||||
The second `use` statement uses a star glob to bring in _all_ symbols from the
|
||||
@ -576,11 +576,13 @@ The third `use` statement bears more explanation. It's using "brace expansion"
|
||||
globbing to compress three `use` statements into one (this sort of syntax
|
||||
may be familiar if you've written Linux shell scripts before). The
|
||||
uncompressed form of this statement would be:
|
||||
|
||||
```rust,ignore
|
||||
use sayings::english;
|
||||
use sayings::english::greetings as en_greetings;
|
||||
use sayings::english::farewells as en_farewells;
|
||||
```
|
||||
|
||||
As you can see, the curly brackets compress `use` statements for several items
|
||||
under the same path, and in this context `self` just refers back to that path.
|
||||
Note: The curly brackets cannot be nested or mixed with star globbing.
|
||||
|
170
src/doc/trpl/custom-allocators.md
Normal file
170
src/doc/trpl/custom-allocators.md
Normal file
@ -0,0 +1,170 @@
|
||||
% Custom Allocators
|
||||
|
||||
Allocating memory isn't always the easiest thing to do, and while Rust generally
|
||||
takes care of this by default it often becomes necessary to customize how
|
||||
allocation occurs. The compiler and standard library currently allow switching
|
||||
out the default global allocator in use at compile time. The design is currently
|
||||
spelled out in [RFC 1183][rfc] but this will walk you through how to get your
|
||||
own allocator up and running.
|
||||
|
||||
[rfc]: https://github.com/rust-lang/rfcs/blob/master/text/1183-swap-out-jemalloc.md
|
||||
|
||||
# Default Allocator
|
||||
|
||||
The compiler currently ships two default allocators: `alloc_system` and
|
||||
`alloc_jemalloc` (some targets don't have jemalloc, however). These allocators
|
||||
are just normal Rust crates and contain an implementation of the routines to
|
||||
allocate and deallocate memory. The standard library is not compiled assuming
|
||||
either one, and the compiler will decide which allocator is in use at
|
||||
compile-time depending on the type of output artifact being produced.
|
||||
|
||||
Binaries generated by the compiler will use `alloc_jemalloc` by default (where
|
||||
available). In this situation the compiler "controls the world" in the sense of
|
||||
it has power over the final link. Primarily this means that the allocator
|
||||
decision can be left up the compiler.
|
||||
|
||||
Dynamic and static libraries, however, will use `alloc_system` by default. Here
|
||||
Rust is typically a 'guest' in another application or another world where it
|
||||
cannot authoritatively decide what allocator is in use. As a result it resorts
|
||||
back to the standard APIs (e.g. `malloc` and `free`) for acquiring and releasing
|
||||
memory.
|
||||
|
||||
# Switching Allocators
|
||||
|
||||
Although the compiler's default choices may work most of the time, it's often
|
||||
necessary to tweak certain aspects. Overriding the compiler's decision about
|
||||
which allocator is in use is done simply by linking to the desired allocator:
|
||||
|
||||
```rust,no_run
|
||||
#![feature(alloc_system)]
|
||||
|
||||
extern crate alloc_system;
|
||||
|
||||
fn main() {
|
||||
let a = Box::new(4); // allocates from the system allocator
|
||||
println!("{}", a);
|
||||
}
|
||||
```
|
||||
|
||||
In this example the binary generated will not link to jemalloc by default but
|
||||
instead use the system allocator. Conversely to generate a dynamic library which
|
||||
uses jemalloc by default one would write:
|
||||
|
||||
```rust,ignore
|
||||
#![feature(alloc_jemalloc)]
|
||||
#![crate_type = "dylib"]
|
||||
|
||||
extern crate alloc_jemalloc;
|
||||
|
||||
pub fn foo() {
|
||||
let a = Box::new(4); // allocates from jemalloc
|
||||
println!("{}", a);
|
||||
}
|
||||
# fn main() {}
|
||||
```
|
||||
|
||||
# Writing a custom allocator
|
||||
|
||||
Sometimes even the choices of jemalloc vs the system allocator aren't enough and
|
||||
an entirely new custom allocator is required. In this you'll write your own
|
||||
crate which implements the allocator API (e.g. the same as `alloc_system` or
|
||||
`alloc_jemalloc`). As an example, let's take a look at a simplified and
|
||||
annotated version of `alloc_system`
|
||||
|
||||
```rust,no_run
|
||||
# // only needed for rustdoc --test down below
|
||||
# #![feature(lang_items)]
|
||||
// The compiler needs to be instructed that this crate is an allocator in order
|
||||
// to realize that when this is linked in another allocator like jemalloc should
|
||||
// not be linked in
|
||||
#![feature(allocator)]
|
||||
#![allocator]
|
||||
|
||||
// Allocators are not allowed to depend on the standard library which in turn
|
||||
// requires an allocator in order to avoid circular dependencies. This crate,
|
||||
// however, can use all of libcore.
|
||||
#![feature(no_std)]
|
||||
#![no_std]
|
||||
|
||||
// Let's give a unique name to our custom allocator
|
||||
#![crate_name = "my_allocator"]
|
||||
#![crate_type = "rlib"]
|
||||
|
||||
// Our system allocator will use the in-tree libc crate for FFI bindings. Note
|
||||
// that currently the external (crates.io) libc cannot be used because it links
|
||||
// to the standard library (e.g. `#![no_std]` isn't stable yet), so that's why
|
||||
// this specifically requires the in-tree version.
|
||||
#![feature(libc)]
|
||||
extern crate libc;
|
||||
|
||||
// Listed below are the five allocation functions currently required by custom
|
||||
// allocators. Their signatures and symbol names are not currently typechecked
|
||||
// by the compiler, but this is a future extension and are required to match
|
||||
// what is found below.
|
||||
//
|
||||
// Note that the standard `malloc` and `realloc` functions do not provide a way
|
||||
// to communicate alignment so this implementation would need to be improved
|
||||
// with respect to alignment in that aspect.
|
||||
|
||||
#[no_mangle]
|
||||
pub extern fn __rust_allocate(size: usize, _align: usize) -> *mut u8 {
|
||||
unsafe { libc::malloc(size as libc::size_t) as *mut u8 }
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern fn __rust_deallocate(ptr: *mut u8, _old_size: usize, _align: usize) {
|
||||
unsafe { libc::free(ptr as *mut libc::c_void) }
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern fn __rust_reallocate(ptr: *mut u8, _old_size: usize, size: usize,
|
||||
_align: usize) -> *mut u8 {
|
||||
unsafe {
|
||||
libc::realloc(ptr as *mut libc::c_void, size as libc::size_t) as *mut u8
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern fn __rust_reallocate_inplace(_ptr: *mut u8, old_size: usize,
|
||||
_size: usize, _align: usize) -> usize {
|
||||
old_size // this api is not supported by libc
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern fn __rust_usable_size(size: usize, _align: usize) -> usize {
|
||||
size
|
||||
}
|
||||
|
||||
# // just needed to get rustdoc to test this
|
||||
# fn main() {}
|
||||
# #[lang = "panic_fmt"] fn panic_fmt() {}
|
||||
# #[lang = "eh_personality"] fn eh_personality() {}
|
||||
# #[lang = "eh_unwind_resume"] extern fn eh_unwind_resume() {}
|
||||
```
|
||||
|
||||
After we compile this crate, it can be used as follows:
|
||||
|
||||
```rust,ignore
|
||||
extern crate my_allocator;
|
||||
|
||||
fn main() {
|
||||
let a = Box::new(8); // allocates memory via our custom allocator crate
|
||||
println!("{}", a);
|
||||
}
|
||||
```
|
||||
|
||||
# Custom allocator limitations
|
||||
|
||||
There are a few restrictions when working with custom allocators which may cause
|
||||
compiler errors:
|
||||
|
||||
* Any one artifact may only be linked to at most one allocator. Binaries,
|
||||
dylibs, and staticlibs must link to exactly one allocator, and if none have
|
||||
been explicitly chosen the compiler will choose one. On the other hand rlibs
|
||||
do not need to link to an allocator (but still can).
|
||||
|
||||
* A consumer of an allocator is tagged with `#![needs_allocator]` (e.g. the
|
||||
`liballoc` crate currently) and an `#[allocator]` crate cannot transitively
|
||||
depend on a crate which needs an allocator (e.g. circular dependencies are not
|
||||
allowed). This basically means that allocators must restrict themselves to
|
||||
libcore currently.
|
@ -13,7 +13,7 @@ Hoare in 1985.
|
||||
> dining room, furnished with a circular table, surrounded by five chairs, each
|
||||
> labelled by the name of the philosopher who was to sit in it. They sat
|
||||
> anticlockwise around the table. To the left of each philosopher there was
|
||||
> laid a golden fork, and in the centre stood a large bowl of spaghetti, which
|
||||
> laid a golden fork, and in the center stood a large bowl of spaghetti, which
|
||||
> was constantly replenished. A philosopher was expected to spend most of
|
||||
> their time thinking; but when they felt hungry, they went to the dining
|
||||
> room, sat down in their own chair, picked up their own fork on their left,
|
||||
@ -45,7 +45,7 @@ Now, let’s imagine this sequence of events:
|
||||
6. ... ? All the forks are taken, but nobody can eat!
|
||||
|
||||
There are different ways to solve this problem. We’ll get to our solution in
|
||||
the tutorial itself. For now, let’s get started modelling the problem itself.
|
||||
the tutorial itself. For now, let’s get started modeling the problem itself.
|
||||
We’ll start with the philosophers:
|
||||
|
||||
```rust
|
||||
@ -434,7 +434,7 @@ ownership of the values it’s capturing. Primarily, the `p` variable of the
|
||||
|
||||
Inside the thread, all we do is call `eat()` on `p`. Also note that the call to `thread::spawn` lacks a trailing semicolon, making this an expression. This distinction is important, yielding the correct return value. For more details, read [Expressions vs. Statements][es].
|
||||
|
||||
[es]: functions.html#expressions-vs.-statements
|
||||
[es]: functions.html#expressions-vs-statements
|
||||
|
||||
```rust,ignore
|
||||
}).collect();
|
||||
@ -512,6 +512,7 @@ impl Philosopher {
|
||||
|
||||
fn eat(&self, table: &Table) {
|
||||
let _left = table.forks[self.left].lock().unwrap();
|
||||
thread::sleep_ms(150);
|
||||
let _right = table.forks[self.right].lock().unwrap();
|
||||
|
||||
println!("{} is eating.", self.name);
|
||||
@ -597,6 +598,7 @@ We now need to construct those `left` and `right` values, so we add them to
|
||||
```rust,ignore
|
||||
fn eat(&self, table: &Table) {
|
||||
let _left = table.forks[self.left].lock().unwrap();
|
||||
thread::sleep_ms(150);
|
||||
let _right = table.forks[self.right].lock().unwrap();
|
||||
|
||||
println!("{} is eating.", self.name);
|
||||
@ -607,11 +609,14 @@ fn eat(&self, table: &Table) {
|
||||
}
|
||||
```
|
||||
|
||||
We have two new lines. We’ve also added an argument, `table`. We access the
|
||||
We have three new lines. We’ve added an argument, `table`. We access the
|
||||
`Table`’s list of forks, and then use `self.left` and `self.right` to access
|
||||
the fork at that particular index. That gives us access to the `Mutex` at that
|
||||
index, and we call `lock()` on it. If the mutex is currently being accessed by
|
||||
someone else, we’ll block until it becomes available.
|
||||
someone else, we’ll block until it becomes available. We have also a call to
|
||||
`thread::sleep_ms` between the moment first fork is picked and the moment the
|
||||
second forked is picked, as the process of picking up the fork is not
|
||||
immediate.
|
||||
|
||||
The call to `lock()` might fail, and if it does, we want to crash. In this
|
||||
case, the error that could happen is that the mutex is [‘poisoned’][poison],
|
||||
@ -660,7 +665,9 @@ We need to pass in our `left` and `right` values to the constructors for our
|
||||
you look at the pattern, it’s all consistent until the very end. Monsieur
|
||||
Foucault should have `4, 0` as arguments, but instead, has `0, 4`. This is what
|
||||
prevents deadlock, actually: one of our philosophers is left handed! This is
|
||||
one way to solve the problem, and in my opinion, it’s the simplest.
|
||||
one way to solve the problem, and in my opinion, it’s the simplest. If you
|
||||
change the order of the parameters, you will be able to observe the deadlock
|
||||
taking place.
|
||||
|
||||
```rust,ignore
|
||||
let handles: Vec<_> = philosophers.into_iter().map(|p| {
|
||||
|
@ -45,7 +45,7 @@ Rust keeps track of these comments, and uses them when generating
|
||||
documentation. This is important when documenting things like enums:
|
||||
|
||||
```rust
|
||||
/// The `Option` type. See [the module level documentation](../) for more.
|
||||
/// The `Option` type. See [the module level documentation](index.html) for more.
|
||||
enum Option<T> {
|
||||
/// No value
|
||||
None,
|
||||
@ -57,7 +57,7 @@ enum Option<T> {
|
||||
The above works, but this does not:
|
||||
|
||||
```rust,ignore
|
||||
/// The `Option` type. See [the module level documentation](../) for more.
|
||||
/// The `Option` type. See [the module level documentation](index.html) for more.
|
||||
enum Option<T> {
|
||||
None, /// No value
|
||||
Some(T), /// Some value `T`
|
||||
@ -213,7 +213,7 @@ Let's discuss our sample example documentation:
|
||||
```
|
||||
|
||||
You'll notice that you don't need a `fn main()` or anything here. `rustdoc` will
|
||||
automatically add a main() wrapper around your code, and in the right place.
|
||||
automatically add a `main()` wrapper around your code, and in the right place.
|
||||
For example:
|
||||
|
||||
```rust
|
||||
@ -234,7 +234,7 @@ fn main() {
|
||||
}
|
||||
```
|
||||
|
||||
Here's the full algorithm rustdoc uses to postprocess examples:
|
||||
Here's the full algorithm rustdoc uses to preprocess examples:
|
||||
|
||||
1. Any leading `#![foo]` attributes are left intact as crate attributes.
|
||||
2. Some common `allow` attributes are inserted, including
|
||||
@ -269,7 +269,9 @@ documentation comment, I need to add a little function definition below
|
||||
it. At the same time, it's just there to satisfy the compiler, so hiding
|
||||
it makes the example more clear. You can use this technique to explain
|
||||
longer examples in detail, while still preserving the testability of your
|
||||
documentation. For example, this code:
|
||||
documentation.
|
||||
|
||||
For example, imagine that we wanted to document this code:
|
||||
|
||||
```rust
|
||||
let x = 5;
|
||||
@ -277,37 +279,11 @@ let y = 6;
|
||||
println!("{}", x + y);
|
||||
```
|
||||
|
||||
Here's an explanation, rendered:
|
||||
|
||||
First, we set `x` to five:
|
||||
|
||||
```rust
|
||||
let x = 5;
|
||||
# let y = 6;
|
||||
# println!("{}", x + y);
|
||||
```
|
||||
|
||||
Next, we set `y` to six:
|
||||
|
||||
```rust
|
||||
# let x = 5;
|
||||
let y = 6;
|
||||
# println!("{}", x + y);
|
||||
```
|
||||
|
||||
Finally, we print the sum of `x` and `y`:
|
||||
|
||||
```rust
|
||||
# let x = 5;
|
||||
# let y = 6;
|
||||
println!("{}", x + y);
|
||||
```
|
||||
|
||||
Here's the same explanation, in raw text:
|
||||
We might want the documentation to end up looking like this:
|
||||
|
||||
> First, we set `x` to five:
|
||||
>
|
||||
> ```text
|
||||
> ```rust
|
||||
> let x = 5;
|
||||
> # let y = 6;
|
||||
> # println!("{}", x + y);
|
||||
@ -315,7 +291,7 @@ Here's the same explanation, in raw text:
|
||||
>
|
||||
> Next, we set `y` to six:
|
||||
>
|
||||
> ```text
|
||||
> ```rust
|
||||
> # let x = 5;
|
||||
> let y = 6;
|
||||
> # println!("{}", x + y);
|
||||
@ -323,12 +299,42 @@ Here's the same explanation, in raw text:
|
||||
>
|
||||
> Finally, we print the sum of `x` and `y`:
|
||||
>
|
||||
> ```text
|
||||
> ```rust
|
||||
> # let x = 5;
|
||||
> # let y = 6;
|
||||
> println!("{}", x + y);
|
||||
> ```
|
||||
|
||||
To keep each code block testable, we want the whole program in each block, but
|
||||
we don't want the reader to see every line every time. Here's what we put in
|
||||
our source code:
|
||||
|
||||
```text
|
||||
First, we set `x` to five:
|
||||
|
||||
```text
|
||||
let x = 5;
|
||||
# let y = 6;
|
||||
# println!("{}", x + y);
|
||||
```
|
||||
|
||||
Next, we set `y` to six:
|
||||
|
||||
```text
|
||||
# let x = 5;
|
||||
let y = 6;
|
||||
# println!("{}", x + y);
|
||||
```
|
||||
|
||||
Finally, we print the sum of `x` and `y`:
|
||||
|
||||
```text
|
||||
# let x = 5;
|
||||
# let y = 6;
|
||||
println!("{}", x + y);
|
||||
```
|
||||
```
|
||||
|
||||
By repeating all parts of the example, you can ensure that your example still
|
||||
compiles, while only showing the parts that are relevant to that part of your
|
||||
explanation.
|
||||
@ -369,7 +375,7 @@ things, so they don’t show up in the output.
|
||||
|
||||
### Running documentation tests
|
||||
|
||||
To run the tests, either
|
||||
To run the tests, either:
|
||||
|
||||
```bash
|
||||
$ rustdoc --test path/to/my/crate/root.rs
|
||||
@ -494,7 +500,8 @@ This `%` line needs to be the very first line of the file.
|
||||
|
||||
## `doc` attributes
|
||||
|
||||
At a deeper level, documentation comments are sugar for documentation attributes:
|
||||
At a deeper level, documentation comments are syntactic sugar for documentation
|
||||
attributes:
|
||||
|
||||
```rust
|
||||
/// this
|
||||
@ -509,7 +516,7 @@ are the same, as are these:
|
||||
```rust
|
||||
//! this
|
||||
|
||||
#![doc="/// this"]
|
||||
#![doc="this"]
|
||||
```
|
||||
|
||||
You won't often see this attribute used for writing documentation, but it
|
||||
@ -525,7 +532,7 @@ extern crate foo;
|
||||
pub use foo::bar;
|
||||
```
|
||||
|
||||
This will create documentation for bar both inside the documentation for the
|
||||
This will create documentation for `bar` both inside the documentation for the
|
||||
crate `foo`, as well as the documentation for your crate. It will use the same
|
||||
documentation in both places.
|
||||
|
||||
@ -538,6 +545,38 @@ extern crate foo;
|
||||
pub use foo::bar;
|
||||
```
|
||||
|
||||
## Missing documentation
|
||||
|
||||
Sometimes you want to make sure that every single public thing in your project
|
||||
is documented, especially when you are working on a library. Rust allows you to
|
||||
to generate warnings or errors, when an item is missing documentation.
|
||||
To generate warnings you use `warn`:
|
||||
|
||||
```rust
|
||||
#![warn(missing_docs)]
|
||||
```
|
||||
|
||||
And to generate errors you use `deny`:
|
||||
|
||||
```rust,ignore
|
||||
#![deny(missing_docs)]
|
||||
```
|
||||
|
||||
There are cases where you want to disable these warnings/errors to explicitly
|
||||
leave something undocumented. This is done by using `allow`:
|
||||
|
||||
```rust
|
||||
#[allow(missing_docs)]
|
||||
struct Undocumented;
|
||||
```
|
||||
|
||||
You might even want to hide items from the documentation completely:
|
||||
|
||||
```rust
|
||||
#[doc(hidden)]
|
||||
struct Hidden;
|
||||
```
|
||||
|
||||
### Controlling HTML
|
||||
|
||||
You can control a few aspects of the HTML that `rustdoc` generates through the
|
||||
|
@ -87,6 +87,8 @@ thread '<main>' panicked at 'Invalid number: 11', src/bin/panic-simple.rs:5
|
||||
Here's another example that is slightly less contrived. A program that accepts
|
||||
an integer as an argument, doubles it and prints it.
|
||||
|
||||
<span id="code-unwrap-double"></span>
|
||||
|
||||
```rust,should_panic
|
||||
use std::env;
|
||||
|
||||
@ -120,10 +122,9 @@ It would be better if we just showed the code for unwrapping because it is so
|
||||
simple, but to do that, we will first need to explore the `Option` and `Result`
|
||||
types. Both of these types have a method called `unwrap` defined on them.
|
||||
|
||||
## The `Option` type
|
||||
### The `Option` type
|
||||
|
||||
The `Option` type is
|
||||
[defined in the standard library][1]:
|
||||
The `Option` type is [defined in the standard library][5]:
|
||||
|
||||
```rust
|
||||
enum Option<T> {
|
||||
@ -138,6 +139,8 @@ system is an important concept because it will cause the compiler to force the
|
||||
programmer to handle that absence. Let's take a look at an example that tries
|
||||
to find a character in a string:
|
||||
|
||||
<span id="code-option-ex-string-find"></span>
|
||||
|
||||
```rust
|
||||
// Searches `haystack` for the Unicode character `needle`. If one is found, the
|
||||
// byte offset of the character is returned. Otherwise, `None` is returned.
|
||||
@ -151,7 +154,7 @@ fn find(haystack: &str, needle: char) -> Option<usize> {
|
||||
}
|
||||
```
|
||||
|
||||
Notice that when this function finds a matching character, it doen't just
|
||||
Notice that when this function finds a matching character, it doesn't just
|
||||
return the `offset`. Instead, it returns `Some(offset)`. `Some` is a variant or
|
||||
a *value constructor* for the `Option` type. You can think of it as a function
|
||||
with the type `fn<T>(value: T) -> Option<T>`. Correspondingly, `None` is also a
|
||||
@ -179,10 +182,12 @@ analysis is the only way to get at the value stored inside an `Option<T>`. This
|
||||
means that you, as the programmer, must handle the case when an `Option<T>` is
|
||||
`None` instead of `Some(t)`.
|
||||
|
||||
But wait, what about `unwrap` used in [`unwrap-double`](#code-unwrap-double)?
|
||||
But wait, what about `unwrap`,which we used [`previously`](#code-unwrap-double)?
|
||||
There was no case analysis there! Instead, the case analysis was put inside the
|
||||
`unwrap` method for you. You could define it yourself if you want:
|
||||
|
||||
<span id="code-option-def-unwrap"></span>
|
||||
|
||||
```rust
|
||||
enum Option<T> {
|
||||
None,
|
||||
@ -206,7 +211,7 @@ that makes `unwrap` ergonomic to use. Unfortunately, that `panic!` means that
|
||||
|
||||
### Composing `Option<T>` values
|
||||
|
||||
In [`option-ex-string-find`](#code-option-ex-string-find-2)
|
||||
In an [example from before](#code-option-ex-string-find),
|
||||
we saw how to use `find` to discover the extension in a file name. Of course,
|
||||
not all file names have a `.` in them, so it's possible that the file name has
|
||||
no extension. This *possibility of absence* is encoded into the types using
|
||||
@ -220,7 +225,7 @@ sense to put it into a function:
|
||||
```rust
|
||||
# fn find(_: &str, _: char) -> Option<usize> { None }
|
||||
// Returns the extension of the given file name, where the extension is defined
|
||||
// as all characters proceding the first `.`.
|
||||
// as all characters proceeding the first `.`.
|
||||
// If `file_name` has no `.`, then `None` is returned.
|
||||
fn extension_explicit(file_name: &str) -> Option<&str> {
|
||||
match find(file_name, '.') {
|
||||
@ -248,6 +253,8 @@ option is `None`, in which case, just return `None`.
|
||||
Rust has parametric polymorphism, so it is very easy to define a combinator
|
||||
that abstracts this pattern:
|
||||
|
||||
<span id="code-option-map"></span>
|
||||
|
||||
```rust
|
||||
fn map<F, T, A>(option: Option<T>, f: F) -> Option<A> where F: FnOnce(T) -> A {
|
||||
match option {
|
||||
@ -265,18 +272,18 @@ to get rid of the case analysis:
|
||||
```rust
|
||||
# fn find(_: &str, _: char) -> Option<usize> { None }
|
||||
// Returns the extension of the given file name, where the extension is defined
|
||||
// as all characters proceding the first `.`.
|
||||
// as all characters proceeding the first `.`.
|
||||
// If `file_name` has no `.`, then `None` is returned.
|
||||
fn extension(file_name: &str) -> Option<&str> {
|
||||
find(file_name, '.').map(|i| &file_name[i+1..])
|
||||
}
|
||||
```
|
||||
|
||||
One other pattern that we find is very common is assigning a default value to
|
||||
the case when an `Option` value is `None`. For example, maybe your program
|
||||
assumes that the extension of a file is `rs` even if none is present. As you
|
||||
might imagine, the case analysis for this is not specific to file
|
||||
extensions - it can work with any `Option<T>`:
|
||||
One other pattern we commonly find is assigning a default value to the case
|
||||
when an `Option` value is `None`. For example, maybe your program assumes that
|
||||
the extension of a file is `rs` even if none is present. As you might imagine,
|
||||
the case analysis for this is not specific to file extensions - it can work
|
||||
with any `Option<T>`:
|
||||
|
||||
```rust
|
||||
fn unwrap_or<T>(option: Option<T>, default: T) -> T {
|
||||
@ -387,6 +394,8 @@ remove choices because they will panic if `Option<T>` is `None`.
|
||||
The `Result` type is also
|
||||
[defined in the standard library][6]:
|
||||
|
||||
<span id="code-result-def"></span>
|
||||
|
||||
```rust
|
||||
enum Result<T, E> {
|
||||
Ok(T),
|
||||
@ -553,7 +562,7 @@ combinators that affect only the error type, such as
|
||||
### The `Result` type alias idiom
|
||||
|
||||
In the standard library, you may frequently see types like
|
||||
`Result<i32>`. But wait, [we defined `Result`](#code-result-def-1) to
|
||||
`Result<i32>`. But wait, [we defined `Result`](#code-result-def) to
|
||||
have two type parameters. How can we get away with only specifying
|
||||
one? The key is to define a `Result` type alias that *fixes* one of
|
||||
the type parameters to a particular type. Usually the fixed type is
|
||||
@ -663,6 +672,8 @@ with both an `Option` and a `Result`, the solution is *usually* to convert the
|
||||
(from `env::args()`) means the user didn't invoke the program correctly. We
|
||||
could just use a `String` to describe the error. Let's try:
|
||||
|
||||
<span id="code-error-double-string"></span>
|
||||
|
||||
```rust
|
||||
use std::env;
|
||||
|
||||
@ -744,7 +755,7 @@ fn main() {
|
||||
(N.B. The `AsRef<Path>` is used because those are the
|
||||
[same bounds used on
|
||||
`std::fs::File::open`](../std/fs/struct.File.html#method.open).
|
||||
This makes it ergnomic to use any kind of string as a file path.)
|
||||
This makes it ergonomic to use any kind of string as a file path.)
|
||||
|
||||
There are three different errors that can occur here:
|
||||
|
||||
@ -829,7 +840,7 @@ example, the very last call to `map` multiplies the `Ok(...)` value (which is
|
||||
an `i32`) by `2`. If an error had occurred before that point, this operation
|
||||
would have been skipped because of how `map` is defined.
|
||||
|
||||
`map_err` is the trick the makes all of this work. `map_err` is just like
|
||||
`map_err` is the trick that makes all of this work. `map_err` is just like
|
||||
`map`, except it applies a function to the `Err(...)` value of a `Result`. In
|
||||
this case, we want to convert all of our errors to one type: `String`. Since
|
||||
both `io::Error` and `num::ParseIntError` implement `ToString`, we can call the
|
||||
@ -895,6 +906,8 @@ seen above.
|
||||
|
||||
Here is a simplified definition of a `try!` macro:
|
||||
|
||||
<span id="code-try-def-simple"></span>
|
||||
|
||||
```rust
|
||||
macro_rules! try {
|
||||
($e:expr) => (match $e {
|
||||
@ -1155,6 +1168,8 @@ The `std::convert::From` trait is
|
||||
[defined in the standard
|
||||
library](../std/convert/trait.From.html):
|
||||
|
||||
<span id="code-from-def"></span>
|
||||
|
||||
```rust
|
||||
trait From<T> {
|
||||
fn from(T) -> Self;
|
||||
@ -1208,7 +1223,7 @@ let err2: Box<Error> = From::from(parse_err);
|
||||
|
||||
There is a really important pattern to recognize here. Both `err1` and `err2`
|
||||
have the *same type*. This is because they are existentially quantified types,
|
||||
or trait objects. In particularly, their underlying type is *erased* from the
|
||||
or trait objects. In particular, their underlying type is *erased* from the
|
||||
compiler's knowledge, so it truly sees `err1` and `err2` as exactly the same.
|
||||
Additionally, we constructed `err1` and `err2` using precisely the same
|
||||
function call: `From::from`. This is because `From::from` is overloaded on both
|
||||
@ -1232,9 +1247,11 @@ macro_rules! try {
|
||||
}
|
||||
```
|
||||
|
||||
This is not it's real definition. It's real definition is
|
||||
This is not its real definition. Its real definition is
|
||||
[in the standard library](../std/macro.try!.html):
|
||||
|
||||
<span id="code-try-def"></span>
|
||||
|
||||
```rust
|
||||
macro_rules! try {
|
||||
($e:expr) => (match $e {
|
||||
@ -1267,7 +1284,7 @@ fn file_double<P: AsRef<Path>>(file_path: P) -> Result<i32, String> {
|
||||
|
||||
Earlier, we promised that we could get rid of the `map_err` calls. Indeed, all
|
||||
we have to do is pick a type that `From` works with. As we saw in the previous
|
||||
section, `From` has an impl that let's it convert any error type into a
|
||||
section, `From` has an impl that lets it convert any error type into a
|
||||
`Box<Error>`:
|
||||
|
||||
```rust
|
||||
@ -1498,7 +1515,7 @@ and [`rustc-serialize`](https://crates.io/crates/rustc-serialize) crates.
|
||||
|
||||
We're not going to spend a lot of time on setting up a project with
|
||||
Cargo because it is already covered well in [the Cargo
|
||||
chapter](../book/hello-cargo) and [Cargo's documentation][14].
|
||||
chapter](../book/hello-cargo.html) and [Cargo's documentation][14].
|
||||
|
||||
To get started from scratch, run `cargo new --bin city-pop` and make sure your
|
||||
`Cargo.toml` looks something like this:
|
||||
@ -1528,14 +1545,14 @@ cargo build --release
|
||||
|
||||
## Argument parsing
|
||||
|
||||
Let's get argument parsing out of the way. we won't go into too much
|
||||
Let's get argument parsing out of the way. We won't go into too much
|
||||
detail on Getopts, but there is [some good documentation][15]
|
||||
describing it. The short story is that Getopts generates an argument
|
||||
parser and a help message from a vector of options (The fact that it
|
||||
is a vector is hidden behind a struct and a set of methods). Once the
|
||||
parsing is done, we can decode the program arguments into a Rust
|
||||
struct. From there, we can get information about the flags, for
|
||||
instance, wether they were passed in, and what arguments they
|
||||
instance, whether they were passed in, and what arguments they
|
||||
had. Here's our program with the appropriate `extern crate`
|
||||
statements, and the basic argument setup for Getopts:
|
||||
|
||||
@ -1577,7 +1594,7 @@ then store the first one, knowing that it is our program's name. Once
|
||||
that's done, we set up our argument flags, in this case a simplistic
|
||||
help message flag. Once we have the argument flags set up, we use
|
||||
`Options.parse` to parse the argument vector (starting from index one,
|
||||
becouse index 0 is the program name). If this was successful, we
|
||||
because index 0 is the program name). If this was successful, we
|
||||
assign matches to the parsed object, if not, we panic. Once past that,
|
||||
we test if the user passed in the help flag, and if so print the usage
|
||||
message. The option help messages are constructed by Getopts, so all
|
||||
@ -1838,7 +1855,7 @@ In our program, we accept a single file for input and do one pass over the
|
||||
data. This means we probably should be able to accept input on stdin. But maybe
|
||||
we like the current format too—so let's have both!
|
||||
|
||||
Adding support for stdin is actually quite easy. There are only two things we
|
||||
Adding support for stdin is actually quite easy. There are only three things we
|
||||
have to do:
|
||||
|
||||
1. Tweak the program arguments so that a single parameter—the
|
||||
@ -1879,9 +1896,9 @@ for pop in search(&data_file, &city) {
|
||||
...
|
||||
```
|
||||
|
||||
In this peice of code, we take `file` (which has the type
|
||||
In this piece of code, we take `file` (which has the type
|
||||
`Option<String>`), and convert it to a type that `search` can use, in
|
||||
this case, `&Option<AsRef<Path>>`. Do do this, we take a reference of
|
||||
this case, `&Option<AsRef<Path>>`. To do this, we take a reference of
|
||||
file, and map `Path::new` onto it. In this case, `as_ref()` converts
|
||||
the `Option<String>` into an `Option<&str>`, and from there, we can
|
||||
execute `Path::new` to the content of the optional, and return the
|
||||
@ -2040,14 +2057,14 @@ so. This can be a little clumsy, especially if you intend for the program to
|
||||
be used in shell scripts.
|
||||
|
||||
So let's start by adding the flags. Like before, we need to tweak the usage
|
||||
string and add a flag to the Option variable. Once were done that, Getopts does the rest:
|
||||
string and add a flag to the Option variable. Once we've done that, Getopts does the rest:
|
||||
|
||||
```rust,ignore
|
||||
...
|
||||
let mut opts = Options::new();
|
||||
opts.optopt("f", "file", "Choose an input file, instead of using STDIN.", "NAME");
|
||||
opts.optflag("h", "help", "Show this usage message.");
|
||||
opts.optflag("q", "quit", "Silences errors and warnings.");
|
||||
opts.optflag("q", "quiet", "Silences errors and warnings.");
|
||||
...
|
||||
```
|
||||
|
||||
@ -2103,7 +2120,7 @@ heuristics!
|
||||
and
|
||||
[`Error`](../std/error/trait.Error.html)
|
||||
impls to make the [`try!`](../std/macro.try!.html)
|
||||
macro more ergnomic.
|
||||
macro more ergonomic.
|
||||
* If you're writing a library and your code can produce errors, define your own
|
||||
error type and implement the
|
||||
[`std::error::Error`](../std/error/trait.Error.html)
|
||||
|
@ -1,5 +1,5 @@
|
||||
% Getting Started
|
||||
|
||||
This first section of the book will get you going with Rust and its tooling.
|
||||
This first section of the book will get us going with Rust and its tooling.
|
||||
First, we’ll install Rust. Then, the classic ‘Hello World’ program. Finally,
|
||||
we’ll talk about Cargo, Rust’s build system and package manager.
|
||||
|
@ -38,11 +38,19 @@ let z = (8, 2, 6);
|
||||
|
||||
In the example above `x` and `y` have arity 2. `z` has arity 3.
|
||||
|
||||
### Bounds
|
||||
|
||||
Bounds are constraints on a type or [trait][traits]. For example, if a bound
|
||||
is placed on the argument a function takes, types passed to that function
|
||||
must abide by that constraint.
|
||||
|
||||
[traits]: traits.html
|
||||
|
||||
### DST (Dynamically Sized Type)
|
||||
|
||||
A type without a statically known size or alignment. ([more info][link])
|
||||
|
||||
[link]: ../nomicon/exotic-sizes.html#dynamically-sized-types-(dsts)
|
||||
[link]: ../nomicon/exotic-sizes.html#dynamically-sized-types-dsts
|
||||
|
||||
### Expression
|
||||
|
||||
|
@ -99,9 +99,12 @@ use std::io;
|
||||
We’ll need to take user input, and then print the result as output. As such, we
|
||||
need the `io` library from the standard library. Rust only imports a few things
|
||||
by default into every program, [the ‘prelude’][prelude]. If it’s not in the
|
||||
prelude, you’ll have to `use` it directly.
|
||||
prelude, you’ll have to `use` it directly. There is also a second ‘prelude’, the
|
||||
[`io` prelude][ioprelude], which serves a similar function: you import it, and it
|
||||
imports a number of useful, `io`-related things.
|
||||
|
||||
[prelude]: ../std/prelude/index.html
|
||||
[ioprelude]: ../std/io/prelude/index.html
|
||||
|
||||
```rust,ignore
|
||||
fn main() {
|
||||
@ -147,7 +150,7 @@ a few tricks up their sleeves.
|
||||
|
||||
For example, they’re [immutable][immutable] by default. That’s why our example
|
||||
uses `mut`: it makes a binding mutable, rather than immutable. `let` doesn’t
|
||||
take a name on the left hand side, it actually accepts a
|
||||
take a name on the left hand side of the assignment, it actually accepts a
|
||||
‘[pattern][patterns]’. We’ll use patterns later. It’s easy enough
|
||||
to use for now:
|
||||
|
||||
@ -599,7 +602,7 @@ With this definition, anything of type `Foo` can be either a
|
||||
`Foo::Bar` or a `Foo::Baz`. We use the `::` to indicate the
|
||||
namespace for a particular `enum` variant.
|
||||
|
||||
The [`Ordering`][ordering] enum has three possible variants: `Less`, `Equal`,
|
||||
The [`Ordering`][ordering] `enum` has three possible variants: `Less`, `Equal`,
|
||||
and `Greater`. The `match` statement takes a value of a type, and lets you
|
||||
create an ‘arm’ for each possible value. Since we have three types of
|
||||
`Ordering`, we have three arms:
|
||||
@ -918,9 +921,9 @@ let guess: u32 = match guess.trim().parse() {
|
||||
|
||||
This is how you generally move from ‘crash on error’ to ‘actually handle the
|
||||
error’, by switching from `ok().expect()` to a `match` statement. The `Result`
|
||||
returned by `parse()` is an enum just like `Ordering`, but in this case, each
|
||||
returned by `parse()` is an `enum` just like `Ordering`, but in this case, each
|
||||
variant has some data associated with it: `Ok` is a success, and `Err` is a
|
||||
failure. Each contains more information: the successful parsed integer, or an
|
||||
failure. Each contains more information: the successfully parsed integer, or an
|
||||
error type. In this case, we `match` on `Ok(num)`, which sets the inner value
|
||||
of the `Ok` to the name `num`, and then we just return it on the right-hand
|
||||
side. In the `Err` case, we don’t care what kind of error it is, so we just
|
||||
|
@ -7,15 +7,16 @@ so it is assumed that Rust projects will use Cargo from the beginning.
|
||||
|
||||
[cratesio]: http://doc.crates.io
|
||||
|
||||
Cargo manages three things: building your code, downloading the dependencies
|
||||
your code needs, and building those dependencies. At first, your program doesn’t
|
||||
have any dependencies, so we’ll only be using the first part of its
|
||||
functionality. Eventually, we’ll add more. Since we started off by using Cargo,
|
||||
it'll be easy to add later.
|
||||
Cargo manages three things: building our code, downloading the dependencies our
|
||||
code needs, and building those dependencies. At first, our program doesn’t have
|
||||
any dependencies, so we’ll only be using the first part of its functionality.
|
||||
Eventually, we’ll add more. Since we started off by using Cargo, it'll be easy
|
||||
to add later.
|
||||
|
||||
If we installed Rust via the official installers we will also have Cargo. If we
|
||||
installed Rust some other way, we may want to [check the Cargo
|
||||
README][cargoreadme] for specific instructions about installing it.
|
||||
If you installed Rust via the official installers you will also have Cargo. If
|
||||
you installed Rust some other way, you may want to
|
||||
[check the Cargo README][cargoreadme] for specific instructions about installing
|
||||
it.
|
||||
|
||||
[cargoreadme]: https://github.com/rust-lang/cargo#installing-cargo-from-nightlies
|
||||
|
||||
@ -30,29 +31,29 @@ old executable (`main.exe` on Windows, `main` everywhere else). Let's do that pa
|
||||
```bash
|
||||
$ mkdir src
|
||||
$ mv main.rs src/main.rs
|
||||
$ rm main # or main.exe on Windows
|
||||
$ rm main # or 'rm main.exe' on Windows
|
||||
```
|
||||
|
||||
Note that since we're creating an executable, we retain `main.rs` as the source
|
||||
filename. If we want to make a library instead, we should use `lib.rs`. This
|
||||
convention is used by Cargo to successfully compile our projects, but it can be
|
||||
overridden if we wish. Custom file locations for the entry point can be
|
||||
specified with a [`[lib]` or `[[bin]]`][crates-custom] key in the TOML file.
|
||||
> Note: since we're creating an executable, we retain `main.rs` as the source
|
||||
> filename. If we want to make a library instead, we should use `lib.rs`. This
|
||||
> convention is used by Cargo to successfully compile our projects, but it can
|
||||
> be overridden if we wish. Custom file locations for the entry point can be
|
||||
> specified with a [`[lib]` or `[[bin]]`][crates-custom] key in the TOML file.
|
||||
|
||||
[crates-custom]: http://doc.crates.io/manifest.html#configuring-a-target
|
||||
|
||||
Cargo expects your source files to live inside a `src` directory. That leaves
|
||||
the top level for other things, like READMEs, license information, and anything
|
||||
not related to your code. Cargo helps us keep our projects nice and tidy. A
|
||||
place for everything, and everything in its place.
|
||||
Cargo expects our source files to live inside a `src` directory. That leaves the
|
||||
top level for other things, like READMEs, license information, and anything not
|
||||
related to our code. Cargo helps us keep our projects nice and tidy. A place for
|
||||
everything, and everything in its place.
|
||||
|
||||
Next, our configuration file:
|
||||
|
||||
```bash
|
||||
$ editor Cargo.toml
|
||||
$ editor Cargo.toml # or 'notepad Cargo.toml' on Windows
|
||||
```
|
||||
|
||||
Make sure to get this name right: you need the capital `C`!
|
||||
Make sure to get this name right: we need the capital `C`!
|
||||
|
||||
Put this inside:
|
||||
|
||||
@ -109,8 +110,8 @@ about the future: when our project gets more complex, we need to do more
|
||||
things to get all of the parts to properly compile. With Cargo, as our project
|
||||
grows, we can just run `cargo build`, and it’ll work the right way.
|
||||
|
||||
When your project is finally ready for release, you can use
|
||||
`cargo build --release` to compile your project with optimizations.
|
||||
When our project is finally ready for release, we can use `cargo build
|
||||
--release` to compile our project with optimizations.
|
||||
|
||||
You'll also notice that Cargo has created a new file: `Cargo.lock`.
|
||||
|
||||
@ -120,14 +121,14 @@ name = "hello_world"
|
||||
version = "0.0.1"
|
||||
```
|
||||
|
||||
The `Cargo.lock` file is used by Cargo to keep track of dependencies in your application.
|
||||
Right now, we don’t have any, so it’s a bit sparse. You won't ever need
|
||||
to touch this file yourself, just let Cargo handle it.
|
||||
The `Cargo.lock` file is used by Cargo to keep track of dependencies in our
|
||||
application. Right now, we don’t have any, so it’s a bit sparse. We won't ever
|
||||
need to touch this file ourselves, just let Cargo handle it.
|
||||
|
||||
That’s it! We’ve successfully built `hello_world` with Cargo. Even though our
|
||||
program is simple, it’s using much of the real tooling that you’ll use for the
|
||||
rest of your Rust career. You can expect to do this to get started with
|
||||
virtually all Rust projects:
|
||||
program is simple, it’s using much of the real tooling that we’ll use for the
|
||||
rest of our Rust career. We can expect to do this to get started with virtually
|
||||
all Rust projects:
|
||||
|
||||
```bash
|
||||
$ git clone someurl.com/foo
|
||||
@ -137,17 +138,19 @@ $ cargo build
|
||||
|
||||
## A New Project
|
||||
|
||||
You don’t have to go through this whole process every time you want to start a
|
||||
new project! Cargo has the ability to make a bare-bones project directory in
|
||||
which you can start developing right away.
|
||||
We don’t have to go through this whole process every time we want to start a new
|
||||
project! Cargo has the ability to make a bare-bones project directory in which
|
||||
we can start developing right away.
|
||||
|
||||
To start a new project with Cargo, use `cargo new`:
|
||||
To start a new project with Cargo, we use `cargo new`:
|
||||
|
||||
```bash
|
||||
$ cargo new hello_world --bin
|
||||
```
|
||||
|
||||
We’re passing `--bin` because our goal is to get straight to making an executable application, as opposed to a library. Executables are often called ‘binaries.’ (as in `/usr/bin`, if you’re on a Unix system)
|
||||
We’re passing `--bin` because our goal is to get straight to making an
|
||||
executable application, as opposed to a library. Executables are often called
|
||||
‘binaries.’ (as in `/usr/bin`, if we’re on a Unix system)
|
||||
|
||||
Let's check out what Cargo has generated for us:
|
||||
|
||||
@ -162,7 +165,7 @@ $ tree .
|
||||
1 directory, 2 files
|
||||
```
|
||||
|
||||
If you don't have the `tree` command, you can probably get it from your
|
||||
If we don't have the `tree` command, we can probably get it from our
|
||||
distribution’s package manager. It’s not necessary, but it’s certainly useful.
|
||||
|
||||
This is all we need to get started. First, let’s check out `Cargo.toml`:
|
||||
@ -176,7 +179,7 @@ authors = ["Your Name <you@example.com>"]
|
||||
```
|
||||
|
||||
Cargo has populated this file with reasonable defaults based off the arguments
|
||||
you gave it and your `git` global configuration. You may notice that Cargo has
|
||||
we gave it and our `git` global configuration. You may notice that Cargo has
|
||||
also initialized the `hello_world` directory as a `git` repository.
|
||||
|
||||
Here’s what’s in `src/main.rs`:
|
||||
@ -187,20 +190,21 @@ fn main() {
|
||||
}
|
||||
```
|
||||
|
||||
Cargo has generated a "Hello World!" for us, and you’re ready to start coding! Cargo
|
||||
has its own [guide][guide] which covers Cargo’s features in much more depth.
|
||||
Cargo has generated a "Hello World!" for us, and we’re ready to start coding!
|
||||
Cargo has its own [guide][guide] which covers Cargo’s features in much more
|
||||
depth.
|
||||
|
||||
[guide]: http://doc.crates.io/guide.html
|
||||
|
||||
Now that you’ve got the tools down, let’s actually learn more about the Rust
|
||||
language itself. These are the basics that will serve you well through the rest
|
||||
of your time with Rust.
|
||||
Now that we’ve got the tools down, let’s actually learn more about the Rust
|
||||
language itself. These are the basics that will serve us well through the rest
|
||||
of our time with Rust.
|
||||
|
||||
You have two options: Dive into a project with ‘[Learn Rust][learnrust]’, or
|
||||
start from the bottom and work your way up with ‘[Syntax and
|
||||
Semantics][syntax]’. More experienced systems programmers will probably prefer
|
||||
‘Learn Rust’, while those from dynamic backgrounds may enjoy either. Different
|
||||
people learn differently! Choose whatever’s right for you.
|
||||
start from the bottom and work your way up with
|
||||
‘[Syntax and Semantics][syntax]’. More experienced systems programmers will
|
||||
probably prefer ‘Learn Rust’, while those from dynamic backgrounds may enjoy
|
||||
either. Different people learn differently! Choose whatever’s right for you.
|
||||
|
||||
[learnrust]: learn-rust.html
|
||||
[syntax]: syntax-and-semantics.html
|
||||
|
@ -1,25 +1,25 @@
|
||||
% Hello, world!
|
||||
|
||||
Now that you have Rust installed, let’s write your first Rust program. It’s
|
||||
traditional to make your first program in any new language one that prints the
|
||||
Now that we have Rust installed, let’s write our first Rust program. It’s
|
||||
traditional to make our first program in any new language one that prints the
|
||||
text “Hello, world!” to the screen. The nice thing about starting with such a
|
||||
simple program is that you can verify that your compiler isn’t just installed,
|
||||
but also working properly. And printing information to the screen is a pretty
|
||||
common thing to do.
|
||||
simple program is that we can verify that our compiler isn’t just installed, but
|
||||
also working properly. And printing information to the screen is a pretty common
|
||||
thing to do.
|
||||
|
||||
The first thing that we need to do is make a file to put our code in. I like
|
||||
to make a `projects` directory in my home directory, and keep all my projects
|
||||
there. Rust does not care where your code lives.
|
||||
The first thing that we need to do is make a file to put our code in. I like to
|
||||
make a `projects` directory in my home directory, and keep all my projects
|
||||
there. Rust doesn't care where our code lives.
|
||||
|
||||
This actually leads to one other concern we should address: this guide will
|
||||
assume that you have basic familiarity with the command line. Rust itself makes
|
||||
no specific demands on your editing tooling, or where your code lives. If you
|
||||
prefer an IDE to the command line, you may want to check out
|
||||
[SolidOak][solidoak], or wherever plugins are for your favorite IDE. There are
|
||||
a number of extensions of varying quality in development by the community. The
|
||||
Rust team also ships [plugins for various editors][plugins]. Configuring your
|
||||
assume that we have basic familiarity with the command line. Rust itself makes
|
||||
no specific demands on our editing tooling, or where our code lives. If we
|
||||
prefer an IDE to the command line, we may want to check out
|
||||
[SolidOak][solidoak], or wherever plugins are for our favorite IDE. There are a
|
||||
number of extensions of varying quality in development by the community. The
|
||||
Rust team also ships [plugins for various editors][plugins]. Configuring our
|
||||
editor or IDE is out of the scope of this tutorial, so check the documentation
|
||||
for your setup, specifically.
|
||||
for our setup, specifically.
|
||||
|
||||
[solidoak]: https://github.com/oakes/SolidOak
|
||||
[plugins]: https://github.com/rust-lang/rust/blob/master/src/etc/CONFIGS.md
|
||||
@ -33,14 +33,15 @@ $ mkdir hello_world
|
||||
$ cd hello_world
|
||||
```
|
||||
|
||||
If you’re on Windows and not using PowerShell, the `~` may not work. Consult
|
||||
the documentation for your shell for more details.
|
||||
If we’re on Windows and not using PowerShell, the `~` may not work. Consult the
|
||||
documentation for our shell for more details.
|
||||
|
||||
Let’s make a new source file next. We’ll call our file `main.rs`. Rust files
|
||||
always end in a `.rs` extension. If you’re using more than one word in your
|
||||
filename, use an underscore: `hello_world.rs` rather than `helloworld.rs`.
|
||||
always end in a `.rs` extension, and if we’re using more than one word in a
|
||||
Rust filename, we use an underscore: for example, `linked_list.rs`, not
|
||||
`linkedlist.rs` or `LinkedList.rs`.
|
||||
|
||||
Now that you’ve got your file open, type this in:
|
||||
Now that we’ve got our file open, type this in:
|
||||
|
||||
```rust
|
||||
fn main() {
|
||||
@ -48,7 +49,7 @@ fn main() {
|
||||
}
|
||||
```
|
||||
|
||||
Save the file, and then type this into your terminal window:
|
||||
Save the file, and then type this into our terminal window:
|
||||
|
||||
```bash
|
||||
$ rustc main.rs
|
||||
@ -72,9 +73,9 @@ we aren’t returning anything from this function, we can omit the return type
|
||||
entirely. We’ll get to it later.
|
||||
|
||||
You’ll also note that the function is wrapped in curly braces (`{` and `}`).
|
||||
Rust requires these around all function bodies. It is also considered good
|
||||
style to put the opening curly brace on the same line as the function
|
||||
declaration, with one space in between.
|
||||
Rust requires these around all function bodies. It is also considered good style
|
||||
to put the opening curly brace on the same line as the function declaration,
|
||||
with one space in between.
|
||||
|
||||
Next up is this line:
|
||||
|
||||
@ -85,29 +86,30 @@ Next up is this line:
|
||||
This line does all of the work in our little program. There are a number of
|
||||
details that are important here. The first is that it’s indented with four
|
||||
spaces, not tabs. Please configure your editor of choice to insert four spaces
|
||||
with the tab key. We provide some [sample configurations for various
|
||||
editors][configs].
|
||||
with the tab key. We provide some
|
||||
[sample configurations for various editors][configs].
|
||||
|
||||
[configs]: https://github.com/rust-lang/rust/tree/master/src/etc/CONFIGS.md
|
||||
|
||||
The second point is the `println!()` part. This is calling a Rust [macro][macro],
|
||||
which is how metaprogramming is done in Rust. If it were a function instead, it
|
||||
would look like this: `println()`. For our purposes, we don’t need to worry
|
||||
about this difference. Just know that sometimes, you’ll see a `!`, and that
|
||||
means that you’re calling a macro instead of a normal function. Rust implements
|
||||
`println!` as a macro rather than a function for good reasons, but that's an
|
||||
advanced topic. One last thing to mention: Rust’s macros are significantly
|
||||
different from C macros, if you’ve used those. Don’t be scared of using macros.
|
||||
We’ll get to the details eventually, you’ll just have to trust us for now.
|
||||
The second point is the `println!()` part. This is calling a Rust
|
||||
[macro][macro], which is how metaprogramming is done in Rust. If it were a
|
||||
function instead, it would look like this: `println()`. For our purposes, we
|
||||
don’t need to worry about this difference. Just know that sometimes, we’ll see a
|
||||
`!`, and that means that we’re calling a macro instead of a normal function.
|
||||
Rust implements `println!` as a macro rather than a function for good reasons,
|
||||
but that's an advanced topic. One last thing to mention: Rust’s macros are
|
||||
significantly different from C macros, if you’ve used those. Don’t be scared of
|
||||
using macros. We’ll get to the details eventually, you’ll just have to take it
|
||||
on trust for now.
|
||||
|
||||
[macro]: macros.html
|
||||
|
||||
Next, `"Hello, world!"` is a ‘string’. Strings are a surprisingly complicated
|
||||
topic in a systems programming language, and this is a ‘statically allocated’
|
||||
string. If you want to read further about allocation, check out
|
||||
[the stack and the heap][allocation], but you don’t need to right now if you
|
||||
don’t want to. We pass this string as an argument to `println!`, which prints the
|
||||
string to the screen. Easy enough!
|
||||
string. If you want to read further about allocation, check out [the stack and
|
||||
the heap][allocation], but you don’t need to right now if you don’t want to. We
|
||||
pass this string as an argument to `println!`, which prints the string to the
|
||||
screen. Easy enough!
|
||||
|
||||
[allocation]: the-stack-and-the-heap.html
|
||||
|
||||
@ -126,8 +128,8 @@ compiler, `rustc`, by passing it the name of our source file:
|
||||
$ rustc main.rs
|
||||
```
|
||||
|
||||
This is similar to `gcc` or `clang`, if you come from a C or C++ background. Rust
|
||||
will output a binary executable. You can see it with `ls`:
|
||||
This is similar to `gcc` or `clang`, if you come from a C or C++ background.
|
||||
Rust will output a binary executable. We can see it with `ls`:
|
||||
|
||||
```bash
|
||||
$ ls
|
||||
@ -142,7 +144,7 @@ main.exe main.rs
|
||||
```
|
||||
|
||||
There are now two files: our source code, with the `.rs` extension, and the
|
||||
executable (`main.exe` on Windows, `main` everywhere else)
|
||||
executable (`main.exe` on Windows, `main` everywhere else).
|
||||
|
||||
```bash
|
||||
$ ./main # or main.exe on Windows
|
||||
@ -150,20 +152,20 @@ $ ./main # or main.exe on Windows
|
||||
|
||||
This prints out our `Hello, world!` text to our terminal.
|
||||
|
||||
If you come from a dynamic language like Ruby, Python, or JavaScript,
|
||||
you may not be used to these two steps being separate. Rust is an
|
||||
‘ahead-of-time compiled language’, which means that you can compile a program,
|
||||
give it to someone else, and they don't need to have Rust installed. If you
|
||||
give someone a `.rb` or `.py` or `.js` file, they need to have a
|
||||
Ruby/Python/JavaScript implementation installed, but you just need one command
|
||||
to both compile and run your program. Everything is a tradeoff in language
|
||||
design, and Rust has made its choice.
|
||||
If you come from a dynamic language like Ruby, Python, or JavaScript, you may
|
||||
not be used to these two steps being separate. Rust is an ‘ahead-of-time
|
||||
compiled language’, which means that we can compile a program, give it to
|
||||
someone else, and they don't need to have Rust installed. If we give someone a
|
||||
`.rb` or `.py` or `.js` file, they need to have a Ruby/Python/JavaScript
|
||||
implementation installed, but we just need one command to both compile and run
|
||||
our program. Everything is a tradeoff in language design, and Rust has made its
|
||||
choice.
|
||||
|
||||
Congratulations! You have officially written a Rust program. That makes you a
|
||||
Rust programmer! Welcome. 🎊🎉👍
|
||||
|
||||
Next, I'd like to introduce you to another tool, Cargo, which is used to write
|
||||
real-world Rust programs. Just using `rustc` is nice for simple things, but as
|
||||
your project grows, you'll want something to help you manage all of the options
|
||||
that it has, and to make it easy to share your code with other people and
|
||||
our project grows, we'll want something to help us manage all of the options
|
||||
that it has, and to make it easy to share our code with other people and
|
||||
projects.
|
||||
|
@ -41,7 +41,7 @@ If a [pattern][patterns] matches successfully, it binds any appropriate parts of
|
||||
the value to the identifiers in the pattern, then evaluates the expression. If
|
||||
the pattern doesn’t match, nothing happens.
|
||||
|
||||
If you’d rather to do something else when the pattern does not match, you can
|
||||
If you want to do something else when the pattern does not match, you can
|
||||
use `else`:
|
||||
|
||||
```rust
|
||||
@ -65,7 +65,7 @@ loop as long as a value matches a certain pattern. It turns code like this:
|
||||
loop {
|
||||
match option {
|
||||
Some(x) => println!("{}", x),
|
||||
_ => break,
|
||||
None => break,
|
||||
}
|
||||
}
|
||||
```
|
||||
|
@ -1,21 +1,21 @@
|
||||
% Installing Rust
|
||||
|
||||
The first step to using Rust is to install it! There are a number of ways to
|
||||
install Rust, but the easiest is to use the `rustup` script. If you're on Linux
|
||||
or a Mac, all you need to do is this:
|
||||
install Rust, but the easiest is to use the `rustup` script. If we're on Linux
|
||||
or a Mac, all we need to do is this:
|
||||
|
||||
> Note: you don't need to type in the `$`s, they just indicate the start of
|
||||
> each command. You’ll see many tutorials and examples around the web that
|
||||
> follow this convention: `$` for commands run as your regular user, and
|
||||
> `#` for commands you should be running as an administrator.
|
||||
> Note: we don't need to type in the `$`s, they are there to indicate the start of
|
||||
> each command. We’ll see many tutorials and examples around the web that
|
||||
> follow this convention: `$` for commands run as our regular user, and `#` for
|
||||
> commands we should be running as an administrator.
|
||||
|
||||
```bash
|
||||
$ curl -sf -L https://static.rust-lang.org/rustup.sh | sh
|
||||
```
|
||||
|
||||
If you're concerned about the [potential insecurity][insecurity] of using `curl
|
||||
| sh`, please keep reading and see our disclaimer below. And feel free to
|
||||
use a two-step version of the installation and examine our installation script:
|
||||
If we're concerned about the [potential insecurity][insecurity] of using `curl |
|
||||
sh`, please keep reading and see our disclaimer below. And feel free to use a
|
||||
two-step version of the installation and examine our installation script:
|
||||
|
||||
```bash
|
||||
$ curl -f -L https://static.rust-lang.org/rustup.sh -O
|
||||
@ -25,11 +25,12 @@ $ sh rustup.sh
|
||||
[insecurity]: http://curlpipesh.tumblr.com
|
||||
|
||||
If you're on Windows, please download the appropriate [installer][install-page].
|
||||
**NOTE:** By default, the Windows installer will not add Rust to the %PATH%
|
||||
system variable. If this is the only version of Rust you are installing and you
|
||||
want to be able to run it from the command line, click on "Advanced" on the
|
||||
install dialog and on the "Product Features" page ensure "Add to PATH" is
|
||||
installed on the local hard drive.
|
||||
|
||||
> Note: By default, the Windows installer won't add Rust to the %PATH% system
|
||||
> variable. If this is the only version of Rust we are installing and we want to
|
||||
> be able to run it from the command line, click on "Advanced" on the install
|
||||
> dialog and on the "Product Features" page ensure "Add to PATH" is installed on
|
||||
> the local hard drive.
|
||||
|
||||
|
||||
[install-page]: https://www.rust-lang.org/install.html
|
||||
@ -37,78 +38,145 @@ installed on the local hard drive.
|
||||
## Uninstalling
|
||||
|
||||
If you decide you don't want Rust anymore, we'll be a bit sad, but that's okay.
|
||||
Not every programming language is great for everyone. Just run the uninstall
|
||||
script:
|
||||
Not every programming language is great for everyone. We can run the
|
||||
uninstall script:
|
||||
|
||||
```bash
|
||||
$ sudo /usr/local/lib/rustlib/uninstall.sh
|
||||
```
|
||||
|
||||
If you used the Windows installer, just re-run the `.msi` and it will give you
|
||||
an uninstall option.
|
||||
If we used the Windows installer, we can re-run the `.msi` and it will give
|
||||
us an uninstall option.
|
||||
|
||||
## That disclaimer we promised
|
||||
|
||||
Some people, and somewhat rightfully so, get very upset when we tell you to
|
||||
`curl | sh`. Basically, when you do this, you are trusting that the good
|
||||
people who maintain Rust aren't going to hack your computer and do bad things.
|
||||
That's a good instinct! If you're one of those people, please check out the
|
||||
documentation on [building Rust from Source][from-source], or [the official
|
||||
binary downloads][install-page].
|
||||
Some people, and somewhat rightfully so, get very upset when we tell them to
|
||||
`curl | sh`. Their concern is that `curl | sh` implicitly requires you to trust
|
||||
that the good people who maintain Rust aren't going to hack your computer and
|
||||
do bad things — and even having accepted that, there is still the possibility
|
||||
that the Rust website has been hacked and the `rustup` script compromised.
|
||||
|
||||
Being wary of such possibilities is a good instinct! If you're uncomfortable
|
||||
using `curl | sh` for reasons like these, please check out the documentation on
|
||||
[building Rust from Source][from-source], or
|
||||
[the official binary downloads][install-page].
|
||||
|
||||
[from-source]: https://github.com/rust-lang/rust#building-from-source
|
||||
|
||||
## Platform support
|
||||
|
||||
Oh, we should also mention the officially supported platforms:
|
||||
The Rust compiler runs on, and compiles to, a great number of platforms, though
|
||||
not all platforms are equally supported. Rust's support levels are organized
|
||||
into three tiers, each with a different set of guarantees.
|
||||
|
||||
* Windows (7, 8, Server 2008 R2)
|
||||
* Linux (2.6.18 or later, various distributions), x86 and x86-64
|
||||
* OSX 10.7 (Lion) or greater, x86 and x86-64
|
||||
Platforms are identified by their "target triple" which is the string to inform
|
||||
the compiler what kind of output should be produced. The columns below indicate
|
||||
whether the corresponding component works on the specified platform.
|
||||
|
||||
We extensively test Rust on these platforms, and a few others, too, like
|
||||
Android. But these are the ones most likely to work, as they have the most
|
||||
testing.
|
||||
### Tier 1
|
||||
|
||||
Finally, a comment about Windows. Rust considers Windows to be a first-class
|
||||
platform upon release, but if we're honest, the Windows experience isn't as
|
||||
integrated as the Linux/OS X experience is. We're working on it! If anything
|
||||
does not work, it is a bug. Please let us know if that happens. Each and every
|
||||
commit is tested against Windows just like any other platform.
|
||||
Tier 1 platforms can be thought of as "guaranteed to build and work".
|
||||
Specifically they will each satisfy the following requirements:
|
||||
|
||||
* Automated testing is set up to run tests for the platform.
|
||||
* Landing changes to the `rust-lang/rust` repository's master branch is gated on
|
||||
tests passing.
|
||||
* Official release artifacts are provided for the platform.
|
||||
* Documentation for how to use and how to build the platform is available.
|
||||
|
||||
| Target | std |rustc|cargo| notes |
|
||||
|-------------------------------|-----|-----|-----|----------------------------|
|
||||
| `x86_64-pc-windows-msvc` | ✓ | ✓ | ✓ | 64-bit MSVC (Windows 7+) |
|
||||
| `i686-pc-windows-gnu` | ✓ | ✓ | ✓ | 32-bit MinGW (Windows 7+) |
|
||||
| `x86_64-pc-windows-gnu` | ✓ | ✓ | ✓ | 64-bit MinGW (Windows 7+) |
|
||||
| `i686-apple-darwin` | ✓ | ✓ | ✓ | 32-bit OSX (10.7+, Lion+) |
|
||||
| `x86_64-apple-darwin` | ✓ | ✓ | ✓ | 64-bit OSX (10.7+, Lion+) |
|
||||
| `i686-unknown-linux-gnu` | ✓ | ✓ | ✓ | 32-bit Linux (2.6.18+) |
|
||||
| `x86_64-unknown-linux-gnu` | ✓ | ✓ | ✓ | 64-bit Linux (2.6.18+) |
|
||||
|
||||
### Tier 2
|
||||
|
||||
Tier 2 platforms can be thought of as "guaranteed to build". Automated tests are
|
||||
not run so it's not guaranteed to produce a working build, but platforms often
|
||||
work to quite a good degree and patches are always welcome! Specifically, these
|
||||
platforms are required to have each of the following:
|
||||
|
||||
* Automated building is set up, but may not be running tests.
|
||||
* Landing changes to the `rust-lang/rust` repository's master branch is gated on
|
||||
platforms **building**. Note that this means for some platforms only the
|
||||
standard library is compiled, but for others the full bootstrap is run.
|
||||
* Official release artifacts are provided for the platform.
|
||||
|
||||
| Target | std |rustc|cargo| notes |
|
||||
|-------------------------------|-----|-----|-----|----------------------------|
|
||||
| `i686-pc-windows-msvc` | ✓ | ✓ | ✓ | 32-bit MSVC (Windows 7+) |
|
||||
|
||||
### Tier 3
|
||||
|
||||
Tier 3 platforms are those which Rust has support for, but landing changes is
|
||||
not gated on the platform either building or passing tests. Working builds for
|
||||
these platforms may be spotty as their reliability is often defined in terms of
|
||||
community contributions. Additionally, release artifacts and installers are not
|
||||
provided, but there may be community infrastructure producing these in
|
||||
unofficial locations.
|
||||
|
||||
| Target | std |rustc|cargo| notes |
|
||||
|-------------------------------|-----|-----|-----|----------------------------|
|
||||
| `x86_64-unknown-linux-musl` | ✓ | | | 64-bit Linux with MUSL |
|
||||
| `arm-linux-androideabi` | ✓ | | | ARM Android |
|
||||
| `i686-linux-android` | ✓ | | | 32-bit x86 Android |
|
||||
| `aarch64-linux-android` | ✓ | | | ARM64 Android |
|
||||
| `arm-unknown-linux-gnueabi` | ✓ | ✓ | | ARM Linux (2.6.18+) |
|
||||
| `arm-unknown-linux-gnueabihf` | ✓ | ✓ | | ARM Linux (2.6.18+) |
|
||||
| `aarch64-unknown-linux-gnu` | ✓ | | | ARM64 Linux (2.6.18+) |
|
||||
| `mips-unknown-linux-gnu` | ✓ | | | MIPS Linux (2.6.18+) |
|
||||
| `mipsel-unknown-linux-gnu` | ✓ | | | MIPS (LE) Linux (2.6.18+) |
|
||||
| `powerpc-unknown-linux-gnu` | ✓ | | | PowerPC Linux (2.6.18+) |
|
||||
| `i386-apple-ios` | ✓ | | | 32-bit x86 iOS |
|
||||
| `x86_64-apple-ios` | ✓ | | | 64-bit x86 iOS |
|
||||
| `armv7-apple-ios` | ✓ | | | ARM iOS |
|
||||
| `armv7s-apple-ios` | ✓ | | | ARM iOS |
|
||||
| `aarch64-apple-ios` | ✓ | | | ARM64 iOS |
|
||||
| `i686-unknown-freebsd` | ✓ | ✓ | | 32-bit FreeBSD |
|
||||
| `x86_64-unknown-freebsd` | ✓ | ✓ | | 64-bit FreeBSD |
|
||||
| `x86_64-unknown-openbsd` | ✓ | ✓ | | 64-bit OpenBSD |
|
||||
| `x86_64-unknown-netbsd` | ✓ | ✓ | | 64-bit NetBSD |
|
||||
| `x86_64-unknown-bitrig` | ✓ | ✓ | | 64-bit Bitrig |
|
||||
| `x86_64-unknown-dragonfly` | ✓ | ✓ | | 64-bit DragonFlyBSD |
|
||||
| `x86_64-rumprun-netbsd` | ✓ | | | 64-bit NetBSD Rump Kernel |
|
||||
| `i686-pc-windows-msvc` (XP) | ✓ | | | Windows XP support |
|
||||
| `x86_64-pc-windows-msvc` (XP) | ✓ | | | Windows XP support |
|
||||
|
||||
Note that this table can be expanded over time, this isn't the exhaustive set of
|
||||
tier 3 platforms that will ever be!
|
||||
|
||||
## After installation
|
||||
|
||||
If you've got Rust installed, you can open up a shell, and type this:
|
||||
If we've got Rust installed, we can open up a shell, and type this:
|
||||
|
||||
```bash
|
||||
$ rustc --version
|
||||
```
|
||||
|
||||
You should see the version number, commit hash, and commit date. If you just
|
||||
installed version 1.2.0, you should see:
|
||||
You should see the version number, commit hash, and commit date.
|
||||
|
||||
```bash
|
||||
rustc 1.2.0 (082e47636 2015-08-03)
|
||||
```
|
||||
If you do, Rust has been installed successfully! Congrats!
|
||||
|
||||
If you did, Rust has been installed successfully! Congrats!
|
||||
|
||||
If you didn't and you're on Windows, check that Rust is in your %PATH% system
|
||||
If you don't and you're on Windows, check that Rust is in your %PATH% system
|
||||
variable. If it isn't, run the installer again, select "Change" on the "Change,
|
||||
repair, or remove installation" page and ensure "Add to PATH" is installed on
|
||||
the local hard drive.
|
||||
|
||||
This installer also installs a copy of the documentation locally, so you can
|
||||
read it offline. On UNIX systems, `/usr/local/share/doc/rust` is the location.
|
||||
On Windows, it's in a `share/doc` directory, inside wherever you installed Rust
|
||||
to.
|
||||
This installer also installs a copy of the documentation locally, so we can read
|
||||
it offline. On UNIX systems, `/usr/local/share/doc/rust` is the location. On
|
||||
Windows, it's in a `share/doc` directory, inside the directory to which Rust was
|
||||
installed.
|
||||
|
||||
If not, there are a number of places where you can get help. The easiest is
|
||||
[the #rust IRC channel on irc.mozilla.org][irc], which you can access through
|
||||
[Mibbit][mibbit]. Click that link, and you'll be chatting with other Rustaceans
|
||||
(a silly nickname we call ourselves), and we can help you out. Other great
|
||||
resources include [the user’s forum][users], and
|
||||
[Stack Overflow][stackoverflow].
|
||||
If not, there are a number of places where we can get help. The easiest is
|
||||
[the #rust IRC channel on irc.mozilla.org][irc], which we can access through
|
||||
[Mibbit][mibbit]. Click that link, and we'll be chatting with other Rustaceans
|
||||
(a silly nickname we call ourselves) who can help us out. Other great resources
|
||||
include [the user’s forum][users], and [Stack Overflow][stackoverflow].
|
||||
|
||||
[irc]: irc://irc.mozilla.org/#rust
|
||||
[mibbit]: http://chat.mibbit.com/?server=irc.mozilla.org&channel=%23rust
|
||||
|
@ -42,12 +42,12 @@ loop is just a handy way to write this `loop`/`match`/`break` construct.
|
||||
`for` loops aren't the only thing that uses iterators, however. Writing your
|
||||
own iterator involves implementing the `Iterator` trait. While doing that is
|
||||
outside of the scope of this guide, Rust provides a number of useful iterators
|
||||
to accomplish various tasks. Before we talk about those, we should talk about a
|
||||
Rust anti-pattern. And that's using ranges like this.
|
||||
to accomplish various tasks. But first, a few notes about limitations of ranges.
|
||||
|
||||
Yes, we just talked about how ranges are cool. But ranges are also very
|
||||
primitive. For example, if you needed to iterate over the contents of a vector,
|
||||
you may be tempted to write this:
|
||||
Ranges are very primitive, and we often can use better alternatives. Consider the
|
||||
following Rust anti-pattern: using ranges to emulate a C-style `for` loop. Let’s
|
||||
suppose you needed to iterate over the contents of a vector. You may be tempted
|
||||
to write this:
|
||||
|
||||
```rust
|
||||
let nums = vec![1, 2, 3];
|
||||
@ -101,10 +101,10 @@ So, now that we've established that ranges are often not what you want, let's
|
||||
talk about what you do want instead.
|
||||
|
||||
There are three broad classes of things that are relevant here: iterators,
|
||||
*iterator adapters*, and *consumers*. Here's some definitions:
|
||||
*iterator adaptors*, and *consumers*. Here's some definitions:
|
||||
|
||||
* *iterators* give you a sequence of values.
|
||||
* *iterator adapters* operate on an iterator, producing a new iterator with a
|
||||
* *iterator adaptors* operate on an iterator, producing a new iterator with a
|
||||
different output sequence.
|
||||
* *consumers* operate on an iterator, producing some final set of values.
|
||||
|
||||
@ -150,15 +150,16 @@ let greater_than_forty_two = (0..100)
|
||||
.find(|x| *x > 42);
|
||||
|
||||
match greater_than_forty_two {
|
||||
Some(_) => println!("We got some numbers!"),
|
||||
None => println!("No numbers found :("),
|
||||
Some(_) => println!("Found a match!"),
|
||||
None => println!("No match found :("),
|
||||
}
|
||||
```
|
||||
|
||||
`find` takes a closure, and works on a reference to each element of an
|
||||
iterator. This closure returns `true` if the element is the element we're
|
||||
looking for, and `false` otherwise. Because we might not find a matching
|
||||
element, `find` returns an `Option` rather than the element itself.
|
||||
looking for, and `false` otherwise. `find` returns the first element satisfying
|
||||
the specified predicate. Because we might not find a matching element, `find`
|
||||
returns an `Option` rather than the element itself.
|
||||
|
||||
Another important consumer is `fold`. Here's what it looks like:
|
||||
|
||||
@ -245,12 +246,12 @@ for num in nums.iter() {
|
||||
These two basic iterators should serve you well. There are some more
|
||||
advanced iterators, including ones that are infinite.
|
||||
|
||||
That's enough about iterators. Iterator adapters are the last concept
|
||||
That's enough about iterators. Iterator adaptors are the last concept
|
||||
we need to talk about with regards to iterators. Let's get to it!
|
||||
|
||||
## Iterator adapters
|
||||
## Iterator adaptors
|
||||
|
||||
*Iterator adapters* take an iterator and modify it somehow, producing
|
||||
*Iterator adaptors* take an iterator and modify it somehow, producing
|
||||
a new iterator. The simplest one is called `map`:
|
||||
|
||||
```rust,ignore
|
||||
@ -279,10 +280,9 @@ doesn't print any numbers:
|
||||
If you are trying to execute a closure on an iterator for its side effects,
|
||||
just use `for` instead.
|
||||
|
||||
There are tons of interesting iterator adapters. `take(n)` will return an
|
||||
iterator over the next `n` elements of the original iterator. Note that this
|
||||
has no side effect on the original iterator. Let's try it out with our infinite
|
||||
iterator from before:
|
||||
There are tons of interesting iterator adaptors. `take(n)` will return an
|
||||
iterator over the next `n` elements of the original iterator. Let's try it out
|
||||
with an infinite iterator:
|
||||
|
||||
```rust
|
||||
for i in (1..).take(5) {
|
||||
@ -302,7 +302,7 @@ This will print
|
||||
|
||||
`filter()` is an adapter that takes a closure as an argument. This closure
|
||||
returns `true` or `false`. The new iterator `filter()` produces
|
||||
only the elements that that closure returns `true` for:
|
||||
only the elements that the closure returns `true` for:
|
||||
|
||||
```rust
|
||||
for i in (1..100).filter(|&x| x % 2 == 0) {
|
||||
@ -329,7 +329,7 @@ a few times, and then consume the result. Check it out:
|
||||
|
||||
This will give you a vector containing `6`, `12`, `18`, `24`, and `30`.
|
||||
|
||||
This is just a small taste of what iterators, iterator adapters, and consumers
|
||||
This is just a small taste of what iterators, iterator adaptors, and consumers
|
||||
can help you with. There are a number of really useful iterators, and you can
|
||||
write your own as well. Iterators provide a safe, efficient way to manipulate
|
||||
all kinds of lists. They're a little unusual at first, but if you play with
|
||||
|
@ -1,6 +1,6 @@
|
||||
% Lifetimes
|
||||
|
||||
This guide is one of three presenting Rust’s ownership system. This is one of
|
||||
This guide is three of three presenting Rust’s ownership system. This is one of
|
||||
Rust’s most unique and compelling features, with which Rust developers should
|
||||
become quite acquainted. Ownership is how Rust achieves its largest goal,
|
||||
memory safety. There are a few distinct concepts, each with its own chapter:
|
||||
@ -43,11 +43,11 @@ With that in mind, let’s learn about lifetimes.
|
||||
Lending out a reference to a resource that someone else owns can be
|
||||
complicated. For example, imagine this set of operations:
|
||||
|
||||
- I acquire a handle to some kind of resource.
|
||||
- I lend you a reference to the resource.
|
||||
- I decide I’m done with the resource, and deallocate it, while you still have
|
||||
1. I acquire a handle to some kind of resource.
|
||||
2. I lend you a reference to the resource.
|
||||
3. I decide I’m done with the resource, and deallocate it, while you still have
|
||||
your reference.
|
||||
- You decide to use the resource.
|
||||
4. You decide to use the resource.
|
||||
|
||||
Uh oh! Your reference is pointing to an invalid resource. This is called a
|
||||
dangling pointer or ‘use after free’, when the resource is memory.
|
||||
@ -70,9 +70,12 @@ fn bar<'a>(x: &'a i32) {
|
||||
```
|
||||
|
||||
The `'a` reads ‘the lifetime a’. Technically, every reference has some lifetime
|
||||
associated with it, but the compiler lets you elide them in common cases.
|
||||
associated with it, but the compiler lets you elide (i.e. omit, see
|
||||
["Lifetime Elision"][lifetime-elision] below) them in common cases.
|
||||
Before we get to that, though, let’s break the explicit example down:
|
||||
|
||||
[lifetime-elision]: #lifetime-elision
|
||||
|
||||
```rust,ignore
|
||||
fn bar<'a>(...)
|
||||
```
|
||||
@ -349,9 +352,9 @@ fn frob<'a, 'b>(s: &'a str, t: &'b str) -> &str; // Expanded: Output lifetime is
|
||||
fn get_mut(&mut self) -> &mut T; // elided
|
||||
fn get_mut<'a>(&'a mut self) -> &'a mut T; // expanded
|
||||
|
||||
fn args<T:ToCStr>(&mut self, args: &[T]) -> &mut Command // elided
|
||||
fn args<'a, 'b, T:ToCStr>(&'a mut self, args: &'b [T]) -> &'a mut Command // expanded
|
||||
fn args<T:ToCStr>(&mut self, args: &[T]) -> &mut Command; // elided
|
||||
fn args<'a, 'b, T:ToCStr>(&'a mut self, args: &'b [T]) -> &'a mut Command; // expanded
|
||||
|
||||
fn new(buf: &mut [u8]) -> BufWriter; // elided
|
||||
fn new<'a>(buf: &'a mut [u8]) -> BufWriter<'a> // expanded
|
||||
fn new<'a>(buf: &'a mut [u8]) -> BufWriter<'a>; // expanded
|
||||
```
|
||||
|
@ -4,14 +4,6 @@ By default, `std` is linked to every Rust crate. In some contexts,
|
||||
this is undesirable, and can be avoided with the `#![no_std]`
|
||||
attribute attached to the crate.
|
||||
|
||||
```ignore
|
||||
// a minimal library
|
||||
#![crate_type="lib"]
|
||||
#![feature(no_std)]
|
||||
#![no_std]
|
||||
# // fn main() {} tricked you, rustdoc!
|
||||
```
|
||||
|
||||
Obviously there's more to life than just libraries: one can use
|
||||
`#[no_std]` with an executable, controlling the entry point is
|
||||
possible in two ways: the `#[start]` attribute, or overriding the
|
||||
@ -21,7 +13,10 @@ The function marked `#[start]` is passed the command line parameters
|
||||
in the same format as C:
|
||||
|
||||
```rust
|
||||
#![feature(lang_items, start, no_std, libc)]
|
||||
# #![feature(libc)]
|
||||
#![feature(lang_items)]
|
||||
#![feature(start)]
|
||||
#![feature(no_std)]
|
||||
#![no_std]
|
||||
|
||||
// Pull in the system libc library for what crt0.o likely requires
|
||||
@ -47,11 +42,13 @@ with `#![no_main]` and then create the appropriate symbol with the
|
||||
correct ABI and the correct name, which requires overriding the
|
||||
compiler's name mangling too:
|
||||
|
||||
```ignore
|
||||
```rust
|
||||
# #![feature(libc)]
|
||||
#![feature(no_std)]
|
||||
#![feature(lang_items)]
|
||||
#![feature(start)]
|
||||
#![no_std]
|
||||
#![no_main]
|
||||
#![feature(lang_items, start)]
|
||||
|
||||
extern crate libc;
|
||||
|
||||
@ -92,19 +89,24 @@ instead.
|
||||
|
||||
The core library has very few dependencies and is much more portable than the
|
||||
standard library itself. Additionally, the core library has most of the
|
||||
necessary functionality for writing idiomatic and effective Rust code.
|
||||
necessary functionality for writing idiomatic and effective Rust code. When
|
||||
using `#![no_std]`, Rust will automatically inject the `core` crate, just like
|
||||
we do for `std` when we’re using it.
|
||||
|
||||
As an example, here is a program that will calculate the dot product of two
|
||||
vectors provided from C, using idiomatic Rust practices.
|
||||
|
||||
```ignore
|
||||
#![feature(lang_items, start, no_std, core, libc)]
|
||||
```rust
|
||||
# #![feature(libc)]
|
||||
#![feature(lang_items)]
|
||||
#![feature(start)]
|
||||
#![feature(no_std)]
|
||||
#![feature(core)]
|
||||
#![feature(core_slice_ext)]
|
||||
#![feature(raw)]
|
||||
#![no_std]
|
||||
|
||||
# extern crate libc;
|
||||
extern crate core;
|
||||
|
||||
use core::prelude::*;
|
||||
extern crate libc;
|
||||
|
||||
use core::mem;
|
||||
|
||||
|
@ -236,13 +236,3 @@ complicated.
|
||||
Luckily, Rust offers a feature, borrowing, which helps us solve this problem.
|
||||
It’s the topic of the next section!
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -23,6 +23,31 @@ match x {
|
||||
|
||||
This prints `one`.
|
||||
|
||||
There’s one pitfall with patterns: like anything that introduces a new binding,
|
||||
they introduce shadowing. For example:
|
||||
|
||||
```rust
|
||||
let x = 'x';
|
||||
let c = 'c';
|
||||
|
||||
match c {
|
||||
x => println!("x: {} c: {}", x, c),
|
||||
}
|
||||
|
||||
println!("x: {}", x)
|
||||
```
|
||||
|
||||
This prints:
|
||||
|
||||
```text
|
||||
x: c c: c
|
||||
x: x
|
||||
```
|
||||
|
||||
In other words, `x =>` matches the pattern and introduces a new binding named
|
||||
`x` that’s in scope for the match arm. Because we already have a binding named
|
||||
`x`, this new `x` shadows it.
|
||||
|
||||
# Multiple patterns
|
||||
|
||||
You can match multiple patterns with `|`:
|
||||
@ -299,7 +324,7 @@ match x {
|
||||
```
|
||||
|
||||
This prints `no`, because the `if` applies to the whole of `4 | 5`, and not to
|
||||
just the `5`, In other words, the the precedence of `if` behaves like this:
|
||||
just the `5`. In other words, the precedence of `if` behaves like this:
|
||||
|
||||
```text
|
||||
(4 | 5) if y => ...
|
||||
|
@ -162,13 +162,18 @@ A ‘slice’ is a reference to (or “view” into) another data structure. The
|
||||
useful for allowing safe, efficient access to a portion of an array without
|
||||
copying. For example, you might want to reference just one line of a file read
|
||||
into memory. By nature, a slice is not created directly, but from an existing
|
||||
variable. Slices have a length, can be mutable or not, and in many ways behave
|
||||
like arrays:
|
||||
variable binding. Slices have a defined length, can be mutable or immutable.
|
||||
|
||||
## Slicing syntax
|
||||
|
||||
You can use a combo of `&` and `[]` to create a slice from various things. The
|
||||
`&` indicates that slices are similar to references, and the `[]`s, with a
|
||||
range, let you define the length of the slice:
|
||||
|
||||
```rust
|
||||
let a = [0, 1, 2, 3, 4];
|
||||
let middle = &a[1..4]; // A slice of a: just the elements 1, 2, and 3
|
||||
let complete = &a[..]; // A slice containing all of the elements in a
|
||||
let middle = &a[1..4]; // A slice of a: just the elements 1, 2, and 3
|
||||
```
|
||||
|
||||
Slices have type `&[T]`. We’ll talk about that `T` when we cover
|
||||
|
@ -98,16 +98,15 @@ these properties are true for any references, no matter how they are created,
|
||||
and so any conversion from raw pointers is asserting that they hold. The
|
||||
programmer *must* guarantee this.
|
||||
|
||||
The recommended method for the conversion is
|
||||
The recommended method for the conversion is:
|
||||
|
||||
```rust
|
||||
let i: u32 = 1;
|
||||
|
||||
// explicit cast
|
||||
let i: u32 = 1;
|
||||
let p_imm: *const u32 = &i as *const u32;
|
||||
let mut m: u32 = 2;
|
||||
|
||||
// implicit coercion
|
||||
let mut m: u32 = 2;
|
||||
let p_mut: *mut u32 = &mut m;
|
||||
|
||||
unsafe {
|
||||
|
@ -1,6 +1,6 @@
|
||||
% References and Borrowing
|
||||
|
||||
This guide is one of three presenting Rust’s ownership system. This is one of
|
||||
This guide is two of three presenting Rust’s ownership system. This is one of
|
||||
Rust’s most unique and compelling features, with which Rust developers should
|
||||
become quite acquainted. Ownership is how Rust achieves its largest goal,
|
||||
memory safety. There are a few distinct concepts, each with its own
|
||||
|
@ -108,7 +108,7 @@ fn process() {
|
||||
let handles: Vec<_> = (0..10).map(|_| {
|
||||
thread::spawn(|| {
|
||||
let mut x = 0;
|
||||
for _ in (0..5_000_000) {
|
||||
for _ in 0..5_000_000 {
|
||||
x += 1
|
||||
}
|
||||
x
|
||||
@ -119,7 +119,6 @@ fn process() {
|
||||
println!("Thread finished with count={}",
|
||||
h.join().map_err(|_| "Could not join a thread!").unwrap());
|
||||
}
|
||||
println!("done!");
|
||||
}
|
||||
```
|
||||
|
||||
|
@ -184,6 +184,8 @@ You can define a `struct` with no members at all:
|
||||
|
||||
```rust
|
||||
struct Electron;
|
||||
|
||||
let x = Electron;
|
||||
```
|
||||
|
||||
Such a `struct` is called ‘unit-like’ because it resembles the empty
|
||||
|
229
src/doc/trpl/syntax-index.md
Normal file
229
src/doc/trpl/syntax-index.md
Normal file
@ -0,0 +1,229 @@
|
||||
% Syntax Index
|
||||
|
||||
## Keywords
|
||||
|
||||
* `as`: primitive casting. See [Casting Between Types (`as`)].
|
||||
* `break`: break out of loop. See [Loops (Ending Iteration Early)].
|
||||
* `const`: constant items. See [`const` and `static`].
|
||||
* `continue`: continue to next loop iteration. See [Loops (Ending Iteration Early)].
|
||||
* `crate`: external crate linkage. See [Crates and Modules (Importing External Crates)].
|
||||
* `else`: fallback for `if` and `if let` constructs. See [`if`], [`if let`].
|
||||
* `enum`: defining enumeration. See [Enums].
|
||||
* `extern`: external crate, function, and variable linkage. See [Crates and Modules (Importing External Crates)], [Foreign Function Interface].
|
||||
* `false`: boolean false literal. See [Primitive Types (Booleans)].
|
||||
* `fn`: function definition and function pointer types. See [Functions].
|
||||
* `for`: iterator loop, part of trait `impl` syntax, and higher-ranked lifetime syntax. See [Loops (`for`)], [Method Syntax].
|
||||
* `if`: conditional branching. See [`if`], [`if let`].
|
||||
* `impl`: inherent and trait implementation blocks. See [Method Syntax].
|
||||
* `in`: part of `for` loop syntax. See [Loops (`for`)].
|
||||
* `let`: variable binding. See [Variable Bindings].
|
||||
* `loop`: unconditional, infinite loop. See [Loops (`loop`)].
|
||||
* `match`: pattern matching. See [Match].
|
||||
* `mod`: module declaration. See [Crates and Modules (Defining Modules)].
|
||||
* `move`: part of closure syntax. See [Closures (`move` closures)].
|
||||
* `mut`: denotes mutability in pointer types and pattern bindings. See [Mutability].
|
||||
* `pub`: denotes public visibility in `struct` fields, `impl` blocks, and modules. See [Crates and Modules (Exporting a Public Interface)].
|
||||
* `ref`: by-reference binding. See [Patterns (`ref` and `ref mut`)].
|
||||
* `return`: return from function. See [Functions (Early Returns)].
|
||||
* `Self`: implementor type alias. See [Traits].
|
||||
* `self`: method subject. See [Method Syntax (Method Calls)].
|
||||
* `static`: global variable. See [`const` and `static` (`static`)].
|
||||
* `struct`: structure definition. See [Structs].
|
||||
* `trait`: trait definition. See [Traits].
|
||||
* `true`: boolean true literal. See [Primitive Types (Booleans)].
|
||||
* `type`: type alias, and associated type definition. See [`type` Aliases], [Associated Types].
|
||||
* `unsafe`: denotes unsafe code, functions, traits, and implementations. See [Unsafe].
|
||||
* `use`: import symbols into scope. See [Crates and Modules (Importing Modules with `use`)].
|
||||
* `where`: type constraint clauses. See [Traits (`where` clause)].
|
||||
* `while`: conditional loop. See [Loops (`while`)].
|
||||
|
||||
## Operators and Symbols
|
||||
|
||||
* `!` (`expr!(…)`, `expr!{…}`, `expr![…]`): denotes macro expansion. See [Macros].
|
||||
* `!` (`!expr`): bitwise or logical complement. Overloadable (`Not`).
|
||||
* `%` (`expr % expr`): arithmetic remainder. Overloadable (`Rem`).
|
||||
* `%=` (`var %= expr`): arithmetic remainder & assignment.
|
||||
* `&` (`expr & expr`): bitwise and. Overloadable (`BitAnd`).
|
||||
* `&` (`&expr`): borrow. See [References and Borrowing].
|
||||
* `&` (`&type`, `&mut type`, `&'a type`, `&'a mut type`): borrowed pointer type. See [References and Borrowing].
|
||||
* `&=` (`var &= expr`): bitwise and & assignment.
|
||||
* `&&` (`expr && expr`): logical and.
|
||||
* `*` (`expr * expr`): arithmetic multiplication. Overloadable (`Mul`).
|
||||
* `*` (`*expr`): dereference.
|
||||
* `*` (`*const type`, `*mut type`): raw pointer. See [Raw Pointers].
|
||||
* `*=` (`var *= expr`): arithmetic multiplication & assignment.
|
||||
* `+` (`expr + expr`): arithmetic addition. Overloadable (`Add`).
|
||||
* `+` (`trait + trait`, `'a + trait`): compound type constraint. See [Traits (Multiple Trait Bounds)].
|
||||
* `+=` (`var += expr`): arithmetic addition & assignment.
|
||||
* `,`: argument and element separator. See [Attributes], [Functions], [Structs], [Generics], [Match], [Closures], [Crates and Modules (Importing Modules with `use`)].
|
||||
* `-` (`expr - expr`): arithmetic subtraction. Overloadable (`Sub`).
|
||||
* `-` (`- expr`): arithmetic negation. Overloadable (`Neg`).
|
||||
* `-=` (`var -= expr`): arithmetic subtraction & assignment.
|
||||
* `->` (`fn(…) -> type`, `|…| -> type`): function and closure return type. See [Functions], [Closures].
|
||||
* `.` (`expr.ident`): member access. See [Structs], [Method Syntax].
|
||||
* `..` (`..`, `expr..`, `..expr`, `expr..expr`): right-exclusive range literal.
|
||||
* `..` (`..expr`): struct literal update syntax. See [Structs (Update syntax)].
|
||||
* `..` (`variant(x, ..)`, `struct_type { x, .. }`): "and the rest" pattern binding. See [Patterns (Ignoring bindings)].
|
||||
* `...` (`expr ... expr`): inclusive range pattern. See [Patterns (Ranges)].
|
||||
* `/` (`expr / expr`): arithmetic division. Overloadable (`Div`).
|
||||
* `/=` (`var /= expr`): arithmetic division & assignment.
|
||||
* `:` (`pat: type`, `ident: type`): constraints. See [Variable Bindings], [Functions], [Structs], [Traits].
|
||||
* `:` (`ident: expr`): struct field initializer. See [Structs].
|
||||
* `:` (`'a: loop {…}`): loop label. See [Loops (Loops Labels)].
|
||||
* `;`: statement and item terminator.
|
||||
* `;` (`[…; len]`): part of fixed-size array syntax. See [Primitive Types (Arrays)].
|
||||
* `<<` (`expr << expr`): left-shift. Overloadable (`Shl`).
|
||||
* `<<=` (`var <<= expr`): left-shift & assignment.
|
||||
* `<` (`expr < expr`): less-than comparison. Overloadable (`Cmp`, `PartialCmp`).
|
||||
* `<=` (`var <= expr`): less-than or equal-to comparison. Overloadable (`Cmp`, `PartialCmp`).
|
||||
* `=` (`var = expr`, `ident = type`): assignment/equivalence. See [Variable Bindings], [`type` Aliases], generic parameter defaults.
|
||||
* `==` (`var == expr`): comparison. Overloadable (`Eq`, `PartialEq`).
|
||||
* `=>` (`pat => expr`): part of match arm syntax. See [Match].
|
||||
* `>` (`expr > expr`): greater-than comparison. Overloadable (`Cmp`, `PartialCmp`).
|
||||
* `>=` (`var >= expr`): greater-than or equal-to comparison. Overloadable (`Cmp`, `PartialCmp`).
|
||||
* `>>` (`expr >> expr`): right-shift. Overloadable (`Shr`).
|
||||
* `>>=` (`var >>= expr`): right-shift & assignment.
|
||||
* `@` (`ident @ pat`): pattern binding. See [Patterns (Bindings)].
|
||||
* `^` (`expr ^ expr`): bitwise exclusive or. Overloadable (`BitXor`).
|
||||
* `^=` (`var ^= expr`): bitwise exclusive or & assignment.
|
||||
* `|` (`expr | expr`): bitwise or. Overloadable (`BitOr`).
|
||||
* `|` (`pat | pat`): pattern alternatives. See [Patterns (Multiple patterns)].
|
||||
* `|=` (`var |= expr`): bitwise or & assignment.
|
||||
* `||` (`expr || expr`): logical or.
|
||||
* `_`: "ignored" pattern binding. See [Patterns (Ignoring bindings)].
|
||||
|
||||
## Other Syntax
|
||||
|
||||
<!-- Various bits of standalone stuff. -->
|
||||
|
||||
* `'ident`: named lifetime or loop label. See [Lifetimes], [Loops (Loops Labels)].
|
||||
* `…u8`, `…i32`, `…f64`, `…usize`, …: numeric literal of specific type.
|
||||
* `"…"`: string literal. See [Strings].
|
||||
* `r"…"`, `r#"…"#`, `r##"…"##`, …: raw string literal.
|
||||
* `b"…"`: byte string literal.
|
||||
* `rb"…"`, `rb#"…"#`, `rb##"…"##`, …: raw byte string literal.
|
||||
* `'…'`: character literal. See [Primitive Types (`char`)].
|
||||
* `b'…'`: ASCII byte literal.
|
||||
|
||||
<!-- Path-related syntax -->
|
||||
|
||||
* `ident::ident`: path. See [Crates and Modules (Defining Modules)].
|
||||
* `::path`: path relative to the crate root (*i.e.* an explicitly absolute path). See [Crates and Modules (Re-exporting with `pub use`)].
|
||||
* `self::path`: path relative to the current module (*i.e.* an explicitly relative path). See [Crates and Modules (Re-exporting with `pub use`)].
|
||||
* `super::path`: path relative to the parent of the current module. See [Crates and Modules (Re-exporting with `pub use`)].
|
||||
* `type::ident`: associated constants, functions, and types. See [Associated Types].
|
||||
* `<type>::…`: associated item for a type which cannot be directly named (*e.g.* `<&T>::…`, `<[T]>::…`, *etc.*). See [Associated Types].
|
||||
|
||||
<!-- Generics -->
|
||||
|
||||
* `path<…>` (*e.g.* `Vec<u8>`): specifies parameters to generic type *in a type*. See [Generics].
|
||||
* `path::<…>`, `method::<…>` (*e.g.* `"42".parse::<i32>()`): specifies parameters to generic type, function, or method *in an expression*.
|
||||
* `fn ident<…> …`: define generic function. See [Generics].
|
||||
* `struct ident<…> …`: define generic structure. See [Generics].
|
||||
* `enum ident<…> …`: define generic enumeration. See [Generics].
|
||||
* `impl<…> …`: define generic implementation.
|
||||
* `for<…> type`: higher-ranked lifetime bounds.
|
||||
* `type<ident=type>` (*e.g.* `Iterator<Item=T>`): a generic type where one or more associated types have specific assignments. See [Associated Types].
|
||||
|
||||
<!-- Constraints -->
|
||||
|
||||
* `T: U`: generic parameter `T` constrained to types that implement `U`. See [Traits].
|
||||
* `T: 'a`: generic type `T` must outlive lifetime `'a`.
|
||||
* `'b: 'a`: generic lifetime `'b` must outlive lifetime `'a`.
|
||||
* `T: ?Sized`: allow generic type parameter to be a dynamically-sized type. See [Unsized Types (`?Sized`)].
|
||||
* `'a + trait`, `trait + trait`: compound type constraint. See [Traits (Multiple Trait Bounds)].
|
||||
|
||||
<!-- Macros and attributes -->
|
||||
|
||||
* `#[meta]`: outer attribute. See [Attributes].
|
||||
* `#![meta]`: inner attribute. See [Attributes].
|
||||
* `$ident`: macro substitution. See [Macros].
|
||||
* `$ident:kind`: macro capture. See [Macros].
|
||||
* `$(…)…`: macro repetition. See [Macros].
|
||||
|
||||
<!-- Comments -->
|
||||
|
||||
* `//`: line comment. See [Comments].
|
||||
* `//!`: inner line doc comment. See [Comments].
|
||||
* `///`: outer line doc comment. See [Comments].
|
||||
* `/*…*/`: block comment. See [Comments].
|
||||
* `/*!…*/`: inner block doc comment. See [Comments].
|
||||
* `/**…*/`: outer block doc comment. See [Comments].
|
||||
|
||||
<!-- Various things involving parens and tuples -->
|
||||
|
||||
* `()`: empty tuple (*a.k.a.* unit), both literal and type.
|
||||
* `(expr)`: parenthesized expression.
|
||||
* `(expr,)`: single-element tuple expression. See [Primitive Types (Tuples)].
|
||||
* `(type,)`: single-element tuple type. See [Primitive Types (Tuples)].
|
||||
* `(expr, …)`: tuple expression. See [Primitive Types (Tuples)].
|
||||
* `(type, …)`: tuple type. See [Primitive Types (Tuples)].
|
||||
* `expr(expr, …)`: function call expression. Also used to initialize tuple `struct`s and tuple `enum` variants. See [Functions].
|
||||
* `ident!(…)`, `ident!{…}`, `ident![…]`: macro invocation. See [Macros].
|
||||
* `expr.0`, `expr.1`, …: tuple indexing. See [Primitive Types (Tuple Indexing)].
|
||||
|
||||
<!-- Bracey things -->
|
||||
|
||||
* `{…}`: block expression.
|
||||
* `Type {…}`: `struct` literal. See [Structs].
|
||||
|
||||
<!-- Brackety things -->
|
||||
|
||||
* `[…]`: array literal. See [Primitive Types (Arrays)].
|
||||
* `[expr; len]`: array literal containing `len` copies of `expr`. See [Primitive Types (Arrays)].
|
||||
* `[type; len]`: array type containing `len` instances of `type`. See [Primitive Types (Arrays)].
|
||||
|
||||
[`const` and `static` (`static`)]: const-and-static.html#static
|
||||
[`const` and `static`]: const-and-static.html
|
||||
[`if let`]: if-let.html
|
||||
[`if`]: if.html
|
||||
[`type` Aliases]: type-aliases.html
|
||||
[Associated Types]: associated-types.html
|
||||
[Attributes]: attributes.html
|
||||
[Casting Between Types (`as`)]: casting-between-types.html#as
|
||||
[Closures (`move` closures)]: closures.html#move-closures
|
||||
[Closures]: closures.html
|
||||
[Comments]: comments.html
|
||||
[Crates and Modules (Defining Modules)]: crates-and-modules.html#defining-modules
|
||||
[Crates and Modules (Exporting a Public Interface)]: crates-and-modules.html#exporting-a-public-interface
|
||||
[Crates and Modules (Importing External Crates)]: crates-and-modules.html#importing-external-crates
|
||||
[Crates and Modules (Importing Modules with `use`)]: crates-and-modules.html#importing-modules-with-use
|
||||
[Crates and Modules (Re-exporting with `pub use`)]: crates-and-modules.html#re-exporting-with-pub-use
|
||||
[Enums]: enums.html
|
||||
[Foreign Function Interface]: ffi.html
|
||||
[Functions (Early Returns)]: functions.html#early-returns
|
||||
[Functions]: functions.html
|
||||
[Generics]: generics.html
|
||||
[Lifetimes]: lifetimes.html
|
||||
[Loops (`for`)]: loops.html#for
|
||||
[Loops (`loop`)]: loops.html#loop
|
||||
[Loops (`while`)]: loops.html#while
|
||||
[Loops (Ending Iteration Early)]: loops.html#ending-iteration-early
|
||||
[Loops (Loops Labels)]: loops.html#loop-labels
|
||||
[Macros]: macros.html
|
||||
[Match]: match.html
|
||||
[Method Syntax (Method Calls)]: method-syntax.html#method-calls
|
||||
[Method Syntax]: method-syntax.html
|
||||
[Mutability]: mutability.html
|
||||
[Operators and Overloading]: operators-and-overloading.html
|
||||
[Patterns (`ref` and `ref mut`)]: patterns.html#ref-and-ref-mut
|
||||
[Patterns (Bindings)]: patterns.html#bindings
|
||||
[Patterns (Ignoring bindings)]: patterns.html#ignoring-bindings
|
||||
[Patterns (Multiple patterns)]: patterns.html#multiple-patterns
|
||||
[Patterns (Ranges)]: patterns.html#ranges
|
||||
[Primitive Types (`char`)]: primitive-types.html#char
|
||||
[Primitive Types (Arrays)]: primitive-types.html#arrays
|
||||
[Primitive Types (Booleans)]: primitive-types.html#booleans
|
||||
[Primitive Types (Tuple Indexing)]: primitive-types.html#tuple-indexing
|
||||
[Primitive Types (Tuples)]: primitive-types.html#tuples
|
||||
[Raw Pointers]: raw-pointers.html
|
||||
[References and Borrowing]: references-and-borrowing.html
|
||||
[Strings]: strings.html
|
||||
[Structs (Update syntax)]: structs.html#update-syntax
|
||||
[Structs]: structs.html
|
||||
[Traits (`where` clause)]: traits.html#where-clause
|
||||
[Traits (Multiple Trait Bounds)]: traits.html#multiple-trait-bounds
|
||||
[Traits]: traits.html
|
||||
[Unsafe]: unsafe.html
|
||||
[Unsized Types (`?Sized`)]: unsized-types.html#?sized
|
||||
[Variable Bindings]: variable-bindings.html
|
@ -82,7 +82,7 @@ fn it_works() {
|
||||
```
|
||||
|
||||
`assert!` is a macro provided by Rust which takes one argument: if the argument
|
||||
is `true`, nothing happens. If the argument is false, it `panic!`s. Let's run
|
||||
is `true`, nothing happens. If the argument is `false`, it `panic!`s. Let's run
|
||||
our tests again:
|
||||
|
||||
```bash
|
||||
@ -289,7 +289,7 @@ running 0 tests
|
||||
test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured
|
||||
```
|
||||
|
||||
The `--ignored` argument is an argument to the test binary, and not to cargo,
|
||||
The `--ignored` argument is an argument to the test binary, and not to Cargo,
|
||||
which is why the command is `cargo test -- --ignored`.
|
||||
|
||||
# The `tests` module
|
||||
@ -367,7 +367,7 @@ It works!
|
||||
The current convention is to use the `tests` module to hold your "unit-style"
|
||||
tests. Anything that just tests one small bit of functionality makes sense to
|
||||
go here. But what about "integration-style" tests instead? For that, we have
|
||||
the `tests` directory
|
||||
the `tests` directory.
|
||||
|
||||
# The `tests` directory
|
||||
|
||||
@ -502,3 +502,8 @@ documentation tests: the `_0` is generated for the module test, and `add_two_0`
|
||||
for the function test. These will auto increment with names like `add_two_1` as
|
||||
you add more examples.
|
||||
|
||||
We haven’t covered all of the details with writing documentation tests. For more,
|
||||
please see the [Documentation chapter](documentation.html)
|
||||
|
||||
One final note: Tests *cannot* be run on a binary file. To see more on file arrangement see the [Crates and Modules](crates-and-modules.html) section.
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user