]> git.lizzy.rs Git - rust.git/commitdiff
auto merge of #15325 : pcwalton/rust/trait-impl-bound-mismatch, r=pnkfelix
authorbors <bors@rust-lang.org>
Thu, 3 Jul 2014 01:06:38 +0000 (01:06 +0000)
committerbors <bors@rust-lang.org>
Thu, 3 Jul 2014 01:06:38 +0000 (01:06 +0000)
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

56 files changed:
.travis.yml
AUTHORS.txt
RELEASES.txt
src/doc/guide-tasks.md
src/doc/guide.md
src/libcollections/str.rs
src/libcollections/string.rs
src/libcore/str.rs
src/libgetopts/lib.rs
src/libnative/io/net.rs
src/librustc/back/link.rs
src/librustc/metadata/decoder.rs
src/librustc/middle/check_match.rs
src/librustc/middle/dead.rs
src/librustc/middle/expr_use_visitor.rs
src/librustc/middle/liveness.rs
src/librustc/middle/mem_categorization.rs
src/librustc/middle/pat_util.rs
src/librustc/middle/ty.rs
src/librustc/middle/typeck/check/mod.rs
src/librustrt/rtio.rs
src/librustuv/homing.rs
src/librustuv/net.rs
src/libstd/collections/hashmap.rs
src/libstd/hash.rs [new file with mode: 0644]
src/libstd/io/fs.rs
src/libstd/io/net/udp.rs
src/libstd/lib.rs
src/libstd/path/windows.rs
src/libsync/comm/duplex.rs
src/libsync/comm/mod.rs
src/libsync/comm/select.rs
src/libsyntax/diagnostic.rs
src/libsyntax/parse/lexer/mod.rs
src/libtime/lib.rs
src/libuuid/lib.rs
src/test/bench/shootout-k-nucleotide-pipes.rs
src/test/compile-fail/borrowck-overloaded-call.rs [new file with mode: 0644]
src/test/compile-fail/drop-with-active-borrows-1.rs [new file with mode: 0644]
src/test/compile-fail/drop-with-active-borrows-2.rs [new file with mode: 0644]
src/test/compile-fail/integral-indexing.rs
src/test/compile-fail/non-exhaustive-match-nested.rs
src/test/compile-fail/str-idx.rs [new file with mode: 0644]
src/test/run-fail/str-overrun.rs
src/test/run-pass/drop-with-type-ascription-1.rs [new file with mode: 0644]
src/test/run-pass/drop-with-type-ascription-2.rs [new file with mode: 0644]
src/test/run-pass/estr-slice.rs
src/test/run-pass/estr-uniq.rs
src/test/run-pass/issue-11205.rs [new file with mode: 0644]
src/test/run-pass/issue-15104.rs [new file with mode: 0644]
src/test/run-pass/match-vec-alternatives.rs [new file with mode: 0644]
src/test/run-pass/str-concat.rs
src/test/run-pass/str-idx.rs [deleted file]
src/test/run-pass/task-comm-16.rs
src/test/run-pass/trait-bounds-in-arc.rs
src/test/run-pass/utf8.rs

index e3cec33ad070d340397e66e7e6a2f6295f3da90a..dd62defa02039ad5934b688d94fe07980706b4df 100644 (file)
@@ -41,7 +41,7 @@ script: |
     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:
index c69cb06bd1803ae5419fe5ed892def0c5b9836d4..ab4f234cc99b1f5249e5eb50b5316df2dc9f65a9 100644 (file)
@@ -1,19 +1,25 @@
 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>
@@ -24,9 +30,12 @@ Andreas Ots <andreasots@gmail.com>
 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>
@@ -34,14 +43,13 @@ Austin King <shout@ozten.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>
@@ -52,13 +60,15 @@ Bill Myers <bill_myers@outlook.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>
@@ -69,23 +79,27 @@ Bryan Dunsmore <dunsmoreb@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>
@@ -102,7 +116,6 @@ Daniel Patterson <dbp@riseup.net>
 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>
@@ -118,14 +131,15 @@ Derek Guenther <dguenther9@gmail.com>
 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>
@@ -133,45 +147,45 @@ Eduard Burtescu <edy.burt@gmail.com>
 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>
@@ -180,13 +194,16 @@ Graydon Hoare <graydon@mozilla.com>
 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>
@@ -195,17 +212,23 @@ Ilyong Cho <ilyoan@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>
@@ -215,75 +238,80 @@ Jason Orendorff <jorendorff@mozilla.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>
@@ -305,37 +333,47 @@ Matthijs Hofstra <thiezz@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>
@@ -343,13 +381,16 @@ Paul Collins <paul@ondioline.org>
 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>
@@ -357,15 +398,20 @@ Rafael Ávila de Espíndola <respindola@mozilla.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>
@@ -373,49 +419,61 @@ Robert Millar <robert.millar@cantab.net>
 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>
@@ -424,11 +482,16 @@ Tony Young <tony@rfw.name>
 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>
@@ -437,17 +500,62 @@ Vivek Galatage <vivekgalatage@gmail.com>
 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>
index ee437b658e1a3071f25bf333e97715cd373c05fa..457328b2c90ca32ab54991f0ff1c21516a6e697c 100644 (file)
@@ -1,3 +1,135 @@
+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)
 -------------------------
 
index 81d7f37d6fbcc45c796900d41a45e51ad894c1f9..9021b761954d05dfd8212e52972c41132dc8d58c 100644 (file)
@@ -457,6 +457,8 @@ the string in response.  The child terminates when it receives `0`.
 Here is the function that implements the child task:
 
 ~~~
+#![allow(deprecated)]
+
 use std::comm::DuplexStream;
 # fn main() {
 fn stringifier(channel: &DuplexStream<String, uint>) {
@@ -481,6 +483,8 @@ response itself is simply the stringified version of the received value,
 Here is the code for the parent task:
 
 ~~~
+#![allow(deprecated)]
+
 use std::comm::duplex;
 # use std::task::spawn;
 # use std::comm::DuplexStream;
index 4577c5a86d77582d18c8f9bf19e243d1a6ddb439..0fc9671c4db292c4bcc05baa38eea38c1a52c261 100644 (file)
@@ -413,23 +413,209 @@ rest of your Rust career.
 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
 
@@ -451,10 +637,35 @@ loop
 
 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
index aa2b38cfa9ddc5543a3f17f5f5b15ebfe25e80f5..fd8ce11d0b5a4bfdfc0256a830edff57445a8229 100644 (file)
@@ -1569,8 +1569,8 @@ fn vec_str_conversions() {
         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);
index 6d1fc43a4f1fd2d1e4b44799bbaa132ea6fd7c42..936e60388a66ae8223cca470b4f837d626399bfc 100644 (file)
@@ -222,7 +222,7 @@ pub unsafe fn pop_byte(&mut self) -> Option<u8> {
             return None
         }
 
-        let byte = self.as_slice()[len - 1];
+        let byte = self.as_bytes()[len - 1];
         self.vec.set_len(len - 1);
         Some(byte)
     }
index b336c57efa07228ad8d6d54518b3e6af46904079..94df7a5a6c2d9c7548a089e8e949fbc32936f226 100644 (file)
@@ -1743,7 +1743,7 @@ fn lines(&self) -> CharSplits<'a, char> {
     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 }
         })
     }
@@ -1867,26 +1867,26 @@ fn trim_right_chars<C: CharEq>(&self, mut to_trim: C) -> &'a str {
     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};
         }
@@ -1899,23 +1899,25 @@ fn char_range_at_reverse(&self, start: uint) -> CharRange {
         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};
         }
index 240f5c007fa24290f372e87e451bac1796cb9bfe..0e525bc46e7c8b124226b32c65210d6ed3f4afca 100644 (file)
@@ -370,7 +370,7 @@ pub fn opt_default(&self, nm: &str, def: &str) -> Option<String> {
 }
 
 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> {
@@ -553,7 +553,7 @@ pub fn getopts(args: &[String], optgrps: &[OptGroup]) -> Result {
         } 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 {
index 395c063e706f11d8494d11fa36901ebd2815f9a6..dfc2c55cde7cb511bb79303ed6942d7b69f1572f 100644 (file)
@@ -630,7 +630,7 @@ fn socket_name(&mut self) -> IoResult<rtio::SocketAddr> {
 #[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;
@@ -652,7 +652,7 @@ fn recvfrom(&mut self, buf: &mut [u8]) -> IoResult<(uint, rtio::SocketAddr)> {
         })
     }
 
-    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;
index b4af291b7eae67ae4275bf7fba70449fb6decde7..17f29639601dd72455e0e7e38202970df8f3a298 100644 (file)
@@ -657,8 +657,8 @@ pub fn sanitize(s: &str) -> String {
 
     // 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());
     }
 
@@ -737,9 +737,9 @@ pub fn mangle_exported_name(ccx: &CrateContext, path: PathElems,
     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(),
index f5ce8cda8c4a6d1b35f00a77c4304701a74e263e..78a29b52bdf5bc45974f05b5adf5bfe4ffc7d88b 100644 (file)
@@ -181,7 +181,7 @@ fn item_sized(item: ebml::Doc) -> ast::Sized {
 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
@@ -757,13 +757,13 @@ fn get_mutability(ch: u8) -> ast::Mutability {
     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)
     }
 }
index 27b826b9d1aa00ac1dc3705c63ba7bb7fb33e0a9..1400e207ab1a8615f73416d3fd7a7227bea279a1 100644 (file)
@@ -8,17 +8,16 @@
 // 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 {
@@ -50,22 +113,6 @@ fn useful(self) -> Option<Vec<Gc<Pat>>> {
     }
 }
 
-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);
@@ -78,11 +125,8 @@ fn visit_fn(&mut self, fk: &FnKind, fd: &FnDecl, b: &Block, s: Span, _: NodeId,
     }
 }
 
-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, ());
 
@@ -116,12 +160,12 @@ fn check_expr(cx: &mut MatchCheckCtxt, ex: &Expr) {
                // 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);
         },
         _ => ()
@@ -130,7 +174,7 @@ fn check_expr(cx: &mut MatchCheckCtxt, ex: &Expr) {
 
 // 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)
@@ -161,7 +205,11 @@ fn check_arms(cx: &MatchCheckCtxt, arms: &[Arm]) {
                 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);
+            }
         }
     }
 }
@@ -175,10 +223,6 @@ fn raw_pat(p: Gc<Pat>) -> Gc<Pat> {
 
 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,
@@ -188,38 +232,58 @@ fn check_exhaustive(cx: &MatchCheckCtxt, sp: Span, m: &Matrix) {
             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)
             };
@@ -235,103 +299,95 @@ fn construct_witness(cx: &MatchCheckCtxt, ctor: &ctor, pats: Vec<Gc<Pat>>, lty:
             } 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)
     }
 }
 
@@ -348,15 +404,16 @@ fn vec_constructors(m: &Matrix) -> Vec<ctor> {
 
 // 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
@@ -374,10 +431,16 @@ fn is_useful(cx: &MatchCheckCtxt, m: &Matrix, v: &[Gc<Pat>],
         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 {
@@ -400,14 +463,15 @@ fn is_useful(cx: &MatchCheckCtxt, m: &Matrix, v: &[Gc<Pat>],
                 }).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!()
@@ -415,64 +479,82 @@ fn is_useful(cx: &MatchCheckCtxt, m: &Matrix, v: &[Gc<Pat>],
                     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")
     }
@@ -482,53 +564,53 @@ fn is_wild(cx: &MatchCheckCtxt, p: Gc<Pat>) -> bool {
     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);
@@ -538,22 +620,30 @@ fn range_covered_by_constructor(ctor_id: &ctor, from: &const_val, to: &const_val
     }
 }
 
+/// 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
@@ -561,11 +651,11 @@ fn specialize(cx: &MatchCheckCtxt, r: &[Gc<Pat>],
                 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
                         }
                     }
@@ -575,22 +665,23 @@ fn specialize(cx: &MatchCheckCtxt, r: &[Gc<Pat>],
                 }
             }
         }
+
         &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(),
@@ -603,9 +694,9 @@ fn specialize(cx: &MatchCheckCtxt, r: &[Gc<Pat>],
 
         &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
@@ -633,11 +724,11 @@ fn specialize(cx: &MatchCheckCtxt, r: &[Gc<Pat>],
 
         &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
                 }
             }
@@ -646,41 +737,42 @@ fn specialize(cx: &MatchCheckCtxt, r: &[Gc<Pat>],
         &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
         }
     };
@@ -740,7 +832,7 @@ fn check_fn(cx: &mut MatchCheckCtxt,
 }
 
 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| {
index 156b8840067720b29fe8b29112d19e304fb24098..e7457f370d9adea16253276cb4fa5bc0b9224758 100644 (file)
@@ -399,7 +399,7 @@ struct DeadVisitor<'a> {
 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);
index 3e72341ebb02fa37db26279e186f9eff122d6400..1e06b3b1fd46393a0434ddd09230667307c76c01 100644 (file)
 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
@@ -101,6 +102,74 @@ pub enum MutateMode {
     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
 //
@@ -413,19 +482,37 @@ fn walk_callee(&mut self, call: &ast::Expr, callee: &ast::Expr) {
                 }
             }
             _ => {
-                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),
                 }
             }
         }
index 77cb5f667fd000c9b7fbe57655718d4181ea901c..5c09466cd96820bdfb686760caf70ba973302ba7 100644 (file)
@@ -1511,7 +1511,7 @@ fn check_lvalue(&mut self, expr: &Expr) {
 
     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)
index d26ccc40d3ac11d9421b9a37e0ce7b500e74d961..e1a2a5741fbe1b0d0e03ba62c41dd7666e647f6e 100644 (file)
@@ -126,7 +126,6 @@ pub enum FieldName {
 #[deriving(Clone, PartialEq, Eq, Hash)]
 pub enum ElementKind {
     VecElement,
-    StrElement,
     OtherElement,
 }
 
@@ -794,7 +793,7 @@ pub fn cat_index<N:ast_node>(&self,
         //! - `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(
@@ -1137,9 +1136,6 @@ pub fn cmt_to_str(&self, cmt: &cmt_) -> String {
           cat_interior(_, InteriorElement(VecElement)) => {
               "vec content".to_string()
           }
-          cat_interior(_, InteriorElement(StrElement)) => {
-              "str content".to_string()
-          }
           cat_interior(_, InteriorElement(OtherElement)) => {
               "indexed content".to_string()
           }
@@ -1320,7 +1316,6 @@ fn element_kind(t: ty::t) -> ElementKind {
         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,
index 44ed0192d1d27601d809613ca6d7967db6ec615c..24d97f5aac354212171f61b1110cae7506c0fb96 100644 (file)
 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>;
 
@@ -111,3 +112,7 @@ pub fn simple_identifier<'a>(pat: &'a Pat) -> Option<&'a Path> {
         }
     }
 }
+
+pub fn wild() -> Gc<Pat> {
+    box (GC) Pat { id: 0, node: PatWild, span: DUMMY_SP }
+}
index 8d84d089c01b2adff75514cf313a74df9196d7b6..79630be7c5e0840c21dfdf99228ed5bbede7f7ac 100644 (file)
@@ -1533,7 +1533,7 @@ pub fn type_is_self(ty: t) -> bool {
     }
 }
 
-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,
@@ -1543,6 +1543,18 @@ fn type_is_slice(ty:t) -> bool {
     }
 }
 
+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(_) |
@@ -1560,7 +1572,7 @@ pub fn type_is_simd(cx: &ctxt, ty: t) -> bool {
 
 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,
@@ -2551,6 +2563,21 @@ pub fn deref(t: t, explicit: bool) -> Option<mt> {
 
 // 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, ..}) |
index 0cef67ec2e55751a3b800ec984940369b5a28a19..f5e34e9307764944b73ff9457acb678b2970fa36 100644 (file)
@@ -1167,24 +1167,9 @@ fn check_cast(fcx: &FnCtxt,
            .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
@@ -2800,10 +2785,30 @@ fn check_struct_enum_variant(fcx: &FnCtxt,
         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 {
@@ -2812,9 +2817,8 @@ fn check_struct_enum_variant(fcx: &FnCtxt,
                     };
                     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;
@@ -2842,8 +2846,7 @@ fn check_struct_enum_variant(fcx: &FnCtxt,
                         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()
@@ -3232,9 +3235,9 @@ fn check_struct_enum_variant(fcx: &FnCtxt,
         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()));
@@ -3243,8 +3246,8 @@ fn check_struct_enum_variant(fcx: &FnCtxt,
       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);
index a68d453b77d89e48011f826e883dfcc0e6e5abd8..0205f2405f9ce8e1345f214a103e39fad5cde3b3 100644 (file)
@@ -269,8 +269,8 @@ pub trait RtioSocket {
 }
 
 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<()>;
index 644ac4e45f6569e62ee82b890fd0f23d3898e5a0..91614763ce52f4ed669fe0a7c25dd367ef0f2451 100644 (file)
@@ -197,13 +197,13 @@ fn test_homing_read() {
             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));
 
index edecb8475e9d136b285d31481d224784086899a8..ddcaeccbc190f9927235259a31b0f3fddba16032 100644 (file)
@@ -540,7 +540,7 @@ fn socket_name(&mut self) -> Result<rtio::SocketAddr, IoError> {
 }
 
 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();
@@ -607,7 +607,7 @@ fn recvfrom(&mut self, buf: &mut [u8])
         }
     }
 
-    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));
@@ -960,7 +960,7 @@ fn udp_recv_ip4() {
                 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),
                     }
@@ -976,7 +976,7 @@ fn udp_recv_ip4() {
         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)
         }
     }
@@ -992,7 +992,7 @@ fn udp_recv_ip6() {
                 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),
                     }
@@ -1008,7 +1008,7 @@ fn udp_recv_ip6() {
         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)
         }
     }
@@ -1057,16 +1057,16 @@ fn test_udp_twice() {
         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);
@@ -1098,10 +1098,10 @@ fn test_udp_many_read() {
             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);
@@ -1120,9 +1120,9 @@ fn test_udp_many_read() {
         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);
@@ -1132,7 +1132,7 @@ fn test_udp_many_read() {
             }
         }
         // 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]
index b94141748d57fe2561cc14a4a20fb43ace1338ca..7c01a0342edc71b30bbcaf89597f1bfc10240b4c 100644 (file)
 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 {
@@ -733,7 +731,7 @@ fn reserve(&mut self, new_capacity: uint) {
 /// }
 /// ```
 #[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,
 
@@ -1033,18 +1031,17 @@ fn pop(&mut self, k: &K) -> Option<V> {
 
 }
 
-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)
     }
 }
@@ -1053,6 +1050,7 @@ impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> HashMap<K, V, H> {
     /// 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)
     }
@@ -1064,6 +1062,7 @@ pub fn with_hasher(hasher: H) -> HashMap<K, V, H> {
     /// 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 {
@@ -1489,7 +1488,7 @@ fn extend<T: Iterator<(K, V)>>(&mut self, mut iter: T) {
 /// 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>
 }
 
@@ -1529,15 +1528,17 @@ fn insert(&mut self, value: T) -> bool { self.map.insert(value, ()) }
     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) }
     }
 }
@@ -1547,6 +1548,7 @@ impl<T: Eq + Hash<S>, S, H: Hasher<S>> HashSet<T, H> {
     /// 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)
     }
@@ -1558,6 +1560,7 @@ pub fn with_hasher(hasher: H) -> HashSet<T, H> {
     /// 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) }
     }
diff --git a/src/libstd/hash.rs b/src/libstd/hash.rs
new file mode 100644 (file)
index 0000000..2cc7e70
--- /dev/null
@@ -0,0 +1,102 @@
+// 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()
+    }
+}
index bc8447dfa2ee9dcfc8161f0cb7c9879f38048b64..e7f26c7bd910e5d21d61de30a703734684f9f1a4 100644 (file)
@@ -1206,8 +1206,8 @@ pub fn tmpdir() -> TempDir {
         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;
         }
index 5f6de52f86632ba9bfe07267c1bbc82c80935646..cd78898d46bb82c22c73b54f39f8d3a3bfc3e516 100644 (file)
 /// };
 ///
 /// 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)
 /// }
@@ -72,9 +72,9 @@ pub fn bind(addr: SocketAddr) -> IoResult<UdpSocket> {
 
     /// 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 }))
             }
@@ -82,15 +82,28 @@ pub fn recvfrom(&mut self, buf: &mut [u8])
         }
     }
 
+    #[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.
@@ -225,7 +238,7 @@ impl Reader for UdpStream {
     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),
@@ -237,7 +250,7 @@ fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> {
 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))
     }
 }
 
@@ -266,7 +279,7 @@ mod test {
             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!()
             }
@@ -277,7 +290,7 @@ mod test {
             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);
@@ -300,7 +313,7 @@ mod test {
             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!()
             }
@@ -310,7 +323,7 @@ mod test {
             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);
@@ -429,9 +442,9 @@ pub fn socket_name(addr: SocketAddr) {
         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();
@@ -441,12 +454,12 @@ pub fn socket_name(addr: SocketAddr) {
         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();
     })
 
@@ -460,9 +473,9 @@ pub fn socket_name(addr: SocketAddr) {
 
         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();
         });
 
@@ -472,12 +485,12 @@ pub fn socket_name(addr: SocketAddr) {
         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();
@@ -497,7 +510,7 @@ pub fn socket_name(addr: SocketAddr) {
             let mut buf = [0, 1];
 
             rx.recv();
-            match sock2.recvfrom(buf) {
+            match sock2.recv_from(buf) {
                 Ok(..) => {}
                 Err(e) => fail!("failed receive: {}", e),
             }
@@ -510,13 +523,13 @@ pub fn socket_name(addr: SocketAddr) {
         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(..) => {}
         }
@@ -526,7 +539,7 @@ pub fn socket_name(addr: SocketAddr) {
         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();
@@ -535,34 +548,34 @@ pub fn socket_name(addr: SocketAddr) {
         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();
@@ -570,7 +583,7 @@ pub fn socket_name(addr: SocketAddr) {
 
         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),
index 48ccd1aa22ce3be3b18f6d517b8816aec688f4b2..06a1d069b6a72b25f9a75eae9c489a88b8545bd4 100644 (file)
 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;
@@ -237,6 +236,7 @@ fn start(argc: int, argv: *const *const u8) -> int {
 /* Common data structures */
 
 pub mod collections;
+pub mod hash;
 
 /* Tasks and communication */
 
index ec225a588fcc18bfb24616b9da80b6cf69eb6907..113b0410875af7ad0d068d0b394554320715de96 100644 (file)
@@ -242,14 +242,18 @@ unsafe fn push_unchecked<T: BytesContainer>(&mut self, path: T) {
         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
             }
         }
@@ -279,7 +283,7 @@ fn append_path(me: &mut Path, path: &str) {
             // 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);
                 }
                 _ => ()
@@ -302,7 +306,7 @@ fn append_path(me: &mut Path, path: &str) {
                     // 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
@@ -478,7 +482,7 @@ fn is_absolute(&self) -> bool {
         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
@@ -638,11 +642,11 @@ pub fn str_components<'a>(&'a self) -> StrComponents<'a> {
         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);
@@ -665,14 +669,14 @@ fn equiv_prefix(&self, other: &Path) -> bool {
         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())
@@ -718,12 +722,12 @@ fn normalize__(s: &str, prefix: Option<PathPrefix>) -> Option<String> {
             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![]);
                     }
                 }
@@ -778,12 +782,12 @@ fn normalize__(s: &str, prefix: Option<PathPrefix>) -> Option<String> {
                         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)) => {
@@ -845,7 +849,7 @@ fn sepidx_or_prefix_len(&self) -> Option<(uint,uint,uint)> {
 
     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) {
@@ -861,7 +865,7 @@ 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
@@ -991,8 +995,8 @@ fn parse_prefix<'a>(mut path: &'a str) -> Option<PathPrefix> {
             } 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);
@@ -1014,9 +1018,9 @@ fn parse_prefix<'a>(mut path: &'a str) -> Option<PathPrefix> {
             }
             _ => ()
         }
-    } 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);
         }
index 4ab2ac97cc1574221ca42798a82f090782719f05..44dd63cbf6c010cfd63058c9d6700e4b00922fa4 100644 (file)
 */
 
 #![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::*;
 
index 665f94d80b237cbe3f651cb8afef226f06577564..6c09a021c4338212efe8056a38efd07f76f6229e 100644 (file)
@@ -370,6 +370,7 @@ fn f() $b
 
 /// 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>,
@@ -380,12 +381,14 @@ pub struct Receiver<T> {
 /// 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>,
@@ -395,6 +398,7 @@ pub struct Sender<T> {
 
 /// 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
@@ -404,6 +408,7 @@ pub struct SyncSender<T> {
 /// 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.
@@ -416,6 +421,7 @@ pub enum TryRecvError {
 /// 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.
@@ -478,6 +484,7 @@ fn inner_unsafe<'a>(&'a self) -> &'a Unsafe<Flavor<T>> {
 /// // 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)))
@@ -514,6 +521,8 @@ pub fn channel<T: Send>() -> (Sender<T>, Receiver<T>) {
 /// 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)))
@@ -547,6 +556,8 @@ fn new(inner: Flavor<T>) -> Sender<T> {
     ///
     /// 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");
@@ -583,6 +594,7 @@ pub fn send(&self, t: T) {
     /// 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
@@ -638,6 +650,7 @@ pub fn send_opt(&self, t: T) -> Result<(), T> {
     }
 }
 
+#[unstable]
 impl<T: Send> Clone for Sender<T> {
     fn clone(&self) -> Sender<T> {
         let (packet, sleeper) = match *unsafe { self.inner() } {
@@ -719,6 +732,8 @@ fn new(inner: Arc<Unsafe<sync::Packet<T>>>) -> SyncSender<T> {
     /// 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");
@@ -736,6 +751,7 @@ pub fn send(&self, t: T) {
     /// # 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) }
     }
@@ -753,11 +769,14 @@ pub fn send_opt(&self, t: T) -> Result<(), 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(); }
@@ -800,6 +819,8 @@ fn new(inner: Flavor<T>) -> Receiver<T> {
     ///
     /// * 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,
@@ -817,6 +838,7 @@ pub fn recv(&self) -> 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
@@ -881,6 +903,7 @@ pub fn try_recv(&self) -> Result<T, TryRecvError> {
     ///
     /// 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() } {
@@ -917,6 +940,7 @@ pub fn recv_opt(&self) -> Result<T, ()> {
 
     /// 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 }
     }
@@ -1009,6 +1033,7 @@ fn abort_selection(&self) -> bool {
     }
 }
 
+#[unstable]
 impl<'a, T: Send> Iterator<T> for Messages<'a, T> {
     fn next(&mut self) -> Option<T> { self.rx.recv_opt().ok() }
 }
index 8d56f9a003b3ff3b8b02b553dab62cc95fbc1289..230bca624f5a7f61ae80f9c2a4ef0f74f8b6b316 100644 (file)
 //! ```
 
 #![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::*;
 
index 90569bfc132c7de3b2c819c37e92a85ee12a501d..dfaa9fb5fcb09507f31144396946f7708b588c40 100644 (file)
@@ -415,7 +415,7 @@ fn highlight_lines(err: &mut EmitterWriter,
         }
         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
index ac570c888375c4bcf8e15e6f73ab18ab8d7858c3..0f188fdf18a5a80c06ee94126b1ac47e16198674 100644 (file)
@@ -1203,8 +1203,8 @@ fn read_to_eol(&mut self) -> String {
 
     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;
     }
 
index 3ed7fccb933e667908d204c2199886dd690eec06..f52a032961dd96a568628259f8d785e43ff21fbd 100644 (file)
@@ -375,7 +375,7 @@ pub fn strptime(s: &str, format: &str) -> Result<Tm, String> {
     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;
index 19627e2c2ce5017ecf7e8a8a35e841554487c5e0..0e73256893e9cc1c06450b755c3fc6ccdccbdc2d 100644 (file)
@@ -324,8 +324,8 @@ pub fn to_simple_str(&self) -> String {
         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()
     }
index 67be7d121a454049b709f6a7ad3f61e9935e34b0..195c146c12fe719f26927bef8016837b91852345 100644 (file)
@@ -183,7 +183,7 @@ fn main() {
 
        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) => {
diff --git a/src/test/compile-fail/borrowck-overloaded-call.rs b/src/test/compile-fail/borrowck-overloaded-call.rs
new file mode 100644 (file)
index 0000000..349a203
--- /dev/null
@@ -0,0 +1,74 @@
+// 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() {}
+
diff --git a/src/test/compile-fail/drop-with-active-borrows-1.rs b/src/test/compile-fail/drop-with-active-borrows-1.rs
new file mode 100644 (file)
index 0000000..9d5020e
--- /dev/null
@@ -0,0 +1,19 @@
+// 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);
+    }
+}
+
diff --git a/src/test/compile-fail/drop-with-active-borrows-2.rs b/src/test/compile-fail/drop-with-active-borrows-2.rs
new file mode 100644 (file)
index 0000000..2700cef
--- /dev/null
@@ -0,0 +1,19 @@
+// 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());
+}
index 967229a34074bd7259cdb9370493b87fe02791ee..8b1f9eb19864fadf3a9caf31f5dcb686b4a09a4c 100644 (file)
@@ -17,10 +17,10 @@ pub fn main() {
     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
 }
index 483168bb8bcfa1ed1585feb453b5506a3d2fdad8..439c82a6df08b19f858cd68de06f24abe731a74d 100644 (file)
@@ -1,4 +1,4 @@
-// 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"); }
     }
 }
diff --git a/src/test/compile-fail/str-idx.rs b/src/test/compile-fail/str-idx.rs
new file mode 100644 (file)
index 0000000..25e4c90
--- /dev/null
@@ -0,0 +1,16 @@
+// 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`
+}
index 26c5a6988cf13d3c7bed9c816bf9ca3ed40cc97c..c3ee76047d13428060432d2ded9cd7359bd79cb1 100644 (file)
@@ -14,5 +14,5 @@ fn main() {
     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);
 }
diff --git a/src/test/run-pass/drop-with-type-ascription-1.rs b/src/test/run-pass/drop-with-type-ascription-1.rs
new file mode 100644 (file)
index 0000000..c4ea169
--- /dev/null
@@ -0,0 +1,17 @@
+// 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");
+}
+
diff --git a/src/test/run-pass/drop-with-type-ascription-2.rs b/src/test/run-pass/drop-with-type-ascription-2.rs
new file mode 100644 (file)
index 0000000..634b100
--- /dev/null
@@ -0,0 +1,17 @@
+// 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");
+}
+
index 3d6b6ba626d1114d48b752dd14125fa47e30c93c..5364cdc627f50b1f95d9304ef8c0756c1c2b89cb 100644 (file)
@@ -17,8 +17,8 @@ pub fn main() {
     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);
index 1652016b51b069151aaaa6195b2a4133c738ee60..b562558822cd1bf2064f346d670fa17a58526175 100644 (file)
@@ -15,6 +15,6 @@ pub fn main() {
     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));
 }
diff --git a/src/test/run-pass/issue-11205.rs b/src/test/run-pass/issue-11205.rs
new file mode 100644 (file)
index 0000000..5b52bc3
--- /dev/null
@@ -0,0 +1,92 @@
+// 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
+    };
+}
diff --git a/src/test/run-pass/issue-15104.rs b/src/test/run-pass/issue-15104.rs
new file mode 100644 (file)
index 0000000..d271133
--- /dev/null
@@ -0,0 +1,21 @@
+// 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)
+    }
+}
diff --git a/src/test/run-pass/match-vec-alternatives.rs b/src/test/run-pass/match-vec-alternatives.rs
new file mode 100644 (file)
index 0000000..ffbc4e8
--- /dev/null
@@ -0,0 +1,82 @@
+// 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");
+}
index 7141d0b9df5250e85decc2cbe02924024289ec37..ad0d2f11abd8611562a1c660f02d556142545134 100644 (file)
@@ -16,5 +16,5 @@ pub fn main() {
     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);
 }
diff --git a/src/test/run-pass/str-idx.rs b/src/test/run-pass/str-idx.rs
deleted file mode 100644 (file)
index 8ac13e8..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-// 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);
-}
index 9263cd1d485422e2dcfed162c1e5d5e4f96172b1..d45e7a20c3b2020271f71a5fa1ff7ac106cafcbb 100644 (file)
@@ -39,10 +39,10 @@ fn test_str() {
     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)]
index 18a0e5d471c4a91fa3134034c6334ab324fee4d6..cfe9a772b2ee84de751ea38d3528d420f32b3bf1 100644 (file)
@@ -99,7 +99,7 @@ fn check_legs(arc: Arc<Vec<Box<Pet+Share+Send>>>) {
 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);
         })
     }
 }
index a79fcfa94171fb4211ac1aa79f9a398c3a2f810a..557d2e5878e1dd1bf03f18786fec07e04b666ac5 100644 (file)
@@ -46,7 +46,7 @@ fn check_str_eq(a: String, b: String) {
         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;