mirror of
https://git.proxmox.com/git/rustc
synced 2025-05-29 18:14:56 +00:00
Imported Upstream version 1.5.0+dfsg1
This commit is contained in:
parent
e9174d1eb2
commit
b039eaaf8a
180
AUTHORS.txt
180
AUTHORS.txt
@ -9,7 +9,9 @@ Aaron Todd <github@opprobrio.us>
|
|||||||
Aaron Turon <aturon@mozilla.com>
|
Aaron 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 O’Kane <rory@roryokane.com>
|
Rory O’Kane <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>
|
||||||
|
@ -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/
|
||||||
|
@ -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.
|
||||||
#
|
#
|
||||||
|
14
README.md
14
README.md
@ -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 don’t re-build the compiler because you made a change
|
To make sure you don’t re-build the compiler because you made a change
|
||||||
|
276
RELEASES.md
276
RELEASES.md
@ -1,5 +1,223 @@
|
|||||||
Version 1.4.0 (October 2015)
|
Version 1.5.0 (2015-12-10)
|
||||||
============================
|
==========================
|
||||||
|
|
||||||
|
* ~700 changes, numerous bugfixes
|
||||||
|
|
||||||
|
Highlights
|
||||||
|
----------
|
||||||
|
|
||||||
|
* Stabilized APIs:
|
||||||
|
[`BinaryHeap::from`], [`BinaryHeap::into_sorted_vec`],
|
||||||
|
[`BinaryHeap::into_vec`], [`Condvar::wait_timeout`],
|
||||||
|
[`FileTypeExt::is_block_device`], [`FileTypeExt::is_char_device`],
|
||||||
|
[`FileTypeExt::is_fifo`], [`FileTypeExt::is_socket`],
|
||||||
|
[`FileTypeExt`], [`Formatter::alternate`], [`Formatter::fill`],
|
||||||
|
[`Formatter::precision`], [`Formatter::sign_aware_zero_pad`],
|
||||||
|
[`Formatter::sign_minus`], [`Formatter::sign_plus`],
|
||||||
|
[`Formatter::width`], [`Iterator::cmp`], [`Iterator::eq`],
|
||||||
|
[`Iterator::ge`], [`Iterator::gt`], [`Iterator::le`],
|
||||||
|
[`Iterator::lt`], [`Iterator::ne`], [`Iterator::partial_cmp`],
|
||||||
|
[`Path::canonicalize`], [`Path::exists`], [`Path::is_dir`],
|
||||||
|
[`Path::is_file`], [`Path::metadata`], [`Path::read_dir`],
|
||||||
|
[`Path::read_link`], [`Path::symlink_metadata`],
|
||||||
|
[`Utf8Error::valid_up_to`], [`Vec::resize`],
|
||||||
|
[`VecDeque::as_mut_slices`], [`VecDeque::as_slices`],
|
||||||
|
[`VecDeque::insert`], [`VecDeque::shrink_to_fit`],
|
||||||
|
[`VecDeque::swap_remove_back`], [`VecDeque::swap_remove_front`],
|
||||||
|
[`slice::split_first_mut`], [`slice::split_first`],
|
||||||
|
[`slice::split_last_mut`], [`slice::split_last`],
|
||||||
|
[`char::from_u32_unchecked`], [`fs::canonicalize`],
|
||||||
|
[`str::MatchIndices`], [`str::RMatchIndices`],
|
||||||
|
[`str::match_indices`], [`str::rmatch_indices`],
|
||||||
|
[`str::slice_mut_unchecked`], [`string::ParseError`].
|
||||||
|
* Rust applications hosted on crates.io can be installed locally to
|
||||||
|
`~/.cargo/bin` with the [`cargo install`] command. Among other
|
||||||
|
things this makes it easier to augment Cargo with new subcommands:
|
||||||
|
when a binary named e.g. `cargo-foo` is found in `$PATH` it can be
|
||||||
|
invoked as `cargo foo`.
|
||||||
|
* Crates with wildcard (`*`) dependencies will [emit warnings when
|
||||||
|
published][1.5w]. In 1.6 it will no longer be possible to publish
|
||||||
|
crates with wildcard dependencies.
|
||||||
|
|
||||||
|
Breaking Changes
|
||||||
|
----------------
|
||||||
|
|
||||||
|
* The rules determining when a particular lifetime must outlive
|
||||||
|
a particular value (known as '[dropck]') have been [modified
|
||||||
|
to not rely on parametricity][1.5p].
|
||||||
|
* [Implementations of `AsRef` and `AsMut` were added to `Box`, `Rc`,
|
||||||
|
and `Arc`][1.5a]. Because these smart pointer types implement
|
||||||
|
`Deref`, this causes breakage in cases where the interior type
|
||||||
|
contains methods of the same name.
|
||||||
|
* [Correct a bug in Rc/Arc][1.5c] that caused [dropck] to be unaware
|
||||||
|
that they could drop their content. Soundness fix.
|
||||||
|
* All method invocations are [properly checked][1.5wf1] for
|
||||||
|
[well-formedness][1.5wf2]. Soundness fix.
|
||||||
|
* Traits whose supertraits contain `Self` are [not object
|
||||||
|
safe][1.5o]. Soundness fix.
|
||||||
|
* Target specifications support a [`no_default_libraries`][1.5nd]
|
||||||
|
setting that controls whether `-nodefaultlibs` is passed to the
|
||||||
|
linker, and in turn the `is_like_windows` setting no longer affects
|
||||||
|
the `-nodefaultlibs` flag.
|
||||||
|
* `#[derive(Show)]`, long-deprecated, [has been removed][1.5ds].
|
||||||
|
* The `#[inline]` and `#[repr]` attributes [can only appear
|
||||||
|
in valid locations][1.5at].
|
||||||
|
* Native libraries linked from the local crate are [passed to
|
||||||
|
the linker before native libraries from upstream crates][1.5nl].
|
||||||
|
* Two rarely-used attributes, `#[no_debug]` and
|
||||||
|
`#[omit_gdb_pretty_printer_section]` [are feature gated][1.5fg].
|
||||||
|
* Negation of unsigned integers, which has been a warning for
|
||||||
|
several releases, [is now behind a feature gate and will
|
||||||
|
generate errors][1.5nu].
|
||||||
|
* The parser accidentally accepted visibility modifiers on
|
||||||
|
enum variants, a bug [which has been fixed][1.5ev].
|
||||||
|
* [A bug was fixed that allowed `use` statements to import unstable
|
||||||
|
features][1.5use].
|
||||||
|
|
||||||
|
Language
|
||||||
|
--------
|
||||||
|
|
||||||
|
* When evaluating expressions at compile-time that are not
|
||||||
|
compile-time constants (const-evaluating expressions in non-const
|
||||||
|
contexts), incorrect code such as overlong bitshifts and arithmetic
|
||||||
|
overflow will [generate a warning instead of an error][1.5ce],
|
||||||
|
delaying the error until runtime. This will allow the
|
||||||
|
const-evaluator to be expanded in the future backwards-compatibly.
|
||||||
|
* The `improper_ctypes` lint [no longer warns about using `isize` and
|
||||||
|
`usize` in FFI][1.5ict].
|
||||||
|
|
||||||
|
Libraries
|
||||||
|
---------
|
||||||
|
|
||||||
|
* `Arc<T>` and `Rc<T>` are [covariant with respect to `T` instead of
|
||||||
|
invariant][1.5c].
|
||||||
|
* `Default` is [implemented for mutable slices][1.5d].
|
||||||
|
* `FromStr` is [implemented for `SockAddrV4` and `SockAddrV6`][1.5s].
|
||||||
|
* There are now `From` conversions [between floating point
|
||||||
|
types][1.5f] where the conversions are lossless.
|
||||||
|
* Thera are now `From` conversions [between integer types][1.5i] where
|
||||||
|
the conversions are lossless.
|
||||||
|
* [`fs::Metadata` implements `Clone`][1.5fs].
|
||||||
|
* The `parse` method [accepts a leading "+" when parsing
|
||||||
|
integers][1.5pi].
|
||||||
|
* [`AsMut` is implemented for `Vec`][1.5am].
|
||||||
|
* The `clone_from` implementations for `String` and `BinaryHeap` [have
|
||||||
|
been optimized][1.5cf] and no longer rely on the default impl.
|
||||||
|
* The `extern "Rust"`, `extern "C"`, `unsafe extern "Rust"` and
|
||||||
|
`unsafe extern "C"` function types now [implement `Clone`,
|
||||||
|
`PartialEq`, `Eq`, `PartialOrd`, `Ord`, `Hash`, `fmt::Pointer`, and
|
||||||
|
`fmt::Debug` for up to 12 arguments][1.5fp].
|
||||||
|
* [Dropping `Vec`s is much faster in unoptimized builds when the
|
||||||
|
element types don't implement `Drop`][1.5dv].
|
||||||
|
* A bug that caused in incorrect behavior when [combining `VecDeque`
|
||||||
|
with zero-sized types][1.5vdz] was resolved.
|
||||||
|
* [`PartialOrd` for slices is faster][1.5po].
|
||||||
|
|
||||||
|
Miscellaneous
|
||||||
|
-------------
|
||||||
|
|
||||||
|
* [Crate metadata size was reduced by 20%][1.5md].
|
||||||
|
* [Improvements to code generation reduced the size of libcore by 3.3
|
||||||
|
MB and rustc's memory usage by 18MB][1.5m].
|
||||||
|
* [Improvements to deref translation increased performance in
|
||||||
|
unoptimized builds][1.5dr].
|
||||||
|
* Various errors in trait resolution [are deduplicated to only be
|
||||||
|
reported once][1.5te].
|
||||||
|
* Rust has preliminary [support for rumprun kernels][1.5rr].
|
||||||
|
* Rust has preliminary [support for NetBSD on amd64][1.5na].
|
||||||
|
|
||||||
|
[1.5use]: https://github.com/rust-lang/rust/pull/28364
|
||||||
|
[1.5po]: https://github.com/rust-lang/rust/pull/28436
|
||||||
|
[1.5ev]: https://github.com/rust-lang/rust/pull/28442
|
||||||
|
[1.5nu]: https://github.com/rust-lang/rust/pull/28468
|
||||||
|
[1.5dr]: https://github.com/rust-lang/rust/pull/28491
|
||||||
|
[1.5vdz]: https://github.com/rust-lang/rust/pull/28494
|
||||||
|
[1.5md]: https://github.com/rust-lang/rust/pull/28521
|
||||||
|
[1.5fg]: https://github.com/rust-lang/rust/pull/28522
|
||||||
|
[1.5dv]: https://github.com/rust-lang/rust/pull/28531
|
||||||
|
[1.5na]: https://github.com/rust-lang/rust/pull/28543
|
||||||
|
[1.5fp]: https://github.com/rust-lang/rust/pull/28560
|
||||||
|
[1.5rr]: https://github.com/rust-lang/rust/pull/28593
|
||||||
|
[1.5cf]: https://github.com/rust-lang/rust/pull/28602
|
||||||
|
[1.5nl]: https://github.com/rust-lang/rust/pull/28605
|
||||||
|
[1.5te]: https://github.com/rust-lang/rust/pull/28645
|
||||||
|
[1.5at]: https://github.com/rust-lang/rust/pull/28650
|
||||||
|
[1.5am]: https://github.com/rust-lang/rust/pull/28663
|
||||||
|
[1.5m]: https://github.com/rust-lang/rust/pull/28778
|
||||||
|
[1.5ict]: https://github.com/rust-lang/rust/pull/28779
|
||||||
|
[1.5a]: https://github.com/rust-lang/rust/pull/28811
|
||||||
|
[1.5pi]: https://github.com/rust-lang/rust/pull/28826
|
||||||
|
[1.5ce]: https://github.com/rust-lang/rfcs/blob/master/text/1229-compile-time-asserts.md
|
||||||
|
[1.5p]: https://github.com/rust-lang/rfcs/blob/master/text/1238-nonparametric-dropck.md
|
||||||
|
[1.5i]: https://github.com/rust-lang/rust/pull/28921
|
||||||
|
[1.5fs]: https://github.com/rust-lang/rust/pull/29021
|
||||||
|
[1.5f]: https://github.com/rust-lang/rust/pull/29129
|
||||||
|
[1.5ds]: https://github.com/rust-lang/rust/pull/29148
|
||||||
|
[1.5s]: https://github.com/rust-lang/rust/pull/29190
|
||||||
|
[1.5d]: https://github.com/rust-lang/rust/pull/29245
|
||||||
|
[1.5o]: https://github.com/rust-lang/rust/pull/29259
|
||||||
|
[1.5nd]: https://github.com/rust-lang/rust/pull/28578
|
||||||
|
[1.5wf2]: https://github.com/rust-lang/rfcs/blob/master/text/1214-projections-lifetimes-and-wf.md
|
||||||
|
[1.5wf1]: https://github.com/rust-lang/rust/pull/28669
|
||||||
|
[dropck]: https://doc.rust-lang.org/nightly/nomicon/dropck.html
|
||||||
|
[1.5c]: https://github.com/rust-lang/rust/pull/29110
|
||||||
|
[1.5w]: https://github.com/rust-lang/rfcs/blob/master/text/1241-no-wildcard-deps.md
|
||||||
|
[`cargo install`]: https://github.com/rust-lang/rfcs/blob/master/text/1200-cargo-install.md
|
||||||
|
[`BinaryHeap::from`]: http://doc.rust-lang.org/nightly/std/convert/trait.From.html#method.from
|
||||||
|
[`BinaryHeap::into_sorted_vec`]: http://doc.rust-lang.org/nightly/std/collections/struct.BinaryHeap.html#method.into_sorted_vec
|
||||||
|
[`BinaryHeap::into_vec`]: http://doc.rust-lang.org/nightly/std/collections/struct.BinaryHeap.html#method.into_vec
|
||||||
|
[`Condvar::wait_timeout`]: http://doc.rust-lang.org/nightly/std/sync/struct.Condvar.html#method.wait_timeout
|
||||||
|
[`FileTypeExt::is_block_device`]: http://doc.rust-lang.org/nightly/std/os/unix/fs/trait.FileTypeExt.html#tymethod.is_block_device
|
||||||
|
[`FileTypeExt::is_char_device`]: http://doc.rust-lang.org/nightly/std/os/unix/fs/trait.FileTypeExt.html#tymethod.is_char_device
|
||||||
|
[`FileTypeExt::is_fifo`]: http://doc.rust-lang.org/nightly/std/os/unix/fs/trait.FileTypeExt.html#tymethod.is_fifo
|
||||||
|
[`FileTypeExt::is_socket`]: http://doc.rust-lang.org/nightly/std/os/unix/fs/trait.FileTypeExt.html#tymethod.is_socket
|
||||||
|
[`FileTypeExt`]: http://doc.rust-lang.org/nightly/std/os/unix/fs/trait.FileTypeExt.html
|
||||||
|
[`Formatter::alternate`]: http://doc.rust-lang.org/nightly/core/fmt/struct.Formatter.html#method.alternate
|
||||||
|
[`Formatter::fill`]: http://doc.rust-lang.org/nightly/core/fmt/struct.Formatter.html#method.fill
|
||||||
|
[`Formatter::precision`]: http://doc.rust-lang.org/nightly/core/fmt/struct.Formatter.html#method.precision
|
||||||
|
[`Formatter::sign_aware_zero_pad`]: http://doc.rust-lang.org/nightly/core/fmt/struct.Formatter.html#method.sign_aware_zero_pad
|
||||||
|
[`Formatter::sign_minus`]: http://doc.rust-lang.org/nightly/core/fmt/struct.Formatter.html#method.sign_minus
|
||||||
|
[`Formatter::sign_plus`]: http://doc.rust-lang.org/nightly/core/fmt/struct.Formatter.html#method.sign_plus
|
||||||
|
[`Formatter::width`]: http://doc.rust-lang.org/nightly/core/fmt/struct.Formatter.html#method.width
|
||||||
|
[`Iterator::cmp`]: http://doc.rust-lang.org/nightly/core/iter/trait.Iterator.html#method.cmp
|
||||||
|
[`Iterator::eq`]: http://doc.rust-lang.org/nightly/core/iter/trait.Iterator.html#method.eq
|
||||||
|
[`Iterator::ge`]: http://doc.rust-lang.org/nightly/core/iter/trait.Iterator.html#method.ge
|
||||||
|
[`Iterator::gt`]: http://doc.rust-lang.org/nightly/core/iter/trait.Iterator.html#method.gt
|
||||||
|
[`Iterator::le`]: http://doc.rust-lang.org/nightly/core/iter/trait.Iterator.html#method.le
|
||||||
|
[`Iterator::lt`]: http://doc.rust-lang.org/nightly/core/iter/trait.Iterator.html#method.lt
|
||||||
|
[`Iterator::ne`]: http://doc.rust-lang.org/nightly/core/iter/trait.Iterator.html#method.ne
|
||||||
|
[`Iterator::partial_cmp`]: http://doc.rust-lang.org/nightly/core/iter/trait.Iterator.html#method.partial_cmp
|
||||||
|
[`Path::canonicalize`]: http://doc.rust-lang.org/nightly/std/path/struct.Path.html#method.canonicalize
|
||||||
|
[`Path::exists`]: http://doc.rust-lang.org/nightly/std/path/struct.Path.html#method.exists
|
||||||
|
[`Path::is_dir`]: http://doc.rust-lang.org/nightly/std/path/struct.Path.html#method.is_dir
|
||||||
|
[`Path::is_file`]: http://doc.rust-lang.org/nightly/std/path/struct.Path.html#method.is_file
|
||||||
|
[`Path::metadata`]: http://doc.rust-lang.org/nightly/std/path/struct.Path.html#method.metadata
|
||||||
|
[`Path::read_dir`]: http://doc.rust-lang.org/nightly/std/path/struct.Path.html#method.read_dir
|
||||||
|
[`Path::read_link`]: http://doc.rust-lang.org/nightly/std/path/struct.Path.html#method.read_link
|
||||||
|
[`Path::symlink_metadata`]: http://doc.rust-lang.org/nightly/std/path/struct.Path.html#method.symlink_metadata
|
||||||
|
[`Utf8Error::valid_up_to`]: http://doc.rust-lang.org/nightly/core/str/struct.Utf8Error.html#method.valid_up_to
|
||||||
|
[`Vec::resize`]: http://doc.rust-lang.org/nightly/std/vec/struct.Vec.html#method.resize
|
||||||
|
[`VecDeque::as_mut_slices`]: http://doc.rust-lang.org/nightly/std/collections/struct.VecDeque.html#method.as_mut_slices
|
||||||
|
[`VecDeque::as_slices`]: http://doc.rust-lang.org/nightly/std/collections/struct.VecDeque.html#method.as_slices
|
||||||
|
[`VecDeque::insert`]: http://doc.rust-lang.org/nightly/std/collections/struct.VecDeque.html#method.insert
|
||||||
|
[`VecDeque::shrink_to_fit`]: http://doc.rust-lang.org/nightly/std/collections/struct.VecDeque.html#method.shrink_to_fit
|
||||||
|
[`VecDeque::swap_remove_back`]: http://doc.rust-lang.org/nightly/std/collections/struct.VecDeque.html#method.swap_remove_back
|
||||||
|
[`VecDeque::swap_remove_front`]: http://doc.rust-lang.org/nightly/std/collections/struct.VecDeque.html#method.swap_remove_front
|
||||||
|
[`slice::split_first_mut`]: http://doc.rust-lang.org/nightly/std/primitive.slice.html#method.split_first_mut
|
||||||
|
[`slice::split_first`]: http://doc.rust-lang.org/nightly/std/primitive.slice.html#method.split_first
|
||||||
|
[`slice::split_last_mut`]: http://doc.rust-lang.org/nightly/std/primitive.slice.html#method.split_last_mut
|
||||||
|
[`slice::split_last`]: http://doc.rust-lang.org/nightly/std/primitive.slice.html#method.split_last
|
||||||
|
[`char::from_u32_unchecked`]: http://doc.rust-lang.org/nightly/std/char/fn.from_u32_unchecked.html
|
||||||
|
[`fs::canonicalize`]: http://doc.rust-lang.org/nightly/std/fs/fn.canonicalize.html
|
||||||
|
[`str::MatchIndices`]: http://doc.rust-lang.org/nightly/std/str/struct.MatchIndices.html
|
||||||
|
[`str::RMatchIndices`]: http://doc.rust-lang.org/nightly/std/str/struct.RMatchIndices.html
|
||||||
|
[`str::match_indices`]: http://doc.rust-lang.org/nightly/std/primitive.str.html#method.match_indices
|
||||||
|
[`str::rmatch_indices`]: http://doc.rust-lang.org/nightly/std/primitive.str.html#method.rmatch_indices
|
||||||
|
[`str::slice_mut_unchecked`]: http://doc.rust-lang.org/nightly/std/primitive.str.html#method.slice_mut_unchecked
|
||||||
|
[`string::ParseError`]: http://doc.rust-lang.org/nightly/std/string/enum.ParseError.html
|
||||||
|
|
||||||
|
Version 1.4.0 (2015-10-29)
|
||||||
|
==========================
|
||||||
|
|
||||||
* ~1200 changes, numerous bugfixes
|
* ~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
41
configure
vendored
@ -578,6 +578,7 @@ opt ccache 0 "invoke gcc/clang via ccache to reuse object files between builds"
|
|||||||
opt local-rust 0 "use an installed rustc rather than downloading a snapshot"
|
opt 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
|
||||||
|
@ -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.
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
24
mk/cfg/x86_64-rumprun-netbsd.mk
Normal file
24
mk/cfg/x86_64-rumprun-netbsd.mk
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
# x86_64-rumprun-netbsd configuration
|
||||||
|
CROSS_PREFIX_x86_64-rumprun-netbsd=x86_64-rumprun-netbsd-
|
||||||
|
CC_x86_64-rumprun-netbsd=gcc
|
||||||
|
CXX_x86_64-rumprun-netbsd=g++
|
||||||
|
CPP_x86_64-rumprun-netbsd=gcc -E
|
||||||
|
AR_x86_64-rumprun-netbsd=ar
|
||||||
|
CFG_INSTALL_ONLY_RLIB_x86_64-rumprun-netbsd = 1
|
||||||
|
CFG_LIB_NAME_x86_64-rumprun-netbsd=lib$(1).so
|
||||||
|
CFG_STATIC_LIB_NAME_x86_64-rumprun-netbsd=lib$(1).a
|
||||||
|
CFG_LIB_GLOB_x86_64-rumprun-netbsd=lib$(1)-*.so
|
||||||
|
CFG_JEMALLOC_CFLAGS_x86_64-rumprun-netbsd := -m64
|
||||||
|
CFG_GCCISH_CFLAGS_x86_64-rumprun-netbsd := -Wall -Werror -g -fPIC -m64
|
||||||
|
CFG_GCCISH_CXXFLAGS_x86_64-rumprun-netbsd :=
|
||||||
|
CFG_GCCISH_LINK_FLAGS_x86_64-rumprun-netbsd :=
|
||||||
|
CFG_GCCISH_DEF_FLAG_x86_64-rumprun-netbsd :=
|
||||||
|
CFG_LLC_FLAGS_x86_64-rumprun-netbsd :=
|
||||||
|
CFG_INSTALL_NAME_x86_64-rumprun-netbsd =
|
||||||
|
CFG_EXE_SUFFIX_x86_64-rumprun-netbsd =
|
||||||
|
CFG_WINDOWSY_x86_64-rumprun-netbsd :=
|
||||||
|
CFG_UNIXY_x86_64-rumprun-netbsd := 1
|
||||||
|
CFG_LDPATH_x86_64-rumprun-netbsd :=
|
||||||
|
CFG_RUN_x86_64-rumprun-netbsd=$(2)
|
||||||
|
CFG_RUN_TARG_x86_64-rumprun-netbsd=$(call CFG_RUN_x86_64-rumprun-netbsd,,$(2))
|
||||||
|
CFG_GNU_TRIPLE_x86_64-rumprun-netbsd := x86_64-rumprun-netbsd
|
@ -1,4 +1,5 @@
|
|||||||
# x86_64-unknown-netbsd configuration
|
# 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)
|
||||||
|
68
mk/crates.mk
68
mk/crates.mk
@ -61,51 +61,55 @@ HOST_CRATES := syntax $(RUSTC_CRATES) rustdoc fmt_macros
|
|||||||
TOOLS := compiletest rustdoc rustc rustbook error-index-generator
|
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
|
||||||
|
117
mk/dist.mk
117
mk/dist.mk
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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), \
|
||||||
|
25
mk/main.mk
25
mk/main.mk
@ -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
|
||||||
|
@ -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"
|
||||||
|
@ -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)))
|
||||||
|
@ -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
|
||||||
|
@ -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);
|
||||||
|
@ -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;
|
||||||
|
@ -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,
|
||||||
|
@ -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:
|
||||||
|
|
||||||
|
@ -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?
|
||||||
|
|
||||||
|
@ -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?
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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)
|
||||||
|
@ -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
|
||||||
|
@ -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.
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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.
|
||||||
|
|
||||||
|
@ -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.
|
||||||
|
@ -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.
|
||||||
|
@ -78,4 +78,4 @@ TODO: other common problems? SEME regions stuff, mostly?
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
[ex2]: lifetimes.html#example-2:-aliasing-a-mutable-reference
|
[ex2]: lifetimes.html#example-aliasing-a-mutable-reference
|
||||||
|
@ -195,7 +195,7 @@ println!("{}", x);
|
|||||||
|
|
||||||
The problem here is is bit more subtle and interesting. We want Rust to
|
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.
|
||||||
|
|
||||||
|
@ -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.
|
||||||
|
@ -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.
|
||||||
|
@ -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.
|
||||||
|
|
||||||
|
|
||||||
|
@ -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)]);
|
||||||
```
|
```
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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.
|
||||||
|
@ -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.
|
||||||
|
|
||||||
|
@ -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!
|
||||||
|
@ -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.
|
||||||
|
@ -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*
|
||||||
|
@ -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.
|
||||||
|
|
||||||
|
@ -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.
|
||||||
|
|
||||||
|
@ -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.
|
||||||
|
@ -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 —
|
well as a compiler, the only existing implementation is a compiler,
|
||||||
from now on referred to as *the* Rust compiler — 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 LLVM’s scoped [noalias] model, except if the `&T`
|
|
||||||
contains an `UnsafeCell<U>`. Unsafe code must not violate these aliasing
|
|
||||||
guarantees.
|
|
||||||
* Mutating non-mutable data (that is, data reached through a shared reference or
|
|
||||||
data owned by a `let` binding), unless that data is contained within an `UnsafeCell<U>`.
|
|
||||||
* Invoking undefined behavior via compiler intrinsics:
|
|
||||||
* Indexing outside of the bounds of an object with `std::ptr::offset`
|
|
||||||
(`offset` intrinsic), with
|
|
||||||
the exception of one byte past the end which is permitted.
|
|
||||||
* Using `std::ptr::copy_nonoverlapping_memory` (`memcpy32`/`memcpy64`
|
|
||||||
intrinsics) on overlapping buffers
|
|
||||||
* Invalid values in primitive types, even in private fields/locals:
|
|
||||||
* Dangling/null references or boxes
|
|
||||||
* A value other than `false` (0) or `true` (1) in a `bool`
|
|
||||||
* A discriminant in an `enum` not included in the type definition
|
|
||||||
* A value in a `char` which is a surrogate or above `char::MAX`
|
|
||||||
* Non-UTF-8 byte sequences in a `str`
|
|
||||||
* Unwinding into Rust from foreign code or unwinding from Rust into foreign
|
|
||||||
code. Rust's failure system is not compatible with exception handling in
|
|
||||||
other languages. Unwinding must be caught and handled at FFI boundaries.
|
|
||||||
|
|
||||||
[noalias]: http://llvm.org/docs/LangRef.html#noalias
|
|
||||||
|
|
||||||
##### Behavior not considered unsafe
|
|
||||||
|
|
||||||
This is a list of behavior not considered *unsafe* in Rust terms, but that may
|
|
||||||
be undesired.
|
|
||||||
|
|
||||||
* Deadlocks
|
|
||||||
* Leaks of memory and other resources
|
|
||||||
* Exiting without calling destructors
|
|
||||||
* Integer overflow
|
|
||||||
- Overflow is considered "unexpected" behavior and is always user-error,
|
|
||||||
unless the `wrapping` primitives are used. In non-optimized builds, the compiler
|
|
||||||
will insert debug checks that panic on overflow, but in optimized builds overflow
|
|
||||||
instead results in wrapped values. See [RFC 560] for the rationale and more details.
|
|
||||||
|
|
||||||
[RFC 560]: https://github.com/rust-lang/rfcs/blob/master/text/0560-integer-overflow.md
|
|
||||||
|
|
||||||
#### Diverging functions
|
#### 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 — a
|
[item](#items) declaration within a module. Declaring an item — a
|
||||||
function, enumeration, structure, type, static, trait, implementation or module
|
function, enumeration, struct, type, static, trait, implementation or module
|
||||||
— locally within a statement block is simply a way of restricting its
|
— 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 — [enumerations](#enumerated-types) and
|
Nominal types — [enumerations](#enumerated-types) and
|
||||||
[structures](#structure-types) — may be recursive. That is, each `enum`
|
[structs](#struct-types) — may be recursive. That is, each `enum`
|
||||||
constructor or `struct` field may refer, directly or indirectly, to the
|
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 LLVM’s scoped [noalias] model, except if the `&T`
|
||||||
|
contains an `UnsafeCell<U>`. Unsafe code must not violate these aliasing
|
||||||
|
guarantees.
|
||||||
|
* Mutating non-mutable data (that is, data reached through a shared reference or
|
||||||
|
data owned by a `let` binding), unless that data is contained within an `UnsafeCell<U>`.
|
||||||
|
* Invoking undefined behavior via compiler intrinsics:
|
||||||
|
* Indexing outside of the bounds of an object with `std::ptr::offset`
|
||||||
|
(`offset` intrinsic), with
|
||||||
|
the exception of one byte past the end which is permitted.
|
||||||
|
* Using `std::ptr::copy_nonoverlapping_memory` (`memcpy32`/`memcpy64`
|
||||||
|
intrinsics) on overlapping buffers
|
||||||
|
* Invalid values in primitive types, even in private fields/locals:
|
||||||
|
* Dangling/null references or boxes
|
||||||
|
* A value other than `false` (0) or `true` (1) in a `bool`
|
||||||
|
* A discriminant in an `enum` not included in the type definition
|
||||||
|
* A value in a `char` which is a surrogate or above `char::MAX`
|
||||||
|
* Non-UTF-8 byte sequences in a `str`
|
||||||
|
* Unwinding into Rust from foreign code or unwinding from Rust into foreign
|
||||||
|
code. Rust's failure system is not compatible with exception handling in
|
||||||
|
other languages. Unwinding must be caught and handled at FFI boundaries.
|
||||||
|
|
||||||
|
[noalias]: http://llvm.org/docs/LangRef.html#noalias
|
||||||
|
|
||||||
|
## Behavior not considered unsafe
|
||||||
|
|
||||||
|
This is a list of behavior not considered *unsafe* in Rust terms, but that may
|
||||||
|
be undesired.
|
||||||
|
|
||||||
|
* Deadlocks
|
||||||
|
* Leaks of memory and other resources
|
||||||
|
* Exiting without calling destructors
|
||||||
|
* Integer overflow
|
||||||
|
- Overflow is considered "unexpected" behavior and is always user-error,
|
||||||
|
unless the `wrapping` primitives are used. In non-optimized builds, the compiler
|
||||||
|
will insert debug checks that panic on overflow, but in optimized builds overflow
|
||||||
|
instead results in wrapped values. See [RFC 560] for the rationale and more details.
|
||||||
|
|
||||||
|
[RFC 560]: https://github.com/rust-lang/rfcs/blob/master/text/0560-integer-overflow.md
|
||||||
|
|
||||||
# Appendix: Influences
|
# 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
|
||||||
|
@ -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 {
|
||||||
|
@ -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)
|
|
||||||
|
@ -1,5 +0,0 @@
|
|||||||
% API design for a changing Rust
|
|
||||||
|
|
||||||
A number of planned Rust features will drastically affect the API design
|
|
||||||
story. This section collects some of the biggest features with concrete examples
|
|
||||||
of how the API will change.
|
|
@ -1,12 +0,0 @@
|
|||||||
% Post-1.0 changes
|
|
||||||
|
|
||||||
### Higher-kinded types
|
|
||||||
|
|
||||||
* A trait encompassing both `Iterable<T>` for some fixed `T` and
|
|
||||||
`FromIterator<U>` for _all_ `U` (where HKT comes in). The train
|
|
||||||
could provide e.g. a default `map` method producing the same kind of
|
|
||||||
the container, but with a new type parameter.
|
|
||||||
|
|
||||||
* **Monadic-generic programming**? Can we add this without deprecating
|
|
||||||
huge swaths of the API (including `Option::map`, `option::collect`,
|
|
||||||
`result::collect`, `try!` etc.
|
|
@ -1,17 +0,0 @@
|
|||||||
% Pre-1.0 changes
|
|
||||||
|
|
||||||
### `std` facade
|
|
||||||
|
|
||||||
We should revisit some APIs in `libstd` now that the facade effort is complete.
|
|
||||||
|
|
||||||
For example, the treatment of environment variables in the new
|
|
||||||
`Command` API is waiting on access to hashtables before being
|
|
||||||
approved.
|
|
||||||
|
|
||||||
### Trait reform
|
|
||||||
|
|
||||||
Potential for standard conversion traits (`to`, `into`, `as`).
|
|
||||||
|
|
||||||
Probably many other opportunities here.
|
|
||||||
|
|
||||||
### Unboxed closures
|
|
@ -1,28 +0,0 @@
|
|||||||
% Changes with unclear timing
|
|
||||||
|
|
||||||
### Associated items
|
|
||||||
|
|
||||||
* Many traits that currently take type parameters should instead use associated
|
|
||||||
types; this will _drastically_ simplify signatures in some cases.
|
|
||||||
|
|
||||||
* Associated constants would be useful in a few places, e.g. traits for
|
|
||||||
numerics, traits for paths.
|
|
||||||
|
|
||||||
### Anonymous, unboxed return types (aka `impl Trait` types)
|
|
||||||
|
|
||||||
* See https://github.com/rust-lang/rfcs/pull/105
|
|
||||||
|
|
||||||
* Could affect API design in several places, e.g. the `Iterator` trait.
|
|
||||||
|
|
||||||
### Default type parameters
|
|
||||||
|
|
||||||
We are already using this in a few places (e.g. `HashMap`), but it's
|
|
||||||
feature-gated.
|
|
||||||
|
|
||||||
### Compile-time function evaluation (CTFE)
|
|
||||||
|
|
||||||
https://github.com/mozilla/rust/issues/11621
|
|
||||||
|
|
||||||
### Improved constant folding
|
|
||||||
|
|
||||||
https://github.com/rust-lang/rust/issues/7834
|
|
@ -57,7 +57,7 @@ fn write_info(info: &Info) -> Result<(), IoError> {
|
|||||||
```
|
```
|
||||||
|
|
||||||
See
|
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]
|
||||||
|
@ -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`
|
||||||
|
@ -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]
|
||||||
|
@ -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.
|
||||||
|
|
||||||
|
@ -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:
|
||||||
|
|
||||||
|
@ -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> {
|
||||||
|
// ...
|
||||||
|
}
|
||||||
|
```
|
||||||
|
@ -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, you’ll want to dive into either ‘Learn Rust’
|
After reading this introduction, you’ll 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 you’re not familiar with this distinction, you can
|
on the heap. If you’re 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 we’re getting started, it’s less of a big deal.
|
when we’re getting started, it’s 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 vector’s memory will be de-allocated. This is done deterministically
|
scope, the vector’s memory will be de-allocated. This is done deterministically
|
||||||
by the Rust compiler, rather than through a mechanism such as a garbage
|
by the Rust compiler, rather than through a mechanism such as a garbage
|
||||||
collector. In other words, in Rust, you don’t call functions like `malloc` and
|
collector. In other words, in Rust, we don’t 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.
|
||||||
|
|
||||||
Let’s add another line to our example:
|
Let’s add another line to our example:
|
||||||
|
|
||||||
@ -105,13 +104,13 @@ fn main() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
We’ve introduced another binding, `y`. In this case, `y` is a ‘reference’ to
|
We’ve introduced another binding, `y`. In this case, `y` is a ‘reference’ to the
|
||||||
the first element of the vector. Rust’s references are similar to pointers in
|
first element of the vector. Rust’s 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, we’d
|
won't deallocate the underlying memory. If it did, we’d 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.
|
||||||
|
@ -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)
|
||||||
|
@ -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
|
||||||
|
@ -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)
|
||||||
|
@ -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)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -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)
|
||||||
|
|
||||||
|
@ -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
|
||||||
we’ll see.
|
get the name ‘closures’ and Rust provides a really great implementation of
|
||||||
|
them, as we’ll see.
|
||||||
|
|
||||||
# Syntax
|
# Syntax
|
||||||
|
|
||||||
@ -34,7 +35,7 @@ assert_eq!(4, plus_two(2));
|
|||||||
```
|
```
|
||||||
|
|
||||||
You’ll notice a few things about closures that are a bit different from regular
|
You’ll notice a few things about closures that are a bit different from regular
|
||||||
functions defined with `fn`. The first is that we did not need to
|
named functions defined with `fn`. The first is that we did not need to
|
||||||
annotate the types of arguments the closure takes or the values it returns. We
|
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 don’t have to. Why is this? Basically, it was chosen for ergonomic reasons.
|
But we don’t 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 they’re anonymous, and they don’t cause the kinds of error-at-a-distance
|
closures are rarely documented since they’re anonymous, and they don’t 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. I’ve added spaces
|
The second is that the syntax is similar, but a bit different. I’ve 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 they’re 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 @@ isn’t 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`.
|
||||||
|
|
||||||
There’s one other key point here: because we’re bounding a generic with a
|
There’s one other key point here: because we’re bounding a generic with a
|
||||||
trait, this will get monomorphized, and therefore, we’ll be doing static
|
trait, this will get monomorphized, and therefore, we’ll be doing static
|
||||||
@ -411,8 +414,9 @@ fn factory() -> &(Fn(i32) -> i32) {
|
|||||||
```
|
```
|
||||||
|
|
||||||
Right. Because we have a reference, we need to give it a lifetime. But
|
Right. Because we have a reference, we need to give it a lifetime. But
|
||||||
our `factory()` function takes no arguments, so elision doesn’t kick in
|
our `factory()` function takes no arguments, so
|
||||||
here. What lifetime can we choose? `'static`:
|
[elision](lifetimes.html#lifetime-elision) doesn’t 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 don’t have a `&'static Fn(i32) -> i32`,
|
This error is letting us know that we don’t have a `&'static Fn(i32) -> i32`,
|
||||||
we have a `[closure <anon>:7:9: 7:20]`. Wait, what?
|
we have a `[closure@<anon>:7:9: 7:20]`. Wait, what?
|
||||||
|
|
||||||
Because each closure generates its own environment `struct` and implementation
|
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 doesn’t 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`. There’s just one last problem:
|
There’s 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> {
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -34,7 +34,7 @@ These can nest arbitrarily:
|
|||||||
As for how to enable or disable these switches, if you’re using Cargo,
|
As for how to enable or disable these switches, if you’re using Cargo,
|
||||||
they get set in the [`[features]` section][features] of your `Cargo.toml`:
|
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]
|
||||||
|
@ -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.
|
||||||
|
170
src/doc/trpl/custom-allocators.md
Normal file
170
src/doc/trpl/custom-allocators.md
Normal file
@ -0,0 +1,170 @@
|
|||||||
|
% Custom Allocators
|
||||||
|
|
||||||
|
Allocating memory isn't always the easiest thing to do, and while Rust generally
|
||||||
|
takes care of this by default it often becomes necessary to customize how
|
||||||
|
allocation occurs. The compiler and standard library currently allow switching
|
||||||
|
out the default global allocator in use at compile time. The design is currently
|
||||||
|
spelled out in [RFC 1183][rfc] but this will walk you through how to get your
|
||||||
|
own allocator up and running.
|
||||||
|
|
||||||
|
[rfc]: https://github.com/rust-lang/rfcs/blob/master/text/1183-swap-out-jemalloc.md
|
||||||
|
|
||||||
|
# Default Allocator
|
||||||
|
|
||||||
|
The compiler currently ships two default allocators: `alloc_system` and
|
||||||
|
`alloc_jemalloc` (some targets don't have jemalloc, however). These allocators
|
||||||
|
are just normal Rust crates and contain an implementation of the routines to
|
||||||
|
allocate and deallocate memory. The standard library is not compiled assuming
|
||||||
|
either one, and the compiler will decide which allocator is in use at
|
||||||
|
compile-time depending on the type of output artifact being produced.
|
||||||
|
|
||||||
|
Binaries generated by the compiler will use `alloc_jemalloc` by default (where
|
||||||
|
available). In this situation the compiler "controls the world" in the sense of
|
||||||
|
it has power over the final link. Primarily this means that the allocator
|
||||||
|
decision can be left up the compiler.
|
||||||
|
|
||||||
|
Dynamic and static libraries, however, will use `alloc_system` by default. Here
|
||||||
|
Rust is typically a 'guest' in another application or another world where it
|
||||||
|
cannot authoritatively decide what allocator is in use. As a result it resorts
|
||||||
|
back to the standard APIs (e.g. `malloc` and `free`) for acquiring and releasing
|
||||||
|
memory.
|
||||||
|
|
||||||
|
# Switching Allocators
|
||||||
|
|
||||||
|
Although the compiler's default choices may work most of the time, it's often
|
||||||
|
necessary to tweak certain aspects. Overriding the compiler's decision about
|
||||||
|
which allocator is in use is done simply by linking to the desired allocator:
|
||||||
|
|
||||||
|
```rust,no_run
|
||||||
|
#![feature(alloc_system)]
|
||||||
|
|
||||||
|
extern crate alloc_system;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let a = Box::new(4); // allocates from the system allocator
|
||||||
|
println!("{}", a);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
In this example the binary generated will not link to jemalloc by default but
|
||||||
|
instead use the system allocator. Conversely to generate a dynamic library which
|
||||||
|
uses jemalloc by default one would write:
|
||||||
|
|
||||||
|
```rust,ignore
|
||||||
|
#![feature(alloc_jemalloc)]
|
||||||
|
#![crate_type = "dylib"]
|
||||||
|
|
||||||
|
extern crate alloc_jemalloc;
|
||||||
|
|
||||||
|
pub fn foo() {
|
||||||
|
let a = Box::new(4); // allocates from jemalloc
|
||||||
|
println!("{}", a);
|
||||||
|
}
|
||||||
|
# fn main() {}
|
||||||
|
```
|
||||||
|
|
||||||
|
# Writing a custom allocator
|
||||||
|
|
||||||
|
Sometimes even the choices of jemalloc vs the system allocator aren't enough and
|
||||||
|
an entirely new custom allocator is required. In this you'll write your own
|
||||||
|
crate which implements the allocator API (e.g. the same as `alloc_system` or
|
||||||
|
`alloc_jemalloc`). As an example, let's take a look at a simplified and
|
||||||
|
annotated version of `alloc_system`
|
||||||
|
|
||||||
|
```rust,no_run
|
||||||
|
# // only needed for rustdoc --test down below
|
||||||
|
# #![feature(lang_items)]
|
||||||
|
// The compiler needs to be instructed that this crate is an allocator in order
|
||||||
|
// to realize that when this is linked in another allocator like jemalloc should
|
||||||
|
// not be linked in
|
||||||
|
#![feature(allocator)]
|
||||||
|
#![allocator]
|
||||||
|
|
||||||
|
// Allocators are not allowed to depend on the standard library which in turn
|
||||||
|
// requires an allocator in order to avoid circular dependencies. This crate,
|
||||||
|
// however, can use all of libcore.
|
||||||
|
#![feature(no_std)]
|
||||||
|
#![no_std]
|
||||||
|
|
||||||
|
// Let's give a unique name to our custom allocator
|
||||||
|
#![crate_name = "my_allocator"]
|
||||||
|
#![crate_type = "rlib"]
|
||||||
|
|
||||||
|
// Our system allocator will use the in-tree libc crate for FFI bindings. Note
|
||||||
|
// that currently the external (crates.io) libc cannot be used because it links
|
||||||
|
// to the standard library (e.g. `#![no_std]` isn't stable yet), so that's why
|
||||||
|
// this specifically requires the in-tree version.
|
||||||
|
#![feature(libc)]
|
||||||
|
extern crate libc;
|
||||||
|
|
||||||
|
// Listed below are the five allocation functions currently required by custom
|
||||||
|
// allocators. Their signatures and symbol names are not currently typechecked
|
||||||
|
// by the compiler, but this is a future extension and are required to match
|
||||||
|
// what is found below.
|
||||||
|
//
|
||||||
|
// Note that the standard `malloc` and `realloc` functions do not provide a way
|
||||||
|
// to communicate alignment so this implementation would need to be improved
|
||||||
|
// with respect to alignment in that aspect.
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub extern fn __rust_allocate(size: usize, _align: usize) -> *mut u8 {
|
||||||
|
unsafe { libc::malloc(size as libc::size_t) as *mut u8 }
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub extern fn __rust_deallocate(ptr: *mut u8, _old_size: usize, _align: usize) {
|
||||||
|
unsafe { libc::free(ptr as *mut libc::c_void) }
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub extern fn __rust_reallocate(ptr: *mut u8, _old_size: usize, size: usize,
|
||||||
|
_align: usize) -> *mut u8 {
|
||||||
|
unsafe {
|
||||||
|
libc::realloc(ptr as *mut libc::c_void, size as libc::size_t) as *mut u8
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub extern fn __rust_reallocate_inplace(_ptr: *mut u8, old_size: usize,
|
||||||
|
_size: usize, _align: usize) -> usize {
|
||||||
|
old_size // this api is not supported by libc
|
||||||
|
}
|
||||||
|
|
||||||
|
#[no_mangle]
|
||||||
|
pub extern fn __rust_usable_size(size: usize, _align: usize) -> usize {
|
||||||
|
size
|
||||||
|
}
|
||||||
|
|
||||||
|
# // just needed to get rustdoc to test this
|
||||||
|
# fn main() {}
|
||||||
|
# #[lang = "panic_fmt"] fn panic_fmt() {}
|
||||||
|
# #[lang = "eh_personality"] fn eh_personality() {}
|
||||||
|
# #[lang = "eh_unwind_resume"] extern fn eh_unwind_resume() {}
|
||||||
|
```
|
||||||
|
|
||||||
|
After we compile this crate, it can be used as follows:
|
||||||
|
|
||||||
|
```rust,ignore
|
||||||
|
extern crate my_allocator;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let a = Box::new(8); // allocates memory via our custom allocator crate
|
||||||
|
println!("{}", a);
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
# Custom allocator limitations
|
||||||
|
|
||||||
|
There are a few restrictions when working with custom allocators which may cause
|
||||||
|
compiler errors:
|
||||||
|
|
||||||
|
* Any one artifact may only be linked to at most one allocator. Binaries,
|
||||||
|
dylibs, and staticlibs must link to exactly one allocator, and if none have
|
||||||
|
been explicitly chosen the compiler will choose one. On the other hand rlibs
|
||||||
|
do not need to link to an allocator (but still can).
|
||||||
|
|
||||||
|
* A consumer of an allocator is tagged with `#![needs_allocator]` (e.g. the
|
||||||
|
`liballoc` crate currently) and an `#[allocator]` crate cannot transitively
|
||||||
|
depend on a crate which needs an allocator (e.g. circular dependencies are not
|
||||||
|
allowed). This basically means that allocators must restrict themselves to
|
||||||
|
libcore currently.
|
@ -13,7 +13,7 @@ Hoare in 1985.
|
|||||||
> dining room, furnished with a circular table, surrounded by five chairs, each
|
> 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, let’s 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. We’ll get to our solution in
|
There are different ways to solve this problem. We’ll get to our solution in
|
||||||
the tutorial itself. For now, let’s get started modelling the problem itself.
|
the tutorial itself. For now, let’s get started modeling the problem itself.
|
||||||
We’ll start with the philosophers:
|
We’ll start with the philosophers:
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
@ -434,7 +434,7 @@ ownership of the values it’s capturing. Primarily, the `p` variable of the
|
|||||||
|
|
||||||
Inside the thread, all we do is call `eat()` on `p`. Also note that the call to `thread::spawn` lacks a trailing semicolon, making this an expression. This distinction is important, yielding the correct return value. For more details, read [Expressions vs. Statements][es].
|
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. We’ve also added an argument, `table`. We access the
|
We have three new lines. We’ve added an argument, `table`. We access the
|
||||||
`Table`’s list of forks, and then use `self.left` and `self.right` to access
|
`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, we’ll block until it becomes available.
|
someone else, we’ll block until it becomes available. We have also a call to
|
||||||
|
`thread::sleep_ms` between the moment first fork is picked and the moment the
|
||||||
|
second forked is picked, as the process of picking up the fork is not
|
||||||
|
immediate.
|
||||||
|
|
||||||
The call to `lock()` might fail, and if it does, we want to crash. In this
|
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, it’s all consistent until the very end. Monsieur
|
you look at the pattern, it’s all consistent until the very end. Monsieur
|
||||||
Foucault should have `4, 0` as arguments, but instead, has `0, 4`. This is what
|
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, it’s the simplest.
|
one way to solve the problem, and in my opinion, it’s the simplest. If you
|
||||||
|
change the order of the parameters, you will be able to observe the deadlock
|
||||||
|
taking place.
|
||||||
|
|
||||||
```rust,ignore
|
```rust,ignore
|
||||||
let handles: Vec<_> = philosophers.into_iter().map(|p| {
|
let handles: Vec<_> = philosophers.into_iter().map(|p| {
|
||||||
|
@ -45,7 +45,7 @@ Rust keeps track of these comments, and uses them when generating
|
|||||||
documentation. This is important when documenting things like enums:
|
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 don’t 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
|
||||||
|
@ -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)
|
||||||
|
@ -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, we’ll install Rust. Then, the classic ‘Hello World’ program. Finally,
|
First, we’ll install Rust. Then, the classic ‘Hello World’ program. Finally,
|
||||||
we’ll talk about Cargo, Rust’s build system and package manager.
|
we’ll talk about Cargo, Rust’s build system and package manager.
|
||||||
|
@ -38,11 +38,19 @@ let z = (8, 2, 6);
|
|||||||
|
|
||||||
In the example above `x` and `y` have arity 2. `z` has arity 3.
|
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
|
||||||
|
|
||||||
|
@ -99,9 +99,12 @@ use std::io;
|
|||||||
We’ll need to take user input, and then print the result as output. As such, we
|
We’ll need to take user input, and then print the result as output. As such, we
|
||||||
need the `io` library from the standard library. Rust only imports a few things
|
need the `io` library from the standard library. Rust only imports a few things
|
||||||
by default into every program, [the ‘prelude’][prelude]. If it’s not in the
|
by default into every program, [the ‘prelude’][prelude]. If it’s not in the
|
||||||
prelude, you’ll have to `use` it directly.
|
prelude, you’ll have to `use` it directly. There is also a second ‘prelude’, the
|
||||||
|
[`io` prelude][ioprelude], which serves a similar function: you import it, and it
|
||||||
|
imports a number of useful, `io`-related things.
|
||||||
|
|
||||||
[prelude]: ../std/prelude/index.html
|
[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, they’re [immutable][immutable] by default. That’s why our example
|
For example, they’re [immutable][immutable] by default. That’s why our example
|
||||||
uses `mut`: it makes a binding mutable, rather than immutable. `let` doesn’t
|
uses `mut`: it makes a binding mutable, rather than immutable. `let` doesn’t
|
||||||
take a name on the left hand side, it actually accepts a
|
take a name on the left hand side of the assignment, it actually accepts a
|
||||||
‘[pattern][patterns]’. We’ll use patterns later. It’s easy enough
|
‘[pattern][patterns]’. We’ll use patterns later. It’s 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 don’t care what kind of error it is, so we just
|
side. In the `Err` case, we don’t care what kind of error it is, so we just
|
||||||
|
@ -7,15 +7,16 @@ so it is assumed that Rust projects will use Cargo from the beginning.
|
|||||||
|
|
||||||
[cratesio]: http://doc.crates.io
|
[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 doesn’t
|
code needs, and building those dependencies. At first, our program doesn’t have
|
||||||
have any dependencies, so we’ll only be using the first part of its
|
any dependencies, so we’ll only be using the first part of its functionality.
|
||||||
functionality. Eventually, we’ll add more. Since we started off by using Cargo,
|
Eventually, we’ll 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 it’ll work the right way.
|
grows, we can just run `cargo build`, and it’ll work the right way.
|
||||||
|
|
||||||
When your project is finally ready for release, you can use
|
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 don’t have any, so it’s a bit sparse. You won't ever need
|
application. Right now, we don’t have any, so it’s 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.
|
||||||
|
|
||||||
That’s it! We’ve successfully built `hello_world` with Cargo. Even though our
|
That’s it! We’ve successfully built `hello_world` with Cargo. Even though our
|
||||||
program is simple, it’s using much of the real tooling that you’ll use for the
|
program is simple, it’s using much of the real tooling that we’ll 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 don’t have to go through this whole process every time you want to start a
|
We don’t 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
|
||||||
```
|
```
|
||||||
|
|
||||||
We’re passing `--bin` because our goal is to get straight to making an executable application, as opposed to a library. Executables are often called ‘binaries.’ (as in `/usr/bin`, if you’re on a Unix system)
|
We’re passing `--bin` because our goal is to get straight to making an
|
||||||
|
executable application, as opposed to a library. Executables are often called
|
||||||
|
‘binaries.’ (as in `/usr/bin`, if we’re on a Unix system)
|
||||||
|
|
||||||
Let's check out what Cargo has generated for us:
|
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
|
||||||
distribution’s package manager. It’s not necessary, but it’s certainly useful.
|
distribution’s package manager. It’s not necessary, but it’s certainly useful.
|
||||||
|
|
||||||
This is all we need to get started. First, let’s check out `Cargo.toml`:
|
This is all we need to get started. First, let’s check out `Cargo.toml`:
|
||||||
@ -176,7 +179,7 @@ authors = ["Your Name <you@example.com>"]
|
|||||||
```
|
```
|
||||||
|
|
||||||
Cargo has populated this file with reasonable defaults based off the arguments
|
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.
|
||||||
|
|
||||||
Here’s what’s in `src/main.rs`:
|
Here’s what’s in `src/main.rs`:
|
||||||
@ -187,20 +190,21 @@ fn main() {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Cargo has generated a "Hello World!" for us, and you’re ready to start coding! Cargo
|
Cargo has generated a "Hello World!" for us, and we’re ready to start coding!
|
||||||
has its own [guide][guide] which covers Cargo’s features in much more depth.
|
Cargo has its own [guide][guide] which covers Cargo’s features in much more
|
||||||
|
depth.
|
||||||
|
|
||||||
[guide]: http://doc.crates.io/guide.html
|
[guide]: http://doc.crates.io/guide.html
|
||||||
|
|
||||||
Now that you’ve got the tools down, let’s actually learn more about the Rust
|
Now that we’ve got the tools down, let’s actually learn more about the Rust
|
||||||
language itself. These are the basics that will serve 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 whatever’s right for you.
|
either. Different people learn differently! Choose whatever’s right for you.
|
||||||
|
|
||||||
[learnrust]: learn-rust.html
|
[learnrust]: learn-rust.html
|
||||||
[syntax]: syntax-and-semantics.html
|
[syntax]: syntax-and-semantics.html
|
||||||
|
@ -1,25 +1,25 @@
|
|||||||
% Hello, world!
|
% Hello, world!
|
||||||
|
|
||||||
Now that you have Rust installed, let’s write your first Rust program. It’s
|
Now that we have Rust installed, let’s write our first Rust program. It’s
|
||||||
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 isn’t just installed,
|
simple program is that we can verify that our compiler isn’t 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 you’re on Windows and not using PowerShell, the `~` may not work. Consult
|
If we’re 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.
|
||||||
|
|
||||||
Let’s make a new source file next. We’ll call our file `main.rs`. Rust files
|
Let’s make a new source file next. We’ll call our file `main.rs`. Rust files
|
||||||
always end in a `.rs` extension. If you’re using more than one word in your
|
always end in a `.rs` extension, and if we’re 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 you’ve got your file open, type this in:
|
Now that we’ve 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 aren’t returning anything from this function, we can omit the return type
|
|||||||
entirely. We’ll get to it later.
|
entirely. We’ll get to it later.
|
||||||
|
|
||||||
You’ll also note that the function is wrapped in curly braces (`{` and `}`).
|
You’ll also note that the function is wrapped in curly braces (`{` and `}`).
|
||||||
Rust requires these around all function bodies. It is also considered good
|
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 it’s indented with four
|
details that are important here. The first is that it’s indented with four
|
||||||
spaces, not tabs. Please configure your editor of choice to insert four spaces
|
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 don’t need to worry
|
function instead, it would look like this: `println()`. For our purposes, we
|
||||||
about this difference. Just know that sometimes, you’ll see a `!`, and that
|
don’t need to worry about this difference. Just know that sometimes, we’ll see a
|
||||||
means that you’re calling a macro instead of a normal function. Rust implements
|
`!`, and that means that we’re 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: Rust’s macros are significantly
|
but that's an advanced topic. One last thing to mention: Rust’s macros are
|
||||||
different from C macros, if you’ve used those. Don’t be scared of using macros.
|
significantly different from C macros, if you’ve used those. Don’t be scared of
|
||||||
We’ll get to the details eventually, you’ll just have to trust us for now.
|
using macros. We’ll get to the details eventually, you’ll 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 don’t need to right now if you
|
the heap][allocation], but you don’t need to right now if you don’t want to. We
|
||||||
don’t 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.
|
||||||
|
@ -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 doesn’t match, nothing happens.
|
the pattern doesn’t match, nothing happens.
|
||||||
|
|
||||||
If you’d rather to do something else when the pattern does not match, you can
|
If you want to do something else when the pattern does not match, you can
|
||||||
use `else`:
|
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,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
@ -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. You’ll see many tutorials and examples around the web that
|
> each command. We’ll 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 user’s forum][users], and
|
include [the user’s 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
|
||||||
|
@ -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. Let’s
|
||||||
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
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
% Lifetimes
|
% Lifetimes
|
||||||
|
|
||||||
This guide is one of three presenting Rust’s ownership system. This is one of
|
This guide is three of three presenting Rust’s ownership system. This is one of
|
||||||
Rust’s most unique and compelling features, with which Rust developers should
|
Rust’s 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, let’s 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 I’m done with the resource, and deallocate it, while you still have
|
3. I decide I’m 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, let’s break the explicit example down:
|
Before we get to that, though, let’s 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
|
||||||
```
|
```
|
||||||
|
@ -55,7 +55,7 @@ kinds of things `foo` could be: `self` if it’s just a value on the stack,
|
|||||||
`&self` if it’s a reference, and `&mut self` if it’s a mutable reference.
|
`&self` if it’s a reference, and `&mut self` if it’s 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 it’s a `Circle`, we can access the `radius`
|
other parameter. Because we know it’s 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. Here’s an
|
ownership, as well as taking immutable references over mutable ones. Here’s an
|
||||||
|
@ -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`).
|
||||||
|
|
||||||
|
@ -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 we’re 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;
|
||||||
|
|
||||||
|
@ -42,7 +42,7 @@ With that in mind, let’s 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 they’re bound to. This means that when a binding goes out of scope,
|
of what they’re 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.
|
||||||
It’s the topic of the next section!
|
It’s the topic of the next section!
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -23,6 +23,31 @@ match x {
|
|||||||
|
|
||||||
This prints `one`.
|
This prints `one`.
|
||||||
|
|
||||||
|
There’s one pitfall with patterns: like anything that introduces a new binding,
|
||||||
|
they introduce shadowing. For example:
|
||||||
|
|
||||||
|
```rust
|
||||||
|
let x = 'x';
|
||||||
|
let c = 'c';
|
||||||
|
|
||||||
|
match c {
|
||||||
|
x => println!("x: {} c: {}", x, c),
|
||||||
|
}
|
||||||
|
|
||||||
|
println!("x: {}", x)
|
||||||
|
```
|
||||||
|
|
||||||
|
This prints:
|
||||||
|
|
||||||
|
```text
|
||||||
|
x: c c: c
|
||||||
|
x: x
|
||||||
|
```
|
||||||
|
|
||||||
|
In other words, `x =>` matches the pattern and introduces a new binding named
|
||||||
|
`x` that’s in scope for the match arm. Because we already have a binding named
|
||||||
|
`x`, this new `x` shadows it.
|
||||||
|
|
||||||
# Multiple patterns
|
# 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 => ...
|
||||||
|
@ -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]`. We’ll talk about that `T` when we cover
|
Slices have type `&[T]`. We’ll talk about that `T` when we cover
|
||||||
|
@ -98,16 +98,15 @@ these properties are true for any references, no matter how they are created,
|
|||||||
and so any conversion from raw pointers is asserting that they hold. The
|
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 {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
% References and Borrowing
|
% References and Borrowing
|
||||||
|
|
||||||
This guide is one of three presenting Rust’s ownership system. This is one of
|
This guide is two of three presenting Rust’s ownership system. This is one of
|
||||||
Rust’s most unique and compelling features, with which Rust developers should
|
Rust’s 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);
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
@ -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!");
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -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
Loading…
Reference in New Issue
Block a user