with the corresponding trait parameter bounds.
This is a version of the patch in PR #12611 by Florian Hahn, modified to
address Niko's feedback.
It does not address the issue of duplicate type parameter bounds, nor
does it address the issue of implementation-defined methods that contain
*fewer* bounds than the trait, because Niko's review indicates that this
should not be necessary (and indeed I believe it is not). A test has
been added to ensure that this works.
This will break code like:
trait Foo {
fn bar<T:Baz>();
}
impl Foo for Boo {
fn bar<T:Baz + Quux>() { ... }
// ^~~~ ERROR
}
This will be rejected because the implementation requires *more* bounds
than the trait. It can be fixed by either adding the missing bound to
the trait:
trait Foo {
fn bar<T:Baz + Quux>();
// ^~~~
}
impl Foo for Boo {
fn bar<T:Baz + Quux>() { ... } // OK
}
Or by removing the bound from the impl:
trait Foo {
fn bar<T:Baz>();
}
impl Foo for Boo {
fn bar<T:Baz>() { ... } // OK
// ^ remove Quux
}
This patch imports the relevant tests from #2687, as well as the test
case in #5886, which is fixed as well by this patch.
Closes #2687.
Closes #5886.
[breaking-change]
r? @pnkfelix
if [[ $LLVM_VERSION != '3.4' ]]; then exit 0; fi
fi &&
make tidy &&
- travis_wait make -j4 rustc-stage1 &&
+ make -j4 rustc-stage1 RUSTFLAGS='-Z time-passes' &&
make check-stage1-std check-stage1-rpass check-stage1-cfail check-stage1-rfail check-stage1-doc
env:
Rust was written by these fine people:
Aaron Laursen <aaronlaursen@gmail.com>
+Aaron Raimist <aaron@aaronraimist.com>
Aaron Todd <github@opprobrio.us>
+Aaron Turon <aturon@mozilla.com>
Adam Bozanich <adam.boz@gmail.com>
Adolfo Ochagavía <aochagavia92@gmail.com>
Adrien Tétar <adri-from-59@hotmail.fr>
+Ahmed Charles <ahmedcharles@gmail.com>
Alan Andrade <alan.andradec@gmail.com>
+Alan Williams <mralert@gmail.com>
Aleksander Balicki <balicki.aleksander@gmail.com>
Alex Crichton <alex@alexcrichton.com>
Alex Lyon <arcterus@mail.com>
Alex Rønne Petersen <alex@lycus.org>
Alex Whitney <aw1209@ic.ac.uk>
Alexander Stavonin <a.stavonin@gmail.com>
+Alexandre Gagnon <alxgnon@gmail.com>
Alexandros Tasos <sdi1100085@di.uoa.gr>
Alexei Sholik <alcosholik@gmail.com>
+Ali Smesseim <smesseim.ali@gmail.com>
Aljaž "g5pw" Srebrnič <a2piratesoft@gmail.com>
Anders Kaseorg <andersk@mit.edu>
Andre Arko <andre@arko.net>
Andrei Formiga <archimedes_siracusa@hotmail.com>
Andrew Chin <achin@eminence32.net>
Andrew Dunham <andrew@du.nham.ca>
+Andrew Gallant <jamslam@gmail.com>
Andrew Paseltiner <apaseltiner@gmail.com>
Anthony Juckel <ajuckel@gmail.com>
+Anton Löfgren <anton.lofgren@gmail.com>
Arcterus <Arcterus@mail.com>
+Ariel Ben-Yehuda <arielb1@mail.tau.ac.il>
Arkaitz Jimenez <arkaitzj@gmail.com>
Armin Ronacher <armin.ronacher@active-4.com>
Ashok Gautham <ScriptDevil@gmail.com>
Austin Seipp <mad.one@gmail.com>
Axel Viala <axel.viala@darnuria.eu>
Aydin Kim <ladinjin@hanmail.net>
-auREAX <mark@xn--hwg34fba.ws>
-b1nd <clint.ryan3@gmail.com>
Ben Alpert <ben@benalpert.com>
Ben Blum <bblum@andrew.cmu.edu>
Ben Harris <mail@bharr.is>
Ben Kelly <ben@wanderview.com>
Ben Noordhuis <info@bnoordhuis.nl>
Ben Striegel <ben.striegel@gmail.com>
+Benjamin Adamson <adamson.benjamin@gmail.com>
Benjamin Herr <ben@0x539.de>
Benjamin Jackman <ben@jackman.biz>
Benjamin Kircher <benjamin.kircher@gmail.com>
Bill Wendling <wendling@apple.com>
Birunthan Mohanathas <birunthan@mohanathas.com>
Björn Steinbrink <bsteinbr@gmail.com>
-blake2-ppc <ulrik.sverdrup@gmail.com>
+Boris Egorov <jightuse@gmail.com>
Bouke van der Bijl <boukevanderbijl@gmail.com>
Brandon Sanderson <singingboyo@hotmail.com>
+Brandon Waskiewicz <brandon.waskiewicz@gmail.com>
+Branimir <branimir@volomp.com>
Brendan Cully <brendan@kublai.com>
Brendan Eich <brendan@mozilla.org>
+Brendan McLoughlin <btmcloughlin@gmail.com>
Brendan Zabarauskas <bjzaba@yahoo.com.au>
-Branimir <branimir@volomp.com>
Brett Cannon <brett@python.org>
Brian Anderson <banderson@mozilla.com>
Brian Dawn <brian.t.dawn@gmail.com>
Byron Williams <byron@112percent.com>
Cadence Marseille <cadencemarseille@gmail.com>
Caitlin Potter <snowball@defpixel.com>
+Cameron Zwarich <zwarich@mozilla.com>
Carl-Anton Ingmarsson <mail@carlanton.se>
Carlos <toqueteos@gmail.com>
Carol Willing <carolcode@willingconsulting.com>
Carter Tazio Schonwald <carter.schonwald@gmail.com>
-chitra
Chris Double <chris.double@double.co.nz>
Chris Morgan <me@chrismorgan.info>
Chris Peterson <cpeterson@mozilla.com>
Chris Pressey <cpressey@gmail.com>
Chris Sainty <csainty@hotmail.com>
+Chris Shea <cmshea@gmail.com>
Chris Wong <lambda.fairy@gmail.com>
-chromatic <chromatic@wgz.org>
+Christoph Burgdorf <christoph.burgdorf@bvsn.org>
+Christopher Bergqvist <spambox0@digitalpoetry.se>
+Christopher Kendell <ckendell@outlook.com>
Clark Gaebel <cg.wowus.cg@gmail.com>
+Clinton Ryan <clint.ryan3@gmail.com>
Cody Schroeder <codys@cs.washington.edu>
Cole Mickens <cole.mickens@gmail.com>
Colin Sherratt <colin.sherratt@gmail.com>
-comex <comexk@gmail.com>
+Conrad Kleinespel <conradk@conradk.com>
Corey Richardson <corey@octayn.net>
Damian Gryski <damian@gryski.com>
Damien Grassart <damien@grassart.com>
Daniel Ralston <Wubbulous@gmail.com>
Daniel Rosenwasser <DanielRosenwasser@gmail.com>
Daniel Ursache Dogariu <contact@danniel.net>
-darkf <lw9k123@gmail.com>
Dave Herman <dherman@mozilla.com>
Dave Hodder <dmh@dmh.org.uk>
David Creswick <dcrewi@gyrae.net>
Diego Ongaro <ongaro@cs.stanford.edu>
Diggory Hardy <diggory.hardy@gmail.com>
Dimitri Krassovski <labria@startika.com>
+Dirk Leifeld <leifeld@posteo.de>
Dirkjan Bussink <d.bussink@gmail.com>
Div Shekhar <div@pagerduty.com>
Dmitry Ermolov <epdmitry@yandex.ru>
Dmitry Promsky <dmitry@willworkforcookies.com>
Dmitry Vasiliev <dima@hlabs.org>
Do Nhat Minh <mrordinaire@gmail.com>
-Douglas Young <rcxdude@gmail.com>
Donovan Preston <donovanpreston@gmail.com>
+Douglas Young <rcxdude@gmail.com>
Drew Willcoxon <adw@mozilla.com>
Dylan Braithwaite <dylanbraithwaite1@gmail.com>
Eduard Bopp <eduard.bopp@aepsil0n.de>
Edward Wang <edward.yu.wang@gmail.com>
Edward Z. Yang <ezyang@cs.stanford.edu>
Ehsanul Hoque <ehsanul@ehsanul.com>
-eliovir <eliovir@gmail.com>
Elliott Slaughter <elliottslaughter@gmail.com>
Elly Fong-Jones <elly@leptoquark.net>
+Emanuel Rylke <ema-fox@web.de>
Eric Biggers <ebiggers3@gmail.com>
Eric Holk <eric.holk@gmail.com>
Eric Holmes <eric@ejholmes.net>
-Erik Lyon <elyon001@local.fake>
Eric Martin <e.a.martin1337@gmail.com>
Eric Reed <ecreed@cs.washington.edu>
Erick Tryzelaar <erick.tryzelaar@gmail.com>
+Erik Lyon <elyon001@local.fake>
Erik Price <erik.price16@gmail.com>
Erik Rose <erik@mozilla.com>
Etienne Millon <me@emillon.org>
Eunchong Yu <kroisse@gmail.com>
Evan McClanahan <evan@evanmcc.com>
+Evgeny Sologubov
+Fabian Deutsch <fabian.deutsch@gmx.de>
Fabrice Desré <fabrice@desre.org>
+Falco Hirschenberger <falco.hirschenberger@gmail.com>
Fedor Indutny <fedor.indutny@gmail.com>
Felix Crux <felixc@felixcrux.com>
Felix S. Klock II <pnkfelix@pnkfx.org>
Flaper Fesp <flaper87@gmail.com>
Flavio Percoco <flaper87@gmail.com>
-flo-l <lacknerflo@gmail.com>
Florian Gilcher <florian.gilcher@asquera.de>
Florian Hahn <flo@fhahn.com>
+Florian Hartwig <florian.j.hartwig@gmail.com>
Florian Zeitz <florob@babelmonkeys.de>
Francisco Souza <f@souza.cc>
Franklin Chen <franklinchen@franklinchen.com>
-g3xzh <g3xzh@yahoo.com>
-Gábor Horváth <xazax.hun@gmail.com>
Gabriel <g2p.code@gmail.com>
Gareth Daniel Smith <garethdanielsmith@gmail.com>
Gary Linscott <glinscott@gmail.com>
Gary M. Josack <gary@byoteki.com>
-gentlefolk <cemacken@gmail.com>
+Gavin Baker <gavinb@antonym.org>
Geoff Hill <geoff@geoffhill.org>
Geoffroy Couprie <geo.couprie@gmail.com>
George Papanikolaou <g3orge.app@gmail.com>
Georges Dubus <georges.dubus@gmail.com>
-gifnksm <makoto.nksm@gmail.com>
Glenn Willen <gwillen@nerdnet.org>
Gonçalo Cabrita <_@gmcabrita.com>
Graham Fawcett <fawcett@uwindsor.ca>
Grigoriy <ohaistarlight@gmail.com>
Guillaume Pinot <texitoi@texitoi.eu>
Gyorgy Andrasek <jurily@gmail.com>
+Gábor Horváth <xazax.hun@gmail.com>
+Gábor Lehel <glaebhoerl@gmail.com>
Haitao Li <lihaitao@gmail.com>
-hansjorg <hansjorg@gmail.com>
+Hanno Braun <mail@hannobraun.de>
Harry Marr <harry.marr@gmail.com>
Heather <heather@cynede.net>
Herman J. Radtke III <hermanradtke@gmail.com>
HeroesGrave <heroesgrave@gmail.com>
Hong Chulju <ang0123dev@gmail.com>
+Honza Strnad <hanny.strnad@gmail.com>
Huon Wilson <dbau.pp+github@gmail.com>
Ian D. Bollinger <ian.bollinger@gmail.com>
Ian Daniher <it.daniher@gmail.com>
Isaac Aggrey <isaac.aggrey@gmail.com>
Isaac Dupree <antispam@idupree.com>
Ivan Enderlin <ivan.enderlin@hoa-project.net>
+Ivan Petkov <ivanppetkov@gmail.com>
Ivano Coppola <rgbfirefox@gmail.com>
+J. J. Weber <jjweber@gmail.com>
+J.C. Moyer <jmoyer1992@gmail.com>
Jack Moffitt <jack@metajack.im>
-Jag Talon <talon.jag@gmail.com>
Jacob Harris Cryer Kragh <jhckragh@gmail.com>
+Jacob Hegna <jacobhegna@gmail.com>
Jacob Parker <j3parker@csclub.uwaterloo.ca>
Jaemin Moon <jaemin.moon@samsung.com>
+Jag Talon <talon.jag@gmail.com>
Jake Kerr <kodafox@gmail.com>
Jakub <jakub@jakub.cc>
Jakub Wieczorek <jakubw@jakubw.net>
James Deng <cnjamesdeng@gmail.com>
+James Laverack <james@jameslaverack.com>
James Miller <bladeon@gmail.com>
+James Sanders <sanderjd@gmail.com>
James Tranovich <james@openhorizonlabs.com>
Jan Kobler <eng1@koblersystems.de>
Jan Niklas Hasse <jhasse@gmail.com>
Jason Toffaletti <jason@topsy.com>
Jay Anderson <jayanderson0@gmail.com>
Jed Davis <jld@panix.com>
+Jed Estep <aje@jhu.edu>
Jeff Balogh <jbalogh@mozilla.com>
Jeff Muizelaar <jmuizelaar@mozilla.com>
Jeff Olson <olson.jeffery@gmail.com>
Jeffrey Yasskin <jyasskin@gmail.com>
-Jeong YunWon <jeong@youknowone.org>
Jens Nockert <jens@nockert.se>
+Jeong YunWon <jeong@youknowone.org>
Jeremy Letang <letang.jeremy@gmail.com>
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>
Jim Blandy <jimb@red-bean.com>
+Jim Radford <radford@blackbean.org>
Jimmy Lu <jimmy.lu.2011@gmail.com>
Jimmy Zelinskie <jimmyzelinskie@gmail.com>
-J. J. Weber <jjweber@gmail.com>
-jmgrosen <jmgrosen@gmail.com>
-joaoxsouls <joaoxsouls@gmail.com>
Joe Pletcher <joepletcher@gmail.com>
Joe Schafer <joe@jschaf.com>
Johannes Löthberg <johannes@kyriasis.com>
Johannes Muenzel <jmuenzel@gmail.com>
John Barker <jebarker@gmail.com>
John Clements <clements@racket-lang.org>
+John Fresco <john.fresco@utah.edu>
John Louis Walker <injyuw@gmail.com>
+John Schmidt <john.schmidt.h@gmail.com>
+John Simon <john@johnsoft.com>
Jon Morton <jonanin@gmail.com>
+Jonathan Bailey <jbailey@mozilla.com>
+Jonathan Reem <jonathan.reem@gmail.com>
Jonathan S <gereeter@gmail.com>
Jonathan Sternberg <jonathansternberg@gmail.com>
Jordi Boggiano <j.boggiano@seld.be>
Jorge Aparicio <japaric@linux.com>
+Joris Rehm <joris.rehm@wakusei.fr>
+Joseph Crail <jbcrail@gmail.com>
Josh Matthews <josh@joshmatthews.net>
Joshua Clark <joshua.clark@txstate.edu>
Joshua Wise <joshua@joshuawise.com>
Joshua Yanovski <pythonesque@gmail.com>
Julia Evans <julia@jvns.ca>
Junyoung Cho <june0.cho@samsung.com>
+JustAPerson <jpriest8@ymail.com>
+Justin Noah <justinnoah@gmail.com>
Jyun-Yan You <jyyou@cs.nctu.edu.tw>
Kang Seonghoon <kang.seonghoon@mearie.org>
+Kasey Carrothers <kaseyc.808@gmail.com>
Keegan McAllister <kmcallister@mozilla.com>
Kelly Wilson <wilsonk@cpsc.ucalgary.ca>
Keshav Kini <keshav.kini@gmail.com>
Kevin Atkinson <kevina@cs.utah.edu>
Kevin Ballard <kevin@sb.org>
+Kevin Butler <haqkrs@gmail.com>
Kevin Cantu <me@kevincantu.org>
Kevin Mehall <km@kevinmehall.net>
Kevin Murphy <kemurphy.cmu@gmail.com>
Kiet Tran <ktt3ja@gmail.com>
-klutzy <klutzytheklutzy@gmail.com>
-korenchkin <korenchkin2@gmail.com>
-kvark <kvarkus@gmail.com>
Kyeongwoon Lee <kyeongwoon.lee@samsung.com>
Lars Bergstrom <lbergstrom@mozilla.com>
Laurent Bonnans <bonnans.l@gmail.com>
Lawrence Velázquez <larryv@alum.mit.edu>
Leah Hanson <astrieanna@gmail.com>
Lee Wondong <wdlee91@gmail.com>
-Léo Testard <leo.testard@gmail.com>
Lennart Kudling <github@kudling.de>
+Léo Testard <leo.testard@gmail.com>
Liigo Zhuang <com.liigo@gmail.com>
Lindsey Kuper <lindsey@composition.al>
-lpy <pylaurent1314@gmail.com>
Luca Bruno <lucab@debian.org>
-lucy <ne.tetewi@gmail.com>
Luis de Bethencourt <luis@debethencourt.com>
Luqman Aden <laden@csclub.uwaterloo.ca>
-lyuts <dioxinu@gmail.com>
Magnus Auvinen <magnus.auvinen@gmail.com>
Mahmut Bulut <mahmutbulut0@gmail.com>
-maikklein <maikklein@googlemail.com>
Makoto Nakashima <makoto.nksm+github@gmail.com>
+Manish Goregaokar <manishsmail@gmail.com>
Marcel Rodrigues <marcelgmr@gmail.com>
Margaret Meyerhofer <mmeyerho@andrew.cmu.edu>
Marijn Haverbeke <marijnh@gmail.com>
Matthijs van der Vleuten <git@zr40.nl>
Max Penet <max.penet@gmail.com>
Maxim Kolganov <kolganov.mv@gmail.com>
+Meyer S. Jacobs <meyermagic@gmail.com>
Micah Chalmer <micah@micahchalmer.net>
Michael Arntzenius <daekharel@gmail.com>
Michael Bebenita <mbebenita@mozilla.com>
+Michael Dagitses <dagitses@google.com>
Michael Darakananda <pongad@gmail.com>
+Michael Fairley <michaelfairley@gmail.com>
Michael Letterle <michael.letterle@gmail.com>
Michael Neumann <mneumann@ntecs.de>
+Michael Pratt <michael@pratt.im>
+Michael Reinhard <mcreinhard@users.noreply.github.com>
Michael Sullivan <sully@msully.net>
Michael Williams <m.t.williams@live.com>
Michael Woerister <michaelwoerister@gmail>
+Michael Zhou <moz@google.com>
+Mick Koch <kchmck@gmail.com>
Mickaël Delahaye <mickael.delahaye@gmail.com>
Mihnea Dobrescu-Balaur <mihnea@linux.com>
Mike Boutin <mike.boutin@gmail.com>
Mikko Perttunen <cyndis@kapsi.fi>
-mr.Shu <mr@shu.io>
Ms2ger <ms2ger@gmail.com>
Mukilan Thiagarajan <mukilanthiagarajan@gmail.com>
-musitdev <philippe.delrieu@free.fr>
+Nathan Typanski <ntypanski@gmail.com>
Nathaniel Herman <nherman@college.harvard.edu>
+NiccosSystem <niccossystem@gmail.com>
Nick Cameron <ncameron@mozilla.com>
Nick Desaulniers <ndesaulniers@mozilla.com>
+Nicolas Silva <nical.silva@gmail.com>
+Niels langager Ellegaard <niels.ellegaard@gmail.com>
Nif Ward <nif.ward@gmail.com>
+Nikita Pekin <contact@nikitapek.in>
+Niklas Koep <niklas.koep@gmail.com>
Niko Matsakis <niko@alum.mit.edu>
-noam <noam@clusterfoo.com>
+Noam Yorav-Raphael <noamraph@gmail.com>
Noufal Ibrahim <noufal@nibrahim.net.in>
-novalis <novalis@novalis.org>
Ogino Masanori <masanori.ogino@gmail.com>
Olivier Saut <osaut@airpost.net>
Olle Jonsson <olle.jonsson@gmail.com>
Or Brostovski <tohava@gmail.com>
Orphée Lafond-Lummis <o@orftz.com>
-osa1 <omeragacan@gmail.com>
+P1start <rewi-github@whanau.org>
Palmer Cox <p@lmercox.com>
Patrick Walton <pwalton@mozilla.com>
Patrik Kårlin <patrik.karlin@gmail.com>
Paul Stansifer <paul.stansifer@gmail.com>
Paul Woolcock <pwoolcoc+github@gmail.com>
Pavel Panchekha <me@pavpanchekha.com>
+Pawel Olzacki <p.olzacki2@samsung.com>
Peter Hull <peterhull90@gmail.com>
Peter Marheine <peter@taricorp.net>
Peter Williams <peter@newton.cx>
Peter Zotov <whitequark@whitequark.org>
Petter Remen <petter.remen@gmail.com>
+Phil Ruffwind <rf@rufflewind.com>
Philipp Brüschweiler <blei42@gmail.com>
Piotr Czarnecki <pioczarn@gmail.com>
+Piotr Jawniak <sawyer47@gmail.com>
Piotr Zolnierek <pz@anixe.pl>
Pradeep Kumar <gohanpra@gmail.com>
Q.P.Liu <qpliu@yahoo.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 Speyer <rspeyer@gmail.com>
-reedlepee <reedlepee123@gmail.com>
+Reilly Watson <reillywatson@gmail.com>
+Renato Riccieri Santos Zannon <renato@rrsz.com.br>
+Renato Zannon <renato@rrsz.com.br>
Reuben Morais <reuben.morais@gmail.com>
+Rich Lane <rlane@club.cc.cmu.edu>
Richard Diamond <wichard@vitalitystudios.com>
Richo Healey <richo@psych0tik.net>
Rick Waldron <waldron.rick@gmail.com>
Rob Arnold <robarnold@cs.cmu.edu>
Rob Hoelz <rob@hoelz.ro>
+Robert Buonpastore <robert.buonpastore@gmail.com>
Robert Gawdzik <rgawdzik@hotmail.com>
Robert Irelan <rirelan@gmail.com>
Robert Knight <robertknight@gmail.com>
Roland Tanglao <roland@rolandtanglao.com>
Ron Dahlgren <ronald.dahlgren@gmail.com>
Roy Frostig <rfrostig@mozilla.com>
+Ryan Mulligan <ryan@ryantm.com>
Ryan Scheel <ryan.havvy@gmail.com>
+Ryman <haqkrs@gmail.com>
+Rüdiger Sonderfeld <ruediger@c-plusplus.de>
+S Pradeep Kumar <gohanpra@gmail.com>
Salem Talha <salem.a.talha@gmail.com>
Samuel Chase <samebchase@gmail.com>
Sander Mathijs van Veen <smvv@kompiler.org>
Sangeun Kim <sammy.kim@samsung.com>
Sankha Narayan Guria <sankha93@gmail.com>
+Santiago Rodriguez <sanrodari@gmail.com>
Saurabh Anand <saurabhanandiit@gmail.com>
Scott Jenkins <scottdjwales@gmail.com>
Scott Lawrence <bytbox@gmail.com>
Sean Chalmers <sclhiannan@gmail.com>
+Sean Gillespie <sean.william.g@gmail.com>
Sean McArthur <sean.monstar@gmail.com>
Sean Moon <ssamoon@ucla.edu>
Sean Stangl <sstangl@mozilla.com>
Sebastian N. Fernandez <cachobot@gmail.com>
-Sébastien Chauvel <eichi237@mailoo.org>
-Sébastien Crozet <developer@crozet.re>
-Sébastien Paolacci <sebastien.paolacci@gmail.com>
-Seth Pink <sethpink@gmail.com>
Seo Sanghyeon <sanxiyn@gmail.com>
Seonghyun Kim <sh8281.kim@samsung.com>
-sevrak <sevrak@rediffmail.com>
+Sergio Benitez <sbenitez@mit.edu>
+Seth Pink <sethpink@gmail.com>
Shamir Khodzha <khodzha.sh@gmail.com>
SiegeLord <slabode@aim.com>
Simon Barber-Dueck <sbarberdueck@gmail.com>
Simon Sapin <simon@exyr.org>
-sp3d <sp3d@github>
-startling <tdixon51793@gmail.com>
Stefan Plantikow <stefan.plantikow@googlemail.com>
Stepan Koltsov <stepan.koltsov@gmail.com>
Sterling Greene <sterling.greene@gmail.com>
Steve Klabnik <steve@steveklabnik.com>
Steven De Coeyer <steven@banteng.be>
Steven Fackler <sfackler@gmail.com>
+Steven Sheldon <steven@sasheldon.com>
Steven Stewart-Gallus <sstewartgallus00@langara.bc.ca>
Strahinja Val Markovic <val@markovic.io>
+Sylvestre Ledru <sylvestre@debian.org>
+Sébastien Chauvel <eichi237@mailoo.org>
+Sébastien Crozet <developer@crozet.re>
+Sébastien Paolacci <sebastien.paolacci@gmail.com>
Taras Shpot <mrshpot@gmail.com>
Ted Horst <ted.horst@earthlink.net>
Thad Guidry <thadguidry@gmail.com>
+Thomas Backman <serenity@exscape.org>
Thomas Daede <daede003@umn.edu>
+Tim Brooks <tim.brooks@staples.com>
Tim Chevalier <chevalier@alum.wellesley.edu>
Tim Kuehn <tkuehn@cmu.edu>
Tim Taubert <tim@timtaubert.de>
+Timothée Ravier <tim@siosm.fr>
+Tobba <tobias.haegermarck@gmail.com>
Tobias Bucher <tobiasbucher5991@gmail.com>
+Tohava <tohava@tohava-laptop.(none)>
+Tom Jakubowski <tom@crystae.net>
Tom Lee <github@tomlee.co>
Tomas Sedovic <tomas@sedovic.cz>
Tommy M. McGuire <mcguire@crsr.net>
Torsten Weber <TorstenWeber12@gmail.com>
Trent Ogren <tedwardo2@gmail.com>
Trinick <slicksilver555@mac.com>
+Tuncer Ayaz <tuncer.ayaz@gmail.com>
+TyOverby <ty@pre-alpha.com>
Tycho Sci <tychosci@gmail.com>
Tyler Bindon <martica@martica.org>
U-NOV2010\eugals
+Utkarsh Kukreti <utkarshkukreti@gmail.com>
Uwe Dauernheim <uwe@dauernheim.net>
Vadim Chugunov <vadimcn@gmail.com>
+Valentin Tsatskin <vtsatskin@mozilla.com>
+Valerii Hiora <valerii.hiora@gmail.com>
Vijay Korapaty <rust@korapaty.com>
Viktor Dahl <pazaconyoman@gmail.com>
Vincent Belliard <vincent@famillebelliard.fr>
Volker Mische <volker.mische@gmail.com>
Wade Mealing <wmealing@gmail.com>
WebeWizard <webewizard@gmail.com>
+Wendell Smith <wendell.smith@yale.edu>
William Ting <io@williamting.com>
-xales <xales@naveria.com>
-Yehuda Katz <wycats@gmail.com>
Yasuhiro Fujii <y-fujii@mimosa-pudica.net>
+Yehuda Katz <wycats@gmail.com>
Young-il Choi <duddlf.choi@samsung.com>
Youngmin Yoo <youngmin.yoo@samsung.com>
Youngsoo Son <ysson83@gmail.com>
Yuri Kunde Schlesner <yuriks@yuriks.net>
Zach Kamsler <smoo.master@gmail.com>
+Zach Pomerantz <zmp@umich.edu>
Zack Corr <zack@z0w0.me>
Zack Slayton <zack.slayton@gmail.com>
Ziad Hatahet <hatahet@gmail.com>
+Zooko Wilcox-O'Hearn <zooko@zooko.com>
+aochagavia <aochagavia92@gmail.com>
+auREAX <mark@xn--hwg34fba.ws>
+b1nd <clint.ryan3@gmail.com>
+bachm <Ab@vapor.com>
+blake2-ppc <ulrik.sverdrup@gmail.com>
+bors <bors@rust-lang.org>
+chitra
+chromatic <chromatic@wgz.org>
+comex <comexk@gmail.com>
+darkf <lw9k123@gmail.com>
+eliovir <eliovir@gmail.com>
+flo-l <lacknerflo@gmail.com>
+fort <e@mail.com>
+free-Runner <aali07@students.poly.edu>
+g3xzh <g3xzh@yahoo.com>
+gentlefolk <cemacken@gmail.com>
+gifnksm <makoto.nksm@gmail.com>
+hansjorg <hansjorg@gmail.com>
+iancormac84 <wilnathan@gmail.com>
+jmgrosen <jmgrosen@gmail.com>
+joaoxsouls <joaoxsouls@gmail.com>
+klutzy <klutzytheklutzy@gmail.com>
+korenchkin <korenchkin2@gmail.com>
+kvark <kvarkus@gmail.com>
+lpy <pylaurent1314@gmail.com>
+lucy <ne.tetewi@gmail.com>
+lyuts <dioxinu@gmail.com>
+m-r-r <raybaudroigm@gmail.com>
+maikklein <maikklein@googlemail.com>
+mdinger <mdinger.bugzilla@gmail.com>
+moonglum <moonglum@moonbeamlabs.com>
+mr.Shu <mr@shu.io>
+mrec <mike.capp@gmail.com>
+musitdev <philippe.delrieu@free.fr>
+noam <noam@clusterfoo.com>
+novalis <novalis@novalis.org>
+osa1 <omeragacan@gmail.com>
+reedlepee <reedlepee123@gmail.com>
+sevrak <sevrak@rediffmail.com>
+sp3d <sp3d@github>
+startling <tdixon51793@gmail.com>
+theptrk <patrick.tran06@gmail.com>
+xales <xales@naveria.com>
zofrex <zofrex@gmail.com>
zslayton <zack.slayton@gmail.com>
+Version 0.11.0 (July 2014)
+-------------------------
+
+ * ~1700 changes, numerous bugfixes
+
+ * Language
+ * ~[T] has been removed from the language. This type is superseded by
+ the Vec<T> type.
+ * ~str has been removed from the language. This type is superseded by
+ the String type.
+ * ~T has been removed from the language. This type is superseded by the
+ Box<T> type.
+ * @T has been removed from the language. This type is superseded by the
+ standard library's std::gc::Gc<T> type.
+ * Struct fields are now all private by default.
+ * Vector indices and shift amounts are both required to be a `uint`
+ instead of any integral type.
+ * Byte character, byte string, and raw byte string literals are now all
+ supported by prefixing the normal literal with a `b`.
+ * Multiple ABIs are no longer allowed in an ABI string
+ * The syntax for lifetimes on closures/procedures has been tweaked
+ slightly: `<'a>|A, B|: 'b + K -> T`
+ * Floating point modulus has been removed from the language; however it
+ is still provided by a library implementation.
+ * Private enum variants are now disallowed.
+ * The `priv` keyword has been removed from the language.
+ * A closure can no longer be invoked through a &-pointer.
+ * The `use foo, bar, baz;` syntax has been removed from the language.
+ * The transmute intrinsic no longer works on type parameters.
+ * Statics now allow blocks/items in their definition.
+ * Trait bounds are separated from objects with + instead of : now.
+ * Objects can no longer be read while they are mutably borrowed.
+ * The address of a static is now marked as insignificant unless the
+ #[inline(never)] attribute is placed it.
+ * The #[unsafe_destructor] attribute is now behind a feature gate.
+ * Struct literals are no longer allowed in ambiguous positions such as
+ if, while, match, and for..in.
+ * Declaration of lang items and intrinsics are now feature-gated by
+ default.
+ * Integral literals no longer default to `int`, and floating point
+ literals no longer default to `f64`. Literals must be suffixed with an
+ appropriate type if inference cannot determine the type of the
+ literal.
+ * The Box<T> type is no longer implicitly borrowed to &mut T.
+ * Procedures are now required to not capture borrowed references.
+
+ * Libraries
+ * The standard library is now a "facade" over a number of underlying
+ libraries. This means that development on the standard library should
+ be speeder due to smaller crates, as well as a clearer line between
+ all dependencies.
+ * A new library, libcore, lives under the standard library's facade
+ which is Rust's "0-assumption" library, suitable for embedded and
+ kernel development for example.
+ * A regex crate has been added to the standard distribution. This crate
+ includes statically compiled regular expressions.
+ * The unwrap/unwrap_err methods on Result require a Show bound for
+ better error messages.
+ * The return types of the std::comm primitives have been centralized
+ around the Result type.
+ * A number of I/O primitives have gained the ability to time out their
+ operations.
+ * A number of I/O primitives have gained the ability to close their
+ reading/writing halves to cancel pending operations.
+ * Reverse iterator methods have been removed in favor of `rev()` on
+ their forward-iteration counterparts.
+ * A bitflags! macro has been added to enable easy interop with C and
+ management of bit flags.
+ * A debug_assert! macro is now provided which is disabled when
+ `--cfg ndebug` is passed to the compiler.
+ * A graphviz crate has been added for creating .dot files.
+ * The std::cast module has been migrated into std::mem.
+ * The std::local_data api has been migrated from freestanding functions
+ to being based on methods.
+ * The Pod trait has been renamed to Copy.
+ * jemalloc has been added as the default allocator for types.
+ * The API for allocating memory has been changed to use proper alignment
+ and sized deallocation
+ * Connecting a TcpStream or binding a TcpListener is now based on a
+ string address and a u16 port. This allows connecting to a hostname as
+ opposed to an IP.
+ * The Reader trait now contains a core method, read_at_least(), which
+ correctly handles many repeated 0-length reads.
+ * The process-spawning API is now centered around a builder-style
+ Command struct.
+ * The :? printing qualifier has been moved from the standard library to
+ an external libdebug crate.
+ * Eq/Ord have been renamed to PartialEq/PartialOrd. TotalEq/TotalOrd
+ have been renamed to Eq/Ord.
+ * The select/plural methods have been removed from format!. The escapes
+ for { and } have also changed from \{ and \} to {{ and }},
+ respectively.
+ * The TaskBuilder API has been re-worked to be a true builder, and
+ extension traits for spawning native/green tasks have been added.
+
+ * Tooling
+ * All breaking changes to the language or libraries now have their
+ commit message annotated with `[breaking-change]` to allow for easy
+ discovery of breaking changes.
+ * The compiler will now try to suggest how to annotate lifetimes if a
+ lifetime-related error occurs.
+ * Debug info continues to be improved greatly with general bug fixes and
+ better support for situations like link time optimization (LTO).
+ * Usage of syntax extensions when cross-compiling has been fixed.
+ * Functionality equivalent to GCC & Clang's -ffunction-sections,
+ -fdata-sections and --gc-sections has been enabled by default
+ * The compiler is now stricter about where it will load module files
+ from when a module is declared via `mod foo;`.
+ * The #[phase(syntax)] attribute has been renamed to #[phase(plugin)].
+ Syntax extensions are now discovered via a "plugin registrar" type
+ which will be extended in the future to other various plugins.
+ * Lints have been restructured to allow for dynamically loadable lints.
+ * A number of rustdoc improvements:
+ * The HTML output has been visually redesigned.
+ * Markdown is now powered by hoedown instead of sundown.
+ * Searching heuristics have been greatly improved.
+ * The search index has been reduced in size by a great amount.
+ * Cross-crate documentation via `pub use` has been greatly improved.
+ * Primitive types are now hyperlinked and documented.
+ * Documentation has been moved from static.rust-lang.org/doc to
+ doc.rust-lang.org
+ * A new sandbox, play.rust-lang.org, is available for running and
+ sharing rust code examples on-line.
+ * Unused attributes are now more robustly warned about.
+ * The dead_code lint now warns about unused struct fields.
+ * Cross-compiling to iOS is now supported.
+ * Cross-compiling to mipsel is now supported.
+ * Stability attributes are now inherited by default and no longer apply
+ to intra-crate usage, only inter-crate usage.
+ * Error message related to non-exhaustive match expressions have been
+ greatly improved.
+
Version 0.10 (April 2014)
-------------------------
Here is the function that implements the child task:
~~~
+#![allow(deprecated)]
+
use std::comm::DuplexStream;
# fn main() {
fn stringifier(channel: &DuplexStream<String, uint>) {
Here is the code for the parent task:
~~~
+#![allow(deprecated)]
+
use std::comm::duplex;
# use std::task::spawn;
# use std::comm::DuplexStream;
Next, we'll learn more about Rust itself, by starting to write a more complicated
program. We hope you want to do more with Rust than just print "Hello, world!"
-## If
+## Guessing Game
-## Functions
+Let's write a bigger program in Rust. We could just go through a laundry list
+of Rust features, but that's boring. Instead, we'll learn more about how to
+code in Rust by writing a few example projects.
-return
+For our first project, we'll implement a classic beginner programming problem:
+the guessing game. Here's how it works: Our program will generate a random
+integer between one and a hundred. It will then prompt us to enter a guess.
+Upon entering our guess, it will tell us if we're too low or too high. Once we
+guess correctly, it will congratulate us, and print the number of guesses we've
+taken to the screen. Sound good? It sounds easy, but it'll end up showing off a
+number of basic features of Rust.
-comments
+### Set up
-## Testing
+Let's set up a new project. Go to your projects directory, and make a new
+directory for the project, as well as a `src` directory for our code:
-attributes
+```{bash}
+$ cd ~/projects
+$ mkdir guessing_game
+$ cd guessing_game
+$ mkdir src
+```
-stability markers
+Great. Next, let's make a `Cargo.toml` file so Cargo knows how to build our
+project:
-## Crates and Modules
+```{ignore}
+[package]
-visibility
+name = "guessing_game"
+version = "0.1.0"
+authors = [ "someone@example.com" ]
+
+[[bin]]
+
+name = "guessing_game"
+```
+
+Finally, we need our source file. Let's just make it hello world for now, so we
+can check that our setup works. In `src/guessing_game.rs`:
+
+```{rust}
+fn main() {
+ println!("Hello world!");
+}
+```
+
+Let's make sure that worked:
+
+```{bash}
+$ cargo build
+ Compiling guessing_game v0.1.0 (file:/home/you/projects/guessing_game)
+$
+```
+
+Excellent! Open up your `src/guessing_game.rs` again. We'll be writing all of
+our code in this file. The next section of the tutorial will show you how to
+build multiple-file projects.
+
+## Variable bindings
+
+The first thing we'll learn about are 'variable bindings.' They look like this:
+
+```{rust}
+let x = 5i;
+```
+
+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:
+
+```{rust}
+let (x, y) = (1i, 2i);
+```
+
+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.
+
+By the way, in these examples, `i` indicates that the number is an integer.
+
+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
+"[Hindley-Milner type
+inference](http://en.wikipedia.org/wiki/Hindley%E2%80%93Milner_type_system)",
+named after some really smart type theorists. If you clicked that link, don't
+be scared: what this means for you is that Rust will attempt to infer the types
+in your program, and it's pretty good at it. If it can infer the type, Rust
+doesn't require you to actually type it out.
+
+We can add the type if we want to. Types come after a colon (`:`):
+
+```{rust}
+let x: int = 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 `int` and the value `five`." Rust requires you to
+initialize the binding with a value before you're allowed to use it. If
+we try...
+
+```{ignore}
+let x;
+```
+
+...we'll get an error:
+
+```{ignore}
+src/guessing_game.rs:2:9: 2:10 error: cannot determine a type for this local variable: unconstrained type
+src/guessing_game.rs:2 let x;
+ ^
+```
+
+Giving it a type will compile, though:
+
+```{ignore}
+let x: int;
+```
+
+Let's try it out. Change your `src/guessing_game.rs` file to look like this:
+
+```{rust}
+fn main() {
+ let x: int;
+
+ println!("Hello world!");
+}
+```
+
+You can use `cargo build` on the command line to build it. You'll get a warning,
+but it will still print "Hello, world!":
+
+```{ignore,notrust}
+ Compiling guessing_game v0.1.0 (file:/home/you/projects/guessing_game)
+src/guessing_game.rs:2:9: 2:10 warning: unused variable: `x`, #[warn(unused_variable)] on by default
+src/guessing_game.rs:2 let x: int;
+ ^
+```
+
+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,ignore}
+fn main() {
+ let x: int;
+
+ println!("The value of x is: {}", x);
+}
+```
+
+And try to build it. You'll get an error:
+
+```{bash}
+$ cargo build
+ Compiling guessing_game v0.1.0 (file:/home/you/projects/guessing_game)
+src/guessing_game.rs:4:39: 4:40 error: use of possibly uninitialized variable: `x`
+src/guessing_game.rs:4 println!("The value of x is: {}", x);
+ ^
+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!
+src/guessing_game.rs:4:5: 4:42 note: expansion site
+error: aborting due to previous error
+Could not execute process `rustc src/guessing_game.rs --crate-type bin --out-dir /home/you/projects/guessing_game/target -L /home/you/projects/guessing_game/target -L /home/you/projects/guessing_game/target/deps` (status=101)
+```
+
+Rust will not let us use a value that has not been initialized. So why let us
+declare a binding without initializing it? You'd think our first example would
+have errored. Well, Rust is smarter than that. Before we get to that, let's 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.
+
+When you just use the double 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). Fow now, we'll just stick to the default:
+integers aren't very complicated to print.
+
+So, we've cleared up all of the confusion around bindings, with one exception:
+why does Rust let us declare a variable binding without an initial value if we
+must initialize the binding before we use it? And how does it know that we have
+or have not initialized the binding? For that, we need to learn our next
+concept: `if`.
+
+## If
+
+## Functions
+
+return
+
+comments
## Compound Data Types
break/continue
-iterators
+## Guessing Game: complete
+
+At this point, you have successfully built the Guessing Game! Congratulations!
+For reference, [We've placed the sample code on
+GitHub](https://github.com/steveklabnik/guessing_game).
+
+You've now learned the basic syntax of Rust. All of this is relatively close to
+various other programming languages you have used in the past. These
+fundamental syntactical and semantic elements will form the foundation for the
+rest of your Rust education.
+
+Now that you're an expert at the basics, it's time to learn about some of
+Rust's more unique features.
+
+## iterators
## Lambdas
+## Testing
+
+attributes
+
+stability markers
+
+## Crates and Modules
+
+visibility
+
+
## Generics
## Traits
let n2: uint = v.len();
assert_eq!(n1, n2);
while i < n1 {
- let a: u8 = s1.as_slice()[i];
- let b: u8 = s2.as_slice()[i];
+ let a: u8 = s1.as_bytes()[i];
+ let b: u8 = s2.as_bytes()[i];
debug!("{}", a);
debug!("{}", b);
assert_eq!(a, b);
return None
}
- let byte = self.as_slice()[len - 1];
+ let byte = self.as_bytes()[len - 1];
self.vec.set_len(len - 1);
Some(byte)
}
fn lines_any(&self) -> AnyLines<'a> {
self.lines().map(|line| {
let l = line.len();
- if l > 0 && line[l - 1] == '\r' as u8 { line.slice(0, l - 1) }
+ if l > 0 && line.as_bytes()[l - 1] == '\r' as u8 { line.slice(0, l - 1) }
else { line }
})
}
fn is_char_boundary(&self, index: uint) -> bool {
if index == self.len() { return true; }
if index > self.len() { return false; }
- let b = self[index];
+ let b = self.as_bytes()[index];
return b < 128u8 || b >= 192u8;
}
#[inline]
fn char_range_at(&self, i: uint) -> CharRange {
- if self[i] < 128u8 {
- return CharRange {ch: self[i] as char, next: i + 1 };
+ if self.as_bytes()[i] < 128u8 {
+ return CharRange {ch: self.as_bytes()[i] as char, next: i + 1 };
}
// Multibyte case is a fn to allow char_range_at to inline cleanly
fn multibyte_char_range_at(s: &str, i: uint) -> CharRange {
- let mut val = s[i] as u32;
+ let mut val = s.as_bytes()[i] as u32;
let w = UTF8_CHAR_WIDTH[val as uint] as uint;
assert!((w != 0));
val = utf8_first_byte!(val, w);
- val = utf8_acc_cont_byte!(val, s[i + 1]);
- if w > 2 { val = utf8_acc_cont_byte!(val, s[i + 2]); }
- if w > 3 { val = utf8_acc_cont_byte!(val, s[i + 3]); }
+ val = utf8_acc_cont_byte!(val, s.as_bytes()[i + 1]);
+ if w > 2 { val = utf8_acc_cont_byte!(val, s.as_bytes()[i + 2]); }
+ if w > 3 { val = utf8_acc_cont_byte!(val, s.as_bytes()[i + 3]); }
return CharRange {ch: unsafe { mem::transmute(val) }, next: i + w};
}
let mut prev = start;
prev = prev.saturating_sub(1);
- if self[prev] < 128 { return CharRange{ch: self[prev] as char, next: prev} }
+ if self.as_bytes()[prev] < 128 {
+ return CharRange{ch: self.as_bytes()[prev] as char, next: prev}
+ }
// Multibyte case is a fn to allow char_range_at_reverse to inline cleanly
fn multibyte_char_range_at_reverse(s: &str, mut i: uint) -> CharRange {
// while there is a previous byte == 10......
- while i > 0 && s[i] & 192u8 == TAG_CONT_U8 {
+ while i > 0 && s.as_bytes()[i] & 192u8 == TAG_CONT_U8 {
i -= 1u;
}
- let mut val = s[i] as u32;
+ let mut val = s.as_bytes()[i] as u32;
let w = UTF8_CHAR_WIDTH[val as uint] as uint;
assert!((w != 0));
val = utf8_first_byte!(val, w);
- val = utf8_acc_cont_byte!(val, s[i + 1]);
- if w > 2 { val = utf8_acc_cont_byte!(val, s[i + 2]); }
- if w > 3 { val = utf8_acc_cont_byte!(val, s[i + 3]); }
+ val = utf8_acc_cont_byte!(val, s.as_bytes()[i + 1]);
+ if w > 2 { val = utf8_acc_cont_byte!(val, s.as_bytes()[i + 2]); }
+ if w > 3 { val = utf8_acc_cont_byte!(val, s.as_bytes()[i + 3]); }
return CharRange {ch: unsafe { mem::transmute(val) }, next: i};
}
}
fn is_arg(arg: &str) -> bool {
- arg.len() > 1 && arg[0] == '-' as u8
+ arg.len() > 1 && arg.as_bytes()[0] == '-' as u8
}
fn find_opt(opts: &[Opt], nm: Name) -> Option<uint> {
} else {
let mut names;
let mut i_arg = None;
- if cur.as_slice()[1] == '-' as u8 {
+ if cur.as_bytes()[1] == '-' as u8 {
let tail = cur.as_slice().slice(2, curlen);
let tail_eq: Vec<&str> = tail.split('=').collect();
if tail_eq.len() <= 1 {
#[cfg(unix)] type msglen_t = libc::size_t;
impl rtio::RtioUdpSocket for UdpSocket {
- fn recvfrom(&mut self, buf: &mut [u8]) -> IoResult<(uint, rtio::SocketAddr)> {
+ fn recv_from(&mut self, buf: &mut [u8]) -> IoResult<(uint, rtio::SocketAddr)> {
let fd = self.fd();
let mut storage: libc::sockaddr_storage = unsafe { mem::zeroed() };
let storagep = &mut storage as *mut _ as *mut libc::sockaddr;
})
}
- fn sendto(&mut self, buf: &[u8], dst: rtio::SocketAddr) -> IoResult<()> {
+ fn send_to(&mut self, buf: &[u8], dst: rtio::SocketAddr) -> IoResult<()> {
let (dst, dstlen) = addr_to_sockaddr(dst);
let dstp = &dst as *const _ as *const libc::sockaddr;
let dstlen = dstlen as libc::socklen_t;
// Underscore-qualify anything that didn't start as an ident.
if result.len() > 0u &&
- result.as_slice()[0] != '_' as u8 &&
- ! char::is_XID_start(result.as_slice()[0] as char) {
+ result.as_bytes()[0] != '_' as u8 &&
+ ! char::is_XID_start(result.as_bytes()[0] as char) {
return format!("_{}", result.as_slice());
}
let extra2 = id % EXTRA_CHARS.len();
let id = id / EXTRA_CHARS.len();
let extra3 = id % EXTRA_CHARS.len();
- hash.push_char(EXTRA_CHARS[extra1] as char);
- hash.push_char(EXTRA_CHARS[extra2] as char);
- hash.push_char(EXTRA_CHARS[extra3] as char);
+ hash.push_char(EXTRA_CHARS.as_bytes()[extra1] as char);
+ hash.push_char(EXTRA_CHARS.as_bytes()[extra2] as char);
+ hash.push_char(EXTRA_CHARS.as_bytes()[extra3] as char);
exported_name(path,
hash.as_slice(),
fn item_method_sort(item: ebml::Doc) -> char {
let mut ret = 'r';
reader::tagged_docs(item, tag_item_trait_method_sort, |doc| {
- ret = doc.as_str_slice()[0] as char;
+ ret = doc.as_str_slice().as_bytes()[0] as char;
false
});
ret
let explicit_self_doc = reader::get_doc(item, tag_item_trait_method_explicit_self);
let string = explicit_self_doc.as_str_slice();
- let explicit_self_kind = string[0];
+ let explicit_self_kind = string.as_bytes()[0];
match explicit_self_kind as char {
's' => ast::SelfStatic,
'v' => ast::SelfValue,
'~' => ast::SelfUniq,
// FIXME(#4846) expl. region
- '&' => ast::SelfRegion(None, get_mutability(string[1])),
+ '&' => ast::SelfRegion(None, get_mutability(string.as_bytes()[1])),
_ => fail!("unknown self type code: `{}`", explicit_self_kind as char)
}
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![allow(non_camel_case_types)]
-
use middle::const_eval::{compare_const_vals, const_bool, const_float, const_nil, const_val};
use middle::const_eval::{eval_const_expr, lookup_const_by_id};
use middle::def::*;
use middle::pat_util::*;
use middle::ty::*;
use middle::ty;
-
+use std::fmt;
use std::gc::{Gc, GC};
-use std::iter;
+use std::iter::AdditiveIterator;
+use std::iter::range_inclusive;
use syntax::ast::*;
use syntax::ast_util::{is_unguarded, walk_pat};
use syntax::codemap::{Span, Spanned, DUMMY_SP};
use syntax::visit::{Visitor, FnKind};
use util::ppaux::ty_to_str;
-type Matrix = Vec<Vec<Gc<Pat>>>;
+struct Matrix(Vec<Vec<Gc<Pat>>>);
+
+/// Pretty-printer for matrices of patterns, example:
+/// ++++++++++++++++++++++++++
+/// + _ + [] +
+/// ++++++++++++++++++++++++++
+/// + true + [First] +
+/// ++++++++++++++++++++++++++
+/// + true + [Second(true)] +
+/// ++++++++++++++++++++++++++
+/// + false + [_] +
+/// ++++++++++++++++++++++++++
+/// + _ + [_, _, ..tail] +
+/// ++++++++++++++++++++++++++
+impl fmt::Show for Matrix {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ try!(write!(f, "\n"));
+
+ let &Matrix(ref m) = self;
+ let pretty_printed_matrix: Vec<Vec<String>> = m.iter().map(|row| {
+ row.iter().map(|&pat| pat_to_str(pat)).collect::<Vec<String>>()
+ }).collect();
+
+ let column_count = m.iter().map(|row| row.len()).max().unwrap_or(0u);
+ assert!(m.iter().all(|row| row.len() == column_count));
+ let column_widths: Vec<uint> = range(0, column_count).map(|col| {
+ pretty_printed_matrix.iter().map(|row| row.get(col).len()).max().unwrap_or(0u)
+ }).collect();
+
+ let total_width = column_widths.iter().map(|n| *n).sum() + column_count * 3 + 1;
+ let br = String::from_char(total_width, '+');
+ try!(write!(f, "{}\n", br));
+ for row in pretty_printed_matrix.move_iter() {
+ try!(write!(f, "+"));
+ for (column, pat_str) in row.move_iter().enumerate() {
+ try!(write!(f, " "));
+ f.width = Some(*column_widths.get(column));
+ try!(f.pad(pat_str.as_slice()));
+ try!(write!(f, " +"));
+ }
+ try!(write!(f, "\n"));
+ try!(write!(f, "{}\n", br));
+ }
+ Ok(())
+ }
+}
+
+struct MatchCheckCtxt<'a> {
+ tcx: &'a ty::ctxt
+}
+
+#[deriving(Clone, PartialEq)]
+enum Constructor {
+ /// The constructor of all patterns that don't vary by constructor,
+ /// e.g. struct patterns and fixed-length arrays.
+ Single,
+ /// Enum variants.
+ Variant(DefId),
+ /// Literal values.
+ ConstantValue(const_val),
+ /// Ranges of literal values (2..5).
+ ConstantRange(const_val, const_val),
+ /// Array patterns of length n.
+ Slice(uint)
+}
#[deriving(Clone)]
enum Usefulness {
}
}
-fn def_to_path(tcx: &ty::ctxt, id: DefId) -> Path {
- ty::with_path(tcx, id, |mut path| Path {
- global: false,
- segments: path.last().map(|elem| PathSegment {
- identifier: Ident::new(elem.name()),
- lifetimes: vec!(),
- types: OwnedSlice::empty()
- }).move_iter().collect(),
- span: DUMMY_SP,
- })
-}
-
-struct MatchCheckCtxt<'a> {
- tcx: &'a ty::ctxt,
-}
-
impl<'a> Visitor<()> for MatchCheckCtxt<'a> {
fn visit_expr(&mut self, ex: &Expr, _: ()) {
check_expr(self, ex);
}
}
-pub fn check_crate(tcx: &ty::ctxt,
- krate: &Crate) {
- let mut cx = MatchCheckCtxt {
- tcx: tcx,
- };
+pub fn check_crate(tcx: &ty::ctxt, krate: &Crate) {
+ let mut cx = MatchCheckCtxt { tcx: tcx, };
visit::walk_crate(&mut cx, krate, ());
// If the type *is* empty, it's vacuously exhaustive
return;
}
- let m: Matrix = arms
+ let m: Matrix = Matrix(arms
.iter()
.filter(|&arm| is_unguarded(arm))
.flat_map(|arm| arm.pats.iter())
.map(|pat| vec!(pat.clone()))
- .collect();
+ .collect());
check_exhaustive(cx, ex.span, &m);
},
_ => ()
// Check for unreachable patterns
fn check_arms(cx: &MatchCheckCtxt, arms: &[Arm]) {
- let mut seen = Vec::new();
+ let mut seen = Matrix(vec!());
for arm in arms.iter() {
for pat in arm.pats.iter() {
// Check that we do not match against a static NaN (#6804)
NotUseful => cx.tcx.sess.span_err(pat.span, "unreachable pattern"),
_ => ()
}
- if arm.guard.is_none() { seen.push(v); }
+ if arm.guard.is_none() {
+ let Matrix(mut rows) = seen;
+ rows.push(v);
+ seen = Matrix(rows);
+ }
}
}
}
fn check_exhaustive(cx: &MatchCheckCtxt, sp: Span, m: &Matrix) {
match is_useful(cx, m, [wild()], ConstructWitness) {
- NotUseful => {
- // This is good, wildcard pattern isn't reachable
- return;
- }
Useful(pats) => {
let witness = match pats.as_slice() {
[witness] => witness,
let msg = format!("non-exhaustive patterns: `{0}` not covered", pat_to_str(&*witness));
cx.tcx.sess.span_err(sp, msg.as_slice());
}
+ NotUseful => {
+ // This is good, wildcard pattern isn't reachable
+ }
}
}
-#[deriving(Clone, PartialEq)]
-enum ctor {
- single,
- variant(DefId),
- val(const_val),
- range(const_val, const_val),
- vec(uint)
-}
-
fn const_val_to_expr(value: &const_val) -> Gc<Expr> {
let node = match value {
&const_bool(b) => LitBool(b),
&const_nil => LitNil,
_ => unreachable!()
};
- box(GC) Expr {
+ box (GC) Expr {
id: 0,
node: ExprLit(box(GC) Spanned { node: node, span: DUMMY_SP }),
span: DUMMY_SP
}
}
-fn construct_witness(cx: &MatchCheckCtxt, ctor: &ctor, pats: Vec<Gc<Pat>>, lty: ty::t) -> Gc<Pat> {
- let pat = match ty::get(lty).sty {
+fn def_to_path(tcx: &ty::ctxt, id: DefId) -> Path {
+ ty::with_path(tcx, id, |mut path| Path {
+ global: false,
+ segments: path.last().map(|elem| PathSegment {
+ identifier: Ident::new(elem.name()),
+ lifetimes: vec!(),
+ types: OwnedSlice::empty()
+ }).move_iter().collect(),
+ span: DUMMY_SP,
+ })
+}
+
+/// Constructs a partial witness for a pattern given a list of
+/// patterns expanded by the specialization step.
+///
+/// When a pattern P is discovered to be useful, this function is used bottom-up
+/// to reconstruct a complete witness, e.g. a pattern P' that covers a subset
+/// of values, V, where each value in that set is not covered by any previously
+/// used patterns and is covered by the pattern P'. Examples:
+///
+/// left_ty: tuple of 3 elements
+/// pats: [10, 20, _] => (10, 20, _)
+///
+/// left_ty: struct X { a: (bool, &'static str), b: uint}
+/// pats: [(false, "foo"), 42] => X { a: (false, "foo"), b: 42 }
+fn construct_witness(cx: &MatchCheckCtxt, ctor: &Constructor,
+ pats: Vec<Gc<Pat>>, left_ty: ty::t) -> Gc<Pat> {
+ let pat = match ty::get(left_ty).sty {
ty::ty_tup(_) => PatTup(pats),
ty::ty_enum(cid, _) | ty::ty_struct(cid, _) => {
let (vid, is_structure) = match ctor {
- &variant(vid) => (vid,
+ &Variant(vid) => (vid,
ty::enum_variant_with_id(cx.tcx, cid, vid).arg_names.is_some()),
_ => (cid, true)
};
} else {
PatEnum(def_to_path(cx.tcx, vid), Some(pats))
}
- },
+ }
ty::ty_rptr(_, ty::mt { ty: ty, .. }) => {
match ty::get(ty).sty {
+ ty::ty_vec(_, Some(n)) => match ctor {
+ &Single => {
+ assert_eq!(pats.len(), n);
+ PatVec(pats, None, vec!())
+ },
+ _ => unreachable!()
+ },
ty::ty_vec(_, None) => match ctor {
- &vec(_) => PatVec(pats, None, vec!()),
+ &Slice(n) => {
+ assert_eq!(pats.len(), n);
+ PatVec(pats, None, vec!())
+ },
_ => unreachable!()
},
ty::ty_str => PatWild,
+
_ => {
assert_eq!(pats.len(), 1);
PatRegion(pats.get(0).clone())
}
}
- },
+ }
ty::ty_box(_) => {
assert_eq!(pats.len(), 1);
PatBox(pats.get(0).clone())
- },
+ }
+
+ ty::ty_vec(_, Some(len)) => {
+ assert_eq!(pats.len(), len);
+ PatVec(pats, None, vec!())
+ }
_ => {
- match ctor {
- &vec(_) => PatVec(pats, None, vec!()),
- &val(ref v) => PatLit(const_val_to_expr(v)),
+ match *ctor {
+ ConstantValue(ref v) => PatLit(const_val_to_expr(v)),
_ => PatWild
}
}
};
- box(GC) Pat {
+ box (GC) Pat {
id: 0,
node: pat,
span: DUMMY_SP
}
}
-fn missing_constructor(cx: &MatchCheckCtxt, m: &Matrix, left_ty: ty::t) -> Option<ctor> {
- let used_constructors: Vec<ctor> = m.iter()
- .filter_map(|r| pat_ctor_id(cx, left_ty, *r.get(0)))
+fn missing_constructor(cx: &MatchCheckCtxt, &Matrix(ref rows): &Matrix,
+ left_ty: ty::t, max_slice_length: uint) -> Option<Constructor> {
+ let used_constructors: Vec<Constructor> = rows.iter()
+ .flat_map(|row| pat_constructors(cx, *row.get(0), left_ty, max_slice_length).move_iter())
.collect();
-
- all_constructors(cx, m, left_ty)
+ all_constructors(cx, left_ty, max_slice_length)
.move_iter()
.find(|c| !used_constructors.contains(c))
}
-fn all_constructors(cx: &MatchCheckCtxt, m: &Matrix, left_ty: ty::t) -> Vec<ctor> {
- // This produces a list of all vector constructors that we would expect to appear
- // in an exhaustive set of patterns. Because such a list would normally be infinite,
- // we narrow it down to only those constructors that actually appear in the inspected
- // column, plus, any that are missing and not covered by a pattern with a destructured slice.
- fn vec_constructors(m: &Matrix) -> Vec<ctor> {
- let max_vec_len = m.iter().map(|r| match r.get(0).node {
- PatVec(ref before, _, ref after) => before.len() + after.len(),
- _ => 0u
- }).max().unwrap_or(0u);
- let min_vec_len_with_slice = m.iter().map(|r| match r.get(0).node {
- PatVec(ref before, Some(_), ref after) => before.len() + after.len(),
- _ => max_vec_len + 1
- }).min().unwrap_or(max_vec_len + 1);
- let other_lengths = m.iter().map(|r| match r.get(0).node {
- PatVec(ref before, _, ref after) => before.len() + after.len(),
- _ => 0u
- }).filter(|&len| len > min_vec_len_with_slice);
- iter::range_inclusive(0u, min_vec_len_with_slice)
- .chain(other_lengths)
- .map(|len| vec(len))
- .collect()
- }
-
+/// This determines the set of all possible constructors of a pattern matching
+/// values of type `left_ty`. For vectors, this would normally be an infinite set
+/// but is instead bounded by the maximum fixed length of slice patterns in
+/// the column of patterns being analyzed.
+fn all_constructors(cx: &MatchCheckCtxt, left_ty: ty::t,
+ max_slice_length: uint) -> Vec<Constructor> {
match ty::get(left_ty).sty {
ty::ty_bool =>
- [true, false].iter().map(|b| val(const_bool(*b))).collect(),
+ [true, false].iter().map(|b| ConstantValue(const_bool(*b))).collect(),
ty::ty_nil =>
- vec!(val(const_nil)),
+ vec!(ConstantValue(const_nil)),
ty::ty_rptr(_, ty::mt { ty: ty, .. }) => match ty::get(ty).sty {
- ty::ty_vec(_, None) => vec_constructors(m),
- _ => vec!(single)
+ ty::ty_vec(_, None) =>
+ range_inclusive(0, max_slice_length).map(|length| Slice(length)).collect(),
+ _ => vec!(Single)
},
ty::ty_enum(eid, _) =>
ty::enum_variants(cx.tcx, eid)
.iter()
- .map(|va| variant(va.id))
+ .map(|va| Variant(va.id))
.collect(),
- ty::ty_vec(_, None) =>
- vec_constructors(m),
-
- ty::ty_vec(_, Some(n)) =>
- vec!(vec(n)),
-
_ =>
- vec!(single)
+ vec!(Single)
}
}
// Note: is_useful doesn't work on empty types, as the paper notes.
// So it assumes that v is non-empty.
-fn is_useful(cx: &MatchCheckCtxt, m: &Matrix, v: &[Gc<Pat>],
- witness: WitnessPreference) -> Usefulness {
- if m.len() == 0u {
+fn is_useful(cx: &MatchCheckCtxt, m @ &Matrix(ref rows): &Matrix,
+ v: &[Gc<Pat>], witness: WitnessPreference) -> Usefulness {
+ debug!("{:}", m);
+ if rows.len() == 0u {
return Useful(vec!());
}
- if m.get(0).len() == 0u {
+ if rows.get(0).len() == 0u {
return NotUseful;
}
- let real_pat = match m.iter().find(|r| r.get(0).id != 0) {
+ let real_pat = match rows.iter().find(|r| r.get(0).id != 0) {
Some(r) => {
match r.get(0).node {
// An arm of the form `ref x @ sub_pat` has type
ty::pat_ty(cx.tcx, &*real_pat)
};
- match pat_ctor_id(cx, left_ty, v[0]) {
- None => match missing_constructor(cx, m, left_ty) {
+ let max_slice_length = rows.iter().filter_map(|row| match row.get(0).node {
+ PatVec(ref before, _, ref after) => Some(before.len() + after.len()),
+ _ => None
+ }).max().map_or(0, |v| v + 1);
+
+ let constructors = pat_constructors(cx, v[0], left_ty, max_slice_length);
+ if constructors.is_empty() {
+ match missing_constructor(cx, m, left_ty, max_slice_length) {
None => {
- all_constructors(cx, m, left_ty).move_iter().filter_map(|c| {
+ all_constructors(cx, left_ty, max_slice_length).move_iter().filter_map(|c| {
is_useful_specialized(cx, m, v, c.clone(),
left_ty, witness).useful().map(|pats| {
Useful(match witness {
}).nth(0).unwrap_or(NotUseful)
},
- Some(ctor) => {
- let matrix = m.iter().filter_map(|r| default(cx, r.as_slice())).collect();
+ Some(constructor) => {
+ let matrix = Matrix(rows.iter().filter_map(|r|
+ default(cx, r.as_slice())).collect());
match is_useful(cx, &matrix, v.tail(), witness) {
Useful(pats) => Useful(match witness {
ConstructWitness => {
- let arity = constructor_arity(cx, &ctor, left_ty);
+ let arity = constructor_arity(cx, &constructor, left_ty);
let wild_pats = Vec::from_elem(arity, wild());
- let enum_pat = construct_witness(cx, &ctor, wild_pats, left_ty);
+ let enum_pat = construct_witness(cx, &constructor, wild_pats, left_ty);
(vec!(enum_pat)).append(pats.as_slice())
}
LeaveOutWitness => vec!()
result => result
}
}
- },
-
- Some(v0_ctor) => is_useful_specialized(cx, m, v, v0_ctor, left_ty, witness)
+ }
+ } else {
+ constructors.move_iter().filter_map(|c| {
+ is_useful_specialized(cx, m, v, c.clone(), left_ty, witness)
+ .useful().map(|pats| Useful(pats))
+ }).nth(0).unwrap_or(NotUseful)
}
}
-fn is_useful_specialized(cx: &MatchCheckCtxt, m: &Matrix, v: &[Gc<Pat>],
- ctor: ctor, lty: ty::t, witness: WitnessPreference) -> Usefulness {
+fn is_useful_specialized(cx: &MatchCheckCtxt, &Matrix(ref m): &Matrix, v: &[Gc<Pat>],
+ ctor: Constructor, lty: ty::t, witness: WitnessPreference) -> Usefulness {
let arity = constructor_arity(cx, &ctor, lty);
- let matrix = m.iter().filter_map(|r| {
+ let matrix = Matrix(m.iter().filter_map(|r| {
specialize(cx, r.as_slice(), &ctor, arity)
- }).collect();
+ }).collect());
match specialize(cx, v, &ctor, arity) {
Some(v) => is_useful(cx, &matrix, v.as_slice(), witness),
None => NotUseful
}
}
-fn pat_ctor_id(cx: &MatchCheckCtxt, left_ty: ty::t, p: Gc<Pat>) -> Option<ctor> {
+/// Determines the constructors that the given pattern can be specialized to.
+///
+/// In most cases, there's only one constructor that a specific pattern
+/// represents, such as a specific enum variant or a specific literal value.
+/// Slice patterns, however, can match slices of different lengths. For instance,
+/// `[a, b, ..tail]` can match a slice of length 2, 3, 4 and so on.
+///
+/// On the other hand, a wild pattern and an identifier pattern cannot be
+/// specialized in any way.
+fn pat_constructors(cx: &MatchCheckCtxt, p: Gc<Pat>,
+ left_ty: ty::t, max_slice_length: uint) -> Vec<Constructor> {
let pat = raw_pat(p);
match pat.node {
PatIdent(..) =>
match cx.tcx.def_map.borrow().find(&pat.id) {
Some(&DefStatic(did, false)) => {
let const_expr = lookup_const_by_id(cx.tcx, did).unwrap();
- Some(val(eval_const_expr(cx.tcx, &*const_expr)))
+ vec!(ConstantValue(eval_const_expr(cx.tcx, &*const_expr)))
},
- Some(&DefVariant(_, id, _)) => Some(variant(id)),
- _ => None
+ Some(&DefVariant(_, id, _)) => vec!(Variant(id)),
+ _ => vec!()
},
PatEnum(..) =>
match cx.tcx.def_map.borrow().find(&pat.id) {
Some(&DefStatic(did, false)) => {
let const_expr = lookup_const_by_id(cx.tcx, did).unwrap();
- Some(val(eval_const_expr(cx.tcx, &*const_expr)))
+ vec!(ConstantValue(eval_const_expr(cx.tcx, &*const_expr)))
},
- Some(&DefVariant(_, id, _)) => Some(variant(id)),
- _ => Some(single)
+ Some(&DefVariant(_, id, _)) => vec!(Variant(id)),
+ _ => vec!(Single)
},
PatStruct(..) =>
match cx.tcx.def_map.borrow().find(&pat.id) {
- Some(&DefVariant(_, id, _)) => Some(variant(id)),
- _ => Some(single)
+ Some(&DefVariant(_, id, _)) => vec!(Variant(id)),
+ _ => vec!(Single)
},
PatLit(expr) =>
- Some(val(eval_const_expr(cx.tcx, &*expr))),
+ vec!(ConstantValue(eval_const_expr(cx.tcx, &*expr))),
PatRange(lo, hi) =>
- Some(range(eval_const_expr(cx.tcx, &*lo), eval_const_expr(cx.tcx, &*hi))),
- PatVec(ref before, _, ref after) => match ty::get(left_ty).sty {
- ty::ty_vec(_, Some(n)) =>
- Some(vec(n)),
- _ =>
- Some(vec(before.len() + after.len()))
- },
+ vec!(ConstantRange(eval_const_expr(cx.tcx, &*lo), eval_const_expr(cx.tcx, &*hi))),
+ PatVec(ref before, ref slice, ref after) =>
+ match ty::get(left_ty).sty {
+ ty::ty_vec(_, Some(_)) => vec!(Single),
+ _ => if slice.is_some() {
+ range_inclusive(before.len() + after.len(), max_slice_length)
+ .map(|length| Slice(length))
+ .collect()
+ } else {
+ vec!(Slice(before.len() + after.len()))
+ }
+ },
PatBox(_) | PatTup(_) | PatRegion(..) =>
- Some(single),
+ vec!(Single),
PatWild | PatWildMulti =>
- None,
+ vec!(),
PatMac(_) =>
cx.tcx.sess.bug("unexpanded macro")
}
let pat = raw_pat(p);
match pat.node {
PatWild | PatWildMulti => true,
- PatIdent(_, _, _) => {
+ PatIdent(_, _, _) =>
match cx.tcx.def_map.borrow().find(&pat.id) {
Some(&DefVariant(_, _, _)) | Some(&DefStatic(..)) => false,
_ => true
- }
- }
+ },
+ PatVec(ref before, Some(_), ref after) =>
+ before.is_empty() && after.is_empty(),
_ => false
}
}
-fn constructor_arity(cx: &MatchCheckCtxt, ctor: &ctor, ty: ty::t) -> uint {
+/// This computes the arity of a constructor. The arity of a constructor
+/// is how many subpattern patterns of that constructor should be expanded to.
+///
+/// For instance, a tuple pattern (_, 42u, Some([])) has the arity of 3.
+/// A struct pattern's arity is the number of fields it contains, etc.
+fn constructor_arity(cx: &MatchCheckCtxt, ctor: &Constructor, ty: ty::t) -> uint {
match ty::get(ty).sty {
ty::ty_tup(ref fs) => fs.len(),
ty::ty_box(_) | ty::ty_uniq(_) => 1u,
ty::ty_rptr(_, ty::mt { ty: ty, .. }) => match ty::get(ty).sty {
ty::ty_vec(_, None) => match *ctor {
- vec(n) => n,
- _ => 0u
+ Slice(length) => length,
+ _ => unreachable!()
},
ty::ty_str => 0u,
_ => 1u
},
ty::ty_enum(eid, _) => {
match *ctor {
- variant(id) => enum_variant_with_id(cx.tcx, eid, id).args.len(),
+ Variant(id) => enum_variant_with_id(cx.tcx, eid, id).args.len(),
_ => unreachable!()
}
}
ty::ty_struct(cid, _) => ty::lookup_struct_fields(cx.tcx, cid).len(),
- ty::ty_vec(_, _) => match *ctor {
- vec(n) => n,
- _ => 0u
- },
+ ty::ty_vec(_, Some(n)) => n,
_ => 0u
}
}
-fn wild() -> Gc<Pat> {
- box(GC) Pat {id: 0, node: PatWild, span: DUMMY_SP}
-}
-
-fn range_covered_by_constructor(ctor_id: &ctor, from: &const_val, to: &const_val) -> Option<bool> {
- let (c_from, c_to) = match *ctor_id {
- val(ref value) => (value, value),
- range(ref from, ref to) => (from, to),
- single => return Some(true),
- _ => unreachable!()
+fn range_covered_by_constructor(ctor: &Constructor,
+ from: &const_val,to: &const_val) -> Option<bool> {
+ let (c_from, c_to) = match *ctor {
+ ConstantValue(ref value) => (value, value),
+ ConstantRange(ref from, ref to) => (from, to),
+ Single => return Some(true),
+ _ => unreachable!()
};
let cmp_from = compare_const_vals(c_from, from);
let cmp_to = compare_const_vals(c_to, to);
}
}
+/// This is the main specialization step. It expands the first pattern in the given row
+/// into `arity` patterns based on the constructor. For most patterns, the step is trivial,
+/// for instance tuple patterns are flattened and box patterns expand into their inner pattern.
+///
+/// OTOH, slice patterns with a subslice pattern (..tail) can be expanded into multiple
+/// different patterns.
+/// Structure patterns with a partial wild pattern (Foo { a: 42, .. }) have their missing
+/// fields filled with wild patterns.
fn specialize(cx: &MatchCheckCtxt, r: &[Gc<Pat>],
- ctor_id: &ctor, arity: uint) -> Option<Vec<Gc<Pat>>> {
+ constructor: &Constructor, arity: uint) -> Option<Vec<Gc<Pat>>> {
let &Pat {
- id: ref pat_id, node: ref n, span: ref pat_span
+ id: pat_id, node: ref node, span: pat_span
} = &(*raw_pat(r[0]));
- let head: Option<Vec<Gc<Pat>>> = match n {
- &PatWild => {
- Some(Vec::from_elem(arity, wild()))
- }
- &PatWildMulti => {
- Some(Vec::from_elem(arity, wild()))
- }
+ let head: Option<Vec<Gc<Pat>>> = match node {
+ &PatWild =>
+ Some(Vec::from_elem(arity, wild())),
+
+ &PatWildMulti =>
+ Some(Vec::from_elem(arity, wild())),
+
&PatIdent(_, _, _) => {
- let opt_def = cx.tcx.def_map.borrow().find_copy(pat_id);
+ let opt_def = cx.tcx.def_map.borrow().find_copy(&pat_id);
match opt_def {
- Some(DefVariant(_, id, _)) => if *ctor_id == variant(id) {
+ Some(DefVariant(_, id, _)) => if *constructor == Variant(id) {
Some(vec!())
} else {
None
Some(DefStatic(did, _)) => {
let const_expr = lookup_const_by_id(cx.tcx, did).unwrap();
let e_v = eval_const_expr(cx.tcx, &*const_expr);
- match range_covered_by_constructor(ctor_id, &e_v, &e_v) {
+ match range_covered_by_constructor(constructor, &e_v, &e_v) {
Some(true) => Some(vec!()),
Some(false) => None,
None => {
- cx.tcx.sess.span_err(*pat_span, "mismatched types between arms");
+ cx.tcx.sess.span_err(pat_span, "mismatched types between arms");
None
}
}
}
}
}
+
&PatEnum(_, ref args) => {
- let def = cx.tcx.def_map.borrow().get_copy(pat_id);
+ let def = cx.tcx.def_map.borrow().get_copy(&pat_id);
match def {
DefStatic(did, _) => {
let const_expr = lookup_const_by_id(cx.tcx, did).unwrap();
let e_v = eval_const_expr(cx.tcx, &*const_expr);
- match range_covered_by_constructor(ctor_id, &e_v, &e_v) {
+ match range_covered_by_constructor(constructor, &e_v, &e_v) {
Some(true) => Some(vec!()),
Some(false) => None,
None => {
- cx.tcx.sess.span_err(*pat_span, "mismatched types between arms");
+ cx.tcx.sess.span_err(pat_span, "mismatched types between arms");
None
}
}
}
- DefVariant(_, id, _) if *ctor_id != variant(id) => None,
+ DefVariant(_, id, _) if *constructor != Variant(id) => None,
DefVariant(..) | DefFn(..) | DefStruct(..) => {
Some(match args {
&Some(ref args) => args.clone(),
&PatStruct(_, ref pattern_fields, _) => {
// Is this a struct or an enum variant?
- let def = cx.tcx.def_map.borrow().get_copy(pat_id);
+ let def = cx.tcx.def_map.borrow().get_copy(&pat_id);
let class_id = match def {
- DefVariant(_, variant_id, _) => if *ctor_id == variant(variant_id) {
+ DefVariant(_, variant_id, _) => if *constructor == Variant(variant_id) {
Some(variant_id)
} else {
None
&PatLit(ref expr) => {
let expr_value = eval_const_expr(cx.tcx, &**expr);
- match range_covered_by_constructor(ctor_id, &expr_value, &expr_value) {
+ match range_covered_by_constructor(constructor, &expr_value, &expr_value) {
Some(true) => Some(vec!()),
Some(false) => None,
None => {
- cx.tcx.sess.span_err(*pat_span, "mismatched types between arms");
+ cx.tcx.sess.span_err(pat_span, "mismatched types between arms");
None
}
}
&PatRange(ref from, ref to) => {
let from_value = eval_const_expr(cx.tcx, &**from);
let to_value = eval_const_expr(cx.tcx, &**to);
- match range_covered_by_constructor(ctor_id, &from_value, &to_value) {
+ match range_covered_by_constructor(constructor, &from_value, &to_value) {
Some(true) => Some(vec!()),
Some(false) => None,
None => {
- cx.tcx.sess.span_err(*pat_span, "mismatched types between arms");
+ cx.tcx.sess.span_err(pat_span, "mismatched types between arms");
None
}
}
}
&PatVec(ref before, ref slice, ref after) => {
- match *ctor_id {
- vec(_) => {
- let num_elements = before.len() + after.len();
- if num_elements < arity && slice.is_some() {
- let mut result = Vec::new();
- result.push_all(before.as_slice());
- result.grow_fn(arity - num_elements, |_| wild());
- result.push_all(after.as_slice());
- Some(result)
- } else if num_elements == arity {
- let mut result = Vec::new();
- result.push_all(before.as_slice());
- result.push_all(after.as_slice());
- Some(result)
- } else {
- None
- }
- }
+ match *constructor {
+ // Fixed-length vectors.
+ Single => {
+ let mut pats = before.clone();
+ pats.grow_fn(arity - before.len() - after.len(), |_| wild());
+ pats.push_all(after.as_slice());
+ Some(pats)
+ },
+ Slice(length) if before.len() + after.len() <= length && slice.is_some() => {
+ let mut pats = before.clone();
+ pats.grow_fn(arity - before.len() - after.len(), |_| wild());
+ pats.push_all(after.as_slice());
+ Some(pats)
+ },
+ Slice(length) if before.len() + after.len() == length => {
+ let mut pats = before.clone();
+ pats.push_all(after.as_slice());
+ Some(pats)
+ },
_ => None
}
}
&PatMac(_) => {
- cx.tcx.sess.span_err(*pat_span, "unexpanded macro");
+ cx.tcx.sess.span_err(pat_span, "unexpanded macro");
None
}
};
}
fn is_refutable(cx: &MatchCheckCtxt, pat: Gc<Pat>) -> Option<Gc<Pat>> {
- let pats = vec!(vec!(pat));
+ let pats = Matrix(vec!(vec!(pat)));
is_useful(cx, &pats, [wild()], ConstructWitness)
.useful()
.map(|pats| {
impl<'a> DeadVisitor<'a> {
fn should_warn_about_field(&mut self, node: &ast::StructField_) -> bool {
let (is_named, has_leading_underscore) = match node.ident() {
- Some(ref ident) => (true, token::get_ident(*ident).get()[0] == ('_' as u8)),
+ Some(ref ident) => (true, token::get_ident(*ident).get().as_bytes()[0] == ('_' as u8)),
_ => (false, false)
};
let field_type = ty::node_id_to_type(self.tcx, node.id);
use middle::freevars;
use middle::pat_util;
use middle::ty;
-use middle::typeck::MethodCall;
+use middle::typeck::{MethodCall, MethodObject, MethodOrigin, MethodParam};
+use middle::typeck::{MethodStatic};
use middle::typeck;
-use syntax::ast;
-use syntax::codemap::{Span};
use util::ppaux::Repr;
use std::gc::Gc;
+use syntax::ast;
+use syntax::codemap::Span;
///////////////////////////////////////////////////////////////////////////
// The Delegate trait
WriteAndRead, // x += y
}
+enum OverloadedCallType {
+ FnOverloadedCall,
+ FnMutOverloadedCall,
+ FnOnceOverloadedCall,
+}
+
+impl OverloadedCallType {
+ fn from_trait_id(tcx: &ty::ctxt, trait_id: ast::DefId)
+ -> OverloadedCallType {
+ for &(maybe_function_trait, overloaded_call_type) in [
+ (tcx.lang_items.fn_once_trait(), FnOnceOverloadedCall),
+ (tcx.lang_items.fn_mut_trait(), FnMutOverloadedCall),
+ (tcx.lang_items.fn_trait(), FnOverloadedCall)
+ ].iter() {
+ match maybe_function_trait {
+ Some(function_trait) if function_trait == trait_id => {
+ return overloaded_call_type
+ }
+ _ => continue,
+ }
+ }
+
+ tcx.sess.bug("overloaded call didn't map to known function trait")
+ }
+
+ fn from_method_id(tcx: &ty::ctxt, method_id: ast::DefId)
+ -> OverloadedCallType {
+ let method_descriptor =
+ match tcx.methods.borrow_mut().find(&method_id) {
+ None => {
+ tcx.sess.bug("overloaded call method wasn't in method \
+ map")
+ }
+ Some(ref method_descriptor) => (*method_descriptor).clone(),
+ };
+ let impl_id = match method_descriptor.container {
+ ty::TraitContainer(_) => {
+ tcx.sess.bug("statically resolved overloaded call method \
+ belonged to a trait?!")
+ }
+ ty::ImplContainer(impl_id) => impl_id,
+ };
+ let trait_ref = match ty::impl_trait_ref(tcx, impl_id) {
+ None => {
+ tcx.sess.bug("statically resolved overloaded call impl \
+ didn't implement a trait?!")
+ }
+ Some(ref trait_ref) => (*trait_ref).clone(),
+ };
+ OverloadedCallType::from_trait_id(tcx, trait_ref.def_id)
+ }
+
+ fn from_method_origin(tcx: &ty::ctxt, origin: &MethodOrigin)
+ -> OverloadedCallType {
+ match *origin {
+ MethodStatic(def_id) => {
+ OverloadedCallType::from_method_id(tcx, def_id)
+ }
+ MethodParam(ref method_param) => {
+ OverloadedCallType::from_trait_id(tcx, method_param.trait_id)
+ }
+ MethodObject(ref method_object) => {
+ OverloadedCallType::from_trait_id(tcx, method_object.trait_id)
+ }
+ }
+ }
+}
+
///////////////////////////////////////////////////////////////////////////
// The ExprUseVisitor type
//
}
}
_ => {
- match self.tcx()
- .method_map
- .borrow()
- .find(&MethodCall::expr(call.id)) {
- Some(_) => {
- // FIXME(#14774, pcwalton): Implement this.
+ let overloaded_call_type =
+ match self.tcx()
+ .method_map
+ .borrow()
+ .find(&MethodCall::expr(call.id)) {
+ Some(ref method_callee) => {
+ OverloadedCallType::from_method_origin(
+ self.tcx(),
+ &method_callee.origin)
}
None => {
self.tcx().sess.span_bug(
callee.span,
format!("unexpected callee type {}",
- callee_ty.repr(self.tcx())).as_slice());
+ callee_ty.repr(self.tcx())).as_slice())
+ }
+ };
+ match overloaded_call_type {
+ FnMutOverloadedCall => {
+ self.borrow_expr(callee,
+ ty::ReScope(call.id),
+ ty::MutBorrow,
+ ClosureInvocation);
+ }
+ FnOverloadedCall => {
+ self.borrow_expr(callee,
+ ty::ReScope(call.id),
+ ty::ImmBorrow,
+ ClosureInvocation);
}
+ FnOnceOverloadedCall => self.consume_expr(callee),
}
}
}
fn should_warn(&self, var: Variable) -> Option<String> {
let name = self.ir.variable_name(var);
- if name.len() == 0 || name.as_slice()[0] == ('_' as u8) {
+ if name.len() == 0 || name.as_bytes()[0] == ('_' as u8) {
None
} else {
Some(name)
#[deriving(Clone, PartialEq, Eq, Hash)]
pub enum ElementKind {
VecElement,
- StrElement,
OtherElement,
}
//! - `derefs`: the deref number to be used for
//! the implicit index deref, if any (see above)
- let element_ty = match ty::index(base_cmt.ty) {
+ let element_ty = match ty::array_element_ty(base_cmt.ty) {
Some(ref mt) => mt.ty,
None => {
self.tcx().sess.span_bug(
cat_interior(_, InteriorElement(VecElement)) => {
"vec content".to_string()
}
- cat_interior(_, InteriorElement(StrElement)) => {
- "str content".to_string()
- }
cat_interior(_, InteriorElement(OtherElement)) => {
"indexed content".to_string()
}
ty::ty_rptr(_, ty::mt{ty:ty, ..}) |
ty::ty_uniq(ty) => match ty::get(ty).sty {
ty::ty_vec(_, None) => VecElement,
- ty::ty_str => StrElement,
_ => OtherElement
},
ty::ty_vec(..) => VecElement,
use middle::resolve;
use std::collections::HashMap;
+use std::gc::{Gc, GC};
use syntax::ast::*;
use syntax::ast_util::{path_to_ident, walk_pat};
-use syntax::codemap::Span;
+use syntax::codemap::{Span, DUMMY_SP};
pub type PatIdMap = HashMap<Ident, NodeId>;
}
}
}
+
+pub fn wild() -> Gc<Pat> {
+ box (GC) Pat { id: 0, node: PatWild, span: DUMMY_SP }
+}
}
}
-fn type_is_slice(ty:t) -> bool {
+fn type_is_slice(ty: t) -> bool {
match get(ty).sty {
ty_rptr(_, mt) => match get(mt.ty).sty {
ty_vec(_, None) | ty_str => true,
}
}
+pub fn type_is_vec(ty: t) -> bool {
+ match get(ty).sty {
+ ty_vec(..) => true,
+ ty_ptr(mt{ty: t, ..}) | ty_rptr(_, mt{ty: t, ..}) |
+ ty_box(t) | ty_uniq(t) => match get(t).sty {
+ ty_vec(_, None) => true,
+ _ => false
+ },
+ _ => false
+ }
+}
+
pub fn type_is_structural(ty: t) -> bool {
match get(ty).sty {
ty_struct(..) | ty_tup(_) | ty_enum(..) | ty_closure(_) |
pub fn sequence_element_type(cx: &ctxt, ty: t) -> t {
match get(ty).sty {
- ty_vec(mt, Some(_)) => mt.ty,
+ ty_vec(mt, _) => mt.ty,
ty_ptr(mt{ty: t, ..}) | ty_rptr(_, mt{ty: t, ..}) |
ty_box(t) | ty_uniq(t) => match get(t).sty {
ty_vec(mt, None) => mt.ty,
// Returns the type of t[i]
pub fn index(t: t) -> Option<mt> {
+ match get(t).sty {
+ ty_vec(mt, Some(_)) => Some(mt),
+ ty_ptr(mt{ty: t, ..}) | ty_rptr(_, mt{ty: t, ..}) |
+ ty_box(t) | ty_uniq(t) => match get(t).sty {
+ ty_vec(mt, None) => Some(mt),
+ _ => None,
+ },
+ _ => None
+ }
+}
+
+// Returns the type of elements contained within an 'array-like' type.
+// This is exactly the same as the above, except it supports strings,
+// which can't actually be indexed.
+pub fn array_element_ty(t: t) -> Option<mt> {
match get(t).sty {
ty_vec(mt, Some(_)) => Some(mt),
ty_ptr(mt{ty: t, ..}) | ty_rptr(_, mt{ty: t, ..}) |
.span_err(span,
"cannot cast as `bool`, compare with zero instead");
} else if ty::type_is_region_ptr(t_e) && ty::type_is_unsafe_ptr(t_1) {
- fn is_vec(t: ty::t) -> bool {
- match ty::get(t).sty {
- ty::ty_vec(..) => true,
- ty::ty_ptr(ty::mt{ty: t, ..}) |
- ty::ty_rptr(_, ty::mt{ty: t, ..}) |
- ty::ty_box(t) |
- ty::ty_uniq(t) => {
- match ty::get(t).sty {
- ty::ty_vec(_, None) => true,
- _ => false,
- }
- }
- _ => false
- }
- }
fn types_compatible(fcx: &FnCtxt, sp: Span,
t1: ty::t, t2: ty::t) -> bool {
- if !is_vec(t1) {
+ if !ty::type_is_vec(t1) {
// If the type being casted from is not a vector, this special
// case does not apply.
return false
fcx.write_ty(id, enum_type);
}
+ type ExprCheckerWithTy = fn(&FnCtxt, &ast::Expr, ty::t);
+
+ fn check_fn_for_vec_elements_expected(fcx: &FnCtxt,
+ expected: Expectation)
+ -> (ExprCheckerWithTy, ty::t) {
+ let tcx = fcx.ccx.tcx;
+ let (coerce, t) = match expected {
+ // If we're given an expected type, we can try to coerce to it
+ ExpectHasType(t) if ty::type_is_vec(t) => (true, ty::sequence_element_type(tcx, t)),
+ // Otherwise we just leave the type to be resolved later
+ _ => (false, fcx.infcx().next_ty_var())
+ };
+ if coerce {
+ (check_expr_coercable_to_type, t)
+ } else {
+ (check_expr_has_type, t)
+ }
+ }
+
let tcx = fcx.ccx.tcx;
let id = expr.id;
match expr.node {
ast::ExprVstore(ev, vst) => {
+ let (check, t) = check_fn_for_vec_elements_expected(fcx, expected);
let typ = match ev.node {
ast::ExprVec(ref args) => {
let mutability = match vst {
};
let mut any_error = false;
let mut any_bot = false;
- let t: ty::t = fcx.infcx().next_ty_var();
for e in args.iter() {
- check_expr_has_type(fcx, &**e, t);
+ check(fcx, &**e, t);
let arg_t = fcx.expr_ty(&**e);
if ty::type_is_error(arg_t) {
any_error = true;
ast::ExprVstoreMutSlice => ast::MutMutable,
_ => ast::MutImmutable,
};
- let t = fcx.infcx().next_ty_var();
- check_expr_has_type(fcx, &**element, t);
+ check(fcx, &**element, t);
let arg_t = fcx.expr_ty(&**element);
if ty::type_is_error(arg_t) {
ty::mk_err()
check_cast(fcx, &**e, &**t, id, expr.span);
}
ast::ExprVec(ref args) => {
- let t: ty::t = fcx.infcx().next_ty_var();
+ let (check, t) = check_fn_for_vec_elements_expected(fcx, expected);
for e in args.iter() {
- check_expr_has_type(fcx, &**e, t);
+ check(fcx, &**e, t);
}
let typ = ty::mk_vec(tcx, ty::mt {ty: t, mutbl: ast::MutImmutable},
Some(args.len()));
ast::ExprRepeat(ref element, ref count_expr) => {
check_expr_has_type(fcx, &**count_expr, ty::mk_uint());
let count = ty::eval_repeat_count(fcx, &**count_expr);
- let t: ty::t = fcx.infcx().next_ty_var();
- check_expr_has_type(fcx, &**element, t);
+ let (check, t) = check_fn_for_vec_elements_expected(fcx, expected);
+ check(fcx, &**element, t);
let element_ty = fcx.expr_ty(&**element);
if ty::type_is_error(element_ty) {
fcx.write_error(id);
}
pub trait RtioUdpSocket : RtioSocket {
- fn recvfrom(&mut self, buf: &mut [u8]) -> IoResult<(uint, SocketAddr)>;
- fn sendto(&mut self, buf: &[u8], dst: SocketAddr) -> IoResult<()>;
+ fn recv_from(&mut self, buf: &mut [u8]) -> IoResult<(uint, SocketAddr)>;
+ fn send_to(&mut self, buf: &[u8], dst: SocketAddr) -> IoResult<()>;
fn join_multicast(&mut self, multi: IpAddr) -> IoResult<()>;
fn leave_multicast(&mut self, multi: IpAddr) -> IoResult<()>;
let listener = UdpWatcher::bind(local_loop(), addr2);
tx.send((listener.unwrap(), addr1));
let mut listener = UdpWatcher::bind(local_loop(), addr1).unwrap();
- listener.sendto([1, 2, 3, 4], addr2).ok().unwrap();
+ listener.send_to([1, 2, 3, 4], addr2).ok().unwrap();
});
let task = pool.task(TaskOpts::new(), proc() {
let (mut watcher, addr) = rx.recv();
let mut buf = [0, ..10];
- assert!(watcher.recvfrom(buf).ok().unwrap() == (4, addr));
+ assert!(watcher.recv_from(buf).ok().unwrap() == (4, addr));
});
pool.spawn_sched().send(sched::TaskFromFriend(task));
}
impl rtio::RtioUdpSocket for UdpWatcher {
- fn recvfrom(&mut self, buf: &mut [u8])
+ fn recv_from(&mut self, buf: &mut [u8])
-> Result<(uint, rtio::SocketAddr), IoError>
{
let loop_ = self.uv_loop();
}
}
- fn sendto(&mut self, buf: &[u8], dst: rtio::SocketAddr) -> Result<(), IoError> {
+ fn send_to(&mut self, buf: &[u8], dst: rtio::SocketAddr) -> Result<(), IoError> {
let m = self.fire_homing_missile();
let loop_ = self.uv_loop();
let guard = try!(self.write_access.grant(m));
Ok(mut w) => {
tx.send(());
let mut buf = [0u8, ..10];
- match w.recvfrom(buf) {
+ match w.recv_from(buf) {
Ok((10, addr)) => assert!(addr == client),
e => fail!("{:?}", e),
}
let mut w = match UdpWatcher::bind(local_loop(), client) {
Ok(w) => w, Err(e) => fail!("{:?}", e)
};
- match w.sendto([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], server) {
+ match w.send_to([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], server) {
Ok(()) => {}, Err(e) => fail!("{:?}", e)
}
}
Ok(mut w) => {
tx.send(());
let mut buf = [0u8, ..10];
- match w.recvfrom(buf) {
+ match w.recv_from(buf) {
Ok((10, addr)) => assert!(addr == client),
e => fail!("{:?}", e),
}
let mut w = match UdpWatcher::bind(local_loop(), client) {
Ok(w) => w, Err(e) => fail!("{:?}", e)
};
- match w.sendto([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], server) {
+ match w.send_to([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], server) {
Ok(()) => {}, Err(e) => fail!("{:?}", e)
}
}
spawn(proc() {
let mut client = UdpWatcher::bind(local_loop(), client_addr).unwrap();
rx.recv();
- assert!(client.sendto([1], server_addr).is_ok());
- assert!(client.sendto([2], server_addr).is_ok());
+ assert!(client.send_to([1], server_addr).is_ok());
+ assert!(client.send_to([2], server_addr).is_ok());
});
let mut server = UdpWatcher::bind(local_loop(), server_addr).unwrap();
tx.send(());
let mut buf1 = [0];
let mut buf2 = [0];
- let (nread1, src1) = server.recvfrom(buf1).ok().unwrap();
- let (nread2, src2) = server.recvfrom(buf2).ok().unwrap();
+ let (nread1, src1) = server.recv_from(buf1).ok().unwrap();
+ let (nread2, src2) = server.recv_from(buf2).ok().unwrap();
assert_eq!(nread1, 1);
assert_eq!(nread2, 1);
assert!(src1 == client_addr);
let mut buf = [1];
while buf[0] == 1 {
// send more data
- assert!(server_out.sendto(msg, client_in_addr).is_ok());
+ assert!(server_out.send_to(msg, client_in_addr).is_ok());
total_bytes_sent += msg.len();
// check if the client has received enough
- let res = server_in.recvfrom(buf);
+ let res = server_in.recv_from(buf);
assert!(res.is_ok());
let (nread, src) = res.ok().unwrap();
assert_eq!(nread, 1);
let mut buf = [0, .. 2048];
while total_bytes_recv < MAX {
// ask for more
- assert!(client_out.sendto([1], server_in_addr).is_ok());
+ assert!(client_out.send_to([1], server_in_addr).is_ok());
// wait for data
- let res = client_in.recvfrom(buf);
+ let res = client_in.recv_from(buf);
assert!(res.is_ok());
let (nread, src) = res.ok().unwrap();
assert!(src == server_out_addr);
}
}
// tell the server we're done
- assert!(client_out.sendto([0], server_in_addr).is_ok());
+ assert!(client_out.send_to([0], server_in_addr).is_ok());
}
#[test]
use default::Default;
use fmt::Show;
use fmt;
-use hash::{Hash, Hasher, sip};
+use hash::{Hash, Hasher, RandomSipHasher};
use iter::{Iterator, FilterMap, Chain, Repeat, Zip, Extendable};
use iter::{range, range_inclusive, FromIterator};
use iter;
use mem::replace;
use num;
use option::{Some, None, Option};
-use rand::Rng;
-use rand;
use result::{Ok, Err};
mod table {
/// }
/// ```
#[deriving(Clone)]
-pub struct HashMap<K, V, H = sip::SipHasher> {
+pub struct HashMap<K, V, H = RandomSipHasher> {
// All hashes are keyed on these values, to prevent hash collision attacks.
hasher: H,
}
-impl<K: Hash + Eq, V> HashMap<K, V, sip::SipHasher> {
+impl<K: Hash + Eq, V> HashMap<K, V, RandomSipHasher> {
/// Create an empty HashMap.
- pub fn new() -> HashMap<K, V, sip::SipHasher> {
+ #[inline]
+ pub fn new() -> HashMap<K, V, RandomSipHasher> {
HashMap::with_capacity(INITIAL_CAPACITY)
}
/// Creates an empty hash map with the given initial capacity.
- pub fn with_capacity(capacity: uint) -> HashMap<K, V, sip::SipHasher> {
- let mut r = rand::task_rng();
- let r0 = r.gen();
- let r1 = r.gen();
- let hasher = sip::SipHasher::new_with_keys(r0, r1);
+ #[inline]
+ pub fn with_capacity(capacity: uint) -> HashMap<K, V, RandomSipHasher> {
+ let hasher = RandomSipHasher::new();
HashMap::with_capacity_and_hasher(capacity, hasher)
}
}
/// Creates an empty hashmap which will use the given hasher to hash keys.
///
/// The creates map has the default initial capacity.
+ #[inline]
pub fn with_hasher(hasher: H) -> HashMap<K, V, H> {
HashMap::with_capacity_and_hasher(INITIAL_CAPACITY, hasher)
}
/// is designed to allow HashMaps to be resistant to attacks that
/// cause many collisions and very poor performance. Setting it
/// manually using this function can expose a DoS attack vector.
+ #[inline]
pub fn with_capacity_and_hasher(capacity: uint, hasher: H) -> HashMap<K, V, H> {
let cap = num::next_power_of_two(max(INITIAL_CAPACITY, capacity));
HashMap {
/// HashMap where the value is (). As with the `HashMap` type, a `HashSet`
/// requires that the elements implement the `Eq` and `Hash` traits.
#[deriving(Clone)]
-pub struct HashSet<T, H = sip::SipHasher> {
+pub struct HashSet<T, H = RandomSipHasher> {
map: HashMap<T, (), H>
}
fn remove(&mut self, value: &T) -> bool { self.map.remove(value) }
}
-impl<T: Hash + Eq> HashSet<T, sip::SipHasher> {
+impl<T: Hash + Eq> HashSet<T, RandomSipHasher> {
/// Create an empty HashSet
- pub fn new() -> HashSet<T, sip::SipHasher> {
+ #[inline]
+ pub fn new() -> HashSet<T, RandomSipHasher> {
HashSet::with_capacity(INITIAL_CAPACITY)
}
/// Create an empty HashSet with space for at least `n` elements in
/// the hash table.
- pub fn with_capacity(capacity: uint) -> HashSet<T, sip::SipHasher> {
+ #[inline]
+ pub fn with_capacity(capacity: uint) -> HashSet<T, RandomSipHasher> {
HashSet { map: HashMap::with_capacity(capacity) }
}
}
/// keys.
///
/// The hash set is also created with the default initial capacity.
+ #[inline]
pub fn with_hasher(hasher: H) -> HashSet<T, H> {
HashSet::with_capacity_and_hasher(INITIAL_CAPACITY, hasher)
}
/// is designed to allow `HashSet`s to be resistant to attacks that
/// cause many collisions and very poor performance. Setting it
/// manually using this function can expose a DoS attack vector.
+ #[inline]
pub fn with_capacity_and_hasher(capacity: uint, hasher: H) -> HashSet<T, H> {
HashSet { map: HashMap::with_capacity_and_hasher(capacity, hasher) }
}
--- /dev/null
+// 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.
+
+/*!
+ * Generic hashing support.
+ *
+ * This module provides a generic way to compute the hash of a value. The
+ * simplest way to make a type hashable is to use `#[deriving(Hash)]`:
+ *
+ * # Example
+ *
+ * ```rust
+ * use std::hash;
+ * use std::hash::Hash;
+ *
+ * #[deriving(Hash)]
+ * struct Person {
+ * id: uint,
+ * name: String,
+ * phone: u64,
+ * }
+ *
+ * let person1 = Person { id: 5, name: "Janet".to_string(), phone: 555_666_7777 };
+ * let person2 = Person { id: 5, name: "Bob".to_string(), phone: 555_666_7777 };
+ *
+ * assert!(hash::hash(&person1) != hash::hash(&person2));
+ * ```
+ *
+ * If you need more control over how a value is hashed, you need to implement
+ * the trait `Hash`:
+ *
+ * ```rust
+ * use std::hash;
+ * use std::hash::Hash;
+ * use std::hash::sip::SipState;
+ *
+ * struct Person {
+ * id: uint,
+ * name: String,
+ * phone: u64,
+ * }
+ *
+ * impl Hash for Person {
+ * fn hash(&self, state: &mut SipState) {
+ * self.id.hash(state);
+ * self.phone.hash(state);
+ * }
+ * }
+ *
+ * let person1 = Person { id: 5, name: "Janet".to_string(), phone: 555_666_7777 };
+ * let person2 = Person { id: 5, name: "Bob".to_string(), phone: 555_666_7777 };
+ *
+ * assert!(hash::hash(&person1) == hash::hash(&person2));
+ * ```
+ */
+
+pub use core_collections::hash::{Hash, Hasher, Writer, hash, sip};
+
+use default::Default;
+use rand::Rng;
+use rand;
+
+/// `RandomSipHasher` computes the SipHash algorithm from a stream of bytes
+/// initialized with random keys.
+#[deriving(Clone)]
+pub struct RandomSipHasher {
+ hasher: sip::SipHasher,
+}
+
+impl RandomSipHasher {
+ /// Construct a new `RandomSipHasher` that is initialized with random keys.
+ #[inline]
+ pub fn new() -> RandomSipHasher {
+ let mut r = rand::task_rng();
+ let r0 = r.gen();
+ let r1 = r.gen();
+ RandomSipHasher {
+ hasher: sip::SipHasher::new_with_keys(r0, r1),
+ }
+ }
+}
+
+impl Hasher<sip::SipState> for RandomSipHasher {
+ #[inline]
+ fn hash<T: Hash<sip::SipState>>(&self, value: &T) -> u64 {
+ self.hasher.hash(value)
+ }
+}
+
+impl Default for RandomSipHasher {
+ #[inline]
+ fn default() -> RandomSipHasher {
+ RandomSipHasher::new()
+ }
+}
let mut cur = [0u8, .. 2];
for f in files {
let stem = f.filestem_str().unwrap();
- let root = stem[0] - ('0' as u8);
- let name = stem[1] - ('0' as u8);
+ let root = stem.as_bytes()[0] - ('0' as u8);
+ let name = stem.as_bytes()[1] - ('0' as u8);
assert!(cur[root as uint] < name);
cur[root as uint] = name;
}
/// };
///
/// let mut buf = [0, ..10];
-/// match socket.recvfrom(buf) {
+/// match socket.recv_from(buf) {
/// Ok((amt, src)) => {
/// // Send a reply to the socket we received data from
/// let buf = buf.mut_slice_to(amt);
/// buf.reverse();
-/// socket.sendto(buf, src);
+/// socket.send_to(buf, src);
/// }
/// Err(e) => println!("couldn't receive a datagram: {}", e)
/// }
/// Receives data from the socket. On success, returns the number of bytes
/// read and the address from whence the data came.
- pub fn recvfrom(&mut self, buf: &mut [u8])
+ pub fn recv_from(&mut self, buf: &mut [u8])
-> IoResult<(uint, SocketAddr)> {
- match self.obj.recvfrom(buf) {
+ match self.obj.recv_from(buf) {
Ok((amt, rtio::SocketAddr { ip, port })) => {
Ok((amt, SocketAddr { ip: super::from_rtio(ip), port: port }))
}
}
}
+ #[allow(missing_doc)]
+ #[deprecated = "renamed to `recv_from`"]
+ pub fn recvfrom(&mut self, buf: &mut [u8])
+ -> IoResult<(uint, SocketAddr)> {
+ self.recv_from(buf)
+ }
+
/// Sends data on the socket to the given address. Returns nothing on
/// success.
- pub fn sendto(&mut self, buf: &[u8], dst: SocketAddr) -> IoResult<()> {
- self.obj.sendto(buf, rtio::SocketAddr {
+ pub fn send_to(&mut self, buf: &[u8], dst: SocketAddr) -> IoResult<()> {
+ self.obj.send_to(buf, rtio::SocketAddr {
ip: super::to_rtio(dst.ip),
port: dst.port,
}).map_err(IoError::from_rtio_error)
}
+ #[allow(missing_doc)]
+ #[deprecated = "renamed to `send_to`"]
+ pub fn sendto(&mut self, buf: &[u8], dst: SocketAddr) -> IoResult<()> {
+ self.send_to(buf, dst)
+ }
+
/// Creates a `UdpStream`, which allows use of the `Reader` and `Writer`
/// traits to receive and send data from the same address. This transfers
/// ownership of the socket to the stream.
fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> {
let peer = self.connected_to;
self.as_socket(|sock| {
- match sock.recvfrom(buf) {
+ match sock.recv_from(buf) {
Ok((_nread, src)) if src != peer => Ok(0),
Ok((nread, _src)) => Ok(nread),
Err(e) => Err(e),
impl Writer for UdpStream {
fn write(&mut self, buf: &[u8]) -> IoResult<()> {
let connected_to = self.connected_to;
- self.as_socket(|sock| sock.sendto(buf, connected_to))
+ self.as_socket(|sock| sock.send_to(buf, connected_to))
}
}
match UdpSocket::bind(client_ip) {
Ok(ref mut client) => {
rx1.recv();
- client.sendto([99], server_ip).unwrap()
+ client.send_to([99], server_ip).unwrap()
}
Err(..) => fail!()
}
Ok(ref mut server) => {
tx1.send(());
let mut buf = [0];
- match server.recvfrom(buf) {
+ match server.recv_from(buf) {
Ok((nread, src)) => {
assert_eq!(nread, 1);
assert_eq!(buf[0], 99);
match UdpSocket::bind(client_ip) {
Ok(ref mut client) => {
rx.recv();
- client.sendto([99], server_ip).unwrap()
+ client.send_to([99], server_ip).unwrap()
}
Err(..) => fail!()
}
Ok(ref mut server) => {
tx.send(());
let mut buf = [0];
- match server.recvfrom(buf) {
+ match server.recv_from(buf) {
Ok((nread, src)) => {
assert_eq!(nread, 1);
assert_eq!(buf[0], 99);
spawn(proc() {
let mut sock2 = sock2;
let mut buf = [0, 0];
- assert_eq!(sock2.recvfrom(buf), Ok((1, addr1)));
+ assert_eq!(sock2.recv_from(buf), Ok((1, addr1)));
assert_eq!(buf[0], 1);
- sock2.sendto([2], addr1).unwrap();
+ sock2.send_to([2], addr1).unwrap();
});
let sock3 = sock1.clone();
spawn(proc() {
let mut sock3 = sock3;
rx1.recv();
- sock3.sendto([1], addr2).unwrap();
+ sock3.send_to([1], addr2).unwrap();
tx2.send(());
});
tx1.send(());
let mut buf = [0, 0];
- assert_eq!(sock1.recvfrom(buf), Ok((1, addr2)));
+ assert_eq!(sock1.recv_from(buf), Ok((1, addr2)));
rx2.recv();
})
spawn(proc() {
let mut sock2 = sock2;
- sock2.sendto([1], addr1).unwrap();
+ sock2.send_to([1], addr1).unwrap();
rx.recv();
- sock2.sendto([2], addr1).unwrap();
+ sock2.send_to([2], addr1).unwrap();
rx.recv();
});
spawn(proc() {
let mut sock3 = sock3;
let mut buf = [0, 0];
- sock3.recvfrom(buf).unwrap();
+ sock3.recv_from(buf).unwrap();
tx2.send(());
done.send(());
});
let mut buf = [0, 0];
- sock1.recvfrom(buf).unwrap();
+ sock1.recv_from(buf).unwrap();
tx1.send(());
rx.recv();
let mut buf = [0, 1];
rx.recv();
- match sock2.recvfrom(buf) {
+ match sock2.recv_from(buf) {
Ok(..) => {}
Err(e) => fail!("failed receive: {}", e),
}
let tx2 = tx.clone();
spawn(proc() {
let mut sock3 = sock3;
- match sock3.sendto([1], addr2) {
+ match sock3.send_to([1], addr2) {
Ok(..) => { let _ = tx2.send_opt(()); }
Err(..) => {}
}
done.send(());
});
- match sock1.sendto([2], addr2) {
+ match sock1.send_to([2], addr2) {
Ok(..) => { let _ = tx.send_opt(()); }
Err(..) => {}
}
serv_rx.recv();
})
- iotest!(fn recvfrom_timeout() {
+ iotest!(fn recv_from_timeout() {
let addr1 = next_test_ip4();
let addr2 = next_test_ip4();
let mut a = UdpSocket::bind(addr1).unwrap();
let (tx2, rx2) = channel();
spawn(proc() {
let mut a = UdpSocket::bind(addr2).unwrap();
- assert_eq!(a.recvfrom([0]), Ok((1, addr1)));
- assert_eq!(a.sendto([0], addr1), Ok(()));
+ assert_eq!(a.recv_from([0]), Ok((1, addr1)));
+ assert_eq!(a.send_to([0], addr1), Ok(()));
rx.recv();
- assert_eq!(a.sendto([0], addr1), Ok(()));
+ assert_eq!(a.send_to([0], addr1), Ok(()));
tx2.send(());
});
// Make sure that reads time out, but writes can continue
a.set_read_timeout(Some(20));
- assert_eq!(a.recvfrom([0]).err().unwrap().kind, TimedOut);
- assert_eq!(a.recvfrom([0]).err().unwrap().kind, TimedOut);
- assert_eq!(a.sendto([0], addr2), Ok(()));
+ assert_eq!(a.recv_from([0]).err().unwrap().kind, TimedOut);
+ assert_eq!(a.recv_from([0]).err().unwrap().kind, TimedOut);
+ assert_eq!(a.send_to([0], addr2), Ok(()));
// Cloned handles should be able to block
let mut a2 = a.clone();
- assert_eq!(a2.recvfrom([0]), Ok((1, addr2)));
+ assert_eq!(a2.recv_from([0]), Ok((1, addr2)));
// Clearing the timeout should allow for receiving
a.set_timeout(None);
tx.send(());
- assert_eq!(a2.recvfrom([0]), Ok((1, addr2)));
+ assert_eq!(a2.recv_from([0]), Ok((1, addr2)));
// Make sure the child didn't die
rx2.recv();
})
- iotest!(fn sendto_timeout() {
+ iotest!(fn send_to_timeout() {
let addr1 = next_test_ip4();
let addr2 = next_test_ip4();
let mut a = UdpSocket::bind(addr1).unwrap();
a.set_write_timeout(Some(1000));
for _ in range(0u, 100) {
- match a.sendto([0, ..4*1024], addr2) {
+ match a.send_to([0, ..4*1024], addr2) {
Ok(()) | Err(IoError { kind: ShortWrite(..), .. }) => {},
Err(IoError { kind: TimedOut, .. }) => break,
Err(e) => fail!("other error: {}", e),
pub use alloc::owned;
pub use alloc::rc;
-pub use core_collections::hash;
pub use core_collections::slice;
pub use core_collections::str;
pub use core_collections::string;
/* Common data structures */
pub mod collections;
+pub mod hash;
/* Tasks and communication */
fn is_vol_abs(path: &str, prefix: Option<PathPrefix>) -> bool {
// assume prefix is Some(DiskPrefix)
let rest = path.slice_from(prefix_len(prefix));
- !rest.is_empty() && rest[0].is_ascii() && is_sep(rest[0] as char)
+ !rest.is_empty() && rest.as_bytes()[0].is_ascii() && is_sep(rest.as_bytes()[0] as char)
}
fn shares_volume(me: &Path, path: &str) -> bool {
// path is assumed to have a prefix of Some(DiskPrefix)
let repr = me.repr.as_slice();
match me.prefix {
- Some(DiskPrefix) => repr[0] == path[0].to_ascii().to_upper().to_byte(),
- Some(VerbatimDiskPrefix) => repr[4] == path[0].to_ascii().to_upper().to_byte(),
+ Some(DiskPrefix) => {
+ repr.as_bytes()[0] == path.as_bytes()[0].to_ascii().to_upper().to_byte()
+ }
+ Some(VerbatimDiskPrefix) => {
+ repr.as_bytes()[4] == path.as_bytes()[0].to_ascii().to_upper().to_byte()
+ }
_ => false
}
}
// if me is "C:" we don't want to add a path separator
match me.prefix {
Some(DiskPrefix) if me.repr.len() == plen => (),
- _ if !(me.repr.len() > plen && me.repr.as_slice()[me.repr.len()-1] == SEP_BYTE) => {
+ _ if !(me.repr.len() > plen && me.repr.as_bytes()[me.repr.len()-1] == SEP_BYTE) => {
s.push_char(SEP);
}
_ => ()
// absolute path, or cwd-relative and self is not same volume
replace_path(self, path, prefix);
}
- None if !path.is_empty() && is_sep_(self.prefix, path[0]) => {
+ None if !path.is_empty() && is_sep_(self.prefix, path.as_bytes()[0]) => {
// volume-relative path
if self.prefix.is_some() {
// truncate self down to the prefix, then append
match self.prefix {
Some(DiskPrefix) => {
let rest = self.repr.as_slice().slice_from(self.prefix_len());
- rest.len() > 0 && rest[0] == SEP_BYTE
+ rest.len() > 0 && rest.as_bytes()[0] == SEP_BYTE
}
Some(_) => true,
None => false
let s = match self.prefix {
Some(_) => {
let plen = self.prefix_len();
- if repr.len() > plen && repr[plen] == SEP_BYTE {
+ if repr.len() > plen && repr.as_bytes()[plen] == SEP_BYTE {
repr.slice_from(plen+1)
} else { repr.slice_from(plen) }
}
- None if repr[0] == SEP_BYTE => repr.slice_from(1),
+ None if repr.as_bytes()[0] == SEP_BYTE => repr.slice_from(1),
None => repr
};
let ret = s.split_terminator(SEP).map(Some);
match (self.prefix, other.prefix) {
(Some(DiskPrefix), Some(VerbatimDiskPrefix)) => {
self.is_absolute() &&
- s_repr[0].to_ascii().eq_ignore_case(o_repr[4].to_ascii())
+ s_repr.as_bytes()[0].to_ascii().eq_ignore_case(o_repr.as_bytes()[4].to_ascii())
}
(Some(VerbatimDiskPrefix), Some(DiskPrefix)) => {
other.is_absolute() &&
- s_repr[4].to_ascii().eq_ignore_case(o_repr[0].to_ascii())
+ s_repr.as_bytes()[4].to_ascii().eq_ignore_case(o_repr.as_bytes()[0].to_ascii())
}
(Some(VerbatimDiskPrefix), Some(VerbatimDiskPrefix)) => {
- s_repr[4].to_ascii().eq_ignore_case(o_repr[4].to_ascii())
+ s_repr.as_bytes()[4].to_ascii().eq_ignore_case(o_repr.as_bytes()[4].to_ascii())
}
(Some(UNCPrefix(_,_)), Some(VerbatimUNCPrefix(_,_))) => {
s_repr.slice(2, self.prefix_len()) == o_repr.slice(8, other.prefix_len())
let mut comps = comps;
match (comps.is_some(),prefix) {
(false, Some(DiskPrefix)) => {
- if s[0] >= 'a' as u8 && s[0] <= 'z' as u8 {
+ if s.as_bytes()[0] >= 'a' as u8 && s.as_bytes()[0] <= 'z' as u8 {
comps = Some(vec![]);
}
}
(false, Some(VerbatimDiskPrefix)) => {
- if s[4] >= 'a' as u8 && s[0] <= 'z' as u8 {
+ if s.as_bytes()[4] >= 'a' as u8 && s.as_bytes()[0] <= 'z' as u8 {
comps = Some(vec![]);
}
}
let mut s = String::with_capacity(n);
match prefix {
Some(DiskPrefix) => {
- s.push_char(prefix_[0].to_ascii().to_upper().to_char());
+ s.push_char(prefix_.as_bytes()[0].to_ascii().to_upper().to_char());
s.push_char(':');
}
Some(VerbatimDiskPrefix) => {
s.push_str(prefix_.slice_to(4));
- s.push_char(prefix_[4].to_ascii().to_upper().to_char());
+ s.push_char(prefix_.as_bytes()[4].to_ascii().to_upper().to_char());
s.push_str(prefix_.slice_from(5));
}
Some(UNCPrefix(a,b)) => {
fn has_nonsemantic_trailing_slash(&self) -> bool {
is_verbatim(self) && self.repr.len() > self.prefix_len()+1 &&
- self.repr.as_slice()[self.repr.len()-1] == SEP_BYTE
+ self.repr.as_bytes()[self.repr.len()-1] == SEP_BYTE
}
fn update_normalized<S: Str>(&mut self, s: S) {
/// but absolute within that volume.
#[inline]
pub fn is_vol_relative(path: &Path) -> bool {
- path.prefix.is_none() && is_sep_byte(&path.repr.as_slice()[0])
+ path.prefix.is_none() && is_sep_byte(&path.repr.as_bytes()[0])
}
/// Returns whether the path is considered "cwd-relative", which means a path
} else {
// \\?\path
let idx = path.find('\\');
- if idx == Some(2) && path[1] == ':' as u8 {
- let c = path[0];
+ if idx == Some(2) && path.as_bytes()[1] == ':' as u8 {
+ let c = path.as_bytes()[0];
if c.is_ascii() && ::char::is_alphabetic(c as char) {
// \\?\C:\ path
return Some(VerbatimDiskPrefix);
}
_ => ()
}
- } else if path.len() > 1 && path[1] == ':' as u8 {
+ } else if path.len() > 1 && path.as_bytes()[1] == ':' as u8 {
// C:
- let c = path[0];
+ let c = path.as_bytes()[0];
if c.is_ascii() && ::char::is_alphabetic(c as char) {
return Some(DiskPrefix);
}
*/
#![allow(missing_doc)]
+#![deprecated = "This type is replaced by having a pair of channels. This type \
+ is not fully composable with other channels in terms of \
+ or possible semantics on a duplex stream. It will be removed \
+ soon"]
use core::prelude::*;
/// The receiving-half of Rust's channel type. This half can only be owned by
/// one task
+#[unstable]
pub struct Receiver<T> {
inner: Unsafe<Flavor<T>>,
receives: Cell<uint>,
/// An iterator over messages on a receiver, this iterator will block
/// whenever `next` is called, waiting for a new message, and `None` will be
/// returned when the corresponding channel has hung up.
+#[unstable]
pub struct Messages<'a, T> {
rx: &'a Receiver<T>
}
/// The sending-half of Rust's asynchronous channel type. This half can only be
/// owned by one task, but it can be cloned to send to other tasks.
+#[unstable]
pub struct Sender<T> {
inner: Unsafe<Flavor<T>>,
sends: Cell<uint>,
/// The sending-half of Rust's synchronous channel type. This half can only be
/// owned by one task, but it can be cloned to send to other tasks.
+#[unstable = "this type may be renamed, but it will always exist"]
pub struct SyncSender<T> {
inner: Arc<Unsafe<sync::Packet<T>>>,
// can't share in an arc
/// This enumeration is the list of the possible reasons that try_recv could not
/// return data when called.
#[deriving(PartialEq, Clone, Show)]
+#[experimental = "this is likely to be removed in changing try_recv()"]
pub enum TryRecvError {
/// This channel is currently empty, but the sender(s) have not yet
/// disconnected, so data may yet become available.
/// This enumeration is the list of the possible error outcomes for the
/// `SyncSender::try_send` method.
#[deriving(PartialEq, Clone, Show)]
+#[experimental = "this is likely to be removed in changing try_send()"]
pub enum TrySendError<T> {
/// The data could not be sent on the channel because it would require that
/// the callee block to send the data.
/// // Let's see what that answer was
/// println!("{}", rx.recv());
/// ```
+#[unstable]
pub fn channel<T: Send>() -> (Sender<T>, Receiver<T>) {
let a = Arc::new(Unsafe::new(oneshot::Packet::new()));
(Sender::new(Oneshot(a.clone())), Receiver::new(Oneshot(a)))
/// assert_eq!(rx.recv(), 1i);
/// assert_eq!(rx.recv(), 2i);
/// ```
+#[unstable = "this function may be renamed to more accurately reflect the type \
+ of channel that is is creating"]
pub fn sync_channel<T: Send>(bound: uint) -> (SyncSender<T>, Receiver<T>) {
let a = Arc::new(Unsafe::new(sync::Packet::new(bound)));
(SyncSender::new(a.clone()), Receiver::new(Sync(a)))
///
/// The purpose of this functionality is to propagate failure among tasks.
/// If failure is not desired, then consider using the `send_opt` method
+ #[experimental = "this function is being considered candidate for removal \
+ to adhere to the general guidelines of rust"]
pub fn send(&self, t: T) {
if self.send_opt(t).is_err() {
fail!("sending on a closed channel");
/// drop(rx);
/// assert_eq!(tx.send_opt(1i), Err(1));
/// ```
+ #[unstable = "this function may be renamed to send() in the future"]
pub fn send_opt(&self, t: T) -> Result<(), T> {
// In order to prevent starvation of other tasks in situations where
// a task sends repeatedly without ever receiving, we occasionally
}
}
+#[unstable]
impl<T: Send> Clone for Sender<T> {
fn clone(&self) -> Sender<T> {
let (packet, sleeper) = match *unsafe { self.inner() } {
/// If failure is not desired, you can achieve the same semantics with the
/// `SyncSender::send_opt` method which will not fail if the receiver
/// disconnects.
+ #[experimental = "this function is being considered candidate for removal \
+ to adhere to the general guidelines of rust"]
pub fn send(&self, t: T) {
if self.send_opt(t).is_err() {
fail!("sending on a closed channel");
/// # Failure
///
/// This function cannot fail.
+ #[unstable = "this function may be renamed to send() in the future"]
pub fn send_opt(&self, t: T) -> Result<(), T> {
unsafe { (*self.inner.get()).send(t) }
}
/// # Failure
///
/// This function cannot fail
+ #[unstable = "the return type of this function is candidate for \
+ modification"]
pub fn try_send(&self, t: T) -> Result<(), TrySendError<T>> {
unsafe { (*self.inner.get()).try_send(t) }
}
}
+#[unstable]
impl<T: Send> Clone for SyncSender<T> {
fn clone(&self) -> SyncSender<T> {
unsafe { (*self.inner.get()).clone_chan(); }
///
/// * If blocking is not desired, then the `try_recv` method will attempt to
/// peek at a value on this receiver.
+ #[experimental = "this function is being considered candidate for removal \
+ to adhere to the general guidelines of rust"]
pub fn recv(&self) -> T {
match self.recv_opt() {
Ok(t) => t,
/// block on a receiver.
///
/// This function cannot fail.
+ #[unstable = "the return type of this function may be altered"]
pub fn try_recv(&self) -> Result<T, TryRecvError> {
// If a thread is spinning in try_recv, we should take the opportunity
// to reschedule things occasionally. See notes above in scheduling on
///
/// If the channel has hung up, then `Err` is returned. Otherwise `Ok` of
/// the value found on the receiver is returned.
+ #[unstable = "this function may be renamed to recv()"]
pub fn recv_opt(&self) -> Result<T, ()> {
loop {
let new_port = match *unsafe { self.inner() } {
/// Returns an iterator which will block waiting for messages, but never
/// `fail!`. It will return `None` when the channel has hung up.
+ #[unstable]
pub fn iter<'a>(&'a self) -> Messages<'a, T> {
Messages { rx: self }
}
}
}
+#[unstable]
impl<'a, T: Send> Iterator<T> for Messages<'a, T> {
fn next(&mut self) -> Option<T> { self.rx.recv_opt().ok() }
}
//! ```
#![allow(dead_code)]
+#![experimental = "This implementation, while likely sufficient, is unsafe and \
+ likely to be error prone. At some point in the future this \
+ module will likely be replaced, and it is currently \
+ unknown how much API breakage that will cause. The ability \
+ to select over a number of channels will remain forever, \
+ but no guarantees beyond this are being made"]
+
use core::prelude::*;
}
let orig = fm.get_line(*lines.lines.get(0) as int);
for pos in range(0u, left-skip) {
- let cur_char = orig.as_slice()[pos] as char;
+ let cur_char = orig.as_bytes()[pos] as char;
// Whenever a tab occurs on the previous line, we insert one on
// the error-point-squiggly-line as well (instead of a space).
// That way the squiggly line will usually appear in the correct
fn read_one_line_comment(&mut self) -> String {
let val = self.read_to_eol();
- assert!((val.as_slice()[0] == '/' as u8 && val.as_slice()[1] == '/' as u8)
- || (val.as_slice()[0] == '#' as u8 && val.as_slice()[1] == '!' as u8));
+ assert!((val.as_bytes()[0] == '/' as u8 && val.as_bytes()[1] == '/' as u8)
+ || (val.as_bytes()[0] == '#' as u8 && val.as_bytes()[1] == '!' as u8));
return val;
}
fn match_str(s: &str, pos: uint, needle: &str) -> bool {
let mut i = pos;
for ch in needle.bytes() {
- if s[i] != ch {
+ if s.as_bytes()[i] != ch {
return false;
}
i += 1u;
let mut s: Vec<u8> = Vec::from_elem(32, 0u8);
for i in range(0u, 16u) {
let digit = format!("{:02x}", self.bytes[i] as uint);
- *s.get_mut(i*2+0) = digit.as_slice()[0];
- *s.get_mut(i*2+1) = digit.as_slice()[1];
+ *s.get_mut(i*2+0) = digit.as_bytes()[0];
+ *s.get_mut(i*2+1) = digit.as_bytes()[1];
}
str::from_utf8(s.as_slice()).unwrap().to_string()
}
if line.len() == 0u { continue; }
- match (line.as_slice()[0] as char, proc_mode) {
+ match (line.as_bytes()[0] as char, proc_mode) {
// start processing if this is the one
('>', false) => {
--- /dev/null
+// Copyright 2012 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.
+
+#![feature(overloaded_calls)]
+
+use std::ops::{Fn, FnMut, FnOnce};
+
+struct SFn {
+ x: int,
+ y: int,
+}
+
+impl Fn<(int,),int> for SFn {
+ fn call(&self, (z,): (int,)) -> int {
+ self.x * self.y * z
+ }
+}
+
+struct SFnMut {
+ x: int,
+ y: int,
+}
+
+impl FnMut<(int,),int> for SFnMut {
+ fn call_mut(&mut self, (z,): (int,)) -> int {
+ self.x * self.y * z
+ }
+}
+
+struct SFnOnce {
+ x: String,
+}
+
+impl FnOnce<(String,),uint> for SFnOnce {
+ fn call_once(self, (z,): (String,)) -> uint {
+ self.x.len() + z.len()
+ }
+}
+
+fn f() {
+ let mut s = SFn {
+ x: 1,
+ y: 2,
+ };
+ let sp = &mut s;
+ s(3); //~ ERROR cannot borrow `s` as immutable because it is also borrowed as mutable
+ //~^ ERROR cannot borrow `s` as immutable because it is also borrowed as mutable
+}
+
+fn g() {
+ let s = SFnMut {
+ x: 1,
+ y: 2,
+ };
+ s(3); //~ ERROR cannot borrow immutable local variable `s` as mutable
+}
+
+fn h() {
+ let s = SFnOnce {
+ x: "hello".to_string(),
+ };
+ s(" world".to_string());
+ s(" world".to_string()); //~ ERROR use of moved value: `s`
+}
+
+fn main() {}
+
--- /dev/null
+// Copyright 2012 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.
+
+fn main() {
+ let a = "".to_string();
+ let b: Vec<&str> = a.as_slice().lines().collect();
+ drop(a); //~ ERROR cannot move out of `a` because it is borrowed
+ for s in b.iter() {
+ println!("{}", *s);
+ }
+}
+
--- /dev/null
+// Copyright 2012 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.
+
+fn read_lines_borrowed() -> Vec<&str> {
+ let raw_lines: Vec<String> = vec!("foo ".to_string(), " bar".to_string());
+ raw_lines.iter().map(|l| l.as_slice().trim()).collect()
+ //~^ ERROR `raw_lines` does not live long enough
+}
+
+fn main() {
+ println!("{}", read_lines_borrowed());
+}
assert_eq!(v.as_slice()[3u32], 3); //~ ERROR: mismatched types
assert_eq!(v.as_slice()[3i32], 3); //~ ERROR: mismatched types
println!("{}", v.as_slice()[3u8]); //~ ERROR: mismatched types
- assert_eq!(s.as_slice()[3u], 'd' as u8);
- assert_eq!(s.as_slice()[3u8], 'd' as u8); //~ ERROR: mismatched types
- assert_eq!(s.as_slice()[3i8], 'd' as u8); //~ ERROR: mismatched types
- assert_eq!(s.as_slice()[3u32], 'd' as u8); //~ ERROR: mismatched types
- assert_eq!(s.as_slice()[3i32], 'd' as u8); //~ ERROR: mismatched types
- println!("{}", s.as_slice()[3u8]); //~ ERROR: mismatched types
+ assert_eq!(s.as_bytes()[3u], 'd' as u8);
+ assert_eq!(s.as_bytes()[3u8], 'd' as u8); //~ ERROR: mismatched types
+ assert_eq!(s.as_bytes()[3i8], 'd' as u8); //~ ERROR: mismatched types
+ assert_eq!(s.as_bytes()[3u32], 'd' as u8); //~ ERROR: mismatched types
+ assert_eq!(s.as_bytes()[3i32], 'd' as u8); //~ ERROR: mismatched types
+ println!("{}", s.as_bytes()[3u8]); //~ ERROR: mismatched types
}
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
enum t { a(u), b }
enum u { c, d }
+fn match_nested_vecs<'a, T>(l1: Option<&'a [T]>, l2: Result<&'a [T], ()>) -> &'static str {
+ match (l1, l2) { //~ ERROR non-exhaustive patterns: `(Some([]), Err(_))` not covered
+ (Some([]), Ok([])) => "Some(empty), Ok(empty)",
+ (Some([_, ..]), Ok(_)) | (Some([_, ..]), Err(())) => "Some(non-empty), any",
+ (None, Ok([])) | (None, Err(())) | (None, Ok([_])) => "None, Ok(less than one element)",
+ (None, Ok([_, _, ..])) => "None, Ok(at least two elements)"
+ }
+}
+
fn main() {
- let x = a(c);
- match x { //~ ERROR non-exhaustive patterns: `a(c)` not covered
- a(d) => { fail!("hello"); }
- b => { fail!("goodbye"); }
+ let x = a(c);
+ match x { //~ ERROR non-exhaustive patterns: `a(c)` not covered
+ a(d) => { fail!("hello"); }
+ b => { fail!("goodbye"); }
}
}
--- /dev/null
+// Copyright 2012 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.
+
+extern crate debug;
+
+pub fn main() {
+ let s: &str = "hello";
+ let c: u8 = s[4]; //~ ERROR cannot index a value of type `&str`
+}
let s: String = "hello".to_string();
// Bounds-check failure.
- assert_eq!(s.as_slice()[5], 0x0 as u8);
+ assert_eq!(s.as_bytes()[5], 0x0 as u8);
}
--- /dev/null
+// Copyright 2012 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.
+
+fn main() {
+ let foo = "hello".to_string();
+ let foo: Vec<&str> = foo.as_slice().words().collect();
+ let invalid_string = foo.get(0);
+ assert_eq!(*invalid_string, "hello");
+}
+
--- /dev/null
+// Copyright 2012 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.
+
+fn main() {
+ let args = vec!("foobie", "asdf::asdf");
+ let arr: Vec<&str> = args.get(1).as_slice().split_str("::").collect();
+ assert_eq!(*arr.get(0), "asdf");
+ assert_eq!(*arr.get(0), "asdf");
+}
+
println!("{}", x);
println!("{}", y);
- assert_eq!(x[0], 'h' as u8);
- assert_eq!(x[4], 'o' as u8);
+ assert_eq!(x.as_bytes()[0], 'h' as u8);
+ assert_eq!(x.as_bytes()[4], 'o' as u8);
let z : &str = "thing";
assert_eq!(v, x);
let _y : String = "there".to_string();
let mut z = "thing".to_string();
z = x;
- assert_eq!(z.as_slice()[0], ('h' as u8));
- assert_eq!(z.as_slice()[4], ('o' as u8));
+ assert_eq!(z.as_bytes()[0], ('h' as u8));
+ assert_eq!(z.as_bytes()[4], ('o' as u8));
}
--- /dev/null
+// 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.
+
+#![allow(dead_code)]
+
+trait Foo {}
+impl Foo for int {}
+fn foo(_: [&Foo, ..2]) {}
+fn foos(_: &[&Foo]) {}
+fn foog<T>(_: &[T], _: &[T]) {}
+
+fn bar(_: [Box<Foo>, ..2]) {}
+fn bars(_: &[Box<Foo>]) {}
+
+fn main() {
+ let x: [&Foo, ..2] = [&1i, &2i];
+ foo(x);
+ foo([&1i, &2i]);
+
+ let r = &1i;
+ let x: [&Foo, ..2] = [r, ..2];
+ foo(x);
+ foo([&1i, ..2]);
+
+ let x: &[&Foo] = &[&1i, &2i];
+ foos(x);
+ foos(&[&1i, &2i]);
+
+ let x: &[&Foo] = &[&1i, &2i];
+ let r = &1i;
+ foog(x, &[r]);
+
+ let x: [Box<Foo>, ..2] = [box 1i, box 2i];
+ bar(x);
+ bar([box 1i, box 2i]);
+
+ let x: &[Box<Foo>] = &[box 1i, box 2i];
+ bars(x);
+ bars(&[box 1i, box 2i]);
+
+ let x: &[Box<Foo>] = &[box 1i, box 2i];
+ foog(x, &[box 1i]);
+
+ struct T<'a> {
+ t: [&'a Foo, ..2]
+ }
+ let _n = T {
+ t: [&1i, &2i]
+ };
+ let r = &1i;
+ let _n = T {
+ t: [r, ..2]
+ };
+ let x: [&Foo, ..2] = [&1i, &2i];
+ let _n = T {
+ t: x
+ };
+
+ struct F<'b> {
+ t: &'b [&'b Foo]
+ }
+ let _n = F {
+ t: &[&1i, &2i]
+ };
+ let r = &1i;
+ let r: [&Foo, ..2] = [r, ..2];
+ let _n = F {
+ t: r
+ };
+ let x: [&Foo, ..2] = [&1i, &2i];
+ let _n = F {
+ t: x
+ };
+
+ struct M<'a> {
+ t: &'a [Box<Foo>]
+ }
+ let _n = M {
+ t: &[box 1i, box 2i]
+ };
+ let x: [Box<Foo>, ..2] = [box 1i, box 2i];
+ let _n = M {
+ t: x
+ };
+}
--- /dev/null
+// 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.
+
+fn main() {
+ assert_eq!(count_members(&[1, 2, 3, 4]), 4);
+}
+
+fn count_members(v: &[uint]) -> uint {
+ match v {
+ [] => 0,
+ [_] => 1,
+ [_x, ..xs] => 1 + count_members(xs)
+ }
+}
--- /dev/null
+// 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.
+
+fn match_vecs<'a, T>(l1: &'a [T], l2: &'a [T]) -> &'static str {
+ match (l1, l2) {
+ ([], []) => "both empty",
+ ([], [..]) | ([..], []) => "one empty",
+ ([..], [..]) => "both non-empty"
+ }
+}
+
+fn match_vecs_cons<'a, T>(l1: &'a [T], l2: &'a [T]) -> &'static str {
+ match (l1, l2) {
+ ([], []) => "both empty",
+ ([], [_, ..]) | ([_, ..], []) => "one empty",
+ ([_, ..], [_, ..]) => "both non-empty"
+ }
+}
+
+fn match_vecs_snoc<'a, T>(l1: &'a [T], l2: &'a [T]) -> &'static str {
+ match (l1, l2) {
+ ([], []) => "both empty",
+ ([], [.., _]) | ([.., _], []) => "one empty",
+ ([.., _], [.., _]) => "both non-empty"
+ }
+}
+
+fn match_nested_vecs_cons<'a, T>(l1: Option<&'a [T]>, l2: Result<&'a [T], ()>) -> &'static str {
+ match (l1, l2) {
+ (Some([]), Ok([])) => "Some(empty), Ok(empty)",
+ (Some([_, ..]), Ok(_)) | (Some([_, ..]), Err(())) => "Some(non-empty), any",
+ (None, Ok([])) | (None, Err(())) | (None, Ok([_])) => "None, Ok(less than one element)",
+ (None, Ok([_, _, ..])) => "None, Ok(at least two elements)",
+ _ => "other"
+ }
+}
+
+fn match_nested_vecs_snoc<'a, T>(l1: Option<&'a [T]>, l2: Result<&'a [T], ()>) -> &'static str {
+ match (l1, l2) {
+ (Some([]), Ok([])) => "Some(empty), Ok(empty)",
+ (Some([.., _]), Ok(_)) | (Some([.., _]), Err(())) => "Some(non-empty), any",
+ (None, Ok([])) | (None, Err(())) | (None, Ok([_])) => "None, Ok(less than one element)",
+ (None, Ok([.., _, _])) => "None, Ok(at least two elements)",
+ _ => "other"
+ }
+}
+
+fn main() {
+ assert_eq!(match_vecs(&[1i, 2], &[2i, 3]), "both non-empty");
+ assert_eq!(match_vecs(&[], &[1i, 2, 3, 4]), "one empty");
+ assert_eq!(match_vecs::<uint>(&[], &[]), "both empty");
+ assert_eq!(match_vecs(&[1i, 2, 3], &[]), "one empty");
+
+ assert_eq!(match_vecs_cons(&[1i, 2], &[2i, 3]), "both non-empty");
+ assert_eq!(match_vecs_cons(&[], &[1i, 2, 3, 4]), "one empty");
+ assert_eq!(match_vecs_cons::<uint>(&[], &[]), "both empty");
+ assert_eq!(match_vecs_cons(&[1i, 2, 3], &[]), "one empty");
+
+ assert_eq!(match_vecs_snoc(&[1i, 2], &[2i, 3]), "both non-empty");
+ assert_eq!(match_vecs_snoc(&[], &[1i, 2, 3, 4]), "one empty");
+ assert_eq!(match_vecs_snoc::<uint>(&[], &[]), "both empty");
+ assert_eq!(match_vecs_snoc(&[1i, 2, 3], &[]), "one empty");
+
+ assert_eq!(match_nested_vecs_cons(None, Ok(&[4u, 2u])), "None, Ok(at least two elements)");
+ assert_eq!(match_nested_vecs_cons::<uint>(None, Err(())), "None, Ok(less than one element)");
+ assert_eq!(match_nested_vecs_cons::<bool>(Some(&[]), Ok(&[])), "Some(empty), Ok(empty)");
+ assert_eq!(match_nested_vecs_cons(Some(&[1i]), Err(())), "Some(non-empty), any");
+ assert_eq!(match_nested_vecs_cons(Some(&[(42i, ())]), Ok(&[(1i, ())])), "Some(non-empty), any");
+
+ assert_eq!(match_nested_vecs_snoc(None, Ok(&[4u, 2u])), "None, Ok(at least two elements)");
+ assert_eq!(match_nested_vecs_snoc::<uint>(None, Err(())), "None, Ok(less than one element)");
+ assert_eq!(match_nested_vecs_snoc::<bool>(Some(&[]), Ok(&[])), "Some(empty), Ok(empty)");
+ assert_eq!(match_nested_vecs_snoc(Some(&[1i]), Err(())), "Some(non-empty), any");
+ assert_eq!(match_nested_vecs_snoc(Some(&[(42i, ())]), Ok(&[(1i, ())])), "Some(non-empty), any");
+}
let b: String = "world".to_string();
let s: String = format!("{}{}", a, b);
println!("{}", s.clone());
- assert_eq!(s.as_slice()[9], 'd' as u8);
+ assert_eq!(s.as_bytes()[9], 'd' as u8);
}
+++ /dev/null
-// Copyright 2012 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.
-
-extern crate debug;
-
-pub fn main() {
- let s = "hello".to_string();
- let c: u8 = s.as_slice()[4];
- println!("{:?}", c);
- assert_eq!(c, 0x6f as u8);
-}
let s0 = "test".to_string();
tx.send(s0);
let s1 = rx.recv();
- assert_eq!(s1.as_slice()[0], 't' as u8);
- assert_eq!(s1.as_slice()[1], 'e' as u8);
- assert_eq!(s1.as_slice()[2], 's' as u8);
- assert_eq!(s1.as_slice()[3], 't' as u8);
+ assert_eq!(s1.as_bytes()[0], 't' as u8);
+ assert_eq!(s1.as_bytes()[1], 'e' as u8);
+ assert_eq!(s1.as_bytes()[2], 's' as u8);
+ assert_eq!(s1.as_bytes()[3], 't' as u8);
}
#[deriving(Show)]
fn check_names(arc: Arc<Vec<Box<Pet+Share+Send>>>) {
for pet in arc.iter() {
pet.name(|name| {
- assert!(name[0] == 'a' as u8 && name[1] == 'l' as u8);
+ assert!(name.as_bytes()[0] == 'a' as u8 && name.as_bytes()[1] == 'l' as u8);
})
}
}
for ab in a.as_slice().bytes() {
println!("{}", i);
println!("{}", ab);
- let bb: u8 = b.as_slice()[i as uint];
+ let bb: u8 = b.as_bytes()[i as uint];
println!("{}", bb);
assert_eq!(ab, bb);
i += 1;