Imported Upstream version 1.0.0+dfsg1

This commit is contained in:
Angus Lees 2015-05-16 08:16:23 +10:00
parent 9346a6ac1c
commit bd371182c2
235 changed files with 9526 additions and 3522 deletions

View File

@ -8,6 +8,7 @@ Aaron Raimist <aaron@aaronraimist.com>
Aaron Todd <github@opprobrio.us> 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@cloudscaling.com>
Adam Bozanich <adam.boz@gmail.com> Adam Bozanich <adam.boz@gmail.com>
Adam Jacob <adam@opscode.com> Adam Jacob <adam@opscode.com>
Adam Roben <adam@roben.org> Adam Roben <adam@roben.org>
@ -28,6 +29,7 @@ Aleksandr Koshlo <sash7ko@gmail.com>
Alex Crichton <alex@alexcrichton.com> Alex Crichton <alex@alexcrichton.com>
Alex Gaynor <alex.gaynor@gmail.com> Alex Gaynor <alex.gaynor@gmail.com>
Alex Lyon <arcterus@mail.com> Alex Lyon <arcterus@mail.com>
Alex Quach <alex@clinkle.com>
Alex Rønne Petersen <alex@lycus.org> Alex Rønne Petersen <alex@lycus.org>
Alex Whitney <aw1209@ic.ac.uk> Alex Whitney <aw1209@ic.ac.uk>
Alexander Bliskovsky <alexander.bliskovsky@gmail.com> Alexander Bliskovsky <alexander.bliskovsky@gmail.com>
@ -41,7 +43,6 @@ Alexandros Tasos <sdi1100085@di.uoa.gr>
Alexei Sholik <alcosholik@gmail.com> Alexei Sholik <alcosholik@gmail.com>
Alexis Beingessner <a.beingessner@gmail.com> Alexis Beingessner <a.beingessner@gmail.com>
Alfie John <alfie@alfie.wtf> Alfie John <alfie@alfie.wtf>
Alfie John <alfiej@fastmail.fm>
Ali Smesseim <smesseim.ali@gmail.com> Ali Smesseim <smesseim.ali@gmail.com>
Alisdair Owens <awo101@zepler.net> Alisdair Owens <awo101@zepler.net>
Aljaž "g5pw" Srebrnič <a2piratesoft@gmail.com> Aljaž "g5pw" Srebrnič <a2piratesoft@gmail.com>
@ -64,10 +65,13 @@ Andrew Gallant <jamslam@gmail.com>
Andrew Hobden <andrew@hoverbear.org> Andrew Hobden <andrew@hoverbear.org>
Andrew Paseltiner <apaseltiner@gmail.com> Andrew Paseltiner <apaseltiner@gmail.com>
Andrew Poelstra <asp11@sfu.ca> Andrew Poelstra <asp11@sfu.ca>
Andrew Seidl <dev@aas.io>
Andrew Wagner <drewm1980@gmail.com> Andrew Wagner <drewm1980@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>
Aram Visser <aramvisser@gmail.com>
Areski Belaid <areski@gmail.com>
Arcterus <Arcterus@mail.com> Arcterus <Arcterus@mail.com>
Ariel Ben-Yehuda <arielb1@mail.tau.ac.il> Ariel Ben-Yehuda <arielb1@mail.tau.ac.il>
Arjan Topolovec <arjan.top@gmail.com> Arjan Topolovec <arjan.top@gmail.com>
@ -78,6 +82,7 @@ Arpad Borsos <arpad.borsos@googlemail.com>
Artem <artemciy@gmail.com> Artem <artemciy@gmail.com>
Arthur Liao <arthurtw8@gmail.com> Arthur Liao <arthurtw8@gmail.com>
Ashok Gautham <ScriptDevil@gmail.com> Ashok Gautham <ScriptDevil@gmail.com>
Augusto Hack <hack.augusto@gmail.com>
Austin Bonander <austin.bonander@gmail.com> Austin Bonander <austin.bonander@gmail.com>
Austin King <shout@ozten.com> Austin King <shout@ozten.com>
Austin Seipp <mad.one@gmail.com> Austin Seipp <mad.one@gmail.com>
@ -85,13 +90,14 @@ Axel Viala <axel.viala@darnuria.eu>
Aydin Kim <ladinjin@hanmail.net> Aydin Kim <ladinjin@hanmail.net>
Barosl Lee <vcs@barosl.com> Barosl Lee <vcs@barosl.com>
Ben Alpert <ben@benalpert.com> Ben Alpert <ben@benalpert.com>
Ben Ashford <ben@bcash.org>
Ben Blum <bblum@andrew.cmu.edu> Ben Blum <bblum@andrew.cmu.edu>
Ben Foppa <benjamin.foppa@gmail.com> Ben Foppa <benjamin.foppa@gmail.com>
Ben Gamari <bgamari.foss@gmail.com> Ben Gamari <bgamari.foss@gmail.com>
Ben Harris <mail@bharr.is> Ben Harris <mail@bharr.is>
Ben Kelly <ben@wanderview.com> Ben Kelly <ben@wanderview.com>
Ben Noordhuis <info@bnoordhuis.nl> Ben Noordhuis <info@bnoordhuis.nl>
Ben S <ogham@users.noreply.github.com> Ben Sago <ogham@users.noreply.github.com>
Ben Striegel <ben.striegel@gmail.com> Ben Striegel <ben.striegel@gmail.com>
Benjamin Adamson <adamson.benjamin@gmail.com> Benjamin Adamson <adamson.benjamin@gmail.com>
Benjamin Herr <ben@0x539.de> Benjamin Herr <ben@0x539.de>
@ -112,6 +118,7 @@ Brandon Waskiewicz <brandon.waskiewicz@gmail.com>
Branimir <branimir@volomp.com> Branimir <branimir@volomp.com>
Brendan Cully <brendan@kublai.com> Brendan Cully <brendan@kublai.com>
Brendan Eich <brendan@mozilla.org> Brendan Eich <brendan@mozilla.org>
Brendan Graetz <github@bguiz.com>
Brendan McLoughlin <btmcloughlin@gmail.com> Brendan McLoughlin <btmcloughlin@gmail.com>
Brendan Zabarauskas <bjzaba@yahoo.com.au> Brendan Zabarauskas <bjzaba@yahoo.com.au>
Brett Cannon <brett@python.org> Brett Cannon <brett@python.org>
@ -135,8 +142,8 @@ Camille TJHOA <camille.tjhoa@outlook.com>
CarVac <c.lo.to.da.down.lo@gmail.com> CarVac <c.lo.to.da.down.lo@gmail.com>
Carl Lerche <me@carllerche.com> Carl Lerche <me@carllerche.com>
Carl-Anton Ingmarsson <mail@carlanton.se> Carl-Anton Ingmarsson <mail@carlanton.se>
Carlos <toqueteos@gmail.com> Carlos Galarza <carloslfu@gmail.com>
Carol Nichols <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>
@ -151,10 +158,11 @@ Chris Peterson <cpeterson@mozilla.com>
Chris Pressey <cpressey@gmail.com> Chris Pressey <cpressey@gmail.com>
Chris Sainty <csainty@hotmail.com> Chris Sainty <csainty@hotmail.com>
Chris Shea <cmshea@gmail.com> Chris Shea <cmshea@gmail.com>
Chris Thorn <thorn@thoughtbot.com> Chris Thorn <chris@thorn.co>
Chris Wong <lambda.fairy@gmail.com> Chris Wong <lambda.fairy@gmail.com>
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 Kendell <ckendell@outlook.com> Christopher Kendell <ckendell@outlook.com>
Chuck Ries <chuck.ries@gmail.com> Chuck Ries <chuck.ries@gmail.com>
Clark Gaebel <cg.wowus.cg@gmail.com> Clark Gaebel <cg.wowus.cg@gmail.com>
@ -172,13 +180,14 @@ Corey Richardson <corey@octayn.net>
Cristi Burcă <scribu@gmail.com> Cristi Burcă <scribu@gmail.com>
Cristian Kubis <cristian.kubis@tsunix.de> Cristian Kubis <cristian.kubis@tsunix.de>
DJUrsus <colinvh@divitu.com> DJUrsus <colinvh@divitu.com>
Dabo Ross <daboross@daboross.net> David 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>
Damien Schoof <damien.schoof@gmail.com> Damien Schoof <damien.schoof@gmail.com>
Dan Albert <danalbert@google.com> Dan Albert <danalbert@google.com>
Dan Burkert <dan@danburkert.com> Dan Burkert <dan@danburkert.com>
Dan Callahan <dan.callahan@gmail.com>
Dan Connolly <dckc@madmode.com> Dan Connolly <dckc@madmode.com>
Dan Luu <danluu@gmail.com> Dan Luu <danluu@gmail.com>
Dan Schatzberg <schatzberg.dan@gmail.com> Dan Schatzberg <schatzberg.dan@gmail.com>
@ -234,6 +243,8 @@ Dmitry Ermolov <epdmitry@yandex.ru>
Dmitry Promsky <dmitry@willworkforcookies.com> Dmitry Promsky <dmitry@willworkforcookies.com>
Dmitry Vasiliev <dima@hlabs.org> Dmitry Vasiliev <dima@hlabs.org>
Do Nhat Minh <mrordinaire@gmail.com> Do Nhat Minh <mrordinaire@gmail.com>
Dominic van Berkel <dominic@baudvine.net>
Dominick Allen <dominick.allen1989@gmail.com>
Dominik Inführ <dominik.infuehr@gmail.com> Dominik Inführ <dominik.infuehr@gmail.com>
Donovan Preston <donovanpreston@gmail.com> Donovan Preston <donovanpreston@gmail.com>
Douglas Young <rcxdude@gmail.com> Douglas Young <rcxdude@gmail.com>
@ -287,11 +298,10 @@ Felix S. Klock II <pnkfelix@pnkfx.org>
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> Flaper Fesp <flaper87@gmail.com>
Flavio Percoco <flaper87@gmail.com>
Florian Gilcher <florian.gilcher@asquera.de> Florian Gilcher <florian.gilcher@asquera.de>
Florian Hahn <flo@fhahn.com> Florian Hahn <flo@fhahn.com>
Florian Hartwig <florian.j.hartwig@gmail.com> Florian Hartwig <florian.j.hartwig@gmail.com>
Florian Wilkens <floya@live.de> Florian Wilkens <mrfloya_github@outlook.com>
Florian Zeitz <florob@babelmonkeys.de> Florian Zeitz <florob@babelmonkeys.de>
Francisco Souza <f@souza.cc> Francisco Souza <f@souza.cc>
Franklin Chen <franklinchen@franklinchen.com> Franklin Chen <franklinchen@franklinchen.com>
@ -310,13 +320,12 @@ Georges Dubus <georges.dubus@gmail.com>
Germano Gabbianelli <tyrion@users.noreply.github.com> 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>
GlacJAY <glacjay@gmail.com>
Gleb Kozyrev <gleb@gkoz.com> Gleb Kozyrev <gleb@gkoz.com>
Glenn Willen <gwillen@nerdnet.org> Glenn Willen <gwillen@nerdnet.org>
Gonçalo Cabrita <_@gmcabrita.com> Gonçalo Cabrita <_@gmcabrita.com>
Graham Fawcett <graham.fawcett@gmail.com> Graham Fawcett <graham.fawcett@gmail.com>
Grahame Bowland <grahame@angrygoats.net> Grahame Bowland <grahame@angrygoats.net>
Graydon Hoare <graydon@mozilla.com> Graydon Hoare <graydon@pobox.com>
Greg Chapple <gregchapple1@gmail.com> Greg Chapple <gregchapple1@gmail.com>
Grigoriy <ohaistarlight@gmail.com> Grigoriy <ohaistarlight@gmail.com>
Guillaume Gomez <guillaume1.gomez@gmail.com> Guillaume Gomez <guillaume1.gomez@gmail.com>
@ -325,11 +334,13 @@ Gyorgy Andrasek <jurily@gmail.com>
Gábor Horváth <xazax.hun@gmail.com> Gábor Horváth <xazax.hun@gmail.com>
Gábor Lehel <glaebhoerl@gmail.com> Gábor Lehel <glaebhoerl@gmail.com>
Haitao Li <lihaitao@gmail.com> Haitao Li <lihaitao@gmail.com>
Hajime Morrita <omo@dodgson.org>
Hanno Braun <mail@hannobraun.de> Hanno Braun <mail@hannobraun.de>
Harry Marr <harry.marr@gmail.com> Harry Marr <harry.marr@gmail.com>
Heather <heather@cynede.net> Heather <heather@cynede.net>
Heejong Ahn <heejongahn@gmail.com
Henrik Schopmans <h.schopmans@googlemail.com> Henrik Schopmans <h.schopmans@googlemail.com>
Herman J. Radtke III <hermanradtke@gmail.com> Herman J. Radtke III <herman@hermanradtke.com>
HeroesGrave <heroesgrave@gmail.com> HeroesGrave <heroesgrave@gmail.com>
Hong Chulju <ang0123dev@gmail.com> Hong Chulju <ang0123dev@gmail.com>
Honza Strnad <hanny.strnad@gmail.com> Honza Strnad <hanny.strnad@gmail.com>
@ -343,6 +354,7 @@ Ian D. Bollinger <ian.bollinger@gmail.com>
Ian Daniher <it.daniher@gmail.com> Ian Daniher <it.daniher@gmail.com>
Ignacio Corderi <icorderi@msn.com> Ignacio Corderi <icorderi@msn.com>
Igor Bukanov <igor@mir2.org> Igor Bukanov <igor@mir2.org>
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>
@ -390,7 +402,7 @@ Jashank Jeremy <jashank@rulingia.com>
Jason Fager <jfager@gmail.com> Jason Fager <jfager@gmail.com>
Jason Orendorff <jorendorff@mozilla.com> Jason Orendorff <jorendorff@mozilla.com>
Jason Thompson <jason@jthompson.ca> Jason Thompson <jason@jthompson.ca>
Jason Toffaletti <jason@topsy.com> Jason Toffaletti <toffaletti@gmail.com>
Jauhien Piatlicki <jauhien@gentoo.org> Jauhien Piatlicki <jauhien@gentoo.org>
Jay Anderson <jayanderson0@gmail.com> Jay Anderson <jayanderson0@gmail.com>
Jay True <glacjay@gmail.com> Jay True <glacjay@gmail.com>
@ -421,8 +433,10 @@ Jimmie Elvenmark <flugsio@gmail.com>
Jimmy Lu <jimmy.lu.2011@gmail.com> Jimmy Lu <jimmy.lu.2011@gmail.com>
Jimmy Zelinskie <jimmyzelinskie@gmail.com> Jimmy Zelinskie <jimmyzelinskie@gmail.com>
Jiří Stránský <jistr@jistr.com> Jiří Stránský <jistr@jistr.com>
João Oliveira <hello@jxs.pt>
Joe Pletcher <joepletcher@gmail.com> Joe Pletcher <joepletcher@gmail.com>
Joe Schafer <joe@jschaf.com> Joe Schafer <joe@jschaf.com>
Johann Hofmann <mail@johann-hofmann.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>
@ -436,10 +450,10 @@ John Gallagher <jgallagher@bignerdranch.com>
John Hodge <acessdev@gmail.com> John Hodge <acessdev@gmail.com>
John Kåre Alsaker <john.kare.alsaker@gmail.com> John Kåre Alsaker <john.kare.alsaker@gmail.com>
John Kleint <jk@hinge.co> John Kleint <jk@hinge.co>
John Kåre Alsaker <john.kare.alsaker@gmail.com>
John Louis Walker <injyuw@gmail.com> 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 Zhang <john@zhang.io> John Zhang <john@zhang.io>
Jon Haddad <jon@jonhaddad.com> Jon Haddad <jon@jonhaddad.com>
Jon Morton <jonanin@gmail.com> Jon Morton <jonanin@gmail.com>
@ -462,6 +476,7 @@ Joseph Rushton Wakeling <joe@webdrake.net>
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>
Joshua Clark <joshua.clark@txstate.edu> Joshua Clark <joshua.clark@txstate.edu>
Joshua Wise <joshua@joshuawise.com> Joshua Wise <joshua@joshuawise.com>
Joshua Yanovski <pythonesque@gmail.com> Joshua Yanovski <pythonesque@gmail.com>
@ -492,6 +507,7 @@ Kevin Walter <kevin.walter.private@googlemail.com>
Kevin Yap <me@kevinyap.ca> Kevin Yap <me@kevinyap.ca>
Kiet Tran <ktt3ja@gmail.com> Kiet Tran <ktt3ja@gmail.com>
Kim Røen <kim@pam.no> Kim Røen <kim@pam.no>
KokaKiwi <kokakiwi+rust@kokakiwi.net>
Kostas Karachalios <vrinek@me.com> Kostas Karachalios <vrinek@me.com>
Kyeongwoon Lee <kyeongwoon.lee@samsung.com> Kyeongwoon Lee <kyeongwoon.lee@samsung.com>
Lai Jiangshan <laijs@cn.fujitsu.com> Lai Jiangshan <laijs@cn.fujitsu.com>
@ -515,17 +531,21 @@ Loïc Damien <loic.damien@dzamlo.ch>
Luca Bruno <lucab@debian.org> Luca Bruno <lucab@debian.org>
Luis de Bethencourt <luis@debethencourt.com> Luis de Bethencourt <luis@debethencourt.com>
Luke Francl <look@recursion.org> Luke Francl <look@recursion.org>
Luke Gallagher <luke@hypergeometric.net>
Luke Metz <luke.metz@students.olin.edu> Luke Metz <luke.metz@students.olin.edu>
Luke Steensen <luke.steensen@gmail.com> Luke Steensen <luke.steensen@gmail.com>
Luqman Aden <me@luqman.ca> Luqman Aden <me@luqman.ca>
Łukasz Niemier <lukasz@niemier.pl>
Magnus Auvinen <magnus.auvinen@gmail.com> Magnus Auvinen <magnus.auvinen@gmail.com>
Mahmut Bulut <mahmutbulut0@gmail.com> Mahmut Bulut <mahmutbulut0@gmail.com>
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>
Marcel Rodrigues <marcelgmr@gmail.com> Marcel Rodrigues <marcelgmr@gmail.com>
Margaret Meyerhofer <mmeyerho@andrew.cmu.edu> Margaret Meyerhofer <mmeyerho@andrew.cmu.edu>
Marijn Haverbeke <marijnh@gmail.com> Marijn Haverbeke <marijnh@gmail.com>
Mark Lacey <641@rudkx.com> Mark Lacey <641@rudkx.com>
Mark Mossberg <mark.mossberg@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>
Mark Vian <mrv.caseus@gmail.com> Mark Vian <mrv.caseus@gmail.com>
@ -562,6 +582,7 @@ Maximilian Haack <mxhaack@gmail.com>
Maya Nitu <maya_nitu@yahoo.com> Maya Nitu <maya_nitu@yahoo.com>
Meyer S. Jacobs <meyermagic@gmail.com> Meyer S. Jacobs <meyermagic@gmail.com>
Micah Chalmer <micah@micahchalmer.net> Micah Chalmer <micah@micahchalmer.net>
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>
@ -581,9 +602,12 @@ Michael Sullivan <sully@msully.net>
Michael Williams <m.t.williams@live.com> Michael Williams <m.t.williams@live.com>
Michael Woerister <michaelwoerister@posteo> Michael Woerister <michaelwoerister@posteo>
Michael Zhou <moz@google.com> Michael Zhou <moz@google.com>
Michał Czardybon <mczard@poczta.onet.pl>
Michał Krasnoborski <mkrdln@gmail.com> Michał Krasnoborski <mkrdln@gmail.com>
Mick Koch <kchmck@gmail.com> Mick Koch <kchmck@gmail.com>
Mickaël Delahaye <mickael.delahaye@gmail.com> Mickaël Delahaye <mickael.delahaye@gmail.com>
Mickaël Raybaud-Roig <raybaudroigm@gmail.com>
Mickaël Salaün <mic@digikod.net>
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>
@ -594,28 +618,28 @@ Mikhail Zabaluev <mikhail.zabaluev@gmail.com>
Mikko Perttunen <cyndis@kapsi.fi> Mikko Perttunen <cyndis@kapsi.fi>
Ms2ger <ms2ger@gmail.com> Ms2ger <ms2ger@gmail.com>
Mukilan Thiagarajan <mukilanthiagarajan@gmail.com> Mukilan Thiagarajan <mukilanthiagarajan@gmail.com>
Mukilan Thiyagarajan <mukilanthiagarajan@gmail.com>
Murarth <murarth@gmail.com> Murarth <murarth@gmail.com>
Mátyás Mustoha <mmatyas@inf.u-szeged.hu> Mátyás Mustoha <mmatyas@inf.u-szeged.hu>
NAKASHIMA, Makoto <makoto.nksm+github@gmail.com>
NODA, Kai <nodakai@gmail.com> NODA, Kai <nodakai@gmail.com>
Nafis <nhoss2@gmail.com> Nafis <nhoss2@gmail.com>
Nathan Froyd <froydnj@gmail.com> Nathan Froyd <froydnj@gmail.com>
Nathan Stoddard <nstodda@purdue.edu> Nathan Stoddard <nstodda@purdue.edu>
Nathan Typanski <ntypanski@gmail.com> Nathan Typanski <ntypanski@gmail.com>
Nathan Wilson <wilnathan@gmail.com>
Nathan Zadoks <nathan@nathan7.eu> Nathan Zadoks <nathan@nathan7.eu>
Nathaniel Herman <nherman@college.harvard.edu> Nathaniel Herman <nherman@post.harvard.edu>
Nathaniel Theis <nttheis@gmail.com> Nathaniel Theis <nttheis@gmail.com>
Neil Pankey <npankey@gmail.com> Neil Pankey <npankey@gmail.com>
Nelson Chen <crazysim@gmail.com> Nelson Chen <crazysim@gmail.com>
NiccosSystem <niccossystem@gmail.com> NiccosSystem <niccossystem@gmail.com>
Nicholas <npmazzuca@gmail.com>
Nicholas Bishop <nicholasbishop@gmail.com> Nicholas Bishop <nicholasbishop@gmail.com>
Nicholas Mazzuca <npmazzuca@gmail.com> Nicholas Mazzuca <npmazzuca@gmail.com>
Nick Cameron <ncameron@mozilla.com> Nick Cameron <ncameron@mozilla.com>
Nick Desaulniers <ndesaulniers@mozilla.com> Nick Desaulniers <ndesaulniers@mozilla.com>
Nick Hamann <nick@wabbo.org>
Nick Howell <howellnick@gmail.com> Nick Howell <howellnick@gmail.com>
Nick Sarten <gen.battle@gmail.com> Nick Sarten <gen.battle@gmail.com>
Nick Platt <platt.nicholas@gmail.com>
Nicolas Silva <nical.silva@gmail.com> Nicolas Silva <nical.silva@gmail.com>
Niels Egberts <git@nielsegberts.nl> Niels Egberts <git@nielsegberts.nl>
Niels langager Ellegaard <niels.ellegaard@gmail.com> Niels langager Ellegaard <niels.ellegaard@gmail.com>
@ -625,9 +649,10 @@ Niklas Koep <niklas.koep@gmail.com>
Niko Matsakis <niko@alum.mit.edu> Niko Matsakis <niko@alum.mit.edu>
Noam Yorav-Raphael <noamraph@gmail.com> Noam Yorav-Raphael <noamraph@gmail.com>
Noufal Ibrahim <noufal@nibrahim.net.in> Noufal Ibrahim <noufal@nibrahim.net.in>
Oak <White-Oak@users.noreply.github.com>
O S K Chaitanya <osk@medhas.org> O S K Chaitanya <osk@medhas.org>
OGINO Masanori <masanori.ogino@gmail.com> OGINO Masanori <masanori.ogino@gmail.com>
Oliver Schneider <oliver.schneider@kit.edu> Oliver Schneider <github6541940@oli-obk.de>
Olivier Saut <osaut@airpost.net> Olivier Saut <osaut@airpost.net>
Olle Jonsson <olle.jonsson@gmail.com> Olle Jonsson <olle.jonsson@gmail.com>
Or Brostovski <tohava@gmail.com> Or Brostovski <tohava@gmail.com>
@ -635,6 +660,7 @@ Or Neeman <oneeman@gmail.com>
Oren Hazi <oren.hazi@gmail.com> Oren Hazi <oren.hazi@gmail.com>
Orpheus Lummis <o@orpheuslummis.com> Orpheus Lummis <o@orpheuslummis.com>
Orphée Lafond-Lummis <o@orftz.com> Orphée Lafond-Lummis <o@orftz.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>
@ -649,6 +675,7 @@ Paul Collier <paul@paulcollier.ca>
Paul Collins <paul@ondioline.org> Paul Collins <paul@ondioline.org>
Paul Crowley <paulcrowley@google.com> Paul Crowley <paulcrowley@google.com>
Paul Osborne <osbpau@gmail.com> Paul Osborne <osbpau@gmail.com>
Paul Quint <DrKwint@gmail.com>
Paul Stansifer <paul.stansifer@gmail.com> Paul Stansifer <paul.stansifer@gmail.com>
Paul Woolcock <pwoolcoc+github@gmail.com> Paul Woolcock <pwoolcoc+github@gmail.com>
Pavel Panchekha <me@pavpanchekha.com> Pavel Panchekha <me@pavpanchekha.com>
@ -656,7 +683,7 @@ Pawel Olzacki <p.olzacki2@samsung.com>
Pedro Larroy <pedro.larroy@here.com> Pedro Larroy <pedro.larroy@here.com>
Peer Aramillo Irizar <peer.aramillo.irizar@gmail.com> Peer Aramillo Irizar <peer.aramillo.irizar@gmail.com>
Peter Atashian <retep998@gmail.com> Peter Atashian <retep998@gmail.com>
Peter Elmers <peter.elmers@yahoo.com> Peter Elmers <peter.elmers@rice.edu>
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>
@ -674,12 +701,12 @@ 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>
Piotr Zolnierek <pz@anixe.pl> Piotr Zolnierek <pz@anixe.pl>
Poga Po <poga.bahamut@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>
Przemek 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>
Rafael Ávila de Espíndola <respindola@mozilla.com> Rafael Ávila de Espíndola <respindola@mozilla.com>
Rahul Horé <hore.rahul@gmail.com> Rahul Horé <hore.rahul@gmail.com>
@ -693,9 +720,9 @@ Raphael Speyer <rspeyer@gmail.com>
Raul Gutierrez S <rgs@itevenworks.net> Raul Gutierrez S <rgs@itevenworks.net>
Ray Clanan <rclanan@utopianconcept.com> Ray Clanan <rclanan@utopianconcept.com>
Reilly Watson <reillywatson@gmail.com> Reilly Watson <reillywatson@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>
Ricardo M. Correia <rcorreia@wizy.org> Ricardo M. Correia <rcorreia@wizy.org>
Ricardo Martins <ricardo@scarybox.net> Ricardo Martins <ricardo@scarybox.net>
@ -708,11 +735,13 @@ Rob Arnold <robarnold@cs.cmu.edu>
Rob Hoelz <rob@hoelz.ro> Rob Hoelz <rob@hoelz.ro>
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 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>
Robert Millar <robert.millar@cantab.net> Robert Millar <robert.millar@cantab.net>
Robin Gloster <robin@loc-com.de> Robin Gloster <robin@loc-com.de>
Robin Kruppe <robin.kruppe@gmail.com>
Robin Stocker <robin@nibor.org> Robin Stocker <robin@nibor.org>
Rohit Joshi <rohitjoshi@users.noreply.github.com> Rohit Joshi <rohitjoshi@users.noreply.github.com>
Roland Tanglao <roland@rolandtanglao.com> Roland Tanglao <roland@rolandtanglao.com>
@ -721,14 +750,13 @@ Rolf van de Krol <info@rolfvandekrol.nl>
Ron Dahlgren <ronald.dahlgren@gmail.com> Ron Dahlgren <ronald.dahlgren@gmail.com>
Roy Crihfield <rscrihf@gmail.com> Roy Crihfield <rscrihf@gmail.com>
Roy Frostig <rfrostig@mozilla.com> Roy Frostig <rfrostig@mozilla.com>
Russell <rpjohnst@gmail.com> Russell Johnston <rpjohnst@gmail.com>
Ruud van Asseldonk <dev@veniogames.com> Ruud van Asseldonk <dev@veniogames.com>
Ryan Levick <ryan@6wunderkinder.com> Ryan Levick <ryan@6wunderkinder.com>
Ryan Mulligan <ryan@ryantm.com> Ryan Mulligan <ryan@ryantm.com>
Ryan Prichard <ryan.prichard@gmail.com> Ryan Prichard <ryan.prichard@gmail.com>
Ryan Riginding <marc.riginding@gmail.com> Ryan Riginding <marc.riginding@gmail.com>
Ryan Scheel <ryan.havvy@gmail.com> Ryan Scheel <ryan.havvy@gmail.com>
Ryman <haqkrs@gmail.com>
Rüdiger Sonderfeld <ruediger@c-plusplus.de> Rüdiger Sonderfeld <ruediger@c-plusplus.de>
S Pradeep Kumar <gohanpra@gmail.com> S Pradeep Kumar <gohanpra@gmail.com>
Sae-bom Kim <sae-bom.kim@samsung.com> Sae-bom Kim <sae-bom.kim@samsung.com>
@ -744,6 +772,7 @@ Saurabh Anand <saurabhanandiit@gmail.com>
Scott Jenkins <scottdjwales@gmail.com> Scott Jenkins <scottdjwales@gmail.com>
Scott Lawrence <bytbox@gmail.com> Scott Lawrence <bytbox@gmail.com>
Scott Olson <scott@scott-olson.org> Scott Olson <scott@scott-olson.org>
Sean Bowe <ewillbefull@gmail.com>
Sean Chalmers <sclhiannan@gmail.com> Sean Chalmers <sclhiannan@gmail.com>
Sean Collins <sean@cllns.com> Sean Collins <sean@cllns.com>
Sean Gillespie <sean.william.g@gmail.com> Sean Gillespie <sean.william.g@gmail.com>
@ -798,16 +827,18 @@ Taylor Hutchison <seanthutchison@gmail.com>
Ted Horst <ted.horst@earthlink.net> Ted Horst <ted.horst@earthlink.net>
Tero Hänninen <lgvz@users.noreply.github.com> Tero Hänninen <lgvz@users.noreply.github.com>
Thad Guidry <thadguidry@gmail.com> Thad Guidry <thadguidry@gmail.com>
Theo Belaire <theo.belaire@gmail.com>
Thiago Carvalho <thiago.carvalho@westwing.de> Thiago Carvalho <thiago.carvalho@westwing.de>
Thiago Pontes <email@thiago.me> Thiago Pontes <email@thiago.me>
Thomas Backman <serenity@exscape.org> Thomas Backman <serenity@exscape.org>
Thomas Bracht Laumann Jespersen <laumann.thomas@gmail.com>
Thomas Daede <daede003@umn.edu> Thomas Daede <daede003@umn.edu>
Tiago Nobrega <tigarmo@gmail.com> Tiago Nobrega <tigarmo@gmail.com>
Tibor Benke <ihrwein@gmail.com>
Till Hoeppner <till@hoeppner.ws> 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 Joseph Dumol <tim@timdumol.com> Tim Joseph Dumol <tim@timdumol.com>
Tim Kuehn <tkuehn@cmu.edu> Tim Kuehn <tkuehn@cmu.edu>
Tim Parenti <timparenti@gmail.com> Tim Parenti <timparenti@gmail.com>
@ -835,7 +866,7 @@ Trinick <slicksilver555@mac.com>
Tristan Storch <tstorch@math.uni-bielefeld.de> Tristan Storch <tstorch@math.uni-bielefeld.de>
Tshepang Lekhonkhobe <tshepang@gmail.com> Tshepang Lekhonkhobe <tshepang@gmail.com>
Tuncer Ayaz <tuncer.ayaz@gmail.com> Tuncer Ayaz <tuncer.ayaz@gmail.com>
TyOverby <ty@pre-alpha.com> Ty Overby <ty@pre-alpha.com>
Tycho Sci <tychosci@gmail.com> Tycho Sci <tychosci@gmail.com>
Tyler Bindon <martica@martica.org> Tyler Bindon <martica@martica.org>
Tyler Thrailkill <tylerbthrailkill@gmail.com> Tyler Thrailkill <tylerbthrailkill@gmail.com>
@ -869,8 +900,10 @@ WebeWizard <webewizard@gmail.com>
Wendell Smith <wendell.smith@yale.edu> Wendell Smith <wendell.smith@yale.edu>
Wesley Wiser <wwiser@gmail.com> Wesley Wiser <wwiser@gmail.com>
Will <will@glozer.net> Will <will@glozer.net>
Will Hipschman <whipsch@gmail.com>
William Ting <io@williamting.com> William Ting <io@williamting.com>
Willson Mock <willson.mock@gmail.com> Willson Mock <willson.mock@gmail.com>
Xue Fuqiao <xfq.free@gmail.com>
Yasuhiro Fujii <y-fujii@mimosa-pudica.net> Yasuhiro Fujii <y-fujii@mimosa-pudica.net>
YawarRaza7349 <YawarRaza7349@gmail.com> YawarRaza7349 <YawarRaza7349@gmail.com>
Yazhong Liu <yorkiefixer@gmail.com> Yazhong Liu <yorkiefixer@gmail.com>
@ -888,27 +921,21 @@ Zack Slayton <zack.slayton@gmail.com>
Zbigniew Siciarz <zbigniew@siciarz.net> Zbigniew Siciarz <zbigniew@siciarz.net>
Ziad Hatahet <hatahet@gmail.com> Ziad Hatahet <hatahet@gmail.com>
Zooko Wilcox-O'Hearn <zooko@zooko.com> Zooko Wilcox-O'Hearn <zooko@zooko.com>
adridu59 <adri-from-59@hotmail.fr>
aochagavia <aochagavia92@gmail.com>
areski <areski@gmail.com>
arturo <arturo@openframeworks.cc> arturo <arturo@openframeworks.cc>
auREAX <mark@xn--hwg34fba.ws> auREAX <mark@xn--hwg34fba.ws>
awlnx <alecweber1994@gmail.com> awlnx <alecweber1994@gmail.com>
aydin.kim <aydin.kim@samsung.com> aydin.kim <aydin.kim@samsung.com>
b1nd <clint.ryan3@gmail.com>
bachm <Ab@vapor.com> bachm <Ab@vapor.com>
bcoopers <coopersmithbrian@gmail.com> bcoopers <coopersmithbrian@gmail.com>
blackbeam <aikorsky@gmail.com> Anatoly Ikorsky <aikorsky@gmail.com>
blake2-ppc <ulrik.sverdrup@gmail.com> blake2-ppc <ulrik.sverdrup@gmail.com>
bluss <bluss> bluss <bluss>
bombless <bombless@126.com>
bors <bors@rust-lang.org> bors <bors@rust-lang.org>
caipre <platt.nicholas@gmail.com>
chitra chitra
chromatic <chromatic@wgz.org> chromatic <chromatic@wgz.org>
comex <comexk@gmail.com> comex <comexk@gmail.com>
crhino <piraino.chris@gmail.com> crhino <piraino.chris@gmail.com>
dan@daramos.com <dan@daramos.com> Daniel Ramos <dan@daramos.com>
darkf <lw9k123@gmail.com> darkf <lw9k123@gmail.com>
defuz <defuz.net@gmail.com> defuz <defuz.net@gmail.com>
dgoon <dgoon@dgoon.net> dgoon <dgoon@dgoon.net>
@ -916,6 +943,7 @@ donkopotamus <general@chocolate-fish.com>
eliovir <eliovir@gmail.com> eliovir <eliovir@gmail.com>
elszben <notgonna@tellyou> elszben <notgonna@tellyou>
emanueLczirai <emanueLczirai@cryptoLab.net> emanueLczirai <emanueLczirai@cryptoLab.net>
fenduru <fenduru@users.noreply.github.com>
flo-l <lacknerflo@gmail.com> flo-l <lacknerflo@gmail.com>
fort <e@mail.com> fort <e@mail.com>
free-Runner <aali07@students.poly.edu> free-Runner <aali07@students.poly.edu>
@ -923,17 +951,13 @@ g3xzh <g3xzh@yahoo.com>
gamazeps <gamaz3ps@gmail.com> gamazeps <gamaz3ps@gmail.com>
gareth <gareth@gareth-N56VM.(none)> gareth <gareth@gareth-N56VM.(none)>
gentlefolk <cemacken@gmail.com> gentlefolk <cemacken@gmail.com>
gifnksm <makoto.nksm@gmail.com> github-monoculture <eocene@gmx.com>
hansjorg <hansjorg@gmail.com> hansjorg <hansjorg@gmail.com>
iancormac84 <wilnathan@gmail.com>
inrustwetrust <inrustwetrust@users.noreply.github.com>
jamesluke <jamesluke@users.noreply.github.com> jamesluke <jamesluke@users.noreply.github.com>
jatinn <jatinn@users.noreply.github.com> jatinn <jatinn@users.noreply.github.com>
jbranchaud <jbranchaud@gmail.com> jbranchaud <jbranchaud@gmail.com>
jfager <jfager@gmail.com>
jmgrosen <jmgrosen@gmail.com> jmgrosen <jmgrosen@gmail.com>
jmu303 <muj@bc.edu> jmu303 <muj@bc.edu>
joaoxsouls <joaoxsouls@gmail.com>
jrincayc <jrincayc@users.noreply.github.com> jrincayc <jrincayc@users.noreply.github.com>
juxiliary <juxiliary@gmail.com> juxiliary <juxiliary@gmail.com>
jxv <joevargas@hush.com> jxv <joevargas@hush.com>
@ -941,15 +965,12 @@ kgv <mail@kgv.name>
kjpgit <kjpgit@users.noreply.github.com> kjpgit <kjpgit@users.noreply.github.com>
klutzy <klutzytheklutzy@gmail.com> klutzy <klutzytheklutzy@gmail.com>
korenchkin <korenchkin2@gmail.com> korenchkin <korenchkin2@gmail.com>
kud1ing <github@kudling.de>
kulakowski <george.kulakowski@gmail.com> kulakowski <george.kulakowski@gmail.com>
kvark <kvarkus@gmail.com>
kwantam <kwantam@gmail.com> kwantam <kwantam@gmail.com>
lpy <pylaurent1314@gmail.com> lpy <pylaurent1314@gmail.com>
lucy <ne.tetewi@gmail.com> lucy <ne.tetewi@gmail.com>
lummax <luogpg@googlemail.com> lummax <luogpg@googlemail.com>
lyuts <dioxinu@gmail.com> lyuts <dioxinu@gmail.com>
m-r-r <raybaudroigm@gmail.com>
madmalik <matthias.tellen@googlemail.com> madmalik <matthias.tellen@googlemail.com>
maikklein <maikklein@googlemail.com> maikklein <maikklein@googlemail.com>
masklinn <github.com@masklinn.net> masklinn <github.com@masklinn.net>
@ -961,21 +982,20 @@ mr.Shu <mr@shu.io>
mrec <mike.capp@gmail.com> mrec <mike.capp@gmail.com>
musitdev <philippe.delrieu@free.fr> musitdev <philippe.delrieu@free.fr>
nathan dotz <nathan.dotz@gmail.com> nathan dotz <nathan.dotz@gmail.com>
nham <hamann.nick@gmail.com> Nils Winter <nils.winter@gmail.com>
niftynif <nif.ward@gmail.com>
noam <noam@clusterfoo.com> noam <noam@clusterfoo.com>
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>
oli-obk <github6541940@oli-obk.de>
olivren <o.renaud@gmx.fr> olivren <o.renaud@gmx.fr>
osa1 <omeragacan@gmail.com> osa1 <omeragacan@gmail.com>
pez <james.austin.perry@gmail.com>
posixphreak <posixphreak@gmail.com> posixphreak <posixphreak@gmail.com>
qwitwa <qwitwa@gmail.com> qwitwa <qwitwa@gmail.com>
ray glover <ray@rayglover.net> ray glover <ray@rayglover.net>
reedlepee <reedlepee123@gmail.com> reedlepee <reedlepee123@gmail.com>
reus <reusee@ymail.com> reus <reusee@ymail.com>
rjz <rj@rjzaworski.com> rjz <rj@rjzaworski.com>
rundrop1 <rundrop1@zoho.com>
sevrak <sevrak@rediffmail.com> sevrak <sevrak@rediffmail.com>
sheroze1123 <mss385@cornell.edu> sheroze1123 <mss385@cornell.edu>
smenardpw <sebastien@knoglr.com> smenardpw <sebastien@knoglr.com>
@ -989,13 +1009,9 @@ tinaun <tinagma@gmail.com>
tshakah <tshakah@gmail.com> tshakah <tshakah@gmail.com>
ville-h <ville3.14159@gmail.com> ville-h <ville3.14159@gmail.com>
visualfc <visualfc@gmail.com> visualfc <visualfc@gmail.com>
we <vadim.petrochenkov@gmail.com>
whataloadofwhat <unusualmoniker@gmail.com> whataloadofwhat <unusualmoniker@gmail.com>
wickerwaka <martin.donlon@gmail.com> wickerwaka <martin.donlon@gmail.com>
wonyong kim <wonyong.kim@samsung.com> wonyong kim <wonyong.kim@samsung.com>
xales <xales@naveria.com> xales <xales@naveria.com>
zofrex <zofrex@gmail.com> zofrex <zofrex@gmail.com>
zslayton <zack.slayton@gmail.com>
zzmp <zmp@umich.edu>
Łukasz Niemier <lukasz@niemier.pl>
克雷 <geekcraik@users.noreply.github.com> 克雷 <geekcraik@users.noreply.github.com>

View File

@ -1,79 +1,142 @@
Version 1.0.0-beta (April 2015) Version 1.0.0 (May 2015)
------------------------------------- ========================
* ~1100 changes, numerous bugfixes * ~1500 changes, numerous bugfixes
* Highlights Highlights
----------
* The big news is that the vast majority of the standard library * The vast majority of the standard library is now `#[stable]`. It is
is now `#[stable]` -- 75% of the non-deprecated API surface at no longer possible to use unstable features with a stable build of
last count. Numerous crates are now running on stable the compiler.
Rust. Starting with this release, it is not possible to use * Many popular crates on [crates.io] now work on the stable release
unstable features on a stable build. channel.
* Arithmetic on basic integer types now * Arithmetic on basic integer types now [checks for overflow in debug
[checks for overflow in debug builds][overflow]. builds][overflow].
* Language Language
--------
* [`Send` no longer implies `'static`][send-rfc], which made * Several [restrictions have been added to trait coherence][coh] in
possible the [`thread::scoped` API][scoped]. Scoped threads can order to make it easier for upstream authors to change traits
borrow data from their parent's stack frame -- safely! without breaking downsteam code.
* [UFCS now supports trait-less associated paths][moar-ufcs] like * Digits of binary and octal literals are [lexed more eagerly][lex] to
`MyType::default()`. improve error messages and macro behavior. For example, `0b1234` is
* Primitive types [now have inherent methods][prim-inherent], now lexed as `0b1234` instead of two tokens, `0b1` and `234`.
obviating the need for extension traits like `SliceExt`. * Trait bounds [are always invariant][inv], eleminating the need for
* Methods with `Self: Sized` in their `where` clause are the `PhantomFn` and `MarkerTrait` lang items, which have been
[considered object-safe][self-sized], allowing many extension removed.
traits like `IteratorExt` to be merged into the traits they * ["-" is no longer a valid character in crate names][cr], the `extern crate
extended. "foo" as bar` syntax has been replaced with `extern crate foo as
* You can now [refer to associated types][assoc-where] whose bar`, and Cargo now automatically translates "-" in *package* names
corresponding trait bounds appear only in a `where` clause. to underscore for the crate name.
* The final bits of [OIBIT landed][oibit-final], meaning that * [Lifetime shadowing is an error][lt].
traits like `Send` and `Sync` are now library-defined. * [`Send` no longer implies `'static`][send-rfc].
* A [Reflect trait][reflect] was introduced, which means that * [UFCS now supports trait-less associated paths][moar-ufcs] like
downcasting via the `Any` trait is effectively limited to `MyType::default()`.
concrete types. This helps retain the potentially-important * Primitive types [now have inherent methods][prim-inherent],
"parametricity" property: generic code cannot behave differently obviating the need for extension traits like `SliceExt`.
for different type arguments except in minor ways. * Methods with `Self: Sized` in their `where` clause are [considered
* The `unsafe_destructor` feature is now deprecated in favor of object-safe][self-sized], allowing many extension traits like
the [new `dropck`][dropck]. This change is a major reduction in `IteratorExt` to be merged into the traits they extended.
unsafe code. * You can now [refer to associated types][assoc-where] whose
* Trait coherence was [revised again][fundamental], this time with corresponding trait bounds appear only in a `where` clause.
an eye toward API evolution over time. * The final bits of [OIBIT landed][oibit-final], meaning that traits
like `Send` and `Sync` are now library-defined.
* A [Reflect trait][reflect] was introduced, which means that
downcasting via the `Any` trait is effectively limited to concrete
types. This helps retain the potentially-important "parametricity"
property: generic code cannot behave differently for different type
arguments except in minor ways.
* The `unsafe_destructor` feature is now deprecated in favor of the
[new `dropck`][dropck]. This change is a major reduction in unsafe
code.
* Libraries Libraries
---------
* The new path and IO modules are complete and `#[stable]`. This * The `thread_local` module [has been renamed to `std::thread`][th].
was the major library focus for this cycle. * The methods of `IteratorExt` [have been moved to the `Iterator`
* The path API was [revised][path-normalize] to normalize `.`, trait itself][ie].
adjusting the tradeoffs in favor of the most common usage. * Several traits that implement Rust's conventions for type
* A large number of remaining APIs in `std` were also stabilized conversions, `AsMut`, `AsRef`, `From`, and `Into` have been
during this cycle; about 75% of the non-deprecated API surface [centralized in the `std::convert` module][con].
is now stable. * The `FromError` trait [was removed in favor of `From`][fe].
* The new [string pattern API][string-pattern] landed, which makes * The basic sleep function [has moved to
the string slice API much more internally consistent and flexible. `std::thread::sleep_ms`][slp].
* A shiny [framework for Debug implementations][debug-builder] landed. * The `splitn` function now takes an `n` parameter that represents the
This makes it possible to opt in to "pretty-printed" debugging output. number of items yielded by the returned iterator [instead of the
* A new set of [generic conversion traits][conversion] replaced number of 'splits'][spl].
many existing ad hoc traits. * [On Unix, all file descriptors are `CLOEXEC` by default][clo].
* Generic numeric traits were * [Derived implementations of `PartialOrd` now order enums according
[completely removed][num-traits]. This was made possible thanks to their explicitly-assigned discriminants][po].
to inherent methods for primitive types, and the removal gives * [Methods for searching strings are generic over `Pattern`s][pat],
maximal flexibility for designing a numeric hierarchy in the future. implemented presently by `&char`, `&str`, `FnMut(char) -> bool` and
* The `Fn` traits are now related via [inheritance][fn-inherit] some others.
and provide ergonomic [blanket implementations][fn-blanket]. * [In method resolution, object methods are resolved before inherent
* The `Index` and `IndexMut` traits were changed to methods][meth].
[take the index by value][index-value], enabling code like * [`String::from_str` has been deprecated in favor of the `From` impl,
`hash_map["string"]` to work. `String::from`][sf].
* `Copy` now [inherits][copy-clone] from `Clone`, meaning that all * [`io::Error` implements `Sync`][ios].
`Copy` data is known to be `Clone` as well. * [The `words` method on `&str` has been replaced with
`split_whitespace`][sw], to avoid answering the tricky question, 'what is
a word?'
* The new path and IO modules are complete and `#[stable]`. This
was the major library focus for this cycle.
* The path API was [revised][path-normalize] to normalize `.`,
adjusting the tradeoffs in favor of the most common usage.
* A large number of remaining APIs in `std` were also stabilized
during this cycle; about 75% of the non-deprecated API surface
is now stable.
* The new [string pattern API][string-pattern] landed, which makes
the string slice API much more internally consistent and flexible.
* A new set of [generic conversion traits][conversion] replaced
many existing ad hoc traits.
* Generic numeric traits were [completely removed][num-traits]. This
was made possible thanks to inherent methods for primitive types,
and the removal gives maximal flexibility for designing a numeric
hierarchy in the future.
* The `Fn` traits are now related via [inheritance][fn-inherit]
and provide ergonomic [blanket implementations][fn-blanket].
* The `Index` and `IndexMut` traits were changed to
[take the index by value][index-value], enabling code like
`hash_map["string"]` to work.
* `Copy` now [inherits][copy-clone] from `Clone`, meaning that all
`Copy` data is known to be `Clone` as well.
* Infrastructure Misc
----
* Metadata was tuned, shrinking binaries [by 27%][metadata-shrink]. * Many errors now have extended explanations that can be accessed with
* Much headway was made on ecosystem-wide CI, making it possible the `--explain` flag to `rustc`.
to [compare builds for breakage][ci-compare]. * Many new examples have been added to the standard library
documentation.
* rustdoc has received a number of improvements focused on completion
and polish.
* Metadata was tuned, shrinking binaries [by 27%][metadata-shrink].
* Much headway was made on ecosystem-wide CI, making it possible
to [compare builds for breakage][ci-compare].
[crates.io]: http://crates.io
[clo]: https://github.com/rust-lang/rust/pull/24034
[coh]: https://github.com/rust-lang/rfcs/blob/master/text/1023-rebalancing-coherence.md
[con]: https://github.com/rust-lang/rust/pull/23875
[cr]: https://github.com/rust-lang/rust/pull/23419
[fe]: https://github.com/rust-lang/rust/pull/23879
[ie]: https://github.com/rust-lang/rust/pull/23300
[inv]: https://github.com/rust-lang/rust/pull/23938
[ios]: https://github.com/rust-lang/rust/pull/24133
[lex]: https://github.com/rust-lang/rfcs/blob/master/text/0879-small-base-lexing.md
[lt]: https://github.com/rust-lang/rust/pull/24057
[meth]: https://github.com/rust-lang/rust/pull/24056
[pat]: https://github.com/rust-lang/rfcs/blob/master/text/0528-string-patterns.md
[po]: https://github.com/rust-lang/rust/pull/24270
[sf]: https://github.com/rust-lang/rust/pull/24517
[slp]: https://github.com/rust-lang/rust/pull/23949
[spl]: https://github.com/rust-lang/rfcs/blob/master/text/0979-align-splitn-with-other-languages.md
[sw]: https://github.com/rust-lang/rfcs/blob/master/text/1054-str-words.md
[th]: https://github.com/rust-lang/rfcs/blob/master/text/0909-move-thread-local-to-std-thread.md
[send-rfc]: https://github.com/rust-lang/rfcs/blob/master/text/0458-send-improvements.md [send-rfc]: https://github.com/rust-lang/rfcs/blob/master/text/0458-send-improvements.md
[scoped]: http://static.rust-lang.org/doc/master/std/thread/fn.scoped.html [scoped]: http://static.rust-lang.org/doc/master/std/thread/fn.scoped.html
[moar-ufcs]: https://github.com/rust-lang/rust/pull/22172 [moar-ufcs]: https://github.com/rust-lang/rust/pull/22172
@ -97,6 +160,7 @@ Version 1.0.0-beta (April 2015)
[copy-clone]: https://github.com/rust-lang/rust/pull/23860 [copy-clone]: https://github.com/rust-lang/rust/pull/23860
[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 (February 2015)
------------------------------------- -------------------------------------

View File

@ -18,7 +18,7 @@ CFG_RELEASE_NUM=1.0.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=.3 CFG_PRERELEASE_VERSION=.5
CFG_FILENAME_EXTRA=4e7c5e5c CFG_FILENAME_EXTRA=4e7c5e5c

View File

@ -226,7 +226,7 @@ pub fn run_tests(config: &Config) {
} }
// android debug-info test uses remote debugger // android debug-info test uses remote debugger
// so, we test 1 task at once. // so, we test 1 thread at once.
// also trying to isolate problems with adb_run_wrapper.sh ilooping // also trying to isolate problems with adb_run_wrapper.sh ilooping
env::set_var("RUST_TEST_THREADS","1"); env::set_var("RUST_TEST_THREADS","1");
} }
@ -234,7 +234,7 @@ pub fn run_tests(config: &Config) {
match config.mode { match config.mode {
DebugInfoLldb => { DebugInfoLldb => {
// Some older versions of LLDB seem to have problems with multiple // Some older versions of LLDB seem to have problems with multiple
// instances running in parallel, so only run one test task at a // instances running in parallel, so only run one test thread at a
// time. // time.
env::set_var("RUST_TEST_THREADS", "1"); env::set_var("RUST_TEST_THREADS", "1");
} }

View File

@ -96,7 +96,7 @@ code should need to run is a stack.
possibility is covered by the `match`, adding further variants to the `enum` possibility is covered by the `match`, adding further variants to the `enum`
in the future will prompt a compilation failure, rather than runtime panic. in the future will prompt a compilation failure, rather than runtime panic.
Second, it makes cost explicit. In general, the only safe way to have a Second, it makes cost explicit. In general, the only safe way to have a
non-exhaustive match would be to panic the task if nothing is matched, though non-exhaustive match would be to panic the thread if nothing is matched, though
it could fall through if the type of the `match` expression is `()`. This sort it could fall through if the type of the `match` expression is `()`. This sort
of hidden cost and special casing is against the language's philosophy. It's of hidden cost and special casing is against the language's philosophy. It's
easy to ignore certain cases by using the `_` wildcard: easy to ignore certain cases by using the `_` wildcard:

View File

@ -62,15 +62,15 @@ Data values in the language can only be constructed through a fixed set of initi
* There is no global inter-crate namespace; all name management occurs within a crate. * There is no global inter-crate namespace; all name management occurs within a crate.
* Using another crate binds the root of _its_ namespace into the user's namespace. * Using another crate binds the root of _its_ namespace into the user's namespace.
## Why is panic unwinding non-recoverable within a task? Why not try to "catch exceptions"? ## Why is panic unwinding non-recoverable within a thread? Why not try to "catch exceptions"?
In short, because too few guarantees could be made about the dynamic environment of the catch block, as well as invariants holding in the unwound heap, to be able to safely resume; we believe that other methods of signalling and logging errors are more appropriate, with tasks playing the role of a "hard" isolation boundary between separate heaps. In short, because too few guarantees could be made about the dynamic environment of the catch block, as well as invariants holding in the unwound heap, to be able to safely resume; we believe that other methods of signalling and logging errors are more appropriate, with threads playing the role of a "hard" isolation boundary between separate heaps.
Rust provides, instead, three predictable and well-defined options for handling any combination of the three main categories of "catch" logic: Rust provides, instead, three predictable and well-defined options for handling any combination of the three main categories of "catch" logic:
* Failure _logging_ is done by the integrated logging subsystem. * Failure _logging_ is done by the integrated logging subsystem.
* _Recovery_ after a panic is done by trapping a task panic from _outside_ * _Recovery_ after a panic is done by trapping a thread panic from _outside_
the task, where other tasks are known to be unaffected. the thread, where other threads are known to be unaffected.
* _Cleanup_ of resources is done by RAII-style objects with destructors. * _Cleanup_ of resources is done by RAII-style objects with destructors.
Cleanup through RAII-style destructors is more likely to work than in catch blocks anyways, since it will be better tested (part of the non-error control paths, so executed all the time). Cleanup through RAII-style destructors is more likely to work than in catch blocks anyways, since it will be better tested (part of the non-error control paths, so executed all the time).
@ -91,8 +91,8 @@ We don't know if there's an obvious, easy, efficient, stock-textbook way of supp
There's a lot of debate on this topic; it's easy to find a proponent of default-sync or default-async communication, and there are good reasons for either. Our choice rests on the following arguments: There's a lot of debate on this topic; it's easy to find a proponent of default-sync or default-async communication, and there are good reasons for either. Our choice rests on the following arguments:
* Part of the point of isolating tasks is to decouple tasks from one another, such that assumptions in one task do not cause undue constraints (or bugs, if violated!) in another. Temporal coupling is as real as any other kind; async-by-default relaxes the default case to only _causal_ coupling. * Part of the point of isolating threads is to decouple threads from one another, such that assumptions in one thread do not cause undue constraints (or bugs, if violated!) in another. Temporal coupling is as real as any other kind; async-by-default relaxes the default case to only _causal_ coupling.
* Default-async supports buffering and batching communication, reducing the frequency and severity of task-switching and inter-task / inter-domain synchronization. * Default-async supports buffering and batching communication, reducing the frequency and severity of thread-switching and inter-thread / inter-domain synchronization.
* Default-async with transmittable channels is the lowest-level building block on which more-complex synchronization topologies and strategies can be built; it is not clear to us that the majority of cases fit the 2-party full-synchronization pattern rather than some more complex multi-party or multi-stage scenario. We did not want to force all programs to pay for wiring the former assumption into all communications. * Default-async with transmittable channels is the lowest-level building block on which more-complex synchronization topologies and strategies can be built; it is not clear to us that the majority of cases fit the 2-party full-synchronization pattern rather than some more complex multi-party or multi-stage scenario. We did not want to force all programs to pay for wiring the former assumption into all communications.
## Why are channels half-duplex (one-way)? ## Why are channels half-duplex (one-way)?

View File

@ -5,8 +5,7 @@
This document is the primary reference for the Rust programming language grammar. It This document is the primary reference for the Rust programming language grammar. It
provides only one kind of material: provides only one kind of material:
- Chapters that formally define the language grammar and, for each - Chapters that formally define the language grammar.
construct.
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
@ -97,12 +96,16 @@ explicit codepoint lists. [^inputformat]
## Special Unicode Productions ## Special Unicode Productions
The following productions in the Rust grammar are defined in terms of Unicode The following productions in the Rust grammar are defined in terms of Unicode
properties: `ident`, `non_null`, `non_star`, `non_eol`, `non_slash_or_star`, properties: `ident`, `non_null`, `non_eol`, `non_single_quote` and
`non_single_quote` and `non_double_quote`. `non_double_quote`.
### Identifiers ### Identifiers
The `ident` production is any nonempty Unicode string of the following form: The `ident` production is any nonempty Unicode[^non_ascii_idents] string of
the following form:
[^non_ascii_idents]: Non-ASCII characters in identifiers are currently feature
gated. This is expected to improve soon.
- The first character has property `XID_start` - The first character has property `XID_start`
- The remaining characters have property `XID_continue` - The remaining characters have property `XID_continue`
@ -119,8 +122,6 @@ Some productions are defined by exclusion of particular Unicode characters:
- `non_null` is any single Unicode character aside from `U+0000` (null) - `non_null` is any single Unicode character aside from `U+0000` (null)
- `non_eol` is `non_null` restricted to exclude `U+000A` (`'\n'`) - `non_eol` is `non_null` restricted to exclude `U+000A` (`'\n'`)
- `non_star` is `non_null` restricted to exclude `U+002A` (`*`)
- `non_slash_or_star` is `non_null` restricted to exclude `U+002F` (`/`) and `U+002A` (`*`)
- `non_single_quote` is `non_null` restricted to exclude `U+0027` (`'`) - `non_single_quote` is `non_null` restricted to exclude `U+0027` (`'`)
- `non_double_quote` is `non_null` restricted to exclude `U+0022` (`"`) - `non_double_quote` is `non_null` restricted to exclude `U+0022` (`"`)
@ -153,19 +154,19 @@ token : simple_token | ident | literal | symbol | whitespace token ;
<p id="keyword-table-marker"></p> <p id="keyword-table-marker"></p>
| | | | | | | | | | | |
|----------|----------|----------|----------|--------| |----------|----------|----------|----------|---------|
| abstract | alignof | as | become | box | | abstract | alignof | as | become | box |
| break | const | continue | crate | do | | break | const | continue | crate | do |
| else | enum | extern | false | final | | else | enum | extern | false | final |
| fn | for | if | impl | in | | fn | for | if | impl | in |
| let | loop | match | mod | move | | let | loop | macro | match | mod |
| mut | offsetof | once | override | priv | | move | mut | offsetof | override | priv |
| proc | pub | pure | ref | return | | proc | pub | pure | ref | return |
| sizeof | static | self | struct | super | | Self | self | sizeof | static | struct |
| true | trait | type | typeof | unsafe | | super | trait | true | type | typeof |
| unsized | use | virtual | where | while | | unsafe | unsized | use | virtual | where |
| yield | | | | | | while | yield | | | |
Each of these keywords has special meaning in its grammar, and all of them are Each of these keywords has special meaning in its grammar, and all of them are
@ -175,9 +176,15 @@ excluded from the `ident` rule.
```antlr ```antlr
lit_suffix : ident; lit_suffix : ident;
literal : [ string_lit | char_lit | byte_string_lit | byte_lit | num_lit ] lit_suffix ?; literal : [ string_lit | char_lit | byte_string_lit | byte_lit | num_lit | bool_lit ] lit_suffix ?;
``` ```
The optional `lit_suffix` production is only used for certain numeric literals,
but is reserved for future extension. That is, the above gives the lexical
grammar, but a Rust parser will reject everything but the 12 special cases
mentioned in [Number literals](reference.html#number-literals) in the
reference.
#### Character and string literals #### Character and string literals
```antlr ```antlr
@ -237,14 +244,16 @@ dec_lit : [ dec_digit | '_' ] + ;
#### Boolean literals #### Boolean literals
**FIXME:** write grammar ```antlr
bool_lit : [ "true" | "false" ] ;
```
The two values of the boolean type are written `true` and `false`. The two values of the boolean type are written `true` and `false`.
### Symbols ### Symbols
```antlr ```antlr
symbol : "::" "->" symbol : "::" | "->"
| '#' | '[' | ']' | '(' | ')' | '{' | '}' | '#' | '[' | ']' | '(' | ')' | '{' | '}'
| ',' | ';' ; | ',' | ';' ;
``` ```
@ -295,8 +304,8 @@ transcriber : '(' transcriber * ')' | '[' transcriber * ']'
## Items ## Items
```antlr ```antlr
item : mod_item | fn_item | type_item | struct_item | enum_item item : vis ? mod_item | fn_item | type_item | struct_item | enum_item
| static_item | trait_item | impl_item | extern_block ; | const_item | static_item | trait_item | impl_item | extern_block ;
``` ```
### Type Parameters ### Type Parameters
@ -313,27 +322,27 @@ mod : [ view_item | item ] * ;
#### View items #### View items
```antlr ```antlr
view_item : extern_crate_decl | use_decl ; view_item : extern_crate_decl | use_decl ';' ;
``` ```
##### Extern crate declarations ##### Extern crate declarations
```antlr ```antlr
extern_crate_decl : "extern" "crate" crate_name extern_crate_decl : "extern" "crate" crate_name
crate_name: ident | ( string_lit as ident ) crate_name: ident | ( ident "as" ident )
``` ```
##### Use declarations ##### Use declarations
```antlr ```antlr
use_decl : "pub" ? "use" [ path "as" ident use_decl : vis ? "use" [ path "as" ident
| path_glob ] ; | path_glob ] ;
path_glob : ident [ "::" [ path_glob path_glob : ident [ "::" [ path_glob
| '*' ] ] ? | '*' ] ] ?
| '{' path_item [ ',' path_item ] * '}' ; | '{' path_item [ ',' path_item ] * '}' ;
path_item : ident | "mod" ; path_item : ident | "self" ;
``` ```
### Functions ### Functions
@ -368,6 +377,10 @@ path_item : ident | "mod" ;
**FIXME:** grammar? **FIXME:** grammar?
### Enumerations
**FIXME:** grammar?
### Constant items ### Constant items
```antlr ```antlr
@ -401,16 +414,17 @@ extern_block : [ foreign_fn ] * ;
## Visibility and Privacy ## Visibility and Privacy
**FIXME:** grammar? ```antlr
vis : "pub" ;
```
### Re-exporting and Visibility ### Re-exporting and Visibility
**FIXME:** grammar? See [Use declarations](#use-declarations).
## Attributes ## Attributes
```antlr ```antlr
attribute : "#!" ? '[' meta_item ']' ; attribute : '#' '!' ? '[' meta_item ']' ;
meta_item : ident [ '=' literal meta_item : ident [ '=' literal
| '(' meta_seq ')' ] ? ; | '(' meta_seq ')' ] ? ;
meta_seq : meta_item [ ',' meta_seq ] ? ; meta_seq : meta_item [ ',' meta_seq ] ? ;
@ -420,28 +434,21 @@ meta_seq : meta_item [ ',' meta_seq ] ? ;
## Statements ## Statements
**FIXME:** grammar? ```antlr
stmt : decl_stmt | expr_stmt ;
```
### Declaration statements ### Declaration statements
**FIXME:** grammar? ```antlr
decl_stmt : item | let_decl ;
A _declaration statement_ is one that introduces one or more *names* into the ```
enclosing statement block. The declared names may denote new slots or new
items.
#### Item declarations #### Item declarations
**FIXME:** grammar? See [Items](#items).
An _item declaration statement_ has a syntactic form identical to an #### Variable declarations
[item](#items) declaration within a module. Declaring an item &mdash; a
function, enumeration, structure, type, static, trait, implementation or module
&mdash; locally within a statement block is simply a way of restricting its
scope to a narrow region containing all of its uses; it is otherwise identical
in meaning to declaring the item outside the statement block.
#### Slot declarations
```antlr ```antlr
let_decl : "let" pat [':' type ] ? [ init ] ? ';' ; let_decl : "let" pat [':' type ] ? [ init ] ? ';' ;
@ -450,11 +457,21 @@ init : [ '=' ] expr ;
### Expression statements ### Expression statements
**FIXME:** grammar? ```antlr
expr_stmt : expr ';' ;
```
## Expressions ## Expressions
**FIXME:** grammar? ```antlr
expr : literal | path | tuple_expr | unit_expr | struct_expr
| block_expr | method_call_expr | field_expr | array_expr
| idx_expr | range_expr | unop_expr | binop_expr
| paren_expr | call_expr | lambda_expr | while_expr
| loop_expr | break_expr | continue_expr | for_expr
| if_expr | match_expr | if_let_expr | while_let_expr
| return_expr ;
```
#### Lvalues, rvalues and temporaries #### Lvalues, rvalues and temporaries
@ -466,19 +483,23 @@ init : [ '=' ] expr ;
### Literal expressions ### Literal expressions
**FIXME:** grammar? See [Literals](#literals).
### Path expressions ### Path expressions
**FIXME:** grammar? See [Paths](#paths).
### Tuple expressions ### Tuple expressions
**FIXME:** grammar? ```antlr
tuple_expr : '(' [ expr [ ',' expr ] * | expr ',' ] ? ')' ;
```
### Unit expressions ### Unit expressions
**FIXME:** grammar? ```antlr
unit_expr : "()" ;
```
### Structure expressions ### Structure expressions
@ -494,8 +515,7 @@ struct_expr : expr_path '{' ident ':' expr
### Block expressions ### Block expressions
```antlr ```antlr
block_expr : '{' [ view_item ] * block_expr : '{' [ stmt ';' | item ] *
[ stmt ';' | item ] *
[ expr ] '}' ; [ expr ] '}' ;
``` ```
@ -516,7 +536,7 @@ field_expr : expr '.' ident ;
```antlr ```antlr
array_expr : '[' "mut" ? array_elems? ']' ; array_expr : '[' "mut" ? array_elems? ']' ;
array_elems : [expr [',' expr]*] | [expr ',' ".." expr] ; array_elems : [expr [',' expr]*] | [expr ';' expr] ;
``` ```
### Index expressions ### Index expressions
@ -525,68 +545,72 @@ array_elems : [expr [',' expr]*] | [expr ',' ".." expr] ;
idx_expr : expr '[' expr ']' ; idx_expr : expr '[' expr ']' ;
``` ```
### Range expressions
```antlr
range_expr : expr ".." expr |
expr ".." |
".." expr |
".." ;
```
### Unary operator expressions ### Unary operator expressions
**FIXME:** grammar? ```antlr
unop_expr : unop expr ;
unop : '-' | '*' | '!' ;
```
### Binary operator expressions ### Binary operator expressions
```antlr ```antlr
binop_expr : expr binop expr ; binop_expr : expr binop expr | type_cast_expr
| assignment_expr | compound_assignment_expr ;
binop : arith_op | bitwise_op | lazy_bool_op | comp_op
``` ```
#### Arithmetic operators #### Arithmetic operators
**FIXME:** grammar? ```antlr
arith_op : '+' | '-' | '*' | '/' | '%' ;
```
#### Bitwise operators #### Bitwise operators
**FIXME:** grammar? ```antlr
bitwise_op : '&' | '|' | '^' | "<<" | ">>" ;
```
#### Lazy boolean operators #### Lazy boolean operators
**FIXME:** grammar? ```antlr
lazy_bool_op : "&&" | "||" ;
```
#### Comparison operators #### Comparison operators
**FIXME:** grammar? ```antlr
comp_op : "==" | "!=" | '<' | '>' | "<=" | ">=" ;
```
#### Type cast expressions #### Type cast expressions
**FIXME:** grammar? ```antlr
type_cast_expr : value "as" type ;
```
#### Assignment expressions #### Assignment expressions
**FIXME:** grammar? ```antlr
assignment_expr : expr '=' expr ;
```
#### Compound assignment expressions #### Compound assignment expressions
**FIXME:** grammar? ```antlr
compound_assignment_expr : expr [ arith_op | bitwise_op ] '=' expr ;
#### Operator precedence
The precedence of Rust binary operators is ordered as follows, going from
strong to weak:
```text
* / %
as
+ -
<< >>
&
^
|
< > <= >=
== !=
&&
||
=
``` ```
Operators at the same precedence level are evaluated left-to-right. [Unary
operators](#unary-operator-expressions) have the same precedence level and it
is stronger than any of the binary operators'.
### Grouped expressions ### Grouped expressions
```antlr ```antlr
@ -611,7 +635,7 @@ lambda_expr : '|' ident_list '|' expr ;
### While loops ### While loops
```antlr ```antlr
while_expr : "while" no_struct_literal_expr '{' block '}' ; while_expr : [ lifetime ':' ] "while" no_struct_literal_expr '{' block '}' ;
``` ```
### Infinite loops ### Infinite loops
@ -635,7 +659,7 @@ continue_expr : "continue" [ lifetime ];
### For expressions ### For expressions
```antlr ```antlr
for_expr : "for" pat "in" no_struct_literal_expr '{' block '}' ; for_expr : [ lifetime ':' ] "for" pat "in" no_struct_literal_expr '{' block '}' ;
``` ```
### If expressions ### If expressions
@ -763,12 +787,12 @@ bound := path | lifetime
### Memory ownership ### Memory ownership
### Memory slots ### Variables
### Boxes ### Boxes
## Tasks ## Threads
### Communication between tasks ### Communication between threads
### Task lifecycle ### Thread lifecycle

View File

@ -5,15 +5,14 @@ to jump to any particular section.
# Getting Started # Getting Started
If you haven't seen Rust at all yet, the first thing you should read is the [30 If you haven't seen Rust at all yet, the first thing you should read is the
minute intro](intro.html). It will give you an overview of the basic ideas of Rust introduction to [The Rust Programming Language](book/index.html). It'll give
at a high level. you a good idea of what Rust is like.
Once you know you really want to learn Rust, the next step is reading [The The book provides a lengthy explanation of Rust, its syntax, and its
Rust Programming Language](book/index.html). It is a lengthy explanation of concepts. Upon completing the book, you'll be an intermediate Rust
Rust, its syntax, and its concepts. Upon completing the book, you'll be an developer, and will have a good grasp of the fundamental ideas behind
intermediate Rust developer, and will have a good grasp of the fundamental Rust.
ideas behind Rust.
[Rust By Example][rbe] was originally a community resource, but was then [Rust By Example][rbe] was originally a community resource, but was then
donated to the Rust project. As the name implies, it teaches you Rust through a donated to the Rust project. As the name implies, it teaches you Rust through a
@ -24,7 +23,7 @@ series of small examples.
# Community & Getting Help # Community & Getting Help
If you need help with something, or just want to talk about Rust with others, If you need help with something, or just want to talk about Rust with others,
there's a few places you can do that: there are a few places you can do that:
The Rust IRC channels on [irc.mozilla.org](http://irc.mozilla.org/) are the The Rust IRC channels on [irc.mozilla.org](http://irc.mozilla.org/) are the
fastest way to get help. fastest way to get help.
@ -59,7 +58,7 @@ the language in as much detail as possible is in [the reference](reference.html)
# Tools # Tools
Rust's still a young language, so there isn't a ton of tooling yet, but the Rust is still a young language, so there isn't a ton of tooling yet, but the
tools we have are really nice. tools we have are really nice.
[Cargo](http://crates.io) is Rust's package manager, and its website contains [Cargo](http://crates.io) is Rust's package manager, and its website contains
@ -69,16 +68,21 @@ lots of good documentation.
# FAQs # FAQs
There are questions that are asked quite often, and so we've made FAQs for them: There are questions that are asked quite often, so we've made FAQs for them:
* [Language Design FAQ](complement-design-faq.html) * [Language Design FAQ](complement-design-faq.html)
* [Language FAQ](complement-lang-faq.html) * [Language FAQ](complement-lang-faq.html)
* [Project FAQ](complement-project-faq.html) * [Project FAQ](complement-project-faq.html)
* [How to submit a bug report](https://github.com/rust-lang/rust/blob/master/CONTRIBUTING.md#bug-reports) * [How to submit a bug report](https://github.com/rust-lang/rust/blob/master/CONTRIBUTING.md#bug-reports)
# The standard library # The Standard Library
We have [API documentation for the entire standard We have [API documentation for the entire standard
library](std/index.html). There's a list of crates on the left with more library](std/index.html). There's a list of crates on the left with more
specific sections, or you can use the search bar at the top to search for specific sections, or you can use the search bar at the top to search for
something if you know its name. something if you know its name.
# The Error Index
If you encounter an error while compiling your code you may be able to look it
up in the [Rust Compiler Error Index](error-index.html).

View File

@ -57,8 +57,12 @@ function populate_rust_search() {
// #18540, use a single token // #18540, use a single token
var a = document.createElement("a");
a.href = "http://doc.rust-lang.org/core/?search=" + encodeURIComponent(lt);
a.textContent = lt;
var search = document.getElementById('core-search'); var search = document.getElementById('core-search');
search.innerHTML = "<a href=\"http://doc.rust-lang.org/core/?search=" + lt + "\">" + lt + "</a>"; search.innerHTML = "";
search.appendChild(a);
} }
populate_site_search(); populate_site_search();
populate_rust_search(); populate_rust_search();

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,7 @@
% Handling errors % Handling errors
### Use task isolation to cope with failure. [FIXME] ### Use thread isolation to cope with failure. [FIXME]
> **[FIXME]** Explain how to isolate tasks and detect task failure for recovery. > **[FIXME]** Explain how to isolate threads and detect thread failure for recovery.
### Consuming `Result` [FIXME] ### Consuming `Result` [FIXME]

View File

@ -11,13 +11,13 @@ Errors fall into one of three categories:
The basic principle of the convention is that: The basic principle of the convention is that:
* Catastrophic errors and programming errors (bugs) can and should only be * Catastrophic errors and programming errors (bugs) can and should only be
recovered at a *coarse grain*, i.e. a task boundary. recovered at a *coarse grain*, i.e. a thread boundary.
* Obstructions preventing an operation should be reported at a maximally *fine * Obstructions preventing an operation should be reported at a maximally *fine
grain* -- to the immediate invoker of the operation. grain* -- to the immediate invoker of the operation.
## Catastrophic errors ## Catastrophic errors
An error is _catastrophic_ if there is no meaningful way for the current task to An error is _catastrophic_ if there is no meaningful way for the current thread to
continue after the error occurs. continue after the error occurs.
Catastrophic errors are _extremely_ rare, especially outside of `libstd`. Catastrophic errors are _extremely_ rare, especially outside of `libstd`.
@ -28,7 +28,7 @@ Catastrophic errors are _extremely_ rare, especially outside of `libstd`.
For errors like stack overflow, Rust currently aborts the process, but For errors like stack overflow, Rust currently aborts the process, but
could in principle panic, which (in the best case) would allow could in principle panic, which (in the best case) would allow
reporting and recovery from a supervisory task. reporting and recovery from a supervisory thread.
## Contract violations ## Contract violations
@ -44,7 +44,7 @@ existing borrows have been relinquished.
A contract violation is always a bug, and for bugs we follow the Erlang A contract violation is always a bug, and for bugs we follow the Erlang
philosophy of "let it crash": we assume that software *will* have bugs, and we philosophy of "let it crash": we assume that software *will* have bugs, and we
design coarse-grained task boundaries to report, and perhaps recover, from these design coarse-grained thread boundaries to report, and perhaps recover, from these
bugs. bugs.
### Contract design ### Contract design

View File

@ -23,7 +23,7 @@ If `T` is such a data structure, consider introducing a `T` _builder_:
4. The builder should provide one or more "_terminal_" methods for actually building a `T`. 4. The builder should provide one or more "_terminal_" methods for actually building a `T`.
The builder pattern is especially appropriate when building a `T` involves side The builder pattern is especially appropriate when building a `T` involves side
effects, such as spawning a task or launching a process. effects, such as spawning a thread or launching a process.
In Rust, there are two variants of the builder pattern, differing in the In Rust, there are two variants of the builder pattern, differing in the
treatment of ownership, as described below. treatment of ownership, as described below.
@ -115,24 +115,24 @@ Sometimes builders must transfer ownership when constructing the final type
`T`, meaning that the terminal methods must take `self` rather than `&self`: `T`, meaning that the terminal methods must take `self` rather than `&self`:
```rust ```rust
// A simplified excerpt from std::task::TaskBuilder // A simplified excerpt from std::thread::Builder
impl TaskBuilder { impl ThreadBuilder {
/// Name the task-to-be. Currently the name is used for identification /// Name the thread-to-be. Currently the name is used for identification
/// only in failure messages. /// only in failure messages.
pub fn named(mut self, name: String) -> TaskBuilder { pub fn named(mut self, name: String) -> ThreadBuilder {
self.name = Some(name); self.name = Some(name);
self self
} }
/// Redirect task-local stdout. /// Redirect thread-local stdout.
pub fn stdout(mut self, stdout: Box<Writer + Send>) -> TaskBuilder { pub fn stdout(mut self, stdout: Box<Writer + Send>) -> ThreadBuilder {
self.stdout = Some(stdout); self.stdout = Some(stdout);
// ^~~~~~ this is owned and cannot be cloned/re-used // ^~~~~~ this is owned and cannot be cloned/re-used
self self
} }
/// Creates and executes a new child task. /// Creates and executes a new child thread.
pub fn spawn(self, f: proc():Send) { pub fn spawn(self, f: proc():Send) {
// consume self // consume self
... ...
@ -141,7 +141,7 @@ impl TaskBuilder {
``` ```
Here, the `stdout` configuration involves passing ownership of a `Writer`, Here, the `stdout` configuration involves passing ownership of a `Writer`,
which must be transferred to the task upon construction (in `spawn`). which must be transferred to the thread upon construction (in `spawn`).
When the terminal methods of the builder require ownership, there is a basic tradeoff: When the terminal methods of the builder require ownership, there is a basic tradeoff:
@ -158,17 +158,17 @@ builder methods for a consuming builder should take and returned an owned
```rust ```rust
// One-liners // One-liners
TaskBuilder::new().named("my_task").spawn(proc() { ... }); ThreadBuilder::new().named("my_thread").spawn(proc() { ... });
// Complex configuration // Complex configuration
let mut task = TaskBuilder::new(); let mut thread = ThreadBuilder::new();
task = task.named("my_task_2"); // must re-assign to retain ownership thread = thread.named("my_thread_2"); // must re-assign to retain ownership
if reroute { if reroute {
task = task.stdout(mywriter); thread = thread.stdout(mywriter);
} }
task.spawn(proc() { ... }); thread.spawn(proc() { ... });
``` ```
One-liners work as before, because ownership is threaded through each of the One-liners work as before, because ownership is threaded through each of the

View File

@ -8,7 +8,7 @@ go out of scope.
### Destructors should not fail. [FIXME: needs RFC] ### Destructors should not fail. [FIXME: needs RFC]
Destructors are executed on task failure, and in that context a failing Destructors are executed on thread failure, and in that context a failing
destructor causes the program to abort. destructor causes the program to abort.
Instead of failing in a destructor, provide a separate method for checking for Instead of failing in a destructor, provide a separate method for checking for

View File

@ -5,7 +5,7 @@
Use line comments: Use line comments:
``` rust ``` rust
// Wait for the main task to return, and set the process error code // Wait for the main thread to return, and set the process error code
// appropriately. // appropriately.
``` ```
@ -13,7 +13,7 @@ Instead of:
``` rust ``` rust
/* /*
* Wait for the main task to return, and set the process error code * Wait for the main thread to return, and set the process error code
* appropriately. * appropriately.
*/ */
``` ```
@ -55,7 +55,7 @@ For example:
/// Sets up a default runtime configuration, given compiler-supplied arguments. /// Sets up a default runtime configuration, given compiler-supplied arguments.
/// ///
/// This function will block until the entire pool of M:N schedulers has /// This function will block until the entire pool of M:N schedulers has
/// exited. This function also requires a local task to be available. /// exited. This function also requires a local thread to be available.
/// ///
/// # Arguments /// # Arguments
/// ///
@ -64,7 +64,7 @@ For example:
/// * `main` - The initial procedure to run inside of the M:N scheduling pool. /// * `main` - The initial procedure to run inside of the M:N scheduling pool.
/// Once this procedure exits, the scheduling pool will begin to shut /// Once this procedure exits, the scheduling pool will begin to shut
/// down. The entire pool (and this function) will only return once /// down. The entire pool (and this function) will only return once
/// all child tasks have finished executing. /// all child threads have finished executing.
/// ///
/// # Return value /// # Return value
/// ///

View File

@ -5,7 +5,7 @@ they enclose. Accessor methods often have variants to access the data
by value, by reference, and by mutable reference. by value, by reference, and by mutable reference.
In general, the `get` family of methods is used to access contained In general, the `get` family of methods is used to access contained
data without any risk of task failure; they return `Option` as data without any risk of thread failure; they return `Option` as
appropriate. This name is chosen rather than names like `find` or appropriate. This name is chosen rather than names like `find` or
`lookup` because it is appropriate for a wider range of container types. `lookup` because it is appropriate for a wider range of container types.

View File

@ -8,7 +8,7 @@ good at: embedding in other languages, programs with specific space and time
requirements, and writing low-level code, like device drivers and operating 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 abstrations 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. Even then, Rust still allows precise control like a low-level language. Even then, Rust still allows precise control like a low-level
language would. language would.
@ -24,6 +24,7 @@ is the first. After this:
* [Syntax and Semantics][ss] - Each bit of Rust, broken down into small chunks. * [Syntax and Semantics][ss] - Each bit of Rust, broken down into small chunks.
* [Nightly Rust][nr] - Cutting-edge features that arent in stable builds yet. * [Nightly Rust][nr] - Cutting-edge features that arent in stable builds yet.
* [Glossary][gl] - A reference of terms used in the book. * [Glossary][gl] - A reference of terms used in the book.
* [Academic Research][ar] - Literature that influenced Rust.
[gs]: getting-started.html [gs]: getting-started.html
[lr]: learn-rust.html [lr]: learn-rust.html
@ -31,6 +32,7 @@ is the first. After this:
[ss]: syntax-and-semantics.html [ss]: syntax-and-semantics.html
[nr]: nightly-rust.html [nr]: nightly-rust.html
[gl]: glossary.html [gl]: glossary.html
[ar]: academic-research.html
After reading this introduction, youll want to dive into either Learn Rust After reading this introduction, youll want to dive into either Learn Rust
or Syntax and Semantics, depending on your preference: Learn Rust if you or Syntax and Semantics, depending on your preference: Learn Rust if you
@ -38,6 +40,11 @@ want to dive in with a project, or Syntax and Semantics if you prefer to
start small, and learn a single concept thoroughly before moving onto the next. start 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
The source files from which this book is generated can be found on Github:
[github.com/rust-lang/rust/tree/master/src/doc/trpl](https://github.com/rust-lang/rust/tree/master/src/doc/trpl)
## A brief introduction to Rust ## A brief introduction to Rust
Is Rust a language you might be interested in? Lets examine a few small code Is Rust a language you might be interested in? Lets examine a few small code
@ -125,7 +132,7 @@ vector. When we try to compile this program, we get an error:
```text ```text
error: cannot borrow `x` as mutable because it is also borrowed as immutable error: cannot borrow `x` as mutable because it is also borrowed as immutable
x.push(4); x.push("foo");
^ ^
note: previous borrow of `x` occurs here; the immutable borrow prevents note: previous borrow of `x` occurs here; the immutable borrow prevents
subsequent moves or mutable borrows of `x` until the borrow ends subsequent moves or mutable borrows of `x` until the borrow ends
@ -165,7 +172,7 @@ fn main() {
Rust has [move semantics][move] by default, so if we want to make a copy of some Rust has [move semantics][move] by default, so if we want to make a copy of some
data, we call the `clone()` method. In this example, `y` is no longer a reference data, we call the `clone()` method. In this example, `y` is no longer a reference
to the vector stored in `x`, but a copy of its first element, `"hello"`. Now to the vector stored in `x`, but a copy of its first element, `"Hello"`. Now
that we dont have a reference, our `push()` works just fine. that we dont have a reference, our `push()` works just fine.
[move]: move-semantics.html [move]: move-semantics.html
@ -188,5 +195,5 @@ fn main() {
We created an inner scope with an additional set of curly braces. `y` will go out of We created an inner scope with an additional set of curly braces. `y` will go out of
scope before we call `push()`, and so were all good. scope before we call `push()`, and so were all good.
This concept of ownership isnt just good for preventing danging pointers, but an This concept of ownership isnt just good for preventing dangling pointers, but an
entire set of related problems, like iterator invalidation, concurrency, and more. entire set of related problems, like iterator invalidation, concurrency, and more.

View File

@ -5,16 +5,20 @@
* [Hello, world!](hello-world.md) * [Hello, world!](hello-world.md)
* [Hello, Cargo!](hello-cargo.md) * [Hello, Cargo!](hello-cargo.md)
* [Learn Rust](learn-rust.md) * [Learn Rust](learn-rust.md)
* [Guessing Game](guessing-game.md)
* [Dining Philosophers](dining-philosophers.md)
* [Rust inside other languages](rust-inside-other-languages.md)
* [Effective Rust](effective-rust.md) * [Effective Rust](effective-rust.md)
* [The Stack and the Heap](the-stack-and-the-heap.md) * [The Stack and the Heap](the-stack-and-the-heap.md)
* [Debug and Display](debug-and-display.md)
* [Testing](testing.md) * [Testing](testing.md)
* [Conditional Compilation](conditional-compilation.md)
* [Documentation](documentation.md) * [Documentation](documentation.md)
* [Iterators](iterators.md) * [Iterators](iterators.md)
* [Concurrency](concurrency.md) * [Concurrency](concurrency.md)
* [Error Handling](error-handling.md) * [Error Handling](error-handling.md)
* [FFI](ffi.md) * [FFI](ffi.md)
* [Deref coercions](deref-coercions.md) * [Borrow and AsRef](borrow-and-asref.md)
* [Release Channels](release-channels.md)
* [Syntax and Semantics](syntax-and-semantics.md) * [Syntax and Semantics](syntax-and-semantics.md)
* [Variable Bindings](variable-bindings.md) * [Variable Bindings](variable-bindings.md)
* [Functions](functions.md) * [Functions](functions.md)
@ -27,34 +31,32 @@
* [References and Borrowing](references-and-borrowing.md) * [References and Borrowing](references-and-borrowing.md)
* [Lifetimes](lifetimes.md) * [Lifetimes](lifetimes.md)
* [Mutability](mutability.md) * [Mutability](mutability.md)
* [Move semantics](move-semantics.md) * [Structs](structs.md)
* [Enums](enums.md) * [Enums](enums.md)
* [Match](match.md) * [Match](match.md)
* [Patterns](patterns.md) * [Patterns](patterns.md)
* [Structs](structs.md)
* [Method Syntax](method-syntax.md) * [Method Syntax](method-syntax.md)
* [Drop](drop.md)
* [Vectors](vectors.md) * [Vectors](vectors.md)
* [Strings](strings.md) * [Strings](strings.md)
* [Traits](traits.md)
* [Operators and Overloading](operators-and-overloading.md)
* [Generics](generics.md) * [Generics](generics.md)
* [Traits](traits.md)
* [Drop](drop.md)
* [if let](if-let.md) * [if let](if-let.md)
* [Trait Objects](trait-objects.md) * [Trait Objects](trait-objects.md)
* [Closures](closures.md) * [Closures](closures.md)
* [Universal Function Call Syntax](ufcs.md) * [Universal Function Call Syntax](ufcs.md)
* [Crates and Modules](crates-and-modules.md) * [Crates and Modules](crates-and-modules.md)
* [`static`](static.md) * [`const` and `static`](const-and-static.md)
* [`const`](const.md)
* [Tuple Structs](tuple-structs.md)
* [Attributes](attributes.md) * [Attributes](attributes.md)
* [Conditional Compilation](conditional-compilation.md)
* [`type` aliases](type-aliases.md) * [`type` aliases](type-aliases.md)
* [Casting between types](casting-between-types.md) * [Casting between types](casting-between-types.md)
* [Associated Types](associated-types.md) * [Associated Types](associated-types.md)
* [Unsized Types](unsized-types.md) * [Unsized Types](unsized-types.md)
* [Operators and Overloading](operators-and-overloading.md)
* [Deref coercions](deref-coercions.md)
* [Macros](macros.md) * [Macros](macros.md)
* [`unsafe` Code](unsafe-code.md) * [Raw Pointers](raw-pointers.md)
* [`unsafe`](unsafe.md)
* [Nightly Rust](nightly-rust.md) * [Nightly Rust](nightly-rust.md)
* [Compiler Plugins](compiler-plugins.md) * [Compiler Plugins](compiler-plugins.md)
* [Inline Assembly](inline-assembly.md) * [Inline Assembly](inline-assembly.md)
@ -65,5 +67,6 @@
* [Benchmark Tests](benchmark-tests.md) * [Benchmark Tests](benchmark-tests.md)
* [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)
* [Glossary](glossary.md) * [Glossary](glossary.md)
* [Academic Research](academic-research.md) * [Academic Research](academic-research.md)

View File

@ -0,0 +1,79 @@
% Associated Constants
With the `associated_consts` feature, you can define constants like this:
```rust,ignore
#![feature(associated_consts)]
trait Foo {
const ID: i32;
}
impl Foo for i32 {
const ID: i32 = 1;
}
fn main() {
assert_eq!(1, i32::ID);
}
```
Any implementor of `Foo` will have to define `ID`. Without the definition:
```rust,ignore
#![feature(associated_consts)]
trait Foo {
const ID: i32;
}
impl Foo for i32 {
}
```
gives
```text
error: not all trait items implemented, missing: `ID` [E0046]
impl Foo for i32 {
}
```
A default value can be implemented as well:
```rust,ignore
#![feature(associated_consts)]
trait Foo {
const ID: i32 = 1;
}
impl Foo for i32 {
}
impl Foo for i64 {
const ID: i32 = 5;
}
fn main() {
assert_eq!(1, i32::ID);
assert_eq!(5, i64::ID);
}
```
As you can see, when implementing `Foo`, you can leave it unimplemented, as
with `i32`. It will then use the default value. But, as in `i64`, we can also
add our own definition.
Associated constants dont have to be associated with a trait. An `impl` block
for a `struct` works fine too:
```rust,ignore
#![feature(associated_consts)]
struct Foo;
impl Foo {
pub const FOO: u32 = 3;
}
```

View File

@ -1,8 +1,8 @@
% Associated Types % Associated Types
Associated types are a powerful part of Rust's type system. They're related to Associated types are a powerful part of Rusts type system. Theyre related to
the idea of a 'type family', in other words, grouping multiple types together. That the idea of a type family, in other words, grouping multiple types together. That
description is a bit abstract, so let's dive right into an example. If you want description is a bit abstract, so lets dive right into an example. If you want
to write a `Graph` trait, you have two types to be generic over: the node type to write a `Graph` trait, you have two types to be generic over: the node type
and the edge type. So you might write a trait, `Graph<N, E>`, that looks like and the edge type. So you might write a trait, `Graph<N, E>`, that looks like
this: this:
@ -48,11 +48,11 @@ fn distance<G: Graph>(graph: &G, start: &G::N, end: &G::N) -> uint { ... }
No need to deal with the `E`dge type here! No need to deal with the `E`dge type here!
Let's go over all this in more detail. Lets go over all this in more detail.
## Defining associated types ## Defining associated types
Let's build that `Graph` trait. Here's the definition: Lets build that `Graph` trait. Heres the definition:
```rust ```rust
trait Graph { trait Graph {
@ -86,7 +86,7 @@ trait Graph {
## Implementing associated types ## Implementing associated types
Just like any trait, traits that use associated types use the `impl` keyword to Just like any trait, traits that use associated types use the `impl` keyword to
provide implementations. Here's a simple implementation of Graph: provide implementations. Heres a simple implementation of Graph:
```rust ```rust
# trait Graph { # trait Graph {
@ -118,13 +118,13 @@ impl Graph for MyGraph {
This silly implementation always returns `true` and an empty `Vec<Edge>`, but it This silly implementation always returns `true` and an empty `Vec<Edge>`, but it
gives you an idea of how to implement this kind of thing. We first need three gives you an idea of how to implement this kind of thing. We first need three
`struct`s, one for the graph, one for the node, and one for the edge. If it made `struct`s, one for the graph, one for the node, and one for the edge. If it made
more sense to use a different type, that would work as well, we're just going to more sense to use a different type, that would work as well, were just going to
use `struct`s for all three here. use `struct`s for all three here.
Next is the `impl` line, which is just like implementing any other trait. Next is the `impl` line, which is just like implementing any other trait.
From here, we use `=` to define our associated types. The name the trait uses From here, we use `=` to define our associated types. The name the trait uses
goes on the left of the `=`, and the concrete type we're `impl`ementing this goes on the left of the `=`, and the concrete type were `impl`ementing this
for goes on the right. Finally, we use the concrete types in our function for goes on the right. Finally, we use the concrete types in our function
declarations. declarations.

View File

@ -1,3 +1,70 @@
% Attributes % Attributes
Coming Soon! Declarations can be annotated with attributes in Rust. They look like this:
```rust
#[test]
# fn foo() {}
```
or like this:
```rust
# mod foo {
#![test]
# }
```
The difference between the two is the `!`, which changes what the attribute
applies to:
```rust,ignore
#[foo]
struct Foo;
mod bar {
#![bar]
}
```
The `#[foo]` attribute applies to the next item, which is the `struct`
declaration. The `#![bar]` attribute applies to the item enclosing it, which is
the `mod` declaration. Otherwise, theyre the same. Both change the meaning of
the item theyre attached to somehow.
For example, consider a function like this:
```rust
#[test]
fn check() {
assert_eq!(2, 1 + 1);
}
```
It is marked with `#[test]`. This means its special: when you run
[tests][tests], this function will execute. When you compile as usual, it wont
even be included. This function is now a test function.
[tests]: testing.html
Attributes may also have additional data:
```rust
#[inline(always)]
fn super_fast_fn() {
# }
```
Or even keys and values:
```rust
#[cfg(target_os = "macos")]
mod macos_only {
# }
```
Rust attributes are used for a number of different things. There is a full list
of attributes [in the reference][reference]. Currently, you are not allowed to
create your own attributes, the Rust compiler defines them.
[reference]: ../reference.html#attributes

View File

@ -13,7 +13,7 @@ pub fn add_two(a: i32) -> i32 {
} }
#[cfg(test)] #[cfg(test)]
mod test { mod tests {
use super::*; use super::*;
use test::Bencher; use test::Bencher;

View File

@ -0,0 +1,93 @@
% Borrow and AsRef
The [`Borrow`][borrow] and [`AsRef`][asref] traits are very similar, but
different. Heres a quick refresher on what these two traits mean.
[borrow]: ../std/borrow/trait.Borrow.html
[asref]: ../std/convert/trait.AsRef.html
# Borrow
The `Borrow` trait is used when youre writing a datastructure, and you want to
use either an owned or borrowed type as synonymous for some purpose.
For example, [`HashMap`][hashmap] has a [`get` method][get] which uses `Borrow`:
```rust,ignore
fn get<Q: ?Sized>(&self, k: &Q) -> Option<&V>
where K: Borrow<Q>,
Q: Hash + Eq
```
[hashmap]: ../std/collections/struct.HashMap.html
[get]: ../std/collections/struct.HashMap.html#method.get
This signature is pretty complicated. The `K` parameter is what were interested
in here. It refers to a parameter of the `HashMap` itself:
```rust,ignore
struct HashMap<K, V, S = RandomState> {
```
The `K` parameter is the type of _key_ the `HashMap` uses. So, looking at
the signature of `get()` again, we can use `get()` when the key implements
`Borrow<Q>`. That way, we can make a `HashMap` which uses `String` keys,
but use `&str`s when were searching:
```rust
use std::collections::HashMap;
let mut map = HashMap::new();
map.insert("Foo".to_string(), 42);
assert_eq!(map.get("Foo"), Some(&42));
```
This is because the standard library has `impl Borrow<str> for String`.
For most types, when you want to take an owned or borrowed type, a `&T` is
enough. But one area where `Borrow` is effective is when theres more than one
kind of borrowed value. Slices are an area where this is especially true: you
can have both an `&[T]` or a `&mut [T]`. If we wanted to accept both of these
types, `Borrow` is up for it:
```
use std::borrow::Borrow;
use std::fmt::Display;
fn foo<T: Borrow<i32> + Display>(a: T) {
println!("a is borrowed: {}", a);
}
let mut i = 5;
foo(&i);
foo(&mut i);
```
This will print out `a is borrowed: 5` twice.
# AsRef
The `AsRef` trait is a conversion trait. Its used for converting some value to
a reference in generic code. Like this:
```rust
let s = "Hello".to_string();
fn foo<T: AsRef<str>>(s: T) {
let slice = s.as_ref();
}
```
# Which should I use?
We can see how theyre kind of the same: they both deal with owned and borrowed
versions of some type. However, theyre a bit different.
Choose `Borrow` when you want to abstract over different kinds of borrowing, or
when youre building a datastructure that treats owned and borrowed values in
equivalent ways, such as hashing and comparison.
Choose `AsRef` when you want to convert something to a reference directly, and
youre writing generic code.

View File

@ -1,3 +1,89 @@
% Casting Between Types % Casting Between Types
Coming Soon Rust, with its focus on safety, provides two different ways of casting
different types between each other. The first, `as`, is for safe casts.
In contrast, `transmute` allows for arbitrary casting, and is one of the
most dangerous features of Rust!
# `as`
The `as` keyword does basic casting:
```rust
let x: i32 = 5;
let y = x as i64;
```
It only allows certain kinds of casting, however:
```rust,ignore
let a = [0u8, 0u8, 0u8, 0u8];
let b = a as u32; // four eights makes 32
```
This errors with:
```text
error: non-scalar cast: `[u8; 4]` as `u32`
let b = a as u32; // four eights makes 32
^~~~~~~~
```
Its a non-scalar cast because we have multiple values here: the four
elements of the array. These kinds of casts are very dangerous, because they
make assumptions about the way that multiple underlying structures are
implemented. For this, we need something more dangerous.
# `transmute`
The `transmute` function is provided by a [compiler intrinsic][intrinsics], and
what it does is very simple, but very scary. It tells Rust to treat a value of
one type as though it were another type. It does this regardless of the
typechecking system, and just completely trusts you.
[intrinsics]: intrinsics.html
In our previous example, we know that an array of four `u8`s represents a `u32`
properly, and so we want to do the cast. Using `transmute` instead of `as`,
Rust lets us:
```rust
use std::mem;
unsafe {
let a = [0u8, 0u8, 0u8, 0u8];
let b = mem::transmute::<[u8; 4], u32>(a);
}
```
We have to wrap the operation in an `unsafe` block for this to compile
successfully. Technically, only the `mem::transmute` call itself needs to be in
the block, but it's nice in this case to enclose everything related, so you
know where to look. In this case, the details about `a` are also important, and
so they're in the block. You'll see code in either style, sometimes the context
is too far away, and wrapping all of the code in `unsafe` isn't a great idea.
While `transmute` does very little checking, it will at least make sure that
the types are the same size. This errors:
```rust,ignore
use std::mem;
unsafe {
let a = [0u8, 0u8, 0u8, 0u8];
let b = mem::transmute::<[u8; 4], u64>(a);
}
```
with:
```text
error: transmute called on types with different sizes: [u8; 4] (32 bits) to u64
(64 bits)
```
Other than that, you're on your own!

View File

@ -1,9 +1,9 @@
% Closures % Closures
Rust not only has named functions, but anonymous functions as well. Anonymous Rust not only has named functions, but anonymous functions as well. Anonymous
functions that have an associated environment are called 'closures', because they functions that have an associated environment are called closures, because they
close over an environment. Rust has a really great implementation of them, as close over an environment. Rust has a really great implementation of them, as
we'll see. well see.
# Syntax # Syntax
@ -15,7 +15,7 @@ let plus_one = |x: i32| x + 1;
assert_eq!(2, plus_one(1)); assert_eq!(2, plus_one(1));
``` ```
We create a binding, `plus_one`, and assign it to a closure. The closure's We create a binding, `plus_one`, and assign it to a closure. The closures
arguments go between the pipes (`|`), and the body is an expression, in this arguments go between the pipes (`|`), and the body is an expression, in this
case, `x + 1`. Remember that `{ }` is an expression, so we can have multi-line case, `x + 1`. Remember that `{ }` is an expression, so we can have multi-line
closures too: closures too:
@ -33,7 +33,7 @@ let plus_two = |x| {
assert_eq!(4, plus_two(2)); assert_eq!(4, plus_two(2));
``` ```
You'll notice a few things about closures that are a bit different than regular Youll notice a few things about closures that are a bit different than regular
functions defined with `fn`. The first of which is that we did not need to functions defined with `fn`. The first of which 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,13 +44,13 @@ 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 dont have to. Why is this? Basically, it was chosen for ergonomic reasons.
While specifying the full type for named functions is helpful with things like While specifying the full type for named functions is helpful with things like
documentation and type inference, the types of closures are rarely documented documentation and type inference, the types of closures are rarely documented
since theyre anonymous, and they dont cause the kinds of error-at-a-distance since theyre anonymous, and they dont cause the kinds of error-at-a-distance
that inferring named function types can. 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. Ive added spaces
here to make them look a little closer: here to make them look a little closer:
```rust ```rust
@ -59,11 +59,11 @@ let plus_one_v2 = |x: i32 | -> i32 { x + 1 };
let plus_one_v3 = |x: i32 | x + 1 ; let plus_one_v3 = |x: i32 | x + 1 ;
``` ```
Small differences, but they're similar in ways. Small differences, but theyre similar in ways.
# Closures and their environment # Closures and their environment
Closures are called such because they 'close over their environment.' It Closures are called such because they close over their environment. It
looks like this: looks like this:
```rust ```rust
@ -105,7 +105,7 @@ fn main() {
^ ^
``` ```
A verbose yet helpful error message! As it says, we can't take a mutable borrow A verbose yet helpful error message! As it says, we cant take a mutable borrow
on `num` because the closure is already borrowing it. If we let the closure go on `num` because the closure is already borrowing it. If we let the closure go
out of scope, we can: out of scope, we can:
@ -140,7 +140,7 @@ let takes_nums = || nums;
``` ```
`Vec<T>` has ownership over its contents, and therefore, when we refer to it `Vec<T>` has ownership over its contents, and therefore, when we refer to it
in our closure, we have to take ownership of `nums`. It's the same as if we'd in our closure, we have to take ownership of `nums`. Its the same as if wed
passed `nums` to a function that took ownership of it. passed `nums` to a function that took ownership of it.
## `move` closures ## `move` closures
@ -156,7 +156,7 @@ let owns_num = move |x: i32| x + num;
Now, even though the keyword is `move`, the variables follow normal move semantics. Now, even though the keyword is `move`, the variables follow normal move semantics.
In this case, `5` implements `Copy`, and so `owns_num` takes ownership of a copy In this case, `5` implements `Copy`, and so `owns_num` takes ownership of a copy
of `num`. So what's the difference? of `num`. So whats the difference?
```rust ```rust
let mut num = 5; let mut num = 5;
@ -171,11 +171,11 @@ assert_eq!(10, num);
``` ```
So in this case, our closure took a mutable reference to `num`, and then when So in this case, our closure took a mutable reference to `num`, and then when
we called `add_num`, it mutated the underlying value, as we'd expect. We also we called `add_num`, it mutated the underlying value, as wed expect. We also
needed to declare `add_num` as `mut` too, because were mutating its needed to declare `add_num` as `mut` too, because were mutating its
environment. environment.
If we change to a `move` closure, it's different: If we change to a `move` closure, its different:
```rust ```rust
let mut num = 5; let mut num = 5;
@ -203,8 +203,8 @@ you tons of control over what your code does, and closures are no different.
# Closure implementation # Closure implementation
Rust's implementation of closures is a bit different than other languages. They Rusts implementation of closures is a bit different than other languages. They
are effectively syntax sugar for traits. You'll want to make sure to have read are effectively syntax sugar for traits. Youll want to make sure to have read
the [traits chapter][traits] before this one, as well as the chapter on [trait the [traits chapter][traits] before this one, as well as the chapter on [trait
objects][trait-objects]. objects][trait-objects].
@ -237,9 +237,9 @@ pub trait FnOnce<Args> {
# } # }
``` ```
You'll notice a few differences between these traits, but a big one is `self`: Youll notice a few differences between these traits, but a big one is `self`:
`Fn` takes `&self`, `FnMut` takes `&mut self`, and `FnOnce` takes `self`. This `Fn` takes `&self`, `FnMut` takes `&mut self`, and `FnOnce` takes `self`. This
covers all three kinds of `self` via the usual method call syntax. But we've covers all three kinds of `self` via the usual method call syntax. But weve
split them up into three traits, rather than having a single one. This gives us split them up into three traits, rather than having a single one. This gives us
a large amount of control over what kind of closures we can take. a large amount of control over what kind of closures we can take.
@ -253,7 +253,7 @@ Now that we know that closures are traits, we already know how to accept and
return closures: just like any other trait! return closures: just like any other trait!
This also means that we can choose static vs dynamic dispatch as well. First, This also means that we can choose static vs dynamic dispatch as well. First,
let's write a function which takes something callable, calls it, and returns lets write a function which takes something callable, calls it, and returns
the result: the result:
```rust ```rust
@ -271,7 +271,7 @@ assert_eq!(3, answer);
We pass our closure, `|x| x + 2`, to `call_with_one`. It just does what it We pass our closure, `|x| x + 2`, to `call_with_one`. It just does what it
suggests: it calls the closure, giving it `1` as an argument. suggests: it calls the closure, giving it `1` as an argument.
Let's examine the signature of `call_with_one` in more depth: Lets examine the signature of `call_with_one` in more depth:
```rust ```rust
fn call_with_one<F>(some_closure: F) -> i32 fn call_with_one<F>(some_closure: F) -> i32
@ -280,7 +280,7 @@ fn call_with_one<F>(some_closure: F) -> i32
``` ```
We take one parameter, and it has the type `F`. We also return a `i32`. This part We take one parameter, and it has the type `F`. We also return a `i32`. This part
isn't interesting. The next part is: isnt interesting. The next part is:
```rust ```rust
# fn call_with_one<F>(some_closure: F) -> i32 # fn call_with_one<F>(some_closure: F) -> i32
@ -292,9 +292,9 @@ Because `Fn` is a trait, we can bound our generic with it. In this case, our clo
takes a `i32` as an argument and returns an `i32`, and so the generic bound we use takes a `i32` as an argument and returns an `i32`, and so the generic bound we use
is `Fn(i32) -> i32`. is `Fn(i32) -> i32`.
There's one other key point here: because we're bounding a generic with a Theres one other key point here: because were bounding a generic with a
trait, this will get monomorphized, and therefore, we'll be doing static trait, this will get monomorphized, and therefore, well be doing static
dispatch into the closure. That's pretty neat. In many langauges, closures are dispatch into the closure. Thats pretty neat. In many languages, closures are
inherently heap allocated, and will always involve dynamic dispatch. In Rust, inherently heap allocated, and will always involve dynamic dispatch. In Rust,
we can stack allocate our closure environment, and statically dispatch the we can stack allocate our closure environment, and statically dispatch the
call. This happens quite often with iterators and their adapters, which often call. This happens quite often with iterators and their adapters, which often
@ -320,7 +320,7 @@ to our closure when we pass it to `call_with_one`, so we use `&||`.
Its very common for functional-style code to return closures in various Its very common for functional-style code to return closures in various
situations. If you try to return a closure, you may run into an error. At situations. If you try to return a closure, you may run into an error. At
first, it may seem strange, but we'll figure it out. Here's how you'd probably first, it may seem strange, but well figure it out. Heres how youd probably
try to return a closure from a function: try to return a closure from a function:
```rust,ignore ```rust,ignore
@ -361,7 +361,7 @@ In order to return something from a function, Rust needs to know what
size the return type is. But since `Fn` is a trait, it could be various size the return type is. But since `Fn` is a trait, it could be various
things of various sizes: many different types can implement `Fn`. An easy things of various sizes: many different types can implement `Fn`. An easy
way to give something a size is to take a reference to it, as references way to give something a size is to take a reference to it, as references
have a known size. So we'd write this: have a known size. So wed write this:
```rust,ignore ```rust,ignore
fn factory() -> &(Fn(i32) -> Vec<i32>) { fn factory() -> &(Fn(i32) -> Vec<i32>) {
@ -385,7 +385,7 @@ 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 elision doesnt kick in
here. What lifetime can we choose? `'static`: here. What lifetime can we choose? `'static`:
```rust,ignore ```rust,ignore
@ -414,7 +414,7 @@ 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 dont have a `&'static Fn(i32) -> i32`,
we have a `[closure <anon>:7:9: 7:20]`. Wait, what? we have a `[closure <anon>:7:9: 7:20]`. Wait, what?
Because each closure generates its own environment `struct` and implementation Because each closure generates its own environment `struct` and implementation
@ -422,7 +422,7 @@ 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, But why doesnt our closure implement `&'static Fn`? Well, as we discussed before,
closures borrow their environment. And in this case, our environment is based closures borrow their environment. And in this case, our environment is based
on a stack-allocated `5`, the `num` variable binding. So the borrow has a lifetime 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 of the stack frame. So if we returned this closure, the function call would be
@ -445,7 +445,7 @@ assert_eq!(6, answer);
# } # }
``` ```
We use a trait object, by `Box`ing up the `Fn`. There's just one last problem: We use a trait object, by `Box`ing up the `Fn`. Theres just one last problem:
```text ```text
error: `num` does not live long enough error: `num` does not live long enough
@ -471,5 +471,5 @@ assert_eq!(6, answer);
``` ```
By making the inner closure a `move Fn`, we create a new stack frame for our By making the inner closure a `move Fn`, we create a new stack frame for our
closure. By `Box`ing it up, we've given it a known size, and allowing it to closure. By `Box`ing it up, weve given it a known size, and allowing it to
escape our stack frame. escape our stack frame.

View File

@ -176,7 +176,7 @@ for a full example, the core of which is reproduced here:
```ignore ```ignore
declare_lint!(TEST_LINT, Warn, declare_lint!(TEST_LINT, Warn,
"Warn about items named 'lintme'") "Warn about items named 'lintme'");
struct Pass; struct Pass;

View File

@ -6,7 +6,7 @@ and more cores, yet many programmers aren't prepared to fully utilize them.
Rust's memory safety features also apply to its concurrency story too. Even Rust's memory safety features also apply to its concurrency story too. Even
concurrent Rust programs must be memory safe, having no data races. Rust's type concurrent Rust programs must be memory safe, having no data races. Rust's type
system is up to the task, and gives you powerful ways to reason about system is up to the thread, and gives you powerful ways to reason about
concurrent code at compile time. concurrent code at compile time.
Before we talk about the concurrency features that come with Rust, it's important Before we talk about the concurrency features that come with Rust, it's important
@ -116,7 +116,7 @@ use std::thread;
fn main() { fn main() {
let mut data = vec![1u32, 2, 3]; let mut data = vec![1u32, 2, 3];
for i in 0..2 { for i in 0..3 {
thread::spawn(move || { thread::spawn(move || {
data[i] += 1; data[i] += 1;
}); });
@ -154,7 +154,7 @@ use std::sync::Mutex;
fn main() { fn main() {
let mut data = Mutex::new(vec![1u32, 2, 3]); let mut data = Mutex::new(vec![1u32, 2, 3]);
for i in 0..2 { for i in 0..3 {
let data = data.lock().unwrap(); let data = data.lock().unwrap();
thread::spawn(move || { thread::spawn(move || {
data[i] += 1; data[i] += 1;
@ -176,8 +176,8 @@ Here's the error:
^~~~~~~~~~~~~ ^~~~~~~~~~~~~
``` ```
You see, [`Mutex`](std/sync/struct.Mutex.html) has a You see, [`Mutex`](../std/sync/struct.Mutex.html) has a
[`lock`](http://doc.rust-lang.org/nightly/std/sync/struct.Mutex.html#method.lock) [`lock`](../std/sync/struct.Mutex.html#method.lock)
method which has this signature: method which has this signature:
```ignore ```ignore
@ -196,7 +196,7 @@ use std::thread;
fn main() { fn main() {
let data = Arc::new(Mutex::new(vec![1u32, 2, 3])); let data = Arc::new(Mutex::new(vec![1u32, 2, 3]));
for i in 0..2 { for i in 0..3 {
let data = data.clone(); let data = data.clone();
thread::spawn(move || { thread::spawn(move || {
let mut data = data.lock().unwrap(); let mut data = data.lock().unwrap();
@ -217,7 +217,7 @@ thread more closely:
# use std::thread; # use std::thread;
# fn main() { # fn main() {
# let data = Arc::new(Mutex::new(vec![1u32, 2, 3])); # let data = Arc::new(Mutex::new(vec![1u32, 2, 3]));
# for i in 0..2 { # for i in 0..3 {
# let data = data.clone(); # let data = data.clone();
thread::spawn(move || { thread::spawn(move || {
let mut data = data.lock().unwrap(); let mut data = data.lock().unwrap();

View File

@ -1,3 +1,93 @@
% Conditional Compilation % Conditional Compilation
Coming Soon! Rust has a special attribute, `#[cfg]`, which allows you to compile code
based on a flag passed to the compiler. It has two forms:
```rust
#[cfg(foo)]
# fn foo() {}
#[cfg(bar = "baz")]
# fn bar() {}
```
They also have some helpers:
```rust
#[cfg(any(unix, windows))]
# fn foo() {}
#[cfg(all(unix, target_pointer_width = "32"))]
# fn bar() {}
#[cfg(not(foo))]
# fn not_foo() {}
```
These can nest arbitrarily:
```rust
#[cfg(any(not(unix), all(target_os="macos", target_arch = "powerpc")))]
# fn foo() {}
```
As for how to enable or disable these switches, if youre using Cargo,
they get set in the [`[features]` section][features] of your `Cargo.toml`:
[features]: http://doc.crates.io/manifest.html#the-[features]-section
```toml
[features]
# no features by default
default = []
# The “secure-password” feature depends on the bcrypt package.
secure-password = ["bcrypt"]
```
When you do this, Cargo passes along a flag to `rustc`:
```text
--cfg feature="${feature_name}"
```
The sum of these `cfg` flags will determine which ones get activated, and
therefore, which code gets compiled. Lets take this code:
```rust
#[cfg(feature = "foo")]
mod foo {
}
```
If we compile it with `cargo build --features "foo"`, it will send the `--cfg
feature="foo"` flag to `rustc`, and the output will have the `mod foo` in it.
If we compile it with a regular `cargo build`, no extra flags get passed on,
and so, no `foo` module will exist.
# cfg_attr
You can also set another attribute based on a `cfg` variable with `cfg_attr`:
```rust
#[cfg_attr(a, b)]
# fn foo() {}
```
Will be the same as `#[b]` if `a` is set by `cfg` attribute, and nothing otherwise.
# cfg!
The `cfg!` [syntax extension][compilerplugins] lets you use these kinds of flags
elsewhere in your code, too:
```rust
if cfg!(target_os = "macos") || cfg!(target_os = "ios") {
println!("Think Different!");
}
```
[compilerplugins]: compiler-plugins.html
These will be replaced by a `true` or `false` at compile-time, depending on the
configuration settings.

View File

@ -0,0 +1,86 @@
% `const` and `static`
Rust has a way of defining constants with the `const` keyword:
```rust
const N: i32 = 5;
```
Unlike [`let`][let] bindings, you must annotate the type of a `const`.
[let]: variable-bindings.html
Constants live for the entire lifetime of a program. More specifically,
constants in Rust have no fixed address in memory. This is because theyre
effectively inlined to each place that theyre used. References to the same
constant are not necessarily guaranteed to refer to the same memory address for
this reason.
# `static`
Rust provides a global variable sort of facility in static items. Theyre
similar to constants, but static items arent inlined upon use. This means that
there is only one instance for each value, and its at a fixed location in
memory.
Heres an example:
```rust
static N: i32 = 5;
```
Unlike [`let`][let] bindings, you must annotate the type of a `static`.
[let]: variable-bindings.html
Statics live for the entire lifetime of a program, and therefore any
reference stored in a constant has a [`static` lifetime][lifetimes]:
```rust
static NAME: &'static str = "Steve";
```
[lifetimes]: lifetimes.html
## Mutability
You can introduce mutability with the `mut` keyword:
```rust
static mut N: i32 = 5;
```
Because this is mutable, one thread could be updating `N` while another is
reading it, causing memory unsafety. As such both accessing and mutating a
`static mut` is [`unsafe`][unsafe], and so must be done in an `unsafe` block:
```rust
# static mut N: i32 = 5;
unsafe {
N += 1;
println!("N: {}", N);
}
```
[unsafe]: unsafe.html
Furthermore, any type stored in a `static` must be `Sync`.
# Initializing
Both `const` and `static` have requirements for giving them a value. They may
only be given a value thats a constant expression. In other words, you cannot
use the result of a function call or anything similarly complex or at runtime.
# Which construct should I use?
Almost always, if you can choose between the two, choose `const`. Its pretty
rare that you actually want a memory location associated with your constant,
and using a const allows for optimizations like constant propagation not only
in your crate but downstream crates.
A const can be thought of as a `#define` in C: it has metadata overhead but it
has no runtime overhead. “Should I use a #define or a static in C,” is largely
the same question as whether you should use a const or a static in Rust.

View File

@ -1,16 +1,16 @@
% Crates and Modules % Crates and Modules
When a project starts getting large, it's considered good software When a project starts getting large, its considered good software
engineering practice to split it up into a bunch of smaller pieces, and then engineering practice to split it up into a bunch of smaller pieces, and then
fit them together. It's also important to have a well-defined interface, so fit them together. Its also important to have a well-defined interface, so
that some of your functionality is private, and some is public. To facilitate that some of your functionality is private, and some is public. To facilitate
these kinds of things, Rust has a module system. these kinds of things, Rust has a module system.
# Basic terminology: Crates and Modules # Basic terminology: Crates and Modules
Rust has two distinct terms that relate to the module system: *crate* and Rust has two distinct terms that relate to the module system: crate and
*module*. A crate is synonymous with a *library* or *package* in other module. A crate is synonymous with a library or package in other
languages. Hence "Cargo" as the name of Rust's package management tool: you languages. Hence “Cargo” as the name of Rusts package management tool: you
ship your crates to others with Cargo. Crates can produce an executable or a ship your crates to others with Cargo. Crates can produce an executable or a
library, depending on the project. library, depending on the project.
@ -18,10 +18,10 @@ Each crate has an implicit *root module* that contains the code for that crate.
You can then define a tree of sub-modules under that root module. Modules allow You can then define a tree of sub-modules under that root module. Modules allow
you to partition your code within the crate itself. you to partition your code within the crate itself.
As an example, let's make a *phrases* crate, which will give us various phrases As an example, lets make a *phrases* crate, which will give us various phrases
in different languages. To keep things simple, we'll stick to "greetings" and in different languages. To keep things simple, well stick to greetings and
"farewells" as two kinds of phrases, and use English and Japanese (日本語) as farewells as two kinds of phrases, and use English and Japanese (日本語) as
two languages for those phrases to be in. We'll use this module layout: two languages for those phrases to be in. Well use this module layout:
```text ```text
+-----------+ +-----------+
@ -47,7 +47,7 @@ In this example, `phrases` is the name of our crate. All of the rest are
modules. You can see that they form a tree, branching out from the crate modules. You can see that they form a tree, branching out from the crate
*root*, which is the root of the tree: `phrases` itself. *root*, which is the root of the tree: `phrases` itself.
Now that we have a plan, let's define these modules in code. To start, Now that we have a plan, lets define these modules in code. To start,
generate a new crate with Cargo: generate a new crate with Cargo:
```bash ```bash
@ -72,7 +72,7 @@ above.
# Defining Modules # Defining Modules
To define each of our modules, we use the `mod` keyword. Let's make our To define each of our modules, we use the `mod` keyword. Lets make our
`src/lib.rs` look like this: `src/lib.rs` look like this:
``` ```
@ -101,7 +101,7 @@ Within a given `mod`, you can declare sub-`mod`s. We can refer to sub-modules
with double-colon (`::`) notation: our four nested modules are with double-colon (`::`) notation: our four nested modules are
`english::greetings`, `english::farewells`, `japanese::greetings`, and `english::greetings`, `english::farewells`, `japanese::greetings`, and
`japanese::farewells`. Because these sub-modules are namespaced under their `japanese::farewells`. Because these sub-modules are namespaced under their
parent module, the names don't conflict: `english::greetings` and parent module, the names dont conflict: `english::greetings` and
`japanese::greetings` are distinct, even though their names are both `japanese::greetings` are distinct, even though their names are both
`greetings`. `greetings`.
@ -116,11 +116,11 @@ build deps examples libphrases-a7448e02a0468eaa.rlib native
``` ```
`libphrase-hash.rlib` is the compiled crate. Before we see how to use this `libphrase-hash.rlib` is the compiled crate. Before we see how to use this
crate from another crate, let's break it up into multiple files. crate from another crate, lets break it up into multiple files.
# Multiple file crates # Multiple file crates
If each crate were just one file, these files would get very large. It's often If each crate were just one file, these files would get very large. Its often
easier to split up crates into multiple files, and Rust supports this in two easier to split up crates into multiple files, and Rust supports this in two
ways. ways.
@ -141,7 +141,7 @@ mod english;
If we do that, Rust will expect to find either a `english.rs` file, or a If we do that, Rust will expect to find either a `english.rs` file, or a
`english/mod.rs` file with the contents of our module. `english/mod.rs` file with the contents of our module.
Note that in these files, you don't need to re-declare the module: that's Note that in these files, you dont need to re-declare the module: thats
already been done with the initial `mod` declaration. already been done with the initial `mod` declaration.
Using these two techniques, we can break up our crate into two directories and Using these two techniques, we can break up our crate into two directories and
@ -180,7 +180,7 @@ mod japanese;
These two declarations tell Rust to look for either `src/english.rs` and These two declarations tell Rust to look for either `src/english.rs` and
`src/japanese.rs`, or `src/english/mod.rs` and `src/japanese/mod.rs`, depending `src/japanese.rs`, or `src/english/mod.rs` and `src/japanese/mod.rs`, depending
on our preference. In this case, because our modules have sub-modules, we've on our preference. In this case, because our modules have sub-modules, weve
chosen the second. Both `src/english/mod.rs` and `src/japanese/mod.rs` look chosen the second. Both `src/english/mod.rs` and `src/japanese/mod.rs` look
like this: like this:
@ -192,11 +192,11 @@ mod farewells;
Again, these declarations tell Rust to look for either Again, these declarations tell Rust to look for either
`src/english/greetings.rs` and `src/japanese/greetings.rs` or `src/english/greetings.rs` and `src/japanese/greetings.rs` or
`src/english/farewells/mod.rs` and `src/japanese/farewells/mod.rs`. Because `src/english/farewells/mod.rs` and `src/japanese/farewells/mod.rs`. Because
these sub-modules don't have their own sub-modules, we've chosen to make them these sub-modules dont have their own sub-modules, weve chosen to make them
`src/english/greetings.rs` and `src/japanese/farewells.rs`. Whew! `src/english/greetings.rs` and `src/japanese/farewells.rs`. Whew!
The contents of `src/english/greetings.rs` and `src/japanese/farewells.rs` are The contents of `src/english/greetings.rs` and `src/japanese/farewells.rs` are
both empty at the moment. Let's add some functions. both empty at the moment. Lets add some functions.
Put this in `src/english/greetings.rs`: Put this in `src/english/greetings.rs`:
@ -223,7 +223,7 @@ fn hello() -> String {
``` ```
Of course, you can copy and paste this from this web page, or just type Of course, you can copy and paste this from this web page, or just type
something else. It's not important that you actually put "konnichiwa" to learn something else. Its not important that you actually put konnichiwa to learn
about the module system. about the module system.
Put this in `src/japanese/farewells.rs`: Put this in `src/japanese/farewells.rs`:
@ -234,17 +234,17 @@ fn goodbye() -> String {
} }
``` ```
(This is "Sayōnara", if you're curious.) (This is Sayōnara, if youre curious.)
Now that we have some functionality in our crate, let's try to use it from Now that we have some functionality in our crate, lets try to use it from
another crate. another crate.
# Importing External Crates # Importing External Crates
We have a library crate. Let's make an executable crate that imports and uses We have a library crate. Lets make an executable crate that imports and uses
our library. our library.
Make a `src/main.rs` and put this in it (it won't quite compile yet): Make a `src/main.rs` and put this in it (it wont quite compile yet):
```rust,ignore ```rust,ignore
extern crate phrases; extern crate phrases;
@ -259,7 +259,7 @@ fn main() {
``` ```
The `extern crate` declaration tells Rust that we need to compile and link to The `extern crate` declaration tells Rust that we need to compile and link to
the `phrases` crate. We can then use `phrases`' modules in this one. As we the `phrases` crate. We can then use `phrases` modules in this one. As we
mentioned earlier, you can use double colons to refer to sub-modules and the mentioned earlier, you can use double colons to refer to sub-modules and the
functions inside of them. functions inside of them.
@ -267,10 +267,10 @@ Also, Cargo assumes that `src/main.rs` is the crate root of a binary crate,
rather than a library crate. Our package now has two crates: `src/lib.rs` and rather than a library crate. Our package now has two crates: `src/lib.rs` and
`src/main.rs`. This pattern is quite common for executable crates: most `src/main.rs`. This pattern is quite common for executable crates: most
functionality is in a library crate, and the executable crate uses that functionality is in a library crate, and the executable crate uses that
library. This way, other programs can also use the library crate, and it's also library. This way, other programs can also use the library crate, and its also
a nice separation of concerns. a nice separation of concerns.
This doesn't quite work yet, though. We get four errors that look similar to This doesnt quite work yet, though. We get four errors that look similar to
this: this:
```bash ```bash
@ -287,14 +287,14 @@ note: in expansion of format_args!
phrases/src/main.rs:4:5: 4:76 note: expansion site phrases/src/main.rs:4:5: 4:76 note: expansion site
``` ```
By default, everything is private in Rust. Let's talk about this in some more By default, everything is private in Rust. Lets talk about this in some more
depth. depth.
# Exporting a Public Interface # Exporting a Public Interface
Rust allows you to precisely control which aspects of your interface are Rust allows you to precisely control which aspects of your interface are
public, and so private is the default. To make things public, you use the `pub` public, and so private is the default. To make things public, you use the `pub`
keyword. Let's focus on the `english` module first, so let's reduce our `src/main.rs` keyword. Lets focus on the `english` module first, so lets reduce our `src/main.rs`
to just this: to just this:
```{rust,ignore} ```{rust,ignore}
@ -306,21 +306,21 @@ fn main() {
} }
``` ```
In our `src/lib.rs`, let's add `pub` to the `english` module declaration: In our `src/lib.rs`, lets add `pub` to the `english` module declaration:
```{rust,ignore} ```{rust,ignore}
pub mod english; pub mod english;
mod japanese; mod japanese;
``` ```
And in our `src/english/mod.rs`, let's make both `pub`: And in our `src/english/mod.rs`, lets make both `pub`:
```{rust,ignore} ```{rust,ignore}
pub mod greetings; pub mod greetings;
pub mod farewells; pub mod farewells;
``` ```
In our `src/english/greetings.rs`, let's add `pub` to our `fn` declaration: In our `src/english/greetings.rs`, lets add `pub` to our `fn` declaration:
```{rust,ignore} ```{rust,ignore}
pub fn hello() -> String { pub fn hello() -> String {
@ -358,12 +358,12 @@ Goodbye in English: Goodbye.
Now that our functions are public, we can use them. Great! However, typing out Now that our functions are public, we can use them. Great! However, typing out
`phrases::english::greetings::hello()` is very long and repetitive. Rust has `phrases::english::greetings::hello()` is very long and repetitive. Rust has
another keyword for importing names into the current scope, so that you can another keyword for importing names into the current scope, so that you can
refer to them with shorter names. Let's talk about `use`. refer to them with shorter names. Lets talk about `use`.
# Importing Modules with `use` # Importing Modules with `use`
Rust has a `use` keyword, which allows us to import names into our local scope. Rust has a `use` keyword, which allows us to import names into our local scope.
Let's change our `src/main.rs` to look like this: Lets change our `src/main.rs` to look like this:
```{rust,ignore} ```{rust,ignore}
extern crate phrases; extern crate phrases;
@ -378,7 +378,7 @@ fn main() {
``` ```
The two `use` lines import each module into the local scope, so we can refer to The two `use` lines import each module into the local scope, so we can refer to
the functions by a much shorter name. By convention, when importing functions, it's the functions by a much shorter name. By convention, when importing functions, its
considered best practice to import the module, rather than the function directly. In considered best practice to import the module, rather than the function directly. In
other words, you _can_ do this: other words, you _can_ do this:
@ -395,7 +395,7 @@ fn main() {
``` ```
But it is not idiomatic. This is significantly more likely to introduce a But it is not idiomatic. This is significantly more likely to introduce a
naming conflict. In our short program, it's not a big deal, but as it grows, it naming conflict. In our short program, its not a big deal, but as it grows, it
becomes a problem. If we have conflicting names, Rust will give a compilation becomes a problem. If we have conflicting names, Rust will give a compilation
error. For example, if we made the `japanese` functions public, and tried to do error. For example, if we made the `japanese` functions public, and tried to do
this: this:
@ -423,7 +423,7 @@ error: aborting due to previous error
Could not compile `phrases`. Could not compile `phrases`.
``` ```
If we're importing multiple names from the same module, we don't have to type it out If were importing multiple names from the same module, we dont have to type it out
twice. Instead of this: twice. Instead of this:
```{rust,ignore} ```{rust,ignore}
@ -439,11 +439,11 @@ use phrases::english::{greetings, farewells};
## Re-exporting with `pub use` ## Re-exporting with `pub use`
You don't just use `use` to shorten identifiers. You can also use it inside of your crate You dont just use `use` to shorten identifiers. You can also use it inside of your crate
to re-export a function inside another module. This allows you to present an external to re-export a function inside another module. This allows you to present an external
interface that may not directly map to your internal code organization. interface that may not directly map to your internal code organization.
Let's look at an example. Modify your `src/main.rs` to read like this: Lets look at an example. Modify your `src/main.rs` to read like this:
```{rust,ignore} ```{rust,ignore}
extern crate phrases; extern crate phrases;
@ -494,11 +494,11 @@ mod farewells;
``` ```
The `pub use` declaration brings the function into scope at this part of our The `pub use` declaration brings the function into scope at this part of our
module hierarchy. Because we've `pub use`d this inside of our `japanese` module hierarchy. Because weve `pub use`d this inside of our `japanese`
module, we now have a `phrases::japanese::hello()` function and a module, we now have a `phrases::japanese::hello()` function and a
`phrases::japanese::goodbye()` function, even though the code for them lives in `phrases::japanese::goodbye()` function, even though the code for them lives in
`phrases::japanese::greetings::hello()` and `phrases::japanese::greetings::hello()` and
`phrases::japanese::farewells::goodbye()`. Our internal organization doesn't `phrases::japanese::farewells::goodbye()`. Our internal organization doesnt
define our external interface. define our external interface.
Here we have a `pub use` for each function we want to bring into the Here we have a `pub use` for each function we want to bring into the
@ -507,13 +507,13 @@ everything from `greetings` into the current scope: `pub use self::greetings::*`
What about the `self`? Well, by default, `use` declarations are absolute paths, What about the `self`? Well, by default, `use` declarations are absolute paths,
starting from your crate root. `self` makes that path relative to your current starting from your crate root. `self` makes that path relative to your current
place in the hierarchy instead. There's one more special form of `use`: you can place in the hierarchy instead. Theres one more special form of `use`: you can
`use super::` to reach one level up the tree from your current location. Some `use super::` to reach one level up the tree from your current location. Some
people like to think of `self` as `.` and `super` as `..`, from many shells' people like to think of `self` as `.` and `super` as `..`, from many shells
display for the current directory and the parent directory. display for the current directory and the parent directory.
Outside of `use`, paths are relative: `foo::bar()` refers to a function inside Outside of `use`, paths are relative: `foo::bar()` refers to a function inside
of `foo` relative to where we are. If that's prefixed with `::`, as in of `foo` relative to where we are. If thats prefixed with `::`, as in
`::foo::bar()`, it refers to a different `foo`, an absolute path from your `::foo::bar()`, it refers to a different `foo`, an absolute path from your
crate root. crate root.

View File

@ -1,3 +1,119 @@
% `Deref` coercions % `Deref` coercions
Coming soon! The standard library provides a special trait, [`Deref`][deref]. Its normally
used to overload `*`, the dereference operator:
```rust
use std::ops::Deref;
struct DerefExample<T> {
value: T,
}
impl<T> Deref for DerefExample<T> {
type Target = T;
fn deref(&self) -> &T {
&self.value
}
}
fn main() {
let x = DerefExample { value: 'a' };
assert_eq!('a', *x);
}
```
[deref]: ../std/ops/trait.Deref.html
This is useful for writing custom pointer types. However, theres a language
feature related to `Deref`: deref coercions. Heres the rule: If you have a
type `U`, and it implements `Deref<Target=T>`, values of `&U` will
automatically coerce to a `&T`. Heres an example:
```rust
fn foo(s: &str) {
// borrow a string for a second
}
// String implements Deref<Target=str>
let owned = "Hello".to_string();
// therefore, this works:
foo(&owned);
```
Using an ampersand in front of a value takes a reference to it. So `owned` is a
`String`, `&owned` is an `&String`, and since `impl Deref<Target=str> for
String`, `&String` will deref to `&str`, which `foo()` takes.
Thats it. This rule is one of the only places in which Rust does an automatic
conversion for you, but it adds a lot of flexibility. For example, the `Rc<T>`
type implements `Deref<Target=T>`, so this works:
```rust
use std::rc::Rc;
fn foo(s: &str) {
// borrow a string for a second
}
// String implements Deref<Target=str>
let owned = "Hello".to_string();
let counted = Rc::new(owned);
// therefore, this works:
foo(&counted);
```
All weve done is wrap our `String` in an `Rc<T>`. But we can now pass the
`Rc<String>` around anywhere wed have a `String`. The signature of `foo`
didnt change, but works just as well with either type. This example has two
conversions: `Rc<String>` to `String` and then `String` to `&str`. Rust will do
this as many times as possible until the types match.
Another very common implementation provided by the standard library is:
```rust
fn foo(s: &[i32]) {
// borrow a slice for a second
}
// Vec<T> implements Deref<Target=[T]>
let owned = vec![1, 2, 3];
foo(&owned);
```
Vectors can `Deref` to a slice.
## Deref and method calls
`Deref` will also kick in when calling a method. In other words, these are
the same two things in Rust:
```rust
struct Foo;
impl Foo {
fn foo(&self) { println!("Foo"); }
}
let f = Foo;
f.foo();
```
Even though `f` isnt a reference, and `foo` takes `&self`, this works.
Thats because these things are the same:
```rust,ignore
f.foo();
(&f).foo();
(&&f).foo();
(&&&&&&&&f).foo();
```
A value of type `&&&&&&&&&&&&&&&&Foo` can still have methods defined on `Foo`
called, because the compiler will insert as many * operations as necessary to
get it right. And since its inserting `*`s, that uses `Deref`.

View File

@ -0,0 +1,690 @@
% Dining Philosophers
For our second project, lets look at a classic concurrency problem. Its
called the dining philosophers. It was originally conceived by Dijkstra in
1965, but well use the version from [this paper][paper] by Tony Hoare in 1985.
[paper]: http://www.usingcsp.com/cspbook.pdf
> In ancient times, a wealthy philanthropist endowed a College to accommodate
> five eminent philosophers. Each philosopher had a room in which he could
> engage in his professional activity of thinking; there was also a common
> dining room, furnished with a circular table, surrounded by five chairs, each
> labelled by the name of the philosopher who was to sit in it. They sat
> anticlockwise around the table. To the left of each philosopher there was
> laid a golden fork, and in the centre stood a large bowl of spaghetti, which
> was constantly replenished. A philosopher was expected to spend most of his
> time thinking; but when he felt hungry, he went to the dining room, sat down
> in his own chair, picked up his own fork on his left, and plunged it into the
> spaghetti. But such is the tangled nature of spaghetti that a second fork is
> required to carry it to the mouth. The philosopher therefore had also to pick
> up the fork on his right. When we was finished he would put down both his
> forks, get up from his chair, and continue thinking. Of course, a fork can be
> used by only one philosopher at a time. If the other philosopher wants it, he
> just has to wait until the fork is available again.
This classic problem shows off a few different elements of concurrency. The
reason is that it's actually slightly tricky to implement: a simple
implementation can deadlock. For example, let's consider a simple algorithm
that would solve this problem:
1. A philosopher picks up the fork on their left.
2. They then pick up the fork on their right.
3. They eat.
4. They return the forks.
Now, lets imagine this sequence of events:
1. Philosopher 1 begins the algorithm, picking up the fork on their left.
2. Philosopher 2 begins the algorithm, picking up the fork on their left.
3. Philosopher 3 begins the algorithm, picking up the fork on their left.
4. Philosopher 4 begins the algorithm, picking up the fork on their left.
5. Philosopher 5 begins the algorithm, picking up the fork on their left.
6. ... ? All the forks are taken, but nobody can eat!
There are different ways to solve this problem. Well get to our solution in
the tutorial itself. For now, lets get started modelling the problem itself.
Well start with the philosophers:
```rust
struct Philosopher {
name: String,
}
impl Philosopher {
fn new(name: &str) -> Philosopher {
Philosopher {
name: name.to_string(),
}
}
}
fn main() {
let p1 = Philosopher::new("Baruch Spinoza");
let p2 = Philosopher::new("Gilles Deleuze");
let p3 = Philosopher::new("Karl Marx");
let p4 = Philosopher::new("Friedrich Nietzsche");
let p5 = Philosopher::new("Michel Foucault");
}
```
Here, we make a [`struct`][struct] to represent a philosopher. For now,
a name is all we need. We choose the [`String`][string] type for the name,
rather than `&str`. Generally speaking, working with a type which owns its
data is easier than working with one that uses references.
Lets continue:
```rust
# struct Philosopher {
# name: String,
# }
impl Philosopher {
fn new(name: &str) -> Philosopher {
Philosopher {
name: name.to_string(),
}
}
}
```
This `impl` block lets us define things on `Philosopher` structs. In this case,
we define an associated function called `new`. The first line looks like this:
```rust
# struct Philosopher {
# name: String,
# }
# impl Philosopher {
fn new(name: &str) -> Philosopher {
# Philosopher {
# name: name.to_string(),
# }
# }
# }
```
We take one argument, a `name`, of type `&str`. This is a reference to another
string. It returns an instance of our `Philosopher` struct.
```rust
# struct Philosopher {
# name: String,
# }
# impl Philosopher {
# fn new(name: &str) -> Philosopher {
Philosopher {
name: name.to_string(),
}
# }
# }
```
This creates a new `Philosopher`, and sets its `name` to our `name` argument.
Not just the argument itself, though, as we call `.to_string()` on it. This
will create a copy of the string that our `&str` points to, and give us a new
`String`, which is the type of the `name` field of `Philosopher`.
Why not accept a `String` directly? Its nicer to call. If we took a `String`,
but our caller had a `&str`, theyd have to call this method themselves. The
downside of this flexibility is that we _always_ make a copy. For this small
program, thats not particularly important, as we know well just be using
short strings anyway.
One last thing youll notice: we just define a `Philosopher`, and seemingly
dont do anything with it. Rust is an expression based language, which means
that almost everything in Rust is an expression which returns a value. This is
true of functions as well, the last expression is automatically returned. Since
we create a new `Philosopher` as the last expression of this function, we end
up returning it.
This name, `new()`, isnt anything special to Rust, but it is a convention for
functions that create new instances of structs. Before we talk about why, lets
look at `main()` again:
```rust
# struct Philosopher {
# name: String,
# }
#
# impl Philosopher {
# fn new(name: &str) -> Philosopher {
# Philosopher {
# name: name.to_string(),
# }
# }
# }
#
fn main() {
let p1 = Philosopher::new("Baruch Spinoza");
let p2 = Philosopher::new("Gilles Deleuze");
let p3 = Philosopher::new("Karl Marx");
let p4 = Philosopher::new("Friedrich Nietzsche");
let p5 = Philosopher::new("Michel Foucault");
}
```
Here, we create five variable bindings with five new philosophers. These are my
favorite five, but you can substitute anyone you want. If we _didnt_ define
that `new()` function, it would look like this:
```rust
# struct Philosopher {
# name: String,
# }
fn main() {
let p1 = Philosopher { name: "Baruch Spinoza".to_string() };
let p2 = Philosopher { name: "Gilles Deleuze".to_string() };
let p3 = Philosopher { name: "Karl Marx".to_string() };
let p4 = Philosopher { name: "Friedrich Nietzche".to_string() };
let p5 = Philosopher { name: "Michel Foucault".to_string() };
}
```
Thats much noisier. Using `new` has other advantages too, but even in
this simple case, it ends up being nicer to use.
Now that weve got the basics in place, theres a number of ways that we can
tackle the broader problem here. I like to start from the end first: lets
set up a way for each philosopher to finish eating. As a tiny step, lets make
a method, and then loop through all the philosophers, calling it:
```rust
struct Philosopher {
name: String,
}
impl Philosopher {
fn new(name: &str) -> Philosopher {
Philosopher {
name: name.to_string(),
}
}
fn eat(&self) {
println!("{} is done eating.", self.name);
}
}
fn main() {
let philosophers = vec![
Philosopher::new("Baruch Spinoza"),
Philosopher::new("Gilles Deleuze"),
Philosopher::new("Karl Marx"),
Philosopher::new("Friedrich Nietzsche"),
Philosopher::new("Michel Foucault"),
];
for p in &philosophers {
p.eat();
}
}
```
Lets look at `main()` first. Rather than have five individual variable
bindings for our philosophers, we make a `Vec<T>` of them instead. `Vec<T>` is
also called a vector, and its a growable array type. We then use a
[`for`][for] loop to iterate through the vector, getting a reference to each
philosopher in turn.
[for]: for-loops.html
In the body of the loop, we call `p.eat()`, which is defined above:
```rust,ignore
fn eat(&self) {
println!("{} is done eating.", self.name);
}
```
In Rust, methods take an explicit `self` parameter. Thats why `eat()` is a
method, but `new` is an associated function: `new()` has no `self`. For our
first version of `eat()`, we just print out the name of the philosopher, and
mention theyre done eating. Running this program should give you the following
output:
```text
Baruch Spinoza is done eating.
Gilles Deleuze is done eating.
Karl Marx is done eating.
Friedrich Nietzsche is done eating.
Michel Foucault is done eating.
```
Easy enough, theyre all done! We havent actually implemented the real problem
yet, though, so were not done yet!
Next, we want to make our philosophers not just finish eating, but actually
eat. Heres the next version:
```rust
use std::thread;
struct Philosopher {
name: String,
}
impl Philosopher {
fn new(name: &str) -> Philosopher {
Philosopher {
name: name.to_string(),
}
}
fn eat(&self) {
println!("{} is eating.", self.name);
thread::sleep_ms(1000);
println!("{} is done eating.", self.name);
}
}
fn main() {
let philosophers = vec![
Philosopher::new("Baruch Spinoza"),
Philosopher::new("Gilles Deleuze"),
Philosopher::new("Karl Marx"),
Philosopher::new("Friedrich Nietzsche"),
Philosopher::new("Michel Foucault"),
];
for p in &philosophers {
p.eat();
}
}
```
Just a few changes. Lets break it down.
```rust,ignore
use std::thread;
```
`use` brings names into scope. Were going to start using the `thread` module
from the standard library, and so we need to `use` it.
```rust,ignore
fn eat(&self) {
println!("{} is eating.", self.name);
thread::sleep_ms(1000);
println!("{} is done eating.", self.name);
}
```
We now print out two messages, with a `sleep_ms()` in the middle. This will
simulate the time it takes a philosopher to eat.
If you run this program, You should see each philosopher eat in turn:
```text
Baruch Spinoza is eating.
Baruch Spinoza is done eating.
Gilles Deleuze is eating.
Gilles Deleuze is done eating.
Karl Marx is eating.
Karl Marx is done eating.
Friedrich Nietzsche is eating.
Friedrich Nietzsche is done eating.
Michel Foucault is eating.
Michel Foucault is done eating.
```
Excellent! Were getting there. Theres just one problem: we arent actually
operating in a concurrent fashion, which is a core part of the problem!
To make our philosophers eat concurrently, we need to make a small change.
Heres the next iteration:
```rust
use std::thread;
struct Philosopher {
name: String,
}
impl Philosopher {
fn new(name: &str) -> Philosopher {
Philosopher {
name: name.to_string(),
}
}
fn eat(&self) {
println!("{} is eating.", self.name);
thread::sleep_ms(1000);
println!("{} is done eating.", self.name);
}
}
fn main() {
let philosophers = vec![
Philosopher::new("Baruch Spinoza"),
Philosopher::new("Gilles Deleuze"),
Philosopher::new("Karl Marx"),
Philosopher::new("Friedrich Nietzsche"),
Philosopher::new("Michel Foucault"),
];
let handles: Vec<_> = philosophers.into_iter().map(|p| {
thread::spawn(move || {
p.eat();
})
}).collect();
for h in handles {
h.join().unwrap();
}
}
```
All weve done is change the loop in `main()`, and added a second one! Heres the
first change:
```rust,ignore
let handles: Vec<_> = philosophers.into_iter().map(|p| {
thread::spawn(move || {
p.eat();
})
}).collect();
```
While this is only five lines, theyre a dense four. Lets break it down.
```rust,ignore
let handles: Vec<_> =
```
We introduce a new binding, called `handles`. Weve given it this name because
we are going to make some new threads, and that will return some handles to those
threads that let us control their operation. We need to explicitly annotate
the type here, though, due to an issue well talk about later. The `_` is
a type placeholder. Were saying “`handles` is a vector of something, but you
can figure out what that something is, Rust.”
```rust,ignore
philosophers.into_iter().map(|p| {
```
We take our list of philosophers and call `into_iter()` on it. This creates an
iterator that takes ownership of each philosopher. We need to do this to pass
them to our threads. We take that iterator and call `map` on it, which takes a
closure as an argument and calls that closure on each element in turn.
```rust,ignore
thread::spawn(move || {
p.eat();
})
```
Heres where the concurrency happens. The `thread::spawn` function takes a closure
as an argument and executes that closure in a new thread. This closure needs
an extra annotation, `move`, to indicate that the closure is going to take
ownership of the values its capturing. Primarily, the `p` variable of the
`map` function.
Inside the thread, all we do is call `eat()` on `p`.
```rust,ignore
}).collect();
```
Finally, we take the result of all those `map` calls and collect them up.
`collect()` will make them into a collection of some kind, which is why we
needed to annotate the return type: we want a `Vec<T>`. The elements are the
return values of the `thread::spawn` calls, which are handles to those threads.
Whew!
```rust,ignore
for h in handles {
h.join().unwrap();
}
```
At the end of `main()`, we loop through the handles and call `join()` on them,
which blocks execution until the thread has completed execution. This ensures
that the threads complete their work before the program exits.
If you run this program, youll see that the philosophers eat out of order!
We have mult-threading!
```text
Gilles Deleuze is eating.
Gilles Deleuze is done eating.
Friedrich Nietzsche is eating.
Friedrich Nietzsche is done eating.
Michel Foucault is eating.
Baruch Spinoza is eating.
Baruch Spinoza is done eating.
Karl Marx is eating.
Karl Marx is done eating.
Michel Foucault is done eating.
```
But what about the forks? We havent modeled them at all yet.
To do that, lets make a new `struct`:
```rust
use std::sync::Mutex;
struct Table {
forks: Vec<Mutex<()>>,
}
```
This `Table` has an vector of `Mutex`es. A mutex is a way to control
concurrency: only one thread can access the contents at once. This is exactly
the property we need with our forks. We use an empty tuple, `()`, inside the
mutex, since were not actually going to use the value, just hold onto it.
Lets modify the program to use the `Table`:
```rust
use std::thread;
use std::sync::{Mutex, Arc};
struct Philosopher {
name: String,
left: usize,
right: usize,
}
impl Philosopher {
fn new(name: &str, left: usize, right: usize) -> Philosopher {
Philosopher {
name: name.to_string(),
left: left,
right: right,
}
}
fn eat(&self, table: &Table) {
let _left = table.forks[self.left].lock().unwrap();
let _right = table.forks[self.right].lock().unwrap();
println!("{} is eating.", self.name);
thread::sleep_ms(1000);
println!("{} is done eating.", self.name);
}
}
struct Table {
forks: Vec<Mutex<()>>,
}
fn main() {
let table = Arc::new(Table { forks: vec![
Mutex::new(()),
Mutex::new(()),
Mutex::new(()),
Mutex::new(()),
Mutex::new(()),
]});
let philosophers = vec![
Philosopher::new("Baruch Spinoza", 0, 1),
Philosopher::new("Gilles Deleuze", 1, 2),
Philosopher::new("Karl Marx", 2, 3),
Philosopher::new("Friedrich Nietzsche", 3, 4),
Philosopher::new("Michel Foucault", 0, 4),
];
let handles: Vec<_> = philosophers.into_iter().map(|p| {
let table = table.clone();
thread::spawn(move || {
p.eat(&table);
})
}).collect();
for h in handles {
h.join().unwrap();
}
}
```
Lots of changes! However, with this iteration, weve got a working program.
Lets go over the details:
```rust,ignore
use std::sync::{Mutex, Arc};
```
Were going to use another structure from the `std::sync` package: `Arc<T>`.
Well talk more about it when we use it.
```rust,ignore
struct Philosopher {
name: String,
left: usize,
right: usize,
}
```
We need to add two more fields to our `Philosopher`. Each philosopher is going
to have two forks: the one on their left, and the one on their right.
Well use the `usize` type to indicate them, as its the type that you index
vectors with. These two values will be the indexes into the `forks` our `Table`
has.
```rust,ignore
fn new(name: &str, left: usize, right: usize) -> Philosopher {
Philosopher {
name: name.to_string(),
left: left,
right: right,
}
}
```
We now need to construct those `left` and `right` values, so we add them to
`new()`.
```rust,ignore
fn eat(&self, table: &Table) {
let _left = table.forks[self.left].lock().unwrap();
let _right = table.forks[self.right].lock().unwrap();
println!("{} is eating.", self.name);
thread::sleep_ms(1000);
println!("{} is done eating.", self.name);
}
```
We have two new lines. Weve also added an argument, `table`. We access the
`Table`s list of forks, and then use `self.left` and `self.right` to access
the fork at that particular index. That gives us access to the `Mutex` at that
index, and we call `lock()` on it. If the mutex is currently being accessed by
someone else, well block until it becomes available.
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],
which is what happens when the thread panics while the lock is held. Since this
shouldnt happen, we just use `unwrap()`.
[poison]: ../std/sync/struct.Mutex.html#poisoning
One other odd thing about these lines: weve named the results `_left` and
`_right`. Whats up with that underscore? Well, we arent planning on
_using_ the value inside the lock. We just want to acquire it. As such,
Rust will warn us that we never use the value. By using the underscore,
we tell Rust that this is what we intended, and it wont throw a warning.
What about releasing the lock? Well, that will happen when `_left` and
`_right` go out of scope, automatically.
```rust,ignore
let table = Arc::new(Table { forks: vec![
Mutex::new(()),
Mutex::new(()),
Mutex::new(()),
Mutex::new(()),
Mutex::new(()),
]});
```
Next, in `main()`, we make a new `Table` and wrap it in an `Arc<T>`.
arc stands for atomic reference count, and we need that to share
our `Table` across multiple threads. As we share it, the reference
count will go up, and when each thread ends, it will go back down.
```rust,ignore
let philosophers = vec![
Philosopher::new("Baruch Spinoza", 0, 1),
Philosopher::new("Gilles Deleuze", 1, 2),
Philosopher::new("Karl Marx", 2, 3),
Philosopher::new("Friedrich Nietzsche", 3, 4),
Philosopher::new("Michel Foucault", 0, 4),
];
```
We need to pass in our `left` and `right` values to the constructors for our
`Philosopher`s. But theres one more detail here, and its _very_ important. If
you look at the pattern, its all consistent until the very end. Monsieur
Foucault should have `4, 0` as arguments, but instead, has `0, 4`. This is what
prevents deadlock, actually: one of our philosophers is left handed! This is
one way to solve the problem, and in my opinion, its the simplest.
```rust,ignore
let handles: Vec<_> = philosophers.into_iter().map(|p| {
let table = table.clone();
thread::spawn(move || {
p.eat(&table);
})
}).collect();
```
Finally, inside of our `map()`/`collect()` loop, we call `table.clone()`. The
`clone()` method on `Arc<T>` is what bumps up the reference count, and when it
goes out of scope, it decrements the count. Youll notice we can introduce a
new binding to `table` here, and it will shadow the old one. This is often used
so that you dont need to come up with two unique names.
With this, our program works! Only two philosophers can eat at any one time,
and so youll get some output like this:
```text
Gilles Deleuze is eating.
Friedrich Nietzsche is eating.
Friedrich Nietzsche is done eating.
Gilles Deleuze is done eating.
Baruch Spinoza is eating.
Karl Marx is eating.
Baruch Spinoza is done eating.
Michel Foucault is eating.
Karl Marx is done eating.
Michel Foucault is done eating.
```
Congrats! Youve implemented a classic concurrency problem in Rust.

View File

@ -380,7 +380,10 @@ $ rustdoc --test path/to/my/crate/root.rs
$ cargo test $ cargo test
``` ```
That's right, `cargo test` tests embedded documentation too. That's right, `cargo test` tests embedded documentation too. However,
`cargo test` will not test binary crates, only library ones. This is
due to the way `rustdoc` works: it links against the library to be tested,
but with a binary, theres nothing to link to.
There are a few more annotations that are useful to help `rustdoc` do the right There are a few more annotations that are useful to help `rustdoc` do the right
thing when testing your code: thing when testing your code:
@ -553,10 +556,20 @@ This sets a few different options, with a logo, favicon, and a root URL.
## Generation options ## Generation options
`rustdoc` also contains a few other options on the command line, for further customiziation: `rustdoc` also contains a few other options on the command line, for further customization:
- `--html-in-header FILE`: includes the contents of FILE at the end of the - `--html-in-header FILE`: includes the contents of FILE at the end of the
`<head>...</head>` section. `<head>...</head>` section.
- `--html-before-content FILE`: includes the contents of FILE directly after - `--html-before-content FILE`: includes the contents of FILE directly after
`<body>`, before the rendered content (including the search bar). `<body>`, before the rendered content (including the search bar).
- `--html-after-content FILE`: includes the contents of FILE after all the rendered content. - `--html-after-content FILE`: includes the contents of FILE after all the rendered content.
## Security note
The Markdown in documentation comments is placed without processing into
the final webpage. Be careful with literal HTML:
```rust
/// <script>alert(document.cookie)</script>
# fn foo() {}
```

View File

@ -1,3 +1,67 @@
% `Drop` % Drop
Coming soon! Now that weve discussed traits, lets talk about a particular trait provided
by the Rust standard library, [`Drop`][drop]. The `Drop` trait provides a way
to run some code when a value goes out of scope. For example:
[drop]: ../std/ops/trait.Drop.html
```rust
struct HasDrop;
impl Drop for HasDrop {
fn drop(&mut self) {
println!("Dropping!");
}
}
fn main() {
let x = HasDrop;
// do stuff
} // x goes out of scope here
```
When `x` goes out of scope at the end of `main()`, the code for `Drop` will
run. `Drop` has one method, which is also called `drop()`. It takes a mutable
reference to `self`.
Thats it! The mechanics of `Drop` are very simple, but there are some
subtleties. For example, values are dropped in the opposite order they are
declared. Heres another example:
```rust
struct Firework {
strength: i32,
}
impl Drop for Firework {
fn drop(&mut self) {
println!("BOOM times {}!!!", self.strength);
}
}
fn main() {
let firecracker = Firework { strength: 1 };
let tnt = Firework { strength: 100 };
}
```
This will output:
```text
BOOM times 100!!!
BOOM times 1!!!
```
The TNT goes off before the firecracker does, because it was declared
afterwards. Last in, first out.
So what is `Drop` good for? Generally, `Drop` is used to clean up any resources
associated with a `struct`. For example, the [`Arc<T>` type][arc] is a
reference-counted type. When `Drop` is called, it will decrement the reference
count, and if the total number of references is zero, will clean up the
underlying value.
[arc]: ../std/sync/struct.Arc.html

View File

@ -1,147 +1,68 @@
% Enums % Enums
Finally, Rust has a "sum type", an *enum*. Enums are an incredibly useful An `enum` in Rust is a type that represents data that could be one of
feature of Rust, and are used throughout the standard library. An `enum` is several possible variants:
a type which relates a set of alternates to a specific name. For example, below
we define `Character` to be either a `Digit` or something else. These
can be used via their fully scoped names: `Character::Other` (more about `::`
below).
```rust ```rust
enum Character { enum Message {
Digit(i32), Quit,
Other, ChangeColor(i32, i32, i32),
Move { x: i32, y: i32 },
Write(String),
} }
``` ```
Most normal types are allowed as the variant components of an `enum`. Here are Each variant can optionally have data associated with it. The syntax for
some examples: defining variants resembles the syntaxes used to define structs: you can
have variants with no data (like unit-like structs), variants with named
data, and variants with unnamed data (like tuple structs). Unlike
separate struct definitions, however, an `enum` is a single type. A
value of the enum can match any of the variants. For this reason, an
enum is sometimes called a sum type: the set of possible values of the
enum is the sum of the sets of possible values for each variant.
We use the `::` syntax to use the name of each variant: theyre scoped by the name
of the `enum` itself. This allows both of these to work:
```rust ```rust
struct Empty; # enum Message {
struct Color(i32, i32, i32); # Move { x: i32, y: i32 },
struct Length(i32); # }
struct Status { Health: i32, Mana: i32, Attack: i32, Defense: i32 } let x: Message = Message::Move { x: 3, y: 4 };
struct HeightDatabase(Vec<i32>);
enum BoardGameTurn {
Move { squares: i32 },
Pass,
}
let y: BoardGameTurn = BoardGameTurn::Move { squares: 1 };
``` ```
You see that, depending on its type, an `enum` variant may or may not hold data. Both variants are named `Move`, but since theyre scoped to the name of
In `Character`, for instance, `Digit` gives a meaningful name for an `i32` the enum, they can both be used without conflict.
value, where `Other` is only a name. However, the fact that they represent
distinct categories of `Character` is a very useful property.
As with structures, the variants of an enum by default are not comparable with A value of an enum type contains information about which variant it is,
equality operators (`==`, `!=`), have no ordering (`<`, `>=`, etc.), and do not in addition to any data associated with that variant. This is sometimes
support other binary operations such as `*` and `+`. As such, the following code referred to as a tagged union, since the data includes a tag
is invalid for the example `Character` type: indicating what type it is. The compiler uses this information to
enforce that youre accessing the data in the enum safely. For instance,
you cant simply try to destructure a value as if it were one of the
possible variants:
```{rust,ignore} ```rust,ignore
// These assignments both succeed fn process_color_change(msg: Message) {
let ten = Character::Digit(10); let Message::ChangeColor(r, g, b) = msg; // compile-time error
let four = Character::Digit(4);
// Error: `*` is not implemented for type `Character`
let forty = ten * four;
// Error: `<=` is not implemented for type `Character`
let four_is_smaller = four <= ten;
// Error: `==` is not implemented for type `Character`
let four_equals_ten = four == ten;
```
This may seem rather limiting, but it's a limitation which we can overcome.
There are two ways: by implementing equality ourselves, or by pattern matching
variants with [`match`][match] expressions, which you'll learn in the next
chapter. We don't know enough about Rust to implement equality yet, but we can
use the `Ordering` enum from the standard library, which does:
```
enum Ordering {
Less,
Equal,
Greater,
} }
``` ```
Because `Ordering` has already been defined for us, we will import it with the Both variants are named `Digit`, but since theyre scoped to the `enum` name
`use` keyword. Here's an example of how it is used: there's no ambiguity.
```{rust} Not supporting these operations may seem rather limiting, but its a limitation
use std::cmp::Ordering; which we can overcome. There are two ways: by implementing equality ourselves,
or by pattern matching variants with [`match`][match] expressions, which youll
learn in the next section. We dont know enough about Rust to implement
equality yet, but well find out in the [`traits`][traits] section.
fn cmp(a: i32, b: i32) -> Ordering { [match]: match.html
if a < b { Ordering::Less } [if-let]: if-let.html
else if a > b { Ordering::Greater }
else { Ordering::Equal }
}
fn main() {
let x = 5;
let y = 10;
let ordering = cmp(x, y); // ordering: Ordering
if ordering == Ordering::Less {
println!("less");
} else if ordering == Ordering::Greater {
println!("greater");
} else if ordering == Ordering::Equal {
println!("equal");
}
}
```
The `::` symbol is used to indicate a namespace. In this case, `Ordering` lives
in the `cmp` submodule of the `std` module. We'll talk more about modules later
in the guide. For now, all you need to know is that you can `use` things from
the standard library if you need them.
Okay, let's talk about the actual code in the example. `cmp` is a function that
compares two things, and returns an `Ordering`. We return either
`Ordering::Less`, `Ordering::Greater`, or `Ordering::Equal`, depending on
whether the first value is less than, greater than, or equal to the second. Note
that each variant of the `enum` is namespaced under the `enum` itself: it's
`Ordering::Greater`, not `Greater`.
The `ordering` variable has the type `Ordering`, and so contains one of the
three values. We then do a bunch of `if`/`else` comparisons to check which
one it is.
This `Ordering::Greater` notation is too long. Let's use another form of `use`
to import the `enum` variants instead. This will avoid full scoping:
```{rust}
use std::cmp::Ordering::{self, Equal, Less, Greater};
fn cmp(a: i32, b: i32) -> Ordering {
if a < b { Less }
else if a > b { Greater }
else { Equal }
}
fn main() {
let x = 5;
let y = 10;
let ordering = cmp(x, y); // ordering: Ordering
if ordering == Less { println!("less"); }
else if ordering == Greater { println!("greater"); }
else if ordering == Equal { println!("equal"); }
}
```
Importing variants is convenient and compact, but can also cause name conflicts,
so do this with caution. For this reason, it's normally considered better style
to `use` an enum rather than its variants directly.
As you can see, `enum`s are quite a powerful tool for data representation, and
are even more useful when they're [generic][generics] across types. Before we
get to generics, though, let's talk about how to use enums with pattern
matching, a tool that will let us deconstruct sum types (the type theory term
for enums) like `Ordering` in a very elegant way that avoids all these messy
and brittle `if`/`else`s.
[match]: ./match.html
[generics]: ./generics.html

View File

@ -20,18 +20,18 @@ panic. A *failure* is an error that can be recovered from in some way. A
*panic* is an error that cannot be recovered from. *panic* is an error that cannot be recovered from.
What do we mean by "recover"? Well, in most cases, the possibility of an error What do we mean by "recover"? Well, in most cases, the possibility of an error
is expected. For example, consider the `from_str` function: is expected. For example, consider the `parse` function:
```{rust,ignore} ```ignore
from_str("5"); "5".parse();
``` ```
This function takes a string argument and converts it into another type. But This method converts a string into another type. But because it's a string, you
because it's a string, you can't be sure that the conversion actually works. can't be sure that the conversion actually works. For example, what should this
For example, what should this convert to? convert to?
```{rust,ignore} ```ignore
from_str("hello5world"); "hello5world".parse();
``` ```
This won't work. So we know that this function will only work properly for some This won't work. So we know that this function will only work properly for some
@ -40,7 +40,8 @@ inputs. It's expected behavior. We call this kind of error a *failure*.
On the other hand, sometimes, there are errors that are unexpected, or which On the other hand, sometimes, there are errors that are unexpected, or which
we cannot recover from. A classic example is an `assert!`: we cannot recover from. A classic example is an `assert!`:
```{rust,ignore} ```rust
# let x = 5;
assert!(x == 5); assert!(x == 5);
``` ```
@ -119,17 +120,19 @@ Rust calls these sorts of errors *panics*.
# Handling errors with `Option` and `Result` # Handling errors with `Option` and `Result`
The simplest way to indicate that a function may fail is to use the `Option<T>` The simplest way to indicate that a function may fail is to use the `Option<T>`
type. Remember our `from_str()` example? Here's its type signature: type. For example, the `find` method on strings attempts to find a pattern
in a string, and returns an `Option`:
```{rust,ignore} ```rust
pub fn from_str<A: FromStr>(s: &str) -> Option<A> let s = "foo";
assert_eq!(s.find('f'), Some(0));
assert_eq!(s.find('z'), None);
``` ```
`from_str()` returns an `Option<A>`. If the conversion succeeds, it will return
`Some(value)`, and if it fails, it will return `None`.
This is appropriate for the simplest of cases, but doesn't give us a lot of This is appropriate for the simplest of cases, but doesn't give us a lot of
information in the failure case. What if we wanted to know _why_ the conversion information in the failure case. What if we wanted to know _why_ the function
failed? For this, we can use the `Result<T, E>` type. It looks like this: failed? For this, we can use the `Result<T, E>` type. It looks like this:
```rust ```rust
@ -201,7 +204,7 @@ Because these kinds of situations are relatively rare, use panics sparingly.
In certain circumstances, even though a function may fail, we may want to treat In certain circumstances, even though a function may fail, we may want to treat
it as a panic instead. For example, `io::stdin().read_line(&mut buffer)` returns it as a panic instead. For example, `io::stdin().read_line(&mut buffer)` returns
an `Result<usize>`, when there is an error reading the line. This allows us to a `Result<usize>`, when there is an error reading the line. This allows us to
handle and possibly recover from error. handle and possibly recover from error.
If we don't want to handle this error, and would rather just abort the program, If we don't want to handle this error, and would rather just abort the program,
@ -211,7 +214,7 @@ we can use the `unwrap()` method:
io::stdin().read_line(&mut buffer).unwrap(); io::stdin().read_line(&mut buffer).unwrap();
``` ```
`unwrap()` will `panic!` if the `Option` is `None`. This basically says "Give `unwrap()` will `panic!` if the `Result` is `Err`. This basically says "Give
me the value, and if something goes wrong, just crash." This is less reliable me the value, and if something goes wrong, just crash." This is less reliable
than matching the error and attempting to recover, but is also significantly than matching the error and attempting to recover, but is also significantly
shorter. Sometimes, just crashing is appropriate. shorter. Sometimes, just crashing is appropriate.
@ -249,7 +252,7 @@ struct Info {
} }
fn write_info(info: &Info) -> io::Result<()> { fn write_info(info: &Info) -> io::Result<()> {
let mut file = File::open("my_best_friends.txt").unwrap(); let mut file = File::create("my_best_friends.txt").unwrap();
if let Err(e) = writeln!(&mut file, "name: {}", info.name) { if let Err(e) = writeln!(&mut file, "name: {}", info.name) {
return Err(e) return Err(e)
@ -279,7 +282,7 @@ struct Info {
} }
fn write_info(info: &Info) -> io::Result<()> { fn write_info(info: &Info) -> io::Result<()> {
let mut file = try!(File::open("my_best_friends.txt")); let mut file = try!(File::create("my_best_friends.txt"));
try!(writeln!(&mut file, "name: {}", info.name)); try!(writeln!(&mut file, "name: {}", info.name));
try!(writeln!(&mut file, "age: {}", info.age)); try!(writeln!(&mut file, "age: {}", info.age));
@ -297,5 +300,5 @@ It's worth noting that you can only use `try!` from a function that returns a
`Result`, which means that you cannot use `try!` inside of `main()`, because `Result`, which means that you cannot use `try!` inside of `main()`, because
`main()` doesn't return anything. `main()` doesn't return anything.
`try!` makes use of [`From<Error>`](../std/convert/trait.From.hml) to determine `try!` makes use of [`From<Error>`](../std/convert/trait.From.html) to determine
what to return in the error case. what to return in the error case.

View File

@ -1,31 +1,13 @@
% Generics % Generics
Sometimes, when writing a function or data type, we may want it to work for Sometimes, when writing a function or data type, we may want it to work for
multiple types of arguments. For example, remember our `OptionalInt` type? multiple types of arguments. Luckily, Rust has a feature that gives us a better
way: generics. Generics are called parametric polymorphism in type theory,
which means that they are types or functions that have multiple forms (poly
is multiple, morph is form) over a given parameter (parametric).
```{rust} Anyway, enough with type theory, lets check out some generic code. Rusts
enum OptionalInt { standard library provides a type, `Option<T>`, thats generic:
Value(i32),
Missing,
}
```
If we wanted to also have an `OptionalFloat64`, we would need a new enum:
```{rust}
enum OptionalFloat64 {
Valuef64(f64),
Missingf64,
}
```
This is really unfortunate. Luckily, Rust has a feature that gives us a better
way: generics. Generics are called *parametric polymorphism* in type theory,
which means that they are types or functions that have multiple forms (*poly*
is multiple, *morph* is form) over a given parameter (*parametric*).
Anyway, enough with type theory declarations, let's check out the generic form
of `OptionalInt`. It is actually provided by Rust itself, and looks like this:
```rust ```rust
enum Option<T> { enum Option<T> {
@ -34,41 +16,40 @@ enum Option<T> {
} }
``` ```
The `<T>` part, which you've seen a few times before, indicates that this is The `<T>` part, which youve seen a few times before, indicates that this is
a generic data type. Inside the declaration of our enum, wherever we see a `T`, a generic data type. Inside the declaration of our enum, wherever we see a `T`,
we substitute that type for the same type used in the generic. Here's an we substitute that type for the same type used in the generic. Heres an
example of using `Option<T>`, with some extra type annotations: example of using `Option<T>`, with some extra type annotations:
```{rust} ```rust
let x: Option<i32> = Some(5); let x: Option<i32> = Some(5);
``` ```
In the type declaration, we say `Option<i32>`. Note how similar this looks to In the type declaration, we say `Option<i32>`. Note how similar this looks to
`Option<T>`. So, in this particular `Option`, `T` has the value of `i32`. On `Option<T>`. So, in this particular `Option`, `T` has the value of `i32`. On
the right-hand side of the binding, we do make a `Some(T)`, where `T` is `5`. the right-hand side of the binding, we do make a `Some(T)`, where `T` is `5`.
Since that's an `i32`, the two sides match, and Rust is happy. If they didn't Since thats an `i32`, the two sides match, and Rust is happy. If they didnt
match, we'd get an error: match, wed get an error:
```{rust,ignore} ```rust,ignore
let x: Option<f64> = Some(5); let x: Option<f64> = Some(5);
// error: mismatched types: expected `core::option::Option<f64>`, // error: mismatched types: expected `core::option::Option<f64>`,
// found `core::option::Option<_>` (expected f64 but found integral variable) // found `core::option::Option<_>` (expected f64 but found integral variable)
``` ```
That doesn't mean we can't make `Option<T>`s that hold an `f64`! They just have to That doesnt mean we cant make `Option<T>`s that hold an `f64`! They just have
match up: to match up:
```{rust} ```rust
let x: Option<i32> = Some(5); let x: Option<i32> = Some(5);
let y: Option<f64> = Some(5.0f64); let y: Option<f64> = Some(5.0f64);
``` ```
This is just fine. One definition, multiple uses. This is just fine. One definition, multiple uses.
Generics don't have to only be generic over one type. Consider Rust's built-in Generics dont have to only be generic over one type. Consider another type from Rusts standard library thats similar, `Result<T, E>`:
`Result<T, E>` type:
```{rust} ```rust
enum Result<T, E> { enum Result<T, E> {
Ok(T), Ok(T),
Err(E), Err(E),
@ -76,9 +57,9 @@ enum Result<T, E> {
``` ```
This type is generic over _two_ types: `T` and `E`. By the way, the capital letters This type is generic over _two_ types: `T` and `E`. By the way, the capital letters
can be any letter you'd like. We could define `Result<T, E>` as: can be any letter youd like. We could define `Result<T, E>` as:
```{rust} ```rust
enum Result<A, Z> { enum Result<A, Z> {
Ok(A), Ok(A),
Err(Z), Err(Z),
@ -86,92 +67,58 @@ enum Result<A, Z> {
``` ```
if we wanted to. Convention says that the first generic parameter should be if we wanted to. Convention says that the first generic parameter should be
`T`, for 'type,' and that we use `E` for 'error.' Rust doesn't care, however. `T`, for type, and that we use `E` for error. Rust doesnt care, however.
The `Result<T, E>` type is intended to be used to return the result of a The `Result<T, E>` type is intended to be used to return the result of a
computation, and to have the ability to return an error if it didn't work out. computation, and to have the ability to return an error if it didnt work out.
Here's an example:
```{rust} ## Generic functions
let x: Result<f64, String> = Ok(2.3f64);
let y: Result<f64, String> = Err("There was an error.".to_string());
```
This particular Result will return an `f64` if there's a success, and a We can write functions that take generic types with a similar syntax:
`String` if there's a failure. Let's write a function that uses `Result<T, E>`:
```{rust} ```rust
fn inverse(x: f64) -> Result<f64, String> { fn takes_anything<T>(x: T) {
if x == 0.0f64 { return Err("x cannot be zero!".to_string()); } // do something with x
Ok(1.0f64 / x)
} }
``` ```
We don't want to take the inverse of zero, so we check to make sure that we The syntax has two parts: the `<T>` says “this function is generic over one
weren't passed zero. If we were, then we return an `Err`, with a message. If type, `T`”, and the `x: T` says “x has the type `T`.”
it's okay, we return an `Ok`, with the answer.
Why does this matter? Well, remember how `match` does exhaustive matches? Multiple arguments can have the same generic type:
Here's how this function gets used:
```{rust} ```rust
# fn inverse(x: f64) -> Result<f64, String> { fn takes_two_of_the_same_things<T>(x: T, y: T) {
# if x == 0.0f64 { return Err("x cannot be zero!".to_string()); } // ...
# Ok(1.0f64 / x)
# }
let x = inverse(25.0f64);
match x {
Ok(x) => println!("The inverse of 25 is {}", x),
Err(msg) => println!("Error: {}", msg),
} }
``` ```
The `match` enforces that we handle the `Err` case. In addition, because the We could write a version that takes multiple types:
answer is wrapped up in an `Ok`, we can't just use the result without doing
the match:
```{rust,ignore} ```rust
let x = inverse(25.0f64); fn takes_two_things<T, U>(x: T, y: U) {
println!("{}", x + 2.0f64); // error: binary operation `+` cannot be applied // ...
// to type `core::result::Result<f64,collections::string::String>`
```
This function is great, but there's one other problem: it only works for 64 bit
floating point values. What if we wanted to handle 32 bit floating point as
well? We'd have to write this:
```{rust}
fn inverse32(x: f32) -> Result<f32, String> {
if x == 0.0f32 { return Err("x cannot be zero!".to_string()); }
Ok(1.0f32 / x)
} }
``` ```
Bummer. What we need is a *generic function*. Luckily, we can write one! Generic functions are most useful with trait bounds, which well cover in the
However, it won't _quite_ work yet. Before we get into that, let's talk syntax. [section on traits][traits].
A generic version of `inverse` would look something like this:
```{rust,ignore} [traits]: traits.html
fn inverse<T>(x: T) -> Result<T, String> {
if x == 0.0 { return Err("x cannot be zero!".to_string()); }
Ok(1.0 / x) ## Generic structs
You can store a generic type in a `struct` as well:
```
struct Point<T> {
x: T,
y: T,
} }
let int_origin = Point { x: 0, y: 0 };
let float_origin = Point { x: 0.0, y: 0.0 };
``` ```
Just like how we had `Option<T>`, we use a similar syntax for `inverse<T>`. Similarly to functions, the `<T>` is where we declare the generic parameters,
We can then use `T` inside the rest of the signature: `x` has type `T`, and half and we then use `x: T` in the type declaration, too.
of the `Result` has type `T`. However, if we try to compile that example, we'll get
an error:
```text
error: binary operation `==` cannot be applied to type `T`
```
Because `T` can be _any_ type, it may be a type that doesn't implement `==`,
and therefore, the first line would be wrong. What do we do?
To fix this example, we need to learn about another Rust feature: traits.

View File

@ -1,5 +1,5 @@
% Getting Started % Getting Started
This first section of the book will get you going with Rust and its tooling. This first section of the book will get you going with Rust and its tooling.
First, well install Rust. Then: the classic Hello World program. Finally, First, well install Rust. Then, the classic Hello World program. Finally,
well talk about Cargo, Rusts build system and package manager. well talk about Cargo, Rusts build system and package manager.

View File

@ -19,7 +19,7 @@ In the example above `x` and `y` have arity 2. `z` has arity 3.
When a compiler is compiling your program, it does a number of different When a compiler is compiling your program, it does a number of different
things. One of the things that it does is turn the text of your program into an things. One of the things that it does is turn the text of your program into an
'abstract syntax tree,' or 'AST.' This tree is a representation of the abstract syntax tree, orAST. This tree is a representation of the
structure of your program. For example, `2 + 3` can be turned into a tree: structure of your program. For example, `2 + 3` can be turned into a tree:
```text ```text

File diff suppressed because it is too large Load Diff

View File

@ -5,7 +5,7 @@ projects. Cargo is currently in a pre-1.0 state, and so it is still a work in
progress. However, it is already good enough to use for many Rust projects, and progress. However, it is already good enough to use for many Rust projects, and
so it is assumed that Rust projects will use Cargo from the beginning. so it is assumed that Rust projects will use Cargo from the beginning.
[cratesio]: https://doc.crates.io [cratesio]: http://doc.crates.io
Cargo manages three things: building your code, downloading the dependencies Cargo manages three things: building your code, downloading the dependencies
your code needs, and building those dependencies. At first, your your code needs, and building those dependencies. At first, your
@ -32,6 +32,13 @@ $ mkdir src
$ mv main.rs src/main.rs $ mv main.rs src/main.rs
``` ```
Note that since we're creating an executable, we used `main.rs`. If we
want to make a library instead, we should use `lib.rs`.
Custom file locations for the entry point can be specified
with a [`[[lib]]` or `[[bin]]`][crates-custom] key in the TOML file described below.
[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 your source files to live inside a `src` directory. That leaves
the top level for other things, like READMEs, license information, and anything the top level for other things, like READMEs, license information, and anything
not related to your code. Cargo helps us keep our projects nice and tidy. A not related to your code. Cargo helps us keep our projects nice and tidy. A
@ -89,7 +96,7 @@ we hadnt changed the source file, and so it just ran the binary. If we had
made a modification, we would have seen it do both: made a modification, we would have seen it do both:
```bash ```bash
$ cargo build $ cargo run
Compiling hello_world v0.0.1 (file:///home/yourname/projects/hello_world) Compiling hello_world v0.0.1 (file:///home/yourname/projects/hello_world)
Running `target/debug/hello_world` Running `target/debug/hello_world`
Hello, world! Hello, world!

View File

@ -147,7 +147,7 @@ $ ./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 dynamically typed language like Ruby, Python, or JavaScript, If you come from a dynamic language like Ruby, Python, or JavaScript,
you may not be used to these two steps being separate. Rust is an you may not be used to these two steps being separate. Rust is an
ahead-of-time compiled language, which means that you can compile a program, ahead-of-time compiled language, which means that you can compile a program,
give it to someone else, and they don't need to have Rust installed. If you give it to someone else, and they don't need to have Rust installed. If you

View File

@ -1,3 +1,82 @@
% if let % if let
COMING SOON `if let` allows you to combine `if` and `let` together to reduce the overhead
of certain kinds of pattern matches.
For example, lets say we have some sort of `Option<T>`. We want to call a function
on it if its `Some<T>`, but do nothing if its `None`. That looks like this:
```rust
# let option = Some(5);
# fn foo(x: i32) { }
match option {
Some(x) => { foo(x) },
None => {},
}
```
We dont have to use `match` here, for example, we could use `if`:
```rust
# let option = Some(5);
# fn foo(x: i32) { }
if option.is_some() {
let x = option.unwrap();
foo(x);
}
```
Neither of these options is particularly appealing. We can use `if let` to
do the same thing in a nicer way:
```rust
# let option = Some(5);
# fn foo(x: i32) { }
if let Some(x) = option {
foo(x);
}
```
If a [pattern][patterns] matches successfully, it binds any appropriate parts of
the value to the identifiers in the pattern, then evaluates the expression. If
the pattern doesnt match, nothing happens.
If youd rather to do something else when the pattern does not match, you can
use `else`:
```rust
# let option = Some(5);
# fn foo(x: i32) { }
# fn bar() { }
if let Some(x) = option {
foo(x);
} else {
bar();
}
```
## `while let`
In a similar fashion, `while let` can be used when you want to conditionally
loop as long as a value matches a certain pattern. It turns code like this:
```rust
# let option: Option<i32> = None;
loop {
match option {
Some(x) => println!("{}", x),
_ => break,
}
}
```
Into code like this:
```rust
# let option: Option<i32> = None;
while let Some(x) = option {
println!("{}", x);
}
```
[patterns]: patterns.html

View File

@ -58,7 +58,7 @@ but you must add the right number of `:` if you skip them:
asm!("xor %eax, %eax" asm!("xor %eax, %eax"
: :
: :
: "eax" : "{eax}"
); );
# } } # } }
``` ```
@ -69,7 +69,7 @@ Whitespace also doesn't matter:
# #![feature(asm)] # #![feature(asm)]
# #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] # #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
# fn main() { unsafe { # fn main() { unsafe {
asm!("xor %eax, %eax" ::: "eax"); asm!("xor %eax, %eax" ::: "{eax}");
# } } # } }
``` ```
@ -77,13 +77,13 @@ asm!("xor %eax, %eax" ::: "eax");
Input and output operands follow the same format: `: Input and output operands follow the same format: `:
"constraints1"(expr1), "constraints2"(expr2), ..."`. Output operand "constraints1"(expr1), "constraints2"(expr2), ..."`. Output operand
expressions must be mutable lvalues: expressions must be mutable lvalues, or not yet assigned:
``` ```
# #![feature(asm)] # #![feature(asm)]
# #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] # #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
fn add(a: i32, b: i32) -> i32 { fn add(a: i32, b: i32) -> i32 {
let mut c = 0; let c: i32;
unsafe { unsafe {
asm!("add $2, $0" asm!("add $2, $0"
: "=r"(c) : "=r"(c)
@ -100,6 +100,22 @@ fn main() {
} }
``` ```
If you would like to use real operands in this position, however,
you are required to put curly braces `{}` around the register that
you want, and you are required to put the specific size of the
operand. This is useful for very low level programming, where
which register you use is important:
```
# #![feature(asm)]
# #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
# unsafe fn read_byte_in(port: u16) -> u8 {
let result: u8;
asm!("in %dx, %al" : "={al}"(result) : "{dx}"(port));
result
# }
```
## Clobbers ## Clobbers
Some instructions modify registers which might otherwise have held Some instructions modify registers which might otherwise have held
@ -112,7 +128,7 @@ stay valid.
# #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] # #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
# fn main() { unsafe { # fn main() { unsafe {
// Put the value 0x200 in eax // Put the value 0x200 in eax
asm!("mov $$0x200, %eax" : /* no outputs */ : /* no inputs */ : "eax"); asm!("mov $$0x200, %eax" : /* no outputs */ : /* no inputs */ : "{eax}");
# } } # } }
``` ```
@ -139,3 +155,14 @@ Current valid options are:
the compiler to insert its usual stack alignment code the compiler to insert its usual stack alignment code
3. *intel* - use intel syntax instead of the default AT&T. 3. *intel* - use intel syntax instead of the default AT&T.
```
# #![feature(asm)]
# #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
# fn main() {
let result: i32;
unsafe {
asm!("mov eax, 2" : "={eax}"(result) : : : "intel")
}
println!("eax is currently {}", result);
# }
```

View File

@ -6,16 +6,16 @@ or a Mac, all you need to do is this (note that you don't need to type in the
`$`s, they just indicate the start of each command): `$`s, they just indicate the start of each command):
```bash ```bash
$ curl -sf -L https://static.rust-lang.org/rustup.sh | sudo 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 you're concerned about the [potential insecurity][insecurity] of using `curl
| sudo 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 two-step version of the installation and examine our installation script: use a 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
$ sudo sh rustup.sh $ sh rustup.sh
``` ```
[insecurity]: http://curlpipesh.tumblr.com [insecurity]: http://curlpipesh.tumblr.com
@ -40,13 +40,11 @@ If you used the Windows installer, just re-run the `.msi` and it will give you
an uninstall option. an uninstall option.
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 you to
`curl | sudo sh`. Basically, when you do this, you are trusting that the good `curl | sh`. Basically, when you do this, you are trusting that the good
people who maintain Rust aren't going to hack your computer and do bad things. people who maintain Rust aren't going to hack your computer and do bad things.
That's a good instinct! If you're one of those people, please check out the That's a good instinct! If you're one of those people, please check out the
documentation on [building Rust from Source][from source], or [the official documentation on [building Rust from Source][from source], or [the official
binary downloads][install page]. And we promise that this method will not be binary downloads][install page].
the way to install Rust forever: it's just the easiest way to keep people
updated while Rust is in its alpha state.
[from source]: https://github.com/rust-lang/rust#building-from-source [from source]: https://github.com/rust-lang/rust#building-from-source
[install page]: http://www.rust-lang.org/install.html [install page]: http://www.rust-lang.org/install.html
@ -91,9 +89,9 @@ If not, there are a number of places where you can get help. The easiest is
[Mibbit][mibbit]. Click that link, and you'll be chatting with other Rustaceans [Mibbit][mibbit]. Click that link, and you'll be chatting with other Rustaceans
(a silly nickname we call ourselves), and we can help you out. Other great (a silly nickname we call ourselves), and we can help you out. Other great
resources include [the users forum][users], and resources include [the users forum][users], and
[Stack Overflow][stack overflow]. [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
[users]: http://users.rust-lang.org/ [users]: http://users.rust-lang.org/
[stack overflow]: http://stackoverflow.com/questions/tagged/rust [stackoverflow]: http://stackoverflow.com/questions/tagged/rust

View File

@ -42,7 +42,7 @@ 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 threads. Before we talk about those, we should talk about a
Rust anti-pattern. And that's using ranges like this. Rust anti-pattern. And that's using ranges like this.
Yes, we just talked about how ranges are cool. But ranges are also very Yes, we just talked about how ranges are cool. But ranges are also very
@ -212,9 +212,9 @@ see why consumers matter.
As we've said before, an iterator is something that we can call the As we've said before, an iterator is something that we can call the
`.next()` method on repeatedly, and it gives us a sequence of things. `.next()` method on repeatedly, and it gives us a sequence of things.
Because you need to call the method, this means that iterators Because you need to call the method, this means that iterators
are *lazy* and don't need to generate all of the values upfront. can be *lazy* and not generate all of the values upfront. This code,
This code, for example, does not actually generate the numbers for example, does not actually generate the numbers `1-100`, instead
`1-100`, and just creates a value that represents the sequence: creating a value that merely represents the sequence:
```rust ```rust
let nums = 1..100; let nums = 1..100;
@ -235,7 +235,7 @@ Ranges are one of two basic iterators that you'll see. The other is `iter()`.
in turn: in turn:
```rust ```rust
let nums = [1, 2, 3]; let nums = vec![1, 2, 3];
for num in nums.iter() { for num in nums.iter() {
println!("{}", num); println!("{}", num);
@ -243,18 +243,7 @@ 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. Like using range syntax advanced iterators, including ones that are infinite.
and `step_by`:
```rust
# #![feature(step_by)]
(1..).step_by(5);
```
This iterator counts up from one, adding five each time. It will give
you a new integer every time, forever (well, technically, until it reaches the
maximum number representable by an `i32`). But since iterators are lazy,
that's okay! You probably don't want to use `collect()` on it, though...
That's enough about iterators. Iterator adapters are the last concept That's enough about iterators. Iterator adapters 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!

View File

@ -7,7 +7,7 @@
The `rustc` compiler has certain pluggable operations, that is, The `rustc` compiler has certain pluggable operations, that is,
functionality that isn't hard-coded into the language, but is functionality that isn't hard-coded into the language, but is
implemented in libraries, with a special marker to tell the compiler implemented in libraries, with a special marker to tell the compiler
it exists. The marker is the attribute `#[lang="..."]` and there are it exists. The marker is the attribute `#[lang = "..."]` and there are
various different values of `...`, i.e. various different 'lang various different values of `...`, i.e. various different 'lang
items'. items'.
@ -28,7 +28,7 @@ extern {
#[lang = "owned_box"] #[lang = "owned_box"]
pub struct Box<T>(*mut T); pub struct Box<T>(*mut T);
#[lang="exchange_malloc"] #[lang = "exchange_malloc"]
unsafe fn allocate(size: usize, _align: usize) -> *mut u8 { unsafe fn allocate(size: usize, _align: usize) -> *mut u8 {
let p = libc::malloc(size as libc::size_t) as *mut u8; let p = libc::malloc(size as libc::size_t) as *mut u8;
@ -39,7 +39,7 @@ unsafe fn allocate(size: usize, _align: usize) -> *mut u8 {
p p
} }
#[lang="exchange_free"] #[lang = "exchange_free"]
unsafe fn deallocate(ptr: *mut u8, _size: usize, _align: usize) { unsafe fn deallocate(ptr: *mut u8, _size: usize, _align: usize) {
libc::free(ptr as *mut libc::c_void) libc::free(ptr as *mut libc::c_void)
} }

View File

@ -1,4 +1,9 @@
% Learn Rust % Learn Rust
This section is coming soon! It will eventually have a few tutorials with Welcome! This section has a few tutorials that teach you Rust through building
building real Rust projects, but they are under development. projects. Youll get a high-level overview, but well skim over the details.
If youd prefer a more from the ground up-style experience, check
out [Syntax and Semantics][ss].
[ss]: syntax-and-semantics.html

View File

@ -1,3 +1,297 @@
% Lifetimes % Lifetimes
Coming soon! This guide is one of three presenting Rusts ownership system. This is one of
Rusts most unique and compelling features, with which Rust developers should
become quite acquainted. Ownership is how Rust achieves its largest goal,
memory safety. There are a few distinct concepts, each with its own chapter:
* [ownership][ownership], the key concept
* [borrowing][borrowing], and their associated feature references
* lifetimes, which youre reading now
These three chapters are related, and in order. Youll need all three to fully
understand the ownership system.
[ownership]: ownership.html
[borrowing]: references-and-borrowing.html
# Meta
Before we get to the details, two important notes about the ownership system.
Rust has a focus on safety and speed. It accomplishes these goals through many
zero-cost abstractions, which means that in Rust, abstractions cost as little
as possible in order to make them work. The ownership system is a prime example
of a zero-cost abstraction. All of the analysis well talk about in this guide
is _done at compile time_. You do not pay any run-time cost for any of these
features.
However, this system does have a certain cost: learning curve. Many new users
to Rust experience something we like to call fighting with the borrow
checker, where the Rust compiler refuses to compile a program that the author
thinks is valid. This often happens because the programmers mental model of
how ownership should work doesnt match the actual rules that Rust implements.
You probably will experience similar things at first. There is good news,
however: more experienced Rust developers report that once they work with the
rules of the ownership system for a period of time, they fight the borrow
checker less and less.
With that in mind, lets learn about lifetimes.
# Lifetimes
Lending out a reference to a resource that someone else owns can be
complicated. For example, imagine this set of operations:
- I acquire a handle to some kind of resource.
- I lend you a reference to the resource.
- I decide Im done with the resource, and deallocate it, while you still have
your reference.
- You decide to use the resource.
Uh oh! Your reference is pointing to an invalid resource. This is called a
dangling pointer or use after free, when the resource is memory.
To fix this, we have to make sure that step four never happens after step
three. The ownership system in Rust does this through a concept called
lifetimes, which describe the scope that a reference is valid for.
When we have a function that takes a reference by argument, we can be implicit
or explicit about the lifetime of the reference:
```rust
// implicit
fn foo(x: &i32) {
}
// explicit
fn bar<'a>(x: &'a i32) {
}
```
The `'a` reads the lifetime a. Technically, every reference has some lifetime
associated with it, but the compiler lets you elide them in common cases.
Before we get to that, though, lets break the explicit example down:
```rust,ignore
fn bar<'a>(...)
```
This part declares our lifetimes. This says that `bar` has one lifetime, `'a`.
If we had two reference parameters, it would look like this:
```rust,ignore
fn bar<'a, 'b>(...)
```
Then in our parameter list, we use the lifetimes weve named:
```rust,ignore
...(x: &'a i32)
```
If we wanted an `&mut` reference, wed do this:
```rust,ignore
...(x: &'a mut i32)
```
If you compare `&mut i32` to `&'a mut i32`, theyre the same, its just that
the lifetime `'a` has snuck in between the `&` and the `mut i32`. We read `&mut
i32` as a mutable reference to an i32 and `&'a mut i32` as a mutable
reference to an `i32` with the lifetime `'a`.
Youll also need explicit lifetimes when working with [`struct`][structs]s:
```rust
struct Foo<'a> {
x: &'a i32,
}
fn main() {
let y = &5; // this is the same as `let _y = 5; let y = &_y;`
let f = Foo { x: y };
println!("{}", f.x);
}
```
[structs]: structs.html
As you can see, `struct`s can also have lifetimes. In a similar way to functions,
```rust
struct Foo<'a> {
# x: &'a i32,
# }
```
declares a lifetime, and
```rust
# struct Foo<'a> {
x: &'a i32,
# }
```
uses it. So why do we need a lifetime here? We need to ensure that any reference
to a `Foo` cannot outlive the reference to an `i32` it contains.
## Thinking in scopes
A way to think about lifetimes is to visualize the scope that a reference is
valid for. For example:
```rust
fn main() {
let y = &5; // -+ y goes into scope
// |
// stuff // |
// |
} // -+ y goes out of scope
```
Adding in our `Foo`:
```rust
struct Foo<'a> {
x: &'a i32,
}
fn main() {
let y = &5; // -+ y goes into scope
let f = Foo { x: y }; // -+ f goes into scope
// stuff // |
// |
} // -+ f and y go out of scope
```
Our `f` lives within the scope of `y`, so everything works. What if it didnt?
This code wont work:
```rust,ignore
struct Foo<'a> {
x: &'a i32,
}
fn main() {
let x; // -+ x goes into scope
// |
{ // |
let y = &5; // ---+ y goes into scope
let f = Foo { x: y }; // ---+ f goes into scope
x = &f.x; // | | error here
} // ---+ f and y go out of scope
// |
println!("{}", x); // |
} // -+ x goes out of scope
```
Whew! As you can see here, the scopes of `f` and `y` are smaller than the scope
of `x`. But when we do `x = &f.x`, we make `x` a reference to something thats
about to go out of scope.
Named lifetimes are a way of giving these scopes a name. Giving something a
name is the first step towards being able to talk about it.
## 'static
The lifetime named static is a special lifetime. It signals that something
has the lifetime of the entire program. Most Rust programmers first come across
`'static` when dealing with strings:
```rust
let x: &'static str = "Hello, world.";
```
String literals have the type `&'static str` because the reference is always
alive: they are baked into the data segment of the final binary. Another
example are globals:
```rust
static FOO: i32 = 5;
let x: &'static i32 = &FOO;
```
This adds an `i32` to the data segment of the binary, and `x` is a reference
to it.
## Lifetime Elision
Rust supports powerful local type inference in function bodies, but its
forbidden in item signatures to allow reasoning about the types just based in
the item signature alone. However, for ergonomic reasons a very restricted
secondary inference algorithm called “lifetime elision” applies in function
signatures. It infers only based on the signature components themselves and not
based on the body of the function, only infers lifetime parameters, and does
this with only three easily memorizable and unambiguous rules. This makes
lifetime elision a shorthand for writing an item signature, while not hiding
away the actual types involved as full local inference would if applied to it.
When talking about lifetime elision, we use the term *input lifetime* and
*output lifetime*. An *input lifetime* is a lifetime associated with a parameter
of a function, and an *output lifetime* is a lifetime associated with the return
value of a function. For example, this function has an input lifetime:
```rust,ignore
fn foo<'a>(bar: &'a str)
```
This one has an output lifetime:
```rust,ignore
fn foo<'a>() -> &'a str
```
This one has a lifetime in both positions:
```rust,ignore
fn foo<'a>(bar: &'a str) -> &'a str
```
Here are the three rules:
* Each elided lifetime in a functions arguments becomes a distinct lifetime
parameter.
* If there is exactly one input lifetime, elided or not, that lifetime is
assigned to all elided lifetimes in the return values of that function.
* If there are multiple input lifetimes, but one of them is `&self` or `&mut
self`, the lifetime of `self` is assigned to all elided output lifetimes.
Otherwise, it is an error to elide an output lifetime.
### Examples
Here are some examples of functions with elided lifetimes. Weve paired each
example of an elided lifetime with its expanded form.
```rust,ignore
fn print(s: &str); // elided
fn print<'a>(s: &'a str); // expanded
fn debug(lvl: u32, s: &str); // elided
fn debug<'a>(lvl: u32, s: &'a str); // expanded
// In the preceding example, `lvl` doesnt need a lifetime because its not a
// reference (`&`). Only things relating to references (such as a `struct`
// which contains a reference) need lifetimes.
fn substr(s: &str, until: u32) -> &str; // elided
fn substr<'a>(s: &'a str, until: u32) -> &'a str; // expanded
fn get_str() -> &str; // ILLEGAL, no inputs
fn frob(s: &str, t: &str) -> &str; // ILLEGAL, two inputs
fn frob<'a, 'b>(s: &'a str, t: &'b str) -> &str; // Expanded: Output lifetime is unclear
fn get_mut(&mut self) -> &mut T; // elided
fn get_mut<'a>(&'a mut self) -> &'a mut T; // expanded
fn args<T:ToCStr>(&mut self, args: &[T]) -> &mut Command // elided
fn args<'a, 'b, T:ToCStr>(&'a mut self, args: &'b [T]) -> &'a mut Command // expanded
fn new(buf: &mut [u8]) -> BufWriter; // elided
fn new<'a>(buf: &'a mut [u8]) -> BufWriter<'a> // expanded
```

View File

@ -1,20 +1,20 @@
% Macros % Macros
By now you've learned about many of the tools Rust provides for abstracting and By now youve learned about many of the tools Rust provides for abstracting and
reusing code. These units of code reuse have a rich semantic structure. For reusing code. These units of code reuse have a rich semantic structure. For
example, functions have a type signature, type parameters have trait bounds, example, functions have a type signature, type parameters have trait bounds,
and overloaded functions must belong to a particular trait. and overloaded functions must belong to a particular trait.
This structure means that Rust's core abstractions have powerful compile-time This structure means that Rusts core abstractions have powerful compile-time
correctness checking. But this comes at the price of reduced flexibility. If correctness checking. But this comes at the price of reduced flexibility. If
you visually identify a pattern of repeated code, you may find it's difficult you visually identify a pattern of repeated code, you may find its difficult
or cumbersome to express that pattern as a generic function, a trait, or or cumbersome to express that pattern as a generic function, a trait, or
anything else within Rust's semantics. anything else within Rusts semantics.
Macros allow us to abstract at a *syntactic* level. A macro invocation is Macros allow us to abstract at a syntactic level. A macro invocation is
shorthand for an "expanded" syntactic form. This expansion happens early in shorthand for an "expanded" syntactic form. This expansion happens early in
compilation, before any static checking. As a result, macros can capture many compilation, before any static checking. As a result, macros can capture many
patterns of code reuse that Rust's core abstractions cannot. patterns of code reuse that Rusts core abstractions cannot.
The drawback is that macro-based code can be harder to understand, because The drawback is that macro-based code can be harder to understand, because
fewer of the built-in rules apply. Like an ordinary function, a well-behaved fewer of the built-in rules apply. Like an ordinary function, a well-behaved
@ -23,8 +23,8 @@ difficult to design a well-behaved macro! Additionally, compiler errors in
macro code are harder to interpret, because they describe problems in the macro code are harder to interpret, because they describe problems in the
expanded code, not the source-level form that developers use. expanded code, not the source-level form that developers use.
These drawbacks make macros something of a "feature of last resort". That's not These drawbacks make macros something of a "feature of last resort". Thats not
to say that macros are bad; they are part of Rust because sometimes they're to say that macros are bad; they are part of Rust because sometimes theyre
needed for truly concise, well-abstracted code. Just keep this tradeoff in needed for truly concise, well-abstracted code. Just keep this tradeoff in
mind. mind.
@ -33,14 +33,14 @@ mind.
You may have seen the `vec!` macro, used to initialize a [vector][] with any You may have seen the `vec!` macro, used to initialize a [vector][] with any
number of elements. number of elements.
[vector]: arrays-vectors-and-slices.html [vector]: vectors.html
```rust ```rust
let x: Vec<u32> = vec![1, 2, 3]; let x: Vec<u32> = vec![1, 2, 3];
# assert_eq!(x, [1, 2, 3]); # assert_eq!(x, [1, 2, 3]);
``` ```
This can't be an ordinary function, because it takes any number of arguments. This cant be an ordinary function, because it takes any number of arguments.
But we can imagine it as syntactic shorthand for But we can imagine it as syntactic shorthand for
```rust ```rust
@ -57,8 +57,7 @@ let x: Vec<u32> = {
We can implement this shorthand, using a macro: [^actual] We can implement this shorthand, using a macro: [^actual]
[^actual]: The actual definition of `vec!` in libcollections differs from the [^actual]: The actual definition of `vec!` in libcollections differs from the
one presented here, for reasons of efficiency and reusability. Some one presented here, for reasons of efficiency and reusability.
of these are mentioned in the [advanced macros chapter][].
```rust ```rust
macro_rules! vec { macro_rules! vec {
@ -77,20 +76,20 @@ macro_rules! vec {
# } # }
``` ```
Whoa, that's a lot of new syntax! Let's break it down. Whoa, thats a lot of new syntax! Lets break it down.
```ignore ```ignore
macro_rules! vec { ... } macro_rules! vec { ... }
``` ```
This says we're defining a macro named `vec`, much as `fn vec` would define a This says were defining a macro named `vec`, much as `fn vec` would define a
function named `vec`. In prose, we informally write a macro's name with an function named `vec`. In prose, we informally write a macros name with an
exclamation point, e.g. `vec!`. The exclamation point is part of the invocation exclamation point, e.g. `vec!`. The exclamation point is part of the invocation
syntax and serves to distinguish a macro from an ordinary function. syntax and serves to distinguish a macro from an ordinary function.
## Matching ## Matching
The macro is defined through a series of *rules*, which are pattern-matching The macro is defined through a series of rules, which are pattern-matching
cases. Above, we had cases. Above, we had
```ignore ```ignore
@ -99,14 +98,14 @@ cases. Above, we had
This is like a `match` expression arm, but the matching happens on Rust syntax This is like a `match` expression arm, but the matching happens on Rust syntax
trees, at compile time. The semicolon is optional on the last (here, only) trees, at compile time. The semicolon is optional on the last (here, only)
case. The "pattern" on the left-hand side of `=>` is known as a *matcher*. case. The "pattern" on the left-hand side of `=>` is known as a matcher.
These have [their own little grammar] within the language. These have [their own little grammar] within the language.
[their own little grammar]: ../reference.html#macros [their own little grammar]: ../reference.html#macros
The matcher `$x:expr` will match any Rust expression, binding that syntax tree The matcher `$x:expr` will match any Rust expression, binding that syntax tree
to the *metavariable* `$x`. The identifier `expr` is a *fragment specifier*; to the metavariable `$x`. The identifier `expr` is a fragment specifier;
the full possibilities are enumerated in the [advanced macros chapter][]. the full possibilities are enumerated later in this chapter.
Surrounding the matcher with `$(...),*` will match zero or more expressions, Surrounding the matcher with `$(...),*` will match zero or more expressions,
separated by commas. separated by commas.
@ -158,8 +157,8 @@ Each matched expression `$x` will produce a single `push` statement in the
macro expansion. The repetition in the expansion proceeds in "lockstep" with macro expansion. The repetition in the expansion proceeds in "lockstep" with
repetition in the matcher (more on this in a moment). repetition in the matcher (more on this in a moment).
Because `$x` was already declared as matching an expression, we don't repeat Because `$x` was already declared as matching an expression, we dont repeat
`:expr` on the right-hand side. Also, we don't include a separating comma as `:expr` on the right-hand side. Also, we dont include a separating comma as
part of the repetition operator. Instead, we have a terminating semicolon part of the repetition operator. Instead, we have a terminating semicolon
within the repeated block. within the repeated block.
@ -180,7 +179,7 @@ The outer braces are part of the syntax of `macro_rules!`. In fact, you can use
The inner braces are part of the expanded syntax. Remember, the `vec!` macro is The inner braces are part of the expanded syntax. Remember, the `vec!` macro is
used in an expression context. To write an expression with multiple statements, used in an expression context. To write an expression with multiple statements,
including `let`-bindings, we use a block. If your macro expands to a single including `let`-bindings, we use a block. If your macro expands to a single
expression, you don't need this extra layer of braces. expression, you dont need this extra layer of braces.
Note that we never *declared* that the macro produces an expression. In fact, Note that we never *declared* that the macro produces an expression. In fact,
this is not determined until we use the macro as an expression. With care, you this is not determined until we use the macro as an expression. With care, you
@ -194,7 +193,7 @@ The repetition operator follows two principal rules:
1. `$(...)*` walks through one "layer" of repetitions, for all of the `$name`s 1. `$(...)*` walks through one "layer" of repetitions, for all of the `$name`s
it contains, in lockstep, and it contains, in lockstep, and
2. each `$name` must be under at least as many `$(...)*`s as it was matched 2. each `$name` must be under at least as many `$(...)*`s as it was matched
against. If it is under more, it'll be duplicated, as appropriate. against. If it is under more, itll be duplicated, as appropriate.
This baroque macro illustrates the duplication of variables from outer This baroque macro illustrates the duplication of variables from outer
repetition levels. repetition levels.
@ -219,7 +218,7 @@ fn main() {
} }
``` ```
That's most of the matcher syntax. These examples use `$(...)*`, which is a Thats most of the matcher syntax. These examples use `$(...)*`, which is a
"zero or more" match. Alternatively you can write `$(...)+` for a "one or "zero or more" match. Alternatively you can write `$(...)+` for a "one or
more" match. Both forms optionally include a separator, which can be any token more" match. Both forms optionally include a separator, which can be any token
except `+` or `*`. except `+` or `*`.
@ -244,9 +243,9 @@ int main() {
``` ```
After expansion we have `5 * 2 + 3`, and multiplication has greater precedence After expansion we have `5 * 2 + 3`, and multiplication has greater precedence
than addition. If you've used C macros a lot, you probably know the standard than addition. If youve used C macros a lot, you probably know the standard
idioms for avoiding this problem, as well as five or six others. In Rust, we idioms for avoiding this problem, as well as five or six others. In Rust, we
don't have to worry about it. dont have to worry about it.
```rust ```rust
macro_rules! five_times { macro_rules! five_times {
@ -261,8 +260,8 @@ fn main() {
The metavariable `$x` is parsed as a single expression node, and keeps its The metavariable `$x` is parsed as a single expression node, and keeps its
place in the syntax tree even after substitution. place in the syntax tree even after substitution.
Another common problem in macro systems is *variable capture*. Here's a C Another common problem in macro systems is variable capture. Heres a C
macro, using [a GNU C extension] to emulate Rust's expression blocks. macro, using [a GNU C extension] to emulate Rusts expression blocks.
[a GNU C extension]: https://gcc.gnu.org/onlinedocs/gcc/Statement-Exprs.html [a GNU C extension]: https://gcc.gnu.org/onlinedocs/gcc/Statement-Exprs.html
@ -275,7 +274,7 @@ macro, using [a GNU C extension] to emulate Rust's expression blocks.
}) })
``` ```
Here's a simple use case that goes terribly wrong: Heres a simple use case that goes terribly wrong:
```text ```text
const char *state = "reticulating splines"; const char *state = "reticulating splines";
@ -315,10 +314,10 @@ fn main() {
``` ```
This works because Rust has a [hygienic macro system][]. Each macro expansion This works because Rust has a [hygienic macro system][]. Each macro expansion
happens in a distinct *syntax context*, and each variable is tagged with the happens in a distinct syntax context, and each variable is tagged with the
syntax context where it was introduced. It's as though the variable `state` syntax context where it was introduced. Its as though the variable `state`
inside `main` is painted a different "color" from the variable `state` inside inside `main` is painted a different "color" from the variable `state` inside
the macro, and therefore they don't conflict. the macro, and therefore they dont conflict.
[hygienic macro system]: http://en.wikipedia.org/wiki/Hygienic_macro [hygienic macro system]: http://en.wikipedia.org/wiki/Hygienic_macro
@ -336,7 +335,7 @@ fn main() {
} }
``` ```
Instead you need to pass the variable name into the invocation, so it's tagged Instead you need to pass the variable name into the invocation, so its tagged
with the right syntax context. with the right syntax context.
```rust ```rust
@ -368,7 +367,7 @@ fn main() {
# Recursive macros # Recursive macros
A macro's expansion can include more macro invocations, including invocations A macros expansion can include more macro invocations, including invocations
of the very same macro being expanded. These recursive macros are useful for of the very same macro being expanded. These recursive macros are useful for
processing tree-structured input, as illustrated by this (simplistic) HTML processing tree-structured input, as illustrated by this (simplistic) HTML
shorthand: shorthand:
@ -429,7 +428,7 @@ they are unstable and require feature gates.
Even when Rust code contains un-expanded macros, it can be parsed as a full Even when Rust code contains un-expanded macros, it can be parsed as a full
[syntax tree][ast]. This property can be very useful for editors and other [syntax tree][ast]. This property can be very useful for editors and other
tools that process code. It also has a few consequences for the design of tools that process code. It also has a few consequences for the design of
Rust's macro system. Rusts macro system.
[ast]: glossary.html#abstract-syntax-tree [ast]: glossary.html#abstract-syntax-tree
@ -454,13 +453,13 @@ consist of valid Rust tokens. Furthermore, parentheses, brackets, and braces
must be balanced within a macro invocation. For example, `foo!([)` is must be balanced within a macro invocation. For example, `foo!([)` is
forbidden. This allows Rust to know where the macro invocation ends. forbidden. This allows Rust to know where the macro invocation ends.
More formally, the macro invocation body must be a sequence of *token trees*. More formally, the macro invocation body must be a sequence of token trees.
A token tree is defined recursively as either A token tree is defined recursively as either
* a sequence of token trees surrounded by matching `()`, `[]`, or `{}`, or * a sequence of token trees surrounded by matching `()`, `[]`, or `{}`, or
* any other single token. * any other single token.
Within a matcher, each metavariable has a *fragment specifier*, identifying Within a matcher, each metavariable has a fragment specifier, identifying
which syntactic form it matches. which syntactic form it matches.
* `ident`: an identifier. Examples: `x`; `foo`. * `ident`: an identifier. Examples: `x`; `foo`.
@ -482,7 +481,7 @@ There are additional rules regarding the next token after a metavariable:
* `pat` variables must be followed by one of: `=> , =` * `pat` variables must be followed by one of: `=> , =`
* Other variables may be followed by any token. * Other variables may be followed by any token.
These rules provide some flexibility for Rust's syntax to evolve without These rules provide some flexibility for Rusts syntax to evolve without
breaking existing macros. breaking existing macros.
The macro system does not deal with parse ambiguity at all. For example, the The macro system does not deal with parse ambiguity at all. For example, the
@ -500,7 +499,7 @@ One downside is that scoping works differently for macros, compared to other
constructs in the language. constructs in the language.
Definition and expansion of macros both happen in a single depth-first, Definition and expansion of macros both happen in a single depth-first,
lexical-order traversal of a crate's source. So a macro defined at module scope lexical-order traversal of a crates source. So a macro defined at module scope
is visible to any subsequent code in the same module, which includes the body is visible to any subsequent code in the same module, which includes the body
of any subsequent child `mod` items. of any subsequent child `mod` items.
@ -508,8 +507,8 @@ A macro defined within the body of a single `fn`, or anywhere else not at
module scope, is visible only within that item. module scope, is visible only within that item.
If a module has the `macro_use` attribute, its macros are also visible in its If a module has the `macro_use` attribute, its macros are also visible in its
parent module after the child's `mod` item. If the parent also has `macro_use` parent module after the childs `mod` item. If the parent also has `macro_use`
then the macros will be visible in the grandparent after the parent's `mod` then the macros will be visible in the grandparent after the parents `mod`
item, and so forth. item, and so forth.
The `macro_use` attribute can also appear on `extern crate`. In this context The `macro_use` attribute can also appear on `extern crate`. In this context
@ -524,7 +523,7 @@ If the attribute is given simply as `#[macro_use]`, all macros are loaded. If
there is no `#[macro_use]` attribute then no macros are loaded. Only macros there is no `#[macro_use]` attribute then no macros are loaded. Only macros
defined with the `#[macro_export]` attribute may be loaded. defined with the `#[macro_export]` attribute may be loaded.
To load a crate's macros *without* linking it into the output, use `#[no_link]` To load a crates macros without linking it into the output, use `#[no_link]`
as well. as well.
An example: An example:
@ -566,7 +565,7 @@ When this library is loaded with `#[macro_use] extern crate`, only `m2` will
be imported. be imported.
The Rust Reference has a [listing of macro-related The Rust Reference has a [listing of macro-related
attributes](../reference.html#macro--and-plugin-related-attributes). attributes](../reference.html#macro-related-attributes).
# The variable `$crate` # The variable `$crate`
@ -619,12 +618,12 @@ only appear at the root of your crate, not inside `mod`. This ensures that
The introductory chapter mentioned recursive macros, but it did not give the The introductory chapter mentioned recursive macros, but it did not give the
full story. Recursive macros are useful for another reason: Each recursive full story. Recursive macros are useful for another reason: Each recursive
invocation gives you another opportunity to pattern-match the macro's invocation gives you another opportunity to pattern-match the macros
arguments. arguments.
As an extreme example, it is possible, though hardly advisable, to implement As an extreme example, it is possible, though hardly advisable, to implement
the [Bitwise Cyclic Tag](http://esolangs.org/wiki/Bitwise_Cyclic_Tag) automaton the [Bitwise Cyclic Tag](http://esolangs.org/wiki/Bitwise_Cyclic_Tag) automaton
within Rust's macro system. within Rusts macro system.
```rust ```rust
macro_rules! bct { macro_rules! bct {
@ -653,11 +652,121 @@ macro_rules! bct {
Exercise: use macros to reduce duplication in the above definition of the Exercise: use macros to reduce duplication in the above definition of the
`bct!` macro. `bct!` macro.
# Common macros
Here are some common macros youll see in Rust code.
## panic!
This macro causes the current thread to panic. You can give it a message
to panic with:
```rust,no_run
panic!("oh no!");
```
## vec!
The `vec!` macro is used throughout the book, so youve probably seen it
already. It creates `Vec<T>`s with ease:
```rust
let v = vec![1, 2, 3, 4, 5];
```
It also lets you make vectors with repeating values. For example, a hundred
zeroes:
```rust
let v = vec![0; 100];
```
## assert! and assert_eq!
These two macros are used in tests. `assert!` takes a boolean, and `assert_eq!`
takes two values and compares them. Truth passes, success `panic!`s. Like
this:
```rust,no_run
// A-ok!
assert!(true);
assert_eq!(5, 3 + 2);
// nope :(
assert!(5 < 3);
assert_eq!(5, 3);
```
## try!
`try!` is used for error handling. It takes something that can return a
`Result<T, E>`, and gives `T` if its a `Ok<T>`, and `return`s with the
`Err(E)` if its that. Like this:
```rust,no_run
use std::fs::File;
fn foo() -> std::io::Result<()> {
let f = try!(File::create("foo.txt"));
Ok(())
}
```
This is cleaner than doing this:
```rust,no_run
use std::fs::File;
fn foo() -> std::io::Result<()> {
let f = File::create("foo.txt");
let f = match f {
Ok(t) => t,
Err(e) => return Err(e),
};
Ok(())
}
```
## unreachable!
This macro is used when you think some code should never execute:
```rust
if false {
unreachable!();
}
```
Sometimes, the compiler may make you have a different branch that you know
will never, ever run. In these cases, use this macro, so that if you end
up wrong, youll get a `panic!` about it.
```rust
let x: Option<i32> = None;
match x {
Some(_) => unreachable!(),
None => println!("I know x is None!"),
}
```
## unimplemented!
The `unimplemented!` macro can be used when youre trying to get your functions
to typecheck, and dont want to worry about writing out the body of the
function. One example of this situation is implementing a trait with multiple
required methods, where you want to tackle one at a time. Define the others
as `unimplemented!` until youre ready to write them.
# Procedural macros # Procedural macros
If Rust's macro system can't do what you need, you may want to write a If Rusts macro system cant do what you need, you may want to write a
[compiler plugin](plugins.html) instead. Compared to `macro_rules!` [compiler plugin](compiler-plugins.html) instead. Compared to `macro_rules!`
macros, this is significantly more work, the interfaces are much less stable, macros, this is significantly more work, the interfaces are much less stable,
and bugs can be much harder to track down. In exchange you get the and bugs can be much harder to track down. In exchange you get the
flexibility of running arbitrary Rust code within the compiler. Syntax flexibility of running arbitrary Rust code within the compiler. Syntax
extension plugins are sometimes called *procedural macros* for this reason. extension plugins are sometimes called procedural macros for this reason.

View File

@ -1,10 +1,8 @@
% Match % Match
Often, a simple `if`/`else` isnt enough, because you have more than two Often, a simple [`if`][if]/`else` isnt enough, because you have more than two
possible options. Also, `else` conditions can get incredibly complicated, so possible options. Also, conditions can get quite complex. Rust
whats the solution? has a keyword, `match`, that allows you to replace complicated `if`/`else`
Rust has a keyword, `match`, that allows you to replace complicated `if`/`else`
groupings with something more powerful. Check it out: groupings with something more powerful. Check it out:
```rust ```rust
@ -20,16 +18,18 @@ match x {
} }
``` ```
`match` takes an expression and then branches based on its value. Each *arm* of [if]: if.html
`match` takes an expression and then branches based on its value. Each arm of
the branch is of the form `val => expression`. When the value matches, that arms the branch is of the form `val => expression`. When the value matches, that arms
expression will be evaluated. Its called `match` because of the term pattern expression will be evaluated. Its called `match` because of the term pattern
matching, which `match` is an implementation of. Theres an [entire section on matching, which `match` is an implementation of. Theres an [entire section on
patterns][patterns] coming up next, that covers all the options that fit here. patterns][patterns] that covers all the patterns that are possible here.
[patterns]: patterns.html [patterns]: patterns.html
So whats the big advantage here? Well, there are a few. First of all, `match` So whats the big advantage? Well, there are a few. First of all, `match`
enforces *exhaustiveness checking*. Do you see that last arm, the one with the enforces exhaustiveness checking. Do you see that last arm, the one with the
underscore (`_`)? If we remove that arm, Rust will give us an error: underscore (`_`)? If we remove that arm, Rust will give us an error:
```text ```text
@ -37,11 +37,12 @@ error: non-exhaustive patterns: `_` not covered
``` ```
In other words, Rust is trying to tell us we forgot a value. Because `x` is an In other words, Rust is trying to tell us we forgot a value. Because `x` is an
integer, Rust knows that it can have a number of different values for example, integer, Rust knows that it can have a number of different values for
`6`. Without the `_`, however, there is no arm that could match, and so Rust refuses example, `6`. Without the `_`, however, there is no arm that could match, and
to compile. `_` acts like a catch-all arm. If none of the other arms match, so Rust refuses to compile the code. `_` acts like a catch-all arm. If none
the arm with `_` will, and since we have this catch-all arm, we now have an arm of the other arms match, the arm with `_` will, and since we have this
for every possible value of `x`, and so our program will compile successfully. catch-all arm, we now have an arm for every possible value of `x`, and so our
program will compile successfully.
`match` is also an expression, which means we can use it on the right-hand `match` is also an expression, which means we can use it on the right-hand
side of a `let` binding or directly where an expression is used: side of a `let` binding or directly where an expression is used:
@ -49,7 +50,7 @@ side of a `let` binding or directly where an expression is used:
```rust ```rust
let x = 5; let x = 5;
let numer = match x { let number = match x {
1 => "one", 1 => "one",
2 => "two", 2 => "two",
3 => "three", 3 => "three",
@ -59,4 +60,41 @@ let numer = match x {
}; };
``` ```
Sometimes, its a nice way of converting things. Sometimes its a nice way of converting something from one type to another.
# Matching on enums
Another important use of the `match` keyword is to process the possible
variants of an enum:
```rust
enum Message {
Quit,
ChangeColor(i32, i32, i32),
Move { x: i32, y: i32 },
Write(String),
}
fn quit() { /* ... */ }
fn change_color(r: i32, g: i32, b: i32) { /* ... */ }
fn move_cursor(x: i32, y: i32) { /* ... */ }
fn process_message(msg: Message) {
match msg {
Message::Quit => quit(),
Message::ChangeColor(r, g, b) => change_color(r, g, b),
Message::Move { x: x, y: y } => move_cursor(x, y),
Message::Write(s) => println!("{}", s),
};
}
```
Again, the Rust compiler checks exhaustiveness, so it demands that you
have a match arm for every variant of the enum. If you leave one off, it
will give you a compile-time error unless you use `_`.
Unlike the previous uses of `match`, you cant use the normal `if`
statement to do this. You can use the [`if let`][if-let] statement,
which can be seen as an abbreviated form of `match`.
[if-let][if-let.html]

View File

@ -3,27 +3,26 @@
Functions are great, but if you want to call a bunch of them on some data, it Functions are great, but if you want to call a bunch of them on some data, it
can be awkward. Consider this code: can be awkward. Consider this code:
```{rust,ignore} ```rust,ignore
baz(bar(foo))); baz(bar(foo)));
``` ```
We would read this left-to right, and so we see "baz bar foo." But this isn't the We would read this left-to right, and so we see baz bar foo. But this isnt the
order that the functions would get called in, that's inside-out: "foo bar baz." order that the functions would get called in, thats inside-out: foo bar baz.
Wouldn't it be nice if we could do this instead? Wouldnt it be nice if we could do this instead?
```{rust,ignore} ```rust,ignore
foo.bar().baz(); foo.bar().baz();
``` ```
Luckily, as you may have guessed with the leading question, you can! Rust provides Luckily, as you may have guessed with the leading question, you can! Rust provides
the ability to use this *method call syntax* via the `impl` keyword. the ability to use this method call syntax via the `impl` keyword.
## Method calls # Method calls
Here's how it works: Heres how it works:
```{rust} ```rust
# #![feature(core)]
struct Circle { struct Circle {
x: f64, x: f64,
y: f64, y: f64,
@ -44,15 +43,23 @@ fn main() {
This will print `12.566371`. This will print `12.566371`.
We've made a struct that represents a circle. We then write an `impl` block,
and inside it, define a method, `area`. Methods take a special first
parameter, of which there are three variants: `self`, `&self`, and `&mut self`. Weve made a struct that represents a circle. We then write an `impl` block,
You can think of this first parameter as being the `foo` in `foo.bar()`. The three and inside it, define a method, `area`.
variants correspond to the three 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 Methods take a special first parameter, of which there are three variants:
a mutable reference. We should default to using `&self`, as you should prefer `self`, `&self`, and `&mut self`. You can think of this first parameter as
borrowing over taking ownership, as well as taking immutable references being the `foo` in `foo.bar()`. The three variants correspond to the three
over mutable ones. Here's an example of all three variants: kinds of things `foo` could be: `self` if its just a value on the stack,
`&self` if its a reference, and `&mut self` if its a mutable reference.
Because we took the `&self` parameter to `area`, we can use it just like any
other parameter. Because we know its a `Circle`, we can access the `radius`
just like we would with any other struct.
We should default to using `&self`, as you should prefer borrowing over taking
ownership, as well as taking immutable references over mutable ones. Heres an
example of all three variants:
```rust ```rust
struct Circle { struct Circle {
@ -76,20 +83,13 @@ impl Circle {
} }
``` ```
Finally, as you may remember, the value of the area of a circle is `π*r²`. # Chaining method calls
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`
just like we would with any other struct. An import of π and some
multiplications later, and we have our area.
## Chaining method calls
So, now we know how to call a method, such as `foo.bar()`. But what about our So, now we know how to call a method, such as `foo.bar()`. But what about our
original example, `foo.bar().baz()`? This is called 'method chaining', and we original example, `foo.bar().baz()`? This is called method chaining, and we
can do it by returning `self`. can do it by returning `self`.
``` ```
# #![feature(core)]
struct Circle { struct Circle {
x: f64, x: f64,
y: f64, y: f64,
@ -124,15 +124,15 @@ fn grow(&self) -> Circle {
# Circle } } # Circle } }
``` ```
We just say we're returning a `Circle`. With this method, we can grow a new We just say were returning a `Circle`. With this method, we can grow a new
circle to any arbitrary size. circle to any arbitrary size.
## Static methods # Associated functions
You can also define methods that do not take a `self` parameter. Here's a You can also define associated functions that do not take a `self` parameter.
pattern that's very common in Rust code: Heres a pattern thats very common in Rust code:
``` ```rust
struct Circle { struct Circle {
x: f64, x: f64,
y: f64, y: f64,
@ -154,20 +154,20 @@ fn main() {
} }
``` ```
This *static method* builds a new `Circle` for us. Note that static methods This associated function builds a new `Circle` for us. Note that associated
are called with the `Struct::method()` syntax, rather than the `ref.method()` functions are called with the `Struct::function()` syntax, rather than the
syntax. `ref.method()` syntax. Some other langauges call associated functions static
methods.
## Builder Pattern # Builder Pattern
Let's say that we want our users to be able to create Circles, but we will Lets say that we want our users to be able to create Circles, but we will
allow them to only set the properties they care about. Otherwise, the `x` allow them to only set the properties they care about. Otherwise, the `x`
and `y` attributes will be `0.0`, and the `radius` will be `1.0`. Rust doesn't and `y` attributes will be `0.0`, and the `radius` will be `1.0`. Rust doesnt
have method overloading, named arguments, or variable arguments. We employ have method overloading, named arguments, or variable arguments. We employ
the builder pattern instead. It looks like this: the builder pattern instead. It looks like this:
``` ```
# #![feature(core)]
struct Circle { struct Circle {
x: f64, x: f64,
y: f64, y: f64,
@ -188,7 +188,7 @@ struct CircleBuilder {
impl CircleBuilder { impl CircleBuilder {
fn new() -> CircleBuilder { fn new() -> CircleBuilder {
CircleBuilder { x: 0.0, y: 0.0, radius: 0.0, } CircleBuilder { x: 0.0, y: 0.0, radius: 1.0, }
} }
fn x(&mut self, coordinate: f64) -> &mut CircleBuilder { fn x(&mut self, coordinate: f64) -> &mut CircleBuilder {
@ -224,9 +224,9 @@ fn main() {
} }
``` ```
What we've done here is make another struct, `CircleBuilder`. We've defined our What weve done here is make another struct, `CircleBuilder`. Weve defined our
builder methods on it. We've also defined our `area()` method on `Circle`. We builder methods on it. Weve also defined our `area()` method on `Circle`. We
also made one more method on `CircleBuilder`: `finalize()`. This method creates also made one more method on `CircleBuilder`: `finalize()`. This method creates
our final `Circle` from the builder. Now, we've used the type system to enforce our final `Circle` from the builder. Now, weve used the type system to enforce
our concerns: we can use the methods on `CircleBuilder` to constrain making our concerns: we can use the methods on `CircleBuilder` to constrain making
`Circle`s in any way we choose. `Circle`s in any way we choose.

View File

@ -1,3 +1,179 @@
% Mutability % Mutability
Coming Soon Mutability, the ability to change something, works a bit differently in Rust
than in other languages. The first aspect of mutability is its non-default
status:
```rust,ignore
let x = 5;
x = 6; // error!
```
We can introduce mutability with the `mut` keyword:
```rust
let mut x = 5;
x = 6; // no problem!
```
This is a mutable [variable binding][vb]. When a binding is mutable, it means
youre allowed to change what the binding points to. So in the above example,
its not so much that the value at `x` is changing, but that the binding
changed from one `i32` to another.
[vb]: variable-bindings.html
If you want to change what the binding points to, youll need a [mutable reference][mr]:
```rust
let mut x = 5;
let y = &mut x;
```
[mr]: references-and-borrowing.html
`y` is an immutable binding to a mutable reference, which means that you cant
bind `y` to something else (`y = &mut z`), but you can mutate the thing thats
bound to `y`. (`*y = 5`) A subtle distinction.
Of course, if you need both:
```rust
let mut x = 5;
let mut y = &mut x;
```
Now `y` can be bound to another value, and the value its referencing can be
changed.
Its important to note that `mut` is part of a [pattern][pattern], so you
can do things like this:
```rust
let (mut x, y) = (5, 6);
fn foo(mut x: i32) {
# }
```
[pattern]: patterns.html
# Interior vs. Exterior Mutability
However, when we say something is immutable in Rust, that doesnt mean that
its not able to be changed: We mean something has exterior mutability. Consider,
for example, [`Arc<T>`][arc]:
```rust
use std::sync::Arc;
let x = Arc::new(5);
let y = x.clone();
```
[arc]: ../std/sync/struct.Arc.html
When we call `clone()`, the `Arc<T>` needs to update the reference count. Yet
weve not used any `mut`s here, `x` is an immutable binding, and we didnt take
`&mut 5` or anything. So what gives?
To understand this, we have to go back to the core of Rusts guiding
philosophy, memory safety, and the mechanism by which Rust guarantees it, the
[ownership][ownership] system, and more specifically, [borrowing][borrowing]:
> You may have one or the other of these two kinds of borrows, but not both at
> the same time:
>
> * one or more references (`&T`) to a resource.
> * exactly one mutable reference (`&mut T`)
[ownership]: ownership.html
[borrowing]: borrowing.html#The-Rules
So, thats the real definition of immutability: is this safe to have two
pointers to? In `Arc<T>`s case, yes: the mutation is entirely contained inside
the structure itself. Its not user facing. For this reason, it hands out `&T`
with `clone()`. If it handed out `&mut T`s, though, that would be a problem.
Other types, like the ones in the [`std::cell`][stdcell] module, have the
opposite: interior mutability. For example:
```rust
use std::cell::RefCell;
let x = RefCell::new(42);
let y = x.borrow_mut();
```
[stdcell]: ../std/cell/index.html
RefCell hands out `&mut` references to whats inside of it with the
`borrow_mut()` method. Isnt that dangerous? What if we do:
```rust,ignore
use std::cell::RefCell;
let x = RefCell::new(42);
let y = x.borrow_mut();
let z = x.borrow_mut();
# (y, z);
```
This will in fact panic, at runtime. This is what `RefCell` does: it enforces
Rusts borrowing rules at runtime, and `panic!`s if theyre violated. This
allows us to get around another aspect of Rusts mutability rules. Lets talk
about it first.
## Field-level mutability
Mutability is a property of either a borrow (`&mut`) or a binding (`let mut`).
This means that, for example, you cannot have a [`struct`][struct] with
some fields mutable and some immutable:
```rust,ignore
struct Point {
x: i32,
mut y: i32, // nope
}
```
The mutability of a struct is in its binding:
```rust,ignore
struct Point {
x: i32,
y: i32,
}
let mut a = Point { x: 5, y: 6 };
a.x = 10;
let b = Point { x: 5, y: 6};
b.x = 10; // error: cannot assign to immutable field `b.x`
```
[struct]: structs.html
However, by using `Cell<T>`, you can emulate field-level mutability:
```
use std::cell::Cell;
struct Point {
x: i32,
y: Cell<i32>,
}
let point = Point { x: 5, y: Cell::new(6) };
point.y.set(7);
println!("y: {:?}", point.y);
```
This will print `y: Cell { value: 7 }`. Weve successfully updated `y`.

View File

@ -9,16 +9,16 @@ process, see [Stability as a deliverable][stability].
To install nightly Rust, you can use `rustup.sh`: To install nightly Rust, you can use `rustup.sh`:
```bash ```bash
$ curl -s https://static.rust-lang.org/rustup.sh | sudo sh -s -- --channel=nightly $ curl -s https://static.rust-lang.org/rustup.sh | sh -s -- --channel=nightly
``` ```
If you're concerned about the [potential insecurity][insecurity] of using `curl If you're concerned about the [potential insecurity][insecurity] of using `curl
| sudo 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 two-step version of the installation and examine our installation script: use a 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
$ sudo sh rustup.sh --channel=nightly $ sh rustup.sh --channel=nightly
``` ```
[insecurity]: http://curlpipesh.tumblr.com [insecurity]: http://curlpipesh.tumblr.com
@ -43,13 +43,11 @@ If you used the Windows installer, just re-run the `.msi` and it will give you
an uninstall option. an uninstall option.
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 you to
`curl | sudo sh`. Basically, when you do this, you are trusting that the good `curl | sh`. Basically, when you do this, you are trusting that the good
people who maintain Rust aren't going to hack your computer and do bad things. people who maintain Rust aren't going to hack your computer and do bad things.
That's a good instinct! If you're one of those people, please check out the That's a good instinct! If you're one of those people, please check out the
documentation on [building Rust from Source][from source], or [the official documentation on [building Rust from Source][from source], or [the official
binary downloads][install page]. And we promise that this method will not be binary downloads][install page].
the way to install Rust forever: it's just the easiest way to keep people
updated while Rust is in its alpha state.
[from source]: https://github.com/rust-lang/rust#building-from-source [from source]: https://github.com/rust-lang/rust#building-from-source
[install page]: http://www.rust-lang.org/install.html [install page]: http://www.rust-lang.org/install.html
@ -93,8 +91,7 @@ If not, there are a number of places where you can get help. The easiest is
[the #rust IRC channel on irc.mozilla.org][irc], which you can access through [the #rust IRC channel on irc.mozilla.org][irc], which you can access through
[Mibbit][mibbit]. Click that link, and you'll be chatting with other Rustaceans [Mibbit][mibbit]. Click that link, and you'll be chatting with other Rustaceans
(a silly nickname we call ourselves), and we can help you out. Other great (a silly nickname we call ourselves), and we can help you out. Other great
resources include [the users forum][users], and [Stack Overflow][stack resources include [the users forum][users], and [Stack Overflow][stack overflow].
overflow].
[irc]: irc://irc.mozilla.org/#rust [irc]: irc://irc.mozilla.org/#rust
[mibbit]: http://chat.mibbit.com/?server=irc.mozilla.org&channel=%23rust [mibbit]: http://chat.mibbit.com/?server=irc.mozilla.org&channel=%23rust

View File

@ -1,3 +1,83 @@
% Operators and Overloading % Operators and Overloading
Coming soon! Rust allows for a limited form of operator overloading. There are certain
operators that are able to be overloaded. To support a particular operator
between types, theres a specific trait that you can implement, which then
overloads the operator.
For example, the `+` operator can be overloaded with the `Add` trait:
```rust
use std::ops::Add;
#[derive(Debug)]
struct Point {
x: i32,
y: i32,
}
impl Add for Point {
type Output = Point;
fn add(self, other: Point) -> Point {
Point { x: self.x + other.x, y: self.y + other.y }
}
}
fn main() {
let p1 = Point { x: 1, y: 0 };
let p2 = Point { x: 2, y: 3 };
let p3 = p1 + p2;
println!("{:?}", p3);
}
```
In `main`, we can use `+` on our two `Point`s, since weve implemented
`Add<Output=Point>` for `Point`.
There are a number of operators that can be overloaded this way, and all of
their associated traits live in the [`std::ops`][stdops] module. Check out its
documentation for the full list.
[stdops]: ../std/ops/index.html
Implementing these traits follows a pattern. Lets look at [`Add`][add] in more
detail:
```rust
# mod foo {
pub trait Add<RHS = Self> {
type Output;
fn add(self, rhs: RHS) -> Self::Output;
}
# }
```
[add]: ../std/ops/trait.Add.html
Theres three types in total involved here: the type you `impl Add` for, `RHS`,
which defaults to `Self`, and `Output`. For an expression `let z = x + y`, `x`
is the `Self` type, `y` is the RHS, and `z` is the `Self::Output` type.
```rust
# struct Point;
# use std::ops::Add;
impl Add<i32> for Point {
type Output = f64;
fn add(self, rhs: i32) -> f64 {
// add an i32 to a Point and get an f64
# 1.0
}
}
```
will let you do this:
```rust,ignore
let p: Point = // ...
let x: f64 = p + 2i32;
```

View File

@ -1,555 +1,208 @@
% Ownership % Ownership
This guide presents Rust's ownership system. This is one of Rust's most unique This guide is one of three presenting Rusts ownership system. This is one of
and compelling features, with which Rust developers should become quite Rusts most unique and compelling features, with which Rust developers should
acquainted. Ownership is how Rust achieves its largest goal, memory safety. become quite acquainted. Ownership is how Rust achieves its largest goal,
The ownership system has a few distinct concepts: *ownership*, *borrowing*, memory safety. There are a few distinct concepts, each with its own
and *lifetimes*. We'll talk about each one in turn. chapter:
* ownership, which youre reading now
* [borrowing][borrowing], and their associated feature references
* [lifetimes][lifetimes], an advanced concept of borrowing
These three chapters are related, and in order. Youll need all three to fully
understand the ownership system.
[borrowing]: references-and-borrowing.html
[lifetimes]: lifetimes.html
# Meta # Meta
Before we get to the details, two important notes about the ownership system. Before we get to the details, two important notes about the ownership system.
Rust has a focus on safety and speed. It accomplishes these goals through many Rust has a focus on safety and speed. It accomplishes these goals through many
*zero-cost abstractions*, which means that in Rust, abstractions cost as little zero-cost abstractions, which means that in Rust, abstractions cost as little
as possible in order to make them work. The ownership system is a prime example as possible in order to make them work. The ownership system is a prime example
of a zero cost abstraction. All of the analysis we'll talk about in this guide of a zero-cost abstraction. All of the analysis well talk about in this guide
is _done at compile time_. You do not pay any run-time cost for any of these is _done at compile time_. You do not pay any run-time cost for any of these
features. features.
However, this system does have a certain cost: learning curve. Many new users However, this system does have a certain cost: learning curve. Many new users
to Rust experience something we like to call "fighting with the borrow to Rust experience something we like to call fighting with the borrow
checker," where the Rust compiler refuses to compile a program that the author checker, where the Rust compiler refuses to compile a program that the author
thinks is valid. This often happens because the programmer's mental model of thinks is valid. This often happens because the programmers mental model of
how ownership should work doesn't match the actual rules that Rust implements. how ownership should work doesnt match the actual rules that Rust implements.
You probably will experience similar things at first. There is good news, You probably will experience similar things at first. There is good news,
however: more experienced Rust developers report that once they work with the however: more experienced Rust developers report that once they work with the
rules of the ownership system for a period of time, they fight the borrow rules of the ownership system for a period of time, they fight the borrow
checker less and less. checker less and less.
With that in mind, let's learn about ownership. With that in mind, lets learn about ownership.
# Ownership # Ownership
At its core, ownership is about *resources*. For the purposes of the vast [Variable bindings][bindings] have a property in Rust: they have ownership
majority of this guide, we will talk about a specific resource: memory. The of what theyre bound to. This means that when a binding goes out of scope, the
concept generalizes to any kind of resource, like a file handle, but to make it resource that theyre bound to are freed. For example:
more concrete, we'll focus on memory.
When your program allocates some memory, it needs some way to deallocate that
memory. Imagine a function `foo` that allocates four bytes of memory, and then
never deallocates that memory. We call this problem *leaking* memory, because
each time we call `foo`, we're allocating another four bytes. Eventually, with
enough calls to `foo`, we will run our system out of memory. That's no good. So
we need some way for `foo` to deallocate those four bytes. It's also important
that we don't deallocate too many times, either. Without getting into the
details, attempting to deallocate memory multiple times can lead to problems.
In other words, any time some memory is allocated, we need to make sure that we
deallocate that memory once and only once. Too many times is bad, not enough
times is bad. The counts must match.
There's one other important detail with regards to allocating memory. Whenever
we request some amount of memory, what we are given is a handle to that memory.
This handle (often called a *pointer*, when we're referring to memory) is how
we interact with the allocated memory. As long as we have that handle, we can
do something with the memory. Once we're done with the handle, we're also done
with the memory, as we can't do anything useful without a handle to it.
Historically, systems programming languages require you to track these
allocations, deallocations, and handles yourself. For example, if we want some
memory from the heap in a language like C, we do this:
```c
{
int *x = malloc(sizeof(int));
// we can now do stuff with our handle x
*x = 5;
free(x);
}
```
The call to `malloc` allocates some memory. The call to `free` deallocates the
memory. There's also bookkeeping about allocating the correct amount of memory.
Rust combines these two aspects of allocating memory (and other resources) into
a concept called *ownership*. Whenever we request some memory, that handle we
receive is called the *owning handle*. Whenever that handle goes out of scope,
Rust knows that you cannot do anything with the memory anymore, and so
therefore deallocates the memory for you. Here's the equivalent example in
Rust:
```rust ```rust
{ fn foo() {
let x = Box::new(5); let v = vec![1, 2, 3];
} }
``` ```
The `Box::new` function creates a `Box<T>` (specifically `Box<i32>` in this When `v` comes into scope, a new [`Vec<T>`][vect] is created. In this case, the
case) by allocating a small segment of memory on the heap with enough space to vector also allocates space on [the heap][heap], for the three elements. When
fit an `i32`. But where in the code is the box deallocated? We said before that `v` goes out of scope at the end of `foo()`, Rust will clean up everything
we must have a deallocation for each allocation. Rust handles this for you. It related to the vector, even the heap-allocated memory. This happens
knows that our handle, `x`, is the owning reference to our box. Rust knows that deterministically, at the end of the scope.
`x` will go out of scope at the end of the block, and so it inserts a call to
deallocate the memory at the end of the scope. Because the compiler does this
for us, it's impossible to forget. We always have exactly one deallocation
paired with each of our allocations.
This is pretty straightforward, but what happens when we want to pass our box [vect]: ../std/vec/struct.Vec.html
to a function? Let's look at some code: [heap]: the-stack-and-the-heap.html
[bindings]: variable-bindings.html
# Move semantics
Theres some more subtlety here, though: Rust ensures that there is _exactly
one_ binding to any given resource. For example, if we have a vector, we can
assign it to another binding:
```rust ```rust
fn main() { let v = vec![1, 2, 3];
let x = Box::new(5);
add_one(x); let v2 = v;
}
fn add_one(mut num: Box<i32>) {
*num += 1;
}
``` ```
This code works, but it's not ideal. For example, let's add one more line of But, if we try to use `v` afterwards, we get an error:
code, where we print out the value of `x`:
```{rust,ignore} ```rust,ignore
fn main() { let v = vec![1, 2, 3];
let x = Box::new(5);
add_one(x); let v2 = v;
println!("{}", x); println!("v[0] is: {}", v[0]);
}
fn add_one(mut num: Box<i32>) {
*num += 1;
}
``` ```
This does not compile, and gives us an error: It looks like this:
```text ```text
error: use of moved value: `x` error: use of moved value: `v`
println!("{}", x); println!("v[0] is: {}", v[0]);
^ ^
``` ```
Remember, we need one deallocation for every allocation. When we try to pass A similar thing happens if we define a function which takes ownership, and
our box to `add_one`, we would have two handles to the memory: `x` in `main`, try to use something after weve passed it as an argument:
and `num` in `add_one`. If we deallocated the memory when each handle went out
of scope, we would have two deallocations and one allocation, and that's wrong.
So when we call `add_one`, Rust defines `num` as the owner of the handle. And
so, now that we've given ownership to `num`, `x` is invalid. `x`'s value has
"moved" from `x` to `num`. Hence the error: use of moved value `x`.
To fix this, we can have `add_one` give ownership back when it's done with the ```rust,ignore
box: fn take(v: Vec<i32>) {
// what happens here isnt important.
}
let v = vec![1, 2, 3];
take(v);
println!("v[0] is: {}", v[0]);
```
Same error: use of moved value. When we transfer ownership to something else,
we say that weve moved the thing we refer to. You dont need some sort of
special annotation here, its the default thing that Rust does.
## The details
The reason that we cannot use a binding after weve moved it is subtle, but
important. When we write code like this:
```rust ```rust
fn main() { let v = vec![1, 2, 3];
let x = Box::new(5);
let y = add_one(x); let v2 = v;
println!("{}", y);
}
fn add_one(mut num: Box<i32>) -> Box<i32> {
*num += 1;
num
}
``` ```
This code will compile and run just fine. Now, we return a `box`, and so the The first line allocates memory for the vector object, `v`, and for the data it
ownership is transferred back to `y` in `main`. We only have ownership for the contains. The vector object is stored on the [stack][sh] and contains a pointer
duration of our function before giving it back. This pattern is very common, to the content (`[1, 2, 3]`) stored on the [heap][sh]. When we move `v` to `v2`,
and so Rust introduces a concept to describe a handle which temporarily refers it creates a copy of that pointer, for `v2`. Which means that there would be two
to something another handle owns. It's called *borrowing*, and it's done with pointers to the content of the vector on the heap. It would violate Rusts
*references*, designated by the `&` symbol. safety guarantees by introducing a data race. Therefore, Rust forbids using `v`
after weve done the move.
# Borrowing [sh]: the-stack-and-the-heap.html
Here's the current state of our `add_one` function: Its also important to note that optimizations may remove the actual copy of
the bytes on the stack, depending on circumstances. So it may not be as
inefficient as it initially seems.
## `Copy` types
Weve established that when ownership is transferred to another binding, you
cannot use the original binding. However, theres a [trait][traits] that changes this
behavior, and its called `Copy`. We havent discussed traits yet, but for now,
you can think of them as an annotation to a particular type that adds extra
behavior. For example:
```rust ```rust
fn add_one(mut num: Box<i32>) -> Box<i32> { let v = 1;
*num += 1;
num let v2 = v;
}
println!("v is: {}", v);
``` ```
This function takes ownership, because it takes a `Box`, which owns its In this case, `v` is an `i32`, which implements the `Copy` trait. This means
contents. But then we give ownership right back. that, just like a move, when we assign `v` to `v2`, a copy of the data is made.
But, unlike a move, we can still use `v` afterward. This is because an `i32`
has no pointers to data somewhere else, copying it is a full copy.
In the physical world, you can give one of your possessions to someone for a We will discuss how to make your own types `Copy` in the [traits][traits]
short period of time. You still own your possession, you're just letting someone section.
else use it for a while. We call that *lending* something to someone, and that
person is said to be *borrowing* that something from you.
Rust's ownership system also allows an owner to lend out a handle for a limited [traits]: traits.html
period. This is also called *borrowing*. Here's a version of `add_one` which
borrows its argument rather than taking ownership: # More than ownership
Of course, if we had to hand ownership back with every function we wrote:
```rust ```rust
fn add_one(num: &mut i32) { fn foo(v: Vec<i32>) -> Vec<i32> {
*num += 1; // do stuff with v
// hand back ownership
v
} }
``` ```
This function borrows an `i32` from its caller, and then increments it. When This would get very tedious. It gets worse the more things we want to take ownership of:
the function is over, and `num` goes out of scope, the borrow is over.
We have to change our `main` a bit too:
```rust ```rust
fn main() { fn foo(v1: Vec<i32>, v2: Vec<i32>) -> (Vec<i32>, Vec<i32>, i32) {
let mut x = 5; // do stuff with v1 and v2
add_one(&mut x); // hand back ownership, and the result of our function
(v1, v2, 42)
println!("{}", x);
} }
fn add_one(num: &mut i32) { let v1 = vec![1, 2, 3];
*num += 1; let v2 = vec![1, 2, 3];
}
let (v1, v2, answer) = foo(v1, v2);
``` ```
We don't need to assign the result of `add_one()` anymore, because it doesn't Ugh! The return type, return line, and calling the function gets way more
return anything anymore. This is because we're not passing ownership back, complicated.
since we just borrow, not take ownership.
# Lifetimes Luckily, Rust offers a feature, borrowing, which helps us solve this problem.
Its the topic of the next section!
Lending out a reference to a resource that someone else owns can be
complicated, however. For example, imagine this set of operations:
1. I acquire a handle to some kind of resource.
2. I lend you a reference to the resource.
3. I decide I'm done with the resource, and deallocate it, while you still have
your reference.
4. You decide to use the resource.
Uh oh! Your reference is pointing to an invalid resource. This is called a
*dangling pointer* or "use after free," when the resource is memory.
To fix this, we have to make sure that step four never happens after step
three. The ownership system in Rust does this through a concept called
*lifetimes*, which describe the scope that a reference is valid for.
Remember the function that borrowed an `i32`? Let's look at it again.
```rust
fn add_one(num: &mut i32) {
*num += 1;
}
```
Rust has a feature called *lifetime elision*, which allows you to not write
lifetime annotations in certain circumstances. This is one of them. We will
cover the others later. Without eliding the lifetimes, `add_one` looks like
this:
```rust
fn add_one<'a>(num: &'a mut i32) {
*num += 1;
}
```
The `'a` is called a *lifetime*. Most lifetimes are used in places where
short names like `'a`, `'b` and `'c` are clearest, but it's often useful to
have more descriptive names. Let's dig into the syntax in a bit more detail:
```{rust,ignore}
fn add_one<'a>(...)
```
This part _declares_ our lifetimes. This says that `add_one` has one lifetime,
`'a`. If we had two, it would look like this:
```{rust,ignore}
fn add_two<'a, 'b>(...)
```
Then in our parameter list, we use the lifetimes we've named:
```{rust,ignore}
...(num: &'a mut i32)
```
If you compare `&mut i32` to `&'a mut i32`, they're the same, it's just that the
lifetime `'a` has snuck in between the `&` and the `mut i32`. We read `&mut i32` as "a
mutable reference to an i32" and `&'a mut i32` as "a mutable reference to an i32 with the lifetime 'a.'"
Why do lifetimes matter? Well, for example, here's some code:
```rust
struct Foo<'a> {
x: &'a i32,
}
fn main() {
let y = &5; // this is the same as `let _y = 5; let y = &_y;`
let f = Foo { x: y };
println!("{}", f.x);
}
```
As you can see, `struct`s can also have lifetimes. In a similar way to functions,
```{rust}
struct Foo<'a> {
# x: &'a i32,
# }
```
declares a lifetime, and
```rust
# struct Foo<'a> {
x: &'a i32,
# }
```
uses it. So why do we need a lifetime here? We need to ensure that any reference
to a `Foo` cannot outlive the reference to an `i32` it contains.
## Thinking in scopes
A way to think about lifetimes is to visualize the scope that a reference is
valid for. For example:
```rust
fn main() {
let y = &5; // -+ y goes into scope
// |
// stuff // |
// |
} // -+ y goes out of scope
```
Adding in our `Foo`:
```rust
struct Foo<'a> {
x: &'a i32,
}
fn main() {
let y = &5; // -+ y goes into scope
let f = Foo { x: y }; // -+ f goes into scope
// stuff // |
// |
} // -+ f and y go out of scope
```
Our `f` lives within the scope of `y`, so everything works. What if it didn't?
This code won't work:
```{rust,ignore}
struct Foo<'a> {
x: &'a i32,
}
fn main() {
let x; // -+ x goes into scope
// |
{ // |
let y = &5; // ---+ y goes into scope
let f = Foo { x: y }; // ---+ f goes into scope
x = &f.x; // | | error here
} // ---+ f and y go out of scope
// |
println!("{}", x); // |
} // -+ x goes out of scope
```
Whew! As you can see here, the scopes of `f` and `y` are smaller than the scope
of `x`. But when we do `x = &f.x`, we make `x` a reference to something that's
about to go out of scope.
Named lifetimes are a way of giving these scopes a name. Giving something a
name is the first step towards being able to talk about it.
## 'static
The lifetime named *static* is a special lifetime. It signals that something
has the lifetime of the entire program. Most Rust programmers first come across
`'static` when dealing with strings:
```rust
let x: &'static str = "Hello, world.";
```
String literals have the type `&'static str` because the reference is always
alive: they are baked into the data segment of the final binary. Another
example are globals:
```rust
static FOO: i32 = 5;
let x: &'static i32 = &FOO;
```
This adds an `i32` to the data segment of the binary, and `x` is a reference
to it.
# Shared Ownership
In all the examples we've considered so far, we've assumed that each handle has
a singular owner. But sometimes, this doesn't work. Consider a car. Cars have
four wheels. We would want a wheel to know which car it was attached to. But
this won't work:
```{rust,ignore}
struct Car {
name: String,
}
struct Wheel {
size: i32,
owner: Car,
}
fn main() {
let car = Car { name: "DeLorean".to_string() };
for _ in 0..4 {
Wheel { size: 360, owner: car };
}
}
```
We try to make four `Wheel`s, each with a `Car` that it's attached to. But the
compiler knows that on the second iteration of the loop, there's a problem:
```text
error: use of moved value: `car`
Wheel { size: 360, owner: car };
^~~
note: `car` moved here because it has type `Car`, which is non-copyable
Wheel { size: 360, owner: car };
^~~
```
We need our `Car` to be pointed to by multiple `Wheel`s. We can't do that with
`Box<T>`, because it has a single owner. We can do it with `Rc<T>` instead:
```rust
use std::rc::Rc;
struct Car {
name: String,
}
struct Wheel {
size: i32,
owner: Rc<Car>,
}
fn main() {
let car = Car { name: "DeLorean".to_string() };
let car_owner = Rc::new(car);
for _ in 0..4 {
Wheel { size: 360, owner: car_owner.clone() };
}
}
```
We wrap our `Car` in an `Rc<T>`, getting an `Rc<Car>`, and then use the
`clone()` method to make new references. We've also changed our `Wheel` to have
an `Rc<Car>` rather than just a `Car`.
This is the simplest kind of multiple ownership possible. For example, there's
also `Arc<T>`, which uses more expensive atomic instructions to be the
thread-safe counterpart of `Rc<T>`.
## Lifetime Elision
Rust supports powerful local type inference in function bodies, but its
forbidden in item signatures to allow reasoning about the types just based in
the item signature alone. However, for ergonomic reasons a very restricted
secondary inference algorithm called “lifetime elision” applies in function
signatures. It infers only based on the signature components themselves and not
based on the body of the function, only infers lifetime parameters, and does
this with only three easily memorizable and unambiguous rules. This makes
lifetime elision a shorthand for writing an item signature, while not hiding
away the actual types involved as full local inference would if applied to it.
When talking about lifetime elision, we use the term *input lifetime* and
*output lifetime*. An *input lifetime* is a lifetime associated with a parameter
of a function, and an *output lifetime* is a lifetime associated with the return
value of a function. For example, this function has an input lifetime:
```{rust,ignore}
fn foo<'a>(bar: &'a str)
```
This one has an output lifetime:
```{rust,ignore}
fn foo<'a>() -> &'a str
```
This one has a lifetime in both positions:
```{rust,ignore}
fn foo<'a>(bar: &'a str) -> &'a str
```
Here are the three rules:
* Each elided lifetime in a function's arguments becomes a distinct lifetime
parameter.
* If there is exactly one input lifetime, elided or not, that lifetime is
assigned to all elided lifetimes in the return values of that function.
* If there are multiple input lifetimes, but one of them is `&self` or `&mut
self`, the lifetime of `self` is assigned to all elided output lifetimes.
Otherwise, it is an error to elide an output lifetime.
### Examples
Here are some examples of functions with elided lifetimes. We've paired each
example of an elided lifetime with its expanded form.
```{rust,ignore}
fn print(s: &str); // elided
fn print<'a>(s: &'a str); // expanded
fn debug(lvl: u32, s: &str); // elided
fn debug<'a>(lvl: u32, s: &'a str); // expanded
// In the preceding example, `lvl` doesn't need a lifetime because it's not a
// reference (`&`). Only things relating to references (such as a `struct`
// which contains a reference) need lifetimes.
fn substr(s: &str, until: u32) -> &str; // elided
fn substr<'a>(s: &'a str, until: u32) -> &'a str; // expanded
fn get_str() -> &str; // ILLEGAL, no inputs
fn frob(s: &str, t: &str) -> &str; // ILLEGAL, two inputs
fn frob<'a, 'b>(s: &'a str, t: &'b str) -> &str; // Expanded: Output lifetime is unclear
fn get_mut(&mut self) -> &mut T; // elided
fn get_mut<'a>(&'a mut self) -> &'a mut T; // expanded
fn args<T:ToCStr>(&mut self, args: &[T]) -> &mut Command // elided
fn args<'a, 'b, T:ToCStr>(&'a mut self, args: &'b [T]) -> &'a mut Command // expanded
fn new(buf: &mut [u8]) -> BufWriter; // elided
fn new<'a>(buf: &'a mut [u8]) -> BufWriter<'a> // expanded
```
# Related Resources
Coming Soon.

View File

@ -21,6 +21,8 @@ match x {
} }
``` ```
This prints `one`.
# Multiple patterns # Multiple patterns
You can match multiple patterns with `|`: You can match multiple patterns with `|`:
@ -35,6 +37,8 @@ match x {
} }
``` ```
This prints `one or two`.
# Ranges # Ranges
You can match a range of values with `...`: You can match a range of values with `...`:
@ -48,12 +52,25 @@ match x {
} }
``` ```
Ranges are mostly used with integers and single characters. This prints `one through five`.
Ranges are mostly used with integers and `char`s:
```rust
let x = '💅';
match x {
'a' ... 'j' => println!("early letter"),
'k' ... 'z' => println!("late letter"),
_ => println!("something else"),
}
```
This prints `something else`
# Bindings # Bindings
If youre matching multiple things, via a `|` or a `...`, you can bind You can bind values to names with `@`:
the value to a name with `@`:
```rust ```rust
let x = 1; let x = 1;
@ -64,6 +81,37 @@ match x {
} }
``` ```
This prints `got a range element 1`. This is useful when you want to
do a complicated match of part of a data structure:
```rust
#[derive(Debug)]
struct Person {
name: Option<String>,
}
let name = "Steve".to_string();
let mut x: Option<Person> = Some(Person { name: Some(name) });
match x {
Some(Person { name: ref a @ Some(_), .. }) => println!("{:?}", a),
_ => {}
}
```
This prints `Some("Steve")`: Weve bound the inner `name` to `a`.
If you use `@` with `|`, you need to make sure the name is bound in each part
of the pattern:
```rust
let x = 5;
match x {
e @ 1 ... 5 | e @ 8 ... 10 => println!("got a range element {}", e),
_ => println!("anything"),
}
```
# Ignoring variants # Ignoring variants
If youre matching on an enum which has variants, you can use `..` to If youre matching on an enum which has variants, you can use `..` to
@ -83,6 +131,8 @@ match x {
} }
``` ```
This prints `Got an int!`.
# Guards # Guards
You can introduce match guards with `if`: You can introduce match guards with `if`:
@ -102,6 +152,8 @@ match x {
} }
``` ```
This prints `Got an int!`
# ref and ref mut # ref and ref mut
If you want to get a [reference][ref], use the `ref` keyword: If you want to get a [reference][ref], use the `ref` keyword:
@ -114,6 +166,8 @@ match x {
} }
``` ```
This prints `Got a reference to 5`.
[ref]: references-and-borrowing.html [ref]: references-and-borrowing.html
Here, the `r` inside the `match` has the type `&i32`. In other words, the `ref` Here, the `r` inside the `match` has the type `&i32`. In other words, the `ref`
@ -130,7 +184,7 @@ match x {
# Destructuring # Destructuring
If you have a compound data type, like a `struct`, you can destructure it If you have a compound data type, like a [`struct`][struct], you can destructure it
inside of a pattern: inside of a pattern:
```rust ```rust
@ -146,6 +200,8 @@ match origin {
} }
``` ```
[struct]: structs.html
If we only care about some of the values, we dont have to give them all names: If we only care about some of the values, we dont have to give them all names:
```rust ```rust
@ -161,6 +217,8 @@ match origin {
} }
``` ```
This prints `x is 0`.
You can do this kind of match on any member, not just the first: You can do this kind of match on any member, not just the first:
```rust ```rust
@ -176,6 +234,8 @@ match origin {
} }
``` ```
This prints `y is 0`.
This destructuring behavior works on any compound data type, like This destructuring behavior works on any compound data type, like
[tuples][tuples] or [enums][enums]. [tuples][tuples] or [enums][enums].
@ -187,10 +247,10 @@ This destructuring behavior works on any compound data type, like
Whew! Thats a lot of different ways to match things, and they can all be Whew! Thats a lot of different ways to match things, and they can all be
mixed and matched, depending on what youre doing: mixed and matched, depending on what youre doing:
```{rust,ignore} ```rust,ignore
match x { match x {
Foo { x: Some(ref name), y: None } => ... Foo { x: Some(ref name), y: None } => ...
} }
``` ```
Patterns are very powerful. Make good use of them. Patterns are very powerful. Make good use of them.

View File

@ -15,7 +15,7 @@ let x = true;
let y: bool = false; let y: bool = false;
``` ```
A common use of booleans is in [`if` statements][if]. A common use of booleans is in [`if` conditionals][if].
[if]: if.html [if]: if.html
@ -62,14 +62,14 @@ let y = 1.0; // y has type f64
Heres a list of the different numeric types, with links to their documentation Heres a list of the different numeric types, with links to their documentation
in the standard library: in the standard library:
* [i8](../std/primitive.i8.html)
* [i16](../std/primitive.i16.html) * [i16](../std/primitive.i16.html)
* [i32](../std/primitive.i32.html) * [i32](../std/primitive.i32.html)
* [i64](../std/primitive.i64.html) * [i64](../std/primitive.i64.html)
* [i8](../std/primitive.i8.html) * [u8](../std/primitive.u8.html)
* [u16](../std/primitive.u16.html) * [u16](../std/primitive.u16.html)
* [u32](../std/primitive.u32.html) * [u32](../std/primitive.u32.html)
* [u64](../std/primitive.u64.html) * [u64](../std/primitive.u64.html)
* [u8](../std/primitive.u8.html)
* [isize](../std/primitive.isize.html) * [isize](../std/primitive.isize.html)
* [usize](../std/primitive.usize.html) * [usize](../std/primitive.usize.html)
* [f32](../std/primitive.f32.html) * [f32](../std/primitive.f32.html)
@ -82,7 +82,7 @@ Lets go over them by category:
Integer types come in two varieties: signed and unsigned. To understand the Integer types come in two varieties: signed and unsigned. To understand the
difference, lets consider a number with four bits of size. A signed, four-bit difference, lets consider a number with four bits of size. A signed, four-bit
number would let you store numbers from `-8` to `+7`. Signed numbers use number would let you store numbers from `-8` to `+7`. Signed numbers use
twos compliment representation. An unsigned four bit number, since it does “twos complement representation”. An unsigned four bit number, since it does
not need to store negatives, can store values from `0` to `+15`. not need to store negatives, can store values from `0` to `+15`.
Unsigned types use a `u` for their category, and signed types use `i`. The `i` Unsigned types use a `u` for their category, and signed types use `i`. The `i`
@ -103,7 +103,7 @@ and unsigned varieties. This makes for two types: `isize` and `usize`.
## Floating-point types ## Floating-point types
Rust also two floating point types: `f32` and `f64`. These correspond to Rust also has two floating point types: `f32` and `f64`. These correspond to
IEEE-754 single and double precision numbers. IEEE-754 single and double precision numbers.
# Arrays # Arrays
@ -168,6 +168,7 @@ like arrays:
```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 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
``` ```
Slices have type `&[T]`. Well talk about that `T` when we cover Slices have type `&[T]`. Well talk about that `T` when we cover
@ -175,7 +176,7 @@ Slices have type `&[T]`. Well talk about that `T` when we cover
[generics]: generics.html [generics]: generics.html
You can find more documentation for `slices`s [in the standard library You can find more documentation for slices [in the standard library
documentation][slice]. documentation][slice].
[slice]: ../std/primitive.slice.html [slice]: ../std/primitive.slice.html
@ -216,6 +217,18 @@ In systems programming languages, strings are a bit more complex than in other
languages. For now, just read `&str` as a *string slice*, and well learn more languages. For now, just read `&str` as a *string slice*, and well learn more
soon. soon.
You can assign one tuple into another, if they have the same contained types
and [arity]. Tuples have the same arity when they have the same length.
[arity]: glossary.html#arity
```rust
let mut x = (1, 2); // x: (i32, i32)
let y = (2, 3); // y: (i32, i32)
x = y;
```
You can access the fields in a tuple through a *destructuring let*. Heres You can access the fields in a tuple through a *destructuring let*. Heres
an example: an example:
@ -228,27 +241,39 @@ println!("x is {}", x);
Remember [before][let] when I said the left-hand side of a `let` statement was more Remember [before][let] when I said the left-hand side of a `let` statement was more
powerful than just assigning a binding? Here we are. We can put a pattern on powerful than just assigning a binding? Here we are. We can put a pattern on
the left-hand side of the `let`, and if it matches up to the right-hand side, the left-hand side of the `let`, and if it matches up to the right-hand side,
we can assign multiple bindings at once. In this case, `let` "destructures," we can assign multiple bindings at once. In this case, `let` “destructures”
or "breaks up," the tuple, and assigns the bits to three bindings. or “breaks up” the tuple, and assigns the bits to three bindings.
[let]: variable-bindings.html [let]: variable-bindings.html
This pattern is very powerful, and well see it repeated more later. This pattern is very powerful, and well see it repeated more later.
There are also a few things you can do with a tuple as a whole, without You can disambiguate a single-element tuple from a value in parentheses with a
destructuring. You can assign one tuple into another, if they have the same comma:
contained types and [arity]. Tuples have the same arity when they have the same
length. ```
(0,); // single-element tuple
(0); // zero in parentheses
```
## Tuple Indexing
You can also access fields of a tuple with indexing syntax:
[arity]: glossary.html#arity
```rust ```rust
let mut x = (1, 2); // x: (i32, i32) let tuple = (1, 2, 3);
let y = (2, 3); // y: (i32, i32)
x = y; let x = tuple.0;
let y = tuple.1;
let z = tuple.2;
println!("x is {}", x);
``` ```
Like array indexing, it starts at zero, but unlike array indexing, it uses a
`.`, rather than `[]`s.
You can find more documentation for tuples [in the standard library You can find more documentation for tuples [in the standard library
documentation][tuple]. documentation][tuple].

View File

@ -0,0 +1,122 @@
% Raw Pointers
Rust has a number of different smart pointer types in its standard library, but
there are two types that are extra-special. Much of Rusts safety comes from
compile-time checks, but raw pointers dont have such guarantees, and are
[unsafe][unsafe] to use.
`*const T` and `*mut T` are called raw pointers in Rust. Sometimes, when
writing certain kinds of libraries, youll need to get around Rusts safety
guarantees for some reason. In this case, you can use raw pointers to implement
your library, while exposing a safe interface for your users. For example, `*`
pointers are allowed to alias, allowing them to be used to write
shared-ownership types, and even thread-safe shared memory types (the `Rc<T>`
and `Arc<T>` types are both implemented entirely in Rust).
Here are some things to remember about raw pointers that are different than
other pointer types. They:
- are not guaranteed to point to valid memory and are not even
guaranteed to be non-null (unlike both `Box` and `&`);
- do not have any automatic clean-up, unlike `Box`, and so require
manual resource management;
- are plain-old-data, that is, they don't move ownership, again unlike
`Box`, hence the Rust compiler cannot protect against bugs like
use-after-free;
- lack any form of lifetimes, unlike `&`, and so the compiler cannot
reason about dangling pointers; and
- have no guarantees about aliasing or mutability other than mutation
not being allowed directly through a `*const T`.
# Basics
Creating a raw pointer is perfectly safe:
```rust
let x = 5;
let raw = &x as *const i32;
let mut y = 10;
let raw_mut = &mut y as *mut i32;
```
However, dereferencing one is not. This wont work:
```rust,ignore
let x = 5;
let raw = &x as *const i32;
println!("raw points at {}", *raw);
```
It gives this error:
```text
error: dereference of unsafe pointer requires unsafe function or block [E0133]
println!("raw points at{}", *raw);
^~~~
```
When you dereference a raw pointer, youre taking responsibility that its not
pointing somewhere that would be incorrect. As such, you need `unsafe`:
```rust
let x = 5;
let raw = &x as *const i32;
let points_at = unsafe { *raw };
println!("raw points at {}", points_at);
```
For more operations on raw pointers, see [their API documentation][rawapi].
[unsafe]: unsafe.html
[rawapi]: ../std/primitive.pointer.html
# FFI
Raw pointers are useful for FFI: Rusts `*const T` and `*mut T` are similar to
Cs `const T*` and `T*`, respectfully. For more about this use, consult the
[FFI chapter][ffi].
[ffi]: ffi.html
# References and raw pointers
At runtime, a raw pointer `*` and a reference pointing to the same piece of
data have an identical representation. In fact, an `&T` reference will
implicitly coerce to an `*const T` raw pointer in safe code and similarly for
the `mut` variants (both coercions can be performed explicitly with,
respectively, `value as *const T` and `value as *mut T`).
Going the opposite direction, from `*const` to a reference `&`, is not safe. A
`&T` is always valid, and so, at a minimum, the raw pointer `*const T` has to
point to a valid instance of type `T`. Furthermore, the resulting pointer must
satisfy the aliasing and mutability laws of references. The compiler assumes
these properties are true for any references, no matter how they are created,
and so any conversion from raw pointers is asserting that they hold. The
programmer *must* guarantee this.
The recommended method for the conversion is
```rust
let i: u32 = 1;
// explicit cast
let p_imm: *const u32 = &i as *const u32;
let mut m: u32 = 2;
// implicit coercion
let p_mut: *mut u32 = &mut m;
unsafe {
let ref_imm: &u32 = &*p_imm;
let ref_mut: &mut u32 = &mut *p_mut;
}
```
The `&*x` dereferencing style is preferred to using a `transmute`. The latter
is far more powerful than necessary, and the more restricted operation is
harder to use incorrectly; for example, it requires that `x` is a pointer
(unlike `transmute`).

View File

@ -1,3 +1,371 @@
% References and Borrowing % References and Borrowing
Coming Soon! This guide is one of three presenting Rusts ownership system. This is one of
Rusts most unique and compelling features, with which Rust developers should
become quite acquainted. Ownership is how Rust achieves its largest goal,
memory safety. There are a few distinct concepts, each with its own
chapter:
* [ownership][ownership], the key concept
* borrowing, which youre reading now
* [lifetimes][lifetimes], an advanced concept of borrowing
These three chapters are related, and in order. Youll need all three to fully
understand the ownership system.
[ownership]: ownership.html
[lifetimes]: lifetimes.html
# Meta
Before we get to the details, two important notes about the ownership system.
Rust has a focus on safety and speed. It accomplishes these goals through many
zero-cost abstractions, which means that in Rust, abstractions cost as little
as possible in order to make them work. The ownership system is a prime example
of a zero cost abstraction. All of the analysis well talk about in this guide
is _done at compile time_. You do not pay any run-time cost for any of these
features.
However, this system does have a certain cost: learning curve. Many new users
to Rust experience something we like to call fighting with the borrow
checker, where the Rust compiler refuses to compile a program that the author
thinks is valid. This often happens because the programmers mental model of
how ownership should work doesnt match the actual rules that Rust implements.
You probably will experience similar things at first. There is good news,
however: more experienced Rust developers report that once they work with the
rules of the ownership system for a period of time, they fight the borrow
checker less and less.
With that in mind, lets learn about borrowing.
# Borrowing
At the end of the [ownership][ownership] section, we had a nasty function that looked
like this:
```rust
fn foo(v1: Vec<i32>, v2: Vec<i32>) -> (Vec<i32>, Vec<i32>, i32) {
// do stuff with v1 and v2
// hand back ownership, and the result of our function
(v1, v2, 42)
}
let v1 = vec![1, 2, 3];
let v2 = vec![1, 2, 3];
let (v1, v2, answer) = foo(v1, v2);
```
This is not idiomatic Rust, however, as it doesnt take advantage of borrowing. Heres
the first step:
```rust
fn foo(v1: &Vec<i32>, v2: &Vec<i32>) -> i32 {
// do stuff with v1 and v2
// return the answer
42
}
let v1 = vec![1, 2, 3];
let v2 = vec![1, 2, 3];
let answer = foo(&v1, &v2);
// we can use v1 and v2 here!
```
Instead of taking `Vec<i32>`s as our arguments, we take a reference:
`&Vec<i32>`. And instead of passing `v1` and `v2` directly, we pass `&v1` and
`&v2`. We call the `&T` type a reference, and rather than owning the resource,
it borrows ownership. A binding that borrows something does not deallocate the
resource when it goes out of scope. This means that after the call to `foo()`,
we can use our original bindings again.
References are immutable, just like bindings. This means that inside of `foo()`,
the vectors cant be changed at all:
```rust,ignore
fn foo(v: &Vec<i32>) {
v.push(5);
}
let v = vec![];
foo(&v);
```
errors with:
```text
error: cannot borrow immutable borrowed content `*v` as mutable
v.push(5);
^
```
Pushing a value mutates the vector, and so we arent allowed to do it.
# &mut references
Theres a second kind of reference: `&mut T`. A mutable reference allows you
to mutate the resource youre borrowing. For example:
```rust
let mut x = 5;
{
let y = &mut x;
*y += 1;
}
println!("{}", x);
```
This will print `6`. We make `y` a mutable reference to `x`, then add one to
the thing `y` points at. Youll notice that `x` had to be marked `mut` as well,
if it wasnt, we couldnt take a mutable borrow to an immutable value.
Otherwise, `&mut` references are just like references. There _is_ a large
difference between the two, and how they interact, though. You can tell
something is fishy in the above example, because we need that extra scope, with
the `{` and `}`. If we remove them, we get an error:
```text
error: cannot borrow `x` as immutable because it is also borrowed as mutable
println!("{}", x);
^
note: previous borrow of `x` occurs here; the mutable borrow prevents
subsequent moves, borrows, or modification of `x` until the borrow ends
let y = &mut x;
^
note: previous borrow ends here
fn main() {
}
^
```
As it turns out, there are rules.
# The Rules
Heres the rules about borrowing in Rust:
First, any borrow must last for a smaller scope than the owner. Second, you may
have one or the other of these two kinds of borrows, but not both at the same
time:
* 0 to N references (`&T`) to a resource.
* exactly one mutable reference (`&mut T`)
You may notice that this is very similar, though not exactly the same as,
to the definition of a data race:
> There is a data race when two or more pointers access the same memory
> location at the same time, where at least one of them is writing, and the
> operations are not synchronized.
With references, you may have as many as youd like, since none of them are
writing. If you are writing, you need two or more pointers to the same memory,
and you can only have one `&mut` at a time. This is how Rust prevents data
races at compile time: well get errors if we break the rules.
With this in mind, lets consider our example again.
## Thinking in scopes
Heres the code:
```rust,ignore
let mut x = 5;
let y = &mut x;
*y += 1;
println!("{}", x);
```
This code gives us this error:
```text
error: cannot borrow `x` as immutable because it is also borrowed as mutable
println!("{}", x);
^
```
This is because weve violated the rules: we have a `&mut T` pointing to `x`,
and so we arent allowed to create any `&T`s. One or the other. The note
hints at how to think about this problem:
```text
note: previous borrow ends here
fn main() {
}
^
```
In other words, the mutable borow is held through the rest of our example. What
we want is for the mutable borrow to end _before_ we try to call `println!` and
make an immutable borrow. In Rust, borrowing is tied to the scope that the
borrow is valid for. And our scopes look like this:
```rust,ignore
let mut x = 5;
let y = &mut x; // -+ &mut borrow of x starts here
// |
*y += 1; // |
// |
println!("{}", x); // -+ - try to borrow x here
// -+ &mut borrow of x ends here
```
The scopes conflict: we cant make an `&x` while `y` is in scope.
So when we add the curly braces:
```rust
let mut x = 5;
{
let y = &mut x; // -+ &mut borrow starts here
*y += 1; // |
} // -+ ... and ends here
println!("{}", x); // <- try to borrow x here
```
Theres no problem. Our mutable borrow goes out of scope before we create an
immutable one. But scope is the key to seeing how long a borrow lasts for.
## Issues borrowing prevents
Why have these restrictive rules? Well, as we noted, these rules prevent data
races. What kinds of issues do data races cause? Heres a few.
### Iterator invalidation
One example is iterator invalidation, which happens when you try to mutate a
collection that youre iterating over. Rusts borrow checker prevents this from
happening:
```rust
let mut v = vec![1, 2, 3];
for i in &v {
println!("{}", i);
}
```
This prints out one through three. As we iterate through the vectors, were
only given references to the elements. And `v` is itself borrowed as immutable,
which means we cant change it while were iterating:
```rust,ignore
let mut v = vec![1, 2, 3];
for i in &v {
println!("{}", i);
v.push(34);
}
```
Heres the error:
```text
error: cannot borrow `v` as mutable because it is also borrowed as immutable
v.push(34);
^
note: previous borrow of `v` occurs here; the immutable borrow prevents
subsequent moves or mutable borrows of `v` until the borrow ends
for i in &v {
^
note: previous borrow ends here
for i in &v {
println!(“{}”, i);
v.push(34);
}
^
```
We cant modify `v` because its borrowed by the loop.
### use after free
References must live as long as the resource they refer to. Rust will check the
scopes of your references to ensure that this is true.
If Rust didnt check that this property, we could accidentally use a reference
which was invalid. For example:
```rust,ignore
let y: &i32;
{
let x = 5;
y = &x;
}
println!("{}", y);
```
We get this error:
```text
error: `x` does not live long enough
y = &x;
^
note: reference must be valid for the block suffix following statement 0 at
2:16...
let y: &i32;
{
let x = 5;
y = &x;
}
note: ...but borrowed value is only valid for the block suffix following
statement 0 at 4:18
let x = 5;
y = &x;
}
```
In other words, `y` is only valid for the scope where `x` exists. As soon as
`x` goes away, it becomes invalid to refer to it. As such, the error says that
the borrow doesnt live long enough because its not valid for the right
amount of time.
The same problem occurs when the reference is declared _before_ the variable it refers to:
```rust,ignore
let y: &i32;
let x = 5;
y = &x;
println!("{}", y);
```
We get this error:
```text
error: `x` does not live long enough
y = &x;
^
note: reference must be valid for the block suffix following statement 0 at
2:16...
let y: &i32;
let x = 5;
y = &x;
println!("{}", y);
}
note: ...but borrowed value is only valid for the block suffix following
statement 1 at 3:14
let x = 5;
y = &x;
println!("{}", y);
}
```

View File

@ -0,0 +1,45 @@
% Release Channels
The Rust project uses a concept called release channels to manage releases.
Its important to understand this process to choose which version of Rust
your project should use.
# Overview
There are three channels for Rust releases:
* Nightly
* Beta
* Stable
New nightly releases are created once a day. Every six weeks, the latest
nightly release is promoted to Beta. At that point, it will only receive
patches to fix serious errors. Six weeks later, the beta is promoted to
Stable, and becomes the next release of `1.x`.
This process happens in parallel. So every six weeks, on the same day,
nightly goes to beta, beta goes to stable. When `1.x` is released, at
the same time, `1.(x + 1)-beta` is released, and the nightly becomes the
first version of `1.(x + 2)-nightly`.
# Choosing a version
Generally speaking, unless you have a specific reason, you should be using the
stable release channel. These releases are intended for a general audience.
However, depending on your interest in Rust, you may choose to use nightly
instead. The basic tradeoff is this: in the nightly channel, you can use
unstable, new Rust features. However, unstable features are subject to change,
and so any new nightly release may break your code. If you use the stable
release, you cannot use experimental features, but the next release of Rust
will not cause significant issues through breaking changes.
# Helping the ecosystem through CI
What about beta? We encourage all Rust users who use the stable release channel
to also test against the beta channel in their continuous integration systems.
This will help alert the team in case theres an accidental regression.
Additionally, testing against nightly can catch regressions even sooner, and so
if you dont mind a third build, wed appreciate testing against all channels.

View File

@ -0,0 +1,353 @@
% Rust Inside Other Languages
For our third project, were going to choose something that shows off one of
Rusts greatest strengths: a lack of a substantial runtime.
As organizations grow, they increasingly rely on a multitude of programming
languages. Different programming languages have different strengths and
weaknesses, and a polyglot stack lets you use a particular language where
its strengths make sense, and use a different language where its weak.
A very common area where many programming languages are weak is in runtime
performance of programs. Often, using a language that is slower, but offers
greater programmer productivity is a worthwhile trade-off. To help mitigate
this, they provide a way to write some of your system in C, and then call
the C code as though it were written in the higher-level language. This is
called a foreign function interface, often shortened to FFI.
Rust has support for FFI in both directions: it can call into C code easily,
but crucially, it can also be called _into_ as easily as C. Combined with
Rusts lack of a garbage collector and low runtime requirements, this makes
Rust a great candidate to embed inside of other languages when you need
some extra oomph.
There is a whole [chapter devoted to FFI][ffi] and its specifics elsewhere in
the book, but in this chapter, well examine this particular use-case of FFI,
with three examples, in Ruby, Python, and JavaScript.
[ffi]: ffi.html
# The problem
There are many different projects we could choose here, but were going to
pick an example where Rust has a clear advantage over many other languages:
numeric computing and threading.
Many languages, for the sake of consistency, place numbers on the heap, rather
than on the stack. Especially in languages that focus on object-oriented
programming and use garbage collection, heap allocation is the default. Sometimes
optimizations can stack allocate particular numbers, but rather than relying
on an optimizer to do its job, we may want to ensure that were always using
primitive number types rather than some sort of object type.
Second, many languages have a global interpreter lock, which limits
concurrency in many situations. This is done in the name of safety, which is
a positive effect, but it limits the amount of work that can be done at the
same time, which is a big negative.
To emphasize these two aspects, were going to create a little project that
uses these two aspects heavily. Since the focus of the example is the embedding
of Rust into the languages, rather than the problem itself, well just use a
toy example:
> Start ten threads. Inside each thread, count from one to five million. After
> All ten threads are finished, print out done!.
I chose five million based on my particular computer. Heres an example of this
code in Ruby:
```ruby
threads = []
10.times do
threads << Thread.new do
count = 0
5_000_000.times do
count += 1
end
end
end
threads.each {|t| t.join }
puts "done!"
```
Try running this example, and choose a number that runs for a few seconds.
Depending on your computers hardware, you may have to increase or decrease the
number.
On my system, running this program takes `2.156` seconds. And, if I use some
sort of process monitoring tool, like `top`, I can see that it only uses one
core on my machine. Thats the GIL kicking in.
While its true that this is a synthetic program, one can imagine many problems
that are similar to this in the real world. For our purposes, spinning up some
busy threads represents some sort of parallel, expensive computation.
# A Rust library
Lets re-write this problem in Rust. First, lets make a new project with
Cargo:
```bash
$ cargo new embed
$ cd embed
```
This program is fairly easy to write in Rust:
```rust
use std::thread;
fn process() {
let handles: Vec<_> = (0..10).map(|_| {
thread::spawn(|| {
let mut _x = 0;
for _ in (0..5_000_001) {
_x += 1
}
})
}).collect();
for h in handles {
h.join().ok().expect("Could not join a thread!");
}
}
```
Some of this should look familiar from previous examples. We spin up ten
threads, collecting them into a `handles` vector. Inside of each thread, we
loop five million times, and add one to `_x` each time. Why the underscore?
Well, if we remove it and compile:
```bash
$ cargo build
Compiling embed v0.1.0 (file:///home/steve/src/embed)
src/lib.rs:3:1: 16:2 warning: function is never used: `process`, #[warn(dead_code)] on by default
src/lib.rs:3 fn process() {
src/lib.rs:4 let handles: Vec<_> = (0..10).map(|_| {
src/lib.rs:5 thread::spawn(|| {
src/lib.rs:6 let mut x = 0;
src/lib.rs:7 for _ in (0..5_000_001) {
src/lib.rs:8 x += 1
...
src/lib.rs:6:17: 6:22 warning: variable `x` is assigned to, but never used, #[warn(unused_variables)] on by default
src/lib.rs:6 let mut x = 0;
^~~~~
```
That first warning is because we are building a library. If we had a test
for this function, the warning would go away. But for now, its never
called.
The second is related to `x` versus `_x`. Because we never actually _do_
anything with `x`, we get a warning about it. In our case, thats perfectly
okay, as were just trying to waste CPU cycles. Prefixing `x` with the
underscore removes the warning.
Finally, we join on each thread.
Right now, however, this is a Rust library, and it doesnt expose anything
thats callable from C. If we tried to hook this up to another language right
now, it wouldnt work. We only need to make two small changes to fix this,
though. The first is modify the beginning of our code:
```rust,ignore
#[no_mangle]
pub extern fn process() {
```
We have to add a new attribute, `no_mangle`. When you create a Rust library, it
changes the name of the function in the compiled output. The reasons for this
are outside the scope of this tutorial, but in order for other languages to
know how to call the function, we need to not do that. This attribute turns
that behavior off.
The other change is the `pub extern`. The `pub` means that this function should
be callable from outside of this module, and the `extern` says that it should
be able to be called from C. Thats it! Not a whole lot of change.
The second thing we need to do is to change a setting in our `Cargo.toml`. Add
this at the bottom:
```toml
[lib]
name = "embed"
crate-type = ["dylib"]
```
This tells Rust that we want to compile our library into a standard dynamic
library. By default, Rust compiles into an rlib, a Rust-specific format.
Lets build the project now:
```bash
$ cargo build --release
Compiling embed v0.1.0 (file:///home/steve/src/embed)
```
Weve chosen `cargo build --release`, which builds with optimizations on. We
want this to be as fast as possible! You can find the output of the library in
`target/release`:
```bash
$ ls target/release/
build deps examples libembed.so native
```
That `libembed.so` is our shared object library. We can use this file
just like any shared object library written in C! As an aside, this may be
`embed.dll` or `libembed.dylib`, depending on the platform.
Now that weve got our Rust library built, lets use it from our Ruby.
# Ruby
Open up a `embed.rb` file inside of our project, and do this:
```ruby
require 'ffi'
module Hello
extend FFI::Library
ffi_lib 'target/release/libembed.so'
attach_function :process, [], :void
end
Hello.process
puts "done!”
```
Before we can run this, we need to install the `ffi` gem:
```bash
$ gem install ffi # this may need sudo
Fetching: ffi-1.9.8.gem (100%)
Building native extensions. This could take a while...
Successfully installed ffi-1.9.8
Parsing documentation for ffi-1.9.8
Installing ri documentation for ffi-1.9.8
Done installing documentation for ffi after 0 seconds
1 gem installed
```
And finally, we can try running it:
```bash
$ ruby embed.rb
done!
$
```
Whoah, that was fast! On my system, this took `0.086` seconds, rather than
the two seconds the pure Ruby version took. Lets break down this Ruby
code:
```ruby
require 'ffi'
```
We first need to require the `ffi` gem. This lets us interface with our
Rust library like a C library.
```ruby
module Hello
extend FFI::Library
ffi_lib 'target/release/libembed.so'
```
The `ffi` gems authors recommend using a module to scope the functions
well import from the shared library. Inside, we `extend` the necessary
`FFI::Library` module, and then call `ffi_lib` to load up our shared
object library. We just pass it the path that our library is stored,
which as we saw before, is `target/release/libembed.so`.
```ruby
attach_function :process, [], :void
```
The `attach_function` method is provided by the FFI gem. Its what
connects our `process()` function in Rust to a Ruby function of the
same name. Since `process()` takes no arguments, the second parameter
is an empty array, and since it returns nothing, we pass `:void` as
the final argument.
```ruby
Hello.process
```
This is the actual call into Rust. The combination of our `module`
and the call to `attach_function` sets this all up. It looks like
a Ruby function, but is actually Rust!
```ruby
puts "done!"
```
Finally, as per our projects requirements, we print out `done!`.
Thats it! As weve seen, bridging between the two languages is really easy,
and buys us a lot of performance.
Next, lets try Python!
# Python
Create an `embed.py` file in this directory, and put this in it:
```python
from ctypes import cdll
lib = cdll.LoadLibrary("target/release/libembed.so")
lib.process()
print("done!")
```
Even easier! We use `cdll` from the `ctypes` module. A quick call
to `LoadLibrary` later, and we can call `process()`.
On my system, this takes `0.017` seconds. Speedy!
# Node.js
Node isnt a language, but its currently the dominant implementation of
server-side JavaScript.
In order to do FFI with Node, we first need to install the library:
```bash
$ npm install ffi
```
After that installs, we can use it:
```javascript
var ffi = require('ffi');
var lib = ffi.Library('target/release/libembed', {
'process': [ 'void', [] ]
});
lib.process();
console.log("done!");
```
It looks more like the Ruby example than the Python example. We use
the `ffi` module to get access to `ffi.Library()`, which loads up
our shared object. We need to annotate the return type and argument
types of the function, which are 'void' for return, and an empty
array to signify no arguments. From there, we just call it and
print the result.
On my system, this takes a quick `0.092` seconds.
# Conclusion
As you can see, the basics of doing this are _very_ easy. Of course,
there's a lot more that we could do here. Check out the [FFI][ffi]
chapter for more details.

View File

@ -16,3 +16,27 @@ fn main() {
} }
``` ```
The `advanced_slice_patterns` gate lets you use `..` to indicate any number of
elements inside a pattern matching a slice. This wildcard can only be used once
for a given array. If there's an identifier before the `..`, the result of the
slice will be bound to that name. For example:
```rust
#![feature(advanced_slice_patterns, slice_patterns)]
fn is_symmetric(list: &[u32]) -> bool {
match list {
[] | [_] => true,
[x, inside.., y] if x == y => is_symmetric(inside),
_ => false
}
}
fn main() {
let sym = &[0, 1, 4, 2, 4, 1, 0];
assert!(is_symmetric(sym));
let not_sym = &[0, 1, 7, 2, 4, 1, 0];
assert!(!is_symmetric(not_sym));
}
```

View File

@ -1,36 +1,34 @@
% Strings % Strings
Strings are an important concept for any programmer to master. Rust's string Strings are an important concept for any programmer to master. Rusts string
handling system is a bit different from other languages, due to its systems handling system is a bit different from other languages, due to its systems
focus. Any time you have a data structure of variable size, things can get focus. Any time you have a data structure of variable size, things can get
tricky, and strings are a re-sizable data structure. That being said, Rust's tricky, and strings are a re-sizable data structure. That being said, Rusts
strings also work differently than in some other systems languages, such as C. strings also work differently than in some other systems languages, such as C.
Let's dig into the details. A *string* is a sequence of Unicode scalar values Lets dig into the details. A string is a sequence of Unicode scalar values
encoded as a stream of UTF-8 bytes. All strings are guaranteed to be encoded as a stream of UTF-8 bytes. All strings are guaranteed to be a valid
validly encoded UTF-8 sequences. Additionally, strings are not null-terminated encoding of UTF-8 sequences. Additionally, unlike some systems languages,
and can contain null bytes. strings are not null-terminated and can contain null bytes.
Rust has two main types of strings: `&str` and `String`. Rust has two main types of strings: `&str` and `String`. Lets talk about
`&str` first. These are called string slices. String literals are of the type
`&'static str`:
The first kind is a `&str`. These are called *string slices*. String literals ```rust
are of the type `&str`: let string = "Hello there."; // string: &'static str
```{rust}
let string = "Hello there."; // string: &str
``` ```
This string is statically allocated, meaning that it's saved inside our This string is statically allocated, meaning that its saved inside our
compiled program, and exists for the entire duration it runs. The `string` compiled program, and exists for the entire duration it runs. The `string`
binding is a reference to this statically allocated string. String slices binding is a reference to this statically allocated string. String slices
have a fixed size, and cannot be mutated. have a fixed size, and cannot be mutated.
A `String`, on the other hand, is a heap-allocated string. This string A `String`, on the other hand, is a heap-allocated string. This string is
is growable, and is also guaranteed to be UTF-8. `String`s are growable, and is also guaranteed to be UTF-8. `String`s are commonly created by
commonly created by converting from a string slice using the converting from a string slice using the `to_string` method.
`to_string` method.
```{rust} ```rust
let mut s = "Hello".to_string(); // mut s: String let mut s = "Hello".to_string(); // mut s: String
println!("{}", s); println!("{}", s);
@ -54,8 +52,78 @@ fn main() {
Viewing a `String` as a `&str` is cheap, but converting the `&str` to a Viewing a `String` as a `&str` is cheap, but converting the `&str` to a
`String` involves allocating memory. No reason to do that unless you have to! `String` involves allocating memory. No reason to do that unless you have to!
That's the basics of strings in Rust! They're probably a bit more complicated ## Indexing
than you are used to, if you come from a scripting language, but when the
low-level details matter, they really matter. Just remember that `String`s Because strings are valid UTF-8, strings do not support indexing:
allocate memory and control their data, while `&str`s are a reference to
another string, and you'll be all set. ```rust,ignore
let s = "hello";
println!("The first letter of s is {}", s[0]); // ERROR!!!
```
Usually, access to a vector with `[]` is very fast. But, because each character
in a UTF-8 encoded string can be multiple bytes, you have to walk over the
string to find the nᵗʰ letter of a string. This is a significantly more
expensive operation, and we dont want to be misleading. Furthermore, letter
isnt something defined in Unicode, exactly. We can choose to look at a string as
individual bytes, or as codepoints:
```rust
let hachiko = "忠犬ハチ公";
for b in hachiko.as_bytes() {
print!("{}, ", b);
}
println!("");
for c in hachiko.chars() {
print!("{}, ", c);
}
println!("");
```
This prints:
```text
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.
You can get something similar to an index like this:
```rust
# let hachiko = "忠犬ハチ公";
let dog = hachiko.chars().nth(1); // kinda like hachiko[1]
```
This emphasizes that we have to go through the whole list of `chars`.
## Concatenation
If you have a `String`, you can concatenate a `&str` to the end of it:
```rust
let hello = "Hello ".to_string();
let world = "world!";
let hello_world = hello + world;
```
But if you have two `String`s, you need an `&`:
```rust
let hello = "Hello ".to_string();
let world = "world!".to_string();
let hello_world = hello + &world;
```
This is because `&String` can automatically coerece to a `&str`. This is a
feature called [`Deref` coercions][dc].
[dc]: deref-coercions.html

View File

@ -1,6 +1,6 @@
% Structs % Structs
Structs are a way of creating more complex datatypes. For example, if we were Structs are a way of creating more complex data types. For example, if we were
doing calculations involving coordinates in 2D space, we would need both an `x` doing calculations involving coordinates in 2D space, we would need both an `x`
and a `y` value: and a `y` value:
@ -24,12 +24,12 @@ fn main() {
} }
``` ```
Theres a lot going on here, so lets break it down. We declare a struct with Theres a lot going on here, so lets break it down. We declare a `struct` with
the `struct` keyword, and then with a name. By convention, structs begin with a the `struct` keyword, and then with a name. By convention, `struct`s begin with
capital letter and are also camel cased: `PointInSpace`, not `Point_In_Space`. a capital letter and are camel cased: `PointInSpace`, not `Point_In_Space`.
We can create an instance of our struct via `let`, as usual, but we use a `key: We can create an instance of our struct via `let`, as usual, but we use a `key:
value` style syntax to set each field. The order doesn't need to be the same as value` style syntax to set each field. The order doesnt need to be the same as
in the original declaration. in the original declaration.
Finally, because fields have names, we can access the field through dot Finally, because fields have names, we can access the field through dot
@ -87,3 +87,112 @@ fn main() {
point.y = 6; // this causes an error point.y = 6; // this causes an error
} }
``` ```
# Update syntax
A `struct` can include `..` to indicate that you want to use a copy of some
other struct for some of the values. For example:
```rust
struct Point3d {
x: i32,
y: i32,
z: i32,
}
let mut point = Point3d { x: 0, y: 0, z: 0 };
point = Point3d { y: 1, .. point };
```
This gives `point` a new `y`, but keeps the old `x` and `z` values. It doesnt
have to be the same `struct` either, you can use this syntax when making new
ones, and it will copy the values you dont specify:
```rust
# struct Point3d {
# x: i32,
# y: i32,
# z: i32,
# }
let origin = Point3d { x: 0, y: 0, z: 0 };
let point = Point3d { z: 1, x: 2, .. origin };
```
# Tuple structs
Rust has another data type thats like a hybrid between a [tuple][tuple] and a
struct, called a tuple struct. Tuple structs have a name, but
their fields dont:
```rust
struct Color(i32, i32, i32);
struct Point(i32, i32, i32);
```
[tuple]: primitive-types.html#tuples
These two will not be equal, even if they have the same values:
```rust
# struct Color(i32, i32, i32);
# struct Point(i32, i32, i32);
let black = Color(0, 0, 0);
let origin = Point(0, 0, 0);
```
It is almost always better to use a struct than a tuple struct. We would write
`Color` and `Point` like this instead:
```rust
struct Color {
red: i32,
blue: i32,
green: i32,
}
struct Point {
x: i32,
y: i32,
z: i32,
}
```
Now, we have actual names, rather than positions. Good names are important,
and with a struct, we have actual names.
There _is_ one case when a tuple struct is very useful, though, and thats a
tuple struct with only one element. We call this the newtype pattern, because
it allows you to create a new type, distinct from that of its contained value
and expressing its own semantic meaning:
```rust
struct Inches(i32);
let length = Inches(10);
let Inches(integer_length) = length;
println!("length is {} inches", integer_length);
```
As you can see here, you can extract the inner integer type through a
destructuring `let`, just as with regular tuples. In this case, the
`let Inches(integer_length)` assigns `10` to `integer_length`.
# Unit-like structs
You can define a struct with no members at all:
```rust
struct Electron;
```
Such a struct is called unit-like because it resembles the empty
tuple, `()`, sometimes called unit. Like a tuple struct, it defines a
new type.
This is rarely useful on its own (although sometimes it can serve as a
marker type), but in combination with other features, it can become
useful. For instance, a library may ask you to create a structure that
implements a certain [trait][trait] to handle events. If you dont have
any data you need to store in the structure, you can just create a
unit-like struct.

View File

@ -219,10 +219,10 @@ fn it_works() {
This is a very common use of `assert_eq!`: call some function with This is a very common use of `assert_eq!`: call some function with
some known arguments and compare it to the expected output. some known arguments and compare it to the expected output.
# The `test` module # The `tests` module
There is one way in which our existing example is not idiomatic: it's There is one way in which our existing example is not idiomatic: it's
missing the test module. The idiomatic way of writing our example missing the `tests` module. The idiomatic way of writing our example
looks like this: looks like this:
```{rust,ignore} ```{rust,ignore}
@ -231,7 +231,7 @@ pub fn add_two(a: i32) -> i32 {
} }
#[cfg(test)] #[cfg(test)]
mod test { mod tests {
use super::add_two; use super::add_two;
#[test] #[test]
@ -241,7 +241,7 @@ mod test {
} }
``` ```
There's a few changes here. The first is the introduction of a `mod test` with There's a few changes here. The first is the introduction of a `mod tests` with
a `cfg` attribute. The module allows us to group all of our tests together, and a `cfg` attribute. The module allows us to group all of our tests together, and
to also define helper functions if needed, that don't become a part of the rest to also define helper functions if needed, that don't become a part of the rest
of our crate. The `cfg` attribute only compiles our test code if we're of our crate. The `cfg` attribute only compiles our test code if we're
@ -260,7 +260,7 @@ pub fn add_two(a: i32) -> i32 {
} }
#[cfg(test)] #[cfg(test)]
mod test { mod tests {
use super::*; use super::*;
#[test] #[test]
@ -279,7 +279,7 @@ $ cargo test
Running target/adder-91b3e234d4ed382a Running target/adder-91b3e234d4ed382a
running 1 test running 1 test
test test::it_works ... ok test tests::it_works ... ok
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured
@ -292,7 +292,7 @@ test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured
It works! It works!
The current convention is to use the `test` module to hold your "unit-style" The current convention is to use the `tests` module to hold your "unit-style"
tests. Anything that just tests one small bit of functionality makes sense to tests. Anything that just tests one small bit of functionality makes sense to
go here. But what about "integration-style" tests instead? For that, we have go here. But what about "integration-style" tests instead? For that, we have
the `tests` directory the `tests` directory
@ -325,7 +325,7 @@ $ cargo test
Running target/adder-91b3e234d4ed382a Running target/adder-91b3e234d4ed382a
running 1 test running 1 test
test test::it_works ... ok test tests::it_works ... ok
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured
@ -346,7 +346,7 @@ test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured
Now we have three sections: our previous test is also run, as well as our new Now we have three sections: our previous test is also run, as well as our new
one. one.
That's all there is to the `tests` directory. The `test` module isn't needed That's all there is to the `tests` directory. The `tests` module isn't needed
here, since the whole thing is focused on tests. here, since the whole thing is focused on tests.
Let's finally check out that third section: documentation tests. Let's finally check out that third section: documentation tests.
@ -382,7 +382,7 @@ pub fn add_two(a: i32) -> i32 {
} }
#[cfg(test)] #[cfg(test)]
mod test { mod tests {
use super::*; use super::*;
#[test] #[test]
@ -405,7 +405,7 @@ $ cargo test
Running target/adder-91b3e234d4ed382a Running target/adder-91b3e234d4ed382a
running 1 test running 1 test
test test::it_works ... ok test tests::it_works ... ok
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured

View File

@ -1,3 +1,570 @@
% The Stack and the Heap % The Stack and the Heap
Coming Soon As a systems language, Rust operates at a low level. If youre coming from a
high-level language, there are some aspects of systems programming that you may
not be familiar with. The most important one is how memory works, with a stack
and a heap. If youre familiar with how C-like languages use stack allocation,
this chapter will be a refresher. If youre not, youll learn about this more
general concept, but with a Rust-y focus.
# Memory management
These two terms are about memory management. The stack and the heap are
abstractions that help you determine when to allocate and deallocate memory.
Heres a high-level comparison:
The stack is very fast, and is where memory is allocated in Rust by default.
But the allocation is local to a function call, and is limited in size. The
heap, on the other hand, is slower, and is explicitly allocated by your
program. But its effectively unlimited in size, and is globally accessible.
# The Stack
Lets talk about this Rust program:
```rust
fn main() {
let x = 42;
}
```
This program has one variable binding, `x`. This memory needs to be allocated
from somewhere. Rust stack allocates by default, which means that basic
values go on the stack. What does that mean?
Well, when a function gets called, some memory gets allocated for all of its
local variables and some other information. This is called a stack frame, and
for the purpose of this tutorial, were going to ignore the extra information
and just consider the local variables were allocating. So in this case, when
`main()` is run, well allocate a single 32-bit integer for our stack frame.
This is automatically handled for you, as you can see, we didnt have to write
any special Rust code or anything.
When the function is over, its stack frame gets deallocated. This happens
automatically, we didnt have to do anything special here.
Thats all there is for this simple program. The key thing to understand here
is that stack allocation is very, very fast. Since we know all the local
variables we have ahead of time, we can grab the memory all at once. And since
well throw them all away at the same time as well, we can get rid of it very
fast too.
The downside is that we cant keep values around if we need them for longer
than a single function. We also havent talked about what that name, stack
means. To do that, we need a slightly more complicated example:
```rust
fn foo() {
let y = 5;
let z = 100;
}
fn main() {
let x = 42;
foo();
}
```
This program has three variables total: two in `foo()`, one in `main()`. Just
as before, when `main()` is called, a single integer is allocated for its stack
frame. But before we can show what happens when `foo()` is called, we need to
visualize whats going on with memory. Your operating system presents a view of
memory to your program thats pretty simple: a huge list of addresses, from 0
to a large number, representing how much RAM your computer has. For example, if
you have a gigabyte of RAM, your addresses go from `0` to `1,073,741,824`. That
number comes from 2<sup>30</sup>, the number of bytes in a gigabyte.
This memory is kind of like a giant array: addresses start at zero and go
up to the final number. So heres a diagram of our first stack frame:
| Address | Name | Value |
+---------+------+-------+
| 0 | x | 42 |
Weve got `x` located at address `0`, with the value `42`.
When `foo()` is called, a new stack frame is allocated:
| Address | Name | Value |
+---------+------+-------+
| 2 | z | 100 |
| 1 | y | 5 |
| 0 | x | 42 |
Because `0` was taken by the first frame, `1` and `2` are used for `foo()`s
stack frame. It grows upward, the more functions we call.
Theres some important things we have to take note of here. The numbers 0, 1,
and 2 are all solely for illustrative purposes, and bear no relationship to the
actual numbers the computer will actually use. In particular, the series of
addresses are in reality going to be separated by some number of bytes that
separate each address, and that separation may even exceed the size of the
value being stored.
After `foo()` is over, its frame is deallocated:
| Address | Name | Value |
+---------+------+-------+
| 0 | x | 42 |
And then, after `main()`, even this last value goes away. Easy!
Its called a stack because it works like a stack of dinner plates: the first
plate you put down is the last plate to pick back up. Stacks are sometimes
called last in, first out queues for this reason, as the last value you put
on the stack is the first one you retrieve from it.
Lets try a three-deep example:
```rust
fn bar() {
let i = 6;
}
fn foo() {
let a = 5;
let b = 100;
let c = 1;
bar();
}
fn main() {
let x = 42;
foo();
}
```
Okay, first, we call `main()`:
| Address | Name | Value |
+---------+------+-------+
| 0 | x | 42 |
Next up, `main()` calls `foo()`:
| Address | Name | Value |
+---------+------+-------+
| 3 | c | 1 |
| 2 | b | 100 |
| 1 | a | 5 |
| 0 | x | 42 |
And then `foo()` calls `bar()`:
| Address | Name | Value |
+---------+------+-------+
| 4 | i | 6 |
| 3 | c | 1 |
| 2 | b | 100 |
| 1 | a | 5 |
| 0 | x | 42 |
Whew! Our stack is growing tall.
After `bar()` is over, its frame is deallocated, leaving just `foo()` and
`main()`:
| Address | Name | Value |
+---------+------+-------+
| 3 | c | 1 |
| 2 | b | 100 |
| 1 | a | 5 |
| 0 | x | 42 |
And then `foo()` ends, leaving just `main()`
| Address | Name | Value |
+---------+------+-------+
| 0 | x | 42 |
And then were done. Getting the hang of it? Its like piling up dishes: you
add to the top, you take away from the top.
# The Heap
Now, this works pretty well, but not everything can work like this. Sometimes,
you need to pass some memory between different functions, or keep it alive for
longer than a single functions execution. For this, we can use the heap.
In Rust, you can allocate memory on the heap with the [`Box<T>` type][box].
Heres an example:
```rust
fn main() {
let x = Box::new(5);
let y = 42;
}
```
[box]: ../std/boxed/index.html
Heres what happens in memory when `main()` is called:
| Address | Name | Value |
+---------+------+--------+
| 1 | y | 42 |
| 0 | x | ?????? |
We allocate space for two variables on the stack. `y` is `42`, as it always has
been, but what about `x`? Well, `x` is a `Box<i32>`, and boxes allocate memory
on the heap. The actual value of the box is a structure which has a pointer to
the heap. When we start executing the function, and `Box::new()` is called,
it allocates some memory for the heap, and puts `5` there. The memory now looks
like this:
| Address | Name | Value |
+-----------------+------+----------------+
| 2<sup>30</sup> | | 5 |
| ... | ... | ... |
| 1 | y | 42 |
| 0 | x | 2<sup>30</sup> |
We have 2<sup>30</sup> in our hypothetical computer with 1GB of RAM. And since
our stack grows from zero, the easiest place to allocate memory is from the
other end. So our first value is at the highest place in memory. And the value
of the struct at `x` has a [raw pointer][rawpointer] to the place weve
allocated on the heap, so the value of `x` is 2<sup>30</sup>, the memory
location weve asked for.
[rawpointer]: raw-pointers.html
We havent really talked too much about what it actually means to allocate and
deallocate memory in these contexts. Getting into very deep detail is out of
the scope of this tutorial, but whats important to point out here is that
the heap isnt just a stack that grows from the opposite end. Well have an
example of this later in the book, but because the heap can be allocated and
freed in any order, it can end up with holes. Heres a diagram of the memory
layout of a program which has been running for a while now:
| Address | Name | Value |
+----------------------+------+----------------------+
| 2<sup>30</sup> | | 5 |
| (2<sup>30</sup>) - 1 | | |
| (2<sup>30</sup>) - 2 | | |
| (2<sup>30</sup>) - 3 | | 42 |
| ... | ... | ... |
| 3 | y | (2<sup>30</sup>) - 3 |
| 2 | y | 42 |
| 1 | y | 42 |
| 0 | x | 2<sup>30</sup> |
In this case, weve allocated four things on the heap, but deallocated two of
them. Theres a gap between 2<sup>30</sup> and (2<sup>30</sup>) - 3 which isnt
currently being used. The specific details of how and why this happens depends
on what kind of strategy you use to manage the heap. Different programs can use
different memory allocators, which are libraries that manage this for you.
Rust programs use [jemalloc][jemalloc] for this purpose.
[jemalloc]: http://www.canonware.com/jemalloc/
Anyway, back to our example. Since this memory is on the heap, it can stay
alive longer than the function which allocates the box. In this case, however,
it doesnt.[^moving] When the function is over, we need to free the stack frame
for `main()`. `Box<T>`, though, has a trick up its sleve: [Drop][drop]. The
implementation of `Drop` for `Box` deallocates the memory that was allocated
when it was created. Great! So when `x` goes away, it first frees the memory
allocated on the heap:
| Address | Name | Value |
+---------+------+--------+
| 1 | y | 42 |
| 0 | x | ?????? |
[drop]: drop.html
[moving]: We can make the memory live longer by transferring ownership,
sometimes called moving out of the box. More complex examples will
be covered later.
And then the stack frame goes away, freeing all of our memory.
# Arguments and borrowing
Weve got some basic examples with the stack and the heap going, but what about
function arguments and borrowing? Heres a small Rust program:
```rust
fn foo(i: &i32) {
let z = 42;
}
fn main() {
let x = 5;
let y = &x;
foo(y);
}
```
When we enter `main()`, memory looks like this:
| Address | Name | Value |
+---------+------+-------+
| 1 | y | 0 |
| 0 | x | 5 |
`x` is a plain old `5`, and `y` is a reference to `x`. So its value is the
memory location that `x` lives at, which in this case is `0`.
What about when we call `foo()`, passing `y` as an argument?
| Address | Name | Value |
+---------+------+-------+
| 3 | z | 42 |
| 2 | i | 0 |
| 1 | y | 0 |
| 0 | x | 5 |
Stack frames arent just for local bindings, theyre for arguments too. So in
this case, we need to have both `i`, our argument, and `z`, our local variable
binding. `i` is a copy of the argument, `y`. Since `y`s value is `0`, so is
`i`s.
This is one reason why borrowing a variable doesnt deallocate any memory: the
value of a reference is just a pointer to a memory location. If we got rid of
the underlying memory, things wouldnt work very well.
# A complex example
Okay, lets go through this complex program step-by-step:
```rust
fn foo(x: &i32) {
let y = 10;
let z = &y;
baz(z);
bar(x, z);
}
fn bar(a: &i32, b: &i32) {
let c = 5;
let d = Box::new(5);
let e = &d;
baz(e);
}
fn baz(f: &i32) {
let g = 100;
}
fn main() {
let h = 3;
let i = Box::new(20);
let j = &h;
foo(j);
}
```
First, we call `main()`:
| Address | Name | Value |
+-----------------+------+----------------+
| 2<sup>30</sup> | | 20 |
| ... | ... | ... |
| 2 | j | 0 |
| 1 | i | 2<sup>30</sup> |
| 0 | h | 3 |
We allocate memory for `j`, `i`, and `h`. `i` is on the heap, and so has a
value pointing there.
Next, at the end of `main()`, `foo()` gets called:
| Address | Name | Value |
+-----------------+------+----------------+
| 2<sup>30</sup> | | 20 |
| ... | ... | ... |
| 5 | z | 4 |
| 4 | y | 10 |
| 3 | x | 0 |
| 2 | j | 0 |
| 1 | i | 2<sup>30</sup> |
| 0 | h | 3 |
Space gets allocated for `x`, `y`, and `z`. The argument `x` has the same value
as `j`, since thats what we passed it in. Its a pointer to the `0` address,
since `j` points at `h`.
Next, `foo()` calls `baz()`, passing `z`:
| Address | Name | Value |
+-----------------+------+----------------+
| 2<sup>30</sup> | | 20 |
| ... | ... | ... |
| 7 | g | 100 |
| 6 | f | 4 |
| 5 | z | 4 |
| 4 | y | 10 |
| 3 | x | 0 |
| 2 | j | 0 |
| 1 | i | 2<sup>30</sup> |
| 0 | h | 3 |
Weve allocated memory for `f` and `g`. `baz()` is very short, so when its
over, we get rid of its stack frame:
| Address | Name | Value |
+-----------------+------+----------------+
| 2<sup>30</sup> | | 20 |
| ... | ... | ... |
| 5 | z | 4 |
| 4 | y | 10 |
| 3 | x | 0 |
| 2 | j | 0 |
| 1 | i | 2<sup>30</sup> |
| 0 | h | 3 |
Next, `foo()` calls `bar()` with `x` and `z`:
| Address | Name | Value |
+----------------------+------+----------------------+
| 2<sup>30</sup> | | 20 |
| (2<sup>30</sup>) - 1 | | 5 |
| ... | ... | ... |
| 10 | e | 4 |
| 9 | d | (2<sup>30</sup>) - 1 |
| 8 | c | 5 |
| 7 | b | 4 |
| 6 | a | 0 |
| 5 | z | 4 |
| 4 | y | 10 |
| 3 | x | 0 |
| 2 | j | 0 |
| 1 | i | 2<sup>30</sup> |
| 0 | h | 3 |
We end up allocating another value on the heap, and so we have to subtract one
from 2<sup>30</sup>. Its easier to just write that than `1,073,741,823`. In any
case, we set up the variables as usual.
At the end of `bar()`, it calls `baz()`:
| Address | Name | Value |
+----------------------+------+----------------------+
| 2<sup>30</sup> | | 20 |
| (2<sup>30</sup>) - 1 | | 5 |
| ... | ... | ... |
| 12 | g | 100 |
| 11 | f | 4 |
| 10 | e | 4 |
| 9 | d | (2<sup>30</sup>) - 1 |
| 8 | c | 5 |
| 7 | b | 4 |
| 6 | a | 0 |
| 5 | z | 4 |
| 4 | y | 10 |
| 3 | x | 0 |
| 2 | j | 0 |
| 1 | i | 2<sup>30</sup> |
| 0 | h | 3 |
With this, were at our deepest point! Whew! Congrats for following along this
far.
After `baz()` is over, we get rid of `f` and `g`:
| Address | Name | Value |
+----------------------+------+----------------------+
| 2<sup>30</sup> | | 20 |
| (2<sup>30</sup>) - 1 | | 5 |
| ... | ... | ... |
| 10 | e | 4 |
| 9 | d | (2<sup>30</sup>) - 1 |
| 8 | c | 5 |
| 7 | b | 4 |
| 6 | a | 0 |
| 5 | z | 4 |
| 4 | y | 10 |
| 3 | x | 0 |
| 2 | j | 0 |
| 1 | i | 2<sup>30</sup> |
| 0 | h | 3 |
Next, we return from `bar()`. `d` in this case is a `Box<T>`, so it also frees
what it points to: (2<sup>30</sup>) - 1.
| Address | Name | Value |
+-----------------+------+----------------+
| 2<sup>30</sup> | | 20 |
| ... | ... | ... |
| 5 | z | 4 |
| 4 | y | 10 |
| 3 | x | 0 |
| 2 | j | 0 |
| 1 | i | 2<sup>30</sup> |
| 0 | h | 3 |
And after that, `foo()` returns:
| Address | Name | Value |
+-----------------+------+----------------+
| 2<sup>30</sup> | | 20 |
| ... | ... | ... |
| 2 | j | 0 |
| 1 | i | 2<sup>30</sup> |
| 0 | h | 3 |
And then, finally, `main()`, which cleans the rest up. When `i` is `Drop`ped,
it will clean up the last of the heap too.
# What do other languages do?
Most languages with a garbage collector heap-allocate by default. This means
that every value is boxed. There are a number of reasons why this is done, but
theyre out of scope for this tutorial. There are some possible optimizations
that dont make it true 100% of the time, too. Rather than relying on the stack
and `Drop` to clean up memory, the garbage collector deals with the heap
instead.
# Which to use?
So if the stack is faster and easier to manage, why do we need the heap? A big
reason is that Stack-allocation alone means you only have LIFO semantics for
reclaiming storage. Heap-allocation is strictly more general, allowing storage
to be taken from and returned to the pool in arbitrary order, but at a
complexity cost.
Generally, you should prefer stack allocation, and so, Rust stack-allocates by
default. The LIFO model of the stack is simpler, at a fundamental level. This
has two big impacts: runtime efficiency and semantic impact.
## Runtime Efficiency.
Managing the memory for the stack is trivial: The machine just
increments or decrements a single value, the so-called “stack pointer”.
Managing memory for the heap is non-trivial: heap-allocated memory is freed at
arbitrary points, and each block of heap-allocated memory can be of arbitrary
size, the memory manager must generally work much harder to identify memory for
reuse.
If youd like to dive into this topic in greater detail, [this paper][wilson]
is a great introduction.
[wilson]: http://www.cs.northwestern.edu/~pdinda/icsclass/doc/dsa.pdf
## Semantic impact
Stack-allocation impacts the Rust language itself, and thus the developers
mental model. The LIFO semantics is what drives how the Rust language handles
automatic memory management. Even the deallocation of a uniquely-owned
heap-allocated box can be driven by the stack-based LIFO semantics, as
discussed throughout this chapter. The flexibility (i.e. expressiveness) of non
LIFO-semantics means that in general the compiler cannot automatically infer at
compile-time where memory should be freed; it has to rely on dynamic protocols,
potentially from outside the language itself, to drive deallocation (reference
counting, as used by `Rc<T>` and `Arc<T>`, is one example of this).
When taken to the extreme, the increased expressive power of heap allocation
comes at the cost of either significant runtime support (e.g. in the form of a
garbage collector) or significant programmer effort (in the form of explicit
memory management calls that require verification not provided by the Rust
compiler).

View File

@ -1,15 +1,15 @@
% Trait Objects % Trait Objects
When code involves polymorphism, there needs to be a mechanism to determine When code involves polymorphism, there needs to be a mechanism to determine
which specific version is actually run. This is called 'dispatch.' There are which specific version is actually run. This is called dispatch. There are
two major forms of dispatch: static dispatch and dynamic dispatch. While Rust two major forms of dispatch: static dispatch and dynamic dispatch. While Rust
favors static dispatch, it also supports dynamic dispatch through a mechanism favors static dispatch, it also supports dynamic dispatch through a mechanism
called 'trait objects.' called trait objects.
## Background ## Background
For the rest of this chapter, we'll need a trait and some implementations. For the rest of this chapter, well need a trait and some implementations.
Let's make a simple one, `Foo`. It has one method that is expected to return a Lets make a simple one, `Foo`. It has one method that is expected to return a
`String`. `String`.
```rust ```rust
@ -18,7 +18,7 @@ trait Foo {
} }
``` ```
We'll also implement this trait for `u8` and `String`: Well also implement this trait for `u8` and `String`:
```rust ```rust
# trait Foo { fn method(&self) -> String; } # trait Foo { fn method(&self) -> String; }
@ -53,7 +53,7 @@ fn main() {
} }
``` ```
Rust uses 'monomorphization' to perform static dispatch here. This means that Rust uses monomorphization to perform static dispatch here. This means that
Rust will create a special version of `do_something()` for both `u8` and Rust will create a special version of `do_something()` for both `u8` and
`String`, and then replace the call sites with calls to these specialized `String`, and then replace the call sites with calls to these specialized
functions. In other words, Rust generates something like this: functions. In other words, Rust generates something like this:
@ -82,7 +82,7 @@ fn main() {
This has a great upside: static dispatch allows function calls to be This has a great upside: static dispatch allows function calls to be
inlined because the callee is known at compile time, and inlining is inlined because the callee is known at compile time, and inlining is
the key to good optimization. Static dispatch is fast, but it comes at the key to good optimization. Static dispatch is fast, but it comes at
a tradeoff: 'code bloat', due to many copies of the same function a tradeoff: code bloat, due to many copies of the same function
existing in the binary, one for each type. existing in the binary, one for each type.
Furthermore, compilers arent perfect and may “optimize” code to become slower. Furthermore, compilers arent perfect and may “optimize” code to become slower.
@ -99,7 +99,7 @@ reason.
## Dynamic dispatch ## Dynamic dispatch
Rust provides dynamic dispatch through a feature called 'trait objects.' Trait Rust provides dynamic dispatch through a feature called trait objects. Trait
objects, like `&Foo` or `Box<Foo>`, are normal values that store a value of objects, like `&Foo` or `Box<Foo>`, are normal values that store a value of
*any* type that implements the given trait, where the precise type can only be *any* type that implements the given trait, where the precise type can only be
known at runtime. known at runtime.
@ -109,12 +109,12 @@ implements the trait by *casting* it (e.g. `&x as &Foo`) or *coercing* it
(e.g. using `&x` as an argument to a function that takes `&Foo`). (e.g. using `&x` as an argument to a function that takes `&Foo`).
These trait object coercions and casts also work for pointers like `&mut T` to These trait object coercions and casts also work for pointers like `&mut T` to
`&mut Foo` and `Box<T>` to `Box<Foo>`, but that's all at the moment. Coercions `&mut Foo` and `Box<T>` to `Box<Foo>`, but thats all at the moment. Coercions
and casts are identical. and casts are identical.
This operation can be seen as "erasing" the compiler's knowledge about the This operation can be seen as erasing the compilers knowledge about the
specific type of the pointer, and hence trait objects are sometimes referred to specific type of the pointer, and hence trait objects are sometimes referred to
as "type erasure". as type erasure.
Coming back to the example above, we can use the same trait to perform dynamic Coming back to the example above, we can use the same trait to perform dynamic
dispatch with trait objects by casting: dispatch with trait objects by casting:
@ -155,7 +155,7 @@ A function that takes a trait object is not specialized to each of the types
that implements `Foo`: only one copy is generated, often (but not always) that implements `Foo`: only one copy is generated, often (but not always)
resulting in less code bloat. However, this comes at the cost of requiring resulting in less code bloat. However, this comes at the cost of requiring
slower virtual function calls, and effectively inhibiting any chance of slower virtual function calls, and effectively inhibiting any chance of
inlining and related optimisations from occurring. inlining and related optimizations from occurring.
### Why pointers? ### Why pointers?
@ -167,7 +167,7 @@ on the heap to store it.
For `Foo`, we would need to have a value that could be at least either a For `Foo`, we would need to have a value that could be at least either a
`String` (24 bytes) or a `u8` (1 byte), as well as any other type for which `String` (24 bytes) or a `u8` (1 byte), as well as any other type for which
dependent crates may implement `Foo` (any number of bytes at all). There's no dependent crates may implement `Foo` (any number of bytes at all). Theres no
way to guarantee that this last point can work if the values are stored without way to guarantee that this last point can work if the values are stored without
a pointer, because those other types can be arbitrarily large. a pointer, because those other types can be arbitrarily large.
@ -177,14 +177,14 @@ when we are tossing a trait object around, only the size of the pointer itself.
### Representation ### Representation
The methods of the trait can be called on a trait object via a special record The methods of the trait can be called on a trait object via a special record
of function pointers traditionally called a 'vtable' (created and managed by of function pointers traditionally called a vtable (created and managed by
the compiler). the compiler).
Trait objects are both simple and complicated: their core representation and Trait objects are both simple and complicated: their core representation and
layout is quite straight-forward, but there are some curly error messages and layout is quite straight-forward, but there are some curly error messages and
surprising behaviors to discover. surprising behaviors to discover.
Let's start simple, with the runtime representation of a trait object. The Lets start simple, with the runtime representation of a trait object. The
`std::raw` module contains structs with layouts that are the same as the `std::raw` module contains structs with layouts that are the same as the
complicated built-in types, [including trait objects][stdraw]: complicated built-in types, [including trait objects][stdraw]:
@ -199,12 +199,12 @@ pub struct TraitObject {
[stdraw]: ../std/raw/struct.TraitObject.html [stdraw]: ../std/raw/struct.TraitObject.html
That is, a trait object like `&Foo` consists of a "data" pointer and a "vtable" That is, a trait object like `&Foo` consists of a data pointer and a vtable
pointer. pointer.
The data pointer addresses the data (of some unknown type `T`) that the trait The data pointer addresses the data (of some unknown type `T`) that the trait
object is storing, and the vtable pointer points to the vtable ("virtual method object is storing, and the vtable pointer points to the vtable (virtual method
table") corresponding to the implementation of `Foo` for `T`. table) corresponding to the implementation of `Foo` for `T`.
A vtable is essentially a struct of function pointers, pointing to the concrete A vtable is essentially a struct of function pointers, pointing to the concrete
@ -212,7 +212,7 @@ piece of machine code for each method in the implementation. A method call like
`trait_object.method()` will retrieve the correct pointer out of the vtable and `trait_object.method()` will retrieve the correct pointer out of the vtable and
then do a dynamic call of it. For example: then do a dynamic call of it. For example:
```{rust,ignore} ```rust,ignore
struct FooVtable { struct FooVtable {
destructor: fn(*mut ()), destructor: fn(*mut ()),
size: usize, size: usize,
@ -261,7 +261,7 @@ static Foo_for_String_vtable: FooVtable = FooVtable {
``` ```
The `destructor` field in each vtable points to a function that will clean up The `destructor` field in each vtable points to a function that will clean up
any resources of the vtable's type, for `u8` it is trivial, but for `String` it any resources of the vtables type, for `u8` it is trivial, but for `String` it
will free the memory. This is necessary for owning trait objects like will free the memory. This is necessary for owning trait objects like
`Box<Foo>`, which need to clean-up both the `Box` allocation as well as the `Box<Foo>`, which need to clean-up both the `Box` allocation as well as the
internal type when they go out of scope. The `size` and `align` fields store internal type when they go out of scope. The `size` and `align` fields store
@ -270,11 +270,11 @@ essentially unused at the moment since the information is embedded in the
destructor, but will be used in the future, as trait objects are progressively destructor, but will be used in the future, as trait objects are progressively
made more flexible. made more flexible.
Suppose we've got some values that implement `Foo`, then the explicit form of Suppose weve got some values that implement `Foo`, then the explicit form of
construction and use of `Foo` trait objects might look a bit like (ignoring the construction and use of `Foo` trait objects might look a bit like (ignoring the
type mismatches: they're all just pointers anyway): type mismatches: theyre all just pointers anyway):
```{rust,ignore} ```rust,ignore
let a: String = "foo".to_string(); let a: String = "foo".to_string();
let x: u8 = 1; let x: u8 = 1;

View File

@ -1,10 +1,9 @@
% Traits % Traits
Do you remember the `impl` keyword, used to call a function with method Do you remember the `impl` keyword, used to call a function with [method
syntax? syntax][methodsyntax]?
```{rust} ```rust
# #![feature(core)]
struct Circle { struct Circle {
x: f64, x: f64,
y: f64, y: f64,
@ -18,11 +17,12 @@ impl Circle {
} }
``` ```
[methodsyntax]: method-syntax.html
Traits are similar, except that we define a trait with just the method Traits are similar, except that we define a trait with just the method
signature, then implement the trait for that struct. Like this: signature, then implement the trait for that struct. Like this:
```{rust} ```rust
# #![feature(core)]
struct Circle { struct Circle {
x: f64, x: f64,
y: f64, y: f64,
@ -41,20 +41,13 @@ impl HasArea for Circle {
``` ```
As you can see, the `trait` block looks very similar to the `impl` block, As you can see, the `trait` block looks very similar to the `impl` block,
but we don't define a body, just a type signature. When we `impl` a trait, but we dont define a body, just a type signature. When we `impl` a trait,
we use `impl Trait for Item`, rather than just `impl Item`. we use `impl Trait for Item`, rather than just `impl Item`.
So what's the big deal? Remember the error we were getting with our generic
`inverse` function?
```text
error: binary operation `==` cannot be applied to type `T`
```
We can use traits to constrain our generics. Consider this function, which We can use traits to constrain our generics. Consider this function, which
does not compile, and gives us a similar error: does not compile, and gives us a similar error:
```{rust,ignore} ```rust,ignore
fn print_area<T>(shape: T) { fn print_area<T>(shape: T) {
println!("This shape has an area of {}", shape.area()); println!("This shape has an area of {}", shape.area());
} }
@ -66,11 +59,11 @@ Rust complains:
error: type `T` does not implement any method in scope named `area` error: type `T` does not implement any method in scope named `area`
``` ```
Because `T` can be any type, we can't be sure that it implements the `area` Because `T` can be any type, we cant be sure that it implements the `area`
method. But we can add a *trait constraint* to our generic `T`, ensuring method. But we can add a trait constraint to our generic `T`, ensuring
that it does: that it does:
```{rust} ```rust
# trait HasArea { # trait HasArea {
# fn area(&self) -> f64; # fn area(&self) -> f64;
# } # }
@ -83,10 +76,9 @@ The syntax `<T: HasArea>` means `any type that implements the HasArea trait`.
Because traits define function type signatures, we can be sure that any type Because traits define function type signatures, we can be sure that any type
which implements `HasArea` will have an `.area()` method. which implements `HasArea` will have an `.area()` method.
Here's an extended example of how this works: Heres an extended example of how this works:
```{rust} ```rust
# #![feature(core)]
trait HasArea { trait HasArea {
fn area(&self) -> f64; fn area(&self) -> f64;
} }
@ -144,10 +136,10 @@ This shape has an area of 3.141593
This shape has an area of 1 This shape has an area of 1
``` ```
As you can see, `print_area` is now generic, but also ensures that we As you can see, `print_area` is now generic, but also ensures that we have
have passed in the correct types. If we pass in an incorrect type: passed in the correct types. If we pass in an incorrect type:
```{rust,ignore} ```rust,ignore
print_area(5); print_area(5);
``` ```
@ -157,11 +149,11 @@ We get a compile-time error:
error: failed to find an implementation of trait main::HasArea for int error: failed to find an implementation of trait main::HasArea for int
``` ```
So far, we've only added trait implementations to structs, but you can So far, weve only added trait implementations to structs, but you can
implement a trait for any type. So technically, we _could_ implement implement a trait for any type. So technically, we _could_ implement `HasArea`
`HasArea` for `i32`: for `i32`:
```{rust} ```rust
trait HasArea { trait HasArea {
fn area(&self) -> f64; fn area(&self) -> f64;
} }
@ -181,102 +173,57 @@ It is considered poor style to implement methods on such primitive types, even
though it is possible. though it is possible.
This may seem like the Wild West, but there are two other restrictions around This may seem like the Wild West, but there are two other restrictions around
implementing traits that prevent this from getting out of hand. First, traits implementing traits that prevent this from getting out of hand. The first is
must be `use`d in any scope where you wish to use the trait's method. So for that if the trait isnt defined in your scope, it doesnt apply. Heres an
example, this does not work: example: the standard library provides a [`Write`][write] trait which adds
extra functionality to `File`s, for doing file I/O. By default, a `File`
wont have its methods:
```{rust,ignore} [write]: ../std/io/trait.Write.html
mod shapes {
use std::f64::consts;
trait HasArea { ```rust,ignore
fn area(&self) -> f64; let mut f = std::fs::File::open("foo.txt").ok().expect("Couldnt open foo.txt");
} let result = f.write("whatever".as_bytes());
# result.unwrap(); // ignore the error
struct Circle {
x: f64,
y: f64,
radius: f64,
}
impl HasArea for Circle {
fn area(&self) -> f64 {
consts::PI * (self.radius * self.radius)
}
}
}
fn main() {
let c = shapes::Circle {
x: 0.0f64,
y: 0.0f64,
radius: 1.0f64,
};
println!("{}", c.area());
}
``` ```
Now that we've moved the structs and traits into their own module, we get an Heres the error:
error:
```text ```text
error: type `shapes::Circle` does not implement any method in scope named `area` error: type `std::fs::File` does not implement any method in scope named `write`
let result = f.write(b"whatever");
^~~~~~~~~~~~~~~~~~
``` ```
If we add a `use` line right above `main` and make the right things public, We need to `use` the `Write` trait first:
everything is fine:
```{rust} ```rust,ignore
# #![feature(core)] use std::io::Write;
mod shapes {
use std::f64::consts;
pub trait HasArea { let mut f = std::fs::File::open("foo.txt").ok().expect("Couldnt open foo.txt");
fn area(&self) -> f64; let result = f.write("whatever".as_bytes());
} # result.unwrap(); // ignore the error
pub struct Circle {
pub x: f64,
pub y: f64,
pub radius: f64,
}
impl HasArea for Circle {
fn area(&self) -> f64 {
consts::PI * (self.radius * self.radius)
}
}
}
use shapes::HasArea;
fn main() {
let c = shapes::Circle {
x: 0.0f64,
y: 0.0f64,
radius: 1.0f64,
};
println!("{}", c.area());
}
``` ```
This will compile without error.
This means that even if someone does something bad like add methods to `int`, This means that even if someone does something bad like add methods to `int`,
it won't affect you, unless you `use` that trait. it wont affect you, unless you `use` that trait.
There's one more restriction on implementing traits. Either the trait or the Theres one more restriction on implementing traits. Either the trait or the
type you're writing the `impl` for must be inside your crate. So, we could type youre writing the `impl` for must be defined by you. So, we could
implement the `HasArea` type for `i32`, because `HasArea` is in our crate. But implement the `HasArea` type for `i32`, because `HasArea` is in our code. But
if we tried to implement `Float`, a trait provided by Rust, for `i32`, we could if we tried to implement `Float`, a trait provided by Rust, for `i32`, we could
not, because both the trait and the type aren't in our crate. not, because neither the trait nor the type are in our code.
One last thing about traits: generic functions with a trait bound use One last thing about traits: generic functions with a trait bound use
*monomorphization* (*mono*: one, *morph*: form), so they are statically monomorphization (mono: one, morph: form), so they are statically dispatched.
dispatched. What's that mean? Check out the chapter on [trait Whats that mean? Check out the chapter on [trait objects][to] for more details.
objects](trait-objects.html) for more.
## Multiple trait bounds [to]: trait-objects.html
# Multiple trait bounds
Youve seen that you can bound a generic type parameter with a trait: Youve seen that you can bound a generic type parameter with a trait:
@ -299,10 +246,10 @@ fn foo<T: Clone + Debug>(x: T) {
`T` now needs to be both `Clone` as well as `Debug`. `T` now needs to be both `Clone` as well as `Debug`.
## Where clause # Where clause
Writing functions with only a few generic types and a small number of trait Writing functions with only a few generic types and a small number of trait
bounds isn't too bad, but as the number increases, the syntax gets increasingly bounds isnt too bad, but as the number increases, the syntax gets increasingly
awkward: awkward:
``` ```
@ -318,7 +265,7 @@ fn foo<T: Clone, K: Clone + Debug>(x: T, y: K) {
The name of the function is on the far left, and the parameter list is on the The name of the function is on the far left, and the parameter list is on the
far right. The bounds are getting in the way. far right. The bounds are getting in the way.
Rust has a solution, and it's called a '`where` clause': Rust has a solution, and its called a `where` clause:
``` ```
use std::fmt::Debug; use std::fmt::Debug;
@ -391,7 +338,7 @@ plain type parameter (like `T`).
## Default methods ## Default methods
There's one last feature of traits we should cover: default methods. It's Theres one last feature of traits we should cover: default methods. Its
easiest just to show an example: easiest just to show an example:
```rust ```rust
@ -402,8 +349,8 @@ trait Foo {
} }
``` ```
Implementors of the `Foo` trait need to implement `bar()`, but they don't Implementors of the `Foo` trait need to implement `bar()`, but they dont
need to implement `baz()`. They'll get this default behavior. They can need to implement `baz()`. Theyll get this default behavior. They can
override the default if they so choose: override the default if they so choose:
```rust ```rust
@ -431,3 +378,43 @@ default.baz(); // prints "We called baz."
let over = OverrideDefault; let over = OverrideDefault;
over.baz(); // prints "Override baz!" over.baz(); // prints "Override baz!"
``` ```
# Inheritance
Sometimes, implementing a trait requires implementing another trait:
```rust
trait Foo {
fn foo(&self);
}
trait FooBar : Foo {
fn foobar(&self);
}
```
Implementors of `FooBar` must also implement `Foo`, like this:
```rust
# trait Foo {
# fn foo(&self);
# }
# trait FooBar : Foo {
# fn foobar(&self);
# }
struct Baz;
impl Foo for Baz {
fn foo(&self) { println!("foo"); }
}
impl FooBar for Baz {
fn foobar(&self) { println!("foobar"); }
}
```
If we forget to implement `Foo`, Rust will tell us:
```text
error: the trait `main::Foo` is not implemented for the type `main::Baz` [E0277]
```

View File

@ -1,3 +1,76 @@
% `type` Aliases % `type` Aliases
Coming soon The `type` keyword lets you declare an alias of another type:
```rust
type Name = String;
```
You can then use this type as if it were a real type:
```rust
type Name = String;
let x: Name = "Hello".to_string();
```
Note, however, that this is an _alias_, not a new type entirely. In other
words, because Rust is strongly typed, youd expect a comparison between two
different types to fail:
```rust,ignore
let x: i32 = 5;
let y: i64 = 5;
if x == y {
// ...
}
```
this gives
```text
error: mismatched types:
expected `i32`,
found `i64`
(expected i32,
found i64) [E0308]
if x == y {
^
```
But, if we had an alias:
```rust
type Num = i32;
let x: i32 = 5;
let y: Num = 5;
if x == y {
// ...
}
```
This compiles without error. Values of a `Num` type are the same as a value of
type `i32`, in every way.
You can also use type aliases with generics:
```rust
use std::result;
enum ConcreteError {
Foo,
Bar,
}
type Result<T> = result::Result<T, ConcreteError>;
```
This creates a specialized version of the `Result` type, which always has a
`ConcreteError` for the `E` part of `Result<T, E>`. This is commonly used
in the standard library to create custom errors for each subsection. For
example, [io::Result][ioresult].
[ioresult]: ../std/io/type.Result.html

View File

@ -1,3 +1,127 @@
% Universal Function Call Syntax % Universal Function Call Syntax
Coming soon Sometimes, functions can have the same names. Consider this code:
```rust
trait Foo {
fn f(&self);
}
trait Bar {
fn f(&self);
}
struct Baz;
impl Foo for Baz {
fn f(&self) { println!("Bazs impl of Foo"); }
}
impl Bar for Baz {
fn f(&self) { println!("Bazs impl of Bar"); }
}
let b = Baz;
```
If we were to try to call `b.f()`, wed get an error:
```text
error: multiple applicable methods in scope [E0034]
b.f();
^~~
note: candidate #1 is defined in an impl of the trait `main::Foo` for the type
`main::Baz`
fn f(&self) { println!("Bazs impl of Foo"); }
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
note: candidate #2 is defined in an impl of the trait `main::Bar` for the type
`main::Baz`
fn f(&self) { println!("Bazs impl of Bar"); }
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
```
We need a way to disambiguate which method we need. This feature is called
universal function call syntax, and it looks like this:
```rust
# trait Foo {
# fn f(&self);
# }
# trait Bar {
# fn f(&self);
# }
# struct Baz;
# impl Foo for Baz {
# fn f(&self) { println!("Bazs impl of Foo"); }
# }
# impl Bar for Baz {
# fn f(&self) { println!("Bazs impl of Bar"); }
# }
# let b = Baz;
Foo::f(&b);
Bar::f(&b);
```
Lets break it down.
```rust,ignore
Foo::
Bar::
```
These halves of the invocation are the types of the two traits: `Foo` and
`Bar`. This is what ends up actually doing the disambiguation between the two:
Rust calls the one from the trait name you use.
```rust,ignore
f(&b)
```
When we call a method like `b.f()` using [method syntax][methodsyntax], Rust
will automatically borrow `b` if `f()` takes `&self`. In this case, Rust will
not, and so we need to pass an explicit `&b`.
[methodsyntax]: method-syntax.html
# Angle-bracket Form
The form of UFCS we just talked about:
```rust,ignore
Trait::method(args);
```
Is a short-hand. Theres an expanded form of this thats needed in some
situations:
```rust,ignore
<Type as Trait>::method(args);
```
The `<>::` syntax is a means of providing a type hint. The type goes inside
the `<>`s. In this case, the type is `Type as Trait`, indicating that we want
`Trait`s version of `method` to be called here. The `as Trait` part is
optional if its not ambiguous. Same with the angle brackets, hence the
shorter form.
Heres an example of using the longer form.
```rust
trait Foo {
fn clone(&self);
}
#[derive(Clone)]
struct Bar;
impl Foo for Bar {
fn clone(&self) {
println!("Making a clone of Bar");
<Bar as Clone>::clone(self);
}
}
```
This will call the `Clone` traits `clone()` method, rather than `Foo`s.

128
src/doc/trpl/unsafe.md Normal file
View File

@ -0,0 +1,128 @@
% Unsafe
Rusts main draw is its powerful static guarantees about behavior. But safety
checks are conservative by nature: there are some programs that are actually
safe, but the compiler is not able to verify this is true. To write these kinds
of programs, we need to tell the compiler to relax its restrictions a bit. For
this, Rust has a keyword, `unsafe`. Code using `unsafe` has less restrictions
than normal code does.
Lets go over the syntax, and then well talk semantics. `unsafe` is used in
two contexts. The first one is to mark a function as unsafe:
```rust
unsafe fn danger_will_robinson() {
// scary stuff
}
```
All functions called from [FFI][ffi] must be marked as `unsafe`, for example.
The second use of `unsafe` is an unsafe block:
[ffi]: ffi.html
```rust
unsafe {
// scary stuff
}
```
Its important to be able to explicitly delineate code that may have bugs that
cause big problems. If a Rust program segfaults, you can be sure its somewhere
in the sections marked `unsafe`.
# What does safe mean?
Safe, in the context of Rust, means “doesnt do anything unsafe.” Easy!
Okay, lets try again: what is not safe to do? Heres a list:
* Data races
* Dereferencing a null/dangling raw pointer
* Reads of [undef][undef] (uninitialized) memory
* Breaking the [pointer aliasing rules][aliasing] with raw pointers.
* `&mut T` and `&T` follow LLVMs scoped [noalias][noalias] model, except if
the `&T` contains an `UnsafeCell<U>`. Unsafe code must not violate these
aliasing guarantees.
* Mutating an immutable value/reference without `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:
* Null/dangling references or boxes
* A value other than `false` (0) or `true` (1) in a `bool`
* A discriminant in an `enum` not included in its 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.
[noalias]: http://llvm.org/docs/LangRef.html#noalias
[undef]: http://llvm.org/docs/LangRef.html#undefined-values
[aliasing]: http://llvm.org/docs/LangRef.html#pointer-aliasing-rules
Whew! Thats a bunch of stuff. Its also important to notice all kinds of
behaviors that are certainly bad, but are expressly _not_ unsafe:
* Deadlocks
* Reading data from private fields
* Leaks due to reference count cycles
* Exiting without calling destructors
* Sending signals
* Accessing/modifying the file system
* Integer overflow
Rust cannot prevent all kinds of software problems. Buggy code can and will be
written in Rust. These things arent great, but they dont qualify as `unsafe`
specifically.
# Unsafe Superpowers
In both unsafe functions and unsafe blocks, Rust will let you do three things
that you normally can not do. Just three. Here they are:
1. Access or update a [static mutable variable][static].
2. Dereference a raw pointer.
3. Call unsafe functions. This is the most powerful ability.
Thats it. Its important that `unsafe` does not, for example, turn off the
borrow checker. Adding `unsafe` to some random Rust code doesnt change its
semantics, it wont just start accepting anything.
But it will let you write things that _do_ break some of the rules. Lets go
over these three abilities in order.
## Access or update a `static mut`
Rust has a feature called `static mut` which allows for mutable global state.
Doing so can cause a data race, and as such is inherently not safe. For more
details, see the [static][static] section of the book.
[static]: const-and-static.html#static
## Dereference a raw pointer
Raw pointers let you do arbitrary pointer arithmetic, and can cause a number of
different memory safety and security issues. In some senses, the ability to
dereference an arbitrary pointer is one of the most dangerous things you can
do. For more on raw pointers, see [their section of the book][rawpointers].
[rawpointers]: raw-pointers.html
## Call unsafe functions
This last ability works with both aspects of `unsafe`: you can only call
functions marked `unsafe` from inside an unsafe block.
This ability is powerful and varied. Rust exposes some [compiler
intrinsics][intrinsics] as unsafe functions, and some unsafe functions bypass
safety checks, trading safety for speed.
Ill repeat again: even though you _can_ do arbitrary things in unsafe blocks
and functions doesnt mean you should. The compiler will act as though youre
upholding its invariants, so be careful!
[intrinsics]: intrinsics.html

View File

@ -1,3 +1,60 @@
% Unsized Types % Unsized Types
Coming Soon! Most types have a particular size, in bytes, that is knowable at compile time.
For example, an `i32` is thirty-two bits big, or four bytes. However, there are
some types which are useful to express, but do not have a defined size. These are
called unsized or dynamically sized types. One example is `[T]`. This type
represents a certain number of `T` in sequence. But we dont know how many
there are, so the size is not known.
Rust understands a few of these types, but they have some restrictions. There
are three:
1. We can only manipulate an instance of an unsized type via a pointer. An
`&[T]` works just fine, but a `[T]` does not.
2. Variables and arguments cannot have dynamically sized types.
3. Only the last field in a `struct` may have a dynamically sized type; the
other fields must not. Enum variants must not have dynamically sized types as
data.
So why bother? Well, because `[T]` can only be used behind a pointer, if we
didnt have language support for unsized types, it would be impossible to write
this:
```rust,ignore
impl Foo for str {
```
or
```rust,ignore
impl<T> Foo for [T] {
```
Instead, you would have to write:
```rust,ignore
impl Foo for &str {
```
Meaning, this implementation would only work for [references][ref], and not
other types of pointers. With the `impl for str`, all pointers, including (at
some point, there are some bugs to fix first) user-defined custom smart
pointers, can use this `impl`.
[ref]: references-and-borrowing.html
# ?Sized
If you want to write a function that accepts a dynamically sized type, you
can use the special bound, `?Sized`:
```rust
struct Foo<T: ?Sized> {
f: T,
}
```
This `?`, read as “T may be `Sized`”, means that this bound is special: it
lets us match more kinds, not less. Its almost like every `T` implicitly has
`T: Sized`, and the `?` undoes this default.

View File

@ -1,6 +1,6 @@
% Variable Bindings % Variable Bindings
Vitually every non-Hello World Rust program uses *variable bindings*. They Virtually every non-'Hello World Rust program uses *variable bindings*. They
look like this: look like this:
```rust ```rust

View File

@ -1,32 +1,60 @@
% Vectors % Vectors
A *vector* is a dynamic or "growable" array, implemented as the standard A vector is a dynamic or growable array, implemented as the standard
library type [`Vec<T>`](../std/vec/) (Where `<T>` is a [Generic](./generics.md) statement). Vectors always allocate their data on the heap. Vectors are to slices library type [`Vec<T>`][vec]. The `T` means that we can have vectors
what `String` is to `&str`. You can create them with the `vec!` macro: of any type (see the chapter on [generics][generic] for more).
Vectors always allocate their data on the heap.
You can create them with the `vec!` macro:
```{rust} ```rust
let v = vec![1, 2, 3]; // v: Vec<i32> let v = vec![1, 2, 3, 4, 5]; // v: Vec<i32>
``` ```
(Notice that unlike the `println!` macro we've used in the past, we use square (Notice that unlike the `println!` macro weve used in the past, we use square
brackets `[]` with `vec!`. Rust allows you to use either in either situation, brackets `[]` with `vec!` macro. Rust allows you to use either in either situation,
this is just convention.) this is just convention.)
There's an alternate form of `vec!` for repeating an initial value: Theres an alternate form of `vec!` for repeating an initial value:
``` ```
let v = vec![0; 10]; // ten zeroes let v = vec![0; 10]; // ten zeroes
``` ```
You can get the length of, iterate over, and subscript vectors just like ## Accessing elements
arrays. In addition, (mutable) vectors can grow automatically:
```{rust} To get the value at a particular index in the vector, we use `[]`s:
let mut nums = vec![1, 2, 3]; // mut nums: Vec<i32>
nums.push(4); ```rust
let v = vec![1, 2, 3, 4, 5];
println!("The length of nums is now {}", nums.len()); // Prints 4 println!("The third element of v is {}", v[2]);
``` ```
Vectors have many more useful methods. The indices count from `0`, so the third element is `v[2]`.
## Iterating
Once you have a vector, you can iterate through its elements with `for`. There
are three versions:
```rust
let mut v = vec![1, 2, 3, 4, 5];
for i in &v {
println!("A reference to {}", i);
}
for i in &mut v {
println!("A mutable reference to {}", i);
}
for i in v {
println!("Take ownership of the vector and its element {}", i);
}
```
Vectors have many more useful methods, which you can read about in [their
API documentation][vec].
[vec]: ../std/vec/index.html
[generic]: generics.html

View File

@ -1,4 +1,4 @@
% while loops % while Loops
Rust also has a `while` loop. It looks like this: Rust also has a `while` loop. It looks like this:

Binary file not shown.

View File

@ -1 +1 @@
0.12.0-8312-g5241bf9c34d156ea6064367a33cbd7222eeb5789 0.12.0-8398-ga59de37e99060162a2674e3ff45409ac73595c0e

View File

@ -31,7 +31,7 @@
//! //!
//! # Examples //! # Examples
//! //!
//! Sharing some immutable data between tasks: //! Sharing some immutable data between threads:
//! //!
//! ```no_run //! ```no_run
//! use std::sync::Arc; //! use std::sync::Arc;
@ -48,7 +48,7 @@
//! } //! }
//! ``` //! ```
//! //!
//! Sharing mutable data safely between tasks with a `Mutex`: //! Sharing mutable data safely between threads with a `Mutex`:
//! //!
//! ```no_run //! ```no_run
//! use std::sync::{Arc, Mutex}; //! use std::sync::{Arc, Mutex};
@ -89,9 +89,9 @@ use heap::deallocate;
/// ///
/// # Examples /// # Examples
/// ///
/// In this example, a large vector of floats is shared between several tasks. /// In this example, a large vector of floats is shared between several threads.
/// With simple pipes, without `Arc`, a copy would have to be made for each /// With simple pipes, without `Arc`, a copy would have to be made for each
/// task. /// thread.
/// ///
/// When you clone an `Arc<T>`, it will create another pointer to the data and /// When you clone an `Arc<T>`, it will create another pointer to the data and
/// increase the reference counter. /// increase the reference counter.

View File

@ -240,6 +240,7 @@ impl<T: ?Sized + Hash> Hash for Box<T> {
impl Box<Any> { impl Box<Any> {
#[inline] #[inline]
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
/// Attempt to downcast the box to a concrete type.
pub fn downcast<T: Any>(self) -> Result<Box<T>, Box<Any>> { pub fn downcast<T: Any>(self) -> Result<Box<T>, Box<Any>> {
if self.is::<T>() { if self.is::<T>() {
unsafe { unsafe {
@ -257,11 +258,15 @@ impl Box<Any> {
} }
} }
impl Box<Any+Send> { impl Box<Any + Send> {
#[inline] #[inline]
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
pub fn downcast<T: Any>(self) -> Result<Box<T>, Box<Any>> { /// Attempt to downcast the box to a concrete type.
<Box<Any>>::downcast(self) pub fn downcast<T: Any>(self) -> Result<Box<T>, Box<Any + Send>> {
<Box<Any>>::downcast(self).map_err(|s| unsafe {
// reapply the Send marker
mem::transmute::<Box<Any>, Box<Any + Send>>(s)
})
} }
} }

View File

@ -26,14 +26,14 @@
//! There can only be one owner of a `Box`, and the owner can decide to mutate //! There can only be one owner of a `Box`, and the owner can decide to mutate
//! the contents, which live on the heap. //! the contents, which live on the heap.
//! //!
//! This type can be sent among tasks efficiently as the size of a `Box` value //! This type can be sent among threads efficiently as the size of a `Box` value
//! is the same as that of a pointer. Tree-like data structures are often built //! is the same as that of a pointer. Tree-like data structures are often built
//! with boxes because each node often has only one owner, the parent. //! with boxes because each node often has only one owner, the parent.
//! //!
//! ## Reference counted pointers //! ## Reference counted pointers
//! //!
//! The [`Rc`](rc/index.html) type is a non-threadsafe reference-counted pointer //! The [`Rc`](rc/index.html) type is a non-threadsafe reference-counted pointer
//! type intended for sharing memory within a task. An `Rc` pointer wraps a //! type intended for sharing memory within a thread. An `Rc` pointer wraps a
//! type, `T`, and only allows access to `&T`, a shared reference. //! type, `T`, and only allows access to `&T`, a shared reference.
//! //!
//! This type is useful when inherited mutability (such as using `Box`) is too //! This type is useful when inherited mutability (such as using `Box`) is too

View File

@ -1434,7 +1434,7 @@ impl BitSet {
bit_vec.nbits = trunc_len * u32::BITS; bit_vec.nbits = trunc_len * u32::BITS;
} }
/// Iterator over each u32 stored in the `BitSet`. /// Iterator over each usize stored in the `BitSet`.
/// ///
/// # Examples /// # Examples
/// ///
@ -1455,7 +1455,7 @@ impl BitSet {
SetIter {set: self, next_idx: 0} SetIter {set: self, next_idx: 0}
} }
/// Iterator over each u32 stored in `self` union `other`. /// Iterator over each usize stored in `self` union `other`.
/// See [union_with](#method.union_with) for an efficient in-place version. /// See [union_with](#method.union_with) for an efficient in-place version.
/// ///
/// # Examples /// # Examples
@ -1555,7 +1555,7 @@ impl BitSet {
}) })
} }
/// Iterator over each u32 stored in the symmetric difference of `self` and `other`. /// Iterator over each usize stored in the symmetric difference of `self` and `other`.
/// See [symmetric_difference_with](#method.symmetric_difference_with) for /// See [symmetric_difference_with](#method.symmetric_difference_with) for
/// an efficient in-place version. /// an efficient in-place version.
/// ///

View File

@ -80,7 +80,6 @@
#![stable(feature = "rust1", since = "1.0.0")] #![stable(feature = "rust1", since = "1.0.0")]
use alloc::boxed::Box; use alloc::boxed::Box;
use core::convert::AsRef;
use core::clone::Clone; use core::clone::Clone;
use core::cmp::Ordering::{self, Greater, Less}; use core::cmp::Ordering::{self, Greater, Less};
use core::cmp::{self, Ord, PartialEq}; use core::cmp::{self, Ord, PartialEq};
@ -1028,23 +1027,23 @@ pub trait SliceConcatExt<T: ?Sized, U> {
fn connect(&self, sep: &T) -> U; fn connect(&self, sep: &T) -> U;
} }
impl<T: Clone, V: AsRef<[T]>> SliceConcatExt<T, Vec<T>> for [V] { impl<T: Clone, V: Borrow<[T]>> SliceConcatExt<T, Vec<T>> for [V] {
fn concat(&self) -> Vec<T> { fn concat(&self) -> Vec<T> {
let size = self.iter().fold(0, |acc, v| acc + v.as_ref().len()); let size = self.iter().fold(0, |acc, v| acc + v.borrow().len());
let mut result = Vec::with_capacity(size); let mut result = Vec::with_capacity(size);
for v in self { for v in self {
result.push_all(v.as_ref()) result.push_all(v.borrow())
} }
result result
} }
fn connect(&self, sep: &T) -> Vec<T> { fn connect(&self, sep: &T) -> Vec<T> {
let size = self.iter().fold(0, |acc, v| acc + v.as_ref().len()); let size = self.iter().fold(0, |acc, v| acc + v.borrow().len());
let mut result = Vec::with_capacity(size + self.len()); let mut result = Vec::with_capacity(size + self.len());
let mut first = true; let mut first = true;
for v in self { for v in self {
if first { first = false } else { result.push(sep.clone()) } if first { first = false } else { result.push(sep.clone()) }
result.push_all(v.as_ref()) result.push_all(v.borrow())
} }
result result
} }

View File

@ -61,7 +61,6 @@ use core::str::pattern::Pattern;
use core::str::pattern::{Searcher, ReverseSearcher, DoubleEndedSearcher}; use core::str::pattern::{Searcher, ReverseSearcher, DoubleEndedSearcher};
use unicode::str::{UnicodeStr, Utf16Encoder}; use unicode::str::{UnicodeStr, Utf16Encoder};
use core::convert::AsRef;
use vec_deque::VecDeque; use vec_deque::VecDeque;
use borrow::{Borrow, ToOwned}; use borrow::{Borrow, ToOwned};
use string::String; use string::String;
@ -85,18 +84,18 @@ pub use core::str::pattern;
Section: Creating a string Section: Creating a string
*/ */
impl<S: AsRef<str>> SliceConcatExt<str, String> for [S] { impl<S: Borrow<str>> SliceConcatExt<str, String> for [S] {
fn concat(&self) -> String { fn concat(&self) -> String {
if self.is_empty() { if self.is_empty() {
return String::new(); return String::new();
} }
// `len` calculation may overflow but push_str will check boundaries // `len` calculation may overflow but push_str will check boundaries
let len = self.iter().map(|s| s.as_ref().len()).sum(); let len = self.iter().map(|s| s.borrow().len()).sum();
let mut result = String::with_capacity(len); let mut result = String::with_capacity(len);
for s in self { for s in self {
result.push_str(s.as_ref()) result.push_str(s.borrow())
} }
result result
@ -115,7 +114,7 @@ impl<S: AsRef<str>> SliceConcatExt<str, String> for [S] {
// this is wrong without the guarantee that `self` is non-empty // this is wrong without the guarantee that `self` is non-empty
// `len` calculation may overflow but push_str but will check boundaries // `len` calculation may overflow but push_str but will check boundaries
let len = sep.len() * (self.len() - 1) let len = sep.len() * (self.len() - 1)
+ self.iter().map(|s| s.as_ref().len()).sum::<usize>(); + self.iter().map(|s| s.borrow().len()).sum::<usize>();
let mut result = String::with_capacity(len); let mut result = String::with_capacity(len);
let mut first = true; let mut first = true;
@ -125,7 +124,7 @@ impl<S: AsRef<str>> SliceConcatExt<str, String> for [S] {
} else { } else {
result.push_str(sep); result.push_str(sep);
} }
result.push_str(s.as_ref()); result.push_str(s.borrow());
} }
result result
} }

View File

@ -742,8 +742,7 @@ impl<'a> FromIterator<&'a str> for String {
} }
} }
#[unstable(feature = "collections", #[stable(feature = "rust1", since = "1.0.0")]
reason = "waiting on Extend stabilization")]
impl Extend<char> for String { impl Extend<char> for String {
fn extend<I: IntoIterator<Item=char>>(&mut self, iterable: I) { fn extend<I: IntoIterator<Item=char>>(&mut self, iterable: I) {
let iterator = iterable.into_iter(); let iterator = iterable.into_iter();
@ -755,8 +754,7 @@ impl Extend<char> for String {
} }
} }
#[unstable(feature = "collections", #[stable(feature = "rust1", since = "1.0.0")]
reason = "waiting on Extend stabilization")]
impl<'a> Extend<&'a str> for String { impl<'a> Extend<&'a str> for String {
fn extend<I: IntoIterator<Item=&'a str>>(&mut self, iterable: I) { fn extend<I: IntoIterator<Item=&'a str>>(&mut self, iterable: I) {
let iterator = iterable.into_iter(); let iterator = iterable.into_iter();
@ -871,8 +869,7 @@ impl hash::Hash for String {
} }
} }
#[unstable(feature = "collections", #[stable(feature = "rust1", since = "1.0.0")]
reason = "recent addition, needs more experience")]
impl<'a> Add<&'a str> for String { impl<'a> Add<&'a str> for String {
type Output = String; type Output = String;
@ -953,23 +950,30 @@ impl<'a> Deref for DerefString<'a> {
/// # #![feature(collections)] /// # #![feature(collections)]
/// use std::string::as_string; /// use std::string::as_string;
/// ///
/// fn string_consumer(s: String) { /// // Let's pretend we have a function that requires `&String`
/// assert_eq!(s, "foo".to_string()); /// fn string_consumer(s: &String) {
/// assert_eq!(s, "foo");
/// } /// }
/// ///
/// let string = as_string("foo").clone(); /// // Provide a `&String` from a `&str` without allocating
/// string_consumer(string); /// string_consumer(&as_string("foo"));
/// ``` /// ```
#[unstable(feature = "collections")] #[unstable(feature = "collections")]
pub fn as_string<'a>(x: &'a str) -> DerefString<'a> { pub fn as_string<'a>(x: &'a str) -> DerefString<'a> {
DerefString { x: as_vec(x.as_bytes()) } DerefString { x: as_vec(x.as_bytes()) }
} }
#[unstable(feature = "collections", reason = "associated error type may change")] /// Error returned from `String::from_str`
#[unstable(feature = "str_parse_error", reason = "may want to be replaced with \
Void if it ever exists")]
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub struct ParseError(());
#[stable(feature = "rust1", since = "1.0.0")]
impl FromStr for String { impl FromStr for String {
type Err = (); type Err = ParseError;
#[inline] #[inline]
fn from_str(s: &str) -> Result<String, ()> { fn from_str(s: &str) -> Result<String, ParseError> {
Ok(String::from_str(s)) Ok(String::from_str(s))
} }
} }
@ -1001,6 +1005,14 @@ impl AsRef<str> for String {
} }
} }
#[stable(feature = "rust1", since = "1.0.0")]
impl AsRef<[u8]> for String {
#[inline]
fn as_ref(&self) -> &[u8] {
self.as_bytes()
}
}
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
impl<'a> From<&'a str> for String { impl<'a> From<&'a str> for String {
#[inline] #[inline]

View File

@ -59,7 +59,7 @@ use core::intrinsics::assume;
use core::iter::{repeat, FromIterator}; use core::iter::{repeat, FromIterator};
use core::marker::PhantomData; use core::marker::PhantomData;
use core::mem; use core::mem;
use core::ops::{Index, IndexMut, Deref, Add}; use core::ops::{Index, IndexMut, Deref};
use core::ops; use core::ops;
use core::ptr; use core::ptr;
use core::ptr::Unique; use core::ptr::Unique;
@ -116,11 +116,7 @@ static MAX_MEMORY_SIZE: usize = isize::MAX as usize;
/// stack.push(2); /// stack.push(2);
/// stack.push(3); /// stack.push(3);
/// ///
/// loop { /// while let Some(top) = stack.pop() {
/// let top = match stack.pop() {
/// None => break, // empty
/// Some(x) => x,
/// };
/// // Prints 3, 2, 1 /// // Prints 3, 2, 1
/// println!("{}", top); /// println!("{}", top);
/// } /// }
@ -540,7 +536,7 @@ impl<T> Vec<T> {
/// ///
/// # Panics /// # Panics
/// ///
/// Panics if `i` is out of bounds. /// Panics if `index` is out of bounds.
/// ///
/// # Examples /// # Examples
/// ///
@ -641,7 +637,7 @@ impl<T> Vec<T> {
// zero-size types consume no memory, so we can't rely on the // zero-size types consume no memory, so we can't rely on the
// address space running out // address space running out
self.len = self.len.checked_add(1).expect("length overflow"); self.len = self.len.checked_add(1).expect("length overflow");
unsafe { mem::forget(value); } mem::forget(value);
return return
} }
@ -963,7 +959,7 @@ impl<T> Vec<T> {
num_u: 0, num_u: 0,
marker: PhantomData, marker: PhantomData,
}; };
unsafe { mem::forget(vec); } mem::forget(vec);
while pv.num_t != 0 { while pv.num_t != 0 {
unsafe { unsafe {
@ -1276,7 +1272,7 @@ pub fn from_elem<T: Clone>(elem: T, n: usize) -> Vec<T> {
// Common trait implementations for Vec // Common trait implementations for Vec
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
#[unstable(feature = "collections")] #[stable(feature = "rust1", since = "1.0.0")]
impl<T:Clone> Clone for Vec<T> { impl<T:Clone> Clone for Vec<T> {
#[cfg(not(test))] #[cfg(not(test))]
fn clone(&self) -> Vec<T> { <[T]>::to_vec(&**self) } fn clone(&self) -> Vec<T> { <[T]>::to_vec(&**self) }
@ -1531,7 +1527,7 @@ impl<'a, T> IntoIterator for &'a mut Vec<T> {
} }
} }
#[unstable(feature = "collections", reason = "waiting on Extend stability")] #[stable(feature = "rust1", since = "1.0.0")]
impl<T> Extend<T> for Vec<T> { impl<T> Extend<T> for Vec<T> {
#[inline] #[inline]
fn extend<I: IntoIterator<Item=T>>(&mut self, iterable: I) { fn extend<I: IntoIterator<Item=T>>(&mut self, iterable: I) {
@ -1591,18 +1587,6 @@ impl<T: Ord> Ord for Vec<T> {
} }
} }
#[unstable(feature = "collections",
reason = "recent addition, needs more experience")]
impl<'a, T: Clone> Add<&'a [T]> for Vec<T> {
type Output = Vec<T>;
#[inline]
fn add(mut self, rhs: &[T]) -> Vec<T> {
self.push_all(rhs);
self
}
}
#[unsafe_destructor] #[unsafe_destructor]
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
impl<T> Drop for Vec<T> { impl<T> Drop for Vec<T> {
@ -1672,7 +1656,7 @@ impl<'a> From<&'a str> for Vec<u8> {
// Clone-on-write // Clone-on-write
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
#[unstable(feature = "collections")] #[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T> FromIterator<T> for Cow<'a, [T]> where T: Clone { impl<'a, T> FromIterator<T> for Cow<'a, [T]> where T: Clone {
fn from_iter<I: IntoIterator<Item=T>>(it: I) -> Cow<'a, [T]> { fn from_iter<I: IntoIterator<Item=T>>(it: I) -> Cow<'a, [T]> {
Cow::Owned(FromIterator::from_iter(it)) Cow::Owned(FromIterator::from_iter(it))
@ -1919,6 +1903,22 @@ impl<'a, T> Drop for DerefVec<'a, T> {
} }
/// Converts a slice to a wrapper type providing a `&Vec<T>` reference. /// Converts a slice to a wrapper type providing a `&Vec<T>` reference.
///
/// # Examples
///
/// ```
/// # #![feature(collections)]
/// use std::vec::as_vec;
///
/// // Let's pretend we have a function that requires `&Vec<i32>`
/// fn vec_consumer(s: &Vec<i32>) {
/// assert_eq!(s, &[1, 2, 3]);
/// }
///
/// // Provide a `&Vec<i32>` from a `&[i32]` without allocating
/// let values = [1, 2, 3];
/// vec_consumer(&as_vec(&values));
/// ```
#[unstable(feature = "collections")] #[unstable(feature = "collections")]
pub fn as_vec<'a, T>(x: &'a [T]) -> DerefVec<'a, T> { pub fn as_vec<'a, T>(x: &'a [T]) -> DerefVec<'a, T> {
unsafe { unsafe {

View File

@ -97,9 +97,7 @@ pub trait Any: Reflect + 'static {
fn get_type_id(&self) -> TypeId; fn get_type_id(&self) -> TypeId;
} }
impl<T> Any for T impl<T: Reflect + 'static> Any for T {
where T: Reflect + 'static
{
fn get_type_id(&self) -> TypeId { TypeId::of::<T>() } fn get_type_id(&self) -> TypeId { TypeId::of::<T>() }
} }
@ -222,7 +220,7 @@ impl TypeId {
/// Returns the `TypeId` of the type this generic function has been /// Returns the `TypeId` of the type this generic function has been
/// instantiated with /// instantiated with
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
pub fn of<T: ?Sized + Any>() -> TypeId { pub fn of<T: ?Sized + Reflect + 'static>() -> TypeId {
TypeId { TypeId {
t: unsafe { intrinsics::type_id::<T>() }, t: unsafe { intrinsics::type_id::<T>() },
} }

View File

@ -52,20 +52,20 @@
//! spinlock_clone.store(0, Ordering::SeqCst); //! spinlock_clone.store(0, Ordering::SeqCst);
//! }); //! });
//! //!
//! // Wait for the other task to release the lock //! // Wait for the other thread to release the lock
//! while spinlock.load(Ordering::SeqCst) != 0 {} //! while spinlock.load(Ordering::SeqCst) != 0 {}
//! } //! }
//! ``` //! ```
//! //!
//! Keep a global count of live tasks: //! Keep a global count of live threads:
//! //!
//! ``` //! ```
//! use std::sync::atomic::{AtomicUsize, Ordering, ATOMIC_USIZE_INIT}; //! use std::sync::atomic::{AtomicUsize, Ordering, ATOMIC_USIZE_INIT};
//! //!
//! static GLOBAL_TASK_COUNT: AtomicUsize = ATOMIC_USIZE_INIT; //! static GLOBAL_THREAD_COUNT: AtomicUsize = ATOMIC_USIZE_INIT;
//! //!
//! let old_task_count = GLOBAL_TASK_COUNT.fetch_add(1, Ordering::SeqCst); //! let old_thread_count = GLOBAL_THREAD_COUNT.fetch_add(1, Ordering::SeqCst);
//! println!("live tasks: {}", old_task_count + 1); //! println!("live threads: {}", old_thread_count + 1);
//! ``` //! ```
#![stable(feature = "rust1", since = "1.0.0")] #![stable(feature = "rust1", since = "1.0.0")]

View File

@ -24,7 +24,8 @@
//! claim temporary, exclusive, mutable access to the inner value. Borrows for `RefCell<T>`s are //! claim temporary, exclusive, mutable access to the inner value. Borrows for `RefCell<T>`s are
//! tracked 'at runtime', unlike Rust's native reference types which are entirely tracked //! tracked 'at runtime', unlike Rust's native reference types which are entirely tracked
//! statically, at compile time. Because `RefCell<T>` borrows are dynamic it is possible to attempt //! statically, at compile time. Because `RefCell<T>` borrows are dynamic it is possible to attempt
//! to borrow a value that is already mutably borrowed; when this happens it results in task panic. //! to borrow a value that is already mutably borrowed; when this happens it results in thread
//! panic.
//! //!
//! # When to choose interior mutability //! # When to choose interior mutability
//! //!
@ -100,7 +101,7 @@
//! // Recursive call to return the just-cached value. //! // Recursive call to return the just-cached value.
//! // Note that if we had not let the previous borrow //! // Note that if we had not let the previous borrow
//! // of the cache fall out of scope then the subsequent //! // of the cache fall out of scope then the subsequent
//! // recursive borrow would cause a dynamic task panic. //! // recursive borrow would cause a dynamic thread panic.
//! // This is the major hazard of using `RefCell`. //! // This is the major hazard of using `RefCell`.
//! self.minimum_spanning_tree() //! self.minimum_spanning_tree()
//! } //! }
@ -417,7 +418,7 @@ impl<T> RefCell<T> {
/// ///
/// let result = thread::spawn(move || { /// let result = thread::spawn(move || {
/// let c = RefCell::new(5); /// let c = RefCell::new(5);
/// let m = c.borrow_mut(); /// let m = c.borrow();
/// ///
/// let b = c.borrow_mut(); // this causes a panic /// let b = c.borrow_mut(); // this causes a panic
/// }).join(); /// }).join();

View File

@ -83,10 +83,8 @@ pub trait Into<T>: Sized {
/// `String` implements `From<&str>`: /// `String` implements `From<&str>`:
/// ///
/// ``` /// ```
/// let s = "hello";
/// let string = "hello".to_string(); /// let string = "hello".to_string();
/// /// let other_string = String::from("hello");
/// let other_string: String = From::from(s);
/// ///
/// assert_eq!(string, other_string); /// assert_eq!(string, other_string);
/// ``` /// ```

View File

@ -217,10 +217,6 @@ extern "rust-intrinsic" {
pub fn uninit<T>() -> T; pub fn uninit<T>() -> T;
/// Moves a value out of scope without running drop glue. /// Moves a value out of scope without running drop glue.
///
/// `forget` is unsafe because the caller is responsible for
/// ensuring the argument is deallocated already.
#[stable(feature = "rust1", since = "1.0.0")]
pub fn forget<T>(_: T) -> (); pub fn forget<T>(_: T) -> ();
/// Unsafely transforms a value of one type into a value of another type. /// Unsafely transforms a value of one type into a value of another type.

View File

@ -124,7 +124,7 @@ pub trait Iterator {
/// ///
/// ``` /// ```
/// let a = [1, 2, 3, 4, 5]; /// let a = [1, 2, 3, 4, 5];
/// assert!(a.iter().last().unwrap() == &5); /// assert_eq!(a.iter().last(), Some(&5));
/// ``` /// ```
#[inline] #[inline]
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
@ -142,8 +142,8 @@ pub trait Iterator {
/// ``` /// ```
/// let a = [1, 2, 3, 4, 5]; /// let a = [1, 2, 3, 4, 5];
/// let mut it = a.iter(); /// let mut it = a.iter();
/// assert!(it.nth(2).unwrap() == &3); /// assert_eq!(it.nth(2), Some(&3));
/// assert!(it.nth(2) == None); /// assert_eq!(it.nth(2), None);
/// ``` /// ```
#[inline] #[inline]
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
@ -165,8 +165,8 @@ pub trait Iterator {
/// let a = [0]; /// let a = [0];
/// let b = [1]; /// let b = [1];
/// let mut it = a.iter().chain(b.iter()); /// let mut it = a.iter().chain(b.iter());
/// assert_eq!(it.next().unwrap(), &0); /// assert_eq!(it.next(), Some(&0));
/// assert_eq!(it.next().unwrap(), &1); /// assert_eq!(it.next(), Some(&1));
/// assert!(it.next().is_none()); /// assert!(it.next().is_none());
/// ``` /// ```
#[inline] #[inline]
@ -179,8 +179,8 @@ pub trait Iterator {
/// Creates an iterator that iterates over both this and the specified /// Creates an iterator that iterates over both this and the specified
/// iterators simultaneously, yielding the two elements as pairs. When /// iterators simultaneously, yielding the two elements as pairs. When
/// either iterator returns `None`, all further invocations of next() will /// either iterator returns `None`, all further invocations of `next()`
/// return `None`. /// will return `None`.
/// ///
/// # Examples /// # Examples
/// ///
@ -188,7 +188,7 @@ pub trait Iterator {
/// let a = [0]; /// let a = [0];
/// let b = [1]; /// let b = [1];
/// let mut it = a.iter().zip(b.iter()); /// let mut it = a.iter().zip(b.iter());
/// assert_eq!(it.next().unwrap(), (&0, &1)); /// assert_eq!(it.next(), Some((&0, &1)));
/// assert!(it.next().is_none()); /// assert!(it.next().is_none());
/// ``` /// ```
/// ///
@ -221,8 +221,8 @@ pub trait Iterator {
/// ``` /// ```
/// let a = [1, 2]; /// let a = [1, 2];
/// let mut it = a.iter().map(|&x| 2 * x); /// let mut it = a.iter().map(|&x| 2 * x);
/// assert_eq!(it.next().unwrap(), 2); /// assert_eq!(it.next(), Some(2));
/// assert_eq!(it.next().unwrap(), 4); /// assert_eq!(it.next(), Some(4));
/// assert!(it.next().is_none()); /// assert!(it.next().is_none());
/// ``` /// ```
#[inline] #[inline]
@ -242,7 +242,7 @@ pub trait Iterator {
/// ``` /// ```
/// let a = [1, 2]; /// let a = [1, 2];
/// let mut it = a.iter().filter(|&x| *x > 1); /// let mut it = a.iter().filter(|&x| *x > 1);
/// assert_eq!(it.next().unwrap(), &2); /// assert_eq!(it.next(), Some(&2));
/// assert!(it.next().is_none()); /// assert!(it.next().is_none());
/// ``` /// ```
#[inline] #[inline]
@ -262,7 +262,7 @@ pub trait Iterator {
/// ``` /// ```
/// let a = [1, 2]; /// let a = [1, 2];
/// let mut it = a.iter().filter_map(|&x| if x > 1 {Some(2 * x)} else {None}); /// let mut it = a.iter().filter_map(|&x| if x > 1 {Some(2 * x)} else {None});
/// assert_eq!(it.next().unwrap(), 4); /// assert_eq!(it.next(), Some(4));
/// assert!(it.next().is_none()); /// assert!(it.next().is_none());
/// ``` /// ```
#[inline] #[inline]
@ -286,8 +286,8 @@ pub trait Iterator {
/// ``` /// ```
/// let a = [100, 200]; /// let a = [100, 200];
/// let mut it = a.iter().enumerate(); /// let mut it = a.iter().enumerate();
/// assert_eq!(it.next().unwrap(), (0, &100)); /// assert_eq!(it.next(), Some((0, &100)));
/// assert_eq!(it.next().unwrap(), (1, &200)); /// assert_eq!(it.next(), Some((1, &200)));
/// assert!(it.next().is_none()); /// assert!(it.next().is_none());
/// ``` /// ```
#[inline] #[inline]
@ -329,9 +329,9 @@ pub trait Iterator {
/// ``` /// ```
/// let a = [1, 2, 3, 4, 5]; /// let a = [1, 2, 3, 4, 5];
/// let mut it = a.iter().skip_while(|&a| *a < 3); /// let mut it = a.iter().skip_while(|&a| *a < 3);
/// assert_eq!(it.next().unwrap(), &3); /// assert_eq!(it.next(), Some(&3));
/// assert_eq!(it.next().unwrap(), &4); /// assert_eq!(it.next(), Some(&4));
/// assert_eq!(it.next().unwrap(), &5); /// assert_eq!(it.next(), Some(&5));
/// assert!(it.next().is_none()); /// assert!(it.next().is_none());
/// ``` /// ```
#[inline] #[inline]
@ -351,8 +351,8 @@ pub trait Iterator {
/// ``` /// ```
/// let a = [1, 2, 3, 4, 5]; /// let a = [1, 2, 3, 4, 5];
/// let mut it = a.iter().take_while(|&a| *a < 3); /// let mut it = a.iter().take_while(|&a| *a < 3);
/// assert_eq!(it.next().unwrap(), &1); /// assert_eq!(it.next(), Some(&1));
/// assert_eq!(it.next().unwrap(), &2); /// assert_eq!(it.next(), Some(&2));
/// assert!(it.next().is_none()); /// assert!(it.next().is_none());
/// ``` /// ```
#[inline] #[inline]
@ -371,8 +371,8 @@ pub trait Iterator {
/// ``` /// ```
/// let a = [1, 2, 3, 4, 5]; /// let a = [1, 2, 3, 4, 5];
/// let mut it = a.iter().skip(3); /// let mut it = a.iter().skip(3);
/// assert_eq!(it.next().unwrap(), &4); /// assert_eq!(it.next(), Some(&4));
/// assert_eq!(it.next().unwrap(), &5); /// assert_eq!(it.next(), Some(&5));
/// assert!(it.next().is_none()); /// assert!(it.next().is_none());
/// ``` /// ```
#[inline] #[inline]
@ -389,9 +389,9 @@ pub trait Iterator {
/// ``` /// ```
/// let a = [1, 2, 3, 4, 5]; /// let a = [1, 2, 3, 4, 5];
/// let mut it = a.iter().take(3); /// let mut it = a.iter().take(3);
/// assert_eq!(it.next().unwrap(), &1); /// assert_eq!(it.next(), Some(&1));
/// assert_eq!(it.next().unwrap(), &2); /// assert_eq!(it.next(), Some(&2));
/// assert_eq!(it.next().unwrap(), &3); /// assert_eq!(it.next(), Some(&3));
/// assert!(it.next().is_none()); /// assert!(it.next().is_none());
/// ``` /// ```
#[inline] #[inline]
@ -413,11 +413,11 @@ pub trait Iterator {
/// *fac = *fac * x; /// *fac = *fac * x;
/// Some(*fac) /// Some(*fac)
/// }); /// });
/// assert_eq!(it.next().unwrap(), 1); /// assert_eq!(it.next(), Some(1));
/// assert_eq!(it.next().unwrap(), 2); /// assert_eq!(it.next(), Some(2));
/// assert_eq!(it.next().unwrap(), 6); /// assert_eq!(it.next(), Some(6));
/// assert_eq!(it.next().unwrap(), 24); /// assert_eq!(it.next(), Some(24));
/// assert_eq!(it.next().unwrap(), 120); /// assert_eq!(it.next(), Some(120));
/// assert!(it.next().is_none()); /// assert!(it.next().is_none());
/// ``` /// ```
#[inline] #[inline]
@ -626,12 +626,10 @@ pub trait Iterator {
/// # Examples /// # Examples
/// ///
/// ``` /// ```
/// # #![feature(core)]
/// let a = [1, 2, 3, 4, 5]; /// let a = [1, 2, 3, 4, 5];
/// let mut it = a.iter(); /// let mut it = a.iter();
/// assert!(it.any(|x| *x == 3)); /// assert!(it.any(|x| *x == 3));
/// assert_eq!(&it[..], [4, 5]); /// assert_eq!(it.collect::<Vec<_>>(), [&4, &5]);
///
/// ``` /// ```
#[inline] #[inline]
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
@ -654,11 +652,10 @@ pub trait Iterator {
/// # Examples /// # Examples
/// ///
/// ``` /// ```
/// # #![feature(core)]
/// let a = [1, 2, 3, 4, 5]; /// let a = [1, 2, 3, 4, 5];
/// let mut it = a.iter(); /// let mut it = a.iter();
/// assert_eq!(it.find(|&x| *x == 3).unwrap(), &3); /// assert_eq!(it.find(|&x| *x == 3), Some(&3));
/// assert_eq!(&it[..], [4, 5]); /// assert_eq!(it.collect::<Vec<_>>(), [&4, &5]);
#[inline] #[inline]
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
fn find<P>(&mut self, mut predicate: P) -> Option<Self::Item> where fn find<P>(&mut self, mut predicate: P) -> Option<Self::Item> where
@ -678,11 +675,10 @@ pub trait Iterator {
/// # Examples /// # Examples
/// ///
/// ``` /// ```
/// # #![feature(core)]
/// let a = [1, 2, 3, 4, 5]; /// let a = [1, 2, 3, 4, 5];
/// let mut it = a.iter(); /// let mut it = a.iter();
/// assert_eq!(it.position(|x| *x == 3).unwrap(), 2); /// assert_eq!(it.position(|x| *x == 3), Some(2));
/// assert_eq!(&it[..], [4, 5]); /// assert_eq!(it.collect::<Vec<_>>(), [&4, &5]);
#[inline] #[inline]
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
fn position<P>(&mut self, mut predicate: P) -> Option<usize> where fn position<P>(&mut self, mut predicate: P) -> Option<usize> where
@ -708,11 +704,10 @@ pub trait Iterator {
/// # Examples /// # Examples
/// ///
/// ``` /// ```
/// # #![feature(core)]
/// let a = [1, 2, 2, 4, 5]; /// let a = [1, 2, 2, 4, 5];
/// let mut it = a.iter(); /// let mut it = a.iter();
/// assert_eq!(it.rposition(|x| *x == 2).unwrap(), 2); /// assert_eq!(it.rposition(|x| *x == 2), Some(2));
/// assert_eq!(&it[..], [1, 2]); /// assert_eq!(it.collect::<Vec<_>>(), [&1, &2]);
#[inline] #[inline]
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
fn rposition<P>(&mut self, mut predicate: P) -> Option<usize> where fn rposition<P>(&mut self, mut predicate: P) -> Option<usize> where
@ -739,7 +734,7 @@ pub trait Iterator {
/// ///
/// ``` /// ```
/// let a = [1, 2, 3, 4, 5]; /// let a = [1, 2, 3, 4, 5];
/// assert!(a.iter().max().unwrap() == &5); /// assert_eq!(a.iter().max(), Some(&5));
/// ``` /// ```
#[inline] #[inline]
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
@ -762,7 +757,7 @@ pub trait Iterator {
/// ///
/// ``` /// ```
/// let a = [1, 2, 3, 4, 5]; /// let a = [1, 2, 3, 4, 5];
/// assert!(a.iter().min().unwrap() == &1); /// assert_eq!(a.iter().min(), Some(&1));
/// ``` /// ```
#[inline] #[inline]
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
@ -991,9 +986,9 @@ pub trait Iterator {
/// ``` /// ```
/// let a = [1, 2]; /// let a = [1, 2];
/// let mut it = a.iter().cycle(); /// let mut it = a.iter().cycle();
/// assert_eq!(it.next().unwrap(), &1); /// assert_eq!(it.next(), Some(&1));
/// assert_eq!(it.next().unwrap(), &2); /// assert_eq!(it.next(), Some(&2));
/// assert_eq!(it.next().unwrap(), &1); /// assert_eq!(it.next(), Some(&1));
/// ``` /// ```
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
#[inline] #[inline]

View File

@ -8,7 +8,7 @@
// 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.
/// Entry point of task panic, for details, see std::macros /// Entry point of thread panic, for details, see std::macros
#[macro_export] #[macro_export]
macro_rules! panic { macro_rules! panic {
() => ( () => (

View File

@ -462,6 +462,8 @@ mod impls {
#[unstable(feature = "core", reason = "requires RFC and more experience")] #[unstable(feature = "core", reason = "requires RFC and more experience")]
#[allow(deprecated)] #[allow(deprecated)]
#[cfg(not(stage0))] #[cfg(not(stage0))]
#[rustc_on_unimplemented = "`{Self}` does not implement `Any`; \
ensure all type parameters are bounded by `Any`"]
pub trait Reflect {} pub trait Reflect {}
/// dox /// dox

View File

@ -22,15 +22,54 @@ use ptr;
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
pub use intrinsics::transmute; pub use intrinsics::transmute;
/// Moves a thing into the void. /// Leaks a value into the void, consuming ownership and never running its
/// destructor.
/// ///
/// The forget function will take ownership of the provided value but neglect /// This function will take ownership of its argument, but is distinct from the
/// to run any required cleanup or memory management operations on it. /// `mem::drop` function in that it **does not run the destructor**, leaking the
/// value and any resources that it owns.
/// ///
/// This function is the unsafe version of the `drop` function because it does /// # Safety
/// not run any destructors. ///
/// This function is not marked as `unsafe` as Rust does not guarantee that the
/// `Drop` implementation for a value will always run. Note, however, that
/// leaking resources such as memory or I/O objects is likely not desired, so
/// this function is only recommended for specialized use cases.
///
/// The safety of this function implies that when writing `unsafe` code
/// yourself care must be taken when leveraging a destructor that is required to
/// run to preserve memory safety. There are known situations where the
/// destructor may not run (such as if ownership of the object with the
/// destructor is returned) which must be taken into account.
///
/// # Other forms of Leakage
///
/// It's important to point out that this function is not the only method by
/// which a value can be leaked in safe Rust code. Other known sources of
/// leakage are:
///
/// * `Rc` and `Arc` cycles
/// * `mpsc::{Sender, Receiver}` cycles (they use `Arc` internally)
/// * Panicking destructors are likely to leak local resources
///
/// # Example
///
/// ```rust,no_run
/// use std::mem;
/// use std::fs::File;
///
/// // Leak some heap memory by never deallocating it
/// let heap_memory = Box::new(3);
/// mem::forget(heap_memory);
///
/// // Leak an I/O object, never closing the file
/// let file = File::open("foo.txt").unwrap();
/// mem::forget(file);
/// ```
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
pub use intrinsics::forget; pub fn forget<T>(t: T) {
unsafe { intrinsics::forget(t) }
}
/// Returns the size of a type in bytes. /// Returns the size of a type in bytes.
/// ///

View File

@ -736,46 +736,6 @@ pub struct Iter<'a, T: 'a> {
unsafe impl<'a, T: Sync> Sync for Iter<'a, T> {} unsafe impl<'a, T: Sync> Sync for Iter<'a, T> {}
unsafe impl<'a, T: Sync> Send for Iter<'a, T> {} unsafe impl<'a, T: Sync> Send for Iter<'a, T> {}
#[unstable(feature = "core")]
impl<'a, T> ops::Index<ops::Range<usize>> for Iter<'a, T> {
type Output = [T];
#[inline]
fn index(&self, index: ops::Range<usize>) -> &[T] {
self.as_slice().index(index)
}
}
#[unstable(feature = "core")]
impl<'a, T> ops::Index<ops::RangeTo<usize>> for Iter<'a, T> {
type Output = [T];
#[inline]
fn index(&self, index: ops::RangeTo<usize>) -> &[T] {
self.as_slice().index(index)
}
}
#[unstable(feature = "core")]
impl<'a, T> ops::Index<ops::RangeFrom<usize>> for Iter<'a, T> {
type Output = [T];
#[inline]
fn index(&self, index: ops::RangeFrom<usize>) -> &[T] {
self.as_slice().index(index)
}
}
#[unstable(feature = "core")]
impl<'a, T> ops::Index<RangeFull> for Iter<'a, T> {
type Output = [T];
#[inline]
fn index(&self, _index: RangeFull) -> &[T] {
self.as_slice()
}
}
impl<'a, T> Iter<'a, T> { impl<'a, T> Iter<'a, T> {
/// View the underlying data as a subslice of the original data. /// View the underlying data as a subslice of the original data.
/// ///
@ -833,76 +793,6 @@ pub struct IterMut<'a, T: 'a> {
unsafe impl<'a, T: Sync> Sync for IterMut<'a, T> {} unsafe impl<'a, T: Sync> Sync for IterMut<'a, T> {}
unsafe impl<'a, T: Send> Send for IterMut<'a, T> {} unsafe impl<'a, T: Send> Send for IterMut<'a, T> {}
#[unstable(feature = "core")]
impl<'a, T> ops::Index<ops::Range<usize>> for IterMut<'a, T> {
type Output = [T];
#[inline]
fn index(&self, index: ops::Range<usize>) -> &[T] {
self.index(RangeFull).index(index)
}
}
#[unstable(feature = "core")]
impl<'a, T> ops::Index<ops::RangeTo<usize>> for IterMut<'a, T> {
type Output = [T];
#[inline]
fn index(&self, index: ops::RangeTo<usize>) -> &[T] {
self.index(RangeFull).index(index)
}
}
#[unstable(feature = "core")]
impl<'a, T> ops::Index<ops::RangeFrom<usize>> for IterMut<'a, T> {
type Output = [T];
#[inline]
fn index(&self, index: ops::RangeFrom<usize>) -> &[T] {
self.index(RangeFull).index(index)
}
}
#[unstable(feature = "core")]
impl<'a, T> ops::Index<RangeFull> for IterMut<'a, T> {
type Output = [T];
#[inline]
fn index(&self, _index: RangeFull) -> &[T] {
make_slice!(T => &[T]: self.ptr, self.end)
}
}
#[unstable(feature = "core")]
impl<'a, T> ops::IndexMut<ops::Range<usize>> for IterMut<'a, T> {
#[inline]
fn index_mut(&mut self, index: ops::Range<usize>) -> &mut [T] {
self.index_mut(RangeFull).index_mut(index)
}
}
#[unstable(feature = "core")]
impl<'a, T> ops::IndexMut<ops::RangeTo<usize>> for IterMut<'a, T> {
#[inline]
fn index_mut(&mut self, index: ops::RangeTo<usize>) -> &mut [T] {
self.index_mut(RangeFull).index_mut(index)
}
}
#[unstable(feature = "core")]
impl<'a, T> ops::IndexMut<ops::RangeFrom<usize>> for IterMut<'a, T> {
#[inline]
fn index_mut(&mut self, index: ops::RangeFrom<usize>) -> &mut [T] {
self.index_mut(RangeFull).index_mut(index)
}
}
#[unstable(feature = "core")]
impl<'a, T> ops::IndexMut<RangeFull> for IterMut<'a, T> {
#[inline]
fn index_mut(&mut self, _index: RangeFull) -> &mut [T] {
make_mut_slice!(T => &mut [T]: self.ptr, self.end)
}
}
impl<'a, T> IterMut<'a, T> { impl<'a, T> IterMut<'a, T> {
/// View the underlying data as a subslice of the original data. /// View the underlying data as a subslice of the original data.
/// ///

View File

@ -23,6 +23,7 @@ use self::pattern::{Searcher, ReverseSearcher, DoubleEndedSearcher};
use char::CharExt; use char::CharExt;
use clone::Clone; use clone::Clone;
use cmp::{self, Eq}; use cmp::{self, Eq};
use convert::AsRef;
use default::Default; use default::Default;
use fmt; use fmt;
use iter::ExactSizeIterator; use iter::ExactSizeIterator;
@ -1843,6 +1844,14 @@ impl StrExt for str {
fn parse<T: FromStr>(&self) -> Result<T, T::Err> { FromStr::from_str(self) } fn parse<T: FromStr>(&self) -> Result<T, T::Err> { FromStr::from_str(self) }
} }
#[stable(feature = "rust1", since = "1.0.0")]
impl AsRef<[u8]> for str {
#[inline]
fn as_ref(&self) -> &[u8] {
self.as_bytes()
}
}
/// Pluck a code point out of a UTF-8-like byte slice and return the /// Pluck a code point out of a UTF-8-like byte slice and return the
/// index of the next code point. /// index of the next code point.
#[inline] #[inline]

View File

@ -33,52 +33,3 @@ fn binary_search_not_found() {
let b = [1, 2, 4, 5, 6, 8]; let b = [1, 2, 4, 5, 6, 8];
assert!(b.binary_search_by(|v| v.cmp(&9)) == Err(6)); assert!(b.binary_search_by(|v| v.cmp(&9)) == Err(6));
} }
#[test]
fn iterator_to_slice() {
macro_rules! test {
($data: expr) => {{
let data: &mut [_] = &mut $data;
let other_data: &mut [_] = &mut $data;
{
let mut iter = data.iter();
assert_eq!(&iter[..], &other_data[..]);
iter.next();
assert_eq!(&iter[..], &other_data[1..]);
iter.next_back();
assert_eq!(&iter[..], &other_data[1..2]);
let s = iter.as_slice();
iter.next();
assert_eq!(s, &other_data[1..2]);
}
{
let mut iter = data.iter_mut();
assert_eq!(&iter[..], &other_data[..]);
// mutability:
assert!(&mut iter[..] == other_data);
iter.next();
assert_eq!(&iter[..], &other_data[1..]);
assert!(&mut iter[..] == &mut other_data[1..]);
iter.next_back();
assert_eq!(&iter[..], &other_data[1..2]);
assert!(&mut iter[..] == &mut other_data[1..2]);
let s = iter.into_slice();
assert!(s == &mut other_data[1..2]);
}
}}
}
// try types of a variety of sizes
test!([(1u64, 1u64, 1u8), (2, 2, 2), (3, 3, 3)]);
test!([1u64,2,3]);
test!([1u8,2,3]);
test!([(),(),()]);
}

View File

@ -12,7 +12,8 @@
#![cfg_attr(stage0, feature(custom_attribute))] #![cfg_attr(stage0, feature(custom_attribute))]
#![crate_name = "libc"] #![crate_name = "libc"]
#![crate_type = "rlib"] #![crate_type = "rlib"]
#![cfg_attr(not(feature = "cargo-build"), unstable(feature = "libc"))] #![cfg_attr(not(feature = "cargo-build"), unstable(feature = "libc",
reason = "use `libc` from crates.io"))]
#![cfg_attr(not(feature = "cargo-build"), feature(staged_api, core, no_std))] #![cfg_attr(not(feature = "cargo-build"), feature(staged_api, core, no_std))]
#![cfg_attr(not(feature = "cargo-build"), staged_api)] #![cfg_attr(not(feature = "cargo-build"), staged_api)]
#![cfg_attr(not(feature = "cargo-build"), no_std)] #![cfg_attr(not(feature = "cargo-build"), no_std)]

View File

@ -228,7 +228,7 @@ thread_local! {
} }
} }
/// A trait used to represent an interface to a task-local logger. Each task /// A trait used to represent an interface to a thread-local logger. Each thread
/// can have its own custom logger which can respond to logging messages /// can have its own custom logger which can respond to logging messages
/// however it likes. /// however it likes.
pub trait Logger { pub trait Logger {
@ -324,7 +324,7 @@ pub fn log(level: u32, loc: &'static LogLocation, args: fmt::Arguments) {
#[inline(always)] #[inline(always)]
pub fn log_level() -> u32 { unsafe { LOG_LEVEL } } pub fn log_level() -> u32 { unsafe { LOG_LEVEL } }
/// Replaces the task-local logger with the specified logger, returning the old /// Replaces the thread-local logger with the specified logger, returning the old
/// logger. /// logger.
pub fn set_logger(logger: Box<Logger + Send>) -> Option<Box<Logger + Send>> { pub fn set_logger(logger: Box<Logger + Send>) -> Option<Box<Logger + Send>> {
let mut l = Some(logger); let mut l = Some(logger);

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