Imported Upstream version 1.5.0+dfsg1

This commit is contained in:
Sylvestre Ledru 2015-12-10 17:51:38 +01:00
parent e9174d1eb2
commit b039eaaf8a
1040 changed files with 33117 additions and 22323 deletions

View File

@ -9,7 +9,9 @@ Aaron Todd <github@opprobrio.us>
Aaron Turon <aturon@mozilla.com> Aaron Turon <aturon@mozilla.com>
Aaron Weiss <aaronweiss74@gmail.com> Aaron Weiss <aaronweiss74@gmail.com>
Abhishek Chanda <abhishek.becs@gmail.com> Abhishek Chanda <abhishek.becs@gmail.com>
Adam Badawy <adambada@buffalo.edu>
Adam Bozanich <adam.boz@gmail.com> Adam Bozanich <adam.boz@gmail.com>
Adam Crume <adamcrume@gmail.com>
Adam Heins <mail@adamheins.com> Adam Heins <mail@adamheins.com>
Adam Jacob <adam@opscode.com> Adam Jacob <adam@opscode.com>
Adam Roben <adam@roben.org> Adam Roben <adam@roben.org>
@ -30,8 +32,10 @@ Alan Cutter <alancutter@chromium.org>
Alan Williams <mralert@gmail.com> Alan Williams <mralert@gmail.com>
Aleksander Balicki <balicki.aleksander@gmail.com> Aleksander Balicki <balicki.aleksander@gmail.com>
Aleksandr Koshlo <sash7ko@gmail.com> Aleksandr Koshlo <sash7ko@gmail.com>
Aleksey Kladov <aleksey.kladov@gmail.com>
Alexander Artemenko <svetlyak.40wt@gmail.com> Alexander Artemenko <svetlyak.40wt@gmail.com>
Alexander Bliskovsky <alexander.bliskovsky@gmail.com> Alexander Bliskovsky <alexander.bliskovsky@gmail.com>
Alexander Bulaev <aleks.bulaev@gmail.com>
Alexander Campbell <alexanderhcampbell@gmail.com> Alexander Campbell <alexanderhcampbell@gmail.com>
Alexander Chernyakhovsky <achernya@mit.edu> Alexander Chernyakhovsky <achernya@mit.edu>
Alexander Korolkov <alexander.korolkov@gmail.com> Alexander Korolkov <alexander.korolkov@gmail.com>
@ -42,19 +46,25 @@ Alexandre Gagnon <alxgnon@gmail.com>
Alexandros Tasos <sdi1100085@di.uoa.gr> Alexandros Tasos <sdi1100085@di.uoa.gr>
Alex Burka <durka42+github@gmail.com> Alex Burka <durka42+github@gmail.com>
Alex Crichton <alex@alexcrichton.com> Alex Crichton <alex@alexcrichton.com>
AlexDenisov <1101.debian@gmail.com>
Alexei Sholik <alcosholik@gmail.com> Alexei Sholik <alcosholik@gmail.com>
Alex Gaynor <alex.gaynor@gmail.com> Alex Gaynor <alex.gaynor@gmail.com>
Alexis Beingessner <a.beingessner@gmail.com> Alexis Beingessner <a.beingessner@gmail.com>
Alex Lyon <arcterus@mail.com> Alex Lyon <arcterus@mail.com>
Alex Newman <posix4e@gmail.com> Alex Newman <posix4e@gmail.com>
Alex Ozdemir <aozdemir@hmc.edu>
Alex Quach <alex@clinkle.com> Alex Quach <alex@clinkle.com>
Alex Rønne Petersen <alex@lycus.org> Alex Rønne Petersen <alex@lycus.org>
Alex Stokes <r.alex.stokes@gmail.com> Alex Stokes <r.alex.stokes@gmail.com>
Alex Whitney <aw1209@ic.ac.uk> Alex Whitney <aw1209@ic.ac.uk>
Alfie John <alfie@alfie.wtf> Alfie John <alfie@alfie.wtf>
Alfie John <alfiej@fastmail.fm>
Alisdair Owens <awo101@zepler.net> Alisdair Owens <awo101@zepler.net>
Ali Smesseim <smesseim.ali@gmail.com> Ali Smesseim <smesseim.ali@gmail.com>
Aljaž "g5pw" Srebrnič <a2piratesoft@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> Amol Mundayoor <amol.com@gmail.com>
Amy Unger <amy.e.unger@gmail.com> Amy Unger <amy.e.unger@gmail.com>
Anatoly Ikorsky <aikorsky@gmail.com> Anatoly Ikorsky <aikorsky@gmail.com>
@ -65,7 +75,9 @@ Andreas Gal <gal@mozilla.com>
Andreas Martens <andreasm@fastmail.fm> Andreas Martens <andreasm@fastmail.fm>
Andreas Neuhaus <zargony@zargony.com> Andreas Neuhaus <zargony@zargony.com>
Andreas Ots <andreasots@gmail.com> Andreas Ots <andreasots@gmail.com>
Andreas Sommer <andreas.sommer87@googlemail.com>
Andreas Tolfsen <ato@mozilla.com> Andreas Tolfsen <ato@mozilla.com>
Andre Bogus <bogusandre@gmail.com>
Andrei Formiga <archimedes_siracusa@hotmail.com> Andrei Formiga <archimedes_siracusa@hotmail.com>
Andrei Oprea <andrei.br92@gmail.com> Andrei Oprea <andrei.br92@gmail.com>
Andrew Barchuk <raindev@icloud.com> Andrew Barchuk <raindev@icloud.com>
@ -82,14 +94,18 @@ Andrew Poelstra <asp11@sfu.ca>
Andrew Seidl <dev@aas.io> Andrew Seidl <dev@aas.io>
Andrew Straw <strawman@astraw.com> Andrew Straw <strawman@astraw.com>
Andrew Wagner <drewm1980@gmail.com> Andrew Wagner <drewm1980@gmail.com>
androm3da <brian.cain@gmail.com>
Andrzej Janik <vosen@vosen.pl> Andrzej Janik <vosen@vosen.pl>
Andy Caldwell <andrew.caldwell@metaswitch.com> Andy Caldwell <andrew.caldwell@metaswitch.com>
Andy Grover <agrover@redhat.com> Andy Grover <agrover@redhat.com>
angelsl <hidingfromhidden@gmail.com>
Angus Lees <gus@inodes.org> Angus Lees <gus@inodes.org>
Anthony Juckel <ajuckel@gmail.com> Anthony Juckel <ajuckel@gmail.com>
Anton Löfgren <anton.lofgren@gmail.com> Anton Löfgren <anton.lofgren@gmail.com>
Antti Keränen <detegr@gmail.com> Antti Keränen <detegr@gmail.com>
aochagavia <aochagavia92@gmail.com>
Aram Visser <aramvisser@gmail.com> Aram Visser <aramvisser@gmail.com>
arcnmx <arcnmx@users.noreply.github.com>
Arcterus <Arcterus@mail.com> Arcterus <Arcterus@mail.com>
Areski Belaid <areski@gmail.com> Areski Belaid <areski@gmail.com>
Ariel Ben-Yehuda <arielb1@mail.tau.ac.il> Ariel Ben-Yehuda <arielb1@mail.tau.ac.il>
@ -99,9 +115,11 @@ Armin Preiml <apreiml@strohwolke.at>
Armin Ronacher <armin.ronacher@active-4.com> Armin Ronacher <armin.ronacher@active-4.com>
Arpad Borsos <arpad.borsos@googlemail.com> Arpad Borsos <arpad.borsos@googlemail.com>
Artem <artemciy@gmail.com> Artem <artemciy@gmail.com>
Artem Shitov <artemshitov@yandex-team.ru>
Arthur Liao <arthurtw8@gmail.com> Arthur Liao <arthurtw8@gmail.com>
arthurprs <arthurprs@gmail.com> arthurprs <arthurprs@gmail.com>
arturo <arturo@openframeworks.cc> arturo <arturo@openframeworks.cc>
Ashkan Kiani <ashkan.k.kiani@gmail.com>
Ashok Gautham <ScriptDevil@gmail.com> Ashok Gautham <ScriptDevil@gmail.com>
Augusto Hack <hack.augusto@gmail.com> Augusto Hack <hack.augusto@gmail.com>
auREAX <mark@xn--hwg34fba.ws> auREAX <mark@xn--hwg34fba.ws>
@ -113,8 +131,11 @@ Avdi Grimm <avdi@avdi.org>
awlnx <alecweber1994@gmail.com> awlnx <alecweber1994@gmail.com>
Axel Viala <axel.viala@darnuria.eu> Axel Viala <axel.viala@darnuria.eu>
Aydin Kim <ladinjin@hanmail.net> Aydin Kim <ladinjin@hanmail.net>
b1nd <clint.ryan3@gmail.com>
bachm <Ab@vapor.com> bachm <Ab@vapor.com>
Barosl LEE <github@barosl.com>
Barosl Lee <vcs@barosl.com> Barosl Lee <vcs@barosl.com>
Bastien Dejean <nihilhill@gmail.com>
bcoopers <coopersmithbrian@gmail.com> bcoopers <coopersmithbrian@gmail.com>
Ben Alpert <ben@benalpert.com> Ben Alpert <ben@benalpert.com>
benaryorg <binary@benary.org> benaryorg <binary@benary.org>
@ -133,19 +154,24 @@ Benjamin Peterson <benjamin@python.org>
Ben Kelly <ben@wanderview.com> Ben Kelly <ben@wanderview.com>
Ben Noordhuis <info@bnoordhuis.nl> Ben Noordhuis <info@bnoordhuis.nl>
Ben Sago <ogham@users.noreply.github.com> Ben Sago <ogham@users.noreply.github.com>
benshu <benshu@benshu.de>
Ben S <ogham@users.noreply.github.com>
Ben Striegel <ben.striegel@gmail.com> Ben Striegel <ben.striegel@gmail.com>
Bhargav Patel <bhargavrpatel@users.noreply.github.com>
Bheesham Persaud <bheesham123@hotmail.com> Bheesham Persaud <bheesham123@hotmail.com>
Bilal Husain <bilal@bilalhusain.com> Bilal Husain <bilal@bilalhusain.com>
Bill Fallon <bill.fallon@robos.li> Bill Fallon <bill.fallon@robos.li>
Bill Myers <bill_myers@outlook.com> Bill Myers <bill_myers@outlook.com>
billpmurphy <billpmurphy92@gmail.com>
Bill Wendling <wendling@apple.com> Bill Wendling <wendling@apple.com>
Birunthan Mohanathas <birunthan@mohanathas.com> Birunthan Mohanathas <birunthan@mohanathas.com>
Björn Steinbrink <bsteinbr@gmail.com> Björn Steinbrink <bsteinbr@gmail.com>
blackbeam <aikorsky@gmail.com>
blake2-ppc <ulrik.sverdrup@gmail.com> blake2-ppc <ulrik.sverdrup@gmail.com>
Blake Loring <Blake.Loring@ig.com> Blake Loring <Blake.Loring@ig.com>
bluss <bluss>
bluss <bluss@users.noreply.github.com> 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> bors <bors@rust-lang.org>
Bouke van der Bijl <boukevanderbijl@gmail.com> Bouke van der Bijl <boukevanderbijl@gmail.com>
Brad King <brad.king@kitware.com> Brad King <brad.king@kitware.com>
@ -169,10 +195,14 @@ Brian Leibig <brian@brianleibig.com>
Brian Quinlan <brian@sweetapp.com> Brian Quinlan <brian@sweetapp.com>
Brody Holden <brody.holden.r@gmail.com> Brody Holden <brody.holden.r@gmail.com>
Bruno de Oliveira Abinader <bruno.d@partner.samsung.com> Bruno de Oliveira Abinader <bruno.d@partner.samsung.com>
Bruno Tavares <connect+github@bltavares.com>
Bryan Dunsmore <dunsmoreb@gmail.com> Bryan Dunsmore <dunsmoreb@gmail.com>
Bryce Van Dyk <bryce@vandyk.net.nz>
Byron Williams <byron@112percent.com> Byron Williams <byron@112percent.com>
Cadence Marseille <cadencemarseille@gmail.com> Cadence Marseille <cadencemarseille@gmail.com>
caipre <platt.nicholas@gmail.com>
Caitlin Potter <snowball@defpixel.com> Caitlin Potter <snowball@defpixel.com>
Cameron Sun <cameron.csun@gmail.com>
Cameron Zwarich <zwarich@mozilla.com> Cameron Zwarich <zwarich@mozilla.com>
Camille Roussel <camille@rousselfamily.com> Camille Roussel <camille@rousselfamily.com>
Camille TJHOA <camille.tjhoa@outlook.com> Camille TJHOA <camille.tjhoa@outlook.com>
@ -180,18 +210,25 @@ Cam Jackson <camjackson89@gmail.com>
Carl-Anton Ingmarsson <mail@carlanton.se> Carl-Anton Ingmarsson <mail@carlanton.se>
Carl Lerche <me@carllerche.com> Carl Lerche <me@carllerche.com>
Carlos Galarza <carloslfu@gmail.com> Carlos Galarza <carloslfu@gmail.com>
Carlos Liam <carlos@aarzee.me>
Carlos <toqueteos@gmail.com>
Carol (Nichols || Goulding) <carol.nichols@gmail.com> Carol (Nichols || Goulding) <carol.nichols@gmail.com>
Carol Willing <carolcode@willingconsulting.com> Carol Willing <carolcode@willingconsulting.com>
Carter Hinsley <carterhinsley@gmail.com> Carter Hinsley <carterhinsley@gmail.com>
Carter Tazio Schonwald <carter.schonwald@gmail.com> Carter Tazio Schonwald <carter.schonwald@gmail.com>
CarVac <c.lo.to.da.down.lo@gmail.com> CarVac <c.lo.to.da.down.lo@gmail.com>
Caspar Krieger <caspar@asparck.com> Caspar Krieger <caspar@asparck.com>
Cesar Eduardo Barros <cesarb@cesarb.eti.br>
Charlotte Spencer <charlottelaspencer@gmail.com>
Chase Southwood <chase.southwood@gmail.com> Chase Southwood <chase.southwood@gmail.com>
Ches Martin <ches@whiskeyandgrits.net> Ches Martin <ches@whiskeyandgrits.net>
chitra chitra <bogus>
Chloe <5paceToast@users.noreply.github.com> Chloe <5paceToast@users.noreply.github.com>
Chris C Cerami <chrisccerami@users.noreply.github.com>
Chris Double <chris.double@double.co.nz> Chris Double <chris.double@double.co.nz>
Chris Drake <cjdrake@gmail.com>
Chris Hellmuth <chellmuth@gmail.com> Chris Hellmuth <chellmuth@gmail.com>
Chris Krycho <chris@krycho.com>
Chris Morgan <me@chrismorgan.info> Chris Morgan <me@chrismorgan.info>
Chris Nixon <chris.nixon@sigma.me.uk> Chris Nixon <chris.nixon@sigma.me.uk>
Chris Peterson <cpeterson@mozilla.com> Chris Peterson <cpeterson@mozilla.com>
@ -205,6 +242,7 @@ Christian Weinz <christian@madez.de>
Christoph Burgdorf <christoph.burgdorf@bvsn.org> Christoph Burgdorf <christoph.burgdorf@bvsn.org>
Christopher Bergqvist <spambox0@digitalpoetry.se> Christopher Bergqvist <spambox0@digitalpoetry.se>
Christopher Chambers <chris.chambers@peanutcode.com> Christopher Chambers <chris.chambers@peanutcode.com>
christopherdumas <christopherdumas@me.com>
Christopher Kendell <ckendell@outlook.com> Christopher Kendell <ckendell@outlook.com>
Chris Wong <lambda.fairy@gmail.com> Chris Wong <lambda.fairy@gmail.com>
chromatic <chromatic@wgz.org> chromatic <chromatic@wgz.org>
@ -220,18 +258,25 @@ Cole Mickens <cole.mickens@gmail.com>
Cole Reynolds <cpjreynolds@gmail.com> Cole Reynolds <cpjreynolds@gmail.com>
Colin Davidson <colrdavidson@gmail.com> Colin Davidson <colrdavidson@gmail.com>
Colin Sherratt <colin.sherratt@gmail.com> Colin Sherratt <colin.sherratt@gmail.com>
Colin Wallace <wallacoloo@gmail.com>
Colin Walters <walters@verbum.org> Colin Walters <walters@verbum.org>
comex <comexk@gmail.com> comex <comexk@gmail.com>
Conrad Kleinespel <conradk@conradk.com> Conrad Kleinespel <conradk@conradk.com>
corentih <corentin.henry@alcatel-lucent.com>
Corentin Henry <corentinhenry@gmail.com>
Corey Farwell <coreyf+rust@rwell.org> Corey Farwell <coreyf+rust@rwell.org>
Corey Ford <corey@coreyford.name> Corey Ford <corey@coreyford.name>
Corey Richardson <corey@octayn.net> Corey Richardson <corey@octayn.net>
Cornel Punga <cornel.punga@gmail.com> Cornel Punga <cornel.punga@gmail.com>
Craig Hills <chills@gmail.com>
crhino <piraino.chris@gmail.com> crhino <piraino.chris@gmail.com>
Cristian Kubis <cristian.kubis@tsunix.de> Cristian Kubis <cristian.kubis@tsunix.de>
Cristi Burcă <scribu@gmail.com> Cristi Burcă <scribu@gmail.com>
Cristi Cobzarenco <cristi.cobzarenco@gmail.com>
critiqjo <john.ch.fr@gmail.com> critiqjo <john.ch.fr@gmail.com>
Cruz Julian Bishop <cruzjbishop@gmail.com> Cruz Julian Bishop <cruzjbishop@gmail.com>
Daan Rijks <daanrijks@gmail.com>
Dabo Ross <daboross@daboross.net>
Damian Gryski <damian@gryski.com> Damian Gryski <damian@gryski.com>
Damien Grassart <damien@grassart.com> Damien Grassart <damien@grassart.com>
Damien Radtke <dradtke@channeliq.com> Damien Radtke <dradtke@channeliq.com>
@ -242,11 +287,13 @@ Dan Callahan <dan.callahan@gmail.com>
Dan Connolly <dckc@madmode.com> Dan Connolly <dckc@madmode.com>
Daniel Albert <albert_daniel@t-online.de> Daniel Albert <albert_daniel@t-online.de>
Daniel Brooks <db48x@db48x.net> Daniel Brooks <db48x@db48x.net>
Daniel Carral <dan@dcarral.org>
Daniel Fagnan <dnfagnan@gmail.com> Daniel Fagnan <dnfagnan@gmail.com>
Daniel Farina <daniel@fdr.io> Daniel Farina <daniel@fdr.io>
Daniel Griffen <daniel@dgriffen.com> Daniel Griffen <daniel@dgriffen.com>
Daniel Grunwald <daniel@danielgrunwald.de> Daniel Grunwald <daniel@danielgrunwald.de>
Daniel Hofstetter <daniel.hofstetter@42dh.com> Daniel Hofstetter <daniel.hofstetter@42dh.com>
Daniel Keep <daniel.keep@gmail.com>
Daniel Lobato García <elobatocs@gmail.com> Daniel Lobato García <elobatocs@gmail.com>
Daniel Luz <dev@mernen.com> Daniel Luz <dev@mernen.com>
Daniel MacDougall <dmacdougall@gmail.com> Daniel MacDougall <dmacdougall@gmail.com>
@ -255,9 +302,12 @@ Daniel Patterson <dbp@riseup.net>
Daniel Raloff <draloff@side2.com> Daniel Raloff <draloff@side2.com>
Daniel Ralston <Wubbulous@gmail.com> Daniel Ralston <Wubbulous@gmail.com>
Daniel Ramos <dan@daramos.com> Daniel Ramos <dan@daramos.com>
Daniel Rollins <drollins@financialforce.com>
Daniel Rosenwasser <DanielRosenwasser@gmail.com> Daniel Rosenwasser <DanielRosenwasser@gmail.com>
Daniel Trebbien <dtrebbien@gmail.com>
Daniel Ursache Dogariu <contact@danniel.net> Daniel Ursache Dogariu <contact@danniel.net>
Daniil Smirnov <danslapman@gmail.com> Daniil Smirnov <danslapman@gmail.com>
Danilo Bargen <mail@dbrgn.ch>
Dan Luu <danluu@gmail.com> Dan Luu <danluu@gmail.com>
Dan Schatzberg <schatzberg.dan@gmail.com> Dan Schatzberg <schatzberg.dan@gmail.com>
Dan W. <1danwade@gmail.com> Dan W. <1danwade@gmail.com>
@ -265,11 +315,13 @@ Dan Yang <dsyang@fb.com>
Darin Morrison <darinmorrison+git@gmail.com> Darin Morrison <darinmorrison+git@gmail.com>
darkf <lw9k123@gmail.com> darkf <lw9k123@gmail.com>
Darrell Hamilton <darrell.noice@gmail.com> Darrell Hamilton <darrell.noice@gmail.com>
Dato Simó <dato@net.com.org.es>
Dave Herman <dherman@mozilla.com> Dave Herman <dherman@mozilla.com>
Dave Hodder <dmh@dmh.org.uk> Dave Hodder <dmh@dmh.org.uk>
Dave Huseby <dhuseby@mozilla.com> Dave Huseby <dhuseby@mozilla.com>
David Campbell <dcampbell24@gmail.com> David Campbell <dcampbell24@gmail.com>
David Creswick <dcrewi@gyrae.net> David Creswick <dcrewi@gyrae.net>
David Elliott <david@gophilosophie.com>
David Forsythe <dforsythe@gmail.com> David Forsythe <dforsythe@gmail.com>
David Halperin <halperin.dr@gmail.com> David Halperin <halperin.dr@gmail.com>
David King <dave@davbo.org> David King <dave@davbo.org>
@ -279,17 +331,21 @@ David Manescu <david.manescu@gmail.com>
David Rajchenbach-Teller <dteller@mozilla.com> David Rajchenbach-Teller <dteller@mozilla.com>
David Reid <dreid@dreid.org> David Reid <dreid@dreid.org>
David Renshaw <dwrenshaw@gmail.com> David Renshaw <dwrenshaw@gmail.com>
David Ripton <dripton@ripton.net>
David Ross <daboross@daboross.net> David Ross <daboross@daboross.net>
David Stygstra <david.stygstra@gmail.com> David Stygstra <david.stygstra@gmail.com>
David Szotten <davidszotten@gmail.com>
David Vazgenovich Shakaryan <dvshakaryan@gmail.com> David Vazgenovich Shakaryan <dvshakaryan@gmail.com>
David Voit <david.voit@gmail.com> David Voit <david.voit@gmail.com>
Davis Silverman <sinistersnare@gmail.com> Davis Silverman <sinistersnare@gmail.com>
defuz <defuz.net@gmail.com> defuz <defuz.net@gmail.com>
Denis Defreyne <denis.defreyne@stoneship.org> Denis Defreyne <denis.defreyne@stoneship.org>
DenisKolodin <DenisKolodin@gmail.com>
Derecho <derecho@sector5d.org> Derecho <derecho@sector5d.org>
Derek Chiang <derekchiang93@gmail.com> Derek Chiang <derekchiang93@gmail.com>
Derek Guenther <dguenther9@gmail.com> Derek Guenther <dguenther9@gmail.com>
Derek Harland <derek.harland@finq.co.nz> Derek Harland <derek.harland@finq.co.nz>
Devon Hollowood <devonhollowood@gmail.com>
dgoon <dgoon@dgoon.net> dgoon <dgoon@dgoon.net>
diaphore <diaphore@gmail.com> diaphore <diaphore@gmail.com>
Diego Giagio <diego@giagio.com> Diego Giagio <diego@giagio.com>
@ -311,10 +367,13 @@ Dmitry Vasiliev <dima@hlabs.org>
Dominick Allen <dominick.allen1989@gmail.com> Dominick Allen <dominick.allen1989@gmail.com>
Dominic van Berkel <dominic@baudvine.net> Dominic van Berkel <dominic@baudvine.net>
Dominik Inführ <dominik.infuehr@gmail.com> 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> Do Nhat Minh <mrordinaire@gmail.com>
donkopotamus <general@chocolate-fish.com> donkopotamus <general@chocolate-fish.com>
Donovan Preston <donovanpreston@gmail.com> Donovan Preston <donovanpreston@gmail.com>
Don Petersen <don@donpetersen.net> Don Petersen <don@donpetersen.net>
Doug Goldstein <cardoe@cardoe.com>
Douglas Young <rcxdude@gmail.com> Douglas Young <rcxdude@gmail.com>
Drew Crawford <drew@sealedabstract.com> Drew Crawford <drew@sealedabstract.com>
Drew Willcoxon <adw@mozilla.com> Drew Willcoxon <adw@mozilla.com>
@ -322,8 +381,10 @@ Duane Edwards <mail@duaneedwards.net>
Duncan Regan <duncanregan@gmail.com> Duncan Regan <duncanregan@gmail.com>
Dylan Braithwaite <dylanbraithwaite1@gmail.com> Dylan Braithwaite <dylanbraithwaite1@gmail.com>
Dylan Ede <dylanede@googlemail.com> Dylan Ede <dylanede@googlemail.com>
Dylan McKay <dylanmckay34@gmail.com>
Dzmitry Malyshau <kvarkus@gmail.com> Dzmitry Malyshau <kvarkus@gmail.com>
Earl St Sauver <estsauver@gmail.com> Earl St Sauver <estsauver@gmail.com>
ebadf <brian.cain@gmail.com>
econoplas <econoplas@gmail.com> econoplas <econoplas@gmail.com>
Eduard Bopp <eduard.bopp@aepsil0n.de> Eduard Bopp <eduard.bopp@aepsil0n.de>
Eduard Burtescu <edy.burt@gmail.com> Eduard Burtescu <edy.burt@gmail.com>
@ -339,12 +400,14 @@ Elliott Slaughter <elliottslaughter@gmail.com>
Elly Fong-Jones <elly@leptoquark.net> Elly Fong-Jones <elly@leptoquark.net>
elszben <notgonna@tellyou> elszben <notgonna@tellyou>
emanueLczirai <emanueLczirai@cryptoLab.net> emanueLczirai <emanueLczirai@cryptoLab.net>
Emanuel Czirai <zazdxscf@gmail.com>
Emanuel Rylke <ema-fox@web.de> Emanuel Rylke <ema-fox@web.de>
Emeliov Dmitrii <demelev1990@gmail.com> Emeliov Dmitrii <demelev1990@gmail.com>
Emilio Cobos Álvarez <ecoal95@gmail.com> Emilio Cobos Álvarez <ecoal95@gmail.com>
Emily Dunham <edunham@mozilla.com> Emily Dunham <edunham@mozilla.com>
Eric Allen <ericpallen@gmail.com> Eric Allen <ericpallen@gmail.com>
Eric Biggers <ebiggers3@gmail.com> Eric Biggers <ebiggers3@gmail.com>
Eric Findlay <e.findlay@protonmail.com>
Eric Holk <eric.holk@gmail.com> Eric Holk <eric.holk@gmail.com>
Eric Holmes <eric@ejholmes.net> Eric Holmes <eric@ejholmes.net>
Eric Kidd <git@randomhacks.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 Platon <eric.platon@waku-waku.ne.jp>
Eric Reed <ecreed@cs.washington.edu> Eric Reed <ecreed@cs.washington.edu>
Eric Ye <me@ericye16.com> Eric Ye <me@ericye16.com>
Erik Davidson <erik@erikd.org>
Erik Lyon <elyon001@local.fake> Erik Lyon <elyon001@local.fake>
Erik Michaels-Ober <sferik@gmail.com> Erik Michaels-Ober <sferik@gmail.com>
Erik Price <erik.price16@gmail.com> Erik Price <erik.price16@gmail.com>
@ -366,8 +430,9 @@ Eunchong Yu <kroisse@gmail.com>
Eunji Jeong <eun-ji.jeong@samsung.com> Eunji Jeong <eun-ji.jeong@samsung.com>
Evan Klitzke <evan@eklitzke.org> Evan Klitzke <evan@eklitzke.org>
Evan McClanahan <evan@evanmcc.com> Evan McClanahan <evan@evanmcc.com>
Evgeny Sologubov Evgeny Sologubov <bogus>
Fabian Deutsch <fabian.deutsch@gmx.de> Fabian Deutsch <fabian.deutsch@gmx.de>
Fabiano Beselga <fabianobeselga@gmail.com>
Fabrice Desré <fabrice@desre.org> Fabrice Desré <fabrice@desre.org>
FakeKane <andrewyli@gmail.com> FakeKane <andrewyli@gmail.com>
Falco Hirschenberger <falco.hirschenberger@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> fenduru <fenduru@users.noreply.github.com>
Fenhl <fenhl@fenhl.net> Fenhl <fenhl@fenhl.net>
Filip Szczepański <jazz2rulez@gmail.com> Filip Szczepański <jazz2rulez@gmail.com>
Flaper Fesp <flaper87@gmail.com> Flavio Percoco <flaper87@gmail.com>
flo-l <lacknerflo@gmail.com> flo-l <lacknerflo@gmail.com>
Florian Gilcher <florian.gilcher@asquera.de> Florian Gilcher <florian.gilcher@asquera.de>
Florian Hahn <flo@fhahn.com> Florian Hahn <flo@fhahn.com>
@ -418,11 +483,13 @@ Germano Gabbianelli <tyrion@users.noreply.github.com>
Gil Cottle <rc@redtown.org> Gil Cottle <rc@redtown.org>
Gioele Barabucci <gioele@svario.it> Gioele Barabucci <gioele@svario.it>
github-monoculture <eocene@gmx.com> github-monoculture <eocene@gmx.com>
GlacJAY <glacjay@gmail.com>
Gleb Kozyrev <gleb@gkoz.com> Gleb Kozyrev <gleb@gkoz.com>
glendc <decauwsemaecker.glen@gmail.com>
Glenn Willen <gwillen@nerdnet.org> Glenn Willen <gwillen@nerdnet.org>
Gonçalo Cabrita <_@gmcabrita.com> Gonçalo Cabrita <_@gmcabrita.com>
Grahame Bowland <grahame@angrygoats.net> Grahame Bowland <grahame@angrygoats.net>
Graham Fawcett <graham.fawcett@gmail.com> Graham Fawcett <fawcett@uwindsor.ca>
Graydon Hoare <graydon@pobox.com> Graydon Hoare <graydon@pobox.com>
Greg Chapple <gregchapple1@gmail.com> Greg Chapple <gregchapple1@gmail.com>
Grigoriy <ohaistarlight@gmail.com> Grigoriy <ohaistarlight@gmail.com>
@ -447,6 +514,7 @@ Honza Strnad <hanny.strnad@gmail.com>
Huachao Huang <huachao.huang@gmail.com> Huachao Huang <huachao.huang@gmail.com>
Hugo Jobling <hello@thisishugo.com> Hugo Jobling <hello@thisishugo.com>
Hugo van der Wijst <hugo@wij.st> Hugo van der Wijst <hugo@wij.st>
Hunan Rostomyan <hunan131@gmail.com>
Huon Wilson <dbau.pp+github@gmail.com> Huon Wilson <dbau.pp+github@gmail.com>
Hyeon Kim <simnalamburt@gmail.com> Hyeon Kim <simnalamburt@gmail.com>
Ian Connolly <iconnolly@mozilla.com> Ian Connolly <iconnolly@mozilla.com>
@ -454,22 +522,30 @@ Ian Daniher <it.daniher@gmail.com>
Ian D. Bollinger <ian.bollinger@gmail.com> Ian D. Bollinger <ian.bollinger@gmail.com>
Ignacio Corderi <icorderi@msn.com> Ignacio Corderi <icorderi@msn.com>
Igor Bukanov <igor@mir2.org> Igor Bukanov <igor@mir2.org>
Igor Shuvalov <i.s.shuvalov@gmail.com>
Igor Strebezhev <xamgore@ya.ru> Igor Strebezhev <xamgore@ya.ru>
Ilya Dmitrichenko <ilya@xively.com> Ilya Dmitrichenko <ilya@xively.com>
Ilyong Cho <ilyoan@gmail.com> Ilyong Cho <ilyoan@gmail.com>
Ingo Blechschmidt <iblech@web.de> Ingo Blechschmidt <iblech@web.de>
inrustwetrust <inrustwetrust@users.noreply.github.com> inrustwetrust <inrustwetrust@users.noreply.github.com>
Irving A.J. Rivas Z. <axel.rivas@gmail.com>
Isaac Aggrey <isaac.aggrey@gmail.com> Isaac Aggrey <isaac.aggrey@gmail.com>
Isaac Dupree <antispam@idupree.com> Isaac Dupree <antispam@idupree.com>
Isaac Ge <acgtyrant@gmail.com> Isaac Ge <acgtyrant@gmail.com>
Ivan Enderlin <ivan.enderlin@hoa-project.net> 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> Ivano Coppola <rgbfirefox@gmail.com>
Ivan Petkov <ivanppetkov@gmail.com> Ivan Petkov <ivanppetkov@gmail.com>
Ivan Radanov Ivanov <ivanradanov@yahoo.co.uk> Ivan Radanov Ivanov <ivanradanov@yahoo.co.uk>
Ivan Stankovic <pokemon@fly.srk.fer.hr>
Ivan Ukhov <ivan.ukhov@gmail.com> Ivan Ukhov <ivan.ukhov@gmail.com>
Iven Hsu <ivenvd@gmail.com> Iven Hsu <ivenvd@gmail.com>
Jack Fransham <moonfudgeman@hotmail.co.uk>
Jack Heizer <jack.heizer@gmail.com> Jack Heizer <jack.heizer@gmail.com>
Jack Moffitt <jack@metajack.im> Jack Moffitt <jack@metajack.im>
Jack Wilson <jack.wilson.v@gmail.com>
Jacob Edelman <edelman.jd@gmail.com> Jacob Edelman <edelman.jd@gmail.com>
Jacob Harris Cryer Kragh <jhckragh@gmail.com> Jacob Harris Cryer Kragh <jhckragh@gmail.com>
Jacob Hegna <jacobhegna@gmail.com> Jacob Hegna <jacobhegna@gmail.com>
@ -481,14 +557,18 @@ Jake Hickey <empty@cqdr.es>
Jake Kaufman <theevocater@gmail.com> Jake Kaufman <theevocater@gmail.com>
Jake Kerr <kodafox@gmail.com> Jake Kerr <kodafox@gmail.com>
Jake Scott <jake.net@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 Bukaj <jakub@jakub.cc>
Jakub Vrána <jakub@vrana.cz> Jakub Vrána <jakub@vrana.cz>
Jakub Wieczorek <jakubw@jakubw.net> Jakub Wieczorek <jakubw@jakubw.net>
James Bell <james.bell@gmail.com>
James Deng <cnjamesdeng@gmail.com> James Deng <cnjamesdeng@gmail.com>
James Hurst <jamesrhurst@users.noreply.github.com> James Hurst <jamesrhurst@users.noreply.github.com>
James Lal <james@lightsofapollo.com> James Lal <james@lightsofapollo.com>
James Laverack <james@jameslaverack.com> James Laverack <james@jameslaverack.com>
jamesluke <jamesluke@users.noreply.github.com> jamesluke <jamesluke@users.noreply.github.com>
James McGlashan <github@darkfox.id.au>
James Miller <bladeon@gmail.com> James Miller <bladeon@gmail.com>
James Perry <james.austin.perry@gmail.com> James Perry <james.austin.perry@gmail.com>
James Rowe <jroweboy@gmail.com> James Rowe <jroweboy@gmail.com>
@ -518,6 +598,7 @@ Jay True <glacjay@gmail.com>
J Bailey <jj2baile@uwaterloo.ca> J Bailey <jj2baile@uwaterloo.ca>
jbranchaud <jbranchaud@gmail.com> jbranchaud <jbranchaud@gmail.com>
J.C. Moyer <jmoyer1992@gmail.com> J.C. Moyer <jmoyer1992@gmail.com>
Jean Maillard <jeanm@users.noreply.github.com>
Jeaye <jeaye@arrownext.com> Jeaye <jeaye@arrownext.com>
Jed Davis <jld@panix.com> Jed Davis <jld@panix.com>
Jed Estep <aje@jhu.edu> Jed Estep <aje@jhu.edu>
@ -527,6 +608,7 @@ Jeff Belgum <jeffbelgum@gmail.com>
Jeff Muizelaar <jmuizelaar@mozilla.com> Jeff Muizelaar <jmuizelaar@mozilla.com>
Jeff Olson <olson.jeffery@gmail.com> Jeff Olson <olson.jeffery@gmail.com>
Jeff Parsons <jeffdougson@gmail.com> Jeff Parsons <jeffdougson@gmail.com>
Jeffrey Seyfried <jeffrey.seyfried@gmail.com>
Jeffrey Yasskin <jyasskin@gmail.com> Jeffrey Yasskin <jyasskin@gmail.com>
Jelte Fennema <github-tech@jeltef.nl> Jelte Fennema <github-tech@jeltef.nl>
Jens Nockert <jens@nockert.se> Jens Nockert <jens@nockert.se>
@ -539,10 +621,11 @@ Jesse Ray <jesse@localhost.localdomain>
Jesse Ruderman <jruderman@gmail.com> Jesse Ruderman <jruderman@gmail.com>
Jessy Diamond Exum <jessy.diamondman@gmail.com> Jessy Diamond Exum <jessy.diamondman@gmail.com>
Jesús Espino <jespinog@gmail.com> Jesús Espino <jespinog@gmail.com>
Jethro Beekman <jethro@jbeekman.nl>
jethrogb <github@jbeekman.nl> jethrogb <github@jbeekman.nl>
Jexell <Jexell@users.noreply.github.com> Jexell <Jexell@users.noreply.github.com>
Jihyeok Seo <me@limeburst.net> 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 Apple <jbapple+rust@google.com>
Jim Blandy <jimb@red-bean.com> Jim Blandy <jimb@red-bean.com>
Jimmie Elvenmark <flugsio@gmail.com> Jimmie Elvenmark <flugsio@gmail.com>
@ -554,13 +637,14 @@ J. J. Weber <jjweber@gmail.com>
jmgrosen <jmgrosen@gmail.com> jmgrosen <jmgrosen@gmail.com>
jmu303 <muj@bc.edu> jmu303 <muj@bc.edu>
João Oliveira <hello@jxs.pt> João Oliveira <hello@jxs.pt>
joaoxsouls <joaoxsouls@gmail.com>
Joe Pletcher <joepletcher@gmail.com> Joe Pletcher <joepletcher@gmail.com>
Joe Schafer <joe@jschaf.com> Joe Schafer <joe@jschaf.com>
Johannes Hoff <johshoff@gmail.com> Johannes Hoff <johshoff@gmail.com>
Johannes Löthberg <johannes@kyriasis.com> Johannes Löthberg <johannes@kyriasis.com>
Johannes Muenzel <jmuenzel@gmail.com> Johannes Muenzel <jmuenzel@gmail.com>
Johannes Oertel <johannes.oertel@uni-due.de> Johannes Oertel <johannes.oertel@uni-due.de>
Johann Hofmann <git@johann-hofmann.com> Johann Hofmann <mail@johann-hofmann.com>
Johann Tuffe <tafia973@gmail.com> Johann Tuffe <tafia973@gmail.com>
John Albietz <inthecloud247@gmail.com> John Albietz <inthecloud247@gmail.com>
John Barker <jebarker@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 Schmidt <john.schmidt.h@gmail.com>
John Simon <john@johnsoft.com> John Simon <john@johnsoft.com>
John Talling <inrustwetrust@users.noreply.github.com> John Talling <inrustwetrust@users.noreply.github.com>
John Thomas <thomas07@vt.edu>
John Van Enk <vanenkj@gmail.com> John Van Enk <vanenkj@gmail.com>
John Zhang <john@zhang.io> John Zhang <john@zhang.io>
joliv <joliv@users.noreply.github.com> joliv <joliv@users.noreply.github.com>
Jonas Hietala <tradet.h@gmail.com> Jonas Hietala <tradet.h@gmail.com>
Jonas Schievink <jonas@schievink.net>
Jonathan Bailey <jbailey@mozilla.com> Jonathan Bailey <jbailey@mozilla.com>
Jonathan Boyett <jonathan@failingservers.com> Jonathan Boyett <jonathan@failingservers.com>
Jonathan Hansford <dangthrimble@hansfords.net> Jonathan Hansford <dangthrimble@hansfords.net>
@ -593,25 +679,32 @@ Joonas Javanainen <joonas.javanainen@gmail.com>
Jordan Humphreys <mrsweaters@users.noreply.github.com> Jordan Humphreys <mrsweaters@users.noreply.github.com>
Jordan Woehr <jordanwoehr@gmail.com> Jordan Woehr <jordanwoehr@gmail.com>
Jordi Boggiano <j.boggiano@seld.be> 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> Jorge Israel Peña <jorge.israel.p@gmail.com>
Joris Rehm <joris.rehm@wakusei.fr> Joris Rehm <joris.rehm@wakusei.fr>
Jormundir <Chaseph@gmail.com> Jormundir <Chaseph@gmail.com>
Jørn Lode <jlode90@gmail.com>
Jose Narvaez <jnarvaez@zendesk.com> Jose Narvaez <jnarvaez@zendesk.com>
Joseph Caudle <joseph@josephcaudle.com>
Joseph Crail <jbcrail@gmail.com> Joseph Crail <jbcrail@gmail.com>
Joseph Martin <pythoner6@gmail.com> Joseph Martin <pythoner6@gmail.com>
Joseph Rushton Wakeling <joe@webdrake.net> Joseph Rushton Wakeling <joe@webdrake.net>
Josh Austin <josh.austin@gmail.com>
Josh Haberman <jhaberman@gmail.com> Josh Haberman <jhaberman@gmail.com>
Josh Matthews <josh@joshmatthews.net> Josh Matthews <josh@joshmatthews.net>
Josh Stone <cuviper@gmail.com> Josh Stone <cuviper@gmail.com>
Josh Triplett <josh@joshtriplett.org> Josh Triplett <josh@joshtriplett.org>
Joshua Clark <joshua.clark@txstate.edu> Joshua Clark <joshua.clark@txstate.edu>
Joshua Holmer <holmerj@uindy.edu>
Joshua Landau <joshua@landau.ws> Joshua Landau <joshua@landau.ws>
Joshua Wise <joshua@joshuawise.com> Joshua Wise <joshua@joshuawise.com>
Joshua Yanovski <pythonesque@gmail.com> Joshua Yanovski <pythonesque@gmail.com>
jotomicron <jotomicron@gmail.com>
JP-Ellis <coujellis@gmail.com> JP-Ellis <coujellis@gmail.com>
JP Sugarbroad <jpsugar@google.com> JP Sugarbroad <jpsugar@google.com>
jrburke <jrburke@gmail.com>
jrincayc <jrincayc@users.noreply.github.com> jrincayc <jrincayc@users.noreply.github.com>
J. Ryan Stinnett <jryans@gmail.com>
Julia Evans <julia@jvns.ca> Julia Evans <julia@jvns.ca>
Julian Orth <ju.orth@gmail.com> Julian Orth <ju.orth@gmail.com>
Julian Viereck <julian.viereck@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 Rauwolf <sweetpea-git@tentacle.net>
Kevin Walter <kevin.walter.private@googlemail.com> Kevin Walter <kevin.walter.private@googlemail.com>
Kevin Yap <me@kevinyap.ca> Kevin Yap <me@kevinyap.ca>
Kevin Yeh <kevinyeah@utexas.edu>
kgv <mail@kgv.name> kgv <mail@kgv.name>
kickinbahk <kickinbahk@gmail.com>
Kieran Hunt <kieran.hunt92@gmail.com> Kieran Hunt <kieran.hunt92@gmail.com>
Kiet Tran <ktt3ja@gmail.com> Kiet Tran <ktt3ja@gmail.com>
Kim Røen <kim@pam.no> Kim Røen <kim@pam.no>
kjpgit <kjpgit@users.noreply.github.com> kjpgit <kjpgit@users.noreply.github.com>
klutzy <klutzytheklutzy@gmail.com> klutzy <klutzytheklutzy@gmail.com>
Kohei Hasegawa <ameutau@gmail.com>
KokaKiwi <kokakiwi+rust@kokakiwi.net> KokaKiwi <kokakiwi+rust@kokakiwi.net>
korenchkin <korenchkin2@gmail.com> korenchkin <korenchkin2@gmail.com>
Kornel Lesiński <kornel@geekhood.net> Kornel Lesiński <kornel@geekhood.net>
@ -657,6 +753,8 @@ Kubilay Kocak <koobs@users.noreply.github.com>
kulakowski <george.kulakowski@gmail.com> kulakowski <george.kulakowski@gmail.com>
kwantam <kwantam@gmail.com> kwantam <kwantam@gmail.com>
Kyeongwoon Lee <kyeongwoon.lee@samsung.com> Kyeongwoon Lee <kyeongwoon.lee@samsung.com>
Kyle Mayes <kyle@mayeses.com>
Kyle Robinson Young <kyle@dontkry.com>
Lai Jiangshan <laijs@cn.fujitsu.com> Lai Jiangshan <laijs@cn.fujitsu.com>
Lars Bergstrom <lbergstrom@mozilla.com> Lars Bergstrom <lbergstrom@mozilla.com>
Laurence Tratt <laurie@tratt.net> Laurence Tratt <laurie@tratt.net>
@ -666,6 +764,7 @@ Lawrence Velázquez <larryv@alum.mit.edu>
Leah Hanson <astrieanna@gmail.com> Leah Hanson <astrieanna@gmail.com>
Lee Aronson <lee@libertad.ucsd.edu> Lee Aronson <lee@libertad.ucsd.edu>
Lee Jeffery <leejeffery@gmail.com> Lee Jeffery <leejeffery@gmail.com>
Lee Jenkins <cljenkins9@gmail.com>
Lee Wondong <wdlee91@gmail.com> Lee Wondong <wdlee91@gmail.com>
Leif Arne Storset <leifarne@storset.net> Leif Arne Storset <leifarne@storset.net>
LemmingAvalanche <haugsbakk@yahoo.no> LemmingAvalanche <haugsbakk@yahoo.no>
@ -678,6 +777,7 @@ Liam Monahan <liam@monahan.io>
Liigo Zhuang <com.liigo@gmail.com> Liigo Zhuang <com.liigo@gmail.com>
Lindsey Kuper <lindsey@composition.al> Lindsey Kuper <lindsey@composition.al>
Lionel Flandrin <lionel.flandrin@parrot.com> Lionel Flandrin <lionel.flandrin@parrot.com>
llogiq <bogusandre@gmail.com>
Logan Chien <tzuhsiang.chien@gmail.com> Logan Chien <tzuhsiang.chien@gmail.com>
Loïc Damien <loic.damien@dzamlo.ch> Loïc Damien <loic.damien@dzamlo.ch>
Lorenz <lorenzb@student.ethz.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> Makoto Nakashima <makoto.nksm+github@gmail.com>
Manish Goregaokar <manishsmail@gmail.com> Manish Goregaokar <manishsmail@gmail.com>
Manuel Hoffmann <manuel@polythematik.de> Manuel Hoffmann <manuel@polythematik.de>
Marc-Antoine Perennou <Marc-Antoine@Perennou.com>
marcell <marcell.pardavi@gmail.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 Müller <neikos@neikos.email>
Marcel Rodrigues <marcelgmr@gmail.com> Marcel Rodrigues <marcelgmr@gmail.com>
Marcus Klaas <mail@marcusklaas.nl> Marcus Klaas <mail@marcusklaas.nl>
@ -712,6 +815,7 @@ Mário Feroldi <thelost-t@live.com>
Mark Buer <mark.buer@booktrack.com> Mark Buer <mark.buer@booktrack.com>
Mark Lacey <641@rudkx.com> Mark Lacey <641@rudkx.com>
Mark Mossberg <mark.mossberg@gmail.com> Mark Mossberg <mark.mossberg@gmail.com>
Marko Lalic <marko.lalic@gmail.com>
Mark Rowe <mrowe@bdash.net.nz> Mark Rowe <mrowe@bdash.net.nz>
Mark Sinclair <mark.edward.x@gmail.com> Mark Sinclair <mark.edward.x@gmail.com>
Markus Siemens <siemens1993@gmail.com> Markus Siemens <siemens1993@gmail.com>
@ -721,9 +825,11 @@ Mark Vian <mrv.caseus@gmail.com>
Martin DeMello <martindemello@gmail.com> Martin DeMello <martindemello@gmail.com>
Martin Olsson <martin@minimum.se> Martin Olsson <martin@minimum.se>
Martin Pool <mbp@sourcefrog.net> Martin Pool <mbp@sourcefrog.net>
Martin Wernstål <m4rw3r@gmail.com>
Marti Raudsepp <marti@juffo.org> Marti Raudsepp <marti@juffo.org>
Marvin Löbel <loebel.marvin@gmail.com> Marvin Löbel <loebel.marvin@gmail.com>
masklinn <github.com@masklinn.net> masklinn <github.com@masklinn.net>
Matěj Grabovský <mgrabovsky@yahoo.com>
Matej Lach <matej.lach@gmail.com> Matej Lach <matej.lach@gmail.com>
Mateusz Czapliński <czapkofan@gmail.com> Mateusz Czapliński <czapkofan@gmail.com>
Mathieu David <mathieudavid@mathieudavid.org> Mathieu David <mathieudavid@mathieudavid.org>
@ -740,7 +846,9 @@ Matthew Auld <matthew.auld@intel.com>
Matthew Iselin <matthew@theiselins.net> Matthew Iselin <matthew@theiselins.net>
Matthew McPherrin <matthew@mcpherrin.ca> Matthew McPherrin <matthew@mcpherrin.ca>
Matthew O'Connor <thegreendragon@gmail.com> Matthew O'Connor <thegreendragon@gmail.com>
Matthias Bussonnier <bussonniermatthias@gmail.com>
Matthias Einwag <matthias.einwag@live.com> Matthias Einwag <matthias.einwag@live.com>
Matthias Kauer <mk.software@zuez.org>
Matthijs Hofstra <thiezz@gmail.com> Matthijs Hofstra <thiezz@gmail.com>
Matthijs van der Vleuten <git@zr40.nl> Matthijs van der Vleuten <git@zr40.nl>
Matt McPherrin <git@mcpherrin.ca> Matt McPherrin <git@mcpherrin.ca>
@ -762,15 +870,18 @@ Michael Alexander <beefsack@gmail.com>
Michael Arntzenius <daekharel@gmail.com> Michael Arntzenius <daekharel@gmail.com>
Michael Bebenita <mbebenita@mozilla.com> Michael Bebenita <mbebenita@mozilla.com>
Michael Budde <mbudde@gmail.com> Michael Budde <mbudde@gmail.com>
Michael Choate <choatemd@miamioh.edu>
Michael Dagitses <dagitses@google.com> Michael Dagitses <dagitses@google.com>
Michael Darakananda <pongad@gmail.com> Michael Darakananda <pongad@gmail.com>
Michael Fairley <michaelfairley@gmail.com> Michael Fairley <michaelfairley@gmail.com>
Michael Gehring <mg@ebfe.org> Michael Gehring <mg@ebfe.org>
Michael Howell <michael@notriddle.com>
Michael Kainer <kaini1123@gmail.com> Michael Kainer <kaini1123@gmail.com>
Michael Layzell <michael@thelayzells.com> Michael Layzell <michael@thelayzells.com>
Michael Letterle <michael.letterle@gmail.com> Michael Letterle <michael.letterle@gmail.com>
Michael Macias <zaeleus@gmail.com> Michael Macias <zaeleus@gmail.com>
Michael Matuzak <mmatuzak@gmail.com> Michael Matuzak <mmatuzak@gmail.com>
Michael McConville <mmcconville@mykolab.com>
Michael Neumann <mneumann@ntecs.de> Michael Neumann <mneumann@ntecs.de>
Michael Pankov <work@michaelpankov.com> Michael Pankov <work@michaelpankov.com>
Michael Park <mcypark@gmail.com> Michael Park <mcypark@gmail.com>
@ -790,10 +901,12 @@ Mickaël Raybaud-Roig <raybaudroigm@gmail.com>
Mickaël Salaün <mic@digikod.net> Mickaël Salaün <mic@digikod.net>
Mick Koch <kchmck@gmail.com> Mick Koch <kchmck@gmail.com>
midinastasurazz <mpavlovsky@gmail.com> midinastasurazz <mpavlovsky@gmail.com>
Mihaly Barasz <klao@nilcons.com>
Mihnea Dobrescu-Balaur <mihnea@linux.com> Mihnea Dobrescu-Balaur <mihnea@linux.com>
Mike Boutin <mike.boutin@gmail.com> Mike Boutin <mike.boutin@gmail.com>
Mike Dilger <mike@efx.co.nz> Mike Dilger <mike@efx.co.nz>
Mike English <mike.english@atomicobject.com> Mike English <mike.english@atomicobject.com>
Mike Marcacci <mike.marcacci@gmail.com>
Mike Pedersen <noctune9@gmail.com> Mike Pedersen <noctune9@gmail.com>
Mike Robinson <mikeprobinsonuk@gmail.com> Mike Robinson <mikeprobinsonuk@gmail.com>
Mike Sampson <mike@sambodata.com> Mike Sampson <mike@sambodata.com>
@ -814,6 +927,7 @@ nathan dotz <nathan.dotz@gmail.com>
Nathan Froyd <froydnj@gmail.com> Nathan Froyd <froydnj@gmail.com>
Nathaniel Herman <nherman@post.harvard.edu> Nathaniel Herman <nherman@post.harvard.edu>
Nathaniel Theis <nttheis@gmail.com> Nathaniel Theis <nttheis@gmail.com>
Nathan Kleyn <nathan@nathankleyn.com>
Nathan Long <nathanmlong@gmail.com> Nathan Long <nathanmlong@gmail.com>
Nathan Stoddard <nstodda@purdue.edu> Nathan Stoddard <nstodda@purdue.edu>
Nathan Typanski <ntypanski@gmail.com> Nathan Typanski <ntypanski@gmail.com>
@ -822,9 +936,11 @@ Nathan Zadoks <nathan@nathan7.eu>
Neil Pankey <npankey@gmail.com> Neil Pankey <npankey@gmail.com>
Nelo Onyiah <nelo.onyiah@gmail.com> Nelo Onyiah <nelo.onyiah@gmail.com>
Nelson Chen <crazysim@gmail.com> Nelson Chen <crazysim@gmail.com>
nham <hamann.nick@gmail.com>
NiccosSystem <niccossystem@gmail.com> NiccosSystem <niccossystem@gmail.com>
Nicholas Bishop <nicholasbishop@gmail.com> Nicholas Bishop <nicholasbishop@gmail.com>
Nicholas Mazzuca <npmazzuca@gmail.com> Nicholas Mazzuca <npmazzuca@gmail.com>
Nicholas Seckar <nseckar@gmail.com>
Nick Cameron <ncameron@mozilla.com> Nick Cameron <ncameron@mozilla.com>
Nick Desaulniers <ndesaulniers@mozilla.com> Nick Desaulniers <ndesaulniers@mozilla.com>
Nick Fitzgerald <fitzgen@gmail.com> Nick Fitzgerald <fitzgen@gmail.com>
@ -839,9 +955,11 @@ Niels langager Ellegaard <niels.ellegaard@gmail.com>
Nif Ward <nif.ward@gmail.com> Nif Ward <nif.ward@gmail.com>
Nikita Pekin <contact@nikitapek.in> Nikita Pekin <contact@nikitapek.in>
Niklas Koep <niklas.koep@gmail.com> Niklas Koep <niklas.koep@gmail.com>
Nikolay Kondratyev <nkondratyev@yandex.ru>
Niko Matsakis <niko@alum.mit.edu> Niko Matsakis <niko@alum.mit.edu>
Nils Liberg <nils@nilsliberg.se> Nils Liberg <nils@nilsliberg.se>
Nils Winter <nils.winter@gmail.com> Nils Winter <nils.winter@gmail.com>
Niranjan Padmanabhan <niranjan.padmanabhan@cloudera.com>
noam <noam@clusterfoo.com> noam <noam@clusterfoo.com>
Noam Yorav-Raphael <noamraph@gmail.com> Noam Yorav-Raphael <noamraph@gmail.com>
NODA, Kai <nodakai@gmail.com> NODA, Kai <nodakai@gmail.com>
@ -849,25 +967,31 @@ Noufal Ibrahim <noufal@nibrahim.net.in>
novalis <novalis@novalis.org> novalis <novalis@novalis.org>
nsf <no.smile.face@gmail.com> nsf <no.smile.face@gmail.com>
nwin <nwin@users.noreply.github.com> nwin <nwin@users.noreply.github.com>
nxnfufunezn <nxnfufunezn@gmail.com>
Oak <White-Oak@users.noreply.github.com> Oak <White-Oak@users.noreply.github.com>
OGINO Masanori <masanori.ogino@gmail.com> OGINO Masanori <masanori.ogino@gmail.com>
OlegTsyba <idethrone1@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> Olivier Saut <osaut@airpost.net>
olivren <o.renaud@gmx.fr> olivren <o.renaud@gmx.fr>
Olle Jonsson <olle.jonsson@gmail.com> Olle Jonsson <olle.jonsson@gmail.com>
olombard <lombard-olivier@bbox.fr> olombard <lombard-olivier@bbox.fr>
Or Brostovski <tohava@gmail.com> Or Brostovski <tohava@gmail.com>
Oren Hazi <oren.hazi@gmail.com> Oren Hazi <oren.hazi@gmail.com>
Ori Avtalion <ori@avtalion.name>
Or Neeman <oneeman@gmail.com> Or Neeman <oneeman@gmail.com>
Orphée Lafond-Lummis <o@orftz.com> Orphée Lafond-Lummis <o@orftz.com>
Orpheus Lummis <o@orpheuslummis.com> Orpheus Lummis <o@orpheuslummis.com>
osa1 <omeragacan@gmail.com> osa1 <omeragacan@gmail.com>
O S K Chaitanya <osk@medhas.org> O S K Chaitanya <osk@medhas.org>
Overmind JIANG <p90eri@gmail.com>
Ožbolt Menegatti <ozbolt.menegatti@gmail.com> Ožbolt Menegatti <ozbolt.menegatti@gmail.com>
P1start <rewi-github@whanau.org> P1start <rewi-github@whanau.org>
Pablo Brasero <pablo@pablobm.com> Pablo Brasero <pablo@pablobm.com>
Palmer Cox <p@lmercox.com> Palmer Cox <p@lmercox.com>
panicbit <panicbit.dev@gmail.com>
Paolo Falabella <paolo.falabella@gmail.com> Paolo Falabella <paolo.falabella@gmail.com>
Parker Moore <parkrmoore@gmail.com> Parker Moore <parkrmoore@gmail.com>
Pascal Hertleif <killercup@gmail.com> Pascal Hertleif <killercup@gmail.com>
@ -876,6 +1000,7 @@ Patrick Walton <pcwalton@mimiga.net>
Patrick Yevsukov <patrickyevsukov@users.noreply.github.com> Patrick Yevsukov <patrickyevsukov@users.noreply.github.com>
Patrik Kårlin <patrik.karlin@gmail.com> Patrik Kårlin <patrik.karlin@gmail.com>
Paul ADENOT <paul@paul.cx> Paul ADENOT <paul@paul.cx>
Paul A. Jungwirth <pj@illuminatedcomputing.com>
Paul Banks <banks@banksdesigns.co.uk> Paul Banks <banks@banksdesigns.co.uk>
Paul Collier <paul@paulcollier.ca> Paul Collier <paul@paulcollier.ca>
Paul Collins <paul@ondioline.org> Paul Collins <paul@ondioline.org>
@ -898,6 +1023,7 @@ Peter Elmers <peter.elmers@yahoo.com>
Peter Hull <peterhull90@gmail.com> Peter Hull <peterhull90@gmail.com>
Peter Marheine <peter@taricorp.net> Peter Marheine <peter@taricorp.net>
Peter Minten <peter@pminten.nl> Peter Minten <peter@pminten.nl>
Peter Reid <peter.d.reid@gmail.com>
Peter Schuller <peter.schuller@infidyne.com> Peter Schuller <peter.schuller@infidyne.com>
Peter Williams <peter@newton.cx> Peter Williams <peter@newton.cx>
Peter Zotov <whitequark@whitequark.org> Peter Zotov <whitequark@whitequark.org>
@ -907,8 +1033,11 @@ Phil Dawes <phil@phildawes.net>
Philip Munksgaard <pmunksgaard@gmail.com> Philip Munksgaard <pmunksgaard@gmail.com>
Philipp Brüschweiler <blei42@gmail.com> Philipp Brüschweiler <blei42@gmail.com>
Philipp Gesang <phg42.2a@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> Phil Ruffwind <rf@rufflewind.com>
Pierre Baillet <pierre@baillet.name> Pierre Baillet <pierre@baillet.name>
pierzchalski <e.a.pierzchalski@gmail.com>
Piotr Czarnecki <pioczarn@gmail.com> Piotr Czarnecki <pioczarn@gmail.com>
Piotr Jawniak <sawyer47@gmail.com> Piotr Jawniak <sawyer47@gmail.com>
Piotr Szotkowski <chastell@chastell.net> Piotr Szotkowski <chastell@chastell.net>
@ -916,10 +1045,12 @@ Piotr Zolnierek <pz@anixe.pl>
Poga Po <poga.bahamut@gmail.com> Poga Po <poga.bahamut@gmail.com>
posixphreak <posixphreak@gmail.com> posixphreak <posixphreak@gmail.com>
Potpourri <pot_pourri@mail.ru> Potpourri <pot_pourri@mail.ru>
Pradeep Kumar <gohanpra@gmail.com>
Prudhvi Krishna Surapaneni <me@prudhvi.net> Prudhvi Krishna Surapaneni <me@prudhvi.net>
Przemysław Wesołek <jest@go.art.pl> Przemysław Wesołek <jest@go.art.pl>
Pyfisch <pyfisch@gmail.com> Pyfisch <pyfisch@gmail.com>
Pyry Kontio <pyry.kontio@drasa.eu> Pyry Kontio <pyry.kontio@drasa.eu>
Pythoner6 <pythoner6@gmail.com>
Q.P.Liu <qpliu@yahoo.com> Q.P.Liu <qpliu@yahoo.com>
qwitwa <qwitwa@gmail.com> qwitwa <qwitwa@gmail.com>
Rafael Ávila de Espíndola <respindola@mozilla.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 Nestler <raphael.nestler@gmail.com>
Raphael Speyer <rspeyer@gmail.com> Raphael Speyer <rspeyer@gmail.com>
Raul Gutierrez S <rgs@itevenworks.net> Raul Gutierrez S <rgs@itevenworks.net>
Ravi Shankar <wafflespeanut@gmail.com>
Ray Clanan <rclanan@utopianconcept.com> Ray Clanan <rclanan@utopianconcept.com>
ray glover <ray@rayglover.net> ray glover <ray@rayglover.net>
reedlepee <reedlepee123@gmail.com> reedlepee <reedlepee123@gmail.com>
@ -942,20 +1074,25 @@ Rémi Audebert <halfr@lse.epita.fr>
Remi Rampin <remirampin@gmail.com> Remi Rampin <remirampin@gmail.com>
Renato Alves <alves.rjc@gmail.com> Renato Alves <alves.rjc@gmail.com>
Renato Riccieri Santos Zannon <renato@rrsz.com.br> Renato Riccieri Santos Zannon <renato@rrsz.com.br>
Renato Zannon <renato@rrsz.com.br>
Reuben Morais <reuben.morais@gmail.com> Reuben Morais <reuben.morais@gmail.com>
reus <reusee@ymail.com> reus <reusee@ymail.com>
Reza Akhavan <reza@akhavan.me>
Ricardo Martins <ricardo@scarybox.net> Ricardo Martins <ricardo@scarybox.net>
Ricardo M. Correia <rcorreia@wizy.org> Ricardo M. Correia <rcorreia@wizy.org>
Ricardo Signes <rjbs@cpan.org>
Richard Diamond <wichard@vitalitystudios.com> Richard Diamond <wichard@vitalitystudios.com>
Rich Lane <rlane@club.cc.cmu.edu> Rich Lane <rlane@club.cc.cmu.edu>
Richo Healey <richo@psych0tik.net> Richo Healey <richo@psych0tik.net>
Rick Waldron <waldron.rick@gmail.com> Rick Waldron <waldron.rick@gmail.com>
Ricky Taylor <rickytaylor26@gmail.com> Ricky Taylor <rickytaylor26@gmail.com>
Rizky Luthfianto <mrluthfianto@gmail.com>
rjz <rj@rjzaworski.com> rjz <rj@rjzaworski.com>
Rob Arnold <robarnold@cs.cmu.edu> Rob Arnold <robarnold@cs.cmu.edu>
Robert Buonpastore <robert.buonpastore@gmail.com> Robert Buonpastore <robert.buonpastore@gmail.com>
Robert Clipsham <robert@octarineparrot.com> Robert Clipsham <robert@octarineparrot.com>
Robert Foss <dev@robertfoss.se> Robert Foss <dev@robertfoss.se>
Robert Gardner <rhg259@nyu.edu>
Robert Gawdzik <rgawdzik@hotmail.com> Robert Gawdzik <rgawdzik@hotmail.com>
Robert Irelan <rirelan@gmail.com> Robert Irelan <rirelan@gmail.com>
Robert Knight <robertknight@gmail.com> Robert Knight <robertknight@gmail.com>
@ -973,6 +1110,7 @@ Ron Dahlgren <ronald.dahlgren@gmail.com>
Rory OKane <rory@roryokane.com> Rory OKane <rory@roryokane.com>
Roy Crihfield <rscrihf@gmail.com> Roy Crihfield <rscrihf@gmail.com>
Roy Frostig <rfrostig@mozilla.com> Roy Frostig <rfrostig@mozilla.com>
Ruby <hi@ruby.sh>
Rüdiger Sonderfeld <ruediger@c-plusplus.de> Rüdiger Sonderfeld <ruediger@c-plusplus.de>
rundrop1 <rundrop1@zoho.com> rundrop1 <rundrop1@zoho.com>
Russell Johnston <rpjohnst@gmail.com> Russell Johnston <rpjohnst@gmail.com>
@ -986,6 +1124,7 @@ Ryan Riginding <marc.riginding@gmail.com>
Ryan Scheel <ryan.havvy@gmail.com> Ryan Scheel <ryan.havvy@gmail.com>
Ryman <haqkrs@gmail.com> Ryman <haqkrs@gmail.com>
らいどっと <ryogo.yoshimura@gmail.com> らいどっと <ryogo.yoshimura@gmail.com>
Ryo Munakata <afpacket@gmail.com>
Sae-bom Kim <sae-bom.kim@samsung.com> Sae-bom Kim <sae-bom.kim@samsung.com>
Salem Talha <salem.a.talha@gmail.com> Salem Talha <salem.a.talha@gmail.com>
saml <saml@users.noreply.github.com> saml <saml@users.noreply.github.com>
@ -1011,14 +1150,17 @@ Sean Patrick Santos <SeanPatrickSantos@gmail.com>
Sean Stangl <sstangl@mozilla.com> Sean Stangl <sstangl@mozilla.com>
Sean T Allen <sean@monkeysnatchbanana.com> Sean T Allen <sean@monkeysnatchbanana.com>
Sebastian Gesemann <s.gesemann@gmail.com> Sebastian Gesemann <s.gesemann@gmail.com>
Sebastian Hahn <sebastian@torproject.org>
Sebastian N. Fernandez <cachobot@gmail.com> Sebastian N. Fernandez <cachobot@gmail.com>
Sebastian Rasmussen <sebras@gmail.com> Sebastian Rasmussen <sebras@gmail.com>
Sebastian Wicki <gandro@gmx.net>
Sebastian Zaha <sebastian.zaha@gmail.com> Sebastian Zaha <sebastian.zaha@gmail.com>
Sébastien Chauvel <eichi237@mailoo.org> Sébastien Chauvel <eichi237@mailoo.org>
Sébastien Crozet <developer@crozet.re> Sébastien Crozet <developer@crozet.re>
Sébastien Marie <semarie@users.noreply.github.com> Sébastien Marie <semarie@users.noreply.github.com>
Sebastien Martini <seb@dbzteam.org> Sebastien Martini <seb@dbzteam.org>
Sébastien Paolacci <sebastien.paolacci@gmail.com> Sébastien Paolacci <sebastien.paolacci@gmail.com>
Seeker14491 <seeker14491@gmail.com>
Seonghyun Kim <sh8281.kim@samsung.com> Seonghyun Kim <sh8281.kim@samsung.com>
Seo Sanghyeon <sanxiyn@gmail.com> Seo Sanghyeon <sanxiyn@gmail.com>
Sergio Benitez <sbenitez@mit.edu> Sergio Benitez <sbenitez@mit.edu>
@ -1033,12 +1175,14 @@ SiegeLord <slabode@aim.com>
Simonas Kazlauskas <git@kazlauskas.me> Simonas Kazlauskas <git@kazlauskas.me>
Simon Barber-Dueck <sbarberdueck@gmail.com> Simon Barber-Dueck <sbarberdueck@gmail.com>
Simon Kern <simon.kern@rwth-aachen.de> Simon Kern <simon.kern@rwth-aachen.de>
Simon Mazur <semmaz.box@gmail.com>
Simon Persson <simon@flaskpost.org> Simon Persson <simon@flaskpost.org>
Simon Sapin <simon@exyr.org> Simon Sapin <simon@exyr.org>
Simon Wollwage <mail.wollwage@gmail.com> Simon Wollwage <mail.wollwage@gmail.com>
simplex <theemptystring@gmail.com> simplex <theemptystring@gmail.com>
Sindre Johansen <sindre@sindrejohansen.no> Sindre Johansen <sindre@sindrejohansen.no>
sinkuu <sinkuupump@gmail.com> sinkuu <sinkuupump@gmail.com>
skeleten <janpelle.thomson@stud.tu-darmstadt.de>
Skyler <skyler.lipthay@gmail.com> Skyler <skyler.lipthay@gmail.com>
smenardpw <sebastien@knoglr.com> smenardpw <sebastien@knoglr.com>
Son <leson.phung@gmail.com> Son <leson.phung@gmail.com>
@ -1047,6 +1191,7 @@ S Pradeep Kumar <gohanpra@gmail.com>
Squeaky <squeaky_pl@gmx.com> Squeaky <squeaky_pl@gmx.com>
startling <tdixon51793@gmail.com> startling <tdixon51793@gmail.com>
Stefan Bucur <stefan.bucur@epfl.ch> Stefan Bucur <stefan.bucur@epfl.ch>
Stefan O'Rear <stefanor@cox.net>
Stefan Plantikow <stefan.plantikow@googlemail.com> Stefan Plantikow <stefan.plantikow@googlemail.com>
Stepan Koltsov <stepan.koltsov@gmail.com> Stepan Koltsov <stepan.koltsov@gmail.com>
Sterling Greene <sterling.greene@gmail.com> Sterling Greene <sterling.greene@gmail.com>
@ -1072,7 +1217,9 @@ Taras Shpot <mrshpot@gmail.com>
tav <tav@espians.com> tav <tav@espians.com>
Taylor Hutchison <seanthutchison@gmail.com> Taylor Hutchison <seanthutchison@gmail.com>
Ted Horst <ted.horst@earthlink.net> Ted Horst <ted.horst@earthlink.net>
Ted Mielczarek <ted@mielczarek.org>
Tero Hänninen <lgvz@users.noreply.github.com> Tero Hänninen <lgvz@users.noreply.github.com>
Tero Hänninen <tejohann@kapsi.fi>
th0114nd <th0114nd@gmail.com> th0114nd <th0114nd@gmail.com>
Thad Guidry <thadguidry@gmail.com> Thad Guidry <thadguidry@gmail.com>
Theo Belaire <theo.belaire@gmail.com> Theo Belaire <theo.belaire@gmail.com>
@ -1092,8 +1239,11 @@ Till Hoeppner <till@hoeppner.ws>
Tim Brooks <brooks@cern.ch> Tim Brooks <brooks@cern.ch>
Tim Chevalier <chevalier@alum.wellesley.edu> Tim Chevalier <chevalier@alum.wellesley.edu>
Tim Cuthbertson <tim@gfxmonk.net> Tim Cuthbertson <tim@gfxmonk.net>
Tim Dumol <tim@timdumol.com>
Tim JIANG <p90eri@gmail.com>
Tim Joseph Dumol <tim@timdumol.com> Tim Joseph Dumol <tim@timdumol.com>
Tim Kuehn <tkuehn@cmu.edu> Tim Kuehn <tkuehn@cmu.edu>
Tim Neumann <mail@timnn.me>
Timon Rapp <timon@zaeda.net> Timon Rapp <timon@zaeda.net>
Timothée Ravier <tim@siosm.fr> Timothée Ravier <tim@siosm.fr>
Tim Parenti <timparenti@gmail.com> Tim Parenti <timparenti@gmail.com>
@ -1131,6 +1281,7 @@ tynopex <tynopex@users.noreply.github.com>
Ty Overby <ty@pre-alpha.com> Ty Overby <ty@pre-alpha.com>
Ulrik Sverdrup <bluss@users.noreply.github.com> Ulrik Sverdrup <bluss@users.noreply.github.com>
Ulysse Carion <ulysse@ulysse.io> Ulysse Carion <ulysse@ulysse.io>
U-NOV2010\eugals <bogus>
User Jyyou <jyyou@plaslab.cs.nctu.edu.tw> User Jyyou <jyyou@plaslab.cs.nctu.edu.tw>
Utkarsh Kukreti <utkarshkukreti@gmail.com> Utkarsh Kukreti <utkarshkukreti@gmail.com>
Uwe Dauernheim <uwe@dauernheim.net> Uwe Dauernheim <uwe@dauernheim.net>
@ -1138,6 +1289,7 @@ Vadim Chugunov <vadimcn@gmail.com>
Vadim Petrochenkov <vadim.petrochenkov@gmail.com> Vadim Petrochenkov <vadim.petrochenkov@gmail.com>
Valentin Tsatskin <vtsatskin@mozilla.com> Valentin Tsatskin <vtsatskin@mozilla.com>
Valerii Hiora <valerii.hiora@gmail.com> Valerii Hiora <valerii.hiora@gmail.com>
Viacheslav Chimishuk <Viacheslav.Chemishuk@keystonett.com>
Victor Berger <victor.berger@m4x.org> Victor Berger <victor.berger@m4x.org>
Victor van den Elzen <victor.vde@gmail.com> Victor van den Elzen <victor.vde@gmail.com>
Victory <git@dfhu.org> Victory <git@dfhu.org>
@ -1157,6 +1309,7 @@ Vladimir Rutsky <rutsky@users.noreply.github.com>
Vladimir Smola <smola.vladimir@gmail.com> Vladimir Smola <smola.vladimir@gmail.com>
Vojtech Kral <vojtech@kral.hk> Vojtech Kral <vojtech@kral.hk>
Volker Mische <volker.mische@gmail.com> Volker Mische <volker.mische@gmail.com>
w00ns <w00ns@w00ns.top>
Wade Mealing <wmealing@gmail.com> Wade Mealing <wmealing@gmail.com>
Wangshan Lu <wisagan@gmail.com> Wangshan Lu <wisagan@gmail.com>
WebeWizard <webewizard@gmail.com> WebeWizard <webewizard@gmail.com>
@ -1173,10 +1326,16 @@ Will Hipschman <whipsch@gmail.com>
William Throwe <wtt6@cornell.edu> William Throwe <wtt6@cornell.edu>
William Ting <io@williamting.com> William Ting <io@williamting.com>
Willson Mock <willson.mock@gmail.com> Willson Mock <willson.mock@gmail.com>
Will Speak <lithiumflame@gmail.com>
Will <will@glozer.net> Will <will@glozer.net>
Willy Aguirre <marti1125@gmail.com>
Without Boats <woboats@gmail.com>
Wojciech Ogrodowczyk <github@haikuco.de> Wojciech Ogrodowczyk <github@haikuco.de>
wonyong kim <wonyong.kim@samsung.com> wonyong kim <wonyong.kim@samsung.com>
xales <xales@naveria.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> Xuefeng Wu <benewu@gmail.com>
XuefengWu <benewu@gmail.com> XuefengWu <benewu@gmail.com>
Xuefeng Wu <xfwu@thoughtworks.com> Xuefeng Wu <xfwu@thoughtworks.com>
@ -1187,6 +1346,7 @@ Yazhong Liu <yorkiefixer@gmail.com>
Yehuda Katz <wycats@gmail.com> Yehuda Katz <wycats@gmail.com>
Yongqian Li <yongqli@kerrmetric.com> Yongqian Li <yongqli@kerrmetric.com>
York Xiang <bombless@126.com> York Xiang <bombless@126.com>
Yoshito Komatsu <ykomatsu@akaumigame.org>
Young-il Choi <duddlf.choi@samsung.com> Young-il Choi <duddlf.choi@samsung.com>
Youngmin Yoo <youngmin.yoo@samsung.com> Youngmin Yoo <youngmin.yoo@samsung.com>
Youngsoo Son <ysson83@gmail.com> Youngsoo Son <ysson83@gmail.com>

View File

@ -145,10 +145,15 @@ To save @bors some work, and to get small changes through more quickly, when
the other rollup-eligible patches too, and they'll get tested and merged at the other rollup-eligible patches too, and they'll get tested and merged at
the same time. the same time.
To find documentation-related issues, sort by the [A-docs label][adocs]. 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 [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 ## Issue Triage
Sometimes, an issue will stay open, even though the bug has been fixed. And Sometimes, an issue will stay open, even though the bug has been fixed. And
@ -164,30 +169,30 @@ Contributors with sufficient permissions on the Rust repo can help by adding
labels to triage issues: labels to triage issues:
* Yellow, **A**-prefixed labels state which **area** of the project an issue * Yellow, **A**-prefixed labels state which **area** of the project an issue
relates to. relates to.
* Magenta, **B**-prefixed labels identify bugs which **belong** elsewhere. * Magenta, **B**-prefixed labels identify bugs which **belong** elsewhere.
* Green, **E**-prefixed labels explain the level of **experience** necessary * Green, **E**-prefixed labels explain the level of **experience** necessary
to fix the issue. to fix the issue.
* Red, **I**-prefixed labels indicate the **importance** of the issue. The * Red, **I**-prefixed labels indicate the **importance** of the issue. The
[I-nominated][inom] label indicates that an issue has been nominated for [I-nominated][inom] label indicates that an issue has been nominated for
prioritizing at the next triage meeting. prioritizing at the next triage meeting.
* Orange, **P**-prefixed labels indicate a bug's **priority**. These labels * Orange, **P**-prefixed labels indicate a bug's **priority**. These labels
are only assigned during triage meetings, and replace the [I-nominated][inom] are only assigned during triage meetings, and replace the [I-nominated][inom]
label. label.
* Blue, **T**-prefixed bugs denote which **team** the issue belongs to. * Blue, **T**-prefixed bugs denote which **team** the issue belongs to.
* Dark blue, **beta-** labels track changes which need to be backported into * Dark blue, **beta-** labels track changes which need to be backported into
the beta branches. the beta branches.
* The purple **metabug** label marks lists of bugs collected by other
categories.
If you're looking for somewhere to start, check out the [E-easy][eeasy] tag. * The purple **metabug** label marks lists of bugs collected by other
categories.
If you're looking for somewhere to start, check out the [E-easy][eeasy] tag.
[inom]: https://github.com/rust-lang/rust/issues?q=is%3Aopen+is%3Aissue+label%3AI-nominated [inom]: https://github.com/rust-lang/rust/issues?q=is%3Aopen+is%3Aissue+label%3AI-nominated
[eeasy]: https://github.com/rust-lang/rust/issues?q=is%3Aopen+is%3Aissue+label%3AE-easy [eeasy]: https://github.com/rust-lang/rust/issues?q=is%3Aopen+is%3Aissue+label%3AE-easy
@ -221,18 +226,19 @@ are:
* The [Rust Internals forum][rif], a place to ask questions and * The [Rust Internals forum][rif], a place to ask questions and
discuss Rust's internals discuss Rust's internals
* The [generated documentation for rust's compiler][gdfrustc] * 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 * Although out of date, [Tom Lee's great blog article][tlgba] is very helpful
* [rustaceans.org][ro] is helpful, but mostly dedicated to IRC * [rustaceans.org][ro] is helpful, but mostly dedicated to IRC
* The [Rust Compiler Testing Docs][rctd] * 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.) * For @bors, [this cheat sheet][cheatsheet] is helpful (Remember to replace `@homu` with `@bors` in the commands that you use.)
* **Google**! * **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. * Don't be afraid to ask! The Rust community is friendly and helpful.
[gdfrustc]: http://manishearth.github.io/rust-internals-docs/rustc/ [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 [rif]: http://internals.rust-lang.org
[rr]: https://doc.rust-lang.org/book/README.html [rr]: https://doc.rust-lang.org/book/README.html
[tlgba]: http://tomlee.co/2014/04/03/a-more-detailed-tour-of-the-rust-compiler/ [tlgba]: http://tomlee.co/2014/04/03/a-more-detailed-tour-of-the-rust-compiler/
[ro]: http://www.rustaceans.org/ [ro]: http://www.rustaceans.org/
[rctd]: ./COMPILER_TESTS.md [rctd]: ./COMPILER_TESTS.md
[cheetsheat]: http://buildbot.rust-lang.org/homu/ [cheatsheet]: http://buildbot.rust-lang.org/homu/

View File

@ -26,7 +26,7 @@
# #
# * check - Run the complete test suite # * 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 # command if you want to build Rust again, after an update
# of the git repository. # of the git repository.
# #

View File

@ -67,11 +67,14 @@ Read ["Installing Rust"] from [The Book].
```sh ```sh
# Update package mirrors (may be needed if you have a fresh install of MSYS2) # Update package mirrors (may be needed if you have a fresh install of MSYS2)
$ pacman -Sy pacman-mirrors $ pacman -Sy pacman-mirrors
# Choose one based on platform: # Choose one based on platform:
$ pacman -S mingw-w64-i686-toolchain $ pacman -S mingw-w64-i686-toolchain
$ pacman -S mingw-w64-x86_64-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 $ pacman -S base-devel
``` ```
@ -84,6 +87,13 @@ Read ["Installing Rust"] from [The Book].
$ ./configure $ ./configure
$ make && make install $ 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 ## Building Documentation
@ -98,7 +108,7 @@ Building the documentation requires building the compiler, so the above
details will apply. Once you have the compiler built, you can details will apply. Once you have the compiler built, you can
```sh ```sh
$ make docs NO_REBUILD=1 $ make docs NO_REBUILD=1
``` ```
To make sure you dont re-build the compiler because you made a change To make sure you dont re-build the compiler because you made a change

View File

@ -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 * ~1200 changes, numerous bugfixes
@ -20,6 +238,12 @@ Breaking Changes
* [The `str::lines` and `BufRead::lines` iterators treat `\r\n` as * [The `str::lines` and `BufRead::lines` iterators treat `\r\n` as
line breaks in addition to `\n`][crlf]. line breaks in addition to `\n`][crlf].
* [Loans of `'static` lifetime extend to the end of a function][stat]. * [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 Language
-------- --------
@ -68,19 +292,22 @@ Libraries
prelude][pr]. prelude][pr].
* [`Extend<String>` and `FromIterator<String` are both implemented for * [`Extend<String>` and `FromIterator<String` are both implemented for
`String`][es]. `String`][es].
* [`IntoIterator` is implemented for `Option<&T>` and * [`IntoIterator` is implemented for references to `Option` and
`Result<&T>`][into]. `Result`][into2].
* [`HashMap` and `HashSet` implement `Extend<&T>` where `T: * [`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]. * [`BinaryHeap` implements `Debug`][bh2].
* [`Borrow` and `BorrowMut` are implemented for fixed-size * [`Borrow` and `BorrowMut` are implemented for fixed-size
arrays][bm]. 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]. traits including `Eq`, `Ord`, `Debug`, `Hash`][fp].
* [String comparison is faster][faststr]. * [String comparison is faster][faststr].
* `&mut T` where `T: Write` [also implements `Write`][mutw]. * `&mut T` where `T: std::fmt::Write` [also implements
* [A stable regression in `VecDec::push_back` that caused panics for `std::fmt::Write`][mutw].
zero-sized types was fixed][vd]. * [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]. * [Function pointers implement traits for up to 12 parameters][fp2].
Miscellaneous Miscellaneous
@ -151,8 +378,9 @@ Miscellaneous
[ffi]: https://github.com/rust-lang/rust/pull/28779 [ffi]: https://github.com/rust-lang/rust/pull/28779
[fp]: https://github.com/rust-lang/rust/pull/28268 [fp]: https://github.com/rust-lang/rust/pull/28268
[fp2]: https://github.com/rust-lang/rust/pull/28560 [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 [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 [it]: https://github.com/rust-lang/rust/pull/27652
[mm]: https://github.com/rust-lang/rust/pull/27338 [mm]: https://github.com/rust-lang/rust/pull/27338
[mutw]: https://github.com/rust-lang/rust/pull/28368 [mutw]: https://github.com/rust-lang/rust/pull/28368
@ -802,7 +1030,7 @@ Misc
[path-normalize]: https://github.com/rust-lang/rust/pull/23229 [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 * ~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 [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 * ~2400 changes, numerous bugfixes
@ -1088,7 +1316,7 @@ Version 1.0.0-alpha (January 2015)
[rbe]: http://rustbyexample.com/ [rbe]: http://rustbyexample.com/
Version 0.12.0 (October 2014) Version 0.12.0 (2014-10-09)
============================= =============================
* ~1900 changes, numerous bugfixes * ~1900 changes, numerous bugfixes
@ -1211,7 +1439,7 @@ Version 0.12.0 (October 2014)
kernels and distributions, built on CentOS 5.10. 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 * ~1700 changes, numerous bugfixes
@ -1344,7 +1572,7 @@ Version 0.11.0 (July 2014)
greatly improved. greatly improved.
Version 0.10 (April 2014) Version 0.10 (2014-04-03)
========================= =========================
* ~1500 changes, numerous bugfixes * ~1500 changes, numerous bugfixes
@ -1511,7 +1739,7 @@ Version 0.10 (April 2014)
directory. directory.
Version 0.9 (January 2014) Version 0.9 (2014-01-09)
========================== ==========================
* ~1800 changes, numerous bugfixes * ~1800 changes, numerous bugfixes
@ -1677,7 +1905,7 @@ Version 0.9 (January 2014)
build tools. build tools.
Version 0.8 (September 2013) Version 0.8 (2013-09-26)
============================ ============================
* ~2200 changes, numerous bugfixes * ~2200 changes, numerous bugfixes
@ -1833,7 +2061,7 @@ Version 0.8 (September 2013)
still invoked through the normal `rustdoc` command. still invoked through the normal `rustdoc` command.
Version 0.7 (July 2013) Version 0.7 (2013-07-03)
======================= =======================
* ~2000 changes, numerous bugfixes * ~2000 changes, numerous bugfixes
@ -1950,7 +2178,7 @@ Version 0.7 (July 2013)
* Improvements to rustpkg (see the detailed release notes). * Improvements to rustpkg (see the detailed release notes).
Version 0.6 (April 2013) Version 0.6 (2013-04-03)
======================== ========================
* ~2100 changes, numerous bugfixes * ~2100 changes, numerous bugfixes
@ -2053,7 +2281,7 @@ Version 0.6 (April 2013)
* Inline assembler supported by new asm!() syntax extension. * Inline assembler supported by new asm!() syntax extension.
Version 0.5 (December 2012) Version 0.5 (2012-12-21)
=========================== ===========================
* ~900 changes, numerous bugfixes * ~900 changes, numerous bugfixes
@ -2110,7 +2338,7 @@ Version 0.5 (December 2012)
* License changed from MIT to dual MIT/APL2 * License changed from MIT to dual MIT/APL2
Version 0.4 (October 2012) Version 0.4 (2012-10-15)
========================== ==========================
* ~2000 changes, numerous bugfixes * ~2000 changes, numerous bugfixes
@ -2166,7 +2394,7 @@ Version 0.4 (October 2012)
* All hash functions and tables converted to secure, randomized SipHash * 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 * ~1900 changes, numerous bugfixes
@ -2225,7 +2453,7 @@ Version 0.3 (July 2012)
* Cargo automatically resolves dependencies * Cargo automatically resolves dependencies
Version 0.2 (March 2012) Version 0.2 (2012-03-29)
========================= =========================
* >1500 changes, numerous bugfixes * >1500 changes, numerous bugfixes
@ -2266,7 +2494,7 @@ Version 0.2 (March 2012)
* Extensive cleanup, regularization in libstd, libcore * Extensive cleanup, regularization in libstd, libcore
Version 0.1 (January 20, 2012) Version 0.1 (2012-01-20)
=============================== ===============================
* Most language features work, including: * Most language features work, including:

41
configure vendored
View File

@ -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 local-rust 0 "use an installed rustc rather than downloading a snapshot"
opt llvm-static-stdcpp 0 "statically link to libstdc++ for LLVM" opt llvm-static-stdcpp 0 "statically link to libstdc++ for LLVM"
opt rpath 0 "build rpaths into rustc itself" 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 # This is used by the automation to produce single-target nightlies
opt dist-host-only 0 "only install bins for the host architecture" 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" 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_GRUN grun
probe CFG_FLEX flex probe CFG_FLEX flex
probe CFG_BISON bison probe CFG_BISON bison
probe CFG_PANDOC pandoc
probe CFG_XELATEX xelatex
probe CFG_GDB gdb probe CFG_GDB gdb
probe CFG_LLDB lldb probe CFG_LLDB lldb
@ -826,26 +825,6 @@ step_msg "looking for target specific programs"
probe CFG_ADB adb 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= BIN_SUF=
if [ "$CFG_OSTYPE" = "pc-windows-gnu" ] || [ "$CFG_OSTYPE" = "pc-windows-msvc" ] if [ "$CFG_OSTYPE" = "pc-windows-gnu" ] || [ "$CFG_OSTYPE" = "pc-windows-msvc" ]
then then
@ -1095,6 +1074,12 @@ envopt CPP
envopt CFLAGS envopt CFLAGS
envopt CXXFLAGS 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 # a little post-processing of various config values
CFG_PREFIX=${CFG_PREFIX%/} CFG_PREFIX=${CFG_PREFIX%/}
CFG_MANDIR=${CFG_MANDIR%/} CFG_MANDIR=${CFG_MANDIR%/}
@ -1289,6 +1274,12 @@ $ pacman -R cmake && pacman -S mingw-w64-x86_64-cmake
putvar CFG_MSVC_LIB_PATH_${bits} putvar CFG_MSVC_LIB_PATH_${bits}
;; ;;
*-rumprun-netbsd)
step_msg "targeting rumprun-netbsd, disabling jemalloc"
CFG_DISABLE_JEMALLOC=1
putvar CFG_DISABLE_JEMALLOC
;;
*) *)
;; ;;
esac esac
@ -1763,12 +1754,6 @@ then
fi fi
if [ -n $BAD_PANDOC ]
then
CFG_PANDOC=
putvar CFG_PANDOC
fi
putvar CFG_LLVM_SRC_DIR putvar CFG_LLVM_SRC_DIR
for t in $CFG_HOST for t in $CFG_HOST

View File

@ -53,7 +53,9 @@ Comma separated list of types of crates for the compiler to emit.
Specify the name of the crate being built. Specify the name of the crate being built.
.TP .TP
\fB\-\-emit\fR [asm|llvm\-bc|llvm\-ir|obj|link|dep\-info] \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 .TP
\fB\-\-print\fR [crate\-name|file\-names|sysroot] \fB\-\-print\fR [crate\-name|file\-names|sysroot]
Comma separated list of compiler information to print on stdout. Comma separated list of compiler information to print on stdout.
@ -66,7 +68,8 @@ Equivalent to \fI\-C\ opt\-level=2\fR.
.TP .TP
\fB\-o\fR \fIFILENAME\fR \fB\-o\fR \fIFILENAME\fR
Write output to \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 .TP
\fB\-\-out\-dir\fR \fIDIR\fR \fB\-\-out\-dir\fR \fIDIR\fR
Write output to compiler\[hy]chosen filename in \fIDIR\fR. Write output to compiler\[hy]chosen filename in \fIDIR\fR.

View File

@ -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_STATIC_LIB_NAME_mips-unknown-linux-gnu=lib$(1).a
CFG_LIB_GLOB_mips-unknown-linux-gnu=lib$(1)-*.so CFG_LIB_GLOB_mips-unknown-linux-gnu=lib$(1)-*.so
CFG_LIB_DSYM_GLOB_mips-unknown-linux-gnu=lib$(1)-*.dylib.dSYM 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_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 -mno-compact-eh $(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_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_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= 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_LDPATH_mips-unknown-linux-gnu :=
CFG_RUN_mips-unknown-linux-gnu= CFG_RUN_mips-unknown-linux-gnu=
CFG_RUN_TARG_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 CFG_GNU_TRIPLE_mips-unknown-linux-gnu := mips-unknown-linux-gnu

View File

@ -1,8 +1,8 @@
# mipsel-unknown-linux-gnu configuration # mipsel-unknown-linux-gnu configuration
CC_mipsel-unknown-linux-gnu=mipsel-unknown-linux-gnu-gcc CC_mipsel-unknown-linux-gnu=mipsel-linux-gnu-gcc
CXX_mipsel-unknown-linux-gnu=mipsel-unknown-linux-gnu-g++ CXX_mipsel-unknown-linux-gnu=mipsel-linux-gnu-g++
CPP_mipsel-unknown-linux-gnu=mipsel-unknown-linux-gnu-gcc CPP_mipsel-unknown-linux-gnu=mipsel-linux-gnu-gcc
AR_mipsel-unknown-linux-gnu=mipsel-unknown-linux-gnu-ar AR_mipsel-unknown-linux-gnu=mipsel-linux-gnu-ar
CFG_LIB_NAME_mipsel-unknown-linux-gnu=lib$(1).so CFG_LIB_NAME_mipsel-unknown-linux-gnu=lib$(1).so
CFG_STATIC_LIB_NAME_mipsel-unknown-linux-gnu=lib$(1).a CFG_STATIC_LIB_NAME_mipsel-unknown-linux-gnu=lib$(1).a
CFG_LIB_GLOB_mipsel-unknown-linux-gnu=lib$(1)-*.so 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_LDPATH_mipsel-unknown-linux-gnu :=
CFG_RUN_mipsel-unknown-linux-gnu= CFG_RUN_mipsel-unknown-linux-gnu=
CFG_RUN_TARG_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 CFG_GNU_TRIPLE_mipsel-unknown-linux-gnu := mipsel-unknown-linux-gnu

View 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

View File

@ -1,4 +1,5 @@
# x86_64-unknown-netbsd configuration # x86_64-unknown-netbsd configuration
CROSS_PREFIX_x86_64-unknown-netbsd=x86_64-unknown-netbsd-
CC_x86_64-unknown-netbsd=$(CC) CC_x86_64-unknown-netbsd=$(CC)
CXX_x86_64-unknown-netbsd=$(CXX) CXX_x86_64-unknown-netbsd=$(CXX)
CPP_x86_64-unknown-netbsd=$(CPP) CPP_x86_64-unknown-netbsd=$(CPP)

View File

@ -61,51 +61,55 @@ HOST_CRATES := syntax $(RUSTC_CRATES) rustdoc fmt_macros
TOOLS := compiletest rustdoc rustc rustbook error-index-generator TOOLS := compiletest rustdoc rustc rustbook error-index-generator
DEPS_core := DEPS_core :=
DEPS_libc := core
DEPS_rustc_unicode := core
DEPS_alloc := core libc alloc_system 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 \ DEPS_std := core libc rand alloc collections rustc_unicode \
native:rust_builtin native:backtrace \ native:rust_builtin native:backtrace \
alloc_system alloc_system
DEPS_arena := std
DEPS_glob := std
DEPS_flate := std native:miniz
DEPS_fmt_macros = std
DEPS_getopts := std
DEPS_graphviz := 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_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 \ 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_typeck rustc_mir rustc_resolve log syntax serialize rustc_llvm \
rustc_trans rustc_privacy rustc_lint rustc_front 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_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 \ DEPS_rustdoc := rustc rustc_driver native:hoedown serialize getopts \
test rustc_lint rustc_front 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_compiletest := test getopts
TOOL_DEPS_rustdoc := rustdoc TOOL_DEPS_rustdoc := rustdoc

View File

@ -21,6 +21,7 @@
# * dist-docs - Stage docs for upload # * dist-docs - Stage docs for upload
PKG_NAME := $(CFG_PACKAGE_NAME) PKG_NAME := $(CFG_PACKAGE_NAME)
STD_PKG_NAME := rust-std-$(CFG_PACKAGE_VERS)
DOC_PKG_NAME := rust-docs-$(CFG_PACKAGE_VERS) DOC_PKG_NAME := rust-docs-$(CFG_PACKAGE_VERS)
MINGW_PKG_NAME := rust-mingw-$(CFG_PACKAGE_VERS) MINGW_PKG_NAME := rust-mingw-$(CFG_PACKAGE_VERS)
@ -77,6 +78,7 @@ $(PKG_TAR): $(PKG_FILES)
-C $(S) \ -C $(S) \
--exclude-vcs \ --exclude-vcs \
--exclude=*~ \ --exclude=*~ \
--exclude=*.pyc \
--exclude=*/llvm/test/*/*.ll \ --exclude=*/llvm/test/*/*.ll \
--exclude=*/llvm/test/*/*.td \ --exclude=*/llvm/test/*/*.td \
--exclude=*/llvm/test/*/*.s \ --exclude=*/llvm/test/*/*.s \
@ -111,19 +113,25 @@ distcheck-tar-src: dist-tar-src
# Unix binary installer tarballs # 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))) $$(eval $$(call DEF_PREPARE,dir-$(1)))
endef
dist-install-dir-$(1): PREPARE_HOST=$(1) $(foreach target,$(CFG_TARGET),\
dist-install-dir-$(1): PREPARE_TARGETS=$(2) $(eval $(call DEF_START_INSTALLER,$(target))))
dist-install-dir-$(1): PREPARE_DEST_DIR=tmp/dist/$$(PKG_NAME)-$(1)-image
dist-install-dir-$(1): PREPARE_DIR_CMD=$(DEFAULT_PREPARE_DIR_CMD) define DEF_INSTALLER
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)-host: PREPARE_HOST=$(1)
dist-install-dir-$(1): PREPARE_MAN_CMD=$(DEFAULT_PREPARE_MAN_CMD) dist-install-dir-$(1)-host: PREPARE_TARGETS=$(2)
dist-install-dir-$(1): PREPARE_CLEAN=true dist-install-dir-$(1)-host: PREPARE_DEST_DIR=tmp/dist/$$(PKG_NAME)-$(1)-image
dist-install-dir-$(1): prepare-base-dir-$(1) docs dist-install-dir-$(1)-host: prepare-base-dir-$(1)-host docs
$$(Q)mkdir -p $$(PREPARE_DEST_DIR)/share/doc/rust $$(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)COPYRIGHT $$(PREPARE_DEST_DIR)/share/doc/rust
$$(Q)$$(PREPARE_MAN_CMD) $$(S)LICENSE-APACHE $$(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 # This tiny morsel of metadata is used by rust-packaging
$$(Q)echo "$(CFG_VERSION)" > tmp/dist/$$(PKG_NAME)-$(1)-overlay/version $$(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: $$@) @$(call E, build: $$@)
# Copy essential gcc components into installer # On a MinGW target we've got a few runtime DLL dependencies that we need
ifdef CFG_WINDOWSY_$(1) # to include. THe first argument to `make-win-dist` is where to put these DLLs
ifeq ($$(findstring gnu,$(1)),gnu) # (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)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)$$(CFG_PYTHON) $$(S)src/etc/make-win-dist.py \
$$(Q)cp -r $$(S)src/etc/third-party tmp/dist/$$(PKG_NAME)-$(1)-image/share/doc/ 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
endif endif
$$(Q)$$(S)src/rust-installer/gen-installer.sh \ $$(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 --bulk-dirs=share/doc/rust/html
$$(Q)rm -R tmp/dist/$$(DOC_PKG_NAME)-$(1)-image $$(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): dist-mingw-install-dir-$(1):
$$(Q)mkdir -p tmp/dist/rust-mingw-tmp-$(1)-image $$(Q)mkdir -p tmp/dist/rust-mingw-tmp-$(1)-image
$$(Q)rm -Rf tmp/dist/$$(MINGW_PKG_NAME)-$(1)-image $$(Q)rm -Rf tmp/dist/$$(MINGW_PKG_NAME)-$(1)-image
$$(Q)$$(CFG_PYTHON) $$(S)src/etc/make-win-dist.py \ $$(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) dist/$$(MINGW_PKG_NAME)-$(1).tar.gz: dist-mingw-install-dir-$(1)
@$(call E, build: $$@) @$(call E, build: $$@)
@ -204,15 +230,52 @@ dist/$$(MINGW_PKG_NAME)-$(1).tar.gz: dist-mingw-install-dir-$(1)
endef endef
ifneq ($(CFG_ENABLE_DIST_HOST_ONLY),) # $(1) - host
$(foreach host,$(CFG_HOST),\ # $(2) - target
$(eval $(call DEF_INSTALLER,$(host),$(host)))) define DEF_INSTALLER_TARGETS
else
$(foreach host,$(CFG_HOST),\
$(eval $(call DEF_INSTALLER,$(host),$(CFG_TARGET))))
endif
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) ifdef CFG_WINDOWSY_$(CFG_BUILD)
define BUILD_MINGW_TARBALL 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) MAYBE_DOC_TARBALLS=$(foreach host,$(CFG_HOST),dist/$(DOC_PKG_NAME)-$(host).tar.gz)
endif 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) $(MAYBE_DOC_TARBALLS) $(MAYBE_MINGW_TARBALLS)
# Just try to run the compiler for the build host # Just try to run the compiler for the build host

View File

@ -58,17 +58,17 @@ check-lexer: $(BG) $(BG)RustLexer.class check-build-lexer-verifier
$(Q)$(SG)check.sh $(S) "$(BG)" \ $(Q)$(SG)check.sh $(S) "$(BG)" \
"$(CFG_GRUN)" "$(BG)verify" "$(BG)RustLexer.tokens" "$(CFG_GRUN)" "$(BG)verify" "$(BG)RustLexer.tokens"
else else
$(info cfg: grun not available, skipping lexer test...) $(info cfg: lexer tooling not available, skipping lexer test...)
check-lexer: check-lexer:
endif endif
else else
$(info cfg: antlr4 not available, skipping lexer test...) $(info cfg: lexer tooling not available, skipping lexer test...)
check-lexer: check-lexer:
endif endif
else else
$(info cfg: javac not available, skipping lexer test...) $(info cfg: lexer tooling not available, skipping lexer test...)
check-lexer: check-lexer:
endif endif

View File

@ -8,6 +8,12 @@
# option. This file may not be copied, modified, or distributed # option. This file may not be copied, modified, or distributed
# except according to those terms. # 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: install:
ifeq (root user, $(USER) $(patsubst %,user,$(SUDO_USER))) ifeq (root user, $(USER) $(patsubst %,user,$(SUDO_USER)))
# Build the dist as the original user # Build the dist as the original user
@ -16,9 +22,11 @@ else
$(Q)$(MAKE) prepare_install $(Q)$(MAKE) prepare_install
endif endif
ifeq ($(CFG_DISABLE_DOCS),) 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 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 # Remove tmp files because it's a decent amount of disk space
$(Q)rm -R tmp/dist $(Q)rm -R tmp/dist
@ -32,9 +40,11 @@ else
$(Q)$(MAKE) prepare_uninstall $(Q)$(MAKE) prepare_uninstall
endif endif
ifeq ($(CFG_DISABLE_DOCS),) 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 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 # Remove tmp files because it's a decent amount of disk space
$(Q)rm -R tmp/dist $(Q)rm -R tmp/dist

View File

@ -73,7 +73,7 @@ $$(LLVM_STAMP_$(1)): $(S)src/rustllvm/llvm-auto-clean-trigger
ifeq ($$(CFG_ENABLE_LLVM_STATIC_STDCPP),1) ifeq ($$(CFG_ENABLE_LLVM_STATIC_STDCPP),1)
LLVM_STDCPP_RUSTFLAGS_$(1) = -L "$$(dir $$(shell $$(CC_$(1)) $$(CFG_GCCISH_CFLAGS_$(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 else
LLVM_STDCPP_RUSTFLAGS_$(1) = LLVM_STDCPP_RUSTFLAGS_$(1) =
endif endif
@ -83,7 +83,7 @@ endif
LLVM_LINKAGE_PATH_$(1):=$$(abspath $$(RT_OUTPUT_DIR_$(1))/llvmdeps.rs) LLVM_LINKAGE_PATH_$(1):=$$(abspath $$(RT_OUTPUT_DIR_$(1))/llvmdeps.rs)
$$(LLVM_LINKAGE_PATH_$(1)): $(S)src/etc/mklldeps.py $$(LLVM_CONFIG_$(1)) $$(LLVM_LINKAGE_PATH_$(1)): $(S)src/etc/mklldeps.py $$(LLVM_CONFIG_$(1))
$(Q)$(CFG_PYTHON) "$$<" "$$@" "$$(LLVM_COMPONENTS)" "$$(CFG_ENABLE_LLVM_STATIC_STDCPP)" \ $(Q)$(CFG_PYTHON) "$$<" "$$@" "$$(LLVM_COMPONENTS)" "$$(CFG_ENABLE_LLVM_STATIC_STDCPP)" \
$$(LLVM_CONFIG_$(1)) $$(LLVM_CONFIG_$(1)) "$(CFG_STDCPP_NAME)"
endef endef
$(foreach host,$(CFG_HOST), \ $(foreach host,$(CFG_HOST), \

View File

@ -13,12 +13,12 @@
###################################################################### ######################################################################
# The version number # 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' # 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 # NB Make sure it starts with a dot to conform to semver pre-release
# versions (section 9) # versions (section 9)
CFG_PRERELEASE_VERSION=.4 CFG_PRERELEASE_VERSION=.5
# Append a version-dependent hash to each library, so we can install different # Append a version-dependent hash to each library, so we can install different
# versions in the same place # versions in the same place
@ -132,7 +132,11 @@ endif
ifdef CFG_ENABLE_DEBUGINFO ifdef CFG_ENABLE_DEBUGINFO
$(info cfg: enabling debuginfo (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 endif
ifdef SAVE_TEMPS 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 # Landing pads require a lot of codegen. We can get through bootstrapping faster
# by not emitting them. # by not emitting them.
RUSTFLAGS_STAGE0 += -Z no-landing-pads
# Enable MIR to "always build" for crates where this works. This is ifdef CFG_DISABLE_STAGE0_LANDING_PADS
# just temporary while MIR is being actively built up -- it's just a RUSTFLAGS_STAGE0 += -Z no-landing-pads
# poor man's unit testing infrastructure. Anyway we only want this for endif
# 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))))
# platform-specific auto-configuration # platform-specific auto-configuration
include $(CFG_SRC_DIR)mk/platform.mk include $(CFG_SRC_DIR)mk/platform.mk

View File

@ -208,6 +208,14 @@ define CFG_MAKE_TOOLCHAIN
ifeq ($$(findstring $(HOST_$(1)),arm aarch64 mips mipsel powerpc),) 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 # On Bitrig, we need the relocation model to be PIC for everything
ifeq (,$(filter $(OSTYPE_$(1)),bitrig)) ifeq (,$(filter $(OSTYPE_$(1)),bitrig))
LLVM_MC_RELOCATION_MODEL="pic" LLVM_MC_RELOCATION_MODEL="pic"

View File

@ -185,16 +185,16 @@ INSTALL_DEBUGGER_SCRIPT_COMMANDS=$(if $(findstring windows,$(1)),\
define DEF_PREPARE define DEF_PREPARE
prepare-base-$(1): PREPARE_SOURCE_DIR=$$(PREPARE_HOST)/stage$$(PREPARE_STAGE) 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_BIN_DIR=$$(PREPARE_SOURCE_DIR)/bin
prepare-base-$(1): PREPARE_SOURCE_LIB_DIR=$$(PREPARE_SOURCE_DIR)/$$(CFG_LIBDIR_RELATIVE) 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_SOURCE_MAN_DIR=$$(S)/man
prepare-base-$(1): PREPARE_DEST_BIN_DIR=$$(PREPARE_DEST_DIR)/bin 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_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_DEST_MAN_DIR=$$(PREPARE_DEST_DIR)/share/man/man1
prepare-base-$(1): prepare-everything-$(1)
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) prepare-host-$(1): prepare-host-tools-$(1)
@ -222,7 +222,7 @@ $$(foreach lib,$$(CRATES), \
$$(foreach host,$$(CFG_HOST), \ $$(foreach host,$$(CFG_HOST), \
$$(eval $$(call DEF_PREPARE_HOST_LIB,$$(lib),$$(PREPARE_STAGE),$$(host),$(1))))) $$(eval $$(call DEF_PREPARE_HOST_LIB,$$(lib),$$(PREPARE_STAGE),$$(host),$(1)))))
prepare-targets-$(1): \ prepare-target-$(1): \
$$(foreach host,$$(CFG_HOST), \ $$(foreach host,$$(CFG_HOST), \
$$(foreach target,$$(CFG_TARGET), \ $$(foreach target,$$(CFG_TARGET), \
prepare-target-$$(target)-host-$$(host)-$$(PREPARE_STAGE)-$(1))) prepare-target-$$(target)-host-$$(host)-$$(PREPARE_STAGE)-$(1)))

View File

@ -1046,6 +1046,10 @@ $$(call TEST_OK_FILE,$(1),$(2),$(3),rmake): \
$$(RMAKE_TESTS:%=$(3)/test/run-make/%-$(1)-T-$(2)-H-$(3).ok) $$(RMAKE_TESTS:%=$(3)/test/run-make/%-$(1)-T-$(2)-H-$(3).ok)
@touch $$@ @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: \ $(3)/test/run-make/%-$(1)-T-$(2)-H-$(3).ok: \
$(S)src/test/run-make/%/Makefile \ $(S)src/test/run-make/%/Makefile \
$$(CSREQ$(1)_T_$(2)_H_$(3)) $$(CSREQ$(1)_T_$(2)_H_$(3))
@ -1056,7 +1060,7 @@ $(3)/test/run-make/%-$(1)-T-$(2)-H-$(3).ok: \
$$(MAKE) \ $$(MAKE) \
$$(HBIN$(1)_H_$(3))/rustc$$(X_$(3)) \ $$(HBIN$(1)_H_$(3))/rustc$$(X_$(3)) \
$(3)/test/run-make/$$* \ $(3)/test/run-make/$$* \
$$(CC_$(3)) \ '$$(CC_$(3))' \
"$$(CFG_GCCISH_CFLAGS_$(3))" \ "$$(CFG_GCCISH_CFLAGS_$(3))" \
$$(HBIN$(1)_H_$(3))/rustdoc$$(X_$(3)) \ $$(HBIN$(1)_H_$(3))/rustdoc$$(X_$(3)) \
"$$(TESTNAME)" \ "$$(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_HOSTDIR$(1)_T_$(2)_H_$(3))" \
"$$(LD_LIBRARY_PATH_ENV_TARGETDIR$(1)_T_$(2)_H_$(3))" \ "$$(LD_LIBRARY_PATH_ENV_TARGETDIR$(1)_T_$(2)_H_$(3))" \
$(1) \ $(1) \
$$(S) $$(S) \
$(3)
@touch -r $$@.start_time $$@ && rm $$@.start_time @touch -r $$@.start_time $$@ && rm $$@.start_time
else else
# FIXME #11094 - The above rule doesn't work right for multiple targets # FIXME #11094 - The above rule doesn't work right for multiple targets

View File

@ -13,9 +13,7 @@
#![feature(box_syntax)] #![feature(box_syntax)]
#![feature(dynamic_lib)] #![feature(dynamic_lib)]
#![feature(libc)] #![feature(libc)]
#![feature(path_ext)]
#![feature(rustc_private)] #![feature(rustc_private)]
#![feature(slice_splits)]
#![feature(str_char)] #![feature(str_char)]
#![feature(test)] #![feature(test)]
#![feature(vec_push_all)] #![feature(vec_push_all)]
@ -92,7 +90,7 @@ pub fn parse_config(args: Vec<String> ) -> Config {
optflag("h", "help", "show this message")); optflag("h", "help", "show this message"));
let (argv0, args_) = args.split_first().unwrap(); 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); let message = format!("Usage: {} [OPTIONS] [TESTNAME...]", argv0);
println!("{}", getopts::usage(&message, &groups)); println!("{}", getopts::usage(&message, &groups));
println!(""); println!("");
@ -348,7 +346,7 @@ fn extract_gdb_version(full_version_line: Option<String>) -> Option<String> {
if !full_version_line.trim().is_empty() => { if !full_version_line.trim().is_empty() => {
let full_version_line = full_version_line.trim(); 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() { for (pos, c) in full_version_line.char_indices() {
if !c.is_digit(10) { continue } if !c.is_digit(10) { continue }
if pos + 2 >= full_version_line.len() { 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) { if pos > 0 && full_version_line.char_at_reverse(pos).is_digit(10) {
continue continue
} }
if pos + 3 < full_version_line.len() && let mut end = pos + 3;
full_version_line.char_at(pos + 3).is_digit(10) { while end < full_version_line.len() &&
continue 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 '{}'", println!("Could not extract GDB version from line '{}'",
full_version_line); full_version_line);

View File

@ -8,6 +8,8 @@
// option. This file may not be copied, modified, or distributed // option. This file may not be copied, modified, or distributed
// except according to those terms. // except according to those terms.
#![allow(deprecated)]
use std::dynamic_lib::DynamicLibrary; use std::dynamic_lib::DynamicLibrary;
use std::io::prelude::*; use std::io::prelude::*;
use std::path::PathBuf; use std::path::PathBuf;

View File

@ -1669,8 +1669,7 @@ fn compile_test_and_save_ir(config: &Config, props: &TestProps,
// FIXME (#9639): This needs to handle non-utf8 paths // FIXME (#9639): This needs to handle non-utf8 paths
let mut link_args = vec!("-L".to_owned(), let mut link_args = vec!("-L".to_owned(),
aux_dir.to_str().unwrap().to_owned()); aux_dir.to_str().unwrap().to_owned());
let llvm_args = vec!("--emit=llvm-ir".to_owned(), let llvm_args = vec!("--emit=llvm-ir".to_owned(),);
"--crate-type=lib".to_owned());
link_args.extend(llvm_args); link_args.extend(llvm_args);
let args = make_compile_args(config, let args = make_compile_args(config,
props, props,

View File

@ -2,9 +2,10 @@
## Building ## Building
To generate all the docs, just run `make docs` from the root of the repository. To generate all the docs, follow the "Building Documentation" instructions in
This will convert the distributed Markdown docs to HTML and generate HTML doc the README in the root of the repository. This will convert the distributed
for the 'std' and 'extra' libraries. 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: To generate HTML documentation from one source file/crate, do something like:

View File

@ -76,7 +76,7 @@ Cleanup through RAII-style destructors is more likely to work than in catch bloc
## Why aren't modules type-parametric? ## 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? ## Why aren't values type-parametric? Why only items?

View File

@ -22,7 +22,7 @@ Existing languages at this level of abstraction and efficiency are unsatisfactor
# Is any part of this thing production-ready? # 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? # Is this a completely Mozilla-planned and orchestrated thing?

View File

@ -9,7 +9,7 @@ provides only one kind of material:
This document does not serve as an introduction to the language. Background This document does not serve as an introduction to the language. Background
familiarity with the language is assumed. A separate [guide] is available to 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 This document also does not serve as a reference to the [standard] library
included in the language distribution. Those libraries are documented 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 Symbols are a general class of printable [tokens](#tokens) that play structural
roles in a variety of grammar productions. They are catalogued here for roles in a variety of grammar productions. They are cataloged here for
completeness as the set of remaining miscellaneous printable tokens that do not completeness as the set of remaining miscellaneous printable tokens that do not
otherwise appear as [unary operators](#unary-operator-expressions), [binary otherwise appear as [unary operators](#unary-operator-expressions), [binary
operators](#binary-operator-expressions), or [keywords](#keywords). operators](#binary-operator-expressions), or [keywords](#keywords).
@ -436,7 +436,7 @@ meta_seq : meta_item [ ',' meta_seq ] ? ;
## Statements ## Statements
```antlr ```antlr
stmt : decl_stmt | expr_stmt ; stmt : decl_stmt | expr_stmt | ';' ;
``` ```
### Declaration statements ### Declaration statements
@ -773,7 +773,7 @@ bound := path | lifetime
## Type kinds ## Type kinds
**FIXME:** this this probably not relevant to the grammar... **FIXME:** this is probably not relevant to the grammar...
# Memory and concurrency models # Memory and concurrency models

View File

@ -98,3 +98,4 @@ languages:
- [Korean](https://github.com/rust-kr/doc.rust-kr.org) - [Korean](https://github.com/rust-kr/doc.rust-kr.org)
- [Chinese](https://github.com/KaiserY/rust-book-chinese) - [Chinese](https://github.com/KaiserY/rust-book-chinese)
- [Spanish](https://goyox86.github.io/elpr) - [Spanish](https://goyox86.github.io/elpr)
- [German](https://panicbit.github.io/rustbook-de)

View File

@ -1,11 +1,11 @@
% Atomics % Atomics
Rust pretty blatantly just inherits C11's memory model for atomics. This is not 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 due to this model being particularly excellent or easy to understand. Indeed,
model is quite complex and known to have [several flaws][C11-busted]. Rather, it this model is quite complex and known to have [several flaws][C11-busted].
is a pragmatic concession to the fact that *everyone* is pretty bad at modeling Rather, it is a pragmatic concession to the fact that *everyone* is pretty bad
atomics. At very least, we can benefit from existing tooling and research around at modeling atomics. At very least, we can benefit from existing tooling and
C. research around C.
Trying to fully explain the model in this book is fairly hopeless. It's defined 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 in terms of madness-inducing causality graphs that require a full book to

View File

@ -52,7 +52,7 @@ For numeric casts, there are quite a few cases to consider:
* zero-extend if the source is unsigned * zero-extend if the source is unsigned
* sign-extend if the source is signed * sign-extend if the source is signed
* casting from a float to an integer will round the float towards zero * 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]**. value cannot be represented by the target integer type][float-int]**.
This includes Inf and NaN. This is a bug and will be fixed. This includes Inf and NaN. This is a bug and will be fixed.
* casting from an integer to float will produce the floating point * 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 f32 to an f64 is perfect and lossless
* casting from an f64 to an f32 will produce the closest possible value * casting from an f64 to an f32 will produce the closest possible value
(rounding strategy unspecified) (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 is finite but larger or smaller than the largest or smallest finite
value representable by f32][float-float]**. This is a bug and will value representable by f32][float-float]**. This is a bug and will
be fixed. be fixed.

View File

@ -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 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 parallelism. The standard library exposes OS threads and blocking sys-calls

View File

@ -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 dropped other than dropping its children, then it means `Drop` doesn't need to
be implemented at all! 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 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, 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 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 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: 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 happily proceed to tell the box to Drop itself and everything will blow up with
use-after-frees and double-frees. 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 regardless of whether they implement Drop. Therefore something like
```rust ```rust

View File

@ -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. // 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: to initialization has static drop semantics:
```rust ```rust

View File

@ -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 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 `'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 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 ```rust,ignore
let x; let x;
@ -115,13 +115,163 @@ section:
**For a generic type to soundly implement drop, its generics arguments must **For a generic type to soundly implement drop, its generics arguments must
strictly outlive it.** strictly outlive it.**
This rule is sufficient but not necessary to satisfy the drop checker. That is, Obeying this rule is (usually) necessary to satisfy the borrow
if your type obeys this rule then it's definitely sound to drop. However checker; obeying it is sufficient but not necessary to be
there are special cases where you can fail to satisfy this, but still sound. That is, if your type obeys this rule then it's definitely
successfully pass the borrow checker. These are the precise rules that are sound to drop.
currently up in the air.
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 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 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 is one special case that you need to worry about, which we will look at in
the next section. the next section.

View File

@ -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. 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. 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. 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. 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. 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 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 *` 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 type with `*const Void`, but this doesn't necessarily gain anything over using
e.g. `*const ()`, which *is* safe to randomly dereference. e.g. `*const ()`, which *is* safe to randomly dereference.

View File

@ -90,16 +90,16 @@ let mut vec = vec![Box::new(0); 4];
println!("{}", vec[0]); 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 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 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). unsound).
So what can we do? Well, we can pick a trivially consistent state: set the Vec's 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 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 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* 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). (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 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 { fn new(data: T) -> Self {
unsafe { unsafe {
// Wouldn't it be nice if heap::allocate worked like this? // 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 { ptr::write(ptr, RcBox {
data: data, data: data,
ref_count: 1, 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 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.

View File

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

View File

@ -195,7 +195,7 @@ println!("{}", x);
The problem here is is bit more subtle and interesting. We want Rust to 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` 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 to `push`. This would create an aliased mutable reference, which would
violate the *second* rule of references. violate the *second* rule of references.

View File

@ -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 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 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. nonsense.
*That's totally awesome.* *That's totally awesome.*
@ -52,11 +52,11 @@ The only things that are different in Unsafe Rust are that you can:
* Mutate statics * Mutate statics
That's it. The reason these operations are relegated to Unsafe is that misusing 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 any of these things will cause the ever dreaded Undefined Behavior. Invoking
Undefined Behaviour gives the compiler full rights to do arbitrarily bad things Undefined Behavior gives the compiler full rights to do arbitrarily bad things
to your program. You definitely *should not* invoke Undefined Behaviour. 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: language cares about is preventing the following things:
* Dereferencing null or dangling pointers * Dereferencing null or dangling pointers
@ -71,9 +71,9 @@ language cares about is preventing the following things:
* Unwinding into another language * Unwinding into another language
* Causing a [data race][race] * 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 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 generally violations of these constraints will just transitively lead to one of
the above problems. Some additional constraints may also derive from compiler the above problems. Some additional constraints may also derive from compiler
intrinsics that make special assumptions about how code can be optimized. intrinsics that make special assumptions about how code can be optimized.

View File

@ -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 `repr(C)` can be applied to types that will be nonsensical or problematic if
passed through the FFI boundary. passed through the FFI boundary.
* ZSTs are still zero-sized, even though this is not a standard behaviour in * ZSTs are still zero-sized, even though this is not a standard behavior in
C, and is explicitly contrary to the behaviour of an empty type in C++, which C, and is explicitly contrary to the behavior of an empty type in C++, which
still consumes a byte of space. still consumes a byte of space.
* DSTs, tuples, and tagged unions are not a concept in C and as such are never * 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 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. 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, `repr(packed)` is not to be used lightly. Unless you have extreme requirements,
this should not be used. this should not be used.

View File

@ -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 a reference into it. This is why Rust requires any references to freeze the
referent and its owners. referent and its owners.

View File

@ -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 a write
* one of them is unsynchronized * 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: 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 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 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 // 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 // in the middle. However our program may panic if the thread we spawned
// managed to increment before this ran. A race condition because correct // 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. // thread execution.
println!("{}", data[idx.load(Ordering::SeqCst)]); println!("{}", data[idx.load(Ordering::SeqCst)]);
``` ```

View File

@ -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 `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 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 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. aligned to 32 bits.
A type's size must always be a multiple of its alignment. This ensures that an 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 special constrained representations. As such it is *especially* desirable that
we leave enum layout unspecified today. we leave enum layout unspecified today.
[dst]: exotic-sizes.html#dynamically-sized-types-(dsts) [dst]: exotic-sizes.html#dynamically-sized-types-dsts

View File

@ -41,8 +41,8 @@ Some examples of unsafe functions:
* `slice::get_unchecked` will perform unchecked indexing, allowing memory * `slice::get_unchecked` will perform unchecked indexing, allowing memory
safety to be freely violated. safety to be freely violated.
* `ptr::offset` is an intrinsic that invokes Undefined Behaviour if it is * every raw pointer to sized type has intrinsic `offset` method that invokes
not "in bounds" as defined by LLVM. Undefined Behavior if it is not "in bounds" as defined by LLVM.
* `mem::transmute` reinterprets some value as having the given type, * `mem::transmute` reinterprets some value as having the given type,
bypassing type safety in arbitrary ways. (see [conversions] for details) bypassing type safety in arbitrary ways. (see [conversions] for details)
* All FFI functions are `unsafe` because they can do arbitrary things. * 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: 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 **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 *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 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 paranoid despair. In particular it's generally regarded as ok to trust the standard library

View File

@ -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 implemented. Since they're *marker traits* (they have no associated items like
methods), correctly implemented simply means that they have the intrinsic methods), correctly implemented simply means that they have the intrinsic
properties an implementor should have. Incorrectly implementing Send or Sync can 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 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 every other trait, if a type is composed entirely of Send or Sync types, then it

View File

@ -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 `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 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 * 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. 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 `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`. 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 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 Also of course you can get most of the functionality of these functions using
pointer casts. pointer casts.

View File

@ -2,7 +2,7 @@
Unsafe code can often end up producing references or lifetimes out of thin air. 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 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 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` than simply becoming `'static`, because for instance `&'static &'a T`
will fail to typecheck, but the unbound lifetime will perfectly mold into 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`. lifetime can be regarded as `'static`.
Almost no reference is `'static`, so this is probably wrong. `transmute` and 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 bound an unbounded lifetime as quick as possible, especially across function
boundaries. boundaries.

View File

@ -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!) (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 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 functions *themselves* require is that the locations you want to read and write
are allocated. However the ways writing arbitrary bits to arbitrary are allocated. However the ways writing arbitrary bits to arbitrary
locations of memory can break things are basically uncountable! locations of memory can break things are basically uncountable!

View File

@ -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 *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 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 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 Rust provides mechanisms to work with uninitialized memory in checked (safe) and
unchecked (unsafe) ways. unchecked (unsafe) ways.

View File

@ -42,7 +42,7 @@ should only panic for programming errors or *extreme* problems.
Rust's unwinding strategy is not specified to be fundamentally compatible Rust's unwinding strategy is not specified to be fundamentally compatible
with any other language's unwinding. As such, unwinding into Rust from another 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 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, 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* at best, your application will crash and burn. At worst, your application *won't*

View File

@ -93,7 +93,7 @@ pub struct Vec<T> {
If you don't care about the null-pointer optimization, then you can use the 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 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 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 need `new` to be unsafe because it doesn't make any interesting guarantees about
its contents. its contents.

View File

@ -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 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 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 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 logically uninitialized, even though there is in fact a perfectly good instance
of T there. of T there.

View File

@ -1,11 +1,11 @@
% Handling Zero-Sized Types % 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 *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 raw allocations, which are exactly the two things that care about
zero-sized types. We need to be careful of two things: 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. allocation size.
* raw pointer offsets are no-ops for zero-sized types, which will break our * raw pointer offsets are no-ops for zero-sized types, which will break our
C-style pointer iterator. C-style pointer iterator.

View File

@ -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 [^non_ascii_idents]: Non-ASCII characters in identifiers are currently feature
gated. This is expected to improve soon. gated. This is expected to improve soon.
- The first character has property `XID_start` Either
- The remaining characters have property `XID_continue`
* 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]. 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
Symbols are a general class of printable [token](#tokens) that play structural Symbols are a general class of printable [tokens](#tokens) that play structural
roles in a variety of grammar productions. They are catalogued here for roles in a variety of grammar productions. They are a
completeness as the set of remaining miscellaneous printable tokens that do not set of remaining miscellaneous printable tokens that do not
otherwise appear as [unary operators](#unary-operator-expressions), [binary otherwise appear as [unary operators](#unary-operator-expressions), [binary
operators](#binary-operator-expressions), or [keywords][keywords]. operators](#binary-operator-expressions), or [keywords][keywords].
They are catalogued in [the Symbols section][symbols] of the Grammar document.
[symbols]: grammar.html#symbols
## Paths ## Paths
@ -586,8 +597,8 @@ Rust syntax is restricted in two ways:
# Crates and source files # Crates and source files
Although Rust, like any other language, can be implemented by an interpreter as Although Rust, like any other language, can be implemented by an interpreter as
well as a compiler, the only existing implementation is a compiler &mdash; well as a compiler, the only existing implementation is a compiler,
from now on referred to as *the* Rust compiler &mdash; and the language has and the language has
always been designed to be compiled. For these reasons, this section assumes a always been designed to be compiled. For these reasons, this section assumes a
compiler. compiler.
@ -674,7 +685,7 @@ There are several kinds of item:
* [modules](#modules) * [modules](#modules)
* [functions](#functions) * [functions](#functions)
* [type definitions](grammar.html#type-definitions) * [type definitions](grammar.html#type-definitions)
* [structures](#structures) * [structs](#structs)
* [enumerations](#enumerations) * [enumerations](#enumerations)
* [constant items](#constant-items) * [constant items](#constant-items)
* [static items](#static-items) * [static items](#static-items)
@ -881,7 +892,7 @@ mod foo {
} }
use foo::example::iter; // good: foo is at crate root 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 self::baz::foobaz; // good: self refers to module 'foo'
use foo::bar::foobar; // good: foo is at crate root use foo::bar::foobar; // good: foo is at crate root
@ -900,9 +911,10 @@ fn main() {}
### Functions ### Functions
A _function item_ defines a sequence of [statements](#statements) and an A _function item_ defines a sequence of [statements](#statements) and a
optional final [expression](#expressions), along with a name and a set of final [expression](#expressions), along with a name and a set of
parameters. Functions are declared with the keyword `fn`. Functions declare a 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 set of *input* [*variables*](#variables) as parameters, through which the caller
passes arguments into the function, and the *output* [*type*](#types) passes arguments into the function, and the *output* [*type*](#types)
of the value the function will return to its caller on completion. 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 { 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, there is not sufficient context to determine the type parameters. For example,
`mem::size_of::<u32>() == 4`. `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 LLVMs 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 #### Diverging functions
A special kind of function can be declared with a `!` character where the 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); 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`. keyword `struct`.
An example of a `struct` item and its use: 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; 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: the keyword `struct`. For example:
``` ```
@ -1177,15 +1096,26 @@ let p = Point(10, 11);
let px: i32 = match p { Point(x, _) => x }; let px: i32 = match p { Point(x, _) => x };
``` ```
A _unit-like struct_ is a structure without any fields, defined by leaving off A _unit-like struct_ is a struct without any fields, defined by leaving off
the list of fields entirely. Such types will have a single value. For example: 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; 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). particular layout using the [`repr` attribute](#ffi-attributes).
### Enumerations ### Enumerations
@ -1508,11 +1438,11 @@ struct Foo;
trait Shape { fn area(&self) -> f64; } trait Shape { fn area(&self) -> f64; }
trait Circle : Shape { fn radius(&self) -> f64; } trait Circle : Shape { fn radius(&self) -> f64; }
# impl Shape for Foo { impl Shape for Foo {
# fn area(&self) -> f64 { fn area(&self) -> f64 {
# 0.0 0.0
# } }
# } }
impl Circle for Foo { impl Circle for Foo {
fn radius(&self) -> f64 { fn radius(&self) -> f64 {
println!("calling area: {}", self.area()); 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 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 methods in such an implementation can only be used as direct calls on the values
values of the type that the implementation targets. In such an implementation, of the type that the implementation targets. In such an implementation, the
the trait type and `for` after `impl` are omitted. Such implementations are trait type and `for` after `impl` are omitted. Such implementations are limited
limited to nominal types (enums, structs), and the implementation must appear to nominal types (enums, structs, trait objects), and the implementation must
in the same crate as the `self` type: appear in the same crate as the `self` type:
``` ```
struct Point {x: i32, y: i32} 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 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 macros named. The `extern crate` must appear at the crate root, not inside
`mod`, which ensures proper function of the [`$crate` macro `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. - `macro_reexport` on an `extern crate` — re-export the named macros.
@ -1987,7 +1917,7 @@ On `struct`s:
link it into the output. link it into the output.
See the [macros section of the 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. macro scope.
@ -2002,6 +1932,20 @@ macro scope.
- `simd` - on certain tuple structs, derive the arithmetic operators, which - `simd` - on certain tuple structs, derive the arithmetic operators, which
lower to the target's SIMD instructions, if any; the `simd` feature gate lower to the target's SIMD instructions, if any; the `simd` feature gate
is necessary to use this attribute. 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 - `unsafe_no_drop_flag` - on structs, remove the flag that prevents
destructors from being run twice. Destructors might be run multiple times on 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 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 * `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 to `"32"` for targets with 32-bit pointers, and likewise set to `"64"` for
64-bit pointers. 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). * `test` - Enabled when compiling the test harness (using the `--test` flag).
* `unix` - See `target_family`. * `unix` - See `target_family`.
* `windows` - 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) * `advanced_slice_patterns` - See the [match expressions](#match-expressions)
section for discussion; the exact semantics of section for discussion; the exact semantics of
slice patterns are subject to change, so some types 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 * `slice_patterns` - OK, actually, slice patterns are just scary and
completely unstable. 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 * `box_syntax` - Allows use of `box` expressions, the exact semantics of which
is subject to change. 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 * `concat_idents` - Allows use of the `concat_idents` macro, which is in many
ways insufficient for concatenating identifiers, and may be ways insufficient for concatenating identifiers, and may be
removed entirely for something more wholesome. removed entirely for something more wholesome.
@ -2411,6 +2360,7 @@ The currently implemented features of the reference compiler are:
terms of encapsulation). terms of encapsulation).
* - `default_type_parameter_fallback` - Allows type parameter defaults to * - `default_type_parameter_fallback` - Allows type parameter defaults to
influence type inference. 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 If a feature is promoted to a language feature, then all existing programs will
start to receive compilation warnings about `#![feature]` directives which enabled 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 An _item declaration statement_ has a syntactic form identical to an
[item](#items) declaration within a module. Declaring an item &mdash; a [item](#items) declaration within a module. Declaring an item &mdash; a
function, enumeration, structure, type, static, trait, implementation or module function, enumeration, struct, type, static, trait, implementation or module
&mdash; locally within a statement block is simply a way of restricting its &mdash; 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 scope to a narrow region containing all of its uses; it is otherwise identical
in meaning to declaring the item outside the statement block. in meaning to declaring the item outside the statement block.
@ -2560,7 +2510,7 @@ Here are some examples:
#### Moved and copied types #### Moved and copied types
When a [local variable](#variables) is used as an 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. if its type implements `Copy`. All others are moved.
### Literal expressions ### Literal expressions
@ -2579,7 +2529,7 @@ value, or the unit value.
### Path expressions ### Path expressions
A [path](#paths) used as an expression context denotes either a local variable 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 ### Tuple expressions
@ -2599,26 +2549,26 @@ comma:
(0); // zero in parentheses (0); // zero in parentheses
``` ```
### Structure expressions ### Struct expressions
There are several forms of structure expressions. A _structure expression_ There are several forms of struct expressions. A _struct expression_
consists of the [path](#paths) of a [structure item](#structures), followed by 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, 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. 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 The location denoted by a struct field is mutable if and only if the
enclosing structure is mutable. enclosing struct is mutable.
A _tuple structure expression_ consists of the [path](#paths) of a [structure A _tuple struct expression_ consists of the [path](#paths) of a [struct
item](#structures), followed by a parenthesized list of one or more item](#structs), followed by a parenthesized list of one or more
comma-separated expressions (in other words, the path of a structure item comma-separated expressions (in other words, the path of a struct item
followed by a tuple expression). The structure item must be a tuple structure followed by a tuple expression). The struct item must be a tuple struct
item. item.
A _unit-like structure expression_ consists only of the [path](#paths) of a A _unit-like struct expression_ consists only of the [path](#paths) of a
[structure item](#structures). [struct item](#structs).
The following are examples of structure expressions: The following are examples of struct expressions:
``` ```
# struct Point { x: f64, y: f64 } # 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); some_fn::<Cookie>(Cookie);
``` ```
A structure expression forms a new value of the named structure type. Note A struct expression forms a new value of the named struct type. Note
that for a given *unit-like* structure type, this will always be the same that for a given *unit-like* struct type, this will always be the same
value. 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 expression to denote a functional update. The expression following `..` (the
base) must have the same structure type as the new structure type being formed. base) must have the same struct type as the new struct type being formed.
The entire expression denotes the result of constructing a new structure (with 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 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 were explicitly specified and the values in the base expression for all other
fields. 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 A _field expression_ consists of an expression followed by a single dot and an
identifier, when not immediately followed by a parenthesized expression-list identifier, when not immediately followed by a parenthesized expression-list
(the latter is a [method call expression](#method-call-expressions)). A field (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} ```{.ignore .field}
mystruct.myfield; mystruct.myfield;
@ -2692,7 +2642,7 @@ foo().x;
(Struct {a: 10, b: 20}).a; (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, the value of that field. When the type providing the field inherits mutability,
it can be [assigned](#assignment-expressions) to. it can be [assigned](#assignment-expressions) to.
@ -2703,7 +2653,7 @@ fewer autoderefs to more.
### Array expressions ### 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. or more comma-separated expressions of uniform type in square brackets.
In the `[expr ';' expr]` form, the expression after the `';'` must be a 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 ### 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 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. be assigned to.
Indices are zero-based, and may be of any integral type. Vector access is 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 x = std::ops::Range {start: 0, end: 10};
let y = 0..10; let y = 0..10;
assert_eq!(x,y); assert_eq!(x, y);
``` ```
### Unary operator expressions ### Unary operator expressions
@ -2775,7 +2725,7 @@ before the expression they apply to.
* `*` * `*`
: Dereference. When applied to a [pointer](#pointer-types) it denotes the : Dereference. When applied to a [pointer](#pointer-types) it denotes the
pointed-to location. For pointers to mutable locations, the resulting 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` 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 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 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 #### Assignment expressions
An _assignment expression_ consists of an An _assignment expression_ consists of an
[lvalue](#lvalues,-rvalues-and-temporaries) expression followed by an equals [lvalue](#lvalues-rvalues-and-temporaries) expression followed by an equals
sign (`=`) and an [rvalue](#lvalues,-rvalues-and-temporaries) expression. sign (`=`) and an [rvalue](#lvalues-rvalues-and-temporaries) expression.
Evaluating an assignment expression [either copies or Evaluating an assignment expression [either copies or
moves](#moved-and-copied-types) its right-hand operand to its left-hand 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 a lifetime preceding the loop expression, as in `'foo: loop{ }`. If a
label is present, then labeled `break` and `continue` expressions nested 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. 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). expressions](#continue-expressions).
### Break expressions ### `break` expressions
A `break` expression has an optional _label_. If the label is absent, then A `break` expression has an optional _label_. If the label is absent, then
executing a `break` expression immediately terminates the innermost loop 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 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. 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 A `continue` expression has an optional _label_. If the label is absent, then
executing a `continue` expression immediately terminates the current iteration 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. 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. A `while` loop begins by evaluating the boolean loop conditional expression.
If the loop conditional expression evaluates to `true`, the loop body block 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 loops](#infinite-loops), [break expressions](#break-expressions), and
[continue expressions](#continue-expressions) for more information. [continue expressions](#continue-expressions) for more information.
### For expressions ### `for` expressions
A `for` expression is a syntactic construct for looping over elements provided A `for` expression is a syntactic construct for looping over elements provided
by an implementation of `std::iter::IntoIterator`. 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; # 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 loops](#infinite-loops), [break expressions](#break-expressions), and
[continue expressions](#continue-expressions) for more information. [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 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 `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 if` condition is evaluated. If all `if` and `else if` conditions evaluate to
`false` then any `else` block is executed. `false` then any `else` block is executed.
### Match expressions ### `match` expressions
A `match` expression branches on a *pattern*. The exact form of matching that A `match` expression branches on a *pattern*. The exact form of matching that
occurs depends on the pattern. Patterns consist of some combination of 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 variable binding specifications, wildcards (`..`), and placeholders (`_`). A
`match` expression has a *head expression*, which is the value to compare to `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 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. fields of a particular variant.
A `match` behaves differently depending on whether or not the head expression 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 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 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 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 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 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 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 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. loop body block executes and control returns to the pattern matching statement.
Otherwise, the while expression completes. Otherwise, the while expression completes.
### Return expressions ### `return` expressions
Return expressions are denoted with the keyword `return`. Evaluating a `return` Return expressions are denoted with the keyword `return`. Evaluating a `return`
expression moves its argument into the designated output location for the 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 All in-bounds elements of arrays and slices are always initialized, and access
to an array or slice is always bounds-checked. 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 A `struct` *type* is a heterogeneous product of other types, called the
*fields* of the type.[^structtype] *fields* of the type.[^structtype]
[^structtype]: `struct` types are analogous to `struct` types in C, [^structtype]: `struct` types are analogous to `struct` types in C,
the *record* types of the ML family, 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 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 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 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 The fields of a `struct` may be qualified by [visibility
modifiers](#visibility-and-privacy), to allow access to data in a 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. anonymous.
A _unit-like struct_ type is like a structure type, except that it has no A _unit-like struct_ type is like a struct type, except that it has no
fields. The one value constructed by the associated [structure fields. The one value constructed by the associated [struct
expression](#structure-expressions) is the only value that inhabits such a expression](#struct-expressions) is the only value that inhabits such a
type. type.
### Enumerated types ### Enumerated types
@ -3457,13 +3407,13 @@ named reference to an [`enum` item](#enumerations).
### Recursive types ### Recursive types
Nominal types &mdash; [enumerations](#enumerated-types) and Nominal types &mdash; [enumerations](#enumerated-types) and
[structures](#structure-types) &mdash; may be recursive. That is, each `enum` [structs](#struct-types) &mdash; may be recursive. That is, each `enum`
constructor or `struct` field may refer, directly or indirectly, to the constructor or `struct` field may refer, directly or indirectly, to the
enclosing `enum` or `struct` type itself. Such recursion has restrictions: enclosing `enum` or `struct` type itself. Such recursion has restrictions:
* Recursive types must include a nominal type in the recursion * Recursive types must include a nominal type in the recursion
(not mere [type definitions](grammar.html#type-definitions), (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 * A recursive `enum` item must have at least one non-recursive constructor
(in order to give the recursion a basis case). (in order to give the recursion a basis case).
* The size of a recursive type must be finite; * 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 ### Pointer types
All pointers in Rust are explicit first-class values. They can be copied, 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: varieties of pointer in Rust:
* References (`&`) * 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 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`. 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`. the sub-expression is a coercion site to `U`.
* Blocks: if a block has type `U`, then the last expression in the block (if * 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 ### Variables
A _variable_ is a component of a stack frame, either a named function parameter, 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. variable.
A _local variable_ (or *stack-local* allocation) holds a value directly, 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 The Rust compiler supports various methods to link crates together both
statically and dynamically. This section will explore the various methods to statically and dynamically. This section will explore the various methods to
link Rust crates together, and more information about native libraries can be 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 In one session of compilation, the compiler can generate multiple artifacts
through the usage of either command line flags or the `crate_type` attribute. 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. be ignored in favor of only building the artifacts specified by command line.
* `--crate-type=bin`, `#[crate_type = "bin"]` - A runnable executable will be * `--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 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 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 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. then only those outputs will be built.
With all these different kinds of outputs, if crate A depends on crate B, then 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 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. 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 LLVMs 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 # Appendix: Influences
@ -4036,7 +4075,7 @@ that have since been removed):
* SML, OCaml: algebraic data types, pattern matching, type inference, * SML, OCaml: algebraic data types, pattern matching, type inference,
semicolon statement separation semicolon statement separation
* C++: references, RAII, smart pointers, move semantics, monomorphisation, * C++: references, RAII, smart pointers, move semantics, monomorphization,
memory model memory model
* ML Kit, Cyclone: region based memory management * ML Kit, Cyclone: region based memory management
* Haskell (GHC): typeclasses, type families * Haskell (GHC): typeclasses, type families

View File

@ -338,14 +338,17 @@ table th {
.rusttest { display: none; } .rusttest { display: none; }
pre.rust { position: relative; } pre.rust { position: relative; }
.test-arrow { a.test-arrow {
display: inline-block; display: inline-block;
position: absolute; position: absolute;
top: 0;
right: 10px; background-color: #4e8bca;
font-size: 150%; color: #f5f5f5;
-webkit-transform: scaleX(-1); padding: 5px 10px 5px 10px;
transform: scaleX(-1); border-radius: 5px;
font-size: 130%;
top: 5px;
right: 5px;
} }
.unstable-feature { .unstable-feature {

View File

@ -48,7 +48,3 @@
* [Testing](testing/README.md) * [Testing](testing/README.md)
* [Unit testing](testing/unit.md) * [Unit testing](testing/unit.md)
* [FFI, platform-specific code](platform.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)

View File

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

View File

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

View File

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

View File

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

View File

@ -57,7 +57,7 @@ fn write_info(info: &Info) -> Result<(), IoError> {
``` ```
See 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. for more details.
### The `Result`-`impl` pattern [FIXME] ### The `Result`-`impl` pattern [FIXME]

View File

@ -17,12 +17,12 @@ Organize module headers as follows:
Avoid using `#[path="..."]` directives; make the file system and Avoid using `#[path="..."]` directives; make the file system and
module hierarchy match, instead. 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 > **[FIXME]** Flesh this out with examples; explain what a "coherent
> section" is with examples. > 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 > Breaking related functionality into submodules makes it understandable to both
> users and contributors to the module. > 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, 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. submodules of `io::net` easier to find.
### Consider top-level definitions or reexports. [FIXME: needs RFC] ### 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) [`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. 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]** > **[FIXME]**
> - Referencing internal modules from the standard library is subject to > - Referencing internal modules from the standard library is subject to
> becoming outdated. > 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. 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` For example, in [`std::io`](https://doc.rust-lang.org/std/io/), `mod mem`

View File

@ -9,18 +9,18 @@ applicable, common traits.
To see why, consider the following situation: To see why, consider the following situation:
* Crate `std` defines trait `Show`. * Crate `std` defines trait `Debug`.
* Crate `url` defines type `Url`, without implementing `Show`. * Crate `url` defines type `Url`, without implementing `Debug`.
* Crate `webapp` imports from both `std` and `url`, * 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 (Note: the newtype pattern can provide an efficient, but inconvenient
workaround; see [newtype for views](../types/newtype.md)) workaround; see [newtype for views](../types/newtype.md))
The most important common traits to implement from `std` are: The most important common traits to implement from `std` are:
```rust ```rust
Clone, Show, Hash, Eq Clone, Debug, Hash, Eq
``` ```
#### When safe, derive or otherwise implement `Send` and `Share`. [FIXME] #### When safe, derive or otherwise implement `Send` and `Share`. [FIXME]

View File

@ -27,7 +27,7 @@ explicitly implement to be used by this generic function.
* _Inference_. Since the type parameters to generic functions can usually be * _Inference_. Since the type parameters to generic functions can usually be
inferred, generic functions can help cut down on verbosity in code where inferred, generic functions can help cut down on verbosity in code where
explicit conversions or other method calls would usually be necessary. See the 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. below.
* _Precise types_. Because generics give a _name_ to the specific type * _Precise types_. Because generics give a _name_ to the specific type
implementing a trait, it is possible to be precise about places where that 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 a `Vec<T>` contains elements of a single concrete type (and, indeed, the
vector representation is specialized to lay these out in line). Sometimes vector representation is specialized to lay these out in line). Sometimes
heterogeneous collections are useful; see 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. * _Signature verbosity_. Heavy use of generics can bloat function signatures.
**[Ed. note]** This problem may be mitigated by some language improvements; stay tuned. **[Ed. note]** This problem may be mitigated by some language improvements; stay tuned.

View File

@ -5,7 +5,7 @@
> **[FIXME]** We probably want to discourage this, at least when used in a way > **[FIXME]** We probably want to discourage this, at least when used in a way
> that is publicly exposed. > 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 across types. For example, a `print` method can be defined across multiple
types as follows: types as follows:

View File

@ -85,3 +85,20 @@ Use inner doc comments _only_ to document crates and file-level modules:
//! //!
//! The core library is a something something... //! 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> {
// ...
}
```

View File

@ -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 systems. It improves on current languages targeting this space by having a
number of compile-time safety checks that produce no runtime overhead, while number of compile-time safety checks that produce no runtime overhead, while
eliminating all data races. Rust also aims to achieve zero-cost abstractions 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 even though some of these abstractions feel like those of a high-level language.
language. Even then, Rust still allows precise control like a low-level Even then, Rust still allows precise control like a low-level language would.
language would.
[rust]: https://www.rust-lang.org [rust]: https://www.rust-lang.org
@ -34,15 +33,15 @@ is the first. After this:
[gl]: glossary.html [gl]: glossary.html
[bi]: bibliography.html [bi]: bibliography.html
After reading this introduction, youll want to dive into either Learn Rust After reading this introduction, youll want to dive into either Learn Rust or
or Syntax and Semantics, depending on your preference: Learn Rust if you Syntax and Semantics, depending on your preference: Learn Rust if you want
want to dive in with a project, or Syntax and Semantics if you prefer to to dive in with a project, or Syntax and Semantics if you prefer to start
start small, and learn a single concept thoroughly before moving onto the next. small, and learn a single concept thoroughly before moving onto the next.
Copious cross-linking connects these parts together. Copious cross-linking connects these parts together.
### Contributing ### 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) [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 ## 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. annotating types.
Rust prefers stack allocation to heap allocation: `x` is placed directly on the 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 stack. However, the `Vec<T>` type allocates space for the elements of the vector
vector on the heap. If youre not familiar with this distinction, you can on the heap. If youre not familiar with this distinction, you can ignore it for
ignore it for now, or check out [The Stack and the Heap][heap]. As a systems now, or check out [The Stack and the Heap][heap]. As a systems programming
programming language, Rust gives you the ability to control how your memory is language, Rust gives us the ability to control how our memory is allocated, but
allocated, but when were getting started, its less of a big deal. when were getting started, its less of a big deal.
[var]: variable-bindings.html [var]: variable-bindings.html
[macro]: macros.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 parlance, `x` is said to own the vector. This means that when `x` goes out of
scope, the vectors memory will be de-allocated. This is done deterministically scope, the vectors memory will be de-allocated. This is done deterministically
by the Rust compiler, rather than through a mechanism such as a garbage by the Rust compiler, rather than through a mechanism such as a garbage
collector. In other words, in Rust, you dont call functions like `malloc` and collector. In other words, in Rust, we dont call functions like `malloc` and
`free` yourself: the compiler statically determines when you need to allocate `free` ourselves: the compiler statically determines when we need to allocate or
or deallocate memory, and inserts those calls itself. To err is to be human, deallocate memory, and inserts those calls itself. To err is to be human, but
but compilers never forget. compilers never forget.
Lets add another line to our example: Lets add another line to our example:
@ -105,13 +104,13 @@ fn main() {
} }
``` ```
Weve introduced another binding, `y`. In this case, `y` is a reference to Weve introduced another binding, `y`. In this case, `y` is a reference to the
the first element of the vector. Rusts references are similar to pointers in first element of the vector. Rusts references are similar to pointers in other
other languages, but with additional compile-time safety checks. References languages, but with additional compile-time safety checks. References interact
interact with the ownership system by [borrowing][borrowing] what they point with the ownership system by [borrowing][borrowing] what they point to, rather
to, rather than owning it. The difference is, when the reference goes out of than owning it. The difference is, when the reference goes out of scope, it
scope, it will not deallocate the underlying memory. If it did, wed won't deallocate the underlying memory. If it did, wed de-allocate twice, which
de-allocate twice, which is bad! is bad!
[borrowing]: references-and-borrowing.html [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 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 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 element of the vector, `y`. Mutating something while another reference exists
is dangerous, because we may invalidate the reference. In this specific case, 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. when we create the vector, we may have only allocated space for two elements.

View File

@ -68,5 +68,7 @@
* [Box Syntax and Patterns](box-syntax-and-patterns.md) * [Box Syntax and Patterns](box-syntax-and-patterns.md)
* [Slice Patterns](slice-patterns.md) * [Slice Patterns](slice-patterns.md)
* [Associated Constants](associated-constants.md) * [Associated Constants](associated-constants.md)
* [Custom Allocators](custom-allocators.md)
* [Glossary](glossary.md) * [Glossary](glossary.md)
* [Syntax Index](syntax-index.md)
* [Bibliography](bibliography.md) * [Bibliography](bibliography.md)

View File

@ -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 so it makes sense to provide extra command line
arguments, but this will not always be the case. In the future `rustc` may use 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 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`. `-C link-args` argument to `rustc`.
It is highly recommended to *not* use this attribute, and rather use the more 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 features on old systems or target systems which do not have the required
dependencies for your program to run. 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 your own version of Rust with `musl` enabled and install it into a custom
directory with the instructions below: 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 $ 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 $ tar xf llvm-3.7.0.src.tar.xz
$ cd llvm-3.7.0.src/projects/ $ 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 $ 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 $ mv libunwind-3.7.0.src libunwind
llvm-3.7.0.src/projects $ mkdir libunwind/build llvm-3.7.0.src/projects $ mkdir libunwind/build

View File

@ -48,7 +48,7 @@ Systems Level
Language](http://www.cs.indiana.edu/~eholk/papers/hips2013.pdf). Early GPU work by Eric Holk. Language](http://www.cs.indiana.edu/~eholk/papers/hips2013.pdf). Early GPU work by Eric Holk.
* [Parallel closures: a new twist on an old * [Parallel closures: a new twist on an old
idea](https://www.usenix.org/conference/hotpar12/parallel-closures-new-twist-old-idea) 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 * [Patina: A Formalization of the Rust Programming
Language](ftp://ftp.cs.washington.edu/tr/2015/03/UW-CSE-15-03-02.pdf). Early 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. 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 Rust](http://scialex.github.io/reenix.pdf). Undergrad paper by Alex
Light. Light.
* [Evaluation of performance and productivity metrics of potential * [Evaluation of performance and productivity metrics of potential
programming languages in the HPC environment](). Bachelor's thesis by programming languages in the HPC environment]
Florian Wilkens. Compares C, Go and Rust. (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 * [Nom, a byte oriented, streaming, zero copy, parser combinators library
in Rust](http://spw15.langsec.org/papers/couprie-nom.pdf). By in Rust](http://spw15.langsec.org/papers/couprie-nom.pdf). By
Geoffroy Couprie, research for VLC. Geoffroy Couprie, research for VLC.
@ -77,4 +78,5 @@ Language](http://www.cs.indiana.edu/~eholk/papers/hips2013.pdf). Early GPU work
Farnstrand's master's thesis. Farnstrand's master's thesis.
* [Session Types for * [Session Types for
Rust](http://munksgaard.me/papers/laumann-munksgaard-larsen.pdf). Philip Rust](http://munksgaard.me/papers/laumann-munksgaard-larsen.pdf). Philip
Munksgaard's master's thesis. Research for Servo. 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)

View File

@ -82,7 +82,7 @@ unsafe {
with: with:
```text ```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) (64 bits)
``` ```

View File

@ -204,7 +204,7 @@ borrow checker. Generally we know that such mutations won't happen in a nested f
to check. to check.
For large, complicated programs, it becomes useful to put some things in `RefCell`s to make things 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 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 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 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 # 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 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) author chose one like this (and when one should be using such a composition in one's own code)

View File

@ -1,9 +1,10 @@
% Closures % Closures
Rust not only has named functions, but anonymous functions as well. Anonymous Sometimes it is useful to wrap up a function and _free variables_ for better
functions that have an associated environment are called closures, because they clarity and reuse. The free variables that can be used come from the
close over an environment. Rust has a really great implementation of them, as enclosing scope and are closed over when used in the function. From this, we
well see. get the name closures and Rust provides a really great implementation of
them, as well see.
# Syntax # Syntax
@ -34,7 +35,7 @@ assert_eq!(4, plus_two(2));
``` ```
Youll notice a few things about closures that are a bit different from regular Youll 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 annotate the types of arguments the closure takes or the values it returns. We
can: can:
@ -44,14 +45,15 @@ let plus_one = |x: i32| -> i32 { x + 1 };
assert_eq!(2, plus_one(1)); assert_eq!(2, plus_one(1));
``` ```
But we dont have to. Why is this? Basically, it was chosen for ergonomic reasons. But we dont have to. Why is this? Basically, it was chosen for ergonomic
While specifying the full type for named functions is helpful with things like reasons. While specifying the full type for named functions is helpful with
documentation and type inference, the types of closures are rarely documented things like documentation and type inference, the full type signatures of
since theyre anonymous, and they dont cause the kinds of error-at-a-distance closures are rarely documented since theyre anonymous, and they dont cause
problems that inferring named function types can. 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. Ive added spaces The second is that the syntax is similar, but a bit different. Ive added
here for easier comparison: spaces here for easier comparison:
```rust ```rust
fn plus_one_v1 (x: i32) -> i32 { x + 1 } fn plus_one_v1 (x: i32) -> i32 { x + 1 }
@ -63,8 +65,8 @@ Small differences, but theyre similar.
# Closures and their environment # Closures and their environment
Closures are called such because they close over their environment. It The environment for a closure can include bindings from its enclosing scope in
looks like this: addition to parameters and local bindings. It looks like this:
```rust ```rust
let num = 5; 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 it, while a `move` closure is self-contained. This means that you cannot
generally return a non-`move` closure from a function, for example. 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 But before we talk about taking and returning closures, we should talk some
about the way that closures are implemented. As a systems language, Rust gives more about the way that closures are implemented. As a systems language, Rust
you tons of control over what your code does, and closures are no different. gives you tons of control over what your code does, and closures are no
different.
# Closure implementation # Closure implementation
@ -288,9 +291,9 @@ isnt interesting. The next part is:
# some_closure(1) } # some_closure(1) }
``` ```
Because `Fn` is a trait, we can bound our generic with it. In this case, our closure Because `Fn` is a trait, we can bound our generic with it. In this case, our
takes a `i32` as an argument and returns an `i32`, and so the generic bound we use closure takes a `i32` as an argument and returns an `i32`, and so the generic
is `Fn(i32) -> i32`. bound we use is `Fn(i32) -> i32`.
Theres one other key point here: because were bounding a generic with a Theres one other key point here: because were bounding a generic with a
trait, this will get monomorphized, and therefore, well be doing static trait, this will get monomorphized, and therefore, well 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 Right. Because we have a reference, we need to give it a lifetime. But
our `factory()` function takes no arguments, so elision doesnt kick in our `factory()` function takes no arguments, so
here. What lifetime can we choose? `'static`: [elision](lifetimes.html#lifetime-elision) doesnt kick in here. Then what
choices do we have? Try `'static`:
```rust,ignore ```rust,ignore
fn factory() -> &'static (Fn(i32) -> i32) { fn factory() -> &'static (Fn(i32) -> i32) {
@ -432,7 +436,7 @@ But we get another error:
```text ```text
error: mismatched types: error: mismatched types:
expected `&'static core::ops::Fn(i32) -> i32`, expected `&'static core::ops::Fn(i32) -> i32`,
found `[closure <anon>:7:9: 7:20]` found `[closure@<anon>:7:9: 7:20]`
(expected &-ptr, (expected &-ptr,
found closure) [E0308] found closure) [E0308]
|x| x + num |x| x + num
@ -441,21 +445,17 @@ error: mismatched types:
``` ```
This error is letting us know that we dont have a `&'static Fn(i32) -> i32`, This error is letting us know that we dont 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 Because each closure generates its own environment `struct` and implementation
of `Fn` and friends, these types are anonymous. They exist just solely for 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. autogenerated name.
But why doesnt our closure implement `&'static Fn`? Well, as we discussed before, The error also points out that the return type is expected to be a reference,
closures borrow their environment. And in this case, our environment is based but what we are trying to return is not. Further, we cannot directly assign a
on a stack-allocated `5`, the `num` variable binding. So the borrow has a lifetime `'static` lifetime to an object. So we'll take a different approach and return
of the stack frame. So if we returned this closure, the function call would be a trait object by `Box`ing up the `Fn`. This _almost_ works:
over, the stack frame would go away, and our closure is capturing an environment
of garbage memory!
So what to do? This _almost_ works:
```rust,ignore ```rust,ignore
fn factory() -> Box<Fn(i32) -> i32> { 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`. Theres just one last problem: Theres just one last problem:
```text ```text
error: closure may outlive the current function, but it borrows `num`, 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 Well, as we discussed before, closures borrow their environment. And in this
make this work: 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 ```rust
fn factory() -> Box<Fn(i32) -> i32> { fn factory() -> Box<Fn(i32) -> i32> {

View File

@ -170,13 +170,25 @@ starting point for an improved quasiquote as an ordinary plugin library.
Plugins can extend [Rust's lint Plugins can extend [Rust's lint
infrastructure](../reference.html#lint-check-attributes) with additional checks for infrastructure](../reference.html#lint-check-attributes) with additional checks for
code style, safety, etc. You can see 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)
[`src/test/auxiliary/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`.
for a full example, the core of which is reproduced here:
```ignore ```ignore
declare_lint!(TEST_LINT, Warn, #![feature(plugin_registrar)]
"Warn about items named 'lintme'"); #![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; struct Pass;
@ -184,9 +196,11 @@ impl LintPass for Pass {
fn get_lints(&self) -> LintArray { fn get_lints(&self) -> LintArray {
lint_array!(TEST_LINT) lint_array!(TEST_LINT)
} }
}
fn check_item(&mut self, cx: &Context, it: &ast::Item) { impl EarlyLintPass for Pass {
if it.ident.name == "lintme" { 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'"); cx.span_lint(TEST_LINT, it.span, "item is named 'lintme'");
} }
} }
@ -194,7 +208,7 @@ impl LintPass for Pass {
#[plugin_registrar] #[plugin_registrar]
pub fn plugin_registrar(reg: &mut Registry) { pub fn plugin_registrar(reg: &mut Registry) {
reg.register_lint_pass(box Pass as LintPassObject); reg.register_early_lint_pass(box Pass as EarlyLintPassObject);
} }
``` ```

View File

@ -26,8 +26,8 @@ to help us make sense of code that can possibly be concurrent.
### `Send` ### `Send`
The first trait we're going to talk about is The first trait we're going to talk about is
[`Send`](../std/marker/trait.Send.html). When a type `T` implements `Send`, it indicates [`Send`](../std/marker/trait.Send.html). When a type `T` implements `Send`, it
to the compiler that something of this type is able to have ownership transferred indicates that something of this type is able to have ownership transferred
safely between threads. safely between threads.
This is important to enforce certain restrictions. For example, if we have a 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 down the channel and to the other thread. Therefore, we'd ensure that `Send` was
implemented for that type. 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 threadsafe, we wouldn't want to implement `Send`, and so the compiler will help
us enforce that it can't leave the current thread. us enforce that it can't leave the current thread.
[ffi]: ffi.html
### `Sync` ### `Sync`
The second of these traits is called [`Sync`](../std/marker/trait.Sync.html). 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 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 For sharing references across threads, Rust provides a wrapper type called
threadsafe. Rust provides a type like this, `Arc<T>`, and it implements `Sync`, `Arc<T>`. `Arc<T>` implements `Send` and `Sync` if and only if `T` implements
so it is safe to share between threads. 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 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 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 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: 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 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`. 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 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. 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. 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, 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. mutate the value inside it at any one time.
For that, we can use the `Mutex<T>` type! 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 Also note that [`lock`](../std/sync/struct.Mutex.html#method.lock) method of
seen another error like: [`Mutex`](../std/sync/struct.Mutex.html) has this signature:
```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:
```ignore ```ignore
fn lock(&self) -> LockResult<MutexGuard<T>> fn lock(&self) -> LockResult<MutexGuard<T>>
``` ```
and because `Send` is not implemented for `MutexGuard<T>`, we couldn't have and because `Send` is not implemented for `MutexGuard<T>`, the guard cannot
transferred the guard across thread boundaries on it's own. cross thread boundaries, ensuring thread-locality of lock acquire and release.
Let's examine the body of the thread more closely: Let's examine the body of the thread more closely:
@ -317,22 +314,24 @@ use std::sync::mpsc;
fn main() { fn main() {
let (tx, rx) = mpsc::channel(); let (tx, rx) = mpsc::channel();
for _ in 0..10 { for i in 0..10 {
let tx = tx.clone(); let tx = tx.clone();
thread::spawn(move || { thread::spawn(move || {
let answer = 42; let answer = i * i;
tx.send(answer); 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 Here we create 10 threads, asking each to calculate the square of a number (`i`
the answer, and then it `send()`s us the answer over the channel. at the time of `spawn()`), and then `send()` back the answer over the channel.
## Panics ## Panics

View File

@ -34,7 +34,7 @@ These can nest arbitrarily:
As for how to enable or disable these switches, if youre using Cargo, As for how to enable or disable these switches, if youre using Cargo,
they get set in the [`[features]` section][features] of your `Cargo.toml`: 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 ```toml
[features] [features]

View File

@ -563,8 +563,8 @@ What's going on here?
First, both `extern crate` and `use` allow renaming the thing that is being 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 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 to it as "sayings". Similarly, the first `use` statement pulls in the
`japanese::farewells` module from the crate, but makes it available as `japanese::greetings` module from the crate, but makes it available as
`jp_farewells` as opposed to simply `farewells`. This can help to avoid `ja_greetings` as opposed to simply `greetings`. This can help to avoid
ambiguity when importing similarly-named items from different places. ambiguity when importing similarly-named items from different places.
The second `use` statement uses a star glob to bring in _all_ symbols from the 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 globbing to compress three `use` statements into one (this sort of syntax
may be familiar if you've written Linux shell scripts before). The may be familiar if you've written Linux shell scripts before). The
uncompressed form of this statement would be: uncompressed form of this statement would be:
```rust,ignore ```rust,ignore
use sayings::english; use sayings::english;
use sayings::english::greetings as en_greetings; use sayings::english::greetings as en_greetings;
use sayings::english::farewells as en_farewells; use sayings::english::farewells as en_farewells;
``` ```
As you can see, the curly brackets compress `use` statements for several items 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. 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. Note: The curly brackets cannot be nested or mixed with star globbing.

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

View File

@ -13,7 +13,7 @@ Hoare in 1985.
> dining room, furnished with a circular table, surrounded by five chairs, each > 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 > 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 > 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 > was constantly replenished. A philosopher was expected to spend most of
> their time thinking; but when they felt hungry, they went to the dining > 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, > room, sat down in their own chair, picked up their own fork on their left,
@ -45,7 +45,7 @@ Now, lets imagine this sequence of events:
6. ... ? All the forks are taken, but nobody can eat! 6. ... ? All the forks are taken, but nobody can eat!
There are different ways to solve this problem. Well get to our solution in There are different ways to solve this problem. Well get to our solution in
the tutorial itself. For now, lets get started modelling the problem itself. the tutorial itself. For now, lets get started modeling the problem itself.
Well start with the philosophers: Well start with the philosophers:
```rust ```rust
@ -434,7 +434,7 @@ ownership of the values its 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]. 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 ```rust,ignore
}).collect(); }).collect();
@ -512,6 +512,7 @@ impl Philosopher {
fn eat(&self, table: &Table) { fn eat(&self, table: &Table) {
let _left = table.forks[self.left].lock().unwrap(); let _left = table.forks[self.left].lock().unwrap();
thread::sleep_ms(150);
let _right = table.forks[self.right].lock().unwrap(); let _right = table.forks[self.right].lock().unwrap();
println!("{} is eating.", self.name); 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 ```rust,ignore
fn eat(&self, table: &Table) { fn eat(&self, table: &Table) {
let _left = table.forks[self.left].lock().unwrap(); let _left = table.forks[self.left].lock().unwrap();
thread::sleep_ms(150);
let _right = table.forks[self.right].lock().unwrap(); let _right = table.forks[self.right].lock().unwrap();
println!("{} is eating.", self.name); println!("{} is eating.", self.name);
@ -607,11 +609,14 @@ fn eat(&self, table: &Table) {
} }
``` ```
We have two new lines. Weve also added an argument, `table`. We access the We have three new lines. Weve added an argument, `table`. We access the
`Table`s list of forks, and then use `self.left` and `self.right` to access `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 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 index, and we call `lock()` on it. If the mutex is currently being accessed by
someone else, well block until it becomes available. someone else, well 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 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], 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, its all consistent until the very end. Monsieur you look at the pattern, its all consistent until the very end. Monsieur
Foucault should have `4, 0` as arguments, but instead, has `0, 4`. This is what 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 prevents deadlock, actually: one of our philosophers is left handed! This is
one way to solve the problem, and in my opinion, its the simplest. one way to solve the problem, and in my opinion, its the simplest. If you
change the order of the parameters, you will be able to observe the deadlock
taking place.
```rust,ignore ```rust,ignore
let handles: Vec<_> = philosophers.into_iter().map(|p| { let handles: Vec<_> = philosophers.into_iter().map(|p| {

View File

@ -45,7 +45,7 @@ Rust keeps track of these comments, and uses them when generating
documentation. This is important when documenting things like enums: documentation. This is important when documenting things like enums:
```rust ```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> { enum Option<T> {
/// No value /// No value
None, None,
@ -57,7 +57,7 @@ enum Option<T> {
The above works, but this does not: The above works, but this does not:
```rust,ignore ```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> { enum Option<T> {
None, /// No value None, /// No value
Some(T), /// Some value `T` Some(T), /// Some value `T`
@ -73,7 +73,7 @@ hello.rs:4 }
``` ```
This [unfortunate error](https://github.com/rust-lang/rust/issues/22547) is This [unfortunate error](https://github.com/rust-lang/rust/issues/22547) is
correct: documentation comments apply to the thing after them, and there's correct: documentation comments apply to the thing after them, and there's
nothing after that last comment. nothing after that last comment.
[rc-new]: https://doc.rust-lang.org/nightly/std/rc/struct.Rc.html#method.new [rc-new]: https://doc.rust-lang.org/nightly/std/rc/struct.Rc.html#method.new
@ -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 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: For example:
```rust ```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. 1. Any leading `#![foo]` attributes are left intact as crate attributes.
2. Some common `allow` attributes are inserted, including 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. 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 it makes the example more clear. You can use this technique to explain
longer examples in detail, while still preserving the testability of your 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 ```rust
let x = 5; let x = 5;
@ -277,37 +279,11 @@ let y = 6;
println!("{}", x + y); println!("{}", x + y);
``` ```
Here's an explanation, rendered: We might want the documentation to end up looking like this:
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:
> First, we set `x` to five: > First, we set `x` to five:
> >
> ```text > ```rust
> let x = 5; > let x = 5;
> # let y = 6; > # let y = 6;
> # println!("{}", x + y); > # println!("{}", x + y);
@ -315,7 +291,7 @@ Here's the same explanation, in raw text:
> >
> Next, we set `y` to six: > Next, we set `y` to six:
> >
> ```text > ```rust
> # let x = 5; > # let x = 5;
> let y = 6; > let y = 6;
> # println!("{}", x + y); > # println!("{}", x + y);
@ -323,12 +299,42 @@ Here's the same explanation, in raw text:
> >
> Finally, we print the sum of `x` and `y`: > Finally, we print the sum of `x` and `y`:
> >
> ```text > ```rust
> # let x = 5; > # let x = 5;
> # let y = 6; > # let y = 6;
> println!("{}", x + y); > 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 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 compiles, while only showing the parts that are relevant to that part of your
explanation. explanation.
@ -369,7 +375,7 @@ things, so they dont show up in the output.
### Running documentation tests ### Running documentation tests
To run the tests, either To run the tests, either:
```bash ```bash
$ rustdoc --test path/to/my/crate/root.rs $ 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 ## `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 ```rust
/// this /// this
@ -509,7 +516,7 @@ are the same, as are these:
```rust ```rust
//! this //! this
#![doc="/// this"] #![doc="this"]
``` ```
You won't often see this attribute used for writing documentation, but it You won't often see this attribute used for writing documentation, but it
@ -525,7 +532,7 @@ extern crate foo;
pub use foo::bar; 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 crate `foo`, as well as the documentation for your crate. It will use the same
documentation in both places. documentation in both places.
@ -538,6 +545,38 @@ extern crate foo;
pub use foo::bar; 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 ### Controlling HTML
You can control a few aspects of the HTML that `rustdoc` generates through the You can control a few aspects of the HTML that `rustdoc` generates through the

View File

@ -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 Here's another example that is slightly less contrived. A program that accepts
an integer as an argument, doubles it and prints it. an integer as an argument, doubles it and prints it.
<span id="code-unwrap-double"></span>
```rust,should_panic ```rust,should_panic
use std::env; 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` 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. types. Both of these types have a method called `unwrap` defined on them.
## The `Option` type ### The `Option` type
The `Option` type is The `Option` type is [defined in the standard library][5]:
[defined in the standard library][1]:
```rust ```rust
enum Option<T> { 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 programmer to handle that absence. Let's take a look at an example that tries
to find a character in a string: to find a character in a string:
<span id="code-option-ex-string-find"></span>
```rust ```rust
// Searches `haystack` for the Unicode character `needle`. If one is found, the // Searches `haystack` for the Unicode character `needle`. If one is found, the
// byte offset of the character is returned. Otherwise, `None` is returned. // 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 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 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 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 means that you, as the programmer, must handle the case when an `Option<T>` is
`None` instead of `Some(t)`. `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 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: `unwrap` method for you. You could define it yourself if you want:
<span id="code-option-def-unwrap"></span>
```rust ```rust
enum Option<T> { enum Option<T> {
None, None,
@ -206,7 +211,7 @@ that makes `unwrap` ergonomic to use. Unfortunately, that `panic!` means that
### Composing `Option<T>` values ### 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, 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 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 no extension. This *possibility of absence* is encoded into the types using
@ -220,7 +225,7 @@ sense to put it into a function:
```rust ```rust
# fn find(_: &str, _: char) -> Option<usize> { None } # fn find(_: &str, _: char) -> Option<usize> { None }
// Returns the extension of the given file name, where the extension is defined // 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. // If `file_name` has no `.`, then `None` is returned.
fn extension_explicit(file_name: &str) -> Option<&str> { fn extension_explicit(file_name: &str) -> Option<&str> {
match find(file_name, '.') { 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 Rust has parametric polymorphism, so it is very easy to define a combinator
that abstracts this pattern: that abstracts this pattern:
<span id="code-option-map"></span>
```rust ```rust
fn map<F, T, A>(option: Option<T>, f: F) -> Option<A> where F: FnOnce(T) -> A { fn map<F, T, A>(option: Option<T>, f: F) -> Option<A> where F: FnOnce(T) -> A {
match option { match option {
@ -265,18 +272,18 @@ to get rid of the case analysis:
```rust ```rust
# fn find(_: &str, _: char) -> Option<usize> { None } # fn find(_: &str, _: char) -> Option<usize> { None }
// Returns the extension of the given file name, where the extension is defined // 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. // If `file_name` has no `.`, then `None` is returned.
fn extension(file_name: &str) -> Option<&str> { fn extension(file_name: &str) -> Option<&str> {
find(file_name, '.').map(|i| &file_name[i+1..]) find(file_name, '.').map(|i| &file_name[i+1..])
} }
``` ```
One other pattern that we find is very common is assigning a default value to One other pattern we commonly find is assigning a default value to the case
the case when an `Option` value is `None`. For example, maybe your program when an `Option` value is `None`. For example, maybe your program assumes that
assumes that the extension of a file is `rs` even if none is present. As you the extension of a file is `rs` even if none is present. As you might imagine,
might imagine, the case analysis for this is not specific to file the case analysis for this is not specific to file extensions - it can work
extensions - it can work with any `Option<T>`: with any `Option<T>`:
```rust ```rust
fn unwrap_or<T>(option: Option<T>, default: T) -> T { 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 The `Result` type is also
[defined in the standard library][6]: [defined in the standard library][6]:
<span id="code-result-def"></span>
```rust ```rust
enum Result<T, E> { enum Result<T, E> {
Ok(T), Ok(T),
@ -553,7 +562,7 @@ combinators that affect only the error type, such as
### The `Result` type alias idiom ### The `Result` type alias idiom
In the standard library, you may frequently see types like 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 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 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 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 (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: could just use a `String` to describe the error. Let's try:
<span id="code-error-double-string"></span>
```rust ```rust
use std::env; use std::env;
@ -744,7 +755,7 @@ fn main() {
(N.B. The `AsRef<Path>` is used because those are the (N.B. The `AsRef<Path>` is used because those are the
[same bounds used on [same bounds used on
`std::fs::File::open`](../std/fs/struct.File.html#method.open). `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: 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 an `i32`) by `2`. If an error had occurred before that point, this operation
would have been skipped because of how `map` is defined. 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 `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 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 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: Here is a simplified definition of a `try!` macro:
<span id="code-try-def-simple"></span>
```rust ```rust
macro_rules! try { macro_rules! try {
($e:expr) => (match $e { ($e:expr) => (match $e {
@ -1155,6 +1168,8 @@ The `std::convert::From` trait is
[defined in the standard [defined in the standard
library](../std/convert/trait.From.html): library](../std/convert/trait.From.html):
<span id="code-from-def"></span>
```rust ```rust
trait From<T> { trait From<T> {
fn from(T) -> Self; 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` 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, 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. compiler's knowledge, so it truly sees `err1` and `err2` as exactly the same.
Additionally, we constructed `err1` and `err2` using precisely 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 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): [in the standard library](../std/macro.try!.html):
<span id="code-try-def"></span>
```rust ```rust
macro_rules! try { macro_rules! try {
($e:expr) => (match $e { ($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 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 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>`: `Box<Error>`:
```rust ```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 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 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 To get started from scratch, run `cargo new --bin city-pop` and make sure your
`Cargo.toml` looks something like this: `Cargo.toml` looks something like this:
@ -1528,14 +1545,14 @@ cargo build --release
## Argument parsing ## 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] detail on Getopts, but there is [some good documentation][15]
describing it. The short story is that Getopts generates an argument 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 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 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 parsing is done, we can decode the program arguments into a Rust
struct. From there, we can get information about the flags, for 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` had. Here's our program with the appropriate `extern crate`
statements, and the basic argument setup for Getopts: statements, and the basic argument setup for Getopts:
@ -1556,7 +1573,7 @@ fn main() {
let mut opts = Options::new(); let mut opts = Options::new();
opts.optflag("h", "help", "Show this usage message."); opts.optflag("h", "help", "Show this usage message.");
let matches = match opts.parse(&args[1..]) { let matches = match opts.parse(&args[1..]) {
Ok(m) => { m } Ok(m) => { m }
Err(e) => { panic!(e.to_string()) } Err(e) => { panic!(e.to_string()) }
@ -1567,7 +1584,7 @@ fn main() {
} }
let data_path = args[1].clone(); let data_path = args[1].clone();
let city = args[2].clone(); let city = args[2].clone();
// Do stuff with information // Do stuff with information
} }
``` ```
@ -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 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 help message flag. Once we have the argument flags set up, we use
`Options.parse` to parse the argument vector (starting from index one, `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, 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 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 message. The option help messages are constructed by Getopts, so all
@ -1630,27 +1647,27 @@ fn main() {
let mut opts = Options::new(); let mut opts = Options::new();
opts.optflag("h", "help", "Show this usage message."); opts.optflag("h", "help", "Show this usage message.");
let matches = match opts.parse(&args[1..]) { let matches = match opts.parse(&args[1..]) {
Ok(m) => { m } Ok(m) => { m }
Err(e) => { panic!(e.to_string()) } Err(e) => { panic!(e.to_string()) }
}; };
if matches.opt_present("h") { if matches.opt_present("h") {
print_usage(&program, opts); print_usage(&program, opts);
return; return;
} }
let data_file = args[1].clone(); let data_file = args[1].clone();
let data_path = Path::new(&data_file); let data_path = Path::new(&data_file);
let city = args[2].clone(); let city = args[2].clone();
let file = fs::File::open(data_path).unwrap(); let file = fs::File::open(data_path).unwrap();
let mut rdr = csv::Reader::from_reader(file); let mut rdr = csv::Reader::from_reader(file);
for row in rdr.decode::<Row>() { for row in rdr.decode::<Row>() {
let row = row.unwrap(); let row = row.unwrap();
if row.city == city { if row.city == city {
println!("{}, {}: {:?}", println!("{}, {}: {:?}",
row.city, row.country, row.city, row.country,
@ -1756,7 +1773,7 @@ fn main() {
print_usage(&program, opts); print_usage(&program, opts);
return; return;
} }
let data_file = args[1].clone(); let data_file = args[1].clone();
let data_path = Path::new(&data_file); let data_path = Path::new(&data_file);
let city = args[2].clone(); let city = args[2].clone();
@ -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 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! 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: have to do:
1. Tweak the program arguments so that a single parameter—the 1. Tweak the program arguments so that a single parameter—the
@ -1865,7 +1882,7 @@ opts.optflag("h", "help", "Show this usage message.");
... ...
let file = matches.opt_str("f"); let file = matches.opt_str("f");
let data_file = file.as_ref().map(Path::new); let data_file = file.as_ref().map(Path::new);
let city = if !matches.free.is_empty() { let city = if !matches.free.is_empty() {
matches.free[0].clone() matches.free[0].clone()
} else { } else {
@ -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 `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 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 the `Option<String>` into an `Option<&str>`, and from there, we can
execute `Path::new` to the content of the optional, and return the 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. be used in shell scripts.
So let's start by adding the flags. Like before, we need to tweak the usage 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 ```rust,ignore
... ...
let mut opts = Options::new(); let mut opts = Options::new();
opts.optopt("f", "file", "Choose an input file, instead of using STDIN.", "NAME"); opts.optopt("f", "file", "Choose an input file, instead of using STDIN.", "NAME");
opts.optflag("h", "help", "Show this usage message."); 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 and
[`Error`](../std/error/trait.Error.html) [`Error`](../std/error/trait.Error.html)
impls to make the [`try!`](../std/macro.try!.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 * If you're writing a library and your code can produce errors, define your own
error type and implement the error type and implement the
[`std::error::Error`](../std/error/trait.Error.html) [`std::error::Error`](../std/error/trait.Error.html)

View File

@ -1,5 +1,5 @@
% Getting Started % 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, well install Rust. Then, the classic Hello World program. Finally, First, well install Rust. Then, the classic Hello World program. Finally,
well talk about Cargo, Rusts build system and package manager. well talk about Cargo, Rusts build system and package manager.

View File

@ -38,11 +38,19 @@ let z = (8, 2, 6);
In the example above `x` and `y` have arity 2. `z` has arity 3. 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) ### DST (Dynamically Sized Type)
A type without a statically known size or alignment. ([more info][link]) 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 ### Expression

View File

@ -99,9 +99,12 @@ use std::io;
Well need to take user input, and then print the result as output. As such, we Well 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 need the `io` library from the standard library. Rust only imports a few things
by default into every program, [the prelude][prelude]. If its not in the by default into every program, [the prelude][prelude]. If its not in the
prelude, youll have to `use` it directly. prelude, youll 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 [prelude]: ../std/prelude/index.html
[ioprelude]: ../std/io/prelude/index.html
```rust,ignore ```rust,ignore
fn main() { fn main() {
@ -147,7 +150,7 @@ a few tricks up their sleeves.
For example, theyre [immutable][immutable] by default. Thats why our example For example, theyre [immutable][immutable] by default. Thats why our example
uses `mut`: it makes a binding mutable, rather than immutable. `let` doesnt uses `mut`: it makes a binding mutable, rather than immutable. `let` doesnt
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]. Well use patterns later. Its easy enough [pattern][patterns]. Well use patterns later. Its easy enough
to use for now: 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 `Foo::Bar` or a `Foo::Baz`. We use the `::` to indicate the
namespace for a particular `enum` variant. 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 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 create an arm for each possible value. Since we have three types of
`Ordering`, we have three arms: `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 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` 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 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 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 of the `Ok` to the name `num`, and then we just return it on the right-hand
side. In the `Err` case, we dont care what kind of error it is, so we just side. In the `Err` case, we dont care what kind of error it is, so we just

View File

@ -7,15 +7,16 @@ so it is assumed that Rust projects will use Cargo from the beginning.
[cratesio]: http://doc.crates.io [cratesio]: http://doc.crates.io
Cargo manages three things: building your code, downloading the dependencies Cargo manages three things: building our code, downloading the dependencies our
your code needs, and building those dependencies. At first, your program doesnt code needs, and building those dependencies. At first, our program doesnt have
have any dependencies, so well only be using the first part of its any dependencies, so well only be using the first part of its functionality.
functionality. Eventually, well add more. Since we started off by using Cargo, Eventually, well add more. Since we started off by using Cargo, it'll be easy
it'll be easy to add later. to add later.
If we installed Rust via the official installers we will also have Cargo. If we If you installed Rust via the official installers you will also have Cargo. If
installed Rust some other way, we may want to [check the Cargo you installed Rust some other way, you may want to
README][cargoreadme] for specific instructions about installing it. [check the Cargo README][cargoreadme] for specific instructions about installing
it.
[cargoreadme]: https://github.com/rust-lang/cargo#installing-cargo-from-nightlies [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 ```bash
$ mkdir src $ mkdir src
$ mv main.rs src/main.rs $ 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 > 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 > 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 > convention is used by Cargo to successfully compile our projects, but it can
overridden if we wish. Custom file locations for the entry point can be > 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. > specified with a [`[lib]` or `[[bin]]`][crates-custom] key in the TOML file.
[crates-custom]: http://doc.crates.io/manifest.html#configuring-a-target [crates-custom]: http://doc.crates.io/manifest.html#configuring-a-target
Cargo expects your source files to live inside a `src` directory. That leaves Cargo expects our source files to live inside a `src` directory. That leaves the
the top level for other things, like READMEs, license information, and anything top level for other things, like READMEs, license information, and anything not
not related to your code. Cargo helps us keep our projects nice and tidy. A related to our code. Cargo helps us keep our projects nice and tidy. A place for
place for everything, and everything in its place. everything, and everything in its place.
Next, our configuration file: Next, our configuration file:
```bash ```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: 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 things to get all of the parts to properly compile. With Cargo, as our project
grows, we can just run `cargo build`, and itll work the right way. grows, we can just run `cargo build`, and itll work the right way.
When your project is finally ready for release, you can use When our project is finally ready for release, we can use `cargo build
`cargo build --release` to compile your project with optimizations. --release` to compile our project with optimizations.
You'll also notice that Cargo has created a new file: `Cargo.lock`. You'll also notice that Cargo has created a new file: `Cargo.lock`.
@ -120,14 +121,14 @@ name = "hello_world"
version = "0.0.1" version = "0.0.1"
``` ```
The `Cargo.lock` file is used by Cargo to keep track of dependencies in your application. The `Cargo.lock` file is used by Cargo to keep track of dependencies in our
Right now, we dont have any, so its a bit sparse. You won't ever need application. Right now, we dont have any, so its a bit sparse. We won't ever
to touch this file yourself, just let Cargo handle it. need to touch this file ourselves, just let Cargo handle it.
Thats it! Weve successfully built `hello_world` with Cargo. Even though our Thats it! Weve successfully built `hello_world` with Cargo. Even though our
program is simple, its using much of the real tooling that youll use for the program is simple, its using much of the real tooling that well use for the
rest of your Rust career. You can expect to do this to get started with rest of our Rust career. We can expect to do this to get started with virtually
virtually all Rust projects: all Rust projects:
```bash ```bash
$ git clone someurl.com/foo $ git clone someurl.com/foo
@ -137,17 +138,19 @@ $ cargo build
## A New Project ## A New Project
You dont have to go through this whole process every time you want to start a We dont have to go through this whole process every time we want to start a new
new project! Cargo has the ability to make a bare-bones project directory in project! Cargo has the ability to make a bare-bones project directory in which
which you can start developing right away. 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 ```bash
$ cargo new hello_world --bin $ cargo new hello_world --bin
``` ```
Were 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 youre on a Unix system) Were 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 were on a Unix system)
Let's check out what Cargo has generated for us: Let's check out what Cargo has generated for us:
@ -162,7 +165,7 @@ $ tree .
1 directory, 2 files 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
distributions package manager. Its not necessary, but its certainly useful. distributions package manager. Its not necessary, but its certainly useful.
This is all we need to get started. First, lets check out `Cargo.toml`: This is all we need to get started. First, lets 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 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. also initialized the `hello_world` directory as a `git` repository.
Heres whats in `src/main.rs`: Heres whats in `src/main.rs`:
@ -187,20 +190,21 @@ fn main() {
} }
``` ```
Cargo has generated a "Hello World!" for us, and youre ready to start coding! Cargo Cargo has generated a "Hello World!" for us, and were ready to start coding!
has its own [guide][guide] which covers Cargos features in much more depth. Cargo has its own [guide][guide] which covers Cargos features in much more
depth.
[guide]: http://doc.crates.io/guide.html [guide]: http://doc.crates.io/guide.html
Now that youve got the tools down, lets actually learn more about the Rust Now that weve got the tools down, lets actually learn more about the Rust
language itself. These are the basics that will serve you well through the rest language itself. These are the basics that will serve us well through the rest
of your time with Rust. of our time with Rust.
You have two options: Dive into a project with [Learn Rust][learnrust], or 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 start from the bottom and work your way up with
Semantics][syntax]. More experienced systems programmers will probably prefer [Syntax and Semantics][syntax]. More experienced systems programmers will
Learn Rust, while those from dynamic backgrounds may enjoy either. Different probably prefer Learn Rust, while those from dynamic backgrounds may enjoy
people learn differently! Choose whatevers right for you. either. Different people learn differently! Choose whatevers right for you.
[learnrust]: learn-rust.html [learnrust]: learn-rust.html
[syntax]: syntax-and-semantics.html [syntax]: syntax-and-semantics.html

View File

@ -1,25 +1,25 @@
% Hello, world! % Hello, world!
Now that you have Rust installed, lets write your first Rust program. Its Now that we have Rust installed, lets write our first Rust program. Its
traditional to make your first program in any new language one that prints the 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 text “Hello, world!” to the screen. The nice thing about starting with such a
simple program is that you can verify that your compiler isnt just installed, simple program is that we can verify that our compiler isnt just installed, but
but also working properly. And printing information to the screen is a pretty also working properly. And printing information to the screen is a pretty common
common thing to do. thing to do.
The first thing that we need to do is make a file to put our code in. I like The first thing that we need to do is make a file to put our code in. I like to
to make a `projects` directory in my home directory, and keep all my projects make a `projects` directory in my home directory, and keep all my projects
there. Rust does not care where your code lives. there. Rust doesn't care where our code lives.
This actually leads to one other concern we should address: this guide will 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 assume that we have basic familiarity with the command line. Rust itself makes
no specific demands on your editing tooling, or where your code lives. If you no specific demands on our editing tooling, or where our code lives. If we
prefer an IDE to the command line, you may want to check out prefer an IDE to the command line, we may want to check out
[SolidOak][solidoak], or wherever plugins are for your favorite IDE. There are [SolidOak][solidoak], or wherever plugins are for our favorite IDE. There are a
a number of extensions of varying quality in development by the community. The number of extensions of varying quality in development by the community. The
Rust team also ships [plugins for various editors][plugins]. Configuring your 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 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 [solidoak]: https://github.com/oakes/SolidOak
[plugins]: https://github.com/rust-lang/rust/blob/master/src/etc/CONFIGS.md [plugins]: https://github.com/rust-lang/rust/blob/master/src/etc/CONFIGS.md
@ -33,14 +33,15 @@ $ mkdir hello_world
$ cd hello_world $ cd hello_world
``` ```
If youre on Windows and not using PowerShell, the `~` may not work. Consult If were on Windows and not using PowerShell, the `~` may not work. Consult the
the documentation for your shell for more details. documentation for our shell for more details.
Lets make a new source file next. Well call our file `main.rs`. Rust files Lets make a new source file next. Well call our file `main.rs`. Rust files
always end in a `.rs` extension. If youre using more than one word in your always end in a `.rs` extension, and if were using more than one word in a
filename, use an underscore: `hello_world.rs` rather than `helloworld.rs`. Rust filename, we use an underscore: for example, `linked_list.rs`, not
`linkedlist.rs` or `LinkedList.rs`.
Now that youve got your file open, type this in: Now that weve got our file open, type this in:
```rust ```rust
fn main() { 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 ```bash
$ rustc main.rs $ rustc main.rs
@ -72,9 +73,9 @@ we arent returning anything from this function, we can omit the return type
entirely. Well get to it later. entirely. Well get to it later.
Youll also note that the function is wrapped in curly braces (`{` and `}`). Youll also note that the function is wrapped in curly braces (`{` and `}`).
Rust requires these around all function bodies. It is also considered good Rust requires these around all function bodies. It is also considered good style
style to put the opening curly brace on the same line as the function to put the opening curly brace on the same line as the function declaration,
declaration, with one space in between. with one space in between.
Next up is this line: 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 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 its indented with four details that are important here. The first is that its indented with four
spaces, not tabs. Please configure your editor of choice to insert four spaces spaces, not tabs. Please configure your editor of choice to insert four spaces
with the tab key. We provide some [sample configurations for various with the tab key. We provide some
editors][configs]. [sample configurations for various editors][configs].
[configs]: https://github.com/rust-lang/rust/tree/master/src/etc/CONFIGS.md [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], The second point is the `println!()` part. This is calling a Rust
which is how metaprogramming is done in Rust. If it were a function instead, it [macro][macro], which is how metaprogramming is done in Rust. If it were a
would look like this: `println()`. For our purposes, we dont need to worry function instead, it would look like this: `println()`. For our purposes, we
about this difference. Just know that sometimes, youll see a `!`, and that dont need to worry about this difference. Just know that sometimes, well see a
means that youre calling a macro instead of a normal function. Rust implements `!`, and that means that were calling a macro instead of a normal function.
`println!` as a macro rather than a function for good reasons, but that's an Rust implements `println!` as a macro rather than a function for good reasons,
advanced topic. One last thing to mention: Rusts macros are significantly but that's an advanced topic. One last thing to mention: Rusts macros are
different from C macros, if youve used those. Dont be scared of using macros. significantly different from C macros, if youve used those. Dont be scared of
Well get to the details eventually, youll just have to trust us for now. using macros. Well get to the details eventually, youll just have to take it
on trust for now.
[macro]: macros.html [macro]: macros.html
Next, `"Hello, world!"` is a string. Strings are a surprisingly complicated Next, `"Hello, world!"` is a string. Strings are a surprisingly complicated
topic in a systems programming language, and this is a statically allocated topic in a systems programming language, and this is a statically allocated
string. If you want to read further about allocation, check out string. If you want to read further about allocation, check out [the stack and
[the stack and the heap][allocation], but you dont need to right now if you the heap][allocation], but you dont need to right now if you dont want to. We
dont want to. We pass this string as an argument to `println!`, which prints the pass this string as an argument to `println!`, which prints the string to the
string to the screen. Easy enough! screen. Easy enough!
[allocation]: the-stack-and-the-heap.html [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 $ rustc main.rs
``` ```
This is similar to `gcc` or `clang`, if you come from a C or C++ background. Rust This is similar to `gcc` or `clang`, if you come from a C or C++ background.
will output a binary executable. You can see it with `ls`: Rust will output a binary executable. We can see it with `ls`:
```bash ```bash
$ ls $ ls
@ -142,7 +144,7 @@ main.exe main.rs
``` ```
There are now two files: our source code, with the `.rs` extension, and the 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 ```bash
$ ./main # or main.exe on Windows $ ./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. This prints out our `Hello, world!` text to our terminal.
If you come from a dynamic language like Ruby, Python, or JavaScript, If you come from a dynamic language like Ruby, Python, or JavaScript, you may
you may not be used to these two steps being separate. Rust is an not be used to these two steps being separate. Rust is an ahead-of-time
ahead-of-time compiled language, which means that you can compile a program, compiled language, which means that we can compile a program, give it to
give it to someone else, and they don't need to have Rust installed. If you someone else, and they don't need to have Rust installed. If we give someone a
give someone a `.rb` or `.py` or `.js` file, they need to have a `.rb` or `.py` or `.js` file, they need to have a Ruby/Python/JavaScript
Ruby/Python/JavaScript implementation installed, but you just need one command implementation installed, but we just need one command to both compile and run
to both compile and run your program. Everything is a tradeoff in language our program. Everything is a tradeoff in language design, and Rust has made its
design, and Rust has made its choice. choice.
Congratulations! You have officially written a Rust program. That makes you a Congratulations! You have officially written a Rust program. That makes you a
Rust programmer! Welcome. 🎊🎉👍 Rust programmer! Welcome. 🎊🎉👍
Next, I'd like to introduce you to another tool, Cargo, which is used to write 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 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 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 your code with other people and that it has, and to make it easy to share our code with other people and
projects. projects.

View File

@ -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 value to the identifiers in the pattern, then evaluates the expression. If
the pattern doesnt match, nothing happens. the pattern doesnt match, nothing happens.
If youd 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`: use `else`:
```rust ```rust
@ -65,7 +65,7 @@ loop as long as a value matches a certain pattern. It turns code like this:
loop { loop {
match option { match option {
Some(x) => println!("{}", x), Some(x) => println!("{}", x),
_ => break, None => break,
} }
} }
``` ```

View File

@ -1,21 +1,21 @@
% Installing Rust % Installing Rust
The first step to using Rust is to install it! There are a number of ways to 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 install Rust, but the easiest is to use the `rustup` script. If we're on Linux
or a Mac, all you need to do is this: 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 > Note: we don't need to type in the `$`s, they are there to indicate the start of
> each command. Youll see many tutorials and examples around the web that > each command. Well see many tutorials and examples around the web that
> follow this convention: `$` for commands run as your regular user, and > follow this convention: `$` for commands run as our regular user, and `#` for
> `#` for commands you should be running as an administrator. > commands we should be running as an administrator.
```bash ```bash
$ curl -sf -L https://static.rust-lang.org/rustup.sh | sh $ curl -sf -L https://static.rust-lang.org/rustup.sh | sh
``` ```
If you're concerned about the [potential insecurity][insecurity] of using `curl 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 sh`, please keep reading and see our disclaimer below. And feel free to use a
use a two-step version of the installation and examine our installation script: two-step version of the installation and examine our installation script:
```bash ```bash
$ curl -f -L https://static.rust-lang.org/rustup.sh -O $ curl -f -L https://static.rust-lang.org/rustup.sh -O
@ -25,11 +25,12 @@ $ sh rustup.sh
[insecurity]: http://curlpipesh.tumblr.com [insecurity]: http://curlpipesh.tumblr.com
If you're on Windows, please download the appropriate [installer][install-page]. 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 > Note: By default, the Windows installer won't add Rust to the %PATH% system
want to be able to run it from the command line, click on "Advanced" on the > variable. If this is the only version of Rust we are installing and we want to
install dialog and on the "Product Features" page ensure "Add to PATH" is > be able to run it from the command line, click on "Advanced" on the install
installed on the local hard drive. > 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 [install-page]: https://www.rust-lang.org/install.html
@ -37,78 +38,145 @@ installed on the local hard drive.
## Uninstalling ## Uninstalling
If you decide you don't want Rust anymore, we'll be a bit sad, but that's okay. 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 Not every programming language is great for everyone. We can run the
script: uninstall script:
```bash ```bash
$ sudo /usr/local/lib/rustlib/uninstall.sh $ sudo /usr/local/lib/rustlib/uninstall.sh
``` ```
If you used the Windows installer, just re-run the `.msi` and it will give you If we used the Windows installer, we can re-run the `.msi` and it will give
an uninstall option. us an uninstall option.
## That disclaimer we promised ## That disclaimer we promised
Some people, and somewhat rightfully so, get very upset when we tell you to Some people, and somewhat rightfully so, get very upset when we tell them to
`curl | sh`. Basically, when you do this, you are trusting that the good `curl | sh`. Their concern is that `curl | sh` implicitly requires you to trust
people who maintain Rust aren't going to hack your computer and do bad things. that the good people who maintain Rust aren't going to hack your computer and
That's a good instinct! If you're one of those people, please check out the do bad things — and even having accepted that, there is still the possibility
documentation on [building Rust from Source][from-source], or [the official that the Rust website has been hacked and the `rustup` script compromised.
binary downloads][install-page].
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 [from-source]: https://github.com/rust-lang/rust#building-from-source
## Platform support ## 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) Platforms are identified by their "target triple" which is the string to inform
* Linux (2.6.18 or later, various distributions), x86 and x86-64 the compiler what kind of output should be produced. The columns below indicate
* OSX 10.7 (Lion) or greater, x86 and x86-64 whether the corresponding component works on the specified platform.
We extensively test Rust on these platforms, and a few others, too, like ### Tier 1
Android. But these are the ones most likely to work, as they have the most
testing.
Finally, a comment about Windows. Rust considers Windows to be a first-class Tier 1 platforms can be thought of as "guaranteed to build and work".
platform upon release, but if we're honest, the Windows experience isn't as Specifically they will each satisfy the following requirements:
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 * Automated testing is set up to run tests for the platform.
commit is tested against Windows just like any other 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 ## 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 ```bash
$ rustc --version $ rustc --version
``` ```
You should see the version number, commit hash, and commit date. If you just You should see the version number, commit hash, and commit date.
installed version 1.2.0, you should see:
```bash If you do, Rust has been installed successfully! Congrats!
rustc 1.2.0 (082e47636 2015-08-03)
```
If you did, Rust has been installed successfully! Congrats! If you don't and you're on Windows, check that Rust is in your %PATH% system
If you didn'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, 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 repair, or remove installation" page and ensure "Add to PATH" is installed on
the local hard drive. the local hard drive.
This installer also installs a copy of the documentation locally, so you can This installer also installs a copy of the documentation locally, so we can read
read it offline. On UNIX systems, `/usr/local/share/doc/rust` is the location. it offline. On UNIX systems, `/usr/local/share/doc/rust` is the location. On
On Windows, it's in a `share/doc` directory, inside wherever you installed Rust Windows, it's in a `share/doc` directory, inside the directory to which Rust was
to. installed.
If not, there are a number of places where you can get help. The easiest is 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 you can access through [the #rust IRC channel on irc.mozilla.org][irc], which we can access through
[Mibbit][mibbit]. Click that link, and you'll be chatting with other Rustaceans [Mibbit][mibbit]. Click that link, and we'll be chatting with other Rustaceans
(a silly nickname we call ourselves), and we can help you out. Other great (a silly nickname we call ourselves) who can help us out. Other great resources
resources include [the users forum][users], and include [the users forum][users], and [Stack Overflow][stackoverflow].
[Stack Overflow][stackoverflow].
[irc]: irc://irc.mozilla.org/#rust [irc]: irc://irc.mozilla.org/#rust
[mibbit]: http://chat.mibbit.com/?server=irc.mozilla.org&channel=%23rust [mibbit]: http://chat.mibbit.com/?server=irc.mozilla.org&channel=%23rust

View File

@ -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 `for` loops aren't the only thing that uses iterators, however. Writing your
own iterator involves implementing the `Iterator` trait. While doing that is 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 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 to accomplish various tasks. But first, a few notes about limitations of ranges.
Rust anti-pattern. And that's using ranges like this.
Yes, we just talked about how ranges are cool. But ranges are also very Ranges are very primitive, and we often can use better alternatives. Consider the
primitive. For example, if you needed to iterate over the contents of a vector, following Rust anti-pattern: using ranges to emulate a C-style `for` loop. Lets
you may be tempted to write this: suppose you needed to iterate over the contents of a vector. You may be tempted
to write this:
```rust ```rust
let nums = vec![1, 2, 3]; 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. talk about what you do want instead.
There are three broad classes of things that are relevant here: iterators, 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. * *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. different output sequence.
* *consumers* operate on an iterator, producing some final set of values. * *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); .find(|x| *x > 42);
match greater_than_forty_two { match greater_than_forty_two {
Some(_) => println!("We got some numbers!"), Some(_) => println!("Found a match!"),
None => println!("No numbers found :("), None => println!("No match found :("),
} }
``` ```
`find` takes a closure, and works on a reference to each element of an `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 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 looking for, and `false` otherwise. `find` returns the first element satisfying
element, `find` returns an `Option` rather than the element itself. 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: 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 These two basic iterators should serve you well. There are some more
advanced iterators, including ones that are infinite. 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! 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`: a new iterator. The simplest one is called `map`:
```rust,ignore ```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, If you are trying to execute a closure on an iterator for its side effects,
just use `for` instead. just use `for` instead.
There are tons of interesting iterator adapters. `take(n)` will return an There are tons of interesting iterator adaptors. `take(n)` will return an
iterator over the next `n` elements of the original iterator. Note that this iterator over the next `n` elements of the original iterator. Let's try it out
has no side effect on the original iterator. Let's try it out with our infinite with an infinite iterator:
iterator from before:
```rust ```rust
for i in (1..).take(5) { 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 `filter()` is an adapter that takes a closure as an argument. This closure
returns `true` or `false`. The new iterator `filter()` produces 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 ```rust
for i in (1..100).filter(|&x| x % 2 == 0) { 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 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 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 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 all kinds of lists. They're a little unusual at first, but if you play with

View File

@ -1,6 +1,6 @@
% Lifetimes % Lifetimes
This guide is one of three presenting Rusts ownership system. This is one of This guide is three of three presenting Rusts ownership system. This is one of
Rusts most unique and compelling features, with which Rust developers should Rusts most unique and compelling features, with which Rust developers should
become quite acquainted. Ownership is how Rust achieves its largest goal, become quite acquainted. Ownership is how Rust achieves its largest goal,
memory safety. There are a few distinct concepts, each with its own chapter: memory safety. There are a few distinct concepts, each with its own chapter:
@ -43,11 +43,11 @@ With that in mind, lets learn about lifetimes.
Lending out a reference to a resource that someone else owns can be Lending out a reference to a resource that someone else owns can be
complicated. For example, imagine this set of operations: complicated. For example, imagine this set of operations:
- I acquire a handle to some kind of resource. 1. I acquire a handle to some kind of resource.
- I lend you a reference to the resource. 2. I lend you a reference to the resource.
- I decide Im done with the resource, and deallocate it, while you still have 3. I decide Im done with the resource, and deallocate it, while you still have
your reference. 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 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. 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 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, lets break the explicit example down: Before we get to that, though, lets break the explicit example down:
[lifetime-elision]: #lifetime-elision
```rust,ignore ```rust,ignore
fn bar<'a>(...) 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(&mut self) -> &mut T; // elided
fn get_mut<'a>(&'a mut self) -> &'a mut T; // expanded fn get_mut<'a>(&'a mut self) -> &'a mut T; // expanded
fn args<T:ToCStr>(&mut self, args: &[T]) -> &mut Command // elided 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<'a, 'b, T:ToCStr>(&'a mut self, args: &'b [T]) -> &'a mut Command; // expanded
fn new(buf: &mut [u8]) -> BufWriter; // elided 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
``` ```

View File

@ -55,7 +55,7 @@ kinds of things `foo` could be: `self` if its just a value on the stack,
`&self` if its a reference, and `&mut self` if its a mutable reference. `&self` if its a reference, and `&mut self` if its a mutable reference.
Because we took the `&self` parameter to `area`, we can use it just like any Because we took the `&self` parameter to `area`, we can use it just like any
other parameter. Because we know its a `Circle`, we can access the `radius` other parameter. Because we know its a `Circle`, we can access the `radius`
just like we would with any other `struct`. just like we would with any other `struct`.
We should default to using `&self`, as you should prefer borrowing over taking We should default to using `&self`, as you should prefer borrowing over taking
ownership, as well as taking immutable references over mutable ones. Heres an ownership, as well as taking immutable references over mutable ones. Heres an

View File

@ -84,7 +84,7 @@ philosophy, memory safety, and the mechanism by which Rust guarantees it, the
> You may have one or the other of these two kinds of borrows, but not both at > You may have one or the other of these two kinds of borrows, but not both at
> the same time: > the same time:
> >
> * one or more references (`&T`) to a resource, > * one or more references (`&T`) to a resource,
> * exactly one mutable reference (`&mut T`). > * exactly one mutable reference (`&mut T`).

View File

@ -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]` this is undesirable, and can be avoided with the `#![no_std]`
attribute attached to the crate. 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 Obviously there's more to life than just libraries: one can use
`#[no_std]` with an executable, controlling the entry point is `#[no_std]` with an executable, controlling the entry point is
possible in two ways: the `#[start]` attribute, or overriding the 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: in the same format as C:
```rust ```rust
#![feature(lang_items, start, no_std, libc)] # #![feature(libc)]
#![feature(lang_items)]
#![feature(start)]
#![feature(no_std)]
#![no_std] #![no_std]
// Pull in the system libc library for what crt0.o likely requires // 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 correct ABI and the correct name, which requires overriding the
compiler's name mangling too: compiler's name mangling too:
```ignore ```rust
# #![feature(libc)]
#![feature(no_std)] #![feature(no_std)]
#![feature(lang_items)]
#![feature(start)]
#![no_std] #![no_std]
#![no_main] #![no_main]
#![feature(lang_items, start)]
extern crate libc; extern crate libc;
@ -92,19 +89,24 @@ instead.
The core library has very few dependencies and is much more portable than the 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 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 were using it.
As an example, here is a program that will calculate the dot product of two As an example, here is a program that will calculate the dot product of two
vectors provided from C, using idiomatic Rust practices. vectors provided from C, using idiomatic Rust practices.
```ignore ```rust
#![feature(lang_items, start, no_std, core, libc)] # #![feature(libc)]
#![feature(lang_items)]
#![feature(start)]
#![feature(no_std)]
#![feature(core)]
#![feature(core_slice_ext)]
#![feature(raw)]
#![no_std] #![no_std]
# extern crate libc; extern crate libc;
extern crate core;
use core::prelude::*;
use core::mem; use core::mem;

View File

@ -42,7 +42,7 @@ With that in mind, lets learn about ownership.
# Ownership # Ownership
[Variable bindings][bindings] have a property in Rust: they have ownership [Variable bindings][bindings] have a property in Rust: they have ownership
of what theyre bound to. This means that when a binding goes out of scope, of what theyre bound to. This means that when a binding goes out of scope,
Rust will free the bound resources. For example: Rust will free the bound resources. For example:
```rust ```rust
@ -158,8 +158,8 @@ has no pointers to data somewhere else, copying it is a full copy.
All primitive types implement the `Copy` trait and their ownership is All primitive types implement the `Copy` trait and their ownership is
therefore not moved like one would assume, following the ´ownership rules´. therefore not moved like one would assume, following the ´ownership rules´.
To give an example, the two following snippets of code only compile because the To give an example, the two following snippets of code only compile because the
`i32` and `bool` types implement the `Copy` trait. `i32` and `bool` types implement the `Copy` trait.
```rust ```rust
fn main() { fn main() {
@ -236,13 +236,3 @@ complicated.
Luckily, Rust offers a feature, borrowing, which helps us solve this problem. Luckily, Rust offers a feature, borrowing, which helps us solve this problem.
Its the topic of the next section! Its the topic of the next section!

View File

@ -23,6 +23,31 @@ match x {
This prints `one`. This prints `one`.
Theres 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` thats in scope for the match arm. Because we already have a binding named
`x`, this new `x` shadows it.
# Multiple patterns # Multiple patterns
You can match multiple patterns with `|`: 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 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 ```text
(4 | 5) if y => ... (4 | 5) if y => ...

View File

@ -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 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 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 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 variable binding. Slices have a defined length, can be mutable or immutable.
like arrays:
## 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 ```rust
let a = [0, 1, 2, 3, 4]; 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 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]`. Well talk about that `T` when we cover Slices have type `&[T]`. Well talk about that `T` when we cover

View File

@ -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 and so any conversion from raw pointers is asserting that they hold. The
programmer *must* guarantee this. programmer *must* guarantee this.
The recommended method for the conversion is The recommended method for the conversion is:
```rust ```rust
let i: u32 = 1;
// explicit cast // explicit cast
let i: u32 = 1;
let p_imm: *const u32 = &i as *const u32; let p_imm: *const u32 = &i as *const u32;
let mut m: u32 = 2;
// implicit coercion // implicit coercion
let mut m: u32 = 2;
let p_mut: *mut u32 = &mut m; let p_mut: *mut u32 = &mut m;
unsafe { unsafe {

View File

@ -1,6 +1,6 @@
% References and Borrowing % References and Borrowing
This guide is one of three presenting Rusts ownership system. This is one of This guide is two of three presenting Rusts ownership system. This is one of
Rusts most unique and compelling features, with which Rust developers should Rusts most unique and compelling features, with which Rust developers should
become quite acquainted. Ownership is how Rust achieves its largest goal, become quite acquainted. Ownership is how Rust achieves its largest goal,
memory safety. There are a few distinct concepts, each with its own memory safety. There are a few distinct concepts, each with its own
@ -233,7 +233,7 @@ So when we add the curly braces:
```rust ```rust
let mut x = 5; let mut x = 5;
{ {
let y = &mut x; // -+ &mut borrow starts here let y = &mut x; // -+ &mut borrow starts here
*y += 1; // | *y += 1; // |
} // -+ ... and ends here } // -+ ... and ends here
@ -306,7 +306,7 @@ which was invalid. For example:
```rust,ignore ```rust,ignore
let y: &i32; let y: &i32;
{ {
let x = 5; let x = 5;
y = &x; y = &x;
} }
@ -323,7 +323,7 @@ error: `x` does not live long enough
note: reference must be valid for the block suffix following statement 0 at note: reference must be valid for the block suffix following statement 0 at
2:16... 2:16...
let y: &i32; let y: &i32;
{ {
let x = 5; let x = 5;
y = &x; y = &x;
} }
@ -363,7 +363,7 @@ note: reference must be valid for the block suffix following statement 0 at
let y: &i32; let y: &i32;
let x = 5; let x = 5;
y = &x; y = &x;
println!("{}", y); println!("{}", y);
} }
@ -371,7 +371,7 @@ note: ...but borrowed value is only valid for the block suffix following
statement 1 at 3:14 statement 1 at 3:14
let x = 5; let x = 5;
y = &x; y = &x;
println!("{}", y); println!("{}", y);
} }
``` ```

View File

@ -108,7 +108,7 @@ fn process() {
let handles: Vec<_> = (0..10).map(|_| { let handles: Vec<_> = (0..10).map(|_| {
thread::spawn(|| { thread::spawn(|| {
let mut x = 0; let mut x = 0;
for _ in (0..5_000_000) { for _ in 0..5_000_000 {
x += 1 x += 1
} }
x x
@ -119,7 +119,6 @@ fn process() {
println!("Thread finished with count={}", println!("Thread finished with count={}",
h.join().map_err(|_| "Could not join a thread!").unwrap()); h.join().map_err(|_| "Could not join a thread!").unwrap());
} }
println!("done!");
} }
``` ```

View File

@ -102,8 +102,8 @@ println!("");
This prints: This prints:
```text ```text
229, 191, 160, 231, 138, 172, 227, 131, 143, 227, 131, 129, 229, 133, 172, 229, 191, 160, 231, 138, 172, 227, 131, 143, 227, 131, 129, 229, 133, 172,
忠, 犬, ハ, チ, 公, 忠, 犬, ハ, チ, 公,
``` ```
As you can see, there are more bytes than `char`s. As you can see, there are more bytes than `char`s.

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