Imported Upstream version 1.0.0~beta.3

This commit is contained in:
Angus Lees 2015-05-05 17:26:13 +10:00
parent c34b17963d
commit 9346a6ac1c
1834 changed files with 21633 additions and 50842 deletions

View File

@ -9,17 +9,19 @@ Aaron Todd <github@opprobrio.us>
Aaron Turon <aturon@mozilla.com>
Aaron Weiss <aaronweiss74@gmail.com>
Adam Bozanich <adam.boz@gmail.com>
Adam Jacob <adam@opscode.com>
Adam Roben <adam@roben.org>
Adam Szkoda <adaszko@gmail.com>
Adenilson Cavalcanti <cavalcantii@gmail.com>
Adolfo Ochagavía <aochagavia92@gmail.com>
Adrien Brault <adrien.brault@gmail.com>
Adrien Tétar <adri-from-59@hotmail.fr>
Ahmed Charles <acharles@outlook.com>
Ahmed Charles <ahmedcharles@gmail.com>
Aidan Cully <github@aidan.users.panix.com>
Aidan Hobson Sayers <aidanhs@cantab.net>
Akos Kiss <akiss@inf.u-szeged.hu>
Alan Andrade <alan.andradec@gmail.com>
Alan Cutter <alancutter@chromium.org>
Alan Williams <mralert@gmail.com>
Aleksander Balicki <balicki.aleksander@gmail.com>
Aleksandr Koshlo <sash7ko@gmail.com>
@ -29,6 +31,8 @@ Alex Lyon <arcterus@mail.com>
Alex Rønne Petersen <alex@lycus.org>
Alex Whitney <aw1209@ic.ac.uk>
Alexander Bliskovsky <alexander.bliskovsky@gmail.com>
Alexander Campbell <alexanderhcampbell@gmail.com>
Alexander Chernyakhovsky <achernya@mit.edu>
Alexander Korolkov <alexander.korolkov@gmail.com>
Alexander Light <allight@cs.brown.edu>
Alexander Stavonin <a.stavonin@gmail.com>
@ -41,6 +45,7 @@ Alfie John <alfiej@fastmail.fm>
Ali Smesseim <smesseim.ali@gmail.com>
Alisdair Owens <awo101@zepler.net>
Aljaž "g5pw" Srebrnič <a2piratesoft@gmail.com>
Amol Mundayoor <amol.com@gmail.com>
Amy Unger <amy.e.unger@gmail.com>
Anders Kaseorg <andersk@mit.edu>
Andre Arko <andre@arko.net>
@ -56,6 +61,7 @@ Andrew Cann <shum@canndrew.org>
Andrew Chin <achin@eminence32.net>
Andrew Dunham <andrew@du.nham.ca>
Andrew Gallant <jamslam@gmail.com>
Andrew Hobden <andrew@hoverbear.org>
Andrew Paseltiner <apaseltiner@gmail.com>
Andrew Poelstra <asp11@sfu.ca>
Andrew Wagner <drewm1980@gmail.com>
@ -110,6 +116,8 @@ Brendan McLoughlin <btmcloughlin@gmail.com>
Brendan Zabarauskas <bjzaba@yahoo.com.au>
Brett Cannon <brett@python.org>
Brian Anderson <banderson@mozilla.com>
Brian Brooks <brooks.brian@gmail.com>
Brian Campbell <lambda@continuation.org>
Brian Dawn <brian.t.dawn@gmail.com>
Brian J Brennan <brianloveswords@gmail.com>
Brian J. Burg <burg@cs.washington.edu>
@ -122,6 +130,8 @@ Cadence Marseille <cadencemarseille@gmail.com>
Caitlin Potter <snowball@defpixel.com>
Cam Jackson <camjackson89@gmail.com>
Cameron Zwarich <zwarich@mozilla.com>
Camille Roussel <camille@rousselfamily.com>
Camille TJHOA <camille.tjhoa@outlook.com>
CarVac <c.lo.to.da.down.lo@gmail.com>
Carl Lerche <me@carllerche.com>
Carl-Anton Ingmarsson <mail@carlanton.se>
@ -132,6 +142,8 @@ Carter Hinsley <carterhinsley@gmail.com>
Carter Tazio Schonwald <carter.schonwald@gmail.com>
Caspar Krieger <caspar@asparck.com>
Chase Southwood <chase.southwood@gmail.com>
Ches Martin <ches@whiskeyandgrits.net>
Chloe <5paceToast@users.noreply.github.com>
Chris Double <chris.double@double.co.nz>
Chris Morgan <me@chrismorgan.info>
Chris Nixon <chris.nixon@sigma.me.uk>
@ -158,7 +170,9 @@ Corey Farwell <coreyf+rust@rwell.org>
Corey Ford <corey@coreyford.name>
Corey Richardson <corey@octayn.net>
Cristi Burcă <scribu@gmail.com>
Cristian Kubis <cristian.kubis@tsunix.de>
DJUrsus <colinvh@divitu.com>
Dabo Ross <daboross@daboross.net>
Damian Gryski <damian@gryski.com>
Damien Grassart <damien@grassart.com>
Damien Radtke <dradtke@channeliq.com>
@ -167,6 +181,8 @@ Dan Albert <danalbert@google.com>
Dan Burkert <dan@danburkert.com>
Dan Connolly <dckc@madmode.com>
Dan Luu <danluu@gmail.com>
Dan Schatzberg <schatzberg.dan@gmail.com>
Dan W. <1danwade@gmail.com>
Dan Yang <dsyang@fb.com>
Daniel Brooks <db48x@db48x.net>
Daniel Fagnan <dnfagnan@gmail.com>
@ -174,6 +190,7 @@ Daniel Farina <daniel@fdr.io>
Daniel Griffen <daniel@dgriffen.com>
Daniel Grunwald <daniel@danielgrunwald.de>
Daniel Hofstetter <daniel.hofstetter@42dh.com>
Daniel Lobato García <elobatocs@gmail.com>
Daniel Luz <dev@mernen.com>
Daniel MacDougall <dmacdougall@gmail.com>
Daniel Micay <danielmicay@gmail.com>
@ -183,17 +200,23 @@ Daniel Ralston <Wubbulous@gmail.com>
Daniel Rosenwasser <DanielRosenwasser@gmail.com>
Daniel Ursache Dogariu <contact@danniel.net>
Daniil Smirnov <danslapman@gmail.com>
Darin Morrison <darinmorrison+git@gmail.com>
Darrell Hamilton <darrell.noice@gmail.com>
Dave Herman <dherman@mozilla.com>
Dave Hodder <dmh@dmh.org.uk>
Dave Huseby <dhuseby@mozilla.com>
David Creswick <dcrewi@gyrae.net>
David Forsythe <dforsythe@gmail.com>
David Halperin <halperin.dr@gmail.com>
David King <dave@davbo.org>
David Klein <david.klein@baesystemsdetica.com>
David Mally <djmally@gmail.com>
David Manescu <david.manescu@gmail.com>
David Rajchenbach-Teller <dteller@mozilla.com>
David Renshaw <dwrenshaw@gmail.com>
David Vazgenovich Shakaryan <dvshakaryan@gmail.com>
Davis Silverman <sinistersnare@gmail.com>
Denis Defreyne <denis.defreyne@stoneship.org>
Derecho <derecho@sector5d.org>
Derek Chiang <derekchiang93@gmail.com>
Derek Guenther <dguenther9@gmail.com>
@ -214,10 +237,12 @@ Do Nhat Minh <mrordinaire@gmail.com>
Dominik Inführ <dominik.infuehr@gmail.com>
Donovan Preston <donovanpreston@gmail.com>
Douglas Young <rcxdude@gmail.com>
Drew Crawford <drew@sealedabstract.com>
Drew Willcoxon <adw@mozilla.com>
Duane Edwards <mail@duaneedwards.net>
Duncan Regan <duncanregan@gmail.com>
Dylan Braithwaite <dylanbraithwaite1@gmail.com>
Dylan Ede <dylanede@googlemail.com>
Dzmitry Malyshau <kvarkus@gmail.com>
Earl St Sauver <estsauver@gmail.com>
Eduard Bopp <eduard.bopp@aepsil0n.de>
@ -230,12 +255,14 @@ Elantsev Serj <elantsev@yandex-team.ru>
Elliott Slaughter <elliottslaughter@gmail.com>
Elly Fong-Jones <elly@leptoquark.net>
Emanuel Rylke <ema-fox@web.de>
Emeliov Dmitrii <demelev1990@gmail.com>
Eric Allen <ericpallen@gmail.com>
Eric Biggers <ebiggers3@gmail.com>
Eric Holk <eric.holk@gmail.com>
Eric Holmes <eric@ejholmes.net>
Eric Kidd <git@randomhacks.net>
Eric Martin <e.a.martin1337@gmail.com>
Eric Platon <eric.platon@waku-waku.ne.jp>
Eric Reed <ecreed@cs.washington.edu>
Erick Rivas <chemical.rivas@gmail.com>
Erick Tryzelaar <erick.tryzelaar@gmail.com>
@ -268,6 +295,7 @@ Florian Wilkens <floya@live.de>
Florian Zeitz <florob@babelmonkeys.de>
Francisco Souza <f@souza.cc>
Franklin Chen <franklinchen@franklinchen.com>
FuGangqiang <fu_gangqiang@163.com>
Gabriel <g2p.code@gmail.com>
Gareth Daniel Smith <garethdanielsmith@gmail.com>
Garrett Heel <garrettheel@gmail.com>
@ -279,8 +307,10 @@ Geoffrey Thomas <geofft@ldpreload.com>
Geoffroy Couprie <geo.couprie@gmail.com>
George Papanikolaou <g3orge.app@gmail.com>
Georges Dubus <georges.dubus@gmail.com>
Germano Gabbianelli <tyrion@users.noreply.github.com>
Gil Cottle <rc@redtown.org>
Gioele Barabucci <gioele@svario.it>
GlacJAY <glacjay@gmail.com>
Gleb Kozyrev <gleb@gkoz.com>
Glenn Willen <gwillen@nerdnet.org>
Gonçalo Cabrita <_@gmcabrita.com>
@ -303,9 +333,11 @@ Herman J. Radtke III <hermanradtke@gmail.com>
HeroesGrave <heroesgrave@gmail.com>
Hong Chulju <ang0123dev@gmail.com>
Honza Strnad <hanny.strnad@gmail.com>
Huachao Huang <huachao.huang@gmail.com>
Hugo Jobling <hello@thisishugo.com>
Hugo van der Wijst <hugo@wij.st>
Huon Wilson <dbau.pp+github@gmail.com>
Hyeon Kim <simnalamburt@gmail.com>
Ian Connolly <iconnolly@mozilla.com>
Ian D. Bollinger <ian.bollinger@gmail.com>
Ian Daniher <it.daniher@gmail.com>
@ -318,12 +350,14 @@ Isaac Aggrey <isaac.aggrey@gmail.com>
Isaac Dupree <antispam@idupree.com>
Ivan Enderlin <ivan.enderlin@hoa-project.net>
Ivan Petkov <ivanppetkov@gmail.com>
Ivan Radanov Ivanov <ivanradanov@yahoo.co.uk>
Ivan Ukhov <ivan.ukhov@gmail.com>
Ivano Coppola <rgbfirefox@gmail.com>
J. J. Weber <jjweber@gmail.com>
J.C. Moyer <jmoyer1992@gmail.com>
JONNALAGADDA Srinivas <js@ojuslabs.com>
JP Sugarbroad <jpsugar@google.com>
JP-Ellis <coujellis@gmail.com>
Jack Heizer <jack.heizer@gmail.com>
Jack Moffitt <jack@metajack.im>
Jacob Edelman <edelman.jd@gmail.com>
@ -338,6 +372,7 @@ Jake Kerr <kodafox@gmail.com>
Jake Scott <jake.net@gmail.com>
Jakub Bukaj <jakub@jakub.cc>
Jakub Wieczorek <jakubw@jakubw.net>
Jakub Vrána <jakub@vrana.cz>
James Deng <cnjamesdeng@gmail.com>
James Hurst <jamesrhurst@users.noreply.github.com>
James Lal <james@lightsofapollo.com>
@ -359,6 +394,7 @@ Jason Toffaletti <jason@topsy.com>
Jauhien Piatlicki <jauhien@gentoo.org>
Jay Anderson <jayanderson0@gmail.com>
Jay True <glacjay@gmail.com>
Jeaye <jeaye@arrownext.com>
Jed Davis <jld@panix.com>
Jed Estep <aje@jhu.edu>
Jeff Balogh <jbalogh@mozilla.com>
@ -375,29 +411,36 @@ Jesse Jones <jesse9jones@gmail.com>
Jesse Luehrs <doy@tozt.net>
Jesse Ray <jesse@localhost.localdomain>
Jesse Ruderman <jruderman@gmail.com>
Jihyun Yu <jihyun@nclab.kaist.ac.kr>
Jessy Diamond Exum <jessy.diamondman@gmail.com>
Jihyeok Seo <me@limeburst.net>
Jihyun Yu <j.yu@navercorp.com>
Jim Apple <jbapple+rust@google.com>
Jim Blandy <jimb@red-bean.com>
Jim Radford <radford@blackbean.org>
Jimmie Elvenmark <flugsio@gmail.com>
Jimmy Lu <jimmy.lu.2011@gmail.com>
Jimmy Zelinskie <jimmyzelinskie@gmail.com>
Jiří Stránský <jistr@jistr.com>
Joe Pletcher <joepletcher@gmail.com>
Joe Schafer <joe@jschaf.com>
Johannes Hoff <johshoff@gmail.com>
Johannes Löthberg <johannes@kyriasis.com>
Johannes Muenzel <jmuenzel@gmail.com>
Johannes Oertel <johannes.oertel@uni-due.de>
John Albietz <inthecloud247@gmail.com>
John Barker <jebarker@gmail.com>
John Clements <clements@racket-lang.org>
John Ericson <Ericson2314@Yahoo.com>
John Fresco <john.fresco@utah.edu>
John Gallagher <jgallagher@bignerdranch.com>
John Hodge <acessdev@gmail.com>
John Kåre Alsaker <john.kare.alsaker@gmail.com>
John Kleint <jk@hinge.co>
John Kåre Alsaker <john.kare.alsaker@gmail.com>
John Louis Walker <injyuw@gmail.com>
John Schmidt <john.schmidt.h@gmail.com>
John Simon <john@johnsoft.com>
John Zhang <john@zhang.io>
Jon Haddad <jon@jonhaddad.com>
Jon Morton <jonanin@gmail.com>
Jonas Hietala <tradet.h@gmail.com>
@ -407,6 +450,7 @@ Jonathan Reem <jonathan.reem@gmail.com>
Jonathan S <gereeter@gmail.com>
Jonathan Sternberg <jonathansternberg@gmail.com>
Joonas Javanainen <joonas.javanainen@gmail.com>
Jordan Woehr <jordanwoehr@gmail.com>
Jordi Boggiano <j.boggiano@seld.be>
Jorge Aparicio <japaricious@gmail.com>
Jorge Israel Peña <jorge.israel.p@gmail.com>
@ -423,16 +467,17 @@ Joshua Wise <joshua@joshuawise.com>
Joshua Yanovski <pythonesque@gmail.com>
Julia Evans <julia@jvns.ca>
Julian Orth <ju.orth@gmail.com>
Julian Viereck <julian.viereck@gmail.com>
Junseok Lee <lee.junseok@berkeley.edu>
Junyoung Cho <june0.cho@samsung.com>
JustAPerson <jpriest8@ymail.com>
Justin Noah <justinnoah@gmail.com>
Jyun-Yan You <jyyou.tw@gmail.com>
Kang Seonghoon <kang.seonghoon@mearie.org>
Kang Seonghoon <public+git@mearie.org>
Kasey Carrothers <kaseyc.808@gmail.com>
Keegan McAllister <mcallister.keegan@gmail.com>
Kelly Wilson <wilsonk@cpsc.ucalgary.ca>
Kelvin Ly <kelvin.ly1618@gmail.com>
Ken Tossell <ken@tossell.net>
KernelJ <kernelj@epixxware.com>
Keshav Kini <keshav.kini@gmail.com>
@ -442,6 +487,7 @@ Kevin Butler <haqkrs@gmail.com>
Kevin Cantu <me@kevincantu.org>
Kevin Mehall <km@kevinmehall.net>
Kevin Murphy <kemurphy.cmu@gmail.com>
Kevin Rauwolf <sweetpea-git@tentacle.net>
Kevin Walter <kevin.walter.private@googlemail.com>
Kevin Yap <me@kevinyap.ca>
Kiet Tran <ktt3ja@gmail.com>
@ -459,6 +505,8 @@ Lee Wondong <wdlee91@gmail.com>
LemmingAvalanche <haugsbakk@yahoo.no>
Lennart Kudling <github@kudling.de>
Leo Testard <leo.testard@gmail.com>
Leonids Maslovs <leonids.maslovs@galeoconsulting.com>
Liam Monahan <liam@monahan.io>
Liigo Zhuang <com.liigo@gmail.com>
Lindsey Kuper <lindsey@composition.al>
Lionel Flandrin <lionel.flandrin@parrot.com>
@ -495,6 +543,7 @@ Mathijs van de Nes <git@mathijs.vd-nes.nl>
Matt Brubeck <mbrubeck@limpet.net>
Matt Carberry <carberry.matt@gmail.com>
Matt Coffin <mcoffin13@gmail.com>
Matt Cox <mattcoxpdx@gmail.com>
Matt McPherrin <git@mcpherrin.ca>
Matt Murphy <matthew.john.murphy@gmail.com>
Matt Roche <angst7@gmail.com>
@ -532,6 +581,7 @@ Michael Sullivan <sully@msully.net>
Michael Williams <m.t.williams@live.com>
Michael Woerister <michaelwoerister@posteo>
Michael Zhou <moz@google.com>
Michał Krasnoborski <mkrdln@gmail.com>
Mick Koch <kchmck@gmail.com>
Mickaël Delahaye <mickael.delahaye@gmail.com>
Mihnea Dobrescu-Balaur <mihnea@linux.com>
@ -559,7 +609,9 @@ Nathaniel Theis <nttheis@gmail.com>
Neil Pankey <npankey@gmail.com>
Nelson Chen <crazysim@gmail.com>
NiccosSystem <niccossystem@gmail.com>
Nicholas <npmazzuca@gmail.com>
Nicholas Bishop <nicholasbishop@gmail.com>
Nicholas Mazzuca <npmazzuca@gmail.com>
Nick Cameron <ncameron@mozilla.com>
Nick Desaulniers <ndesaulniers@mozilla.com>
Nick Howell <howellnick@gmail.com>
@ -579,8 +631,10 @@ Oliver Schneider <oliver.schneider@kit.edu>
Olivier Saut <osaut@airpost.net>
Olle Jonsson <olle.jonsson@gmail.com>
Or Brostovski <tohava@gmail.com>
Or Neeman <oneeman@gmail.com>
Oren Hazi <oren.hazi@gmail.com>
Orpheus Lummis <o@orpheuslummis.com>
Orphée Lafond-Lummis <o@orftz.com>
P1start <rewi-github@whanau.org>
Pablo Brasero <pablo@pablobm.com>
Palmer Cox <p@lmercox.com>
@ -590,8 +644,11 @@ Patrick Reisert <kpreisert@gmail.com>
Patrick Walton <pcwalton@mimiga.net>
Patrick Yevsukov <patrickyevsukov@users.noreply.github.com>
Patrik Kårlin <patrik.karlin@gmail.com>
Paul ADENOT <paul@paul.cx>
Paul Collier <paul@paulcollier.ca>
Paul Collins <paul@ondioline.org>
Paul Crowley <paulcrowley@google.com>
Paul Osborne <osbpau@gmail.com>
Paul Stansifer <paul.stansifer@gmail.com>
Paul Woolcock <pwoolcoc+github@gmail.com>
Pavel Panchekha <me@pavpanchekha.com>
@ -602,6 +659,7 @@ Peter Atashian <retep998@gmail.com>
Peter Elmers <peter.elmers@yahoo.com>
Peter Hull <peterhull90@gmail.com>
Peter Marheine <peter@taricorp.net>
Peter Minten <peter@pminten.nl>
Peter Schuller <peter.schuller@infidyne.com>
Peter Williams <peter@newton.cx>
Peter Zotov <whitequark@whitequark.org>
@ -620,14 +678,17 @@ Potpourri <pot_pourri@mail.ru>
Pradeep Kumar <gohanpra@gmail.com>
Prudhvi Krishna Surapaneni <me@prudhvi.net>
Pyfisch <pyfisch@gmail.com>
Pyry Kontio <pyry.kontio@drasa.eu>
Pythoner6 <pythoner6@gmail.com>
Q.P.Liu <qpliu@yahoo.com>
Rafael Ávila de Espíndola <respindola@mozilla.com>
Rahul Horé <hore.rahul@gmail.com>
Ralph Bodenner <rkbodenner+github@gmail.com>
Ralph Giles <giles@thaumas.net>
Ramkumar Ramachandra <artagnon@gmail.com>
Randati <anttivan@gmail.com>
Raphael Catolino <raphael.catolino@gmail.com>
Raphael Nestler <raphael.nestler@gmail.com>
Raphael Speyer <rspeyer@gmail.com>
Raul Gutierrez S <rgs@itevenworks.net>
Ray Clanan <rclanan@utopianconcept.com>
@ -637,6 +698,7 @@ Renato Riccieri Santos Zannon <renato@rrsz.com.br>
Renato Zannon <renato@rrsz.com.br>
Reuben Morais <reuben.morais@gmail.com>
Ricardo M. Correia <rcorreia@wizy.org>
Ricardo Martins <ricardo@scarybox.net>
Rich Lane <rlane@club.cc.cmu.edu>
Richard Diamond <wichard@vitalitystudios.com>
Richo Healey <richo@psych0tik.net>
@ -663,10 +725,13 @@ Russell <rpjohnst@gmail.com>
Ruud van Asseldonk <dev@veniogames.com>
Ryan Levick <ryan@6wunderkinder.com>
Ryan Mulligan <ryan@ryantm.com>
Ryan Prichard <ryan.prichard@gmail.com>
Ryan Riginding <marc.riginding@gmail.com>
Ryan Scheel <ryan.havvy@gmail.com>
Ryman <haqkrs@gmail.com>
Rüdiger Sonderfeld <ruediger@c-plusplus.de>
S Pradeep Kumar <gohanpra@gmail.com>
Sae-bom Kim <sae-bom.kim@samsung.com>
Salem Talha <salem.a.talha@gmail.com>
Samuel Chase <samebchase@gmail.com>
Samuel Neves <sneves@dei.uc.pt>
@ -678,6 +743,7 @@ Santiago Rodriguez <sanrodari@gmail.com>
Saurabh Anand <saurabhanandiit@gmail.com>
Scott Jenkins <scottdjwales@gmail.com>
Scott Lawrence <bytbox@gmail.com>
Scott Olson <scott@scott-olson.org>
Sean Chalmers <sclhiannan@gmail.com>
Sean Collins <sean@cllns.com>
Sean Gillespie <sean.william.g@gmail.com>
@ -730,10 +796,13 @@ Tamir Duberstein <tamird@squareup.com>
Taras Shpot <mrshpot@gmail.com>
Taylor Hutchison <seanthutchison@gmail.com>
Ted Horst <ted.horst@earthlink.net>
Tero Hänninen <lgvz@users.noreply.github.com>
Thad Guidry <thadguidry@gmail.com>
Thiago Carvalho <thiago.carvalho@westwing.de>
Thiago Pontes <email@thiago.me>
Thomas Backman <serenity@exscape.org>
Thomas Daede <daede003@umn.edu>
Tiago Nobrega <tigarmo@gmail.com>
Till Hoeppner <till@hoeppner.ws>
Tim Brooks <brooks@cern.ch>
Tim Chevalier <chevalier@alum.wellesley.edu>
@ -760,6 +829,7 @@ Toni Cárdenas <toni@tcardenas.me>
Tony Young <tony@rfw.name>
Torsten Weber <TorstenWeber12@gmail.com>
Travis Watkins <amaranth@ubuntu.com>
Trent Nadeau <tanadeau@gmail.com>
Trent Ogren <tedwardo2@gmail.com>
Trinick <slicksilver555@mac.com>
Tristan Storch <tstorch@math.uni-bielefeld.de>
@ -769,9 +839,9 @@ TyOverby <ty@pre-alpha.com>
Tycho Sci <tychosci@gmail.com>
Tyler Bindon <martica@martica.org>
Tyler Thrailkill <tylerbthrailkill@gmail.com>
U-NOV2010\eugals
Ulrik Sverdrup <root@localhost>
Ulysse Carion <ulysse@ulysse.io>
User Jyyou <jyyou@plaslab.cs.nctu.edu.tw>
Utkarsh Kukreti <utkarshkukreti@gmail.com>
Uwe Dauernheim <uwe@dauernheim.net>
Vadim Chugunov <vadimcn@gmail.com>
@ -797,6 +867,7 @@ Wade Mealing <wmealing@gmail.com>
Wangshan Lu <wisagan@gmail.com>
WebeWizard <webewizard@gmail.com>
Wendell Smith <wendell.smith@yale.edu>
Wesley Wiser <wwiser@gmail.com>
Will <will@glozer.net>
William Ting <io@williamting.com>
Willson Mock <willson.mock@gmail.com>
@ -817,12 +888,16 @@ Zack Slayton <zack.slayton@gmail.com>
Zbigniew Siciarz <zbigniew@siciarz.net>
Ziad Hatahet <hatahet@gmail.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>
auREAX <mark@xn--hwg34fba.ws>
awlnx <alecweber1994@gmail.com>
aydin.kim <aydin.kim@samsung.com>
b1nd <clint.ryan3@gmail.com>
bachm <Ab@vapor.com>
bcoopers <coopersmithbrian@gmail.com>
blackbeam <aikorsky@gmail.com>
blake2-ppc <ulrik.sverdrup@gmail.com>
bluss <bluss>
@ -835,6 +910,7 @@ comex <comexk@gmail.com>
crhino <piraino.chris@gmail.com>
dan@daramos.com <dan@daramos.com>
darkf <lw9k123@gmail.com>
defuz <defuz.net@gmail.com>
dgoon <dgoon@dgoon.net>
donkopotamus <general@chocolate-fish.com>
eliovir <eliovir@gmail.com>
@ -845,6 +921,7 @@ fort <e@mail.com>
free-Runner <aali07@students.poly.edu>
g3xzh <g3xzh@yahoo.com>
gamazeps <gamaz3ps@gmail.com>
gareth <gareth@gareth-N56VM.(none)>
gentlefolk <cemacken@gmail.com>
gifnksm <makoto.nksm@gmail.com>
hansjorg <hansjorg@gmail.com>
@ -860,6 +937,8 @@ joaoxsouls <joaoxsouls@gmail.com>
jrincayc <jrincayc@users.noreply.github.com>
juxiliary <juxiliary@gmail.com>
jxv <joevargas@hush.com>
kgv <mail@kgv.name>
kjpgit <kjpgit@users.noreply.github.com>
klutzy <klutzytheklutzy@gmail.com>
korenchkin <korenchkin2@gmail.com>
kud1ing <github@kudling.de>
@ -868,6 +947,7 @@ kvark <kvarkus@gmail.com>
kwantam <kwantam@gmail.com>
lpy <pylaurent1314@gmail.com>
lucy <ne.tetewi@gmail.com>
lummax <luogpg@googlemail.com>
lyuts <dioxinu@gmail.com>
m-r-r <raybaudroigm@gmail.com>
madmalik <matthias.tellen@googlemail.com>
@ -882,20 +962,26 @@ mrec <mike.capp@gmail.com>
musitdev <philippe.delrieu@free.fr>
nathan dotz <nathan.dotz@gmail.com>
nham <hamann.nick@gmail.com>
niftynif <nif.ward@gmail.com>
noam <noam@clusterfoo.com>
novalis <novalis@novalis.org>
nsf <no.smile.face@gmail.com>
nwin <nwin@users.noreply.github.com>
oli-obk <github6541940@oli-obk.de>
olivren <o.renaud@gmx.fr>
osa1 <omeragacan@gmail.com>
posixphreak <posixphreak@gmail.com>
qwitwa <qwitwa@gmail.com>
ray glover <ray@rayglover.net>
reedlepee <reedlepee123@gmail.com>
reus <reusee@ymail.com>
rjz <rj@rjzaworski.com>
sevrak <sevrak@rediffmail.com>
sheroze1123 <mss385@cornell.edu>
smenardpw <sebastien@knoglr.com>
sp3d <sp3d@github>
startling <tdixon51793@gmail.com>
tav <tav@espians.com>
th0114nd <th0114nd@gmail.com>
theptrk <patrick.tran06@gmail.com>
thiagopnts <thiagopnts@gmail.com>
@ -911,3 +997,5 @@ xales <xales@naveria.com>
zofrex <zofrex@gmail.com>
zslayton <zack.slayton@gmail.com>
zzmp <zmp@umich.edu>
Łukasz Niemier <lukasz@niemier.pl>
克雷 <geekcraik@users.noreply.github.com>

View File

@ -159,6 +159,13 @@
#
# Admittedly this is a little convoluted.
#
# If you find yourself working on the make infrastructure itself, and trying to
# find the value of a given variable after expansion, you can use:
#
# make print-VARIABLE_NAME
#
# To extract it
#
# </nitty-gritty>
#

98
configure vendored
View File

@ -192,6 +192,7 @@ valopt_core() {
then
local UOP=$(echo $OP | tr '[:lower:]' '[:upper:]' | tr '\-' '\_')
local V="CFG_${UOP}"
local V_PROVIDED="${V}_PROVIDED"
eval $V="$DEFAULT"
for arg in $CFG_CONFIGURE_ARGS
do
@ -199,6 +200,7 @@ valopt_core() {
then
val=$(echo "$arg" | cut -f2 -d=)
eval $V=$val
eval $V_PROVIDED=1
fi
done
if [ "$SAVE" = "save" ]
@ -247,8 +249,10 @@ opt_core() {
if [ $DEFAULT -eq 0 ]
then
FLAG="enable"
DEFAULT_FLAG="disable"
else
FLAG="disable"
DEFAULT_FLAG="enable"
DOC="don't $DOC"
fi
@ -261,11 +265,19 @@ opt_core() {
OP=$(echo $OP | tr 'a-z-' 'A-Z_')
FLAG=$(echo $FLAG | tr 'a-z' 'A-Z')
local V="CFG_${FLAG}_${OP}"
local V_PROVIDED="CFG_${FLAG}_${OP}_PROVIDED"
eval $V=1
eval $V_PROVIDED=1
if [ "$SAVE" = "save" ]
then
putvar $V
fi
elif [ "$arg" = "--${DEFAULT_FLAG}-${OP}" ]
then
OP=$(echo $OP | tr 'a-z-' 'A-Z_')
DEFAULT_FLAG=$(echo $DEFAULT_FLAG | tr 'a-z' 'A-Z')
local V_PROVIDED="CFG_${DEFAULT_FLAG}_${OP}_PROVIDED"
eval $V_PROVIDED=1
fi
done
else
@ -523,31 +535,35 @@ fi
BOOL_OPTIONS=""
VAL_OPTIONS=""
opt debug 0 "debug mode"
opt valgrind 0 "run tests with valgrind (memcheck by default)"
opt helgrind 0 "run tests with helgrind instead of memcheck"
opt valgrind-rpass 1 "run rpass-valgrind tests with valgrind"
opt docs 1 "build standard library documentation"
opt compiler-docs 0 "build compiler documentation"
opt optimize 1 "build optimized rust code"
opt optimize-cxx 1 "build optimized C++ code"
opt optimize-llvm 1 "build optimized LLVM"
opt optimize-tests 1 "build tests with optimizations"
opt libcpp 1 "build with llvm with libc++ instead of libstdc++ when using clang"
opt llvm-assertions 1 "build LLVM with assertions"
opt debug 1 "build with extra debug fun"
opt llvm-assertions 0 "build LLVM with assertions"
opt debug-assertions 0 "build with debugging assertions"
opt fast-make 0 "use .gitmodules as timestamp for submodule deps"
opt ccache 0 "invoke gcc/clang via ccache to reuse object files between builds"
opt local-rust 0 "use an installed rustc rather than downloading a snapshot"
opt llvm-static-stdcpp 0 "statically link to libstdc++ for LLVM"
opt rpath 0 "build rpaths into rustc itself"
opt nightly 0 "build nightly packages"
opt verify-install 1 "verify installed binaries work"
# This is used by the automation to produce single-target nightlies
opt dist-host-only 0 "only install bins for the host architecture"
opt inject-std-version 1 "inject the current compiler version of libstd into programs"
opt jemalloc 1 "build liballoc with jemalloc"
opt llvm-version-check 1 "don't check if the LLVM version is supported, build anyway"
# Optimization and debugging options. These may be overridden by the release channel, etc.
opt_nosave optimize 1 "build optimized rust code"
opt_nosave optimize-cxx 1 "build optimized C++ code"
opt_nosave optimize-llvm 1 "build optimized LLVM"
opt_nosave llvm-assertions 0 "build LLVM with assertions"
opt_nosave debug-assertions 0 "build with debugging assertions"
opt_nosave debuginfo 0 "build with debugger metadata"
opt_nosave debug-jemalloc 0 "build jemalloc with --enable-debug --enable-fill"
valopt localstatedir "/var/lib" "local state directory"
valopt sysconfdir "/etc" "install system configuration files"
@ -557,18 +573,19 @@ valopt llvm-root "" "set LLVM root"
valopt jemalloc-root "" "set directory where libjemalloc_pic.a is located"
valopt build "${DEFAULT_BUILD}" "GNUs ./configure syntax LLVM build triple"
valopt android-cross-path "/opt/ndk_standalone" "Android NDK standalone path"
valopt release-channel "dev" "the name of the release channel to build"
# Many of these are saved below during the "writing configuration" step
# (others are conditionally saved).
opt_nosave manage-submodules 1 "let the build manage the git submodules"
opt_nosave clang 0 "prefer clang to gcc for building the runtime"
opt_nosave jemalloc 1 "build liballoc with jemalloc"
valopt_nosave prefix "/usr/local" "set installation prefix"
valopt_nosave local-rust-root "/usr/local" "set prefix for local rust binary"
valopt_nosave host "${CFG_BUILD}" "GNUs ./configure syntax LLVM host triples"
valopt_nosave target "${CFG_HOST}" "GNUs ./configure syntax LLVM target triples"
valopt_nosave mandir "${CFG_PREFIX}/share/man" "install man pages in PATH"
valopt_nosave release-channel "dev" "the name of the release channel to build"
# Temporarily support old triples until buildbots get updated
CFG_BUILD=$(to_llvm_triple $CFG_BUILD)
@ -612,22 +629,40 @@ fi
step_msg "validating $CFG_SELF args"
validate_opt
# Validate the release channel
# Validate the release channel, and configure options
case "$CFG_RELEASE_CHANNEL" in
(dev | nightly | beta | stable)
nightly )
msg "overriding settings for $CFG_RELEASE_CHANNEL"
CFG_ENABLE_LLVM_ASSERTIONS=1
;;
(*)
dev | beta | stable)
;;
*)
err "release channel must be 'dev', 'nightly', 'beta' or 'stable'"
;;
esac
# Continue supporting the old --enable-nightly flag to transition the bots
# XXX Remove me
if [ ! -z "$CFG_ENABLE_NIGHTLY" ]
then
CFG_RELEASE_CHANNEL=nightly
# Adjust perf and debug options for debug mode
if [ -n "$CFG_ENABLE_DEBUG" ]; then
msg "debug mode enabled, setting performance options"
if [ -z "$CFG_ENABLE_OPTIMIZE_PROVIDED" ]; then
msg "optimization not explicitly enabled, disabling optimization"
CFG_DISABLE_OPTIMIZE=1
CFG_DISABLE_OPTIMIZE_CXX=1
fi
CFG_ENABLE_LLVM_ASSERTIONS=1
CFG_ENABLE_DEBUG_ASSERTIONS=1
CFG_ENABLE_DEBUG_JEMALLOC=1
fi
putvar CFG_RELEASE_CHANNEL
# OK, now write the debugging options
if [ -n "$CFG_DISABLE_OPTIMIZE" ]; then putvar CFG_DISABLE_OPTIMIZE; fi
if [ -n "$CFG_DISABLE_OPTIMIZE_CXX" ]; then putvar CFG_DISABLE_OPTIMIZE_CXX; fi
if [ -n "$CFG_DISABLE_OPTIMIZE_LLVM" ]; then putvar CFG_DISABLE_OPTIMIZE_LLVM; fi
if [ -n "$CFG_ENABLE_LLVM_ASSERTIONS" ]; then putvar CFG_ENABLE_LLVM_ASSERTIONS; fi
if [ -n "$CFG_ENABLE_DEBUG_ASSERTIONS" ]; then putvar CFG_ENABLE_DEBUG_ASSERTIONS; fi
if [ -n "$CFG_ENABLE_DEBUGINFO" ]; then putvar CFG_ENABLE_DEBUGINFO; fi
if [ -n "$CFG_ENABLE_DEBUG_JEMALLOC" ]; then putvar CFG_ENABLE_DEBUG_JEMALLOC; fi
# A magic value that allows the compiler to use unstable features
# during the bootstrap even when doing so would normally be an error
@ -669,7 +704,6 @@ probe CFG_LD ld
probe CFG_VALGRIND valgrind
probe CFG_PERF perf
probe CFG_ISCC iscc
probe CFG_JAVAC javac
probe CFG_ANTLR4 antlr4
probe CFG_GRUN grun
probe CFG_FLEX flex
@ -679,6 +713,14 @@ probe CFG_XELATEX xelatex
probe CFG_GDB gdb
probe CFG_LLDB lldb
# On MacOS X, invoking `javac` pops up a dialog if the JDK is not
# installed. Since `javac` is only used if `antlr4` is available,
# probe for it only in this case.
if [ ! -z "$CFG_ANTLR4" ]
then
probe CFG_JAVAC javac
fi
if [ ! -z "$CFG_GDB" ]
then
# Store GDB's version
@ -775,7 +817,7 @@ if [ $CFG_OSTYPE = unknown-bitrig ]
then
step_msg "on Bitrig, forcing use of clang, disabling jemalloc"
CFG_ENABLE_CLANG=1
CFG_ENABLE_JEMALLOC=0
CFG_DISABLE_JEMALLOC=1
fi
if [ -z "$CFG_ENABLE_CLANG" -a -z "$CFG_GCC" ]
@ -828,6 +870,12 @@ then
putvar CFG_ENABLE_CLANG
fi
# Same with jemalloc. save the setting here.
if [ ! -z "$CFG_DISABLE_JEMALLOC" ]
then
putvar CFG_DISABLE_JEMALLOC
fi
if [ ! -z "$CFG_LLVM_ROOT" -a -z "$CFG_DISABLE_LLVM_VERSION_CHECK" -a -e "$CFG_LLVM_ROOT/bin/llvm-config" ]
then
step_msg "using custom LLVM at $CFG_LLVM_ROOT"
@ -1095,6 +1143,7 @@ do
make_dir $h/test/debuginfo-gdb
make_dir $h/test/debuginfo-lldb
make_dir $h/test/codegen
make_dir $h/test/rustdoc
done
# Configure submodules
@ -1167,7 +1216,7 @@ do
LLVM_DBG_OPTS="--enable-optimized"
LLVM_INST_DIR=$LLVM_BUILD_DIR/Release
fi
if [ ! -z "$CFG_DISABLE_LLVM_ASSERTIONS" ]
if [ -z "$CFG_ENABLE_LLVM_ASSERTIONS" ]
then
LLVM_ASSERTION_OPTS="--disable-assertions"
else
@ -1421,6 +1470,11 @@ move_if_changed config.tmp config.mk
rm -f config.tmp
touch config.stamp
step_msg "complete"
if [ -z "$CFG_ENABLE_DEBUG" ]; then
step_msg "configured in release mode. for development consider --enable-debug"
else
step_msg "complete"
fi
msg "run \`make help\`"
msg

View File

@ -118,42 +118,13 @@ ONLY_RLIB_collections := 1
ONLY_RLIB_unicode := 1
ONLY_RLIB_rustc_bitflags := 1
# Documented-by-default crates
DOC_CRATES := std alloc collections core libc unicode
################################################################################
# You should not need to edit below this line
################################################################################
# On channels where the only usable crate is std, only build documentation for
# std. This keeps distributions small and doesn't clutter up the API docs with
# confusing internal details from the crates behind the facade.
#
# (Disabled while cmr figures out how to change rustdoc to make reexports work
# slightly nicer. Otherwise, all cross-crate links to Vec will go to
# libcollections, breaking them, and [src] links for anything reexported will
# not work.)
#ifeq ($(CFG_RELEASE_CHANNEL),stable)
#DOC_CRATES := std
#else
#ifeq ($(CFG_RELEASE_CHANNEL),beta)
#DOC_CRATES := std
#else
DOC_CRATES := $(filter-out rustc, \
$(filter-out rustc_trans, \
$(filter-out rustc_typeck, \
$(filter-out rustc_borrowck, \
$(filter-out rustc_resolve, \
$(filter-out rustc_driver, \
$(filter-out rustc_privacy, \
$(filter-out rustc_lint, \
$(filter-out log, \
$(filter-out getopts, \
$(filter-out syntax, $(CRATES))))))))))))
#endif
#endif
COMPILER_DOC_CRATES := rustc rustc_trans rustc_borrowck rustc_resolve \
rustc_typeck rustc_driver syntax rustc_privacy \
rustc_lint
# This macro creates some simple definitions for each crate being built, just
# some munging of all of the parameters above.
#

View File

@ -250,18 +250,20 @@ endif
doc/$(1)/:
$$(Q)mkdir -p $$@
$(2) += doc/$(1)/index.html
doc/$(1)/index.html: CFG_COMPILER_HOST_TRIPLE = $(CFG_TARGET)
doc/$(1)/index.html: $$(LIB_DOC_DEP_$(1)) doc/$(1)/
@$$(call E, rustdoc: $$@)
$$(Q)CFG_LLVM_LINKAGE_FILE=$$(LLVM_LINKAGE_PATH_$(CFG_BUILD)) \
$$(RUSTDOC) --cfg dox --cfg stage2 $$<
$$(RUSTDOC) --cfg dox --cfg stage2 $$(RUSTFLAGS_$(1)) $$<
endef
$(foreach crate,$(DOC_CRATES),$(eval $(call DEF_LIB_DOC,$(crate),DOC_TARGETS)))
$(foreach crate,$(CRATES),$(eval $(call DEF_LIB_DOC,$(crate))))
COMPILER_DOC_TARGETS := $(CRATES:%=doc/%/index.html)
ifdef CFG_COMPILER_DOCS
$(foreach crate,$(COMPILER_DOC_CRATES),$(eval $(call DEF_LIB_DOC,$(crate),COMPILER_DOC_TARGETS)))
DOC_TARGETS += $(COMPILER_DOC_TARGETS)
else
DOC_TARGETS += $(DOC_CRATES:%=doc/%/index.html)
endif
ifdef CFG_DISABLE_DOCS

View File

@ -8,12 +8,6 @@
# option. This file may not be copied, modified, or distributed
# except according to those terms.
ifdef CFG_DISABLE_VERIFY_INSTALL
MAYBE_DISABLE_VERIFY=--disable-verify
else
MAYBE_DISABLE_VERIFY=
endif
install:
ifeq (root user, $(USER) $(patsubst %,user,$(SUDO_USER)))
# Build the dist as the original user
@ -22,9 +16,9 @@ else
$(Q)$(MAKE) prepare_install
endif
ifeq ($(CFG_DISABLE_DOCS),)
$(Q)cd tmp/empty_dir && sh ../../tmp/dist/$(DOC_PKG_NAME)-$(CFG_BUILD)/install.sh --prefix="$(DESTDIR)$(CFG_PREFIX)" --libdir="$(DESTDIR)$(CFG_LIBDIR)" --mandir="$(DESTDIR)$(CFG_MANDIR)" "$(MAYBE_DISABLE_VERIFY)"
$(Q)cd tmp/empty_dir && sh ../../tmp/dist/$(DOC_PKG_NAME)-$(CFG_BUILD)/install.sh --prefix="$(DESTDIR)$(CFG_PREFIX)" --libdir="$(DESTDIR)$(CFG_LIBDIR)" --mandir="$(DESTDIR)$(CFG_MANDIR)"
endif
$(Q)cd tmp/empty_dir && sh ../../tmp/dist/$(PKG_NAME)-$(CFG_BUILD)/install.sh --prefix="$(DESTDIR)$(CFG_PREFIX)" --libdir="$(DESTDIR)$(CFG_LIBDIR)" --mandir="$(DESTDIR)$(CFG_MANDIR)" "$(MAYBE_DISABLE_VERIFY)"
$(Q)cd tmp/empty_dir && sh ../../tmp/dist/$(PKG_NAME)-$(CFG_BUILD)/install.sh --prefix="$(DESTDIR)$(CFG_PREFIX)" --libdir="$(DESTDIR)$(CFG_LIBDIR)" --mandir="$(DESTDIR)$(CFG_MANDIR)"
# Remove tmp files because it's a decent amount of disk space
$(Q)rm -R tmp/dist

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'
# NB Make sure it starts with a dot to conform to semver pre-release
# versions (section 9)
CFG_PRERELEASE_VERSION=
CFG_PRERELEASE_VERSION=.3
CFG_FILENAME_EXTRA=4e7c5e5c
@ -126,11 +126,16 @@ endif
CFG_JEMALLOC_FLAGS += $(JEMALLOC_FLAGS)
ifdef CFG_DISABLE_DEBUG
CFG_RUSTC_FLAGS += --cfg ndebug
else
$(info cfg: enabling more debugging (CFG_ENABLE_DEBUG))
ifdef CFG_ENABLE_DEBUG_ASSERTIONS
$(info cfg: enabling debug assertions (CFG_ENABLE_DEBUG_ASSERTIONS))
CFG_RUSTC_FLAGS += --cfg debug -C debug-assertions=on
else
CFG_RUSTC_FLAGS += --cfg ndebug
endif
ifdef CFG_ENABLE_DEBUGINFO
$(info cfg: enabling debuginfo (CFG_ENABLE_DEBUGINFO))
CFG_RUSTC_FLAGS += -g
endif
ifdef SAVE_TEMPS

View File

@ -143,6 +143,10 @@ else ifeq ($(findstring android, $(OSTYPE_$(1))), android)
JEMALLOC_ARGS_$(1) := --disable-tls
endif
ifdef CFG_ENABLE_DEBUG_JEMALLOC
JEMALLOC_ARGS_$(1) += --enable-debug --enable-fill
endif
################################################################################
# jemalloc
################################################################################

View File

@ -22,9 +22,11 @@ $(eval $(call RUST_CRATE,coretest))
DEPS_collectionstest :=
$(eval $(call RUST_CRATE,collectionstest))
TEST_TARGET_CRATES = $(filter-out core unicode,$(TARGET_CRATES)) collectionstest coretest
TEST_TARGET_CRATES = $(filter-out core unicode,$(TARGET_CRATES)) \
collectionstest coretest
TEST_DOC_CRATES = $(DOC_CRATES)
TEST_HOST_CRATES = $(filter-out rustc_typeck rustc_borrowck rustc_resolve rustc_trans rustc_lint,\
TEST_HOST_CRATES = $(filter-out rustc_typeck rustc_borrowck rustc_resolve \
rustc_trans rustc_lint,\
$(HOST_CRATES))
TEST_CRATES = $(TEST_TARGET_CRATES) $(TEST_HOST_CRATES)
@ -304,6 +306,7 @@ check-stage$(1)-T-$(2)-H-$(3)-exec: \
check-stage$(1)-T-$(2)-H-$(3)-rpass-full-exec \
check-stage$(1)-T-$(2)-H-$(3)-cfail-full-exec \
check-stage$(1)-T-$(2)-H-$(3)-rmake-exec \
check-stage$(1)-T-$(2)-H-$(3)-rustdocck-exec \
check-stage$(1)-T-$(2)-H-$(3)-crates-exec \
check-stage$(1)-T-$(2)-H-$(3)-doc-crates-exec \
check-stage$(1)-T-$(2)-H-$(3)-bench-exec \
@ -471,6 +474,7 @@ DEBUGINFO_GDB_RS := $(wildcard $(S)src/test/debuginfo/*.rs)
DEBUGINFO_LLDB_RS := $(wildcard $(S)src/test/debuginfo/*.rs)
CODEGEN_RS := $(wildcard $(S)src/test/codegen/*.rs)
CODEGEN_CC := $(wildcard $(S)src/test/codegen/*.cc)
RUSTDOCCK_RS := $(wildcard $(S)src/test/rustdoc/*.rs)
# perf tests are the same as bench tests only they run under
# a performance monitor.
@ -489,6 +493,7 @@ PRETTY_TESTS := $(PRETTY_RS)
DEBUGINFO_GDB_TESTS := $(DEBUGINFO_GDB_RS)
DEBUGINFO_LLDB_TESTS := $(DEBUGINFO_LLDB_RS)
CODEGEN_TESTS := $(CODEGEN_RS) $(CODEGEN_CC)
RUSTDOCCK_TESTS := $(RUSTDOCCK_RS)
CTEST_SRC_BASE_rpass = run-pass
CTEST_BUILD_BASE_rpass = run-pass
@ -550,6 +555,11 @@ CTEST_BUILD_BASE_codegen = codegen
CTEST_MODE_codegen = codegen
CTEST_RUNTOOL_codegen = $(CTEST_RUNTOOL)
CTEST_SRC_BASE_rustdocck = rustdoc
CTEST_BUILD_BASE_rustdocck = rustdoc
CTEST_MODE_rustdocck = rustdoc
CTEST_RUNTOOL_rustdocck = $(CTEST_RUNTOOL)
# CTEST_DISABLE_$(TEST_GROUP), if set, will cause the test group to be
# disabled and the associated message to be printed as a warning
# during attempts to run those tests.
@ -618,12 +628,14 @@ CTEST_COMMON_ARGS$(1)-T-$(2)-H-$(3) := \
--compile-lib-path $$(HLIB$(1)_H_$(3)) \
--run-lib-path $$(TLIB$(1)_T_$(2)_H_$(3)) \
--rustc-path $$(HBIN$(1)_H_$(3))/rustc$$(X_$(3)) \
--rustdoc-path $$(HBIN$(1)_H_$(3))/rustdoc$$(X_$(3)) \
--clang-path $(if $(CFG_CLANG),$(CFG_CLANG),clang) \
--llvm-bin-path $(CFG_LLVM_INST_DIR_$(CFG_BUILD))/bin \
--aux-base $$(S)src/test/auxiliary/ \
--stage-id stage$(1)-$(2) \
--target $(2) \
--host $(3) \
--python $$(CFG_PYTHON) \
--gdb-version="$(CFG_GDB_VERSION)" \
--lldb-version="$(CFG_LLDB_VERSION)" \
--android-cross-path=$(CFG_ANDROID_CROSS_PATH) \
@ -660,6 +672,9 @@ CTEST_DEPS_debuginfo-lldb_$(1)-T-$(2)-H-$(3) = $$(DEBUGINFO_LLDB_TESTS) \
$(S)src/etc/lldb_batchmode.py \
$(S)src/etc/lldb_rust_formatters.py
CTEST_DEPS_codegen_$(1)-T-$(2)-H-$(3) = $$(CODEGEN_TESTS)
CTEST_DEPS_rustdocck_$(1)-T-$(2)-H-$(3) = $$(RUSTDOCCK_TESTS) \
$$(HBIN$(1)_H_$(3))/rustdoc$$(X_$(3)) \
$(S)src/etc/htmldocck.py
endef
@ -722,7 +737,8 @@ endif
endef
CTEST_NAMES = rpass rpass-valgrind rpass-full cfail-full rfail cfail pfail bench perf debuginfo-gdb debuginfo-lldb codegen
CTEST_NAMES = rpass rpass-valgrind rpass-full cfail-full rfail cfail pfail \
bench perf debuginfo-gdb debuginfo-lldb codegen rustdocck
$(foreach host,$(CFG_HOST), \
$(eval $(foreach target,$(CFG_TARGET), \
@ -890,6 +906,7 @@ TEST_GROUPS = \
bench \
perf \
rmake \
rustdocck \
debuginfo-gdb \
debuginfo-lldb \
codegen \

View File

@ -16,4 +16,7 @@ else
E = echo $(1)
endif
print-%:
@echo $*=$($*)
S := $(CFG_SRC_DIR)

View File

@ -23,7 +23,8 @@ pub enum Mode {
Pretty,
DebugInfoGdb,
DebugInfoLldb,
Codegen
Codegen,
Rustdoc,
}
impl FromStr for Mode {
@ -39,6 +40,7 @@ impl FromStr for Mode {
"debuginfo-lldb" => Ok(DebugInfoLldb),
"debuginfo-gdb" => Ok(DebugInfoGdb),
"codegen" => Ok(Codegen),
"rustdoc" => Ok(Rustdoc),
_ => Err(()),
}
}
@ -56,6 +58,7 @@ impl fmt::Display for Mode {
DebugInfoGdb => "debuginfo-gdb",
DebugInfoLldb => "debuginfo-lldb",
Codegen => "codegen",
Rustdoc => "rustdoc",
}, f)
}
}
@ -71,6 +74,12 @@ pub struct Config {
// The rustc executable
pub rustc_path: PathBuf,
// The rustdoc executable
pub rustdoc_path: PathBuf,
// The python executable
pub python: String,
// The clang executable
pub clang_path: Option<PathBuf>,

View File

@ -12,16 +12,16 @@
#![feature(box_syntax)]
#![feature(collections)]
#![feature(old_io)]
#![feature(rustc_private)]
#![feature(unboxed_closures)]
#![feature(std_misc)]
#![feature(test)]
#![feature(path_ext)]
#![feature(str_char)]
#![feature(libc)]
#![deny(warnings)]
extern crate libc;
extern crate test;
extern crate getopts;
@ -42,6 +42,7 @@ pub mod header;
pub mod runtest;
pub mod common;
pub mod errors;
mod raise_fd_limit;
pub fn main() {
let config = parse_config(env::args().collect());
@ -60,6 +61,8 @@ pub fn parse_config(args: Vec<String> ) -> Config {
vec!(reqopt("", "compile-lib-path", "path to host shared libraries", "PATH"),
reqopt("", "run-lib-path", "path to target shared libraries", "PATH"),
reqopt("", "rustc-path", "path to rustc to use for compiling", "PATH"),
reqopt("", "rustdoc-path", "path to rustdoc to use for compiling", "PATH"),
reqopt("", "python", "path to python to use for doc tests", "PATH"),
optopt("", "clang-path", "path to executable for codegen tests", "PATH"),
optopt("", "valgrind-path", "path to Valgrind executable for Valgrind tests", "PROGRAM"),
optflag("", "force-valgrind", "fail if Valgrind tests cannot be run under Valgrind"),
@ -128,6 +131,8 @@ pub fn parse_config(args: Vec<String> ) -> Config {
compile_lib_path: matches.opt_str("compile-lib-path").unwrap(),
run_lib_path: matches.opt_str("run-lib-path").unwrap(),
rustc_path: opt_path(matches, "rustc-path"),
rustdoc_path: opt_path(matches, "rustdoc-path"),
python: matches.opt_str("python").unwrap(),
clang_path: matches.opt_str("clang-path").map(|s| PathBuf::from(&s)),
valgrind_path: matches.opt_str("valgrind-path"),
force_valgrind: matches.opt_present("force-valgrind"),
@ -168,6 +173,7 @@ pub fn log_config(config: &Config) {
logv(c, format!("compile_lib_path: {:?}", config.compile_lib_path));
logv(c, format!("run_lib_path: {:?}", config.run_lib_path));
logv(c, format!("rustc_path: {:?}", config.rustc_path.display()));
logv(c, format!("rustdoc_path: {:?}", config.rustdoc_path.display()));
logv(c, format!("src_base: {:?}", config.src_base.display()));
logv(c, format!("build_base: {:?}", config.build_base.display()));
logv(c, format!("stage_id: {}", config.stage_id));
@ -240,11 +246,7 @@ pub fn run_tests(config: &Config) {
// sadly osx needs some file descriptor limits raised for running tests in
// parallel (especially when we have lots and lots of child processes).
// For context, see #8904
#[allow(deprecated)]
fn raise_fd_limit() {
std::old_io::test::raise_fd_limit();
}
raise_fd_limit();
unsafe { raise_fd_limit::raise_fd_limit(); }
// Prevent issue #21352 UAC blocking .exe containing 'patch' etc. on Windows
// If #11207 is resolved (adding manifest to .exe) this becomes unnecessary
env::set_var("__COMPAT_LAYER", "RunAsInvoker");
@ -366,7 +368,7 @@ pub fn make_metrics_test_closure(config: &Config, testfile: &Path) -> test::Test
fn extract_gdb_version(full_version_line: Option<String>) -> Option<String> {
match full_version_line {
Some(ref full_version_line)
if full_version_line.trim().len() > 0 => {
if !full_version_line.trim().is_empty() => {
let full_version_line = full_version_line.trim();
// used to be a regex "(^|[^0-9])([0-9]\.[0-9])([^0-9]|$)"
@ -406,7 +408,7 @@ fn extract_lldb_version(full_version_line: Option<String>) -> Option<String> {
match full_version_line {
Some(ref full_version_line)
if full_version_line.trim().len() > 0 => {
if !full_version_line.trim().is_empty() => {
let full_version_line = full_version_line.trim();
for (pos, l) in full_version_line.char_indices() {
@ -424,7 +426,7 @@ fn extract_lldb_version(full_version_line: Option<String>) -> Option<String> {
let vers = full_version_line[pos + 5..].chars().take_while(|c| {
c.is_digit(10)
}).collect::<String>();
if vers.len() > 0 { return Some(vers) }
if !vers.is_empty() { return Some(vers) }
}
println!("Could not extract LLDB version from line '{}'",
full_version_line);

View File

@ -0,0 +1,79 @@
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
/// darwin_fd_limit exists to work around an issue where launchctl on Mac OS X
/// defaults the rlimit maxfiles to 256/unlimited. The default soft limit of 256
/// ends up being far too low for our multithreaded scheduler testing, depending
/// on the number of cores available.
///
/// This fixes issue #7772.
#[cfg(any(target_os = "macos", target_os = "ios"))]
#[allow(non_camel_case_types)]
pub unsafe fn raise_fd_limit() {
use libc;
use std::cmp;
use std::io;
use std::mem::size_of_val;
use std::ptr::null_mut;
type rlim_t = libc::uint64_t;
#[repr(C)]
struct rlimit {
rlim_cur: rlim_t,
rlim_max: rlim_t
}
extern {
// name probably doesn't need to be mut, but the C function doesn't
// specify const
fn sysctl(name: *mut libc::c_int, namelen: libc::c_uint,
oldp: *mut libc::c_void, oldlenp: *mut libc::size_t,
newp: *mut libc::c_void, newlen: libc::size_t) -> libc::c_int;
fn getrlimit(resource: libc::c_int, rlp: *mut rlimit) -> libc::c_int;
fn setrlimit(resource: libc::c_int, rlp: *const rlimit) -> libc::c_int;
}
static CTL_KERN: libc::c_int = 1;
static KERN_MAXFILESPERPROC: libc::c_int = 29;
static RLIMIT_NOFILE: libc::c_int = 8;
// The strategy here is to fetch the current resource limits, read the
// kern.maxfilesperproc sysctl value, and bump the soft resource limit for
// maxfiles up to the sysctl value.
// Fetch the kern.maxfilesperproc value
let mut mib: [libc::c_int; 2] = [CTL_KERN, KERN_MAXFILESPERPROC];
let mut maxfiles: libc::c_int = 0;
let mut size: libc::size_t = size_of_val(&maxfiles) as libc::size_t;
if sysctl(&mut mib[0], 2, &mut maxfiles as *mut _ as *mut _, &mut size,
null_mut(), 0) != 0 {
let err = io::Error::last_os_error();
panic!("raise_fd_limit: error calling sysctl: {}", err);
}
// Fetch the current resource limits
let mut rlim = rlimit{rlim_cur: 0, rlim_max: 0};
if getrlimit(RLIMIT_NOFILE, &mut rlim) != 0 {
let err = io::Error::last_os_error();
panic!("raise_fd_limit: error calling getrlimit: {}", err);
}
// Bump the soft limit to the smaller of kern.maxfilesperproc and the hard
// limit
rlim.rlim_cur = cmp::min(maxfiles as rlim_t, rlim.rlim_max);
// Set our newly-increased resource limit
if setrlimit(RLIMIT_NOFILE, &rlim) != 0 {
let err = io::Error::last_os_error();
panic!("raise_fd_limit: error calling setrlimit: {}", err);
}
}
#[cfg(not(any(target_os = "macos", target_os = "ios")))]
pub unsafe fn raise_fd_limit() {}

View File

@ -12,7 +12,7 @@ use self::TargetLocation::*;
use common::Config;
use common::{CompileFail, ParseFail, Pretty, RunFail, RunPass, RunPassValgrind};
use common::{Codegen, DebugInfoLldb, DebugInfoGdb};
use common::{Codegen, DebugInfoLldb, DebugInfoGdb, Rustdoc};
use errors;
use header::TestProps;
use header;
@ -29,7 +29,6 @@ use std::net::TcpStream;
use std::path::{Path, PathBuf};
use std::process::{Command, Output, ExitStatus};
use std::str;
use std::time::Duration;
use test::MetricMap;
pub fn run(config: Config, testfile: &Path) {
@ -57,15 +56,16 @@ pub fn run_metrics(config: Config, testfile: &Path, mm: &mut MetricMap) {
let props = header::load_props(&testfile);
debug!("loaded props");
match config.mode {
CompileFail => run_cfail_test(&config, &props, &testfile),
ParseFail => run_cfail_test(&config, &props, &testfile),
RunFail => run_rfail_test(&config, &props, &testfile),
RunPass => run_rpass_test(&config, &props, &testfile),
RunPassValgrind => run_valgrind_test(&config, &props, &testfile),
Pretty => run_pretty_test(&config, &props, &testfile),
DebugInfoGdb => run_debuginfo_gdb_test(&config, &props, &testfile),
DebugInfoLldb => run_debuginfo_lldb_test(&config, &props, &testfile),
Codegen => run_codegen_test(&config, &props, &testfile, mm),
CompileFail => run_cfail_test(&config, &props, &testfile),
ParseFail => run_cfail_test(&config, &props, &testfile),
RunFail => run_rfail_test(&config, &props, &testfile),
RunPass => run_rpass_test(&config, &props, &testfile),
RunPassValgrind => run_valgrind_test(&config, &props, &testfile),
Pretty => run_pretty_test(&config, &props, &testfile),
DebugInfoGdb => run_debuginfo_gdb_test(&config, &props, &testfile),
DebugInfoLldb => run_debuginfo_lldb_test(&config, &props, &testfile),
Codegen => run_codegen_test(&config, &props, &testfile, mm),
Rustdoc => run_rustdoc_test(&config, &props, &testfile),
}
}
@ -382,7 +382,7 @@ fn run_debuginfo_gdb_test(config: &Config, props: &TestProps, testfile: &Path) {
// write debugger script
let mut script_str = String::with_capacity(2048);
script_str.push_str("set charset UTF-8\n");
script_str.push_str(&format!("set charset {}\n", charset()));
script_str.push_str(&format!("file {}\n", exe_file.to_str().unwrap()));
script_str.push_str("target remote :5039\n");
script_str.push_str(&format!("set solib-search-path \
@ -451,11 +451,7 @@ fn run_debuginfo_gdb_test(config: &Config, props: &TestProps, testfile: &Path) {
.expect(&format!("failed to exec `{:?}`", config.adb_path));
loop {
//waiting 1 second for gdbserver start
#[allow(deprecated)]
fn sleep() {
::std::old_io::timer::sleep(Duration::milliseconds(1000));
}
sleep();
::std::thread::sleep_ms(1000);
if TcpStream::connect("127.0.0.1:5039").is_ok() {
break
}
@ -516,8 +512,7 @@ fn run_debuginfo_gdb_test(config: &Config, props: &TestProps, testfile: &Path) {
.to_string();
// write debugger script
let mut script_str = String::with_capacity(2048);
script_str.push_str("set charset UTF-8\n");
script_str.push_str(&format!("set charset {}\n", charset()));
script_str.push_str("show version\n");
match config.gdb_version {
@ -726,32 +721,37 @@ fn run_debuginfo_lldb_test(config: &Config, props: &TestProps, testfile: &Path)
-> ProcRes {
// Prepare the lldb_batchmode which executes the debugger script
let lldb_script_path = rust_src_root.join("src/etc/lldb_batchmode.py");
cmd2procres(config,
test_executable,
Command::new(&config.python)
.arg(&lldb_script_path)
.arg(test_executable)
.arg(debugger_script)
.env("PYTHONPATH",
config.lldb_python_dir.as_ref().unwrap()))
}
}
let mut cmd = Command::new("python");
cmd.arg(&lldb_script_path)
.arg(test_executable)
.arg(debugger_script)
.env("PYTHONPATH", config.lldb_python_dir.as_ref().unwrap());
fn cmd2procres(config: &Config, test_executable: &Path, cmd: &mut Command)
-> ProcRes {
let (status, out, err) = match cmd.output() {
Ok(Output { status, stdout, stderr }) => {
(status,
String::from_utf8(stdout).unwrap(),
String::from_utf8(stderr).unwrap())
},
Err(e) => {
fatal(&format!("Failed to setup Python process for \
LLDB script: {}", e))
}
};
let (status, out, err) = match cmd.output() {
Ok(Output { status, stdout, stderr }) => {
(status,
String::from_utf8(stdout).unwrap(),
String::from_utf8(stderr).unwrap())
},
Err(e) => {
fatal(&format!("Failed to setup Python process for \
LLDB script: {}", e))
}
};
dump_output(config, test_executable, &out, &err);
return ProcRes {
status: Status::Normal(status),
stdout: out,
stderr: err,
cmdline: format!("{:?}", cmd)
};
dump_output(config, test_executable, &out, &err);
ProcRes {
status: Status::Normal(status),
stdout: out,
stderr: err,
cmdline: format!("{:?}", cmd)
}
}
@ -864,7 +864,7 @@ fn check_debugger_output(debugger_run_result: &ProcRes, check_lines: &[String])
}
first = false;
}
if !failed && rest.len() == 0 {
if !failed && rest.is_empty() {
i += 1;
}
if i == num_check_lines {
@ -1158,6 +1158,26 @@ fn compile_test_(config: &Config, props: &TestProps,
compose_and_run_compiler(config, props, testfile, args, None)
}
fn document(config: &Config, props: &TestProps,
testfile: &Path, extra_args: &[String]) -> (ProcRes, PathBuf) {
let aux_dir = aux_output_dir_name(config, testfile);
let out_dir = output_base_name(config, testfile);
let _ = fs::remove_dir_all(&out_dir);
ensure_dir(&out_dir);
let mut args = vec!["-L".to_string(),
aux_dir.to_str().unwrap().to_string(),
"-o".to_string(),
out_dir.to_str().unwrap().to_string(),
testfile.to_str().unwrap().to_string()];
args.extend(extra_args.iter().cloned());
args.extend(split_maybe_args(&props.compile_flags).into_iter());
let args = ProcArgs {
prog: config.rustdoc_path.to_str().unwrap().to_string(),
args: args,
};
(compose_and_run_compiler(config, props, testfile, args, None), out_dir)
}
fn exec_compiled_test(config: &Config, props: &TestProps,
testfile: &Path) -> ProcRes {
@ -1182,20 +1202,17 @@ fn exec_compiled_test(config: &Config, props: &TestProps,
}
}
fn compose_and_run_compiler(
config: &Config,
props: &TestProps,
testfile: &Path,
args: ProcArgs,
input: Option<String>) -> ProcRes {
fn compose_and_run_compiler(config: &Config, props: &TestProps,
testfile: &Path, args: ProcArgs,
input: Option<String>) -> ProcRes {
if !props.aux_builds.is_empty() {
ensure_dir(&aux_output_dir_name(config, testfile));
}
let aux_dir = aux_output_dir_name(config, testfile);
// FIXME (#9639): This needs to handle non-utf8 paths
let extra_link_args = vec!("-L".to_string(), aux_dir.to_str().unwrap().to_string());
let extra_link_args = vec!["-L".to_string(),
aux_dir.to_str().unwrap().to_string()];
for rel_ab in &props.aux_builds {
let abs_ab = config.aux_base.join(rel_ab);
@ -1331,8 +1348,8 @@ fn make_exe_name(config: &Config, testfile: &Path) -> PathBuf {
f
}
fn make_run_args(config: &Config, props: &TestProps, testfile: &Path) ->
ProcArgs {
fn make_run_args(config: &Config, props: &TestProps, testfile: &Path)
-> ProcArgs {
// If we've got another tool to run under (valgrind),
// then split apart its command
let mut args = split_maybe_args(&config.runtool);
@ -1645,7 +1662,7 @@ fn _arm_push_aux_shared_library(config: &Config, testfile: &Path) {
// codegen tests (vs. clang)
fn append_suffix_to_stem(p: &Path, suffix: &str) -> PathBuf {
if suffix.len() == 0 {
if suffix.is_empty() {
p.to_path_buf()
} else {
let mut stem = p.file_stem().unwrap().to_os_string();
@ -1790,3 +1807,29 @@ fn run_codegen_test(config: &Config, props: &TestProps,
(base_lines as f64) / (clang_lines as f64),
0.001);
}
fn charset() -> &'static str {
if cfg!(any(target_os = "bitrig", target_os = "freebsd")) {
"auto"
} else {
"UTF-8"
}
}
fn run_rustdoc_test(config: &Config, props: &TestProps, testfile: &Path) {
let (proc_res, out_dir) = document(config, props, testfile, &[]);
if !proc_res.status.success() {
fatal_proc_rec("rustdoc failed!", &proc_res);
}
let root = find_rust_src_root(config).unwrap();
let res = cmd2procres(config,
testfile,
Command::new(&config.python)
.arg(root.join("src/etc/htmldocck.py"))
.arg(out_dir)
.arg(testfile));
if !res.status.success() {
fatal_proc_rec("htmldocck failed!", &res);
}
}

View File

@ -56,7 +56,7 @@ Types which are [`Sync`][sync] are thread-safe when multiple shared
references to them are used concurrently. Types which are not `Sync` are not
thread-safe, and thus when used in a global require unsafe code to use.
[sync]: core/kinds/trait.Sync.html
[sync]: core/marker/trait.Sync.html
### If mutable static items that implement `Sync` are safe, why is taking &mut SHARABLE unsafe?
@ -139,7 +139,7 @@ and explicitly calling the `clone` method. Making user-defined copy operators
explicit surfaces the underlying complexity, forcing the developer to opt-in
to potentially expensive operations.
[copy]: core/kinds/trait.Copy.html
[copy]: core/marker/trait.Copy.html
[clone]: core/clone/trait.Clone.html
## No move constructors
@ -163,13 +163,18 @@ This is to make the language easier to parse for humans, especially in the face
of higher-order functions. `fn foo<T>(f: fn(int): int, fn(T): U): U` is not
particularly easy to read.
## `let` is used to introduce variables
## Why is `let` used to introduce variables?
`let` not only defines variables, but can do pattern matching. One can also
redeclare immutable variables with `let`. This is useful to avoid unnecessary
`mut` annotations. An interesting historical note is that Rust comes,
syntactically, most closely from ML, which also uses `let` to introduce
bindings.
Instead of the term "variable", we use "variable bindings". The
simplest way for creating a binding is by using the `let` syntax.
Other ways include `if let`, `while let`, and `match`. Bindings also
exist in function argument positions.
Bindings always happen in pattern matching positions, and it's also Rust's way
to declare mutability. One can also re-declare mutability of a binding in
pattern matching. This is useful to avoid unnecessary `mut` annotations. An
interesting historical note is that Rust comes, syntactically, most closely
from ML, which also uses `let` to introduce bindings.
See also [a long thread][alt] on renaming `let mut` to `var`.

View File

@ -42,10 +42,7 @@ Let the fact that this is an easily countable number be a warning.
## Does it run on Windows?
Yes. All development happens in lockstep on all 3 target platforms (using MinGW, not Cygwin). Note that the Windows implementation currently has some limitations; in particular, the 64-bit build is [not fully supported yet][win64], and all executables created by rustc [depend on libgcc DLL at runtime][libgcc].
[win64]: https://github.com/rust-lang/rust/issues/1237
[libgcc]: https://github.com/rust-lang/rust/issues/11782
Yes. All development happens in lockstep on all 3 target platforms (using MinGW, not Cygwin).
## Is it OO? How do I do this thing I normally do in an OO language?

View File

@ -15,6 +15,12 @@ Rust, its syntax, and its concepts. Upon completing the book, you'll be an
intermediate Rust developer, and will have a good grasp of the fundamental
ideas behind Rust.
[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
series of small examples.
[rbe]: http://rustbyexample.com/
# Community & Getting Help
If you need help with something, or just want to talk about Rust with others,
@ -76,17 +82,3 @@ We have [API documentation for the entire standard
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
something if you know its name.
# External documentation
*Note: While these are great resources for learning Rust, they may track a
particular version of Rust that is likely not exactly the same as that for
which this documentation was generated.*
* [Rust by Example] - Short examples of common tasks in Rust (tracks the master
branch).
* [Rust for Rubyists] - The first community tutorial for Rust. Tracks the last
stable release. Not just for Ruby programmers.
[Rust by Example]: http://rustbyexample.com/
[Rust for Rubyists]: http://www.rustforrubyists.com/

View File

@ -1,590 +1,5 @@
% A 30-minute Introduction to Rust
Rust is a modern systems programming language focusing on safety and speed. It
accomplishes these goals by being memory safe without using garbage collection.
This introduction is now deprecated. Please see [the introduction to the book][intro].
This introduction will give you a rough idea of what Rust is like, eliding many
details. It does not require prior experience with systems programming, but you
may find the syntax easier if you've used a "curly brace" programming language
before, like C or JavaScript. The concepts are more important than the syntax,
so don't worry if you don't get every last detail: you can read [The
Rust Programming Language](book/index.html) to get a more complete explanation.
Because this is about high-level concepts, you don't need to actually install
Rust to follow along. If you'd like to anyway, check out [the
homepage](http://rust-lang.org) for explanation.
To show off Rust, let's talk about how easy it is to get started with Rust.
Then, we'll talk about Rust's most interesting feature, *ownership*, and
then discuss how it makes concurrency easier to reason about. Finally,
we'll talk about how Rust breaks down the perceived dichotomy between speed
and safety.
# Tools
Getting started on a new Rust project is incredibly easy, thanks to Rust's
package manager, [Cargo](http://crates.io).
To start a new project with Cargo, use `cargo new`:
```{bash}
$ cargo new hello_world --bin
```
We're passing `--bin` because we're making a binary program: if we
were making a library, we'd leave it off.
Let's check out what Cargo has generated for us:
```{bash}
$ cd hello_world
$ tree .
.
├── Cargo.toml
└── src
└── main.rs
1 directory, 2 files
```
This is all we need to get started. First, let's check out `Cargo.toml`:
```{toml}
[package]
name = "hello_world"
version = "0.0.1"
authors = ["Your Name <you@example.com>"]
```
This is called a *manifest*, and it contains all of the metadata that Cargo
needs to compile your project.
Here's what's in `src/main.rs`:
```{rust}
fn main() {
println!("Hello, world!");
}
```
Cargo generated a "Hello World" for us. We'll talk more about the syntax here
later, but that's what Rust code looks like! Let's compile and run it:
```{bash}
$ cargo run
Compiling hello_world v0.0.1 (file:///Users/you/src/hello_world)
Running `target/hello_world`
Hello, world!
```
Using an external dependency in Rust is incredibly easy. You add a line to
your `Cargo.toml`:
```{toml}
[package]
name = "hello_world"
version = "0.0.1"
authors = ["Your Name <someone@example.com>"]
[dependencies.semver]
git = "https://github.com/rust-lang/semver.git"
```
You added the `semver` library, which parses version numbers and compares them
according to the [SemVer specification](http://semver.org/).
Now, you can pull in that library using `extern crate` in
`main.rs`.
```{rust,ignore}
extern crate semver;
use semver::Version;
fn main() {
assert!(Version::parse("1.2.3") == Ok(Version {
major: 1u64,
minor: 2u64,
patch: 3u64,
pre: vec!(),
build: vec!(),
}));
println!("Versions compared successfully!");
}
```
Again, we'll discuss the exact details of all of this syntax soon. For now,
let's compile and run it:
```{bash}
$ cargo run
Updating git repository `https://github.com/rust-lang/semver.git`
Compiling semver v0.0.1 (https://github.com/rust-lang/semver.git#bf739419)
Compiling hello_world v0.0.1 (file:///home/you/projects/hello_world)
Running `target/hello_world`
Versions compared successfully!
```
Because we only specified a repository without a version, if someone else were
to try out our project at a later date, when `semver` was updated, they would
get a different, possibly incompatible version. To solve this problem, Cargo
produces a file, `Cargo.lock`, which records the versions of any dependencies.
This gives us repeatable builds.
There is a lot more here, and this is a whirlwind tour, but you should feel
right at home if you've used tools like [Bundler](http://bundler.io/),
[npm](https://www.npmjs.org/), or [pip](https://pip.pypa.io/en/latest/).
There's no `Makefile`s or endless `autotools` output here. (Rust's tooling does
[play nice with external libraries written in those
tools](http://doc.crates.io/build-script.html), if you need to.)
Enough about tools, let's talk code!
# Ownership
Rust's defining feature is "memory safety without garbage collection". Let's
take a moment to talk about what that means. *Memory safety* means that the
programming language eliminates certain kinds of bugs, such as [buffer
overflows](http://en.wikipedia.org/wiki/Buffer_overflow) and [dangling
pointers](http://en.wikipedia.org/wiki/Dangling_pointer). These problems occur
when you have unrestricted access to memory. As an example, here's some Ruby
code:
```{ruby}
v = []
v.push("Hello")
x = v[0]
v.push("world")
puts x
```
We make an array, `v`, and then call `push` on it. `push` is a method which
adds an element to the end of an array.
Next, we make a new variable, `x`, that's equal to the first element of
the array. Simple, but this is where the "bug" will appear.
Let's keep going. We then call `push` again, pushing "world" onto the
end of the array. `v` now is `["Hello", "world"]`.
Finally, we print `x` with the `puts` method. This prints "Hello."
All good? Let's go over a similar, but subtly different example, in C++:
```{cpp}
#include<iostream>
#include<vector>
#include<string>
int main() {
std::vector<std::string> v;
v.push_back("Hello");
std::string& x = v[0];
v.push_back("world");
std::cout << x;
}
```
It's a little more verbose due to the static typing, but it's almost the same
thing. We make a `std::vector` of `std::string`s, we call `push_back` (same as
`push`) on it, take a reference to the first element of the vector, call
`push_back` again, and then print out the reference.
There's two big differences here: one, they're not _exactly_ the same thing,
and two...
```{bash}
$ g++ hello.cpp -Wall -Werror
$ ./a.out
Segmentation fault (core dumped)
```
A crash! (Note that this is actually system-dependent. Because referring to an
invalid reference is undefined behavior, the compiler can do anything,
including the right thing!) Even though we compiled with flags to give us as
many warnings as possible, and to treat those warnings as errors, we got no
errors. When we ran the program, it crashed.
Why does this happen? When we append to an array, its length changes. Since
its length changes, we may need to allocate more memory. In Ruby, this happens
as well, we just don't think about it very often. So why does the C++ version
segfault when we allocate more memory?
The answer is that in the C++ version, `x` is a *reference* to the memory
location where the first element of the array is stored. But in Ruby, `x` is a
standalone value, not connected to the underlying array at all. Let's dig into
the details for a moment. Your program has access to memory, provided to it by
the operating system. Each location in memory has an address. So when we make
our vector, `v`, it's stored in a memory location somewhere:
| location | name | value |
|----------|------|-------|
| 0x30 | v | |
(Address numbers made up, and in hexadecimal. Those of you with deep C++
knowledge, there are some simplifications going on here, like the lack of an
allocated length for the vector. This is an introduction.)
When we push our first string onto the array, we allocate some memory,
and `v` refers to it:
| location | name | value |
|----------|------|----------|
| 0x30 | v | 0x18 |
| 0x18 | | "Hello" |
We then make a reference to that first element. A reference is a variable
that points to a memory location, so its value is the memory location of
the `"Hello"` string:
| location | name | value |
|----------|------|----------|
| 0x30 | v | 0x18 |
| 0x18 | | "Hello" |
| 0x14 | x | 0x18 |
When we push `"world"` onto the vector with `push_back`, there's no room:
we only allocated one element. So, we need to allocate two elements,
copy the `"Hello"` string over, and update the reference. Like this:
| location | name | value |
|----------|------|----------|
| 0x30 | v | 0x08 |
| 0x18 | | GARBAGE |
| 0x14 | x | 0x18 |
| 0x08 | | "Hello" |
| 0x04 | | "world" |
Note that `v` now refers to the new list, which has two elements. It's all
good. But our `x` didn't get updated! It still points at the old location,
which isn't valid anymore. In fact, [the documentation for `push_back` mentions
this](http://en.cppreference.com/w/cpp/container/vector/push_back):
> If the new `size()` is greater than `capacity()` then all iterators and
> references (including the past-the-end iterator) are invalidated.
Finding where these iterators and references are is a difficult problem, and
even in this simple case, `g++` can't help us here. While the bug is obvious in
this case, in real code, it can be difficult to track down the source of the
error.
Before we talk about this solution, why didn't our Ruby code have this problem?
The semantics are a little more complicated, and explaining Ruby's internals is
out of the scope of a guide to Rust. But in a nutshell, Ruby's garbage
collector keeps track of references, and makes sure that everything works as
you might expect. This comes at an efficiency cost, and the internals are more
complex. If you'd really like to dig into the details, [this
article](http://patshaughnessy.net/2012/1/18/seeing-double-how-ruby-shares-string-values)
can give you more information.
Garbage collection is a valid approach to memory safety, but Rust chooses a
different path. Let's examine what the Rust version of this looks like:
```{rust,ignore}
fn main() {
let mut v = vec![];
v.push("Hello");
let x = &v[0];
v.push("world");
println!("{}", x);
}
```
This looks like a bit of both: fewer type annotations, but we do create new
variables with `let`. The method name is `push`, some other stuff is different,
but it's pretty close. So what happens when we compile this code? Does Rust
print `"Hello"`, or does Rust crash?
Neither. It refuses to compile:
```bash
$ cargo run
Compiling hello_world v0.0.1 (file:///Users/you/src/hello_world)
main.rs:8:5: 8:6 error: cannot borrow `v` as mutable because it is also borrowed as immutable
main.rs:8 v.push("world");
^
main.rs:6:14: 6:15 note: previous borrow of `v` occurs here; the immutable borrow prevents subsequent moves or mutable borrows of `v` until the borrow ends
main.rs:6 let x = &v[0];
^
main.rs:11:2: 11:2 note: previous borrow ends here
main.rs:1 fn main() {
...
main.rs:11 }
^
error: aborting due to previous error
```
When we try to mutate the array by `push`ing it the second time, Rust throws
an error. It says that we "cannot borrow v as mutable because it is also
borrowed as immutable." What does it mean by "borrowed"?
In Rust, the type system encodes the notion of *ownership*. The variable `v`
is an *owner* of the vector. When we make a reference to `v`, we let that
variable (in this case, `x`) *borrow* it for a while. Just like if you own a
book, and you lend it to me, I'm borrowing the book.
So, when I try to modify the vector with the second call to `push`, I need
to be owning it. But `x` is borrowing it. You can't modify something that
you've lent to someone. And so Rust throws an error.
So how do we fix this problem? Well, we can make a copy of the element:
```{rust}
fn main() {
let mut v = vec![];
v.push("Hello");
let x = v[0].clone();
v.push("world");
println!("{}", x);
}
```
Note the addition of `clone()`. This creates a copy of the element, leaving
the original untouched. Now, we no longer have two references to the same
memory, and so the compiler is happy. Let's give that a try:
```{bash}
$ cargo run
Compiling hello_world v0.0.1 (file:///Users/you/src/hello_world)
Running `target/hello_world`
Hello
```
Same result. Now, making a copy can be inefficient, so this solution may not be
acceptable. There are other ways to get around this problem, but this is a toy
example, and because we're in an introduction, we'll leave that for later.
The point is, the Rust compiler and its notion of ownership has saved us from a
bug that would crash the program. We've achieved safety, at compile time,
without needing to rely on a garbage collector to handle our memory.
# Concurrency
Rust's ownership model can help in other ways, as well. For example, take
concurrency. Concurrency is a big topic, and an important one for any modern
programming language. Let's take a look at how ownership can help you write
safe concurrent programs.
Here's an example of a concurrent Rust program:
```{rust}
use std::thread;
fn main() {
let guards: Vec<_> = (0..10).map(|_| {
thread::scoped(|| {
println!("Hello, world!");
})
}).collect();
}
```
This program creates ten threads, which all print `Hello, world!`. The `scoped`
function takes one argument, a closure, indicated by the double bars `||`. This
closure is executed in a new thread created by `scoped`. The method is called
`scoped` because it returns a 'join guard', which will automatically join the
child thread when it goes out of scope. Because we `collect` these guards into
a `Vec<T>`, and that vector goes out of scope at the end of our program, our
program will wait for every thread to finish before finishing.
One common form of problem in concurrent programs is a *data race*.
This occurs when two different threads attempt to access the same
location in memory in a non-synchronized way, where at least one of
them is a write. If one thread is attempting to read, and one thread
is attempting to write, you cannot be sure that your data will not be
corrupted. Note the first half of that requirement: two threads that
attempt to access the same location in memory. Rust's ownership model
can track which pointers own which memory locations, which solves this
problem.
Let's see an example. This Rust code will not compile:
```{rust,ignore}
use std::thread;
fn main() {
let mut numbers = vec![1, 2, 3];
let guards: Vec<_> = (0..3).map(|i| {
thread::scoped(move || {
numbers[i] += 1;
println!("numbers[{}] is {}", i, numbers[i]);
})
}).collect();
}
```
It gives us this error:
```text
7:25: 10:6 error: cannot move out of captured outer variable in an `FnMut` closure
7 thread::scoped(move || {
8 numbers[i] += 1;
9 println!("numbers[{}] is {}", i, numbers[i]);
10 })
error: aborting due to previous error
```
This is a little confusing because there are two closures here: the one passed
to `map`, and the one passed to `thread::scoped`. In this case, the closure for
`thread::scoped` is attempting to reference `numbers`, a `Vec<i32>`. This
closure is a `FnOnce` closure, as thats what `thread::scoped` takes as an
argument. `FnOnce` closures take ownership of their environment. Thats fine,
but theres one detail: because of `map`, were going to make three of these
closures. And since all three try to take ownership of `numbers`, that would be
a problem. Thats what it means by cannot move out of captured outer
variable: our `thread::scoped` closure wants to take ownership, and it cant,
because the closure for `map` wont let it.
What to do here? Rust has two types that helps us: `Arc<T>` and `Mutex<T>`.
*Arc* stands for "atomically reference counted". In other words, an Arc will
keep track of the number of references to something, and not free the
associated resource until the count is zero. The *atomic* portion refers to an
Arc's usage of concurrency primitives to atomically update the count, making it
safe across threads. If we use an Arc, we can have our three references. But,
an Arc does not allow mutable borrows of the data it holds, and we want to
modify what we're sharing. In this case, we can use a `Mutex<T>` inside of our
Arc. A Mutex will synchronize our accesses, so that we can ensure that our
mutation doesn't cause a data race.
Here's what using an Arc with a Mutex looks like:
```{rust}
use std::thread;
use std::sync::{Arc,Mutex};
fn main() {
let numbers = Arc::new(Mutex::new(vec![1, 2, 3]));
let guards: Vec<_> = (0..3).map(|i| {
let number = numbers.clone();
thread::scoped(move || {
let mut array = number.lock().unwrap();
array[i] += 1;
println!("numbers[{}] is {}", i, array[i]);
})
}).collect();
}
```
We first have to `use` the appropriate library, and then we wrap our vector in
an Arc with the call to `Arc::new()`. Inside of the loop, we make a new
reference to the Arc with the `clone()` method. This will increment the
reference count. When each new `numbers` variable binding goes out of scope, it
will decrement the count. The `lock()` call will return us a reference to the
value inside the Mutex, and block any other calls to `lock()` until said
reference goes out of scope.
We can compile and run this program without error, and in fact, see the
non-deterministic aspect:
```{shell}
$ cargo run
Compiling hello_world v0.0.1 (file:///Users/you/src/hello_world)
Running `target/hello_world`
numbers[1] is 3
numbers[0] is 2
numbers[2] is 4
$ cargo run
Running `target/hello_world`
numbers[2] is 4
numbers[1] is 3
numbers[0] is 2
```
Each time, we can get a slightly different output because the threads are not
guaranteed to run in any set order. If you get the same order every time it is
because each of these threads are very small and complete too fast for their
indeterminate behavior to surface.
The important part here is that the Rust compiler was able to use ownership to
give us assurance _at compile time_ that we weren't doing something incorrect
with regards to concurrency. In order to share ownership, we were forced to be
explicit and use a mechanism to ensure that it would be properly handled.
# Safety _and_ Speed
Safety and speed are always presented as a continuum. At one end of the spectrum,
you have maximum speed, but no safety. On the other end, you have absolute safety
with no speed. Rust seeks to break out of this paradigm by introducing safety at
compile time, ensuring that you haven't done anything wrong, while compiling to
the same low-level code you'd expect without the safety.
As an example, Rust's ownership system is _entirely_ at compile time. The
safety check that makes this an error about moved values:
```{rust,ignore}
use std::thread;
fn main() {
let numbers = vec![1, 2, 3];
let guards: Vec<_> = (0..3).map(|i| {
thread::scoped(move || {
println!("{}", numbers[i]);
})
}).collect();
}
```
carries no runtime penalty. And while some of Rust's safety features do have
a run-time cost, there's often a way to write your code in such a way that
you can remove it. As an example, this is a poor way to iterate through
a vector:
```{rust}
let vec = vec![1, 2, 3];
for i in 0..vec.len() {
println!("{}", vec[i]);
}
```
The reason is that the access of `vec[i]` does bounds checking, to ensure
that we don't try to access an invalid index. However, we can remove this
while retaining safety. The answer is iterators:
```{rust}
let vec = vec![1, 2, 3];
for x in &vec {
println!("{}", x);
}
```
This version uses an iterator that yields each element of the vector in turn.
Because we have a reference to the element, rather than the whole vector itself,
there's no array access bounds to check.
# Learning More
I hope that this taste of Rust has given you an idea if Rust is the right
language for you. We talked about Rust's tooling, how encoding ownership into
the type system helps you find bugs, how Rust can help you write correct
concurrent code, and how you don't have to pay a speed cost for much of this
safety.
To continue your Rustic education, read [The Rust Programming
Language](book/index.html) for a more in-depth exploration of Rust's syntax and
concepts.
[intro]: book/README.html

View File

@ -3788,7 +3788,7 @@ its type parameters are types:
```ignore
fn map<A: Clone, B: Clone>(f: |A| -> B, xs: &[A]) -> Vec<B> {
if xs.len() == 0 {
if xs.is_empty() {
return vec![];
}
let first: B = f(xs[0].clone());

View File

@ -1,10 +1,10 @@
% Unit testing
Unit tests should live in a `test` submodule at the bottom of the module they
test. Mark the `test` submodule with `#[cfg(test)]` so it is only compiled when
Unit tests should live in a `tests` submodule at the bottom of the module they
test. Mark the `tests` submodule with `#[cfg(test)]` so it is only compiled when
testing.
The `test` module should contain:
The `tests` module should contain:
* Imports needed only for testing.
* Functions marked with `#[test]` striving for full coverage of the parent module's
@ -17,7 +17,7 @@ For example:
// Excerpt from std::str
#[cfg(test)]
mod test {
mod tests {
#[test]
fn test_eq() {
assert!((eq(&"".to_owned(), &"".to_owned())));

View File

@ -1,39 +1,192 @@
% The Rust Programming Language
Welcome! This book will teach you about [the Rust Programming
Language](http://www.rust-lang.org/). Rust is a modern systems programming
language focusing on safety and speed. It accomplishes these goals by being
memory safe without using garbage collection.
Welcome! This book will teach you about the [Rust Programming Language][rust].
Rust is a systems programming language focused on three goals: safety, speed,
and concurrency. It maintains these goals without having a garbage collector,
making it a useful language for a number of use cases other languages arent
good at: embedding in other languages, programs with specific space and time
requirements, and writing low-level code, like device drivers and operating
systems. It improves on current languages targeting this space by having a
number of compile-time safety checks that produce no runtime overhead, while
eliminating all data races. Rust also aims to achieve zero-cost abstrations
even though some of these abstractions feel like those of a high-level
language. Even then, Rust still allows precise control like a low-level
language would.
"The Rust Programming Language" is split into three sections, which you can
navigate through the menu on the left.
[rust]: http://rust-lang.org
<h2 class="section-header"><a href="basic.html">Basics</a></h2>
“The Rust Programming Language” is split into seven sections. This introduction
is the first. After this:
This section is a linear introduction to the basic syntax and semantics of
Rust. It has individual sections on each part of Rust's syntax.
* [Getting started][gs] - Set up your computer for Rust development.
* [Learn Rust][lr] - Learn Rust programming through small projects.
* [Effective Rust][er] - Higher-level concepts for writing excellent Rust code.
* [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.
* [Glossary][gl] - A reference of terms used in the book.
After reading "Basics," you will have a good foundation to learn more about
Rust, and can write very simple programs.
[gs]: getting-started.html
[lr]: learn-rust.html
[er]: effective-rust.html
[ss]: syntax-and-semantics.html
[nr]: nightly-rust.html
[gl]: glossary.html
<h2 class="section-header"><a href="intermediate.html">Intermediate</a></h2>
After reading this introduction, youll want to dive into either Learn Rust
or Syntax and Semantics, depending on your preference: Learn Rust if you
want to dive in with a project, or Syntax and Semantics if you prefer to
start small, and learn a single concept thoroughly before moving onto the next.
Copious cross-linking connects these parts together.
This section contains individual chapters, which are self-contained. They focus
on specific topics, and can be read in any order.
## A brief introduction to Rust
After reading "Intermediate," you will have a solid understanding of Rust,
and will be able to understand most Rust code and write more complex programs.
Is Rust a language you might be interested in? Lets examine a few small code
samples to show off a few of its strengths.
<h2 class="section-header"><a href="advanced.html">Advanced</a></h2>
The main concept that makes Rust unique is called ownership. Consider this
small example:
In a similar fashion to "Intermediate," this section is full of individual,
deep-dive chapters, which stand alone and can be read in any order. These
chapters focus on the most complex features,
```rust
fn main() {
let mut x = vec!["Hello", "world"];
}
```
<h2 class="section-header"><a href="unstable.html">Unstable</a></h2>
This program makes a [variable binding][var] named `x`. The value of this
binding is a `Vec<T>`, a vector, that we create through a [macro][macro]
defined in the standard library. This macro is called `vec`, and we invoke
macros with a `!`. This follows a general principle of Rust: make things
explicit. Macros can do significantly more complicated things than function
calls, and so theyre visually distinct. The `!` also helps with parsing,
making tooling easier to write, which is also important.
In a similar fashion to "Intermediate," this section is full of individual,
deep-dive chapters, which stand alone and can be read in any order.
We used `mut` to make `x` mutable: bindings are immutable by default in Rust.
Well be mutating this vector later in the example.
This chapter contains things that are only available on the nightly channel of
Rust.
Its also worth noting that we didnt need a type annotation here: while Rust
is statically typed, we didnt need to explicitly annotate the type. Rust has
type inference to balance out the power of static typing with the verbosity of
annotating types.
Rust prefers stack allocation to heap allocation: `x` is placed directly on the
stack. However, the `Vec<T>` type allocates space for the elements of the
vector on the heap. If youre not familiar with this distinction, you can
ignore it for now, or check out [The Stack and the Heap][heap]. As a systems
programming language, Rust gives you the ability to control how your memory is
allocated, but when were getting started, its less of a big deal.
[var]: variable-bindings.html
[macro]: macros.html
[heap]: the-stack-and-the-heap.html
Earlier, we mentioned that ownership is the key new concept in Rust. In Rust
parlance, `x` is said to own the vector. This means that when `x` goes out of
scope, the vectors memory will be de-allocated. This is done deterministically
by the Rust compiler, rather than through a mechanism such as a garbage
collector. In other words, in Rust, you dont call functions like `malloc` and
`free` yourself: the compiler statically determines when you need to allocate
or deallocate memory, and inserts those calls itself. To err is to be human,
but compilers never forget.
Lets add another line to our example:
```rust
fn main() {
let mut x = vec!["Hello", "world"];
let y = &x[0];
}
```
Weve introduced another binding, `y`. In this case, `y` is a reference to
the first element of the vector. Rusts references are similar to pointers in
other languages, but with additional compile-time safety checks. References
interact with the ownership system by [borrowing][borrowing] what they point
to, rather than owning it. The difference is, when the reference goes out of
scope, it will not deallocate the underlying memory. If it did, wed
de-allocate twice, which is bad!
[borrowing]: references-and-borrowing.html
Lets add a third line. It looks innocent enough, but causes a compiler error:
```rust,ignore
fn main() {
let mut x = vec!["Hello", "world"];
let y = &x[0];
x.push("foo");
}
```
`push` is a method on vectors that appends another element to the end of the
vector. When we try to compile this program, we get an error:
```text
error: cannot borrow `x` as mutable because it is also borrowed as immutable
x.push(4);
^
note: previous borrow of `x` occurs here; the immutable borrow prevents
subsequent moves or mutable borrows of `x` until the borrow ends
let y = &x[0];
^
note: previous borrow ends here
fn main() {
}
^
```
Whew! The Rust compiler gives quite detailed errors at times, and this is one
of those times. As the error explains, while we made our binding mutable, we
still cannot call `push`. This is because we already have a reference to an
element of the vector, `y`. Mutating something while another reference exists
is dangerous, because we may invalidate the reference. In this specific case,
when we create the vector, we may have only allocated space for three elements.
Adding a fourth would mean allocating a new chunk of memory for all those elements,
copying the old values over, and updating the internal pointer to that memory.
That all works just fine. The problem is that `y` wouldnt get updated, and so
wed have a dangling pointer. Thats bad. Any use of `y` would be an error in
this case, and so the compiler has caught this for us.
So how do we solve this problem? There are two approaches we can take. The first
is making a copy rather than using a reference:
```rust
fn main() {
let mut x = vec!["Hello", "world"];
let y = x[0].clone();
x.push("foo");
}
```
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
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.
[move]: move-semantics.html
If we truly want a reference, we need the other option: ensure that our reference
goes out of scope before we try to do the mutation. That looks like this:
```rust
fn main() {
let mut x = vec!["Hello", "world"];
{
let y = &x[0];
}
x.push("foo");
}
```
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.
This concept of ownership isnt just good for preventing danging pointers, but an
entire set of related problems, like iterator invalidation, concurrency, and more.

View File

@ -1,42 +1,62 @@
# Summary
* [The Basics](basic.md)
* [Getting Started](getting-started.md)
* [Installing Rust](installing-rust.md)
* [Hello, world!](hello-world.md)
* [Hello, Cargo!](hello-cargo.md)
* [Variable Bindings](variable-bindings.md)
* [If](if.md)
* [Functions](functions.md)
* [Comments](comments.md)
* [Compound Data Types](compound-data-types.md)
* [Match](match.md)
* [Looping](looping.md)
* [Strings](strings.md)
* [Arrays, Vectors, and Slices](arrays-vectors-and-slices.md)
* [Intermediate Rust](intermediate.md)
* [Crates and Modules](crates-and-modules.md)
* [Learn Rust](learn-rust.md)
* [Effective Rust](effective-rust.md)
* [The Stack and the Heap](the-stack-and-the-heap.md)
* [Debug and Display](debug-and-display.md)
* [Testing](testing.md)
* [Pointers](pointers.md)
* [Ownership](ownership.md)
* [More Strings](more-strings.md)
* [Patterns](patterns.md)
* [Method Syntax](method-syntax.md)
* [Associated Types](associated-types.md)
* [Closures](closures.md)
* [Documentation](documentation.md)
* [Iterators](iterators.md)
* [Generics](generics.md)
* [Traits](traits.md)
* [Static and Dynamic Dispatch](static-and-dynamic-dispatch.md)
* [Macros](macros.md)
* [Concurrency](concurrency.md)
* [Error Handling](error-handling.md)
* [Documentation](documentation.md)
* [Advanced Topics](advanced.md)
* [FFI](ffi.md)
* [Unsafe Code](unsafe.md)
* [Advanced Macros](advanced-macros.md)
* [Unstable Rust](unstable.md)
* [Compiler Plugins](plugins.md)
* [Deref coercions](deref-coercions.md)
* [Syntax and Semantics](syntax-and-semantics.md)
* [Variable Bindings](variable-bindings.md)
* [Functions](functions.md)
* [Primitive Types](primitive-types.md)
* [Comments](comments.md)
* [if](if.md)
* [for loops](for-loops.md)
* [while loops](while-loops.md)
* [Ownership](ownership.md)
* [References and Borrowing](references-and-borrowing.md)
* [Lifetimes](lifetimes.md)
* [Mutability](mutability.md)
* [Move semantics](move-semantics.md)
* [Enums](enums.md)
* [Match](match.md)
* [Patterns](patterns.md)
* [Structs](structs.md)
* [Method Syntax](method-syntax.md)
* [Drop](drop.md)
* [Vectors](vectors.md)
* [Strings](strings.md)
* [Traits](traits.md)
* [Operators and Overloading](operators-and-overloading.md)
* [Generics](generics.md)
* [if let](if-let.md)
* [Trait Objects](trait-objects.md)
* [Closures](closures.md)
* [Universal Function Call Syntax](ufcs.md)
* [Crates and Modules](crates-and-modules.md)
* [`static`](static.md)
* [`const`](const.md)
* [Tuple Structs](tuple-structs.md)
* [Attributes](attributes.md)
* [Conditional Compilation](conditional-compilation.md)
* [`type` aliases](type-aliases.md)
* [Casting between types](casting-between-types.md)
* [Associated Types](associated-types.md)
* [Unsized Types](unsized-types.md)
* [Macros](macros.md)
* [`unsafe` Code](unsafe-code.md)
* [Nightly Rust](nightly-rust.md)
* [Compiler Plugins](compiler-plugins.md)
* [Inline Assembly](inline-assembly.md)
* [No stdlib](no-stdlib.md)
* [Intrinsics](intrinsics.md)
@ -44,5 +64,6 @@
* [Link args](link-args.md)
* [Benchmark Tests](benchmark-tests.md)
* [Box Syntax and Patterns](box-syntax-and-patterns.md)
* [Conclusion](conclusion.md)
* [Slice Patterns](slice-patterns.md)
* [Glossary](glossary.md)
* [Academic Research](academic-research.md)

View File

@ -0,0 +1,46 @@
% Academic Research
An incomplete list of papers that have had some influence in Rust.
Recommended for inspiration and a better understanding of Rust's background.
### Type system
* [Region based memory management in Cyclone](http://209.68.42.137/ucsd-pages/Courses/cse227.w03/handouts/cyclone-regions.pdf)
* [Safe manual memory management in Cyclone](http://www.cs.umd.edu/projects/PL/cyclone/scp.pdf)
* [Typeclasses: making ad-hoc polymorphism less ad hoc](http://www.ps.uni-sb.de/courses/typen-ws99/class.ps.gz)
* [Macros that work together](https://www.cs.utah.edu/plt/publications/jfp12-draft-fcdf.pdf)
* [Traits: composable units of behavior](http://scg.unibe.ch/archive/papers/Scha03aTraits.pdf)
* [Alias burying](http://www.cs.uwm.edu/faculty/boyland/papers/unique-preprint.ps) - We tried something similar and abandoned it.
* [External uniqueness is unique enough](http://www.computingscience.nl/research/techreps/repo/CS-2002/2002-048.pdf)
* [Uniqueness and Reference Immutability for Safe Parallelism](https://research.microsoft.com/pubs/170528/msr-tr-2012-79.pdf)
* [Region Based Memory Management](http://www.cs.ucla.edu/~palsberg/tba/papers/tofte-talpin-iandc97.pdf)
### Concurrency
* [Singularity: rethinking the software stack](https://research.microsoft.com/pubs/69431/osr2007_rethinkingsoftwarestack.pdf)
* [Language support for fast and reliable message passing in singularity OS](https://research.microsoft.com/pubs/67482/singsharp.pdf)
* [Scheduling multithreaded computations by work stealing](http://supertech.csail.mit.edu/papers/steal.pdf)
* [Thread scheduling for multiprogramming multiprocessors](http://www.eecis.udel.edu/%7Ecavazos/cisc879-spring2008/papers/arora98thread.pdf)
* [The data locality of work stealing](http://www.aladdin.cs.cmu.edu/papers/pdfs/y2000/locality_spaa00.pdf)
* [Dynamic circular work stealing deque](http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.170.1097&rep=rep1&type=pdf) - The Chase/Lev deque
* [Work-first and help-first scheduling policies for async-finish task parallelism](http://www.cs.rice.edu/%7Eyguo/pubs/PID824943.pdf) - More general than fully-strict work stealing
* [A Java fork/join calamity](http://www.coopsoft.com/ar/CalamityArticle.html) - critique of Java's fork/join library, particularly its application of work stealing to non-strict computation
* [Scheduling techniques for concurrent systems](http://www.ece.rutgers.edu/%7Eparashar/Classes/ece572-papers/05/ps-ousterhout.pdf)
* [Contention aware scheduling](http://www.blagodurov.net/files/a8-blagodurov.pdf)
* [Balanced work stealing for time-sharing multicores](http://www.cse.ohio-state.edu/hpcs/WWW/HTML/publications/papers/TR-12-1.pdf)
* [Three layer cake](http://www.upcrc.illinois.edu/workshops/paraplop10/papers/paraplop10_submission_8.pdf)
* [Non-blocking steal-half work queues](http://www.cs.bgu.ac.il/%7Ehendlerd/papers/p280-hendler.pdf)
* [Reagents: expressing and composing fine-grained concurrency](http://www.mpi-sws.org/~turon/reagents.pdf)
* [Algorithms for scalable synchronization of shared-memory multiprocessors](https://www.cs.rochester.edu/u/scott/papers/1991_TOCS_synch.pdf)
### Others
* [Crash-only software](https://www.usenix.org/legacy/events/hotos03/tech/full_papers/candea/candea.pdf)
* [Composing High-Performance Memory Allocators](http://people.cs.umass.edu/~emery/pubs/berger-pldi2001.pdf)
* [Reconsidering Custom Memory Allocation](http://people.cs.umass.edu/~emery/pubs/berger-oopsla2002.pdf)
### Papers *about* Rust
* [GPU programming in Rust](http://www.cs.indiana.edu/~eholk/papers/hips2013.pdf)
* [Parallel closures: a new twist on an old idea](https://www.usenix.org/conference/hotpar12/parallel-closures-new-twist-old-idea) - not exactly about rust, but by nmatsakis

View File

@ -1,242 +0,0 @@
% Advanced macros
This chapter picks up where the [introductory macro chapter](macros.html) left
off.
# Syntactic requirements
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
tools that process code. It also has a few consequences for the design of
Rust's macro system.
[ast]: glossary.html#abstract-syntax-tree
One consequence is that Rust must determine, when it parses a macro invocation,
whether the macro stands in for
* zero or more items,
* zero or more methods,
* an expression,
* a statement, or
* a pattern.
A macro invocation within a block could stand for some items, or for an
expression / statement. Rust uses a simple rule to resolve this ambiguity. A
macro invocation that stands for items must be either
* delimited by curly braces, e.g. `foo! { ... }`, or
* terminated by a semicolon, e.g. `foo!(...);`
Another consequence of pre-expansion parsing is that the macro invocation must
consist of valid Rust tokens. Furthermore, parentheses, brackets, and braces
must be balanced within a macro invocation. For example, `foo!([)` is
forbidden. This allows Rust to know where the macro invocation ends.
More formally, the macro invocation body must be a sequence of *token trees*.
A token tree is defined recursively as either
* a sequence of token trees surrounded by matching `()`, `[]`, or `{}`, or
* any other single token.
Within a matcher, each metavariable has a *fragment specifier*, identifying
which syntactic form it matches.
* `ident`: an identifier. Examples: `x`; `foo`.
* `path`: a qualified name. Example: `T::SpecialA`.
* `expr`: an expression. Examples: `2 + 2`; `if true then { 1 } else { 2 }`; `f(42)`.
* `ty`: a type. Examples: `i32`; `Vec<(char, String)>`; `&T`.
* `pat`: a pattern. Examples: `Some(t)`; `(17, 'a')`; `_`.
* `stmt`: a single statement. Example: `let x = 3`.
* `block`: a brace-delimited sequence of statements. Example:
`{ log(error, "hi"); return 12; }`.
* `item`: an [item][]. Examples: `fn foo() { }`; `struct Bar;`.
* `meta`: a "meta item", as found in attributes. Example: `cfg(target_os = "windows")`.
* `tt`: a single token tree.
There are additional rules regarding the next token after a metavariable:
* `expr` variables must be followed by one of: `=> , ;`
* `ty` and `path` variables must be followed by one of: `=> , : = > as`
* `pat` variables must be followed by one of: `=> , =`
* Other variables may be followed by any token.
These rules provide some flexibility for Rust's syntax to evolve without
breaking existing macros.
The macro system does not deal with parse ambiguity at all. For example, the
grammar `$($t:ty)* $e:expr` will always fail to parse, because the parser would
be forced to choose between parsing `$t` and parsing `$e`. Changing the
invocation syntax to put a distinctive token in front can solve the problem. In
this case, you can write `$(T $t:ty)* E $e:exp`.
[item]: ../reference.html#items
# Scoping and macro import/export
Macros are expanded at an early stage in compilation, before name resolution.
One downside is that scoping works differently for macros, compared to other
constructs in the language.
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
is visible to any subsequent code in the same module, which includes the body
of any subsequent child `mod` items.
A macro defined within the body of a single `fn`, or anywhere else not at
module scope, is visible only within that item.
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`
then the macros will be visible in the grandparent after the parent's `mod`
item, and so forth.
The `macro_use` attribute can also appear on `extern crate`. In this context
it controls which macros are loaded from the external crate, e.g.
```rust,ignore
#[macro_use(foo, bar)]
extern crate baz;
```
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
defined with the `#[macro_export]` attribute may be loaded.
To load a crate's macros *without* linking it into the output, use `#[no_link]`
as well.
An example:
```rust
macro_rules! m1 { () => (()) }
// visible here: m1
mod foo {
// visible here: m1
#[macro_export]
macro_rules! m2 { () => (()) }
// visible here: m1, m2
}
// visible here: m1
macro_rules! m3 { () => (()) }
// visible here: m1, m3
#[macro_use]
mod bar {
// visible here: m1, m3
macro_rules! m4 { () => (()) }
// visible here: m1, m3, m4
}
// visible here: m1, m3, m4
# fn main() { }
```
When this library is loaded with `#[macro_use] extern crate`, only `m2` will
be imported.
The Rust Reference has a [listing of macro-related
attributes](../reference.html#macro--and-plugin-related-attributes).
# The variable `$crate`
A further difficulty occurs when a macro is used in multiple crates. Say that
`mylib` defines
```rust
pub fn increment(x: u32) -> u32 {
x + 1
}
#[macro_export]
macro_rules! inc_a {
($x:expr) => ( ::increment($x) )
}
#[macro_export]
macro_rules! inc_b {
($x:expr) => ( ::mylib::increment($x) )
}
# fn main() { }
```
`inc_a` only works within `mylib`, while `inc_b` only works outside the
library. Furthermore, `inc_b` will break if the user imports `mylib` under
another name.
Rust does not (yet) have a hygiene system for crate references, but it does
provide a simple workaround for this problem. Within a macro imported from a
crate named `foo`, the special macro variable `$crate` will expand to `::foo`.
By contrast, when a macro is defined and then used in the same crate, `$crate`
will expand to nothing. This means we can write
```rust
#[macro_export]
macro_rules! inc {
($x:expr) => ( $crate::increment($x) )
}
# fn main() { }
```
to define a single macro that works both inside and outside our library. The
function name will expand to either `::increment` or `::mylib::increment`.
To keep this system simple and correct, `#[macro_use] extern crate ...` may
only appear at the root of your crate, not inside `mod`. This ensures that
`$crate` is a single identifier.
# The deep end
The introductory chapter mentioned recursive macros, but it did not give the
full story. Recursive macros are useful for another reason: Each recursive
invocation gives you another opportunity to pattern-match the macro's
arguments.
As an extreme example, it is possible, though hardly advisable, to implement
the [Bitwise Cyclic Tag](http://esolangs.org/wiki/Bitwise_Cyclic_Tag) automaton
within Rust's macro system.
```rust
macro_rules! bct {
// cmd 0: d ... => ...
(0, $($ps:tt),* ; $_d:tt)
=> (bct!($($ps),*, 0 ; ));
(0, $($ps:tt),* ; $_d:tt, $($ds:tt),*)
=> (bct!($($ps),*, 0 ; $($ds),*));
// cmd 1p: 1 ... => 1 ... p
(1, $p:tt, $($ps:tt),* ; 1)
=> (bct!($($ps),*, 1, $p ; 1, $p));
(1, $p:tt, $($ps:tt),* ; 1, $($ds:tt),*)
=> (bct!($($ps),*, 1, $p ; 1, $($ds),*, $p));
// cmd 1p: 0 ... => 0 ...
(1, $p:tt, $($ps:tt),* ; $($ds:tt),*)
=> (bct!($($ps),*, 1, $p ; $($ds),*));
// halt on empty data string
( $($ps:tt),* ; )
=> (());
}
```
Exercise: use macros to reduce duplication in the above definition of the
`bct!` macro.
# Procedural macros
If Rust's macro system can't do what you need, you may want to write a
[compiler plugin](plugins.html) instead. Compared to `macro_rules!`
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
flexibility of running arbitrary Rust code within the compiler. Syntax
extension plugins are sometimes called *procedural macros* for this reason.

View File

@ -1,8 +0,0 @@
% Advanced
In a similar fashion to "Intermediate," this section is full of individual,
deep-dive chapters, which stand alone and can be read in any order. These
chapters focus on the most complex features, as well as some things that
are only available in upcoming versions of Rust.
After reading "Advanced," you'll be a Rust expert!

View File

@ -1,102 +0,0 @@
% Arrays, Vectors, and Slices
Like many programming languages, Rust has list types to represent a sequence of
things. The most basic is the *array*, a fixed-size list of elements of the
same type. By default, arrays are immutable.
```{rust}
let a = [1, 2, 3]; // a: [i32; 3]
let mut m = [1, 2, 3]; // mut m: [i32; 3]
```
There's a shorthand for initializing each element of an array to the same
value. In this example, each element of `a` will be initialized to `0`:
```{rust}
let a = [0; 20]; // a: [i32; 20]
```
Arrays have type `[T; N]`. We'll talk about this `T` notation later, when we
cover generics.
You can get the number of elements in an array `a` with `a.len()`, and use
`a.iter()` to iterate over them with a for loop. This code will print each
number in order:
```{rust}
let a = [1, 2, 3];
println!("a has {} elements", a.len());
for e in a.iter() {
println!("{}", e);
}
```
You can access a particular element of an array with *subscript notation*:
```{rust}
let names = ["Graydon", "Brian", "Niko"]; // names: [&str; 3]
println!("The second name is: {}", names[1]);
```
Subscripts start at zero, like in most programming languages, so the first name
is `names[0]` and the second name is `names[1]`. The above example prints
`The second name is: Brian`. If you try to use a subscript that is not in the
array, you will get an error: array access is bounds-checked at run-time. Such
errant access is the source of many bugs in other systems programming
languages.
A *vector* is a dynamic or "growable" array, implemented as the standard
library type [`Vec<T>`](../std/vec/) (we'll talk about what the `<T>` means
later). Vectors always allocate their data on the heap. Vectors are to slices
what `String` is to `&str`. You can create them with the `vec!` macro:
```{rust}
let v = vec![1, 2, 3]; // v: Vec<i32>
```
(Notice that unlike the `println!` macro we've used in the past, we use square
brackets `[]` with `vec!`. Rust allows you to use either in either situation,
this is just convention.)
There's an alternate form of `vec!` for repeating an initial value:
```
let v = vec![0; 10]; // ten zeroes
```
You can get the length of, iterate over, and subscript vectors just like
arrays. In addition, (mutable) vectors can grow automatically:
```{rust}
let mut nums = vec![1, 2, 3]; // mut nums: Vec<i32>
nums.push(4);
println!("The length of nums is now {}", nums.len()); // Prints 4
```
Vectors have many more useful methods.
A *slice* is a reference to (or "view" into) an array. They are useful for
allowing safe, efficient access to a portion of an array without copying. For
example, you might want to reference just one line of a file read into memory.
By nature, a slice is not created directly, but from an existing variable.
Slices have a length, can be mutable or not, and in many ways behave like
arrays:
```{rust}
let a = [0, 1, 2, 3, 4];
let middle = &a[1..4]; // A slice of a: just the elements 1, 2, and 3
for e in middle.iter() {
println!("{}", e); // Prints 1, 2, 3
}
```
You can also take a slice of a vector, `String`, or `&str`, because they are
backed by arrays. Slices have type `&[T]`, which we'll talk about when we cover
generics.
We have now learned all of the most basic Rust concepts.

View File

@ -198,5 +198,5 @@ let obj = Box::new(graph) as Box<Graph<N=Node, E=Edge>>;
```
The `N=Node` syntax allows us to provide a concrete type, `Node`, for the `N`
type parameter. Same with `E=Edge`. If we didnt proide this constraint, we
type parameter. Same with `E=Edge`. If we didnt provide this constraint, we
couldnt be sure which `impl` to match this trait object to.

View File

@ -0,0 +1,3 @@
% Attributes
Coming Soon!

View File

@ -1,7 +0,0 @@
% Basics
This section is a linear introduction to the basic syntax and semantics of
Rust. It has individual sections on each part of Rust's syntax.
After reading "Basics," you will have a good foundation to learn more about
Rust, and can write very simple programs.

View File

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

View File

@ -0,0 +1,3 @@
% Casting Between Types
Coming Soon

View File

@ -54,7 +54,7 @@ The second is that the syntax is similar, but a bit different. I've added spaces
here to make them look a little closer:
```rust
fn plus_one_v1 ( x: i32 ) -> i32 { x + 1 }
fn plus_one_v1 (x: i32 ) -> i32 { x + 1 }
let plus_one_v2 = |x: i32 | -> i32 { x + 1 };
let plus_one_v3 = |x: i32 | x + 1 ;
```
@ -175,9 +175,6 @@ we called `add_num`, it mutated the underlying value, as we'd expect. We also
needed to declare `add_num` as `mut` too, because were mutating its
environment.
We also had to declare `add_num` as mut, since we will be modifying its
environment.
If we change to a `move` closure, it's different:
```rust
@ -208,11 +205,11 @@ you tons of control over what your code does, and closures are no different.
Rust's 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
the [traits chapter][traits] before this one, as well as the chapter on [static
and dynamic dispatch][dispatch], which talks about trait objects.
the [traits chapter][traits] before this one, as well as the chapter on [trait
objects][trait-objects].
[traits]: traits.html
[dispatch]: static-and-dynamic-dispatch.html
[trait-objects]: trait-objects.html
Got all that? Good.

View File

@ -1,47 +1,45 @@
% Comments
Now that we have some functions, it's a good idea to learn about comments.
Now that we have some functions, its a good idea to learn about comments.
Comments are notes that you leave to other programmers to help explain things
about your code. The compiler mostly ignores them.
Rust has two kinds of comments that you should care about: *line comments*
and *doc comments*.
```{rust}
// Line comments are anything after '//' and extend to the end of the line.
```rust
// Line comments are anything after // and extend to the end of the line.
let x = 5; // this is also a line comment.
// If you have a long explanation for something, you can put line comments next
// to each other. Put a space between the // and your comment so that it's
// to each other. Put a space between the // and your comment so that its
// more readable.
```
The other kind of comment is a doc comment. Doc comments use `///` instead of
`//`, and support Markdown notation inside:
```{rust}
/// `hello` is a function that prints a greeting that is personalized based on
/// the name given.
///
/// # Arguments
///
/// * `name` - The name of the person you'd like to greet.
```rust
/// Adds one to the number given.
///
/// # Examples
///
/// ```rust
/// let name = "Steve";
/// hello(name); // prints "Hello, Steve!"
/// ```
fn hello(name: &str) {
println!("Hello, {}!", name);
/// let five = 5;
///
/// assert_eq!(6, add_one(5));
/// ```
fn add_one(x: i32) -> i32 {
x + 1
}
```
When writing doc comments, adding sections for any arguments, return values,
and providing some examples of usage is very, very helpful. Don't worry about
the `&str`, we'll get to it soon.
When writing doc comments, providing some examples of usage is very, very
helpful. Youll notice weve used a new macro here: `assert_eq!`. This compares
two values, and `panic!`s if theyre not equal to each other. Its very helpful
in documentation. Theres another macro, `assert!`, which `panic!`s if the
value passed to it is `false`.
You can use the [`rustdoc`](documentation.html) tool to generate HTML documentation
from these doc comments.
from these doc comments, and also to run the code examples as tests!

View File

@ -1,364 +0,0 @@
% Compound Data Types
Rust, like many programming languages, has a number of different data types
that are built-in. You've already done some simple work with integers and
strings, but next, let's talk about some more complicated ways of storing data.
## Tuples
The first compound data type we're going to talk about is called the *tuple*.
A tuple is an ordered list of fixed size. Like this:
```rust
let x = (1, "hello");
```
The parentheses and commas form this two-length tuple. Here's the same code, but
with the type annotated:
```rust
let x: (i32, &str) = (1, "hello");
```
As you can see, the type of a tuple looks just like the tuple, but with each
position having a type name rather than the value. Careful readers will also
note that tuples are heterogeneous: we have an `i32` and a `&str` in this tuple.
You have briefly seen `&str` used as a type before, and we'll discuss the
details of strings later. In systems programming languages, strings are a bit
more complex than in other languages. For now, just read `&str` as a *string
slice*, and we'll learn more soon.
You can access the fields in a tuple through a *destructuring let*. Here's
an example:
```rust
let (x, y, z) = (1, 2, 3);
println!("x is {}", x);
```
Remember before 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
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,"
or "breaks up," the tuple, and assigns the bits to three bindings.
This pattern is very powerful, and we'll see it repeated more later.
There are also a few things you can do with a tuple as a whole, without
destructuring. 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.
```rust
let mut x = (1, 2); // x: (i32, i32)
let y = (2, 3); // y: (i32, i32)
x = y;
```
You can also check for equality with `==`. Again, this will only compile if the
tuples have the same type.
```rust
let x = (1, 2, 3);
let y = (2, 2, 4);
if x == y {
println!("yes");
} else {
println!("no");
}
```
This will print `no`, because some of the values aren't equal.
Note that the order of the values is considered when checking for equality,
so the following example will also print `no`.
```rust
let x = (1, 2, 3);
let y = (2, 1, 3);
if x == y {
println!("yes");
} else {
println!("no");
}
```
One other use of tuples is to return multiple values from a function:
```rust
fn next_two(x: i32) -> (i32, i32) { (x + 1, x + 2) }
fn main() {
let (x, y) = next_two(5);
println!("x, y = {}, {}", x, y);
}
```
Even though Rust functions can only return one value, a tuple *is* one value,
that happens to be made up of more than one value. You can also see in this
example how you can destructure a pattern returned by a function, as well.
Tuples are a very simple data structure, and so are not often what you want.
Let's move on to their bigger sibling, structs.
## Structs
A struct is another form of a *record type*, just like a tuple. There's a
difference: structs give each element that they contain a name, called a
*field* or a *member*. Check it out:
```rust
struct Point {
x: i32,
y: i32,
}
fn main() {
let origin = Point { x: 0, y: 0 }; // origin: Point
println!("The origin is at ({}, {})", origin.x, origin.y);
}
```
There's a lot going on here, so let's break it down. We declare a struct with
the `struct` keyword, and then with a name. By convention, structs begin with a
capital letter and are also camel cased: `PointInSpace`, not `Point_In_Space`.
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
in the original declaration.
Finally, because fields have names, we can access the field through dot
notation: `origin.x`.
The values in structs are immutable by default, like other bindings in Rust.
Use `mut` to make them mutable:
```{rust}
struct Point {
x: i32,
y: i32,
}
fn main() {
let mut point = Point { x: 0, y: 0 };
point.x = 5;
println!("The point is at ({}, {})", point.x, point.y);
}
```
This will print `The point is at (5, 0)`.
## Tuple Structs and Newtypes
Rust has another data type that's like a hybrid between a tuple and a struct,
called a *tuple struct*. Tuple structs do have a name, but their fields don't:
```{rust}
struct Color(i32, i32, i32);
struct Point(i32, i32, i32);
```
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 that's 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`, as we discussed previously in 'tuples.' In this case, the
`let Inches(integer_length)` assigns `10` to `integer_length`.
## Enums
Finally, Rust has a "sum type", an *enum*. Enums are an incredibly useful
feature of Rust, and are used throughout the standard library. An `enum` is
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
enum Character {
Digit(i32),
Other,
}
```
Most normal types are allowed as the variant components of an `enum`. Here are
some examples:
```rust
struct Empty;
struct Color(i32, i32, i32);
struct Length(i32);
struct Status { Health: i32, Mana: i32, Attack: i32, Defense: i32 }
struct HeightDatabase(Vec<i32>);
```
You see that, depending on its type, an `enum` variant may or may not hold data.
In `Character`, for instance, `Digit` gives a meaningful name for an `i32`
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
equality operators (`==`, `!=`), have no ordering (`<`, `>=`, etc.), and do not
support other binary operations such as `*` and `+`. As such, the following code
is invalid for the example `Character` type:
```{rust,ignore}
// These assignments both succeed
let ten = Character::Digit(10);
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
`use` keyword. Here's an example of how it is used:
```{rust}
use std::cmp::Ordering;
fn cmp(a: i32, b: i32) -> Ordering {
if a < b { Ordering::Less }
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.
[arity]: ./glossary.html#arity
[match]: ./match.html
[generics]: ./generics.html

View File

@ -1,11 +0,0 @@
% Conclusion
We covered a lot of ground here. When you've mastered everything in this Guide,
you will have a firm grasp of Rust development. There's a whole lot more
out there, though, we've just covered the surface. There's tons of topics that
you can dig deeper into, e.g. by reading the API documentation of the
[standard library](http://doc.rust-lang.org/std/), by discovering solutions for
common problems on [Rust by Example](http://rustbyexample.com/), or by browsing
crates written by the community on [crates.io](https://crates.io/).
Happy hacking!

View File

@ -56,70 +56,34 @@ place!
## Threads
Rust's standard library provides a library for 'threads', which allow you to
Rust's standard library provides a library for threads, which allow you to
run Rust code in parallel. Here's a basic example of using `std::thread`:
```
use std::thread;
fn main() {
thread::scoped(|| {
println!("Hello from a thread!");
});
}
```
The `thread::scoped()` method accepts a closure, which is executed in a new
thread. It's called `scoped` because this thread returns a join guard:
```
use std::thread;
fn main() {
let guard = thread::scoped(|| {
println!("Hello from a thread!");
});
// guard goes out of scope here
}
```
When `guard` goes out of scope, it will block execution until the thread is
finished. If we didn't want this behaviour, we could use `thread::spawn()`:
```
# #![feature(old_io, std_misc)]
use std::thread;
use std::old_io::timer;
use std::time::Duration;
fn main() {
thread::spawn(|| {
println!("Hello from a thread!");
});
timer::sleep(Duration::milliseconds(50));
}
```
We need to `sleep` here because when `main()` ends, it kills all of the
running threads.
The `thread::spawn()` method accepts a closure, which is executed in a
new thread. It returns a handle to the thread, that can be used to
wait for the child thread to finish and extract its result:
[`scoped`](std/thread/struct.Builder.html#method.scoped) has an interesting
type signature:
```text
fn scoped<'a, T, F>(self, f: F) -> JoinGuard<'a, T>
where T: Send + 'a,
F: FnOnce() -> T,
F: Send + 'a
```
use std::thread;
Specifically, `F`, the closure that we pass to execute in the new thread. It
has two restrictions: It must be a `FnOnce` from `()` to `T`. Using `FnOnce`
allows the closure to take ownership of any data it mentions from the parent
thread. The other restriction is that `F` must be `Send`. We aren't allowed to
transfer this ownership unless the type thinks that's okay.
fn main() {
let handle = thread::spawn(|| {
"Hello from a thread!"
});
println!("{}", handle.join().unwrap());
}
```
Many languages have the ability to execute threads, but it's wildly unsafe.
There are entire books about how to prevent errors that occur from shared
@ -147,10 +111,7 @@ As an example, here is a Rust program that would have a data race in many
languages. It will not compile:
```ignore
# #![feature(old_io, std_misc)]
use std::thread;
use std::old_io::timer;
use std::time::Duration;
fn main() {
let mut data = vec![1u32, 2, 3];
@ -161,14 +122,14 @@ fn main() {
});
}
timer::sleep(Duration::milliseconds(50));
thread::sleep_ms(50);
}
```
This gives us an error:
```text
12:17 error: capture of moved value: `data`
8:17 error: capture of moved value: `data`
data[i] += 1;
^~~~
```
@ -187,10 +148,7 @@ only one person at a time can mutate what's inside. For that, we can use the
but for a different reason:
```ignore
# #![feature(old_io, std_misc)]
use std::thread;
use std::old_io::timer;
use std::time::Duration;
use std::sync::Mutex;
fn main() {
@ -203,17 +161,17 @@ fn main() {
});
}
timer::sleep(Duration::milliseconds(50));
thread::sleep_ms(50);
}
```
Here's the error:
```text
<anon>:11:9: 11:22 error: the trait `core::marker::Send` is not implemented for the type `std::sync::mutex::MutexGuard<'_, collections::vec::Vec<u32>>` [E0277]
<anon>:9:9: 9:22 error: the trait `core::marker::Send` is not implemented for the type `std::sync::mutex::MutexGuard<'_, collections::vec::Vec<u32>>` [E0277]
<anon>:11 thread::spawn(move || {
^~~~~~~~~~~~~
<anon>:11:9: 11:22 note: `std::sync::mutex::MutexGuard<'_, collections::vec::Vec<u32>>` cannot be sent between threads safely
<anon>:9:9: 9:22 note: `std::sync::mutex::MutexGuard<'_, collections::vec::Vec<u32>>` cannot be sent between threads safely
<anon>:11 thread::spawn(move || {
^~~~~~~~~~~~~
```
@ -232,11 +190,8 @@ guard across thread boundaries, which gives us our error.
We can use `Arc<T>` to fix this. Here's the working version:
```
# #![feature(old_io, std_misc)]
use std::sync::{Arc, Mutex};
use std::thread;
use std::old_io::timer;
use std::time::Duration;
fn main() {
let data = Arc::new(Mutex::new(vec![1u32, 2, 3]));
@ -249,7 +204,7 @@ fn main() {
});
}
timer::sleep(Duration::milliseconds(50));
thread::sleep_ms(50);
}
```
@ -257,12 +212,9 @@ We now call `clone()` on our `Arc`, which increases the internal count. This
handle is then moved into the new thread. Let's examine the body of the
thread more closely:
```
# #![feature(old_io, std_misc)]
```rust
# use std::sync::{Arc, Mutex};
# use std::thread;
# use std::old_io::timer;
# use std::time::Duration;
# fn main() {
# let data = Arc::new(Mutex::new(vec![1u32, 2, 3]));
# for i in 0..2 {
@ -272,6 +224,7 @@ thread::spawn(move || {
data[i] += 1;
});
# }
# thread::sleep_ms(50);
# }
```

View File

@ -0,0 +1,3 @@
% Conditional Compilation
Coming Soon!

3
src/doc/trpl/const.md Normal file
View File

@ -0,0 +1,3 @@
% `const`
Coming soon!

View File

@ -111,8 +111,8 @@ Cargo will build this crate as a library:
```bash
$ cargo build
Compiling phrases v0.0.1 (file:///home/you/projects/phrases)
$ ls target
deps libphrases-a7448e02a0468eaa.rlib native
$ ls target/debug
build deps examples libphrases-a7448e02a0468eaa.rlib native
```
`libphrase-hash.rlib` is the compiled crate. Before we see how to use this
@ -163,9 +163,12 @@ $ tree .
│   │   └── mod.rs
│   └── lib.rs
└── target
├── deps
├── libphrases-a7448e02a0468eaa.rlib
└── native
└── debug
├── build
├── deps
├── examples
├── libphrases-a7448e02a0468eaa.rlib
└── native
```
`src/lib.rs` is our crate root, and looks like this:
@ -214,8 +217,6 @@ fn goodbye() -> String {
Put this in `src/japanese/greetings.rs`:
```rust
// in src/japanese/greetings.rs
fn hello() -> String {
"こんにちは".to_string()
}
@ -275,14 +276,15 @@ this:
```bash
$ cargo build
Compiling phrases v0.0.1 (file:///home/you/projects/phrases)
/home/you/projects/phrases/src/main.rs:4:38: 4:72 error: function `hello` is private
/home/you/projects/phrases/src/main.rs:4 println!("Hello in English: {}", phrases::english::greetings::hello());
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
src/main.rs:4:38: 4:72 error: function `hello` is private
src/main.rs:4 println!("Hello in English: {}", phrases::english::greetings::hello());
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
note: in expansion of format_args!
<std macros>:2:23: 2:77 note: expansion site
<std macros>:1:1: 3:2 note: in expansion of println!
/home/you/projects/phrases/src/main.rs:4:5: 4:76 note: expansion site
<std macros>:2:25: 2:58 note: expansion site
<std macros>:1:1: 2:62 note: in expansion of print!
<std macros>:3:1: 3:54 note: expansion site
<std macros>:1:1: 3:58 note: in expansion of println!
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
@ -340,15 +342,15 @@ functions:
```bash
$ cargo run
Compiling phrases v0.0.1 (file:///home/you/projects/phrases)
/home/you/projects/phrases/src/japanese/greetings.rs:1:1: 3:2 warning: code is never used: `hello`, #[warn(dead_code)] on by default
/home/you/projects/phrases/src/japanese/greetings.rs:1 fn hello() -> String {
/home/you/projects/phrases/src/japanese/greetings.rs:2 "こんにちは".to_string()
/home/you/projects/phrases/src/japanese/greetings.rs:3 }
/home/you/projects/phrases/src/japanese/farewells.rs:1:1: 3:2 warning: code is never used: `goodbye`, #[warn(dead_code)] on by default
/home/you/projects/phrases/src/japanese/farewells.rs:1 fn goodbye() -> String {
/home/you/projects/phrases/src/japanese/farewells.rs:2 "さようなら".to_string()
/home/you/projects/phrases/src/japanese/farewells.rs:3 }
Running `target/phrases`
src/japanese/greetings.rs:1:1: 3:2 warning: function is never used: `hello`, #[warn(dead_code)] on by default
src/japanese/greetings.rs:1 fn hello() -> String {
src/japanese/greetings.rs:2 "こんにちは".to_string()
src/japanese/greetings.rs:3 }
src/japanese/farewells.rs:1:1: 3:2 warning: function is never used: `goodbye`, #[warn(dead_code)] on by default
src/japanese/farewells.rs:1 fn goodbye() -> String {
src/japanese/farewells.rs:2 "さようなら".to_string()
src/japanese/farewells.rs:3 }
Running `target/debug/phrases`
Hello in English: Hello!
Goodbye in English: Goodbye.
```
@ -414,9 +416,9 @@ Rust will give us a compile-time error:
```text
Compiling phrases v0.0.1 (file:///home/you/projects/phrases)
/home/you/projects/phrases/src/main.rs:4:5: 4:40 error: a value named `hello` has already been imported in this module
/home/you/projects/phrases/src/main.rs:4 use phrases::japanese::greetings::hello;
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
src/main.rs:4:5: 4:40 error: a value named `hello` has already been imported in this module [E0252]
src/main.rs:4 use phrases::japanese::greetings::hello;
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
error: aborting due to previous error
Could not compile `phrases`.
```
@ -523,7 +525,7 @@ This will build and run:
```bash
$ cargo run
Compiling phrases v0.0.1 (file:///home/you/projects/phrases)
Running `target/phrases`
Running `target/debug/phrases`
Hello in English: Hello!
Goodbye in English: Goodbye.
Hello in Japanese: こんにちは

View File

@ -0,0 +1,3 @@
% Debug and Display
Coming soon!

View File

@ -0,0 +1,3 @@
% `Deref` coercions
Coming soon!

3
src/doc/trpl/drop.md Normal file
View File

@ -0,0 +1,3 @@
% `Drop`
Coming soon!

View File

@ -0,0 +1,8 @@
% Effective Rust
So youve learned how to write some Rust code. But theres a difference between
writing *any* Rust code and writing *good* Rust code.
This section consists of relatively independent tutorials which show you how to
take your Rust to the next level. Common patterns and standard library features
will be introduced. Read these sections in any order of your choosing.

147
src/doc/trpl/enums.md Normal file
View File

@ -0,0 +1,147 @@
% Enums
Finally, Rust has a "sum type", an *enum*. Enums are an incredibly useful
feature of Rust, and are used throughout the standard library. An `enum` is
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
enum Character {
Digit(i32),
Other,
}
```
Most normal types are allowed as the variant components of an `enum`. Here are
some examples:
```rust
struct Empty;
struct Color(i32, i32, i32);
struct Length(i32);
struct Status { Health: i32, Mana: i32, Attack: i32, Defense: i32 }
struct HeightDatabase(Vec<i32>);
```
You see that, depending on its type, an `enum` variant may or may not hold data.
In `Character`, for instance, `Digit` gives a meaningful name for an `i32`
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
equality operators (`==`, `!=`), have no ordering (`<`, `>=`, etc.), and do not
support other binary operations such as `*` and `+`. As such, the following code
is invalid for the example `Character` type:
```{rust,ignore}
// These assignments both succeed
let ten = Character::Digit(10);
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
`use` keyword. Here's an example of how it is used:
```{rust}
use std::cmp::Ordering;
fn cmp(a: i32, b: i32) -> Ordering {
if a < b { Ordering::Less }
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

@ -297,5 +297,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
`main()` doesn't return anything.
`try!` makes use of [`FromError`](../std/error/#the-fromerror-trait) to determine
`try!` makes use of [`From<Error>`](../std/convert/trait.From.hml) to determine
what to return in the error case.

View File

@ -166,7 +166,7 @@ pub fn uncompress(src: &[u8]) -> Option<Vec<u8>> {
}
```
For reference, the examples used here are also available as an [library on
For reference, the examples used here are also available as a [library on
GitHub](https://github.com/thestinger/rust-snappy).
# Destructors

43
src/doc/trpl/for-loops.md Normal file
View File

@ -0,0 +1,43 @@
% for Loops
The `for` loop is used to loop a particular number of times. Rusts `for` loops
work a bit differently than in other systems languages, however. Rusts `for`
loop doesnt look like this “C-style” `for` loop:
```c
for (x = 0; x < 10; x++) {
printf( "%d\n", x );
}
```
Instead, it looks like this:
```rust
for x in 0..10 {
println!("{}", x); // x: i32
}
```
In slightly more abstract terms,
```ignore
for var in expression {
code
}
```
The expression is an [iterator][iterator]. The iterator gives back a series of
elements. Each element is one iteration of the loop. That value is then bound
to the name `var`, which is valid for the loop body. Once the body is over, the
next value is fetched from the iterator, and we loop another time. When there
are no more values, the `for` loop is over.
[iterator]: iterators.html
In our example, `0..10` is an expression that takes a start and an end position,
and gives an iterator over those values. The upper bound is exclusive, though,
so our loop will print `0` through `9`, not `10`.
Rust does not have the “C-style” `for` loop on purpose. Manually controlling
each element of the loop is complicated and error prone, even for experienced C
developers.

View File

@ -1,6 +1,6 @@
% Functions
You've already seen one function so far, the `main` function:
Every Rust program has at least one function, the `main` function:
```rust
fn main() {
@ -8,16 +8,16 @@ fn main() {
```
This is the simplest possible function declaration. As we mentioned before,
`fn` says "this is a function," followed by the name, some parentheses because
`fn` says this is a function, followed by the name, some parentheses because
this function takes no arguments, and then some curly braces to indicate the
body. Here's a function named `foo`:
body. Heres a function named `foo`:
```rust
fn foo() {
}
```
So, what about taking arguments? Here's a function that prints a number:
So, what about taking arguments? Heres a function that prints a number:
```rust
fn print_number(x: i32) {
@ -25,7 +25,7 @@ fn print_number(x: i32) {
}
```
Here's a complete program that uses `print_number`:
Heres a complete program that uses `print_number`:
```rust
fn main() {
@ -40,7 +40,7 @@ fn print_number(x: i32) {
As you can see, function arguments work very similar to `let` declarations:
you add a type to the argument name, after a colon.
Here's a complete program that adds two numbers together and prints them:
Heres a complete program that adds two numbers together and prints them:
```rust
fn main() {
@ -58,7 +58,7 @@ as when you declare it.
Unlike `let`, you _must_ declare the types of function arguments. This does
not work:
```{rust,ignore}
```rust,ignore
fn print_sum(x, y) {
println!("sum is: {}", x + y);
}
@ -67,8 +67,8 @@ fn print_sum(x, y) {
You get this error:
```text
hello.rs:5:18: 5:19 expected one of `!`, `:`, or `@`, found `)`
hello.rs:5 fn print_number(x, y) {
expected one of `!`, `:`, or `@`, found `)`
fn print_number(x, y) {
```
This is a deliberate design decision. While full-program inference is possible,
@ -77,7 +77,7 @@ types explicitly is a best-practice. We agree that forcing functions to declare
types while allowing for inference inside of function bodies is a wonderful
sweet spot between full inference and no inference.
What about returning a value? Here's a function that adds one to an integer:
What about returning a value? Heres a function that adds one to an integer:
```rust
fn add_one(x: i32) -> i32 {
@ -86,11 +86,11 @@ fn add_one(x: i32) -> i32 {
```
Rust functions return exactly one value, and you declare the type after an
"arrow," which is a dash (`-`) followed by a greater-than sign (`>`).
arrow, which is a dash (`-`) followed by a greater-than sign (`>`). The last
line of a function determines what it returns. Youll note the lack of a
semicolon here. If we added it in:
You'll note the lack of a semicolon here. If we added it in:
```{rust,ignore}
```rust,ignore
fn add_one(x: i32) -> i32 {
x + 1;
}
@ -109,24 +109,79 @@ help: consider removing this semicolon:
^
```
Remember our earlier discussions about semicolons and `()`? Our function claims
to return an `i32`, but with a semicolon, it would return `()` instead. Rust
realizes this probably isn't what we want, and suggests removing the semicolon.
This reveals two interesting things about Rust: it is an expression-based
language, and semicolons are different from semicolons in other curly brace
and semicolon-based languages. These two things are related.
This is very much like our `if` statement before: the result of the block
(`{}`) is the value of the expression. Other expression-oriented languages,
such as Ruby, work like this, but it's a bit unusual in the systems programming
world. When people first learn about this, they usually assume that it
introduces bugs. But because Rust's type system is so strong, and because unit
is its own unique type, we have never seen an issue where adding or removing a
semicolon in a return position would cause a bug.
## Expressions vs. Statements
Rust is primarily an expression-based language. There are only two kinds of
statements, and everything else is an expression.
So what's the difference? Expressions return a value, and statements do not.
Thats why we end up with not all control paths return a value here: the
statement `x + 1;` doesnt return a value. There are two kinds of statements in
Rust: declaration statements and expression statements. Everything else is
an expression. Lets talk about declaration statements first.
In some languages, variable bindings can be written as expressions, not just
statements. Like Ruby:
```ruby
x = y = 5
```
In Rust, however, using `let` to introduce a binding is _not_ an expression. The
following will produce a compile-time error:
```ignore
let x = (let y = 5); // expected identifier, found keyword `let`
```
The compiler is telling us here that it was expecting to see the beginning of
an expression, and a `let` can only begin a statement, not an expression.
Note that assigning to an already-bound variable (e.g. `y = 5`) is still an
expression, although its value is not particularly useful. Unlike other
languages where an assignment evaluates to the assigned value (e.g. `5` in the
previous example), in Rust the value of an assignment is an empty tuple `()`:
```
let mut y = 5;
let x = (y = 6); // x has the value `()`, not `6`
```
The second kind of statement in Rust is the *expression statement*. Its
purpose is to turn any expression into a statement. In practical terms, Rust's
grammar expects statements to follow other statements. This means that you use
semicolons to separate expressions from each other. This means that Rust
looks a lot like most other languages that require you to use semicolons
at the end of every line, and you will see semicolons at the end of almost
every line of Rust code you see.
What is this exception that makes us say "almost"? You saw it already, in this
code:
```rust
fn add_one(x: i32) -> i32 {
x + 1
}
```
Our function claims to return an `i32`, but with a semicolon, it would return
`()` instead. Rust realizes this probably isnt what we want, and suggests
removing the semicolon in the error we saw before.
## Early returns
But what about early returns? Rust does have a keyword for that, `return`:
```rust
fn foo(x: i32) -> i32 {
if x < 5 { return x; }
return x;
// we never run this code!
x + 1
}
```
@ -136,33 +191,17 @@ style:
```rust
fn foo(x: i32) -> i32 {
if x < 5 { return x; }
return x + 1;
}
```
The previous definition without `return` may look a bit strange if you haven't
The previous definition without `return` may look a bit strange if you havent
worked in an expression-based language before, but it becomes intuitive over
time. If this were production code, we wouldn't write it in that way anyway,
we'd write this:
```rust
fn foo(x: i32) -> i32 {
if x < 5 {
x
} else {
x + 1
}
}
```
Because `if` is an expression, and it's the only expression in this function,
the value will be the result of the `if`.
time.
## Diverging functions
Rust has some special syntax for 'diverging functions', which are functions that
Rust has some special syntax for diverging functions, which are functions that
do not return:
```
@ -171,23 +210,18 @@ fn diverges() -> ! {
}
```
`panic!` is a macro, similar to `println!()` that we've already seen. Unlike
`panic!` is a macro, similar to `println!()` that weve already seen. Unlike
`println!()`, `panic!()` causes the current thread of execution to crash with
the given message.
Because this function will cause a crash, it will never return, and so it has
the type '`!`', which is read "diverges." A diverging function can be used
the type `!`, which is read diverges. A diverging function can be used
as any type:
```should_panic
# fn diverges() -> ! {
# panic!("This function never returns!");
# }
let x: i32 = diverges();
let x: String = diverges();
```
We don't have a good use for diverging functions yet, because they're used in
conjunction with other Rust features. But when you see `-> !` later, you'll
know what it's called.

View File

@ -0,0 +1,5 @@
% Getting Started
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,
well talk about Cargo, Rusts build system and package manager.

View File

@ -1,26 +1,27 @@
% Hello, Cargo!
[Cargo](http://crates.io) is a tool that Rustaceans use to help manage their
Rust projects. Cargo is currently in an alpha state, just like Rust, and so it
is still a work in 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.
[Cargo][cratesio] is a tool that Rustaceans use to help manage their Rust
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
so it is assumed that Rust projects will use Cargo from the beginning.
[cratesio]: https://doc.crates.io
Cargo manages three things: building your code, downloading the dependencies
your code needs, and building those dependencies. At first, your
program doesn't have any dependencies, so we'll only be using the first part of
its functionality. Eventually, we'll add more. Since we started off by using
program doesnt have any dependencies, so well only be using the first part of
its functionality. Eventually, well add more. Since we started off by using
Cargo, it'll be easy to add later.
If you installed Rust via the official installers you will also have
Cargo. If you installed Rust some other way, you may want to [check
the Cargo
README](https://github.com/rust-lang/cargo#installing-cargo-from-nightlies)
for specific instructions about installing it.
If you installed Rust via the official installers you will also have Cargo. If
you installed Rust some other way, you may want to [check the Cargo
README][cargoreadme] for specific instructions about installing it.
[cargoreadme]: https://github.com/rust-lang/cargo#installing-cargo-from-nightlies
## Converting to Cargo
Let's convert Hello World to Cargo.
Lets convert Hello World to Cargo.
To Cargo-ify our project, we need to do two things: Make a `Cargo.toml`
configuration file, and put our source file in the right place. Let's
@ -52,14 +53,9 @@ Put this inside:
name = "hello_world"
version = "0.0.1"
authors = [ "Your name <you@example.com>" ]
[[bin]]
name = "hello_world"
```
This file is in the [TOML](https://github.com/toml-lang/toml) format. Let's let
it explain itself to you:
This file is in the [TOML][toml] format. Lets let it explain itself to you:
> TOML aims to be a minimal configuration file format that's easy to read due
> to obvious semantics. TOML is designed to map unambiguously to a hash table.
@ -68,10 +64,7 @@ it explain itself to you:
TOML is very similar to INI, but with some extra goodies.
Anyway, there are two *tables* in this file: `package` and `bin`. The first
tells Cargo metadata about your package. The second tells Cargo that we're
interested in building a binary, not a library (though we could do both!), as
well as what it is named.
[toml]: https://github.com/toml-lang/toml
Once you have this file in place, we should be ready to build! Try this:
@ -83,13 +76,32 @@ Hello, world!
```
Bam! We build our project with `cargo build`, and run it with
`./target/debug/hello_world`. This hasn't bought us a whole lot over our simple use
of `rustc`, but think about the future: when our project has more than one
file, we would need to call `rustc` more than once and pass it a bunch of options to
tell it to build everything together. With Cargo, as our project grows, we can
just `cargo build`, and it'll work the right way. When your project is finally
ready for release, you can use `cargo build --release` to compile your crates with
optimizations.
`./target/debug/hello_world`. We can do both in one step with `cargo run`:
```bash
$ cargo run
Running `target/debug/hello_world`
Hello, world!
```
Notice that we didnt re-build the project this time. Cargo figured out that
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:
```bash
$ cargo build
Compiling hello_world v0.0.1 (file:///home/yourname/projects/hello_world)
Running `target/debug/hello_world`
Hello, world!
```
This hasnt bought us a whole lot over our simple use of `rustc`, but think
about the future: when our project gets more complex, we would need to do more
things to get all of the parts to properly compile. With Cargo, as our project
grows, we can just `cargo build`, and itll work the right way.
When your project is finally ready for release, you can use
`cargo build --release` to compile your project with optimizations.
You'll also notice that Cargo has created a new file: `Cargo.lock`.
@ -100,18 +112,25 @@ version = "0.0.1"
```
This file is used by Cargo to keep track of dependencies in your application.
Right now, we don't have any, so it's a bit sparse. You won't ever need
Right now, we dont have any, so its a bit sparse. You won't ever need
to touch this file yourself, just let Cargo handle it.
That's it! We've successfully built `hello_world` with Cargo. Even though our
program is simple, it's using much of the real tooling that you'll use for the
rest of your Rust career.
Thats it! Weve successfully built `hello_world` with Cargo. Even though our
program is simple, its using much of the real tooling that youll use for the
rest of your Rust career. You can expect to do this to get started with
virtually all Rust projects:
```bash
$ git clone someurl.com/foo
$ cd foo
$ cargo build
```
## A New Project
You don't have to go through this whole process every time you want to start a new
project! Cargo has the ability to make a bare-bones project directory in which you
can start developing right away.
You dont have to go through this whole process every time you want to start a
new project! Cargo has the ability to make a bare-bones project directory in
which you can start developing right away.
To start a new project with Cargo, use `cargo new`:
@ -119,8 +138,8 @@ To start a new project with Cargo, use `cargo new`:
$ cargo new hello_world --bin
```
We're passing `--bin` because we're making a binary program: if we
were making a library, we'd leave it off.
Were passing `--bin` because we're making a binary program: if we were making
a library, we'd leave it off.
Let's check out what Cargo has generated for us:
@ -135,10 +154,10 @@ $ tree .
1 directory, 2 files
```
If you don't have the `tree` command, you can probably get it from your distro's package
manager. It's not necessary, but it's certainly useful.
If you don't have the `tree` command, you can probably get it from your
distributions package manager. Its not necessary, but its certainly useful.
This is all we need to get started. First, let's check out `Cargo.toml`:
This is all we need to get started. First, lets check out `Cargo.toml`:
```toml
[package]
@ -148,11 +167,11 @@ version = "0.0.1"
authors = ["Your Name <you@example.com>"]
```
Cargo has populated this file with reasonable defaults based off the arguments you gave
it and your `git` global configuration. You may notice that Cargo has also initialized
the `hello_world` directory as a `git` repository.
Cargo has populated this file with reasonable defaults based off the arguments
you gave it and your `git` global configuration. You may notice that Cargo has
also initialized the `hello_world` directory as a `git` repository.
Here's what's in `src/main.rs`:
Heres whats in `src/main.rs`:
```rust
fn main() {
@ -160,9 +179,20 @@ fn main() {
}
```
Cargo has generated a "Hello World!" for us, and you're ready to start coding! A
much more in-depth guide to Cargo can be found [here](http://doc.crates.io/guide.html).
Cargo has generated a "Hello World!" for us, and youre ready to start coding! Cargo
has its own [guide][guide] which covers Cargos features in much more depth.
Now that you've got the tools down, let's actually learn more about the Rust
[guide]: http://doc.crates.io/guide.html
Now that youve got the tools down, lets actually learn more about the Rust
language itself. These are the basics that will serve you well through the rest
of your time with Rust.
You have two options: Dive into a project with [Learn Rust][learnrust], or
start from the bottom and work your way up with [Syntax and
Semantics][syntax]. More experienced systems programmers will probably prefer
Learn Rust, while those from dynamic backgrounds may enjoy either. Different
people learn differently! Choose whatevers right for you.
[learnrust]: learn-rust.html
[syntax]: syntax-and-semantics.html

View File

@ -1,9 +1,9 @@
% Hello, world!
Now that you have Rust installed, let's write your first Rust program. It's
Now that you have Rust installed, lets write your first Rust program. Its
traditional to make your first program in any new language one that prints the
text "Hello, world!" to the screen. The nice thing about starting with such a
simple program is that you can verify that your compiler isn't just installed,
text “Hello, world!” to the screen. The nice thing about starting with such a
simple program is that you can verify that your compiler isnt just installed,
but also working properly. And printing information to the screen is a pretty
common thing to do.
@ -12,38 +12,37 @@ to make a `projects` directory in my home directory, and keep all my projects
there. Rust does not care where your code lives.
This actually leads to one other concern we should address: this guide will
assume that you have basic familiarity with the command line. Rust does not
require that you know a whole ton about the command line, but until the
language is in a more finished state, IDE support is spotty. Rust makes no
specific demands on your editing tooling, or where your code lives.
assume that you have basic familiarity with the command line. Rust itself makes
no specific demands on your editing tooling, or where your code lives. If you
prefer an IDE to the command line, you may want to check out
[SolidOak][solidoak], or wherever plugins are for your favorite IDE. There are
a number of extensions of varying quality in development by the community. The
Rust team also ships [plugins for various editors][plugins]. Configuring your
editor or IDE is out of the scope of this tutorial, so check the documentation
for your setup, specifically.
With that said, let's make a directory in our projects directory.
[solidoak]: https://github.com/oakes/SolidOak
[plugins]: https://github.com/rust-lang/rust/blob/master/src/etc/CONFIGS.md
```{bash}
With that said, lets make a directory in our projects directory.
```bash
$ mkdir ~/projects
$ cd ~/projects
$ mkdir hello_world
$ cd hello_world
```
If you're on Windows and not using PowerShell, the `~` may not work. Consult
If youre on Windows and not using PowerShell, the `~` may not work. Consult
the documentation for your shell for more details.
Let's make a new source file next. I'm going to use the syntax `editor
filename` to represent editing a file in these examples, but you should use
whatever method you want. We'll call our file `main.rs`:
Lets make a new source file next. Well call our file `main.rs`. Rust files
always end in a `.rs` extension. If youre using more than one word in your
filename, use an underscore: `hello_world.rs` rather than `helloworld.rs`.
```{bash}
$ editor main.rs
```
Now that youve got your file open, type this in:
Rust files always end in a `.rs` extension. If you're using more than one word
in your filename, use an underscore. `hello_world.rs` rather than
`helloworld.rs`.
Now that you've got your file open, type this in:
```{rust}
```rust
fn main() {
println!("Hello, world!");
}
@ -51,87 +50,90 @@ fn main() {
Save the file, and then type this into your terminal window:
```{bash}
```bash
$ rustc main.rs
$ ./main # or main.exe on Windows
Hello, world!
```
You can also run these examples on [play.rust-lang.org](http://play.rust-lang.org/) by clicking on the arrow that appears in the upper right of the example when you mouse over the code.
Success! Lets go over what just happened in detail.
Success! Let's go over what just happened in detail.
```{rust}
```rust
fn main() {
}
```
These lines define a *function* in Rust. The `main` function is special:
it's the beginning of every Rust program. The first line says "I'm declaring a
function named `main`, which takes no arguments and returns nothing." If there
it's the beginning of every Rust program. The first line says "Im declaring a
function named `main` which takes no arguments and returns nothing." If there
were arguments, they would go inside the parentheses (`(` and `)`), and because
we aren't returning anything from this function, we can omit the return type
entirely. We'll get to it later.
we arent returning anything from this function, we can omit the return type
entirely. Well get to it later.
You'll also note that the function is wrapped in curly braces (`{` and `}`).
Youll also note that the function is wrapped in curly braces (`{` and `}`).
Rust requires these around all function bodies. It is also considered good
style to put the opening curly brace on the same line as the function
declaration, with one space in between.
Next up is this line:
```{rust}
```rust
println!("Hello, world!");
```
This line does all of the work in our little program. There are a number of
details that are important here. The first is that it's indented with four
details that are important here. The first is that its indented with four
spaces, not tabs. Please configure your editor of choice to insert four spaces
with the tab key. We provide some [sample configurations for various
editors](https://github.com/rust-lang/rust/tree/master/src/etc/CONFIGS.md).
editors][configs].
The second point is the `println!()` part. This is calling a Rust *macro*,
[configs]: https://github.com/rust-lang/rust/tree/master/src/etc/CONFIGS.md
The second point is the `println!()` part. This is calling a Rust [macro][macro],
which is how metaprogramming is done in Rust. If it were a function instead, it
would look like this: `println()`. For our purposes, we don't need to worry
about this difference. Just know that sometimes, you'll see a `!`, and that
means that you're calling a macro instead of a normal function. Rust implements
`println!` as a macro rather than a function for good reasons, but that's a
very advanced topic. You'll learn more when we talk about macros later. One
last thing to mention: Rust's macros are significantly different from C macros,
if you've used those. Don't be scared of using macros. We'll get to the details
eventually, you'll just have to trust us for now.
would look like this: `println()`. For our purposes, we dont need to worry
about this difference. Just know that sometimes, youll see a `!`, and that
means that youre calling a macro instead of a normal function. Rust implements
`println!` as a macro rather than a function for good reasons, but that's an
advanced topic. One last thing to mention: Rusts macros are significantly
different from C macros, if youve used those. Dont be scared of using macros.
Well get to the details eventually, youll just have to trust us for now.
Next, `"Hello, world!"` is a *string*. Strings are a surprisingly complicated
topic in a systems programming language, and this is a *statically allocated*
string. We will talk more about different kinds of allocation later. We pass
this string as an argument to `println!`, which prints the string to the
screen. Easy enough!
[macro]: macros.html
Finally, the line ends with a semicolon (`;`). Rust is an *expression
oriented* language, which means that most things are expressions. The `;` is
used to indicate that this expression is over, and the next one is ready to
begin. Most lines of Rust code end with a `;`. We will cover this in-depth
later in the guide.
Next, `"Hello, world!"` is a string. Strings are a surprisingly complicated
topic in a systems programming language, and this is a statically allocated
string. If you want to read further about allocation, check out
[the stack and the heap][allocation], but you dont need to right now if you
dont want to. We pass this string as an argument to `println!`, which prints the
string to the screen. Easy enough!
Finally, actually *compiling* and *running* our program. We can compile
with our compiler, `rustc`, by passing it the name of our source file:
[allocation]: the-stack-and-the-heap.html
```{bash}
Finally, the line ends with a semicolon (`;`). Rust is an expression oriented
language, which means that most things are expressions, rather than statements.
The `;` is used to indicate that this expression is over, and the next one is
ready to begin. Most lines of Rust code end with a `;`.
Finally, actually compiling and running our program. We can compile with our
compiler, `rustc`, by passing it the name of our source file:
```bash
$ rustc main.rs
```
This is similar to `gcc` or `clang`, if you come from a C or C++ background. Rust
will output a binary executable. You can see it with `ls`:
```{bash}
```bash
$ ls
main main.rs
```
Or on Windows:
```{bash}
```bash
$ dir
main.exe main.rs
```
@ -139,7 +141,7 @@ main.exe main.rs
There are now two files: our source code, with the `.rs` extension, and the
executable (`main.exe` on Windows, `main` everywhere else)
```{bash}
```bash
$ ./main # or main.exe on Windows
```
@ -147,15 +149,15 @@ This prints out our `Hello, world!` text to our terminal.
If you come from a dynamically typed language like Ruby, Python, or JavaScript,
you may not be used to these two steps being separate. Rust is an
*ahead-of-time compiled language*, which means that you can compile a
program, give it to someone else, and they don't need to have Rust installed.
If you give someone a `.rb` or `.py` or `.js` file, they need to have
Ruby/Python/JavaScript installed, but you just need one command to both compile
and run your program. Everything is a tradeoff in language design, and Rust has
made its choice.
ahead-of-time compiled language, which means that you can compile a program,
give it to someone else, and they don't need to have Rust installed. If you
give someone a `.rb` or `.py` or `.js` file, they need to have a
Ruby/Python/JavaScript implementation installed, but you just need one command
to both compile and run your program. Everything is a tradeoff in language
design, and Rust has made its choice.
Congratulations! You have officially written a Rust program. That makes you a
Rust programmer! Welcome.
Rust programmer! Welcome. 🎊🎉👍
Next, I'd like to introduce you to another tool, Cargo, which is used to write
real-world Rust programs. Just using `rustc` is nice for simple things, but as

3
src/doc/trpl/if-let.md Normal file
View File

@ -0,0 +1,3 @@
% if let
COMING SOON

View File

@ -1,10 +1,10 @@
% If
% if
Rust's take on `if` is not particularly complex, but it's much more like the
`if` you'll find in a dynamically typed language than in a more traditional
systems language. So let's talk about it, to make sure you grasp the nuances.
Rusts take on `if` is not particularly complex, but its much more like the
`if` youll find in a dynamically typed language than in a more traditional
systems language. So lets talk about it, to make sure you grasp the nuances.
`if` is a specific form of a more general concept, the *branch*. The name comes
`if` is a specific form of a more general concept, the branch. The name comes
from a branch in a tree: a decision point, where depending on a choice,
multiple paths can be taken.
@ -20,11 +20,11 @@ if x == 5 {
If we changed the value of `x` to something else, this line would not print.
More specifically, if the expression after the `if` evaluates to `true`, then
the block is executed. If it's `false`, then it is not.
the block is executed. If its `false`, then it is not.
If you want something to happen in the `false` case, use an `else`:
```{rust}
```rust
let x = 5;
if x == 5 {
@ -50,8 +50,7 @@ if x == 5 {
This is all pretty standard. However, you can also do this:
```{rust}
```rust
let x = 5;
let y = if x == 5 {
@ -63,93 +62,12 @@ let y = if x == 5 {
Which we can (and probably should) write like this:
```{rust}
```rust
let x = 5;
let y = if x == 5 { 10 } else { 15 }; // y: i32
```
This reveals two interesting things about Rust: it is an expression-based
language, and semicolons are different from semicolons in other 'curly brace
and semicolon'-based languages. These two things are related.
## Expressions vs. Statements
Rust is primarily an expression based language. There are only two kinds of
statements, and everything else is an expression.
So what's the difference? Expressions return a value, and statements do not.
In many languages, `if` is a statement, and therefore, `let x = if ...` would
make no sense. But in Rust, `if` is an expression, which means that it returns
a value. We can then use this value to initialize the binding.
Speaking of which, bindings are a kind of the first of Rust's two statements.
The proper name is a *declaration statement*. So far, `let` is the only kind
of declaration statement we've seen. Let's talk about that some more.
In some languages, variable bindings can be written as expressions, not just
statements. Like Ruby:
```{ruby}
x = y = 5
```
In Rust, however, using `let` to introduce a binding is _not_ an expression. The
following will produce a compile-time error:
```{ignore}
let x = (let y = 5); // expected identifier, found keyword `let`
```
The compiler is telling us here that it was expecting to see the beginning of
an expression, and a `let` can only begin a statement, not an expression.
Note that assigning to an already-bound variable (e.g. `y = 5`) is still an
expression, although its value is not particularly useful. Unlike C, where an
assignment evaluates to the assigned value (e.g. `5` in the previous example),
in Rust the value of an assignment is the unit type `()` (which we'll cover later).
The second kind of statement in Rust is the *expression statement*. Its
purpose is to turn any expression into a statement. In practical terms, Rust's
grammar expects statements to follow other statements. This means that you use
semicolons to separate expressions from each other. This means that Rust
looks a lot like most other languages that require you to use semicolons
at the end of every line, and you will see semicolons at the end of almost
every line of Rust code you see.
What is this exception that makes us say "almost"? You saw it already, in this
code:
```{rust}
let x = 5;
let y: i32 = if x == 5 { 10 } else { 15 };
```
Note that I've added the type annotation to `y`, to specify explicitly that I
want `y` to be an integer.
This is not the same as this, which won't compile:
```{ignore}
let x = 5;
let y: i32 = if x == 5 { 10; } else { 15; };
```
Note the semicolons after the 10 and 15. Rust will give us the following error:
```text
error: mismatched types: expected `i32`, found `()` (expected i32, found ())
```
We expected an integer, but we got `()`. `()` is pronounced *unit*, and is a
special type in Rust's type system. In Rust, `()` is _not_ a valid value for a
variable of type `i32`. It's only a valid value for variables of the type `()`,
which aren't very useful. Remember how we said statements don't return a value?
Well, that's the purpose of unit in this case. The semicolon turns any
expression into a statement by throwing away its value and returning unit
instead.
There's one more time in which you won't see a semicolon at the end of a line
of Rust code. For that, we'll need our next concept: functions.
This works because `if` is an expression. The value of the expression is the
value of the last expression in whichever branch was chosen. An `if` without an
`else` always results in `()` as the value.

View File

@ -1,27 +1,32 @@
% Installing Rust
The first step to using Rust is to install it! There are a number of ways to
install Rust, but the easiest is to use the `rustup` script. If you're on
Linux or a Mac, all you need to do is this (note that you don't need to type
in the `$`s, they just indicate the start of each command):
install Rust, but the easiest is to use the `rustup` script. If you're on Linux
or a Mac, all you need to do is this (note that you don't need to type in the
`$`s, they just indicate the start of each command):
```bash
$ curl -sf -L https://static.rust-lang.org/rustup.sh | sudo sh
```
If you're concerned about the [potential insecurity](http://curlpipesh.tumblr.com/) of using `curl | sudo sh`,
please keep reading and see our disclaimer below. And feel free to use a two-step version of the installation and examine our installation script:
If 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
use a two-step version of the installation and examine our installation script:
```bash
$ curl -f -L https://static.rust-lang.org/rustup.sh -O
$ sudo sh rustup.sh
```
If you're on Windows, please download either the [32-bit
installer](https://static.rust-lang.org/dist/rust-nightly-i686-pc-windows-gnu.exe)
or the [64-bit
installer](https://static.rust-lang.org/dist/rust-nightly-x86_64-pc-windows-gnu.exe)
and run it.
[insecurity]: http://curlpipesh.tumblr.com
If you're on Windows, please download either the [32-bit installer][win32] or
the [64-bit installer][win64] and run it.
[win32]: https://static.rust-lang.org/dist/rust-1.0.0-beta-i686-pc-windows-gnu.msi
[win64]: https://static.rust-lang.org/dist/rust-1.0.0-beta-x86_64-pc-windows-gnu.msi
## Uninstalling
If you decide you don't want Rust anymore, we'll be a bit sad, but that's okay.
Not every programming language is great for everyone. Just run the uninstall
@ -31,22 +36,20 @@ script:
$ sudo /usr/local/lib/rustlib/uninstall.sh
```
If you used the Windows installer, just re-run the `.exe` and it will give you
If you used the Windows installer, just re-run the `.msi` and it will give you
an uninstall option.
You can re-run this script any time you want to update Rust. Which, at this
point, is often. Rust is still pre-1.0, and so people assume that you're using
a very recent Rust.
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
people who maintain Rust aren't going to hack your computer and do bad things.
That's a good instinct! If you're one of those people, please check out the
documentation on [building Rust from Source][from source], or [the official
binary downloads][install page]. And we promise that this method will not be
the way to install Rust forever: it's just the easiest way to keep people
updated while Rust is in its alpha state.
This brings me to one other point: some people, and somewhat rightfully so, get
very upset when we tell you to `curl | sudo sh`. And they should be! Basically,
when you do this, you are trusting that the good people who maintain Rust
aren't going to hack your computer and do bad things. That's a good instinct!
If you're one of those people, please check out the documentation on [building
Rust from Source](https://github.com/rust-lang/rust#building-from-source), or
[the official binary downloads](http://www.rust-lang.org/install.html). And we
promise that this method will not be 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
[install page]: http://www.rust-lang.org/install.html
Oh, we should also mention the officially supported platforms:
@ -73,7 +76,7 @@ $ rustc --version
You should see the version number, commit hash, commit date and build date:
```bash
rustc 1.0.0-nightly (f11f3e7ba 2015-01-04) (built 2015-01-06)
rustc 1.0.0-beta (9854143cb 2015-04-02) (built 2015-04-02)
```
If you did, Rust has been installed successfully! Congrats!
@ -84,10 +87,13 @@ On Windows, it's in a `share/doc` directory, inside wherever you installed Rust
to.
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://irc.mozilla.org/#rust), which
you can access through
[Mibbit](http://chat.mibbit.com/?server=irc.mozilla.org&channel=%23rust). Click
that link, and you'll be chatting with other Rustaceans (a silly nickname we
call ourselves), and we can help you out. Other great resources include [the
/r/rust subreddit](http://www.reddit.com/r/rust), and [Stack
Overflow](http://stackoverflow.com/questions/tagged/rust).
[the #rust IRC channel on irc.mozilla.org][irc], which you can access through
[Mibbit][mibbit]. Click that link, and you'll be chatting with other Rustaceans
(a silly nickname we call ourselves), and we can help you out. Other great
resources include [the users forum][users], and
[Stack Overflow][stack overflow].
[irc]: irc://irc.mozilla.org/#rust
[mibbit]: http://chat.mibbit.com/?server=irc.mozilla.org&channel=%23rust
[users]: http://users.rust-lang.org/
[stack overflow]: http://stackoverflow.com/questions/tagged/rust

View File

@ -1,7 +0,0 @@
% Intermediate
This section contains individual chapters, which are self-contained. They focus
on specific topics, and can be read in any order.
After reading "Intermediate," you will have a solid understanding of Rust,
and will be able to understand most Rust code and write more complex programs.

View File

@ -291,7 +291,7 @@ If you are trying to execute a closure on an iterator for its side effects,
just use `for` instead.
There are tons of interesting iterator adapters. `take(n)` will return an
iterator over the next `n` elements of the original iterator, note that this
iterator over the next `n` elements of the original iterator. Note that this
has no side effect on the original iterator. Let's try it out with our infinite
iterator from before:

View File

@ -0,0 +1,4 @@
% Learn Rust
This section is coming soon! It will eventually have a few tutorials with
building real Rust projects, but they are under development.

View File

@ -0,0 +1,3 @@
% Lifetimes
Coming soon!

View File

@ -1,133 +0,0 @@
% Looping
Looping is the last basic construct that we haven't learned yet in Rust. Rust has
two main looping constructs: `for` and `while`.
## `for`
The `for` loop is used to loop a particular number of times. Rust's `for` loops
work a bit differently than in other systems languages, however. Rust's `for`
loop doesn't look like this "C-style" `for` loop:
```{c}
for (x = 0; x < 10; x++) {
printf( "%d\n", x );
}
```
Instead, it looks like this:
```{rust}
for x in 0..10 {
println!("{}", x); // x: i32
}
```
In slightly more abstract terms,
```{ignore}
for var in expression {
code
}
```
The expression is an iterator, which we will discuss in more depth later in the
guide. The iterator gives back a series of elements. Each element is one
iteration of the loop. That value is then bound to the name `var`, which is
valid for the loop body. Once the body is over, the next value is fetched from
the iterator, and we loop another time. When there are no more values, the
`for` loop is over.
In our example, `0..10` is an expression that takes a start and an end position,
and gives an iterator over those values. The upper bound is exclusive, though,
so our loop will print `0` through `9`, not `10`.
Rust does not have the "C-style" `for` loop on purpose. Manually controlling
each element of the loop is complicated and error prone, even for experienced C
developers.
We'll talk more about `for` when we cover *iterators*, later in the Guide.
## `while`
The other kind of looping construct in Rust is the `while` loop. It looks like
this:
```{rust}
let mut x = 5; // mut x: u32
let mut done = false; // mut done: bool
while !done {
x += x - 3;
println!("{}", x);
if x % 5 == 0 { done = true; }
}
```
`while` loops are the correct choice when you're not sure how many times
you need to loop.
If you need an infinite loop, you may be tempted to write this:
```{rust,ignore}
while true {
```
However, Rust has a dedicated keyword, `loop`, to handle this case:
```{rust,ignore}
loop {
```
Rust's control-flow analysis treats this construct differently than a
`while true`, since we know that it will always loop. The details of what
that _means_ aren't super important to understand at this stage, but in
general, the more information we can give to the compiler, the better it
can do with safety and code generation, so you should always prefer
`loop` when you plan to loop infinitely.
## Ending iteration early
Let's take a look at that `while` loop we had earlier:
```{rust}
let mut x = 5;
let mut done = false;
while !done {
x += x - 3;
println!("{}", x);
if x % 5 == 0 { done = true; }
}
```
We had to keep a dedicated `mut` boolean variable binding, `done`, to know
when we should exit out of the loop. Rust has two keywords to help us with
modifying iteration: `break` and `continue`.
In this case, we can write the loop in a better way with `break`:
```{rust}
let mut x = 5;
loop {
x += x - 3;
println!("{}", x);
if x % 5 == 0 { break; }
}
```
We now loop forever with `loop` and use `break` to break out early.
`continue` is similar, but instead of ending the loop, goes to the next
iteration. This will only print the odd numbers:
```{rust}
for x in 0..10 {
if x % 2 == 0 { continue; }
println!("{}", x);
}
```
Both `continue` and `break` are valid in both kinds of loops.

View File

@ -424,9 +424,240 @@ they are unstable and require feature gates.
* `trace_macros!(true)` will enable a compiler message every time a macro is
expanded. Use `trace_macros!(false)` later in expansion to turn it off.
# Further reading
# Syntactic requirements
The [advanced macros chapter][] goes into more detail about macro syntax. It
also describes how to share macros between different modules or crates.
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
tools that process code. It also has a few consequences for the design of
Rust's macro system.
[advanced macros chapter]: advanced-macros.html
[ast]: glossary.html#abstract-syntax-tree
One consequence is that Rust must determine, when it parses a macro invocation,
whether the macro stands in for
* zero or more items,
* zero or more methods,
* an expression,
* a statement, or
* a pattern.
A macro invocation within a block could stand for some items, or for an
expression / statement. Rust uses a simple rule to resolve this ambiguity. A
macro invocation that stands for items must be either
* delimited by curly braces, e.g. `foo! { ... }`, or
* terminated by a semicolon, e.g. `foo!(...);`
Another consequence of pre-expansion parsing is that the macro invocation must
consist of valid Rust tokens. Furthermore, parentheses, brackets, and braces
must be balanced within a macro invocation. For example, `foo!([)` is
forbidden. This allows Rust to know where the macro invocation ends.
More formally, the macro invocation body must be a sequence of *token trees*.
A token tree is defined recursively as either
* a sequence of token trees surrounded by matching `()`, `[]`, or `{}`, or
* any other single token.
Within a matcher, each metavariable has a *fragment specifier*, identifying
which syntactic form it matches.
* `ident`: an identifier. Examples: `x`; `foo`.
* `path`: a qualified name. Example: `T::SpecialA`.
* `expr`: an expression. Examples: `2 + 2`; `if true then { 1 } else { 2 }`; `f(42)`.
* `ty`: a type. Examples: `i32`; `Vec<(char, String)>`; `&T`.
* `pat`: a pattern. Examples: `Some(t)`; `(17, 'a')`; `_`.
* `stmt`: a single statement. Example: `let x = 3`.
* `block`: a brace-delimited sequence of statements. Example:
`{ log(error, "hi"); return 12; }`.
* `item`: an [item][]. Examples: `fn foo() { }`; `struct Bar;`.
* `meta`: a "meta item", as found in attributes. Example: `cfg(target_os = "windows")`.
* `tt`: a single token tree.
There are additional rules regarding the next token after a metavariable:
* `expr` variables must be followed by one of: `=> , ;`
* `ty` and `path` variables must be followed by one of: `=> , : = > as`
* `pat` variables must be followed by one of: `=> , =`
* Other variables may be followed by any token.
These rules provide some flexibility for Rust's syntax to evolve without
breaking existing macros.
The macro system does not deal with parse ambiguity at all. For example, the
grammar `$($t:ty)* $e:expr` will always fail to parse, because the parser would
be forced to choose between parsing `$t` and parsing `$e`. Changing the
invocation syntax to put a distinctive token in front can solve the problem. In
this case, you can write `$(T $t:ty)* E $e:exp`.
[item]: ../reference.html#items
# Scoping and macro import/export
Macros are expanded at an early stage in compilation, before name resolution.
One downside is that scoping works differently for macros, compared to other
constructs in the language.
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
is visible to any subsequent code in the same module, which includes the body
of any subsequent child `mod` items.
A macro defined within the body of a single `fn`, or anywhere else not at
module scope, is visible only within that item.
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`
then the macros will be visible in the grandparent after the parent's `mod`
item, and so forth.
The `macro_use` attribute can also appear on `extern crate`. In this context
it controls which macros are loaded from the external crate, e.g.
```rust,ignore
#[macro_use(foo, bar)]
extern crate baz;
```
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
defined with the `#[macro_export]` attribute may be loaded.
To load a crate's macros *without* linking it into the output, use `#[no_link]`
as well.
An example:
```rust
macro_rules! m1 { () => (()) }
// visible here: m1
mod foo {
// visible here: m1
#[macro_export]
macro_rules! m2 { () => (()) }
// visible here: m1, m2
}
// visible here: m1
macro_rules! m3 { () => (()) }
// visible here: m1, m3
#[macro_use]
mod bar {
// visible here: m1, m3
macro_rules! m4 { () => (()) }
// visible here: m1, m3, m4
}
// visible here: m1, m3, m4
# fn main() { }
```
When this library is loaded with `#[macro_use] extern crate`, only `m2` will
be imported.
The Rust Reference has a [listing of macro-related
attributes](../reference.html#macro--and-plugin-related-attributes).
# The variable `$crate`
A further difficulty occurs when a macro is used in multiple crates. Say that
`mylib` defines
```rust
pub fn increment(x: u32) -> u32 {
x + 1
}
#[macro_export]
macro_rules! inc_a {
($x:expr) => ( ::increment($x) )
}
#[macro_export]
macro_rules! inc_b {
($x:expr) => ( ::mylib::increment($x) )
}
# fn main() { }
```
`inc_a` only works within `mylib`, while `inc_b` only works outside the
library. Furthermore, `inc_b` will break if the user imports `mylib` under
another name.
Rust does not (yet) have a hygiene system for crate references, but it does
provide a simple workaround for this problem. Within a macro imported from a
crate named `foo`, the special macro variable `$crate` will expand to `::foo`.
By contrast, when a macro is defined and then used in the same crate, `$crate`
will expand to nothing. This means we can write
```rust
#[macro_export]
macro_rules! inc {
($x:expr) => ( $crate::increment($x) )
}
# fn main() { }
```
to define a single macro that works both inside and outside our library. The
function name will expand to either `::increment` or `::mylib::increment`.
To keep this system simple and correct, `#[macro_use] extern crate ...` may
only appear at the root of your crate, not inside `mod`. This ensures that
`$crate` is a single identifier.
# The deep end
The introductory chapter mentioned recursive macros, but it did not give the
full story. Recursive macros are useful for another reason: Each recursive
invocation gives you another opportunity to pattern-match the macro's
arguments.
As an extreme example, it is possible, though hardly advisable, to implement
the [Bitwise Cyclic Tag](http://esolangs.org/wiki/Bitwise_Cyclic_Tag) automaton
within Rust's macro system.
```rust
macro_rules! bct {
// cmd 0: d ... => ...
(0, $($ps:tt),* ; $_d:tt)
=> (bct!($($ps),*, 0 ; ));
(0, $($ps:tt),* ; $_d:tt, $($ds:tt),*)
=> (bct!($($ps),*, 0 ; $($ds),*));
// cmd 1p: 1 ... => 1 ... p
(1, $p:tt, $($ps:tt),* ; 1)
=> (bct!($($ps),*, 1, $p ; 1, $p));
(1, $p:tt, $($ps:tt),* ; 1, $($ds:tt),*)
=> (bct!($($ps),*, 1, $p ; 1, $($ds),*, $p));
// cmd 1p: 0 ... => 0 ...
(1, $p:tt, $($ps:tt),* ; $($ds:tt),*)
=> (bct!($($ps),*, 1, $p ; $($ds),*));
// halt on empty data string
( $($ps:tt),* ; )
=> (());
}
```
Exercise: use macros to reduce duplication in the above definition of the
`bct!` macro.
# Procedural macros
If Rust's macro system can't do what you need, you may want to write a
[compiler plugin](plugins.html) instead. Compared to `macro_rules!`
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
flexibility of running arbitrary Rust code within the compiler. Syntax
extension plugins are sometimes called *procedural macros* for this reason.

View File

@ -1,13 +1,13 @@
% Match
Often, a simple `if`/`else` isn't enough, because you have more than two
Often, a simple `if`/`else` isnt enough, because you have more than two
possible options. Also, `else` conditions can get incredibly complicated, so
what's the solution?
whats the solution?
Rust has a keyword, `match`, that allows you to replace complicated `if`/`else`
groupings with something more powerful. Check it out:
```{rust}
```rust
let x = 5;
match x {
@ -21,11 +21,14 @@ match x {
```
`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 arm's
expression will be evaluated. It's called `match` because of the term 'pattern
matching', which `match` is an implementation of.
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
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.
So what's the big advantage here? Well, there are a few. First of all, `match`
[patterns]: patterns.html
So whats the big advantage here? Well, there are a few. First of all, `match`
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:
@ -36,121 +39,24 @@ error: non-exhaustive patterns: `_` not covered
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,
`6`. Without the `_`, however, there is no arm that could match, and so Rust refuses
to compile. `_` acts like a *catch-all arm*. If none of the other arms match,
to compile. `_` acts like a catch-all arm. If none of the other arms match,
the arm with `_` will, and since we have this catch-all arm, we now have an arm
for every possible value of `x`, and so our program will compile successfully.
`match` statements also destructure enums, as well. Remember this code from the
section on enums?
```{rust}
use std::cmp::Ordering;
fn cmp(a: i32, b: i32) -> Ordering {
if a < b { Ordering::Less }
else if a > b { Ordering::Greater }
else { Ordering::Equal }
}
fn main() {
let x = 5;
let y = 10;
let ordering = cmp(x, y);
if ordering == Ordering::Less {
println!("less");
} else if ordering == Ordering::Greater {
println!("greater");
} else if ordering == Ordering::Equal {
println!("equal");
}
}
```
We can re-write this as a `match`:
```{rust}
use std::cmp::Ordering;
fn cmp(a: i32, b: i32) -> Ordering {
if a < b { Ordering::Less }
else if a > b { Ordering::Greater }
else { Ordering::Equal }
}
fn main() {
let x = 5;
let y = 10;
match cmp(x, y) {
Ordering::Less => println!("less"),
Ordering::Greater => println!("greater"),
Ordering::Equal => println!("equal"),
}
}
```
This version has way less noise, and it also checks exhaustively to make sure
that we have covered all possible variants of `Ordering`. With our `if`/`else`
version, if we had forgotten the `Greater` case, for example, our program would
have happily compiled. If we forget in the `match`, it will not. Rust helps us
make sure to cover all of our bases.
`match` expressions also allow us to get the values contained in an `enum`
(also known as destructuring) as follows:
```{rust}
enum OptionalInt {
Value(i32),
Missing,
}
fn main() {
let x = OptionalInt::Value(5);
let y = OptionalInt::Missing;
match x {
OptionalInt::Value(n) => println!("x is {}", n),
OptionalInt::Missing => println!("x is missing!"),
}
match y {
OptionalInt::Value(n) => println!("y is {}", n),
OptionalInt::Missing => println!("y is missing!"),
}
}
```
That is how you can get and use the values contained in `enum`s.
It can also allow us to handle errors or unexpected computations; for example, a
function that is not guaranteed to be able to compute a result (an `i32` here)
could return an `OptionalInt`, and we would handle that value with a `match`.
As you can see, `enum` and `match` used together are quite useful!
`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. We could
also implement the previous example like this:
side of a `let` binding or directly where an expression is used:
```{rust}
use std::cmp::Ordering;
```rust
let x = 5;
fn cmp(a: i32, b: i32) -> Ordering {
if a < b { Ordering::Less }
else if a > b { Ordering::Greater }
else { Ordering::Equal }
}
fn main() {
let x = 5;
let y = 10;
println!("{}", match cmp(x, y) {
Ordering::Less => "less",
Ordering::Greater => "greater",
Ordering::Equal => "equal",
});
}
let numer = match x {
1 => "one",
2 => "two",
3 => "three",
4 => "four",
5 => "five",
_ => "something else",
};
```
Sometimes, it's a nice pattern.
Sometimes, its a nice way of converting things.

View File

@ -4,7 +4,7 @@ Functions are great, but if you want to call a bunch of them on some data, it
can be awkward. Consider this code:
```{rust,ignore}
baz(bar(foo(x)));
baz(bar(foo)));
```
We would read this left-to right, and so we see "baz bar foo." But this isn't the
@ -12,7 +12,7 @@ order that the functions would get called in, that's inside-out: "foo bar baz."
Wouldn't it be nice if we could do this instead?
```{rust,ignore}
x.foo().bar().baz();
foo.bar().baz();
```
Luckily, as you may have guessed with the leading question, you can! Rust provides
@ -47,8 +47,8 @@ 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`.
You can think of this first parameter as being the `x` in `x.foo()`. The three
variants correspond to the three kinds of thing `x` could be: `self` if it's
You can think of this first parameter as being the `foo` in `foo.bar()`. The three
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
a mutable reference. We should default to using `&self`, as you should prefer
borrowing over taking ownership, as well as taking immutable references
@ -197,7 +197,7 @@ impl CircleBuilder {
}
fn y(&mut self, coordinate: f64) -> &mut CircleBuilder {
self.x = coordinate;
self.y = coordinate;
self
}

View File

@ -1,325 +0,0 @@
% More Strings
Strings are an important concept to master in any programming language. If you
come from a managed language background, you may be surprised at the complexity
of string handling in a systems programming language. Efficient access and
allocation of memory for a dynamically sized structure involves a lot of
details. Luckily, Rust has lots of tools to help us here.
A **string** is a sequence of unicode scalar values encoded as a stream of
UTF-8 bytes. All strings are guaranteed to be validly-encoded UTF-8 sequences.
Additionally, strings are not null-terminated and can contain null bytes.
Rust has two main types of strings: `&str` and `String`.
# `&str`
The first kind is a `&str`. This is pronounced a 'string slice'.
String literals are of the type `&str`:
```
let string = "Hello there.";
```
Like any Rust reference, string slices have an associated lifetime. A string
literal is a `&'static str`. A string slice can be written without an explicit
lifetime in many cases, such as in function arguments. In these cases the
lifetime will be inferred:
```
fn takes_slice(slice: &str) {
println!("Got: {}", slice);
}
```
Like vector slices, string slices are simply a pointer plus a length. This
means that they're a 'view' into an already-allocated string, such as a
string literal or a `String`.
## `str`
You may occasionally see references to a `str` type, without the `&`. While
this type does exist, its not something you want to use yourself. Sometimes,
people confuse `str` for `String`, and write this:
```rust
struct S {
s: str,
}
```
This leads to ugly errors:
```text
error: the trait `core::marker::Sized` is not implemented for the type `str` [E0277]
note: `str` does not have a constant size known at compile-time
```
Instead, this `struct` should be
```rust
struct S {
s: String,
}
```
So lets talk about `String`s.
# `String`
A `String` is a heap-allocated string. This string is growable, and is
also guaranteed to be UTF-8. `String`s are commonly created by
converting from a string slice using the `to_string` method.
```
let mut s = "Hello".to_string();
println!("{}", s);
s.push_str(", world.");
println!("{}", s);
```
A reference to a `String` will automatically coerce to a string slice:
```
fn takes_slice(slice: &str) {
println!("Got: {}", slice);
}
fn main() {
let s = "Hello".to_string();
takes_slice(&s);
}
```
You can also get a `&str` from a stack-allocated array of bytes:
```
use std::str;
let x: &[u8] = &[b'a', b'b'];
let stack_str: &str = str::from_utf8(x).unwrap();
```
# Best Practices
## `String` vs. `&str`
In general, you should prefer `String` when you need ownership, and `&str` when
you just need to borrow a string. This is very similar to using `Vec<T>` vs. `&[T]`,
and `T` vs `&T` in general.
This means starting off with this:
```{rust,ignore}
fn foo(s: &str) {
```
and only moving to this:
```{rust,ignore}
fn foo(s: String) {
```
if you have good reason. It's not polite to hold on to ownership you don't
need, and it can make your lifetimes more complex.
## Generic functions
To write a function that's generic over types of strings, use `&str`.
```
fn some_string_length(x: &str) -> usize {
x.len()
}
fn main() {
let s = "Hello, world";
println!("{}", some_string_length(s));
let s = "Hello, world".to_string();
println!("{}", some_string_length(&s));
}
```
Both of these lines will print `12`.
## Indexing strings
You may be tempted to try to access a certain character of a `String`, like
this:
```{rust,ignore}
let s = "hello".to_string();
println!("{}", s[0]);
```
This does not compile. This is on purpose. In the world of UTF-8, direct
indexing is basically never what you want to do. The reason is that each
character can be a variable number of bytes. This means that you have to iterate
through the characters anyway, which is an O(n) operation.
There's 3 basic levels of unicode (and its encodings):
- code units, the underlying data type used to store everything
- code points/unicode scalar values (char)
- graphemes (visible characters)
Rust provides iterators for each of these situations:
- `.bytes()` will iterate over the underlying bytes
- `.chars()` will iterate over the code points
- `.graphemes()` will iterate over each grapheme
Usually, the `graphemes()` method on `&str` is what you want:
```
# #![feature(unicode)]
let s = "u͔n͈̰̎i̙̮͚̦c͚̉o̼̩̰͗d͔̆̓ͥé";
for l in s.graphemes(true) {
println!("{}", l);
}
```
This prints:
```text
n͈̰̎
i̙̮͚̦
c͚̉
o̼̩̰͗
d͔̆̓ͥ
```
Note that `l` has the type `&str` here, since a single grapheme can consist of
multiple codepoints, so a `char` wouldn't be appropriate.
This will print out each visible character in turn, as you'd expect: first `u͔`, then
`n͈̰̎`, etc. If you wanted each individual codepoint of each grapheme, you can use `.chars()`:
```
let s = "u͔n͈̰̎i̙̮͚̦c͚̉o̼̩̰͗d͔̆̓ͥé";
for l in s.chars() {
println!("{}", l);
}
```
This prints:
```text
u
͔
n
̎
͈
̰
i
̙
̮
͚
̦
c
̉
͚
o
͗
̼
̩
̰
d
̆
̓
ͥ
͔
e
́
```
You can see how some of them are combining characters, and therefore the output
looks a bit odd.
If you want the individual byte representation of each codepoint, you can use
`.bytes()`:
```
let s = "u͔n͈̰̎i̙̮͚̦c͚̉o̼̩̰͗d͔̆̓ͥé";
for l in s.bytes() {
println!("{}", l);
}
```
This will print:
```text
117
205
148
110
204
142
205
136
204
176
105
204
153
204
174
205
154
204
166
99
204
137
205
154
111
205
151
204
188
204
169
204
176
100
204
134
205
131
205
165
205
148
101
204
129
```
Many more bytes than graphemes!
# `Deref` coercions
References to `String`s will automatically coerce into `&str`s. Like this:
```
fn hello(s: &str) {
println!("Hello, {}!", s);
}
let slice = "Steve";
let string = "Steve".to_string();
hello(slice);
hello(&string);
```

View File

@ -0,0 +1,3 @@
% Move Semantics
Coming Soon

View File

@ -0,0 +1,3 @@
% Mutability
Coming Soon

View File

@ -0,0 +1,102 @@
% Nightly Rust
Rust provides three distribution channels for Rust: nightly, beta, and stable.
Unstable features are only available on nightly Rust. For more details on this
process, see [Stability as a deliverable][stability].
[stability]: http://blog.rust-lang.org/2014/10/30/Stability.html
To install nightly Rust, you can use `rustup.sh`:
```bash
$ curl -s https://static.rust-lang.org/rustup.sh | sudo sh -s -- --channel=nightly
```
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
use a two-step version of the installation and examine our installation script:
```bash
$ curl -f -L https://static.rust-lang.org/rustup.sh -O
$ sudo sh rustup.sh --channel=nightly
```
[insecurity]: http://curlpipesh.tumblr.com
If you're on Windows, please download either the [32-bit installer][win32] or
the [64-bit installer][win64] and run it.
[win32]: https://static.rust-lang.org/dist/rust-1.0.0-beta-i686-pc-windows-gnu.msi
[win64]: https://static.rust-lang.org/dist/rust-1.0.0-beta-x86_64-pc-windows-gnu.msi
## Uninstalling
If you decide you don't want Rust anymore, we'll be a bit sad, but that's okay.
Not every programming language is great for everyone. Just run the uninstall
script:
```bash
$ sudo /usr/local/lib/rustlib/uninstall.sh
```
If you used the Windows installer, just re-run the `.msi` and it will give you
an uninstall option.
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
people who maintain Rust aren't going to hack your computer and do bad things.
That's a good instinct! If you're one of those people, please check out the
documentation on [building Rust from Source][from source], or [the official
binary downloads][install page]. And we promise that this method will not be
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
[install page]: http://www.rust-lang.org/install.html
Oh, we should also mention the officially supported platforms:
* Windows (7, 8, Server 2008 R2)
* Linux (2.6.18 or later, various distributions), x86 and x86-64
* OSX 10.7 (Lion) or greater, x86 and x86-64
We extensively test Rust on these platforms, and a few others, too, like
Android. But these are the ones most likely to work, as they have the most
testing.
Finally, a comment about Windows. Rust considers Windows to be a first-class
platform upon release, but if we're honest, the Windows experience isn't as
integrated as the Linux/OS X experience is. We're working on it! If anything
does not work, it is a bug. Please let us know if that happens. Each and every
commit is tested against Windows just like any other platform.
If you've got Rust installed, you can open up a shell, and type this:
```bash
$ rustc --version
```
You should see the version number, commit hash, commit date and build date:
```bash
rustc 1.0.0-nightly (f11f3e7ba 2015-01-04) (built 2015-01-06)
```
If you did, Rust has been installed successfully! Congrats!
This installer also installs a copy of the documentation locally, so you can
read it offline. On UNIX systems, `/usr/local/share/doc/rust` is the location.
On Windows, it's in a `share/doc` directory, inside wherever you installed Rust
to.
If not, there are a number of places where you can get help. The easiest is
[the #rust IRC channel on irc.mozilla.org][irc], which you can access through
[Mibbit][mibbit]. Click that link, and you'll be chatting with other Rustaceans
(a silly nickname we call ourselves), and we can help you out. Other great
resources include [the users forum][users], and [Stack Overflow][stack
overflow].
[irc]: irc://irc.mozilla.org/#rust
[mibbit]: http://chat.mibbit.com/?server=irc.mozilla.org&channel=%23rust
[users]: http://users.rust-lang.org/
[stack overflow]: http://stackoverflow.com/questions/tagged/rust

View File

@ -103,7 +103,7 @@ necessary functionality for writing idiomatic and effective Rust code.
As an example, here is a program that will calculate the dot product of two
vectors provided from C, using idiomatic Rust practices.
```
```ignore
#![feature(lang_items, start, no_std, core, libc)]
#![no_std]

View File

@ -0,0 +1,3 @@
% Operators and Overloading
Coming soon!

View File

@ -1,13 +1,16 @@
% Patterns
We've made use of patterns a few times in the guide: first with `let` bindings,
then with `match` statements. Let's go on a whirlwind tour of all of the things
patterns can do!
Patterns are quite common in Rust. We use them in [variable
bindings][bindings], [match statements][match], and other places, too. Lets go
on a whirlwind tour of all of the things patterns can do!
[bindings]: variable-bindings.html
[match]: match.html
A quick refresher: you can match against literals directly, and `_` acts as an
*any* case:
any case:
```{rust}
```rust
let x = 1;
match x {
@ -18,9 +21,11 @@ match x {
}
```
# Multiple patterns
You can match multiple patterns with `|`:
```{rust}
```rust
let x = 1;
match x {
@ -30,9 +35,11 @@ match x {
}
```
# Ranges
You can match a range of values with `...`:
```{rust}
```rust
let x = 1;
match x {
@ -43,10 +50,12 @@ match x {
Ranges are mostly used with integers and single characters.
If you're matching multiple things, via a `|` or a `...`, you can bind
# Bindings
If youre matching multiple things, via a `|` or a `...`, you can bind
the value to a name with `@`:
```{rust}
```rust
let x = 1;
match x {
@ -55,10 +64,12 @@ match x {
}
```
If you're matching on an enum which has variants, you can use `..` to
# Ignoring variants
If youre matching on an enum which has variants, you can use `..` to
ignore the value and type in the variant:
```{rust}
```rust
enum OptionalInt {
Value(i32),
Missing,
@ -72,9 +83,11 @@ match x {
}
```
You can introduce *match guards* with `if`:
# Guards
```{rust}
You can introduce match guards with `if`:
```rust
enum OptionalInt {
Value(i32),
Missing,
@ -89,24 +102,11 @@ match x {
}
```
If you're matching on a pointer, you can use the same syntax as you declared it
with. First, `&`:
# ref and ref mut
```{rust}
let x = &5;
If you want to get a [reference][ref], use the `ref` keyword:
match x {
&val => println!("Got a value: {}", val),
}
```
Here, the `val` inside the `match` has type `i32`. In other words, the left-hand
side of the pattern destructures the value. If we have `&5`, then in `&val`, `val`
would be `5`.
If you want to get a reference, use the `ref` keyword:
```{rust}
```rust
let x = 5;
match x {
@ -114,11 +114,13 @@ match x {
}
```
[ref]: references-and-borrowing.html
Here, the `r` inside the `match` has the type `&i32`. In other words, the `ref`
keyword _creates_ a reference, for use in the pattern. If you need a mutable
reference, `ref mut` will work in the same way:
```{rust}
```rust
let mut x = 5;
match x {
@ -126,10 +128,12 @@ match x {
}
```
If you have a struct, you can destructure it inside of a pattern:
# Destructuring
```{rust}
# #![allow(non_shorthand_field_patterns)]
If you have a compound data type, like a `struct`, you can destructure it
inside of a pattern:
```rust
struct Point {
x: i32,
y: i32,
@ -142,10 +146,9 @@ match origin {
}
```
If we only care about some of the values, we don't have to give them all names:
If we only care about some of the values, we dont have to give them all names:
```{rust}
# #![allow(non_shorthand_field_patterns)]
```rust
struct Point {
x: i32,
y: i32,
@ -160,8 +163,7 @@ match origin {
You can do this kind of match on any member, not just the first:
```{rust}
# #![allow(non_shorthand_field_patterns)]
```rust
struct Point {
x: i32,
y: i32,
@ -174,22 +176,16 @@ match origin {
}
```
If you want to match against a slice or array, you can use `&`:
This destructuring behavior works on any compound data type, like
[tuples][tuples] or [enums][enums].
```{rust}
# #![feature(slice_patterns)]
fn main() {
let v = vec!["match_this", "1"];
[tuples]: primitive-types.html#tuples
[enums]: enums.html
match &v[..] {
["match_this", second] => println!("The second element is {}", second),
_ => {},
}
}
```
# Mix and Match
Whew! That's a lot of different ways to match things, and they can all be
mixed and matched, depending on what you're doing:
Whew! Thats a lot of different ways to match things, and they can all be
mixed and matched, depending on what youre doing:
```{rust,ignore}
match x {

View File

@ -1,699 +0,0 @@
% Pointers
Rust's pointers are one of its more unique and compelling features. Pointers
are also one of the more confusing topics for newcomers to Rust. They can also
be confusing for people coming from other languages that support pointers, such
as C++. This guide will help you understand this important topic.
Be sceptical of non-reference pointers in Rust: use them for a deliberate
purpose, not just to make the compiler happy. Each pointer type comes with an
explanation about when they are appropriate to use. Default to references
unless you're in one of those specific situations.
You may be interested in the [cheat sheet](#cheat-sheet), which gives a quick
overview of the types, names, and purpose of the various pointers.
# An introduction
If you aren't familiar with the concept of pointers, here's a short
introduction. Pointers are a very fundamental concept in systems programming
languages, so it's important to understand them.
## Pointer Basics
When you create a new variable binding, you're giving a name to a value that's
stored at a particular location on the stack. (If you're not familiar with the
*heap* vs. *stack*, please check out [this Stack Overflow
question](http://stackoverflow.com/questions/79923/what-and-where-are-the-stack-and-heap),
as the rest of this guide assumes you know the difference.) Like this:
```{rust}
let x = 5;
let y = 8;
```
| location | value |
|----------|-------|
| 0xd3e030 | 5 |
| 0xd3e028 | 8 |
We're making up memory locations here, they're just sample values. Anyway, the
point is that `x`, the name we're using for our variable, corresponds to the
memory location `0xd3e030`, and the value at that location is `5`. When we
refer to `x`, we get the corresponding value. Hence, `x` is `5`.
Let's introduce a pointer. In some languages, there is just one type of
'pointer,' but in Rust, we have many types. In this case, we'll use a Rust
*reference*, which is the simplest kind of pointer.
```{rust}
let x = 5;
let y = 8;
let z = &y;
```
|location | value |
|-------- |----------|
|0xd3e030 | 5 |
|0xd3e028 | 8 |
|0xd3e020 | 0xd3e028 |
See the difference? Rather than contain a value, the value of a pointer is a
location in memory. In this case, the location of `y`. `x` and `y` have the
type `i32`, but `z` has the type `&i32`. We can print this location using the
`{:p}` format string:
```{rust}
let x = 5;
let y = 8;
let z = &y;
println!("{:p}", z);
```
This would print `0xd3e028`, with our fictional memory addresses.
Because `i32` and `&i32` are different types, we can't, for example, add them
together:
```{rust,ignore}
let x = 5;
let y = 8;
let z = &y;
println!("{}", x + z);
```
This gives us an error:
```text
hello.rs:6:24: 6:25 error: mismatched types: expected `_`, found `&_` (expected integral variable, found &-ptr)
hello.rs:6 println!("{}", x + z);
^
```
We can *dereference* the pointer by using the `*` operator. Dereferencing a
pointer means accessing the value at the location stored in the pointer. This
will work:
```{rust}
let x = 5;
let y = 8;
let z = &y;
println!("{}", x + *z);
```
It prints `13`.
That's it! That's all pointers are: they point to some memory location. Not
much else to them. Now that we've discussed the *what* of pointers, let's
talk about the *why*.
## Pointer uses
Rust's pointers are quite useful, but in different ways than in other systems
languages. We'll talk about best practices for Rust pointers later in
the guide, but here are some ways that pointers are useful in other languages:
In C, strings are a pointer to a list of `char`s, ending with a null byte.
The only way to use strings is to get quite familiar with pointers.
Pointers are useful to point to memory locations that are not on the stack. For
example, our example used two stack variables, so we were able to give them
names. But if we allocated some heap memory, we wouldn't have that name
available. In C, `malloc` is used to allocate heap memory, and it returns a
pointer.
As a more general variant of the previous two points, any time you have a
structure that can change in size, you need a pointer. You can't tell at
compile time how much memory to allocate, so you've gotta use a pointer to
point at the memory where it will be allocated, and deal with it at run time.
Pointers are useful in languages that are pass-by-value, rather than
pass-by-reference. Basically, languages can make two choices (this is made
up syntax, it's not Rust):
```text
func foo(x) {
x = 5
}
func main() {
i = 1
foo(i)
// what is the value of i here?
}
```
In languages that are pass-by-value, `foo` will get a copy of `i`, and so
the original version of `i` is not modified. At the comment, `i` will still be
`1`. In a language that is pass-by-reference, `foo` will get a reference to `i`,
and therefore, can change its value. At the comment, `i` will be `5`.
So what do pointers have to do with this? Well, since pointers point to a
location in memory...
```text
func foo(&i32 x) {
*x = 5
}
func main() {
i = 1
foo(&i)
// what is the value of i here?
}
```
Even in a language which is pass by value, `i` will be `5` at the comment. You
see, because the argument `x` is a pointer, we do send a copy over to `foo`,
but because it points at a memory location, which we then assign to, the
original value is still changed. This pattern is called
*pass-reference-by-value*. Tricky!
## Common pointer problems
We've talked about pointers, and we've sung their praises. So what's the
downside? Well, Rust attempts to mitigate each of these kinds of problems,
but here are problems with pointers in other languages:
Uninitialized pointers can cause a problem. For example, what does this program
do?
```{ignore}
&int x;
*x = 5; // whoops!
```
Who knows? We just declare a pointer, but don't point it at anything, and then
set the memory location that it points at to be `5`. But which location? Nobody
knows. This might be harmless, and it might be catastrophic.
When you combine pointers and functions, it's easy to accidentally invalidate
the memory the pointer is pointing to. For example:
```text
func make_pointer(): &int {
x = 5;
return &x;
}
func main() {
&int i = make_pointer();
*i = 5; // uh oh!
}
```
`x` is local to the `make_pointer` function, and therefore, is invalid as soon
as `make_pointer` returns. But we return a pointer to its memory location, and
so back in `main`, we try to use that pointer, and it's a very similar
situation to our first one. Setting invalid memory locations is bad.
As one last example of a big problem with pointers, *aliasing* can be an
issue. Two pointers are said to alias when they point at the same location
in memory. Like this:
```text
func mutate(&int i, int j) {
*i = j;
}
func main() {
x = 5;
y = &x;
z = &x; //y and z are aliased
run_in_new_thread(mutate, y, 1);
run_in_new_thread(mutate, z, 100);
// what is the value of x here?
}
```
In this made-up example, `run_in_new_thread` spins up a new thread, and calls
the given function name with its arguments. Since we have two threads, and
they're both operating on aliases to `x`, we can't tell which one finishes
first, and therefore, the value of `x` is actually non-deterministic. Worse,
what if one of them had invalidated the memory location they pointed to? We'd
have the same problem as before, where we'd be setting an invalid location.
## Conclusion
That's a basic overview of pointers as a general concept. As we alluded to
before, Rust has different kinds of pointers, rather than just one, and
mitigates all of the problems that we talked about, too. This does mean that
Rust pointers are slightly more complicated than in other languages, but
it's worth it to not have the problems that simple pointers have.
# References
The most basic type of pointer that Rust has is called a *reference*. Rust
references look like this:
```{rust}
let x = 5;
let y = &x;
println!("{}", *y);
println!("{:p}", y);
println!("{}", y);
```
We'd say "`y` is a reference to `x`." The first `println!` prints out the
value of `y`'s referent by using the dereference operator, `*`. The second
one prints out the memory location that `y` points to, by using the pointer
format string. The third `println!` *also* prints out the value of `y`'s
referent, because `println!` will automatically dereference it for us.
Here's a function that takes a reference:
```{rust}
fn succ(x: &i32) -> i32 { *x + 1 }
```
You can also use `&` as an operator to create a reference, so we can
call this function in two different ways:
```{rust}
fn succ(x: &i32) -> i32 { *x + 1 }
fn main() {
let x = 5;
let y = &x;
println!("{}", succ(y));
println!("{}", succ(&x));
}
```
Both of these `println!`s will print out `6`.
Of course, if this were real code, we wouldn't bother with the reference, and
just write:
```{rust}
fn succ(x: i32) -> i32 { x + 1 }
```
References are immutable by default:
```{rust,ignore}
let x = 5;
let y = &x;
*y = 5; // error: cannot assign to immutable borrowed content `*y`
```
They can be made mutable with `mut`, but only if its referent is also mutable.
This works:
```{rust}
let mut x = 5;
let y = &mut x;
```
This does not:
```{rust,ignore}
let x = 5;
let y = &mut x; // error: cannot borrow immutable local variable `x` as mutable
```
Immutable pointers are allowed to alias:
```{rust}
let x = 5;
let y = &x;
let z = &x;
```
Mutable ones, however, are not:
```{rust,ignore}
let mut x = 5;
let y = &mut x;
let z = &mut x; // error: cannot borrow `x` as mutable more than once at a time
```
Despite their complete safety, a reference's representation at runtime is the
same as that of an ordinary pointer in a C program. They introduce zero
overhead. The compiler does all safety checks at compile time. The theory that
allows for this was originally called *region pointers*. Region pointers
evolved into what we know today as *lifetimes*.
Here's the simple explanation: would you expect this code to compile?
```{rust,ignore}
fn main() {
println!("{}", x);
let x = 5;
}
```
Probably not. That's because you know that the name `x` is valid from where
it's declared to when it goes out of scope. In this case, that's the end of
the `main` function. So you know this code will cause an error. We call this
duration a *lifetime*. Let's try a more complex example:
```{rust}
fn main() {
let mut x = 5;
if x < 10 {
let y = &x;
println!("Oh no: {}", y);
return;
}
x -= 1;
println!("Oh no: {}", x);
}
```
Here, we're borrowing a pointer to `x` inside of the `if`. The compiler, however,
is able to determine that that pointer will go out of scope without `x` being
mutated, and therefore, lets us pass. This wouldn't work:
```{rust,ignore}
fn main() {
let mut x = 5;
if x < 10 {
let y = &x;
x -= 1;
println!("Oh no: {}", y);
return;
}
x -= 1;
println!("Oh no: {}", x);
}
```
It gives this error:
```text
test.rs:7:9: 7:15 error: cannot assign to `x` because it is borrowed
test.rs:7 x -= 1;
^~~~~~
test.rs:5:18: 5:19 note: borrow of `x` occurs here
test.rs:5 let y = &x;
^
```
As you might guess, this kind of analysis is complex for a human, and therefore
hard for a computer, too! There is an entire [guide devoted to references, ownership,
and lifetimes](ownership.html) that goes into this topic in
great detail, so if you want the full details, check that out.
## Best practices
In general, prefer stack allocation over heap allocation. Using references to
stack allocated information is preferred whenever possible. Therefore,
references are the default pointer type you should use, unless you have a
specific reason to use a different type. The other types of pointers cover when
they're appropriate to use in their own best practices sections.
Use references when you want to use a pointer, but do not want to take ownership.
References just borrow ownership, which is more polite if you don't need the
ownership. In other words, prefer:
```{rust}
fn succ(x: &i32) -> i32 { *x + 1 }
```
to
```{rust}
fn succ(x: Box<i32>) -> i32 { *x + 1 }
```
As a corollary to that rule, references allow you to accept a wide variety of
other pointers, and so are useful so that you don't have to write a number
of variants per pointer. In other words, prefer:
```{rust}
fn succ(x: &i32) -> i32 { *x + 1 }
```
to
```{rust}
use std::rc::Rc;
fn box_succ(x: Box<i32>) -> i32 { *x + 1 }
fn rc_succ(x: Rc<i32>) -> i32 { *x + 1 }
```
Note that the caller of your function will have to modify their calls slightly:
```{rust}
use std::rc::Rc;
fn succ(x: &i32) -> i32 { *x + 1 }
let ref_x = &5;
let box_x = Box::new(5);
let rc_x = Rc::new(5);
succ(ref_x);
succ(&*box_x);
succ(&*rc_x);
```
The initial `*` dereferences the pointer, and then `&` takes a reference to
those contents.
# Boxes
`Box<T>` is Rust's *boxed pointer* type. Boxes provide the simplest form of
heap allocation in Rust. Creating a box looks like this:
```{rust}
let x = Box::new(5);
```
Boxes are heap allocated and they are deallocated automatically by Rust when
they go out of scope:
```{rust}
{
let x = Box::new(5);
// stuff happens
} // x is destructed and its memory is free'd here
```
However, boxes do _not_ use reference counting or garbage collection. Boxes are
what's called an *affine type*. This means that the Rust compiler, at compile
time, determines when the box comes into and goes out of scope, and inserts the
appropriate calls there.
You don't need to fully grok the theory of affine types to grok boxes, though.
As a rough approximation, you can treat this Rust code:
```{rust}
{
let x = Box::new(5);
// stuff happens
}
```
As being similar to this C code:
```c
{
int *x;
x = (int *)malloc(sizeof(int));
*x = 5;
// stuff happens
free(x);
}
```
Of course, this is a 10,000 foot view. It leaves out destructors, for example.
But the general idea is correct: you get the semantics of `malloc`/`free`, but
with some improvements:
1. It's impossible to allocate the incorrect amount of memory, because Rust
figures it out from the types.
2. You cannot forget to `free` memory you've allocated, because Rust does it
for you.
3. Rust ensures that this `free` happens at the right time, when it is truly
not used. Use-after-free is not possible.
4. Rust enforces that no other writeable pointers alias to this heap memory,
which means writing to an invalid pointer is not possible.
See the section on references or the [ownership guide](ownership.html)
for more detail on how lifetimes work.
Using boxes and references together is very common. For example:
```{rust}
fn add_one(x: &i32) -> i32 {
*x + 1
}
fn main() {
let x = Box::new(5);
println!("{}", add_one(&*x));
}
```
In this case, Rust knows that `x` is being *borrowed* by the `add_one()`
function, and since it's only reading the value, allows it.
We can borrow `x` as read-only multiple times, even simultaneously:
```{rust}
fn add(x: &i32, y: &i32) -> i32 {
*x + *y
}
fn main() {
let x = Box::new(5);
println!("{}", add(&*x, &*x));
println!("{}", add(&*x, &*x));
}
```
We can mutably borrow `x` multiple times, but only if x itself is mutable, and
it may not be *simultaneously* borrowed:
```{rust,ignore}
fn increment(x: &mut i32) {
*x += 1;
}
fn main() {
// If variable x is not "mut", this will not compile
let mut x = Box::new(5);
increment(&mut x);
increment(&mut x);
println!("{}", x);
}
```
Notice the signature of `increment()` requests a mutable reference.
## Best practices
Boxes are most appropriate to use when defining recursive data structures.
### Recursive data structures
Sometimes, you need a recursive data structure. The simplest is known as a
*cons list*:
```{rust}
#[derive(Debug)]
enum List<T> {
Cons(T, Box<List<T>>),
Nil,
}
fn main() {
let list: List<i32> = List::Cons(1, Box::new(List::Cons(2, Box::new(List::Cons(3, Box::new(List::Nil))))));
println!("{:?}", list);
}
```
This prints:
```text
Cons(1, Box(Cons(2, Box(Cons(3, Box(Nil))))))
```
The reference to another `List` inside of the `Cons` enum variant must be a box,
because we don't know the length of the list. Because we don't know the length,
we don't know the size, and therefore, we need to heap allocate our list.
Working with recursive or other unknown-sized data structures is the primary
use-case for boxes.
# Rc and Arc
This part is coming soon.
## Best practices
This part is coming soon.
# Raw Pointers
This part is coming soon.
## Best practices
This part is coming soon.
# Creating your own Pointers
This part is coming soon.
## Best practices
This part is coming soon.
# Patterns and `ref`
When you're trying to match something that's stored in a pointer, there may be
a situation where matching directly isn't the best option available. Let's see
how to properly handle this:
```{rust,ignore}
fn possibly_print(x: &Option<String>) {
match *x {
// BAD: cannot move out of a `&`
Some(s) => println!("{}", s)
// GOOD: instead take a reference into the memory of the `Option`
Some(ref s) => println!("{}", *s),
None => {}
}
}
```
The `ref s` here means that `s` will be of type `&String`, rather than type
`String`.
This is important when the type you're trying to get access to has a destructor
and you don't want to move it, you just want a reference to it.
# Cheat Sheet
Here's a quick rundown of Rust's pointer types:
| Type | Name | Summary |
|--------------|---------------------|---------------------------------------------------------------------|
| `&T` | Reference | Allows one or more references to read `T` |
| `&mut T` | Mutable Reference | Allows a single reference to read and write `T` |
| `Box<T>` | Box | Heap allocated `T` with a single owner that may read and write `T`. |
| `Rc<T>` | "arr cee" pointer | Heap allocated `T` with many readers |
| `Arc<T>` | Arc pointer | Same as above, but safe sharing across threads |
| `*const T` | Raw pointer | Unsafe read access to `T` |
| `*mut T` | Mutable raw pointer | Unsafe read and write access to `T` |
# Related resources
* [API documentation for Box](../std/boxed/index.html)
* [Ownership guide](ownership.html)
* [Cyclone paper on regions](http://www.cs.umd.edu/projects/cyclone/papers/cyclone-regions.pdf), which inspired Rust's lifetime system

View File

@ -0,0 +1,268 @@
% Primitive Types
The Rust language has a number of types that are considered primitive. This
means that theyre built-in to the language. Rust is structured in such a way
that the standard library also provides a number of useful types built on top
of these ones, as well, but these are the most primitive.
# Booleans
Rust has a built in boolean type, named `bool`. It has two values, `true` and `false`:
```rust
let x = true;
let y: bool = false;
```
A common use of booleans is in [`if` statements][if].
[if]: if.html
You can find more documentation for `bool`s [in the standard library
documentation][bool].
[bool]: ../std/primitive.bool.html
# `char`
The `char` type represents a single Unicode scalar value. You can create `char`s
with a single tick: (`'`)
```rust
let x = 'x';
let two_hearts = '💕';
```
Unlike some other languages, this means that Rusts `char` is not a single byte,
but four.
You can find more documentation for `char`s [in the standard library
documentation][char].
[char]: ../std/primitive.char.html
# Numeric types
Rust has a variety of numeric types in a few categories: signed and unsigned,
fixed and variable, floating-point and integer.
These types consist of two parts: the category, and the size. For example,
`u16` is an unsigned type with sixteen bits of size. More bits lets you have
bigger numbers.
If a number literal has nothing to cause its type to be inferred, it defaults:
```rust
let x = 42; // x has type i32
let y = 1.0; // y has type f64
```
Heres a list of the different numeric types, with links to their documentation
in the standard library:
* [i16](../std/primitive.i16.html)
* [i32](../std/primitive.i32.html)
* [i64](../std/primitive.i64.html)
* [i8](../std/primitive.i8.html)
* [u16](../std/primitive.u16.html)
* [u32](../std/primitive.u32.html)
* [u64](../std/primitive.u64.html)
* [u8](../std/primitive.u8.html)
* [isize](../std/primitive.isize.html)
* [usize](../std/primitive.usize.html)
* [f32](../std/primitive.f32.html)
* [f64](../std/primitive.f64.html)
Lets go over them by category:
## Signed and Unsigned
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
number would let you store numbers from `-8` to `+7`. Signed numbers use
twos compliment representation. An unsigned four bit number, since it does
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`
is for integer. So `u8` is an eight-bit unsigned number, and `i8` is an
eight-bit signed number.
## Fixed size types
Fixed size types have a specific number of bits in their representation. Valid
bit sizes are `8`, `16`, `32`, and `64`. So, `u32` is an unsigned, 32-bit integer,
and `i64` is a signed, 64-bit integer.
## Variable sized types
Rust also provides types whose size depends on the size of a pointer of the
underlying machine. These types have size as the category, and come in signed
and unsigned varieties. This makes for two types: `isize` and `usize`.
## Floating-point types
Rust also two floating point types: `f32` and `f64`. These correspond to
IEEE-754 single and double precision numbers.
# Arrays
Like many programming languages, Rust has list types to represent a sequence of
things. The most basic is the *array*, a fixed-size list of elements of the
same type. By default, arrays are immutable.
```rust
let a = [1, 2, 3]; // a: [i32; 3]
let mut m = [1, 2, 3]; // m: [i32; 3]
```
Arrays have type `[T; N]`. Well talk about this `T` notation [in the generics
section][generics]. The `N` is a compile-time constant, for the length of the
array.
Theres a shorthand for initializing each element of an array to the same
value. In this example, each element of `a` will be initialized to `0`:
```rust
let a = [0; 20]; // a: [i32; 20]
```
You can get the number of elements in an array `a` with `a.len()`:
```rust
let a = [1, 2, 3];
println!("a has {} elements", a.len());
```
You can access a particular element of an array with *subscript notation*:
```rust
let names = ["Graydon", "Brian", "Niko"]; // names: [&str; 3]
println!("The second name is: {}", names[1]);
```
Subscripts start at zero, like in most programming languages, so the first name
is `names[0]` and the second name is `names[1]`. The above example prints
`The second name is: Brian`. If you try to use a subscript that is not in the
array, you will get an error: array access is bounds-checked at run-time. Such
errant access is the source of many bugs in other systems programming
languages.
You can find more documentation for `array`s [in the standard library
documentation][array].
[array]: ../std/primitive.array.html
# Slices
A slice is a reference to (or “view” into) another data structure. They are
useful for allowing safe, efficient access to a portion of an array without
copying. For example, you might want to reference just one line of a file read
into memory. By nature, a slice is not created directly, but from an existing
variable. Slices have a length, can be mutable or not, and in many ways behave
like arrays:
```rust
let a = [0, 1, 2, 3, 4];
let middle = &a[1..4]; // A slice of a: just the elements 1, 2, and 3
```
Slices have type `&[T]`. Well talk about that `T` when we cover
[generics][generics].
[generics]: generics.html
You can find more documentation for `slices`s [in the standard library
documentation][slice].
[slice]: ../std/primitive.slice.html
# `str`
Rusts `str` type is the most primitive string type. As an [unsized type][dst],
its not very useful by itself, but becomes useful when placed behind a reference,
like [`&str`][strings]. As such, well just leave it at that.
[dst]: unsized-types.html
[strings]: strings.html
You can find more documentation for `str` [in the standard library
documentation][str].
[str]: ../std/primitive.str.html
# Tuples
A tuple is an ordered list of fixed size. Like this:
```rust
let x = (1, "hello");
```
The parentheses and commas form this two-length tuple. Heres the same code, but
with the type annotated:
```rust
let x: (i32, &str) = (1, "hello");
```
As you can see, the type of a tuple looks just like the tuple, but with each
position having a type name rather than the value. Careful readers will also
note that tuples are heterogeneous: we have an `i32` and a `&str` in this tuple.
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
soon.
You can access the fields in a tuple through a *destructuring let*. Heres
an example:
```rust
let (x, y, z) = (1, 2, 3);
println!("x is {}", x);
```
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
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,"
or "breaks up," the tuple, and assigns the bits to three bindings.
[let]: variable-bindings.html
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
destructuring. 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 find more documentation for tuples [in the standard library
documentation][tuple].
[tuple]: ../std/primitive.tuple.html
# Functions
Functions also have a type! They look like this:
```
fn foo(x: i32) -> i32 { x }
let x: fn(i32) -> i32 = foo;
```
In this case, `x` is a function pointer to a function that takes an `i32` and
returns an `i32`.

View File

@ -0,0 +1,3 @@
% References and Borrowing
Coming Soon!

View File

@ -0,0 +1,18 @@
% Slice patterns
If you want to match against a slice or array, you can use `&` with the
`slice_patterns` feature:
```rust
#![feature(slice_patterns)]
fn main() {
let v = vec!["match_this", "1"];
match &v[..] {
["match_this", second] => println!("The second element is {}", second),
_ => {},
}
}
```

3
src/doc/trpl/static.md Normal file
View File

@ -0,0 +1,3 @@
% `static`
Coming soon!

89
src/doc/trpl/structs.md Normal file
View File

@ -0,0 +1,89 @@
% Structs
Structs are a way of creating more complex datatypes. For example, if we were
doing calculations involving coordinates in 2D space, we would need both an `x`
and a `y` value:
```rust
let origin_x = 0;
let origin_y = 0;
```
A struct lets us combine these two into a single, unified datatype:
```rust
struct Point {
x: i32,
y: i32,
}
fn main() {
let origin = Point { x: 0, y: 0 }; // origin: Point
println!("The origin is at ({}, {})", origin.x, origin.y);
}
```
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
capital letter and are also camel cased: `PointInSpace`, not `Point_In_Space`.
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
in the original declaration.
Finally, because fields have names, we can access the field through dot
notation: `origin.x`.
The values in structs are immutable by default, like other bindings in Rust.
Use `mut` to make them mutable:
```rust
struct Point {
x: i32,
y: i32,
}
fn main() {
let mut point = Point { x: 0, y: 0 };
point.x = 5;
println!("The point is at ({}, {})", point.x, point.y);
}
```
This will print `The point is at (5, 0)`.
Rust does not support field mutability at the language level, so you cannot
write something like this:
```rust,ignore
struct Point {
mut x: i32,
y: i32,
}
```
Mutability is a property of the binding, not of the structure itself. If youre
used to field-level mutability, this may seem strange at first, but it
significantly simplifies things. It even lets you make things mutable for a short
time only:
```rust,ignore
struct Point {
x: i32,
y: i32,
}
fn main() {
let mut point = Point { x: 0, y: 0 };
point.x = 5;
let point = point; // this new binding cant change now
point.y = 6; // this causes an error
}
```

View File

@ -0,0 +1,10 @@
% Syntax and Semantics
This section breaks Rust down into small chunks, one for each concept.
If youd like to learn Rust from the bottom up, reading this in order is a
great way to do that.
These sections also form a reference for each concept, so if youre reading
another tutorial and find something confusing, you can find it explained
somewhere in here.

View File

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

View File

@ -0,0 +1,3 @@
% The Stack and the Heap
Coming Soon

View File

@ -1,91 +0,0 @@
% Tracing Macros
The `trace_macros` feature allows you to use a special feature: tracing macro
invocations.
In the advanced macros chapter, we defined a `bct` macro:
```rust
macro_rules! bct {
// cmd 0: d ... => ...
(0, $($ps:tt),* ; $_d:tt)
=> (bct!($($ps),*, 0 ; ));
(0, $($ps:tt),* ; $_d:tt, $($ds:tt),*)
=> (bct!($($ps),*, 0 ; $($ds),*));
// cmd 1p: 1 ... => 1 ... p
(1, $p:tt, $($ps:tt),* ; 1)
=> (bct!($($ps),*, 1, $p ; 1, $p));
(1, $p:tt, $($ps:tt),* ; 1, $($ds:tt),*)
=> (bct!($($ps),*, 1, $p ; 1, $($ds),*, $p));
// cmd 1p: 0 ... => 0 ...
(1, $p:tt, $($ps:tt),* ; $($ds:tt),*)
=> (bct!($($ps),*, 1, $p ; $($ds),*));
// halt on empty data string
( $($ps:tt),* ; )
=> (());
}
```
This is pretty complex! we can see the output
```rust,ignore
#![feature(trace_macros)]
macro_rules! bct {
// cmd 0: d ... => ...
(0, $($ps:tt),* ; $_d:tt)
=> (bct!($($ps),*, 0 ; ));
(0, $($ps:tt),* ; $_d:tt, $($ds:tt),*)
=> (bct!($($ps),*, 0 ; $($ds),*));
// cmd 1p: 1 ... => 1 ... p
(1, $p:tt, $($ps:tt),* ; 1)
=> (bct!($($ps),*, 1, $p ; 1, $p));
(1, $p:tt, $($ps:tt),* ; 1, $($ds:tt),*)
=> (bct!($($ps),*, 1, $p ; 1, $($ds),*, $p));
// cmd 1p: 0 ... => 0 ...
(1, $p:tt, $($ps:tt),* ; $($ds:tt),*)
=> (bct!($($ps),*, 1, $p ; $($ds),*));
// halt on empty data string
( $($ps:tt),* ; )
=> (());
}
fn main() {
trace_macros!(true);
bct!(0, 0, 1, 1, 1 ; 1, 0, 1);
}
```
This will print out a wall of text:
```text
bct! { 0 , 0 , 1 , 1 , 1 ; 1 , 0 , 1 }
bct! { 0 , 1 , 1 , 1 , 0 ; 0 , 1 }
bct! { 1 , 1 , 1 , 0 , 0 ; 1 }
bct! { 1 , 0 , 0 , 1 , 1 ; 1 , 1 }
bct! { 0 , 1 , 1 , 1 , 0 ; 1 , 1 , 0 }
bct! { 1 , 1 , 1 , 0 , 0 ; 1 , 0 }
bct! { 1 , 0 , 0 , 1 , 1 ; 1 , 0 , 1 }
bct! { 0 , 1 , 1 , 1 , 0 ; 1 , 0 , 1 , 0 }
bct! { 1 , 1 , 1 , 0 , 0 ; 0 , 1 , 0 }
bct! { 1 , 0 , 0 , 1 , 1 ; 0 , 1 , 0 }
bct! { 0 , 1 , 1 , 1 , 0 ; 0 , 1 , 0 }
```
And eventually, error:
```text
18:45 error: recursion limit reached while expanding the macro `bct`
=> (bct!($($ps),*, 1, $p ; $($ds),*));
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
```
The `trace_macros!` call is what produces this output, showing how we match
each time.

View File

@ -1,4 +1,4 @@
% Static and Dynamic Dispatch
% Trait Objects
When code involves polymorphism, there needs to be a mechanism to determine
which specific version is actually run. This is called 'dispatch.' There are

View File

@ -229,8 +229,6 @@ everything is fine:
```{rust}
# #![feature(core)]
use shapes::HasArea;
mod shapes {
use std::f64::consts;
@ -251,6 +249,7 @@ mod shapes {
}
}
use shapes::HasArea;
fn main() {
let c = shapes::Circle {
@ -274,8 +273,8 @@ not, because both the trait and the type aren't in our crate.
One last thing about traits: generic functions with a trait bound use
*monomorphization* (*mono*: one, *morph*: form), so they are statically
dispatched. What's that mean? Check out the chapter on [static and dynamic
dispatch](static-and-dynamic-dispatch.html) for more.
dispatched. What's that mean? Check out the chapter on [trait
objects](trait-objects.html) for more.
## Multiple trait bounds
@ -390,81 +389,6 @@ This shows off the additional feature of `where` clauses: they allow bounds
where the left-hand side is an arbitrary type (`i32` in this case), not just a
plain type parameter (like `T`).
## Our `inverse` Example
Back in [Generics](generics.html), we were trying to write code like this:
```{rust,ignore}
fn inverse<T>(x: T) -> Result<T, String> {
if x == 0.0 { return Err("x cannot be zero!".to_string()); }
Ok(1.0 / x)
}
```
If we try to compile it, we get this error:
```text
error: binary operation `==` cannot be applied to type `T`
```
This is because `T` is too generic: we don't know if a random `T` can be
compared. For that, we can use trait bounds. It doesn't quite work, but try
this:
```{rust,ignore}
fn inverse<T: PartialEq>(x: T) -> Result<T, String> {
if x == 0.0 { return Err("x cannot be zero!".to_string()); }
Ok(1.0 / x)
}
```
You should get this error:
```text
error: mismatched types:
expected `T`,
found `_`
(expected type parameter,
found floating-point variable)
```
So this won't work. While our `T` is `PartialEq`, we expected to have another `T`,
but instead, we found a floating-point variable. We need a different bound. `Float`
to the rescue:
```
# #![feature(std_misc)]
use std::num::Float;
fn inverse<T: Float>(x: T) -> Result<T, String> {
if x == Float::zero() { return Err("x cannot be zero!".to_string()) }
let one: T = Float::one();
Ok(one / x)
}
```
We've had to replace our generic `0.0` and `1.0` with the appropriate methods
from the `Float` trait. Both `f32` and `f64` implement `Float`, so our function
works just fine:
```
# #![feature(std_misc)]
# use std::num::Float;
# fn inverse<T: Float>(x: T) -> Result<T, String> {
# if x == Float::zero() { return Err("x cannot be zero!".to_string()) }
# let one: T = Float::one();
# Ok(one / x)
# }
println!("the inverse of {} is {:?}", 2.0f32, inverse(2.0f32));
println!("the inverse of {} is {:?}", 2.0f64, inverse(2.0f64));
println!("the inverse of {} is {:?}", 0.0f32, inverse(0.0f32));
println!("the inverse of {} is {:?}", 0.0f64, inverse(0.0f64));
```
## Default methods
There's one last feature of traits we should cover: default methods. It's

View File

@ -0,0 +1,56 @@
% Tuple Structs
Rust has another data type that's like a hybrid between a tuple and a struct,
called a *tuple struct*. Tuple structs do have a name, but their fields don't:
```{rust}
struct Color(i32, i32, i32);
struct Point(i32, i32, i32);
```
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 that's 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`, as we discussed previously in 'tuples.' In this case, the
`let Inches(integer_length)` assigns `10` to `integer_length`.

View File

@ -0,0 +1,3 @@
% `type` Aliases
Coming soon

3
src/doc/trpl/ufcs.md Normal file
View File

@ -0,0 +1,3 @@
% Universal Function Call Syntax
Coming soon

View File

@ -1,4 +1,4 @@
% Unsafe and Low-Level Code
% Unsafe Code
# Introduction

View File

@ -0,0 +1,3 @@
% Unsized Types
Coming Soon!

View File

@ -1 +0,0 @@
% Unstable Rust

View File

@ -1,44 +1,48 @@
% Variable Bindings
The first thing we'll learn about are *variable bindings*. They look like this:
Vitually every non-Hello World Rust program uses *variable bindings*. They
look like this:
```{rust}
```rust
fn main() {
let x = 5;
}
```
Putting `fn main() {` in each example is a bit tedious, so we'll leave that out
in the future. If you're following along, make sure to edit your `main()`
function, rather than leaving it off. Otherwise, you'll get an error.
Putting `fn main() {` in each example is a bit tedious, so well leave that out
in the future. If youre following along, make sure to edit your `main()`
function, rather than leaving it off. Otherwise, youll get an error.
In many languages, this is called a *variable*. But Rust's variable bindings
have a few tricks up their sleeves. Rust has a very powerful feature called
*pattern matching* that we'll get into detail with later, but the left
hand side of a `let` expression is a full pattern, not just a variable name.
This means we can do things like:
In many languages, this is called a *variable*, but Rusts variable bindings
have a few tricks up their sleeves. For example the left-hand side of a `let`
expression is a [pattern][pattern], not just a variable name. This means we
can do things like:
```{rust}
```rust
let (x, y) = (1, 2);
```
After this expression is evaluated, `x` will be one, and `y` will be two.
Patterns are really powerful, but this is about all we can do with them so far.
So let's just keep this in the back of our minds as we go forward.
Patterns are really powerful, and have [their own section][pattern] in the
book. We dont need those features for now, so well just keep this in the back
of our minds as we go forward.
[pattern]: patterns.html
Rust is a statically typed language, which means that we specify our types up
front. So why does our first example compile? Well, Rust has this thing called
*type inference*. If it can figure out what the type of something is, Rust
doesn't require you to actually type it out.
front, and theyre checked at compile time. So why does our first example
compile? Well, Rust has this thing called type inference. If it can figure
out what the type of something is, Rust doesnt require you to actually type it
out.
We can add the type if we want to, though. Types come after a colon (`:`):
```{rust}
```rust
let x: i32 = 5;
```
If I asked you to read this out loud to the rest of the class, you'd say "`x`
is a binding with the type `i32` and the value `five`."
If I asked you to read this out loud to the rest of the class, youd say “`x`
is a binding with the type `i32` and the value `five`.
In this case we chose to represent `x` as a 32-bit signed integer. Rust has
many different primitive integer types. They begin with `i` for signed integers
@ -48,19 +52,20 @@ bits.
In future examples, we may annotate the type in a comment. The examples will
look like this:
```{rust}
```rust
fn main() {
let x = 5; // x: i32
}
```
Note the similarities between this annotation and the syntax you use with `let`.
Including these kinds of comments is not idiomatic Rust, but we'll occasionally
include them to help you understand what the types that Rust infers are.
Note the similarities between this annotation and the syntax you use with
`let`. Including these kinds of comments is not idiomatic Rust, but we'll
occasionally include them to help you understand what the types that Rust
infers are.
By default, bindings are *immutable*. This code will not compile:
```{ignore}
```rust,ignore
let x = 5;
x = 10;
```
@ -75,30 +80,30 @@ error: re-assignment of immutable variable `x`
If you want a binding to be mutable, you can use `mut`:
```{rust}
```rust
let mut x = 5; // mut x: i32
x = 10;
```
There is no single reason that bindings are immutable by default, but we can
think about it through one of Rust's primary focuses: safety. If you forget to
think about it through one of Rusts primary focuses: safety. If you forget to
say `mut`, the compiler will catch it, and let you know that you have mutated
something you may not have intended to mutate. If bindings were mutable by
default, the compiler would not be able to tell you this. If you _did_ intend
mutation, then the solution is quite easy: add `mut`.
There are other good reasons to avoid mutable state when possible, but they're
There are other good reasons to avoid mutable state when possible, but theyre
out of the scope of this guide. In general, you can often avoid explicit
mutation, and so it is preferable in Rust. That said, sometimes, mutation is
what you need, so it's not verboten.
what you need, so its not verboten.
Let's get back to bindings. Rust variable bindings have one more aspect that
Lets get back to bindings. Rust variable bindings have one more aspect that
differs from other languages: bindings are required to be initialized with a
value before you're allowed to use them.
Let's try it out. Change your `src/main.rs` file to look like this:
Lets try it out. Change your `src/main.rs` file to look like this:
```{rust}
```rust
fn main() {
let x: i32;
@ -106,21 +111,22 @@ fn main() {
}
```
You can use `cargo build` on the command line to build it. You'll get a warning,
but it will still print "Hello, world!":
You can use `cargo build` on the command line to build it. Youll get a
warning, but it will still print "Hello, world!":
```text
Compiling hello_world v0.0.1 (file:///home/you/projects/hello_world)
src/main.rs:2:9: 2:10 warning: unused variable: `x`, #[warn(unused_variable)] on by default
src/main.rs:2:9: 2:10 warning: unused variable: `x`, #[warn(unused_variable)]
on by default
src/main.rs:2 let x: i32;
^
```
Rust warns us that we never use the variable binding, but since we never use it,
no harm, no foul. Things change if we try to actually use this `x`, however. Let's
do that. Change your program to look like this:
Rust warns us that we never use the variable binding, but since we never use
it, no harm, no foul. Things change if we try to actually use this `x`,
however. Lets do that. Change your program to look like this:
```{rust,ignore}
```rust,ignore
fn main() {
let x: i32;
@ -128,9 +134,9 @@ fn main() {
}
```
And try to build it. You'll get an error:
And try to build it. Youll get an error:
```{bash}
```bash
$ cargo build
Compiling hello_world v0.0.1 (file:///home/you/projects/hello_world)
src/main.rs:4:39: 4:40 error: use of possibly uninitialized variable: `x`
@ -144,18 +150,20 @@ error: aborting due to previous error
Could not compile `hello_world`.
```
Rust will not let us use a value that has not been initialized. Next, let's
Rust will not let us use a value that has not been initialized. Next, lets
talk about this stuff we've added to `println!`.
If you include two curly braces (`{}`, some call them moustaches...) in your
string to print, Rust will interpret this as a request to interpolate some sort
of value. *String interpolation* is a computer science term that means "stick
in the middle of a string." We add a comma, and then `x`, to indicate that we
want `x` to be the value we're interpolating. The comma is used to separate
arguments we pass to functions and macros, if you're passing more than one.
want `x` to be the value were interpolating. The comma is used to separate
arguments we pass to functions and macros, if youre passing more than one.
When you just use the curly braces, Rust will attempt to display the
value in a meaningful way by checking out its type. If you want to specify the
format in a more detailed manner, there are a [wide number of options
available](../std/fmt/index.html). For now, we'll just stick to the default:
integers aren't very complicated to print.
When you just use the curly braces, Rust will attempt to display the value in a
meaningful way by checking out its type. If you want to specify the format in a
more detailed manner, there are a [wide number of options available][format].
For now, we'll just stick to the default: integers aren't very complicated to
print.
[format]: ../std/fmt/index.html

32
src/doc/trpl/vectors.md Normal file
View File

@ -0,0 +1,32 @@
% Vectors
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
what `String` is to `&str`. You can create them with the `vec!` macro:
```{rust}
let v = vec![1, 2, 3]; // v: Vec<i32>
```
(Notice that unlike the `println!` macro we've used in the past, we use square
brackets `[]` with `vec!`. Rust allows you to use either in either situation,
this is just convention.)
There's an alternate form of `vec!` for repeating an initial value:
```
let v = vec![0; 10]; // ten zeroes
```
You can get the length of, iterate over, and subscript vectors just like
arrays. In addition, (mutable) vectors can grow automatically:
```{rust}
let mut nums = vec![1, 2, 3]; // mut nums: Vec<i32>
nums.push(4);
println!("The length of nums is now {}", nums.len()); // Prints 4
```
Vectors have many more useful methods.

View File

@ -0,0 +1,93 @@
% while loops
Rust also has a `while` loop. It looks like this:
```{rust}
let mut x = 5; // mut x: u32
let mut done = false; // mut done: bool
while !done {
x += x - 3;
println!("{}", x);
if x % 5 == 0 {
done = true;
}
}
```
`while` loops are the correct choice when youre not sure how many times
you need to loop.
If you need an infinite loop, you may be tempted to write this:
```rust,ignore
while true {
```
However, Rust has a dedicated keyword, `loop`, to handle this case:
```rust,ignore
loop {
```
Rusts control-flow analysis treats this construct differently than a `while
true`, since we know that it will always loop. In general, the more information
we can give to the compiler, the better it can do with safety and code
generation, so you should always prefer `loop` when you plan to loop
infinitely.
## Ending iteration early
Lets take a look at that `while` loop we had earlier:
```rust
let mut x = 5;
let mut done = false;
while !done {
x += x - 3;
println!("{}", x);
if x % 5 == 0 {
done = true;
}
}
```
We had to keep a dedicated `mut` boolean variable binding, `done`, to know
when we should exit out of the loop. Rust has two keywords to help us with
modifying iteration: `break` and `continue`.
In this case, we can write the loop in a better way with `break`:
```rust
let mut x = 5;
loop {
x += x - 3;
println!("{}", x);
if x % 5 == 0 { break; }
}
```
We now loop forever with `loop` and use `break` to break out early.
`continue` is similar, but instead of ending the loop, goes to the next
iteration. This will only print the odd numbers:
```rust
for x in 0..10 {
if x % 2 == 0 { continue; }
println!("{}", x);
}
```
Both `continue` and `break` are valid in both `while` loops and [`for` loops][for].
[for]: for-loops.html

View File

@ -9,6 +9,7 @@
# except according to those terms.
import gdb
import re
#===============================================================================
# GDB Pretty Printing Module for Rust
@ -299,12 +300,12 @@ def classify_struct(type):
if fields[0].name == "RUST$ENUM$DISR":
if field_count == 1:
return STRUCT_KIND_CSTYLE_VARIANT
elif fields[1].name is None:
elif all_fields_conform_to_tuple_field_naming(fields, 1):
return STRUCT_KIND_TUPLE_VARIANT
else:
return STRUCT_KIND_STRUCT_VARIANT
if fields[0].name is None:
if all_fields_conform_to_tuple_field_naming(fields, 0):
if type.tag.startswith("("):
return STRUCT_KIND_TUPLE
else:
@ -325,7 +326,6 @@ def first_field(val):
for field in val.type.fields():
return field
def get_field_at_index(val, index):
i = 0
for field in val.type.fields():
@ -334,6 +334,12 @@ def get_field_at_index(val, index):
i += 1
return None
def all_fields_conform_to_tuple_field_naming(fields, start_index):
for i in range(start_index, len(fields)):
if (fields[i].name is None) or (re.match(r"__\d+$", fields[i].name) is None):
return False
return True
def extract_length_and_data_ptr_from_std_vec(vec_val):
length = int(vec_val["len"])
vec_ptr_val = vec_val["ptr"]

View File

@ -186,7 +186,8 @@ def concat_multi_lines(f):
firstlineno = firstlineno or lineno
if line.endswith('\\'):
lastline = line[:-1]
if lastline is None:
lastline = line[:-1]
catenated += line[:-1]
else:
yield firstlineno, catenated + line

View File

@ -9,7 +9,7 @@
# except according to those terms.
import lldb
import re
def print_val(val, internal_dict):
'''Prints the given value with Rust syntax'''
@ -61,14 +61,14 @@ def print_struct_val_starting_from(field_start_index, val, internal_dict):
# The only field of this struct is the enum discriminant
return type_name
has_field_names = type_has_field_names(t)
is_tuple_like = type_is_tuple_like(t)
if has_field_names:
template = "%(type_name)s {\n%(body)s\n}"
separator = ", \n"
else:
if is_tuple_like:
template = "%(type_name)s(%(body)s)"
separator = ", "
else:
template = "%(type_name)s {\n%(body)s\n}"
separator = ", \n"
if type_name.startswith("("):
# this is a tuple, so don't print the type name
@ -76,7 +76,7 @@ def print_struct_val_starting_from(field_start_index, val, internal_dict):
def render_child(child_index):
this = ""
if has_field_names:
if not is_tuple_like:
field_name = t.GetFieldAtIndex(child_index).GetName()
this += field_name + ": "
@ -233,13 +233,15 @@ def extract_type_name(qualified_type_name):
return qualified_type_name[index + 2:]
def type_has_field_names(ty):
def type_is_tuple_like(ty):
'''Returns true of this is a type with field names (struct, struct-like enum variant)'''
# This may also be an enum variant where the first field doesn't have a name but the rest has
if ty.GetNumberOfFields() > 1:
return ty.GetFieldAtIndex(1).GetName() is not None
else:
return ty.GetFieldAtIndex(0).GetName() is not None
for field in ty.fields:
if field.GetName() == "RUST$ENUM$DISR":
# Ignore the enum discriminant field if there is one.
continue
if (field.GetName() is None) or (re.match(r"__\d+$", field.GetName()) is None):
return False
return True
def is_vec_slice(val):

View File

@ -1,615 +0,0 @@
#!/bin/sh
# Copyright 2014 The Rust Project Developers. See the COPYRIGHT
# file at the top-level directory of this distribution and at
# http://rust-lang.org/COPYRIGHT.
#
# Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
# http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
# <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
# option. This file may not be copied, modified, or distributed
# except according to those terms.
msg() {
echo "rustup: $1"
}
step_msg() {
msg
msg "$1"
msg
}
warn() {
echo "rustup: WARNING: $1"
}
err() {
echo "rustup: error: $1"
exit 1
}
need_ok() {
if [ $? -ne 0 ]
then
err "$1"
fi
}
putvar() {
local T
eval T=\$$1
eval TLEN=\${#$1}
if [ $TLEN -gt 35 ]
then
printf "rustup: %-20s := %.35s ...\n" $1 "$T"
else
printf "rustup: %-20s := %s %s\n" $1 "$T" "$2"
fi
}
probe() {
local V=$1
shift
local P
local T
for P
do
T=$(which $P 2>&1)
if [ $? -eq 0 ]
then
VER0=$($P --version 2>/dev/null | head -1 \
| sed -e 's/[^0-9]*\([vV]\?[0-9.]\+[^ ]*\).*/\1/' )
if [ $? -eq 0 -a "x${VER0}" != "x" ]
then
VER="($VER0)"
else
VER=""
fi
break
else
VER=""
T=""
fi
done
eval $V=\$T
putvar $V "$VER"
}
probe_need() {
local V=$1
probe $*
eval VV=\$$V
if [ -z "$VV" ]
then
err "needed, but unable to find any of: $*"
fi
}
valopt() {
VAL_OPTIONS="$VAL_OPTIONS $1"
local OP=$1
local DEFAULT=$2
shift
shift
local DOC="$*"
if [ $HELP -eq 0 ]
then
local UOP=$(echo $OP | tr '[:lower:]' '[:upper:]' | tr '\-' '\_')
local V="CFG_${UOP}"
eval $V="$DEFAULT"
for arg in $CFG_ARGS
do
if echo "$arg" | grep -q -- "--$OP="
then
val=$(echo "$arg" | cut -f2 -d=)
eval $V=$val
fi
done
putvar $V
else
if [ -z "$DEFAULT" ]
then
DEFAULT="<none>"
fi
OP="${OP}=[${DEFAULT}]"
printf " --%-30s %s\n" "$OP" "$DOC"
fi
}
opt() {
BOOL_OPTIONS="$BOOL_OPTIONS $1"
local OP=$1
local DEFAULT=$2
shift
shift
local DOC="$*"
local FLAG=""
if [ $DEFAULT -eq 0 ]
then
FLAG="enable"
else
FLAG="disable"
DOC="don't $DOC"
fi
if [ $HELP -eq 0 ]
then
for arg in $CFG_ARGS
do
if [ "$arg" = "--${FLAG}-${OP}" ]
then
OP=$(echo $OP | tr 'a-z-' 'A-Z_')
FLAG=$(echo $FLAG | tr 'a-z' 'A-Z')
local V="CFG_${FLAG}_${OP}"
eval $V=1
putvar $V
fi
done
else
if [ ! -z "$META" ]
then
OP="$OP=<$META>"
fi
printf " --%-30s %s\n" "$FLAG-$OP" "$DOC"
fi
}
flag() {
BOOL_OPTIONS="$BOOL_OPTIONS $1"
local OP=$1
shift
local DOC="$*"
if [ $HELP -eq 0 ]
then
for arg in $CFG_ARGS
do
if [ "$arg" = "--${OP}" ]
then
OP=$(echo $OP | tr 'a-z-' 'A-Z_')
local V="CFG_${OP}"
eval $V=1
putvar $V
fi
done
else
if [ ! -z "$META" ]
then
OP="$OP=<$META>"
fi
printf " --%-30s %s\n" "$OP" "$DOC"
fi
}
validate_opt() {
for arg in $CFG_ARGS
do
isArgValid=0
for option in $BOOL_OPTIONS
do
if test --disable-$option = $arg
then
isArgValid=1
fi
if test --enable-$option = $arg
then
isArgValid=1
fi
if test --$option = $arg
then
isArgValid=1
fi
done
for option in $VAL_OPTIONS
do
if echo "$arg" | grep -q -- "--$option="
then
isArgValid=1
fi
done
if [ "$arg" = "--help" ]
then
echo
echo "No more help available for Configure options,"
echo "check the Wiki or join our IRC channel"
break
else
if test $isArgValid -eq 0
then
err "Option '$arg' is not recognized"
fi
fi
done
}
create_tmp_dir() {
local TMP_DIR=`pwd`/rustup-tmp-install
rm -Rf "${TMP_DIR}"
need_ok "failed to remove temporary installation directory"
mkdir -p "${TMP_DIR}"
need_ok "failed to create create temporary installation directory"
echo $TMP_DIR
}
# Make `tr` locale independent
LC_CTYPE=C
probe_need CFG_CURL curl
probe_need CFG_TAR tar
probe_need CFG_FILE file
probe CFG_SHA256SUM sha256sum
probe CFG_SHASUM shasum
if [ -z "$CFG_SHA256SUM" -a -z "$CFG_SHASUM" ]; then
err "unable to find either sha256sum or shasum"
fi
calculate_hash() {
if [ -n "$CFG_SHA256SUM" ]; then
${CFG_SHA256SUM} $@
else
${CFG_SHASUM} -a 256 $@
fi
}
CFG_SRC_DIR="$(cd $(dirname $0) && pwd)/"
CFG_SELF="$0"
CFG_ARGS="$@"
HELP=0
if [ "$1" = "--help" ]
then
HELP=1
shift
echo
echo "Usage: $CFG_SELF [options]"
echo
echo "Options:"
echo
else
step_msg "processing $CFG_SELF args"
fi
OPTIONS=""
BOOL_OPTIONS=""
VAL_OPTIONS=""
flag uninstall "only uninstall from the installation prefix"
valopt prefix "" "set installation prefix"
valopt date "" "use the YYYY-MM-DD nightly instead of the current nightly"
valopt channel "beta" "use the selected release channel [beta]"
flag save "save the downloaded nightlies to ~/.rustup"
if [ $HELP -eq 1 ]
then
echo
exit 0
fi
step_msg "validating $CFG_SELF args"
validate_opt
# Platform detection copied from `configure`
CFG_OSTYPE=$(uname -s)
CFG_CPUTYPE=$(uname -m)
if [ $CFG_OSTYPE = Darwin -a $CFG_CPUTYPE = i386 ]
then
# Darwin's `uname -m` lies and always returns i386. We have to use sysctl
# instead.
if sysctl hw.optional.x86_64 | grep -q ': 1'
then
CFG_CPUTYPE=x86_64
fi
fi
# The goal here is to come up with the same triple as LLVM would,
# at least for the subset of platforms we're willing to target.
case $CFG_OSTYPE in
Linux)
CFG_OSTYPE=unknown-linux-gnu
;;
FreeBSD)
CFG_OSTYPE=unknown-freebsd
;;
Darwin)
CFG_OSTYPE=apple-darwin
;;
MINGW32*)
CFG_OSTYPE=pc-mingw32
;;
# Thad's Cygwin identifiers below
# Vista 32 bit
CYGWIN_NT-6.0)
CFG_OSTYPE=pc-mingw32
CFG_CPUTYPE=i686
;;
# Vista 64 bit
CYGWIN_NT-6.0-WOW64)
CFG_OSTYPE=w64-mingw32
CFG_CPUTYPE=x86_64
;;
# Win 7 32 bit
CYGWIN_NT-6.1)
CFG_OSTYPE=pc-mingw32
CFG_CPUTYPE=i686
;;
# Win 7 64 bit
CYGWIN_NT-6.1-WOW64)
CFG_OSTYPE=w64-mingw32
CFG_CPUTYPE=x86_64
;;
# We do not detect other OS such as XP/2003 using 64 bit using uname.
# If we want to in the future, we will need to use Cygwin
# Chuck's csih helper in /usr/lib/csih/winProductName.exe or alternative.
*)
err "unknown OS type: $CFG_OSTYPE"
;;
esac
case $CFG_CPUTYPE in
i386 | i486 | i686 | i786 | x86)
CFG_CPUTYPE=i686
;;
xscale | arm)
CFG_CPUTYPE=arm
;;
x86_64 | x86-64 | x64 | amd64)
CFG_CPUTYPE=x86_64
;;
*)
err "unknown CPU type: $CFG_CPUTYPE"
esac
# Detect 64 bit linux systems with 32 bit userland and force 32 bit compilation
if [ $CFG_OSTYPE = unknown-linux-gnu -a $CFG_CPUTYPE = x86_64 ]
then
"${CFG_FILE}" -L "$SHELL" | grep -q "x86[_-]64"
if [ $? != 0 ]; then
CFG_CPUTYPE=i686
fi
fi
HOST_TRIPLE="${CFG_CPUTYPE}-${CFG_OSTYPE}"
# Is this a triple we have nightlies for?
case $HOST_TRIPLE in
x86_64-unknown-linux-gnu)
;;
i686-unknown-linux-gnu)
;;
x86_64-apple-darwin)
;;
i686-apple-darwin)
;;
*)
err "rustup.sh doesn't work for host $HOST_TRIPLE"
esac
msg "host triple: ${HOST_TRIPLE}"
CFG_INSTALL_FLAGS=""
if [ -n "${CFG_UNINSTALL}" ]
then
CFG_INSTALL_FLAGS="${CFG_INSTALL_FLAGS} --uninstall"
fi
if [ -n "${CFG_PREFIX}" ]
then
CFG_INSTALL_FLAGS="${CFG_INSTALL_FLAGS} --prefix=${CFG_PREFIX}"
fi
CFG_TMP_DIR=$(mktemp -d 2>/dev/null \
|| mktemp -d -t 'rustup-tmp-install' 2>/dev/null \
|| create_tmp_dir)
# If we're saving nightlies and we didn't specify which one, grab the latest
# version from the perspective of the server. Buildbot has typically finished
# building and uploading by ~8UTC, but we want to include a little buffer.
#
# FIXME It would be better to use the known most recent nightly that has been
# built. This is waiting on a change to have buildbot publish metadata that
# can be queried.
if [ -n "${CFG_SAVE}" -a -z "${CFG_DATE}" ];
then
CFG_DATE=`TZ=Etc/UTC+9 date "+%Y-%m-%d"`
fi
RUST_URL="https://static.rust-lang.org/dist"
case "$CFG_CHANNEL" in
nightly)
# add a date suffix if we want a particular nightly.
if [ -n "${CFG_DATE}" ];
then
RUST_URL="${RUST_URL}/${CFG_DATE}"
fi
RUST_PACKAGE_NAME=rust-nightly
;;
beta)
RUST_PACKAGE_NAME=rust-1.0.0-beta
;;
*)
err "Currently 'beta' and 'nightly' are the only supported channels"
esac
RUST_PACKAGE_NAME_AND_TRIPLE="${RUST_PACKAGE_NAME}-${HOST_TRIPLE}"
RUST_TARBALL_NAME="${RUST_PACKAGE_NAME_AND_TRIPLE}.tar.gz"
RUST_LOCAL_INSTALL_DIR="${CFG_TMP_DIR}/${RUST_PACKAGE_NAME_AND_TRIPLE}"
RUST_LOCAL_INSTALL_SCRIPT="${RUST_LOCAL_INSTALL_DIR}/install.sh"
download_hash() {
msg "Downloading ${remote_sha256}"
remote_sha256=`"${CFG_CURL}" -f "${remote_sha256}"`
if [ -n "${CFG_SAVE}" ]; then
echo "${remote_sha256}" > "${local_sha_file}"
fi
if [ "$?" -ne 0 ]; then
rm -Rf "${CFG_TMP_DIR}"
err "Failed to download ${remote_url}"
fi
}
verify_hash() {
remote_sha256="$1"
local_file="$2"
local_sha_file="${local_file}.sha256"
if [ -n "${CFG_SAVE}" ]; then
if [ -f "${local_sha_file}" ]; then
msg "Local ${local_sha_file} exists, treating as remote hash"
remote_sha256=`cat "${local_sha_file}"`
else
download_hash
fi
else
download_hash
fi
msg "Verifying hash"
local_sha256=$(calculate_hash "${local_file}")
if [ "$?" -ne 0 ]; then
rm -Rf "${CFG_TMP_DIR}"
err "Failed to compute hash for ${local_tarball}"
fi
# We only need the sha, not the filenames
remote_sha256=`echo ${remote_sha256} | cut -f 1 -d ' '`
local_sha256=`echo ${local_sha256} | cut -f 1 -d ' '`
if [ "${remote_sha256}" != "${local_sha256}" ]; then
rm -Rf "${CFG_TMP_DIR}"
errmsg="invalid sha256.\n"
errmsg="$errmsg ${remote_sha256}\t${remote_tarball}\n"
errmsg="$errmsg ${local_sha256}\t${local_tarball}"
err "$errmsg"
fi
}
# Fetch the package. Optionally caches the tarballs.
download_package() {
remote_tarball="$1"
local_tarball="$2"
remote_sha256="${remote_tarball}.sha256"
# Check if we've already downloaded this file.
if [ -e "${local_tarball}.tmp" ]; then
msg "Resuming ${remote_tarball} to ${local_tarball}"
"${CFG_CURL}" -f -C - -o "${local_tarball}.tmp" "${remote_tarball}"
if [ $? -ne 0 ]
then
rm -Rf "${CFG_TMP_DIR}"
err "failed to download installer"
fi
mv "${local_tarball}.tmp" "${local_tarball}"
elif [ ! -e "${local_tarball}" ]; then
msg "Downloading ${remote_tarball} to ${local_tarball}"
"${CFG_CURL}" -f -o "${local_tarball}.tmp" "${remote_tarball}"
if [ $? -ne 0 ]
then
rm -Rf "${CFG_TMP_DIR}"
err "failed to download installer"
fi
mv "${local_tarball}.tmp" "${local_tarball}"
fi
verify_hash "${remote_sha256}" "${local_tarball}"
}
# Wrap all the commands needed to install a package.
install_package() {
local_tarball="$1"
install_script="$2"
msg "Extracting ${local_tarball}"
(cd "${CFG_TMP_DIR}" && "${CFG_TAR}" -xzf "${local_tarball}")
if [ $? -ne 0 ]; then
rm -Rf "${CFG_TMP_DIR}"
err "failed to unpack installer"
fi
sh "${install_script}" "${CFG_INSTALL_FLAGS}"
if [ $? -ne 0 ]
then
rm -Rf "${CFG_TMP_DIR}"
err "failed to install Rust"
fi
}
# It's possible that curl could be interrupted partway though downloading
# `rustup.sh`, truncating the file. This could be especially bad if we were in
# the middle of a line that would run "rm -rf ". To protect against this, we
# wrap up the `rustup.sh` destructive functionality in this helper function,
# which we call as the last thing we do. This means we will not do anything
# unless we have the entire file downloaded.
install_packages() {
rm -Rf "${CFG_TMP_DIR}"
need_ok "failed to remove temporary installation directory"
mkdir -p "${CFG_TMP_DIR}"
need_ok "failed to create create temporary installation directory"
# If we're saving our nightlies, put them in $HOME/.rustup.
if [ -n "${CFG_SAVE}" ]
then
RUST_DOWNLOAD_DIR="${HOME}/.rustup/${CFG_DATE}"
else
RUST_DOWNLOAD_DIR="${CFG_TMP_DIR}"
fi
mkdir -p "${RUST_DOWNLOAD_DIR}"
need_ok "failed to create create download directory"
RUST_LOCAL_TARBALL="${RUST_DOWNLOAD_DIR}/${RUST_TARBALL_NAME}"
download_package \
"${RUST_URL}/${RUST_TARBALL_NAME}" \
"${RUST_LOCAL_TARBALL}"
install_package \
"${RUST_LOCAL_TARBALL}" \
"${RUST_LOCAL_INSTALL_SCRIPT}"
rm -Rf "${CFG_TMP_DIR}"
need_ok "couldn't rm temporary installation directory"
}
install_packages

Binary file not shown.

View File

@ -12,8 +12,11 @@
# This script uses the following Unicode tables:
# - DerivedCoreProperties.txt
# - DerivedNormalizationProps.txt
# - EastAsianWidth.txt
# - auxiliary/GraphemeBreakProperty.txt
# - PropList.txt
# - ReadMe.txt
# - Scripts.txt
# - UnicodeData.txt
#
@ -51,41 +54,20 @@ expanded_categories = {
'Cc': ['C'], 'Cf': ['C'], 'Cs': ['C'], 'Co': ['C'], 'Cn': ['C'],
}
# Grapheme cluster data
# taken from UAX29, http://www.unicode.org/reports/tr29/
# these code points are excluded from the Control category
# NOTE: CR and LF are also technically excluded, but for
# the sake of convenience we leave them in the Control group
# and manually check them in the appropriate place. This is
# still compliant with the implementation requirements.
grapheme_control_exceptions = set([0x200c, 0x200d])
# the Regional_Indicator category
grapheme_regional_indicator = [(0x1f1e6, 0x1f1ff)]
# "The following ... are specifically excluded" from the SpacingMark category
# http://www.unicode.org/reports/tr29/#SpacingMark
grapheme_spacingmark_exceptions = [(0x102b, 0x102c), (0x1038, 0x1038),
(0x1062, 0x1064), (0x1067, 0x106d), (0x1083, 0x1083), (0x1087, 0x108c),
(0x108f, 0x108f), (0x109a, 0x109c), (0x19b0, 0x19b4), (0x19b8, 0x19b9),
(0x19bb, 0x19c0), (0x19c8, 0x19c9), (0x1a61, 0x1a61), (0x1a63, 0x1a64),
(0xaa7b, 0xaa7b), (0xaa7d, 0xaa7d)]
# these are included in the SpacingMark category
grapheme_spacingmark_extra = set([0xe33, 0xeb3])
# these are the surrogate codepoints, which are not valid rust characters
surrogate_codepoints = (0xd800, 0xdfff)
def fetch(f):
if not os.path.exists(f):
if not os.path.exists(os.path.basename(f)):
os.system("curl -O http://www.unicode.org/Public/UNIDATA/%s"
% f)
if not os.path.exists(f):
if not os.path.exists(os.path.basename(f)):
sys.stderr.write("cannot load %s" % f)
exit(1)
def is_surrogate(n):
return 0xD800 <= n <= 0xDFFF
return surrogate_codepoints[0] <= n <= surrogate_codepoints[1]
def load_unicode_data(f):
fetch(f)
@ -228,7 +210,7 @@ def load_properties(f, interestingprops):
re1 = re.compile("^([0-9A-F]+) +; (\w+)")
re2 = re.compile("^([0-9A-F]+)\.\.([0-9A-F]+) +; (\w+)")
for line in fileinput.input(f):
for line in fileinput.input(os.path.basename(f)):
prop = None
d_lo = 0
d_hi = 0
@ -323,33 +305,13 @@ def emit_table(f, name, t_data, t_type = "&'static [(char, char)]", is_pub=True,
format_table_content(f, data, 8)
f.write("\n ];\n\n")
def emit_property_module(f, mod, tbl, emit_fn):
def emit_property_module(f, mod, tbl, emit):
f.write("pub mod %s {\n" % mod)
keys = tbl.keys()
keys.sort()
for cat in keys:
for cat in sorted(emit):
emit_table(f, "%s_table" % cat, tbl[cat])
if cat in emit_fn:
f.write(" pub fn %s(c: char) -> bool {\n" % cat)
f.write(" super::bsearch_range_table(c, %s_table)\n" % cat)
f.write(" }\n\n")
f.write("}\n\n")
def emit_regex_module(f, cats, w_data):
f.write("pub mod regex {\n")
regex_class = "&'static [(char, char)]"
class_table = "&'static [(&'static str, %s)]" % regex_class
emit_table(f, "UNICODE_CLASSES", cats, class_table,
pfun=lambda x: "(\"%s\",super::%s::%s_table)" % (x[0], x[1], x[0]))
f.write(" pub const PERLD: %s = super::general_category::Nd_table;\n\n"
% regex_class)
f.write(" pub const PERLS: %s = super::property::White_Space_table;\n\n"
% regex_class)
emit_table(f, "PERLW", w_data, regex_class)
f.write(" pub fn %s(c: char) -> bool {\n" % cat)
f.write(" super::bsearch_range_table(c, %s_table)\n" % cat)
f.write(" }\n\n")
f.write("}\n\n")
def emit_conversions_module(f, lowerupper, upperlower):
@ -623,44 +585,21 @@ pub const UNICODE_VERSION: (u64, u64, u64) = (%s, %s, %s);
(canon_decomp, compat_decomp, gencats, combines,
lowerupper, upperlower) = load_unicode_data("UnicodeData.txt")
want_derived = ["XID_Start", "XID_Continue", "Alphabetic", "Lowercase", "Uppercase"]
other_derived = ["Default_Ignorable_Code_Point", "Grapheme_Extend"]
derived = load_properties("DerivedCoreProperties.txt", want_derived + other_derived)
derived = load_properties("DerivedCoreProperties.txt", want_derived)
scripts = load_properties("Scripts.txt", [])
props = load_properties("PropList.txt",
["White_Space", "Join_Control", "Noncharacter_Code_Point"])
norm_props = load_properties("DerivedNormalizationProps.txt",
["Full_Composition_Exclusion"])
# grapheme cluster category from DerivedCoreProperties
# the rest are defined below
grapheme_cats = {}
grapheme_cats["Extend"] = derived["Grapheme_Extend"]
del(derived["Grapheme_Extend"])
# bsearch_range_table is used in all the property modules below
emit_bsearch_range_table(rf)
# all of these categories will also be available as \p{} in libregex
allcats = []
# category tables
for (name, cat, pfuns) in ("general_category", gencats, ["N", "Cc"]), \
("derived_property", derived, want_derived), \
("script", scripts, []), \
("property", props, ["White_Space"]):
emit_property_module(rf, name, cat, pfuns)
allcats.extend(map(lambda x: (x, name), cat))
allcats.sort(key=lambda c: c[0])
# the \w regex corresponds to Alphabetic + Mark + Decimal_Number +
# Connector_Punctuation + Join-Control according to UTS#18
# http://www.unicode.org/reports/tr18/#Compatibility_Properties
perl_words = []
for cat in derived["Alphabetic"], gencats["M"], gencats["Nd"], \
gencats["Pc"], props["Join_Control"]:
perl_words.extend(ungroup_cat(cat))
perl_words = group_cat(perl_words)
# emit lookup tables for \p{}, along with \d, \w, and \s for libregex
emit_regex_module(rf, allcats, perl_words)
# normalizations and conversions module
emit_norm_module(rf, canon_decomp, compat_decomp, combines, norm_props)
@ -691,34 +630,24 @@ pub const UNICODE_VERSION: (u64, u64, u64) = (%s, %s, %s);
### grapheme cluster module
# from http://www.unicode.org/reports/tr29/#Grapheme_Cluster_Break_Property_Values
# Hangul syllable categories
want_hangul = ["L", "V", "T", "LV", "LVT"]
grapheme_cats.update(load_properties("HangulSyllableType.txt", want_hangul))
grapheme_cats = load_properties("auxiliary/GraphemeBreakProperty.txt", [])
# Control
# Note 1:
# This category also includes Cs (surrogate codepoints), but Rust's `char`s are
# Unicode Scalar Values only, and surrogates are thus invalid `char`s.
grapheme_cats["Control"] = set()
for cat in ["Zl", "Zp", "Cc", "Cf"]:
grapheme_cats["Control"] |= set(ungroup_cat(gencats[cat]))
# Thus, we have to remove Cs from the Control category
# Note 2:
# 0x0a and 0x0d (CR and LF) are not in the Control category for Graphemes.
# However, the Graphemes iterator treats these as a special case, so they
# should be included in grapheme_cats["Control"] for our implementation.
grapheme_cats["Control"] = group_cat(list(
grapheme_cats["Control"]
- grapheme_control_exceptions
| (set(ungroup_cat(gencats["Cn"]))
& set(ungroup_cat(derived["Default_Ignorable_Code_Point"])))))
# Regional Indicator
grapheme_cats["RegionalIndicator"] = grapheme_regional_indicator
# Prepend - "Currently there are no characters with this value"
# (from UAX#29, Unicode 7.0)
# SpacingMark
grapheme_cats["SpacingMark"] = group_cat(list(
set(ungroup_cat(gencats["Mc"]))
- set(ungroup_cat(grapheme_cats["Extend"]))
| grapheme_spacingmark_extra
- set(ungroup_cat(grapheme_spacingmark_exceptions))))
(set(ungroup_cat(grapheme_cats["Control"]))
| set(ungroup_cat(grapheme_cats["CR"]))
| set(ungroup_cat(grapheme_cats["LF"])))
- set(ungroup_cat([surrogate_codepoints]))))
del(grapheme_cats["CR"])
del(grapheme_cats["LF"])
grapheme_table = []
for cat in grapheme_cats:

View File

@ -1 +1 @@
0.12.0-7693-g9854143cba679834bc4ef932858cd5303f015a0e
0.12.0-8312-g5241bf9c34d156ea6064367a33cbd7222eeb5789

View File

@ -77,7 +77,6 @@ use core::atomic;
use core::atomic::Ordering::{Relaxed, Release, Acquire, SeqCst};
use core::fmt;
use core::cmp::Ordering;
use core::default::Default;
use core::mem::{min_align_of, size_of};
use core::mem;
use core::nonzero::NonZero;
@ -103,7 +102,7 @@ use heap::deallocate;
/// use std::thread;
///
/// fn main() {
/// let numbers: Vec<_> = (0..100u32).map(|i| i as f32).collect();
/// let numbers: Vec<_> = (0..100u32).collect();
/// let shared_numbers = Arc::new(numbers);
///
/// for _ in 0..10 {
@ -243,10 +242,9 @@ pub fn weak_count<T>(this: &Arc<T>) -> usize { this.inner().weak.load(SeqCst) -
pub fn strong_count<T>(this: &Arc<T>) -> usize { this.inner().strong.load(SeqCst) }
/// Try accessing a mutable reference to the contents behind an unique `Arc<T>`.
/// Returns a mutable reference to the contained value if the `Arc<T>` is unique.
///
/// The access is granted only if this is the only reference to the object.
/// Otherwise, `None` is returned.
/// Returns `None` if the `Arc<T>` is not unique.
///
/// # Examples
///
@ -254,16 +252,19 @@ pub fn strong_count<T>(this: &Arc<T>) -> usize { this.inner().strong.load(SeqCst
/// # #![feature(alloc)]
/// extern crate alloc;
/// # fn main() {
/// use alloc::arc;
/// use alloc::arc::{Arc, get_mut};
///
/// let mut four = arc::Arc::new(4);
/// let mut x = Arc::new(3);
/// *get_mut(&mut x).unwrap() = 4;
/// assert_eq!(*x, 4);
///
/// arc::unique(&mut four).map(|num| *num = 5);
/// let _y = x.clone();
/// assert!(get_mut(&mut x).is_none());
/// # }
/// ```
#[inline]
#[unstable(feature = "alloc")]
pub fn unique<T>(this: &mut Arc<T>) -> Option<&mut T> {
pub fn get_mut<T>(this: &mut Arc<T>) -> Option<&mut T> {
if strong_count(this) == 1 && weak_count(this) == 0 {
// This unsafety is ok because we're guaranteed that the pointer
// returned is the *only* pointer that will ever be returned to T. Our
@ -272,7 +273,7 @@ pub fn unique<T>(this: &mut Arc<T>) -> Option<&mut T> {
// reference to the inner data.
let inner = unsafe { &mut **this._ptr };
Some(&mut inner.data)
}else {
} else {
None
}
}
@ -347,7 +348,7 @@ impl<T: Clone> Arc<T> {
self.inner().weak.load(SeqCst) != 1 {
*self = Arc::new((**self).clone())
}
// As with `unique()`, the unsafety is ok because our reference was
// As with `get_mut()`, the unsafety is ok because our reference was
// either unique to begin with, or became one upon cloning the contents.
let inner = unsafe { &mut **self._ptr };
&mut inner.data
@ -446,7 +447,7 @@ impl<T> Weak<T> {
/// ```
pub fn upgrade(&self) -> Option<Arc<T>> {
// We use a CAS loop to increment the strong count instead of a
// fetch_add because once the count hits 0 is must never be above 0.
// fetch_add because once the count hits 0 it must never be above 0.
let inner = self.inner();
loop {
let n = inner.strong.load(SeqCst);
@ -666,6 +667,13 @@ impl<T: fmt::Debug> fmt::Debug for Arc<T> {
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<T> fmt::Pointer for Arc<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::Pointer::fmt(&*self._ptr, f)
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: Default + Sync + Send> Default for Arc<T> {
#[stable(feature = "rust1", since = "1.0.0")]
@ -691,7 +699,7 @@ mod tests {
use std::sync::atomic::Ordering::{Acquire, SeqCst};
use std::thread;
use std::vec::Vec;
use super::{Arc, Weak, weak_count, strong_count, unique};
use super::{Arc, Weak, get_mut, weak_count, strong_count};
use std::sync::Mutex;
struct Canary(*mut atomic::AtomicUsize);
@ -728,18 +736,16 @@ mod tests {
}
#[test]
fn test_arc_unique() {
let mut x = Arc::new(10);
assert!(unique(&mut x).is_some());
{
let y = x.clone();
assert!(unique(&mut x).is_none());
}
{
let z = x.downgrade();
assert!(unique(&mut x).is_none());
}
assert!(unique(&mut x).is_some());
fn test_arc_get_mut() {
let mut x = Arc::new(3);
*get_mut(&mut x).unwrap() = 4;
assert_eq!(*x, 4);
let y = x.clone();
assert!(get_mut(&mut x).is_none());
drop(y);
assert!(get_mut(&mut x).is_some());
let _w = x.downgrade();
assert!(get_mut(&mut x).is_none());
}
#[test]

View File

@ -10,14 +10,9 @@
//! A pointer type for heap allocation.
//!
//! `Box<T>`, casually referred to as a 'box', provides the simplest form of
//! heap allocation in Rust. Boxes provide ownership for this allocation, and
//! drop their contents when they go out of scope.
//!
//! Boxes are useful in two situations: recursive data structures, and
//! occasionally when returning data. [The Pointer chapter of the
//! Book](../../../book/pointers.html#best-practices-1) explains these cases in
//! detail.
//! `Box<T>`, casually referred to as a 'box', provides the simplest form of heap allocation in
//! Rust. Boxes provide ownership for this allocation, and drop their contents when they go out of
//! scope.
//!
//! # Examples
//!
@ -43,6 +38,16 @@
//! ```
//!
//! This will print `Cons(1, Box(Cons(2, Box(Nil))))`.
//!
//! Recursive structures must be boxed, because if the definition of `Cons` looked like this:
//!
//! ```rust,ignore
//! Cons(T, List<T>),
//! ```
//!
//! It wouldn't work. This is because the size of a `List` depends on how many elements are in the
//! list, and so we don't know how much memory to allocate for a `Cons`. By introducing a `Box`,
//! which has a defined size, we know how big `Cons` needs to be.
#![stable(feature = "rust1", since = "1.0.0")]
@ -50,7 +55,6 @@ use core::prelude::*;
use core::any::Any;
use core::cmp::Ordering;
use core::default::Default;
use core::fmt;
use core::hash::{self, Hash};
use core::mem;
@ -275,6 +279,16 @@ impl<T: fmt::Debug + ?Sized> fmt::Debug for Box<T> {
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<T> fmt::Pointer for Box<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
// It's not possible to extract the inner Uniq directly from the Box,
// instead we cast it to a *const which aliases the Unique
let ptr: *const T = &**self;
fmt::Pointer::fmt(&ptr, f)
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized> Deref for Box<T> {
type Target = T;

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