Fix the relative path issue by including the files using include_bytes!

This commit is contained in:
Mathieu David 2015-07-27 20:46:01 +02:00
commit f6e9240a99
679 changed files with 29823 additions and 16933 deletions

1
.gitignore vendored
View File

@ -19,6 +19,7 @@
*.exe
*.fn
*.html
*.kdev4
*.ky
*.ll
*.llvm

View File

@ -8,12 +8,13 @@
Aaron Todd <github@opprobrio.us>
Abhishek Chanda <abhishek.becs@gmail.com> Abhishek Chanda <abhishek@cloudscaling.com>
Ahmed Charles <ahmedcharles@gmail.com> <acharles@outlook.com>
Aydin Kim <ladinjin@hanmail.net> aydin.kim <aydin.kim@samsung.com>
Alex Lyon <arcterus@mail.com> <Arcterus@mail.com>
Alex Rønne Petersen <alex@lycus.org>
Andreas Gal <gal@mozilla.com> <andreas.gal@gmail.com>
Andrew Poelstra <asp11@sfu.ca> <apoelstra@wpsoftware.net>
Anton Löfgren <anton.lofgren@gmail.com> <alofgren@op5.com>
Ariel Ben-Yehuda <arielb1@mail.tau.ac.il> <ariel.byd@gmail.com>
Ariel Ben-Yehuda <arielb1@mail.tau.ac.il> arielb1 <arielb1@mail.tau.ac.il> <ariel.byd@gmail.com>
Austin Seipp <mad.one@gmail.com> <as@hacks.yi.org>
Ben Alpert <ben@benalpert.com> <spicyjalapeno@gmail.com>
Benjamin Jackman <ben@jackman.biz>
@ -38,6 +39,7 @@ Eduardo Bautista <me@eduardobautista.com> <mail@eduardobautista.com>
Eduardo Bautista <me@eduardobautista.com> <=>
Elliott Slaughter <elliottslaughter@gmail.com> <eslaughter@mozilla.com>
Elly Fong-Jones <elly@leptoquark.net>
Emily Dunham <edunham@mozilla.com> edunham <edunham@mozilla.com>
Eric Holk <eric.holk@gmail.com> <eholk@mozilla.com>
Eric Holk <eric.holk@gmail.com> <eholk@cs.indiana.edu>
Eric Holmes <eric@ejholmes.net>
@ -45,6 +47,7 @@ Eric Reed <ecreed@cs.washington.edu> <ereed@mozilla.com>
Erick Tryzelaar <erick.tryzelaar@gmail.com> <etryzelaar@iqt.org>
Evgeny Sologubov
Falco Hirschenberger <falco.hirschenberger@gmail.com> <hirschen@itwm.fhg.de>
Felix S. Klock II <pnkfelix@pnkfx.org> Felix S Klock II <pnkfelix@pnkfx.org>
Gareth Daniel Smith <garethdanielsmith@gmail.com>
Georges Dubus <georges.dubus@gmail.com> <georges.dubus@compiletoi.net>
Graham Fawcett <fawcett@uwindsor.ca> <graham.fawcett@gmail.com>
@ -64,6 +67,7 @@ Jihyun Yu <jihyun@nclab.kaist.ac.kr> jihyun <jihyun@nablecomm.com>
Jihyun Yu <jihyun@nclab.kaist.ac.kr> <yjh0502@gmail.com>
Johann Hofmann <mail@johann-hofmann.com> Johann <git@johann-hofmann.com> Johann Hofmann <git@johann-hofmann.com>
John Clements <clements@racket-lang.org> <clements@brinckerhoff.org>
John Hodge <acessdev@gmail.com> John Hodge <tpg@mutabah.net>
Jorge Aparicio <japaric@linux.com> <japaricious@gmail.com>
Jonathan Bailey <jbailey@mozilla.com> <jbailey@jbailey-20809.local>
Junyoung Cho <june0.cho@samsung.com>
@ -80,20 +84,24 @@ Luqman Aden <me@luqman.ca> <laden@csclub.uwaterloo.ca>
Luke Metz <luke.metz@students.olin.edu>
Makoto Nakashima <makoto.nksm+github@gmail.com> <makoto.nksm@gmail.com>
Makoto Nakashima <makoto.nksm+github@gmail.com> gifnksm <makoto.nksm+github@gmail.com>
Markus Westerlind <marwes91@gmail.com> Markus <marwes91@gmail.com>
Margaret Meyerhofer <mmeyerho@andrew.cmu.edu> <mmeyerho@andrew>
Mark Sinclair <mark.edward.x@gmail.com>
Mark Sinclair <mark.edward.x@gmail.com> =Mark Sinclair <=125axel125@gmail.com>
Matej Lach <matej.lach@gmail.com> Matej Ľach <matej.lach@gmail.com>
Matt Brubeck <mbrubeck@limpet.net> <mbrubeck@cs.hmc.edu>
Matthew Auld <matthew.auld@intel.com>
Matthew McPherrin <matthew@mcpherrin.ca> <matt@mcpherrin.ca>
Matthijs Hofstra <thiezz@gmail.com>
Michael Williams <m.t.williams@live.com>
Michael Woerister <michaelwoerister@gmail> <michaelwoerister@gmail.com>
Michael Woerister <michaelwoerister@gmail> <michaelwoerister@posteo>
Michael Woerister <michaelwoerister@gmail> <michaelwoerister@gmail.com> <michaelwoerister@posteo> Michael Woerister <michaelwoerister@posteo>
Neil Pankey <npankey@gmail.com> <neil@wire.im>
Nicholas Mazzuca <npmazzuca@gmail.com> Nicholas <npmazzuca@gmail.com>
Oliver Schneider <github6541940@oli-obk.de> <git1984941651981@oli-obk.de> <git1984941651981@oli-obk.de> Oliver 'ker' Schneider <rust19446194516@oli-obk.de>
Ožbolt Menegatti <ozbolt.menegatti@gmail.com> gareins <ozbolt.menegatti@gmail.com>
Paul Faria <paul_faria@ultimatesoftware.com> Paul Faria <Nashenas88@gmail.com>
Peer Aramillo Irizar <peer.aramillo.irizar@gmail.com> parir <peer.aramillo.irizar@gmail.com>
Peter Elmers <peter.elmers@yahoo.com> <peter.elmers@rice.edu>
Philipp Brüschweiler <blei42@gmail.com> <blei42@gmail.com>
Philipp Brüschweiler <blei42@gmail.com> <bruphili@student.ethz.ch>
Pradeep Kumar <gohanpra@gmail.com>
@ -105,6 +113,7 @@ Robert Foss <dev@robertfoss.se> robertfoss <dev@robertfoss.se>
Robert Gawdzik <rgawdzik@hotmail.com> Robert Gawdzik ☢ <rgawdzik@hotmail.com>
Robert Millar <robert.millar@cantab.net>
Ryan Scheel <ryan.havvy@gmail.com>
Sean Gillespie <sean.william.g@gmail.com> swgillespie <sean.william.g@gmail.com>
Seonghyun Kim <sh8281.kim@samsung.com>
Simon Barber-Dueck <sbarberdueck@gmail.com> Simon BD <simon@server>
Simon Sapin <simon@exyr.org> <simon.sapin@exyr.org>
@ -114,7 +123,9 @@ Steven Stewart-Gallus <sstewartgallus00@langara.bc.ca> <sstewartgallus00@mylanga
Tamir Duberstein <tamird@gmail.com> Tamir Duberstein <tamird@squareup.com>
Tim Chevalier <chevalier@alum.wellesley.edu> <catamorphism@gmail.com>
Torsten Weber <TorstenWeber12@gmail.com> <torstenweber12@gmail.com>
Vadim Petrochenkov <vadim.petrochenkov@gmail.com> petrochenkov <vadim.petrochenkov@gmail.com>
William Ting <io@williamting.com> <william.h.ting@gmail.com>
Xuefeng Wu <benewu@gmail.com> Xuefeng Wu <xfwu@thoughtworks.com> XuefengWu <benewu@gmail.com>
Youngsoo Son <ysson83@gmail.com> <ysoo.son@samsung.com>
Zack Corr <zack@z0w0.me> <zackcorr95@gmail.com>
Zack Slayton <zack.slayton@gmail.com>

View File

@ -1,7 +1,9 @@
# Use something that's not 'ruby' so we don't set up things like
# RVM/bundler/ruby and whatnot. Right now 'rust' as a language actually
# downloads a rust/cargo snapshot, which we don't really want for building rust.
# ccache support is disabled unless your language is a C-derivative. However
# `language: C` unconditionally sets `CC=compiler`. If we just set it in our
# `env` it will be overwritten by the default (gcc 4.6).
language: c
compiler: /usr/bin/gcc-4.7
cache: ccache
sudo: false
# The test suite is in general way too stressful for travis, especially in
@ -9,12 +11,28 @@ sudo: false
# back to only build the stage1 compiler and run a subset of tests, but this
# didn't end up panning out very well.
#
# As a result, we're just using travis to run `make tidy` now. It'll help
# everyone find out about their trailing spaces early on!
# As a result, we're just using travis to run `make tidy` and *only* build
# stage1 but *not* test it for now (a strict subset of the bootstrap). This will
# catch "obvious" errors like style or not even compiling.
#
# We need gcc4.7 or higher to build LLVM, and travis (well, Ubuntu 12.04)
# currently ships with 4.6. Gotta download our own.
before_script:
- ./configure --llvm-root=path/to/nowhere
- ./configure --enable-ccache
script:
- make tidy
- make rustc-stage1 -j4
env:
- CXX=/usr/bin/g++-4.7
addons:
apt:
sources:
- ubuntu-toolchain-r-test
packages:
- gcc-4.7
- g++-4.7
# Real testing happens on http://buildbot.rust-lang.org/
#

View File

@ -22,11 +22,13 @@ Aidan Cully <github@aidan.users.panix.com>
Aidan Hobson Sayers <aidanhs@cantab.net>
A.J. Gardner <mrhota@users.noreply.github.com>
Akos Kiss <akiss@inf.u-szeged.hu>
Akshay Chiwhane <achiwhane@gmail.com>
Alan Andrade <alan.andradec@gmail.com>
Alan Cutter <alancutter@chromium.org>
Alan Williams <mralert@gmail.com>
Aleksander Balicki <balicki.aleksander@gmail.com>
Aleksandr Koshlo <sash7ko@gmail.com>
Alexander Artemenko <svetlyak.40wt@gmail.com>
Alexander Bliskovsky <alexander.bliskovsky@gmail.com>
Alexander Campbell <alexanderhcampbell@gmail.com>
Alexander Chernyakhovsky <achernya@mit.edu>
@ -44,6 +46,7 @@ Alexis Beingessner <a.beingessner@gmail.com>
Alex Lyon <arcterus@mail.com>
Alex Quach <alex@clinkle.com>
Alex Rønne Petersen <alex@lycus.org>
Alex Stokes <r.alex.stokes@gmail.com>
Alex Whitney <aw1209@ic.ac.uk>
Alfie John <alfie@alfie.wtf>
Alisdair Owens <awo101@zepler.net>
@ -66,8 +69,10 @@ Andrew Barchuk <raindev@icloud.com>
Andrew Cann <shum@canndrew.org>
Andrew Chin <achin@eminence32.net>
Andrew Dunham <andrew@du.nham.ca>
Andrew Foote <afoote97@gmail.com>
Andrew Gallant <jamslam@gmail.com>
Andrew Hobden <andrew@hoverbear.org>
Andrew Kensler <andrew@eastfarthing.com>
Andrew Paseltiner <apaseltiner@gmail.com>
Andrew Poelstra <asp11@sfu.ca>
Andrew Seidl <dev@aas.io>
@ -93,19 +98,21 @@ Ashok Gautham <ScriptDevil@gmail.com>
Augusto Hack <hack.augusto@gmail.com>
auREAX <mark@xn--hwg34fba.ws>
Austin Bonander <austin.bonander@gmail.com>
Austin Hellyer <hello@austinhellyer.me>
Austin King <shout@ozten.com>
Austin Seipp <mad.one@gmail.com>
Avdi Grimm <avdi@avdi.org>
awlnx <alecweber1994@gmail.com>
Axel Viala <axel.viala@darnuria.eu>
aydin.kim <aydin.kim@samsung.com>
Aydin Kim <ladinjin@hanmail.net>
bachm <Ab@vapor.com>
Barosl Lee <vcs@barosl.com>
bcoopers <coopersmithbrian@gmail.com>
Ben Alpert <ben@benalpert.com>
benaryorg <binary@benary.org>
Ben Ashford <ben@bcash.org>
Ben Blum <bblum@andrew.cmu.edu>
ben fleis <ben.fleis@gmail.com>
Ben Foppa <benjamin.foppa@gmail.com>
Ben Gamari <bgamari.foss@gmail.com>
Ben Gesoff <ben.gesoff@gmail.com>
@ -128,6 +135,7 @@ Birunthan Mohanathas <birunthan@mohanathas.com>
Björn Steinbrink <bsteinbr@gmail.com>
blake2-ppc <ulrik.sverdrup@gmail.com>
bluss <bluss>
bluss <bluss@users.noreply.github.com>
Boris Egorov <egorov@linux.com>
bors <bors@rust-lang.org>
Bouke van der Bijl <boukevanderbijl@gmail.com>
@ -149,6 +157,7 @@ Brian J Brennan <brianloveswords@gmail.com>
Brian J. Burg <burg@cs.washington.edu>
Brian Koropoff <bkoropoff@gmail.com>
Brian Leibig <brian@brianleibig.com>
Brian Quinlan <brian@sweetapp.com>
Bruno de Oliveira Abinader <bruno.d@partner.samsung.com>
Bryan Dunsmore <dunsmoreb@gmail.com>
Byron Williams <byron@112percent.com>
@ -172,6 +181,7 @@ Ches Martin <ches@whiskeyandgrits.net>
chitra
Chloe <5paceToast@users.noreply.github.com>
Chris Double <chris.double@double.co.nz>
Chris Hellmuth <chellmuth@gmail.com>
Chris Morgan <me@chrismorgan.info>
Chris Nixon <chris.nixon@sigma.me.uk>
Chris Peterson <cpeterson@mozilla.com>
@ -179,14 +189,17 @@ Chris Pressey <cpressey@gmail.com>
Chris Sainty <csainty@hotmail.com>
Chris Shea <cmshea@gmail.com>
Chris Thorn <chris@thorn.co>
Christian Stadelmann <dev@genodeftest.de>
Christoph Burgdorf <christoph.burgdorf@bvsn.org>
Christopher Bergqvist <spambox0@digitalpoetry.se>
Christopher Chambers <chris.chambers@peanutcode.com>
Christopher Kendell <ckendell@outlook.com>
Chris Wong <lambda.fairy@gmail.com>
chromatic <chromatic@wgz.org>
Chuck Bassett <iamchuckb@gmail.com>
Chuck Ries <chuck.ries@gmail.com>
Clark Gaebel <cg.wowus.cg@gmail.com>
clatour <chandler.latour@gmail.com>
Clifford Caoile <piyo@users.sf.net>
Clinton Ryan <clint.ryan3@gmail.com>
Cody P Schafer <dev@codyps.com>
@ -201,10 +214,12 @@ Conrad Kleinespel <conradk@conradk.com>
Corey Farwell <coreyf+rust@rwell.org>
Corey Ford <corey@coreyford.name>
Corey Richardson <corey@octayn.net>
Cornel Punga <cornel.punga@gmail.com>
crhino <piraino.chris@gmail.com>
Cristian Kubis <cristian.kubis@tsunix.de>
Cristi Burcă <scribu@gmail.com>
critiqjo <john.ch.fr@gmail.com>
Cruz Julian Bishop <cruzjbishop@gmail.com>
Damian Gryski <damian@gryski.com>
Damien Grassart <damien@grassart.com>
Damien Radtke <dradtke@channeliq.com>
@ -240,6 +255,7 @@ Darrell Hamilton <darrell.noice@gmail.com>
Dave Herman <dherman@mozilla.com>
Dave Hodder <dmh@dmh.org.uk>
Dave Huseby <dhuseby@mozilla.com>
David Campbell <dcampbell24@gmail.com>
David Creswick <dcrewi@gyrae.net>
David Forsythe <dforsythe@gmail.com>
David Halperin <halperin.dr@gmail.com>
@ -251,7 +267,9 @@ David Rajchenbach-Teller <dteller@mozilla.com>
David Reid <dreid@dreid.org>
David Renshaw <dwrenshaw@gmail.com>
David Ross <daboross@daboross.net>
David Stygstra <david.stygstra@gmail.com>
David Vazgenovich Shakaryan <dvshakaryan@gmail.com>
David Voit <david.voit@gmail.com>
Davis Silverman <sinistersnare@gmail.com>
defuz <defuz.net@gmail.com>
Denis Defreyne <denis.defreyne@stoneship.org>
@ -271,6 +289,7 @@ Dirk Leifeld <leifeld@posteo.de>
Div Shekhar <div@pagerduty.com>
diwic <diwic@users.noreply.github.com>
DJUrsus <colinvh@divitu.com>
dmgawel <dgkonik@gmail.com>
Dmitry Ermolov <epdmitry@yandex.ru>
Dmitry Promsky <dmitry@willworkforcookies.com>
Dmitry Vasiliev <dima@hlabs.org>
@ -290,6 +309,7 @@ Dylan Braithwaite <dylanbraithwaite1@gmail.com>
Dylan Ede <dylanede@googlemail.com>
Dzmitry Malyshau <kvarkus@gmail.com>
Earl St Sauver <estsauver@gmail.com>
econoplas <econoplas@gmail.com>
Eduard Bopp <eduard.bopp@aepsil0n.de>
Eduard Burtescu <edy.burt@gmail.com>
Eduardo Bautista <me@eduardobautista.com>
@ -297,6 +317,7 @@ Edward Wang <edward.yu.wang@gmail.com>
Edward Z. Yang <ezyang@cs.stanford.edu>
Ehsanul Hoque <ehsanul@ehsanul.com>
Elantsev Serj <elantsev@yandex-team.ru>
Eli Friedman <eli.friedman@gmail.com>
eliovir <eliovir@gmail.com>
Elliott Slaughter <elliottslaughter@gmail.com>
Elly Fong-Jones <elly@leptoquark.net>
@ -304,6 +325,8 @@ elszben <notgonna@tellyou>
emanueLczirai <emanueLczirai@cryptoLab.net>
Emanuel Rylke <ema-fox@web.de>
Emeliov Dmitrii <demelev1990@gmail.com>
Emilio Cobos Álvarez <ecoal95@gmail.com>
Emily Dunham <edunham@mozilla.com>
Eric Allen <ericpallen@gmail.com>
Eric Biggers <ebiggers3@gmail.com>
Eric Holk <eric.holk@gmail.com>
@ -314,7 +337,9 @@ Erick Tryzelaar <erick.tryzelaar@gmail.com>
Eric Martin <e.a.martin1337@gmail.com>
Eric Platon <eric.platon@waku-waku.ne.jp>
Eric Reed <ecreed@cs.washington.edu>
Eric Ye <me@ericye16.com>
Erik Lyon <elyon001@local.fake>
Erik Michaels-Ober <sferik@gmail.com>
Erik Price <erik.price16@gmail.com>
Erik Rose <erik@mozilla.com>
Erwan <erwan.ricq@gmail.com>
@ -344,10 +369,12 @@ Florian Wilkens <mrfloya_github@outlook.com>
Florian Zeitz <florob@babelmonkeys.de>
fort <e@mail.com>
Francisco Souza <f@souza.cc>
frankamp <frankamp@gmail.com>
Franklin Chen <franklinchen@franklinchen.com>
Franziska Hinkelmann <franziska.hinkelmann@gmail.com>
free-Runner <aali07@students.poly.edu>
FuGangqiang <fu_gangqiang@163.com>
funkill <funkill2@gmail.com>
g3xzh <g3xzh@yahoo.com>
Gábor Horváth <xazax.hun@gmail.com>
Gábor Lehel <glaebhoerl@gmail.com>
@ -381,6 +408,7 @@ Greg Chapple <gregchapple1@gmail.com>
Grigoriy <ohaistarlight@gmail.com>
Guillaume Gomez <guillaume1.gomez@gmail.com>
Guillaume Pinot <texitoi@texitoi.eu>
Gulshan Singh <gsingh2011@gmail.com>
Gyorgy Andrasek <jurily@gmail.com>
Haitao Li <lihaitao@gmail.com>
Hajime Morrita <omo@dodgson.org>
@ -419,6 +447,7 @@ Ivano Coppola <rgbfirefox@gmail.com>
Ivan Petkov <ivanppetkov@gmail.com>
Ivan Radanov Ivanov <ivanradanov@yahoo.co.uk>
Ivan Ukhov <ivan.ukhov@gmail.com>
Iven Hsu <ivenvd@gmail.com>
Jack Heizer <jack.heizer@gmail.com>
Jack Moffitt <jack@metajack.im>
Jacob Edelman <edelman.jd@gmail.com>
@ -428,6 +457,7 @@ Jacob Parker <j3parker@csclub.uwaterloo.ca>
Jaemin Moon <jaemin.moon@samsung.com>
Jag Talon <talon.jag@gmail.com>
Jake Goulding <jake.goulding@gmail.com>
Jake Hickey <empty@cqdr.es>
Jake Kaufman <theevocater@gmail.com>
Jake Kerr <kodafox@gmail.com>
Jake Scott <jake.net@gmail.com>
@ -439,7 +469,7 @@ James Hurst <jamesrhurst@users.noreply.github.com>
James Lal <james@lightsofapollo.com>
James Laverack <james@jameslaverack.com>
jamesluke <jamesluke@users.noreply.github.com>
James Miller <james@aatch.net>
James Miller <bladeon@gmail.com>
James Perry <james.austin.perry@gmail.com>
James Rowe <jroweboy@gmail.com>
James Sanders <sanderjd@gmail.com>
@ -479,11 +509,13 @@ Jelte Fennema <github-tech@jeltef.nl>
Jens Nockert <jens@nockert.se>
Jeong YunWon <jeong@youknowone.org>
Jeremy Letang <letang.jeremy@gmail.com>
Jeremy Schlatter <jeremy.schlatter@gmail.com>
Jesse Jones <jesse9jones@gmail.com>
Jesse Luehrs <doy@tozt.net>
Jesse Ray <jesse@localhost.localdomain>
Jesse Ruderman <jruderman@gmail.com>
Jessy Diamond Exum <jessy.diamondman@gmail.com>
Jexell <Jexell@users.noreply.github.com>
Jihyeok Seo <me@limeburst.net>
Jihyun Yu <j.yu@navercorp.com>
Jim Apple <jbapple+rust@google.com>
@ -504,6 +536,7 @@ Johannes Löthberg <johannes@kyriasis.com>
Johannes Muenzel <jmuenzel@gmail.com>
Johannes Oertel <johannes.oertel@uni-due.de>
Johann Hofmann <git@johann-hofmann.com>
Johann Tuffe <tafia973@gmail.com>
John Albietz <inthecloud247@gmail.com>
John Barker <jebarker@gmail.com>
John Clements <clements@racket-lang.org>
@ -519,6 +552,7 @@ John Simon <john@johnsoft.com>
John Talling <inrustwetrust@users.noreply.github.com>
John Van Enk <vanenkj@gmail.com>
John Zhang <john@zhang.io>
joliv <joliv@users.noreply.github.com>
Jonas Hietala <tradet.h@gmail.com>
Jonathan Bailey <jbailey@mozilla.com>
Jonathan Boyett <jonathan@failingservers.com>
@ -545,6 +579,7 @@ Josh Matthews <josh@joshmatthews.net>
Josh Stone <cuviper@gmail.com>
Josh Triplett <josh@joshtriplett.org>
Joshua Clark <joshua.clark@txstate.edu>
Joshua Landau <joshua@landau.ws>
Joshua Wise <joshua@joshuawise.com>
Joshua Yanovski <pythonesque@gmail.com>
JP-Ellis <coujellis@gmail.com>
@ -586,6 +621,7 @@ KokaKiwi <kokakiwi+rust@kokakiwi.net>
korenchkin <korenchkin2@gmail.com>
Kostas Karachalios <vrinek@me.com>
Krzysztof Drewniak <krzysdrewniak@gmail.com>
Kubilay Kocak <koobs@users.noreply.github.com>
kulakowski <george.kulakowski@gmail.com>
kwantam <kwantam@gmail.com>
Kyeongwoon Lee <kyeongwoon.lee@samsung.com>
@ -601,6 +637,7 @@ Lee Jeffery <leejeffery@gmail.com>
Lee Wondong <wdlee91@gmail.com>
LemmingAvalanche <haugsbakk@yahoo.no>
Lennart Kudling <github@kudling.de>
Leo Correa <lcorr005@gmail.com>
Leonids Maslovs <leonids.maslovs@galeoconsulting.com>
Leo Testard <leo.testard@gmail.com>
leunggamciu <gamciuleung@gmail.com>
@ -610,6 +647,7 @@ Lindsey Kuper <lindsey@composition.al>
Lionel Flandrin <lionel.flandrin@parrot.com>
Logan Chien <tzuhsiang.chien@gmail.com>
Loïc Damien <loic.damien@dzamlo.ch>
Lorenz <lorenzb@student.ethz.ch>
lpy <pylaurent1314@gmail.com>
Luca Bruno <lucab@debian.org>
lucy <ne.tetewi@gmail.com>
@ -629,16 +667,21 @@ maikklein <maikklein@googlemail.com>
Makoto Nakashima <makoto.nksm+github@gmail.com>
Manish Goregaokar <manishsmail@gmail.com>
Manuel Hoffmann <manuel@polythematik.de>
marcell <marcell.pardavi@gmail.com>
Marcel Müller <neikos@neikos.email>
Marcel Rodrigues <marcelgmr@gmail.com>
Marcus Klaas <mail@marcusklaas.nl>
Margaret Meyerhofer <mmeyerho@andrew.cmu.edu>
Marijn Haverbeke <marijnh@gmail.com>
Marin Atanasov Nikolov <dnaeon@gmail.com>
Mário Feroldi <thelost-t@live.com>
Mark Lacey <641@rudkx.com>
Mark Mossberg <mark.mossberg@gmail.com>
Mark Rowe <mrowe@bdash.net.nz>
Mark Sinclair <mark.edward.x@gmail.com>
Markus Siemens <siemens1993@gmail.com>
Markus Unterwaditzer <markus@unterwaditzer.net>
Markus Westerlind <marwes91@gmail.com>
Mark Vian <mrv.caseus@gmail.com>
Martin DeMello <martindemello@gmail.com>
Martin Olsson <martin@minimum.se>
@ -648,6 +691,7 @@ Marvin Löbel <loebel.marvin@gmail.com>
masklinn <github.com@masklinn.net>
Matej Lach <matej.lach@gmail.com>
Mateusz Czapliński <czapkofan@gmail.com>
Mathieu David <mathieudavid@mathieudavid.org>
Mathieu Poumeyrol <kali@zoy.org>
Mathieu Rochette <mathieu@rochette.cc>
Mathijs van de Nes <git@mathijs.vd-nes.nl>
@ -655,6 +699,7 @@ Matt Brubeck <mbrubeck@limpet.net>
Matt Carberry <carberry.matt@gmail.com>
Matt Coffin <mcoffin13@gmail.com>
Matt Cox <mattcoxpdx@gmail.com>
Matthew Astley <mca@sanger.ac.uk>
Matthew Auld <matthew.auld@intel.com>
Matthew Iselin <matthew@theiselins.net>
Matthew McPherrin <matthew@mcpherrin.ca>
@ -670,6 +715,7 @@ Mátyás Mustoha <mmatyas@inf.u-szeged.hu>
Maxime Quandalle <maxime@quandalle.com>
Maximilian Haack <mxhaack@gmail.com>
Maxim Kolganov <kolganov.mv@gmail.com>
Max Jacobson <max@hardscrabble.net>
Max Penet <max.penet@gmail.com>
Maya Nitu <maya_nitu@yahoo.com>
mchaput <matt@whoosh.ca>
@ -685,7 +731,9 @@ Michael Darakananda <pongad@gmail.com>
Michael Fairley <michaelfairley@gmail.com>
Michael Gehring <mg@ebfe.org>
Michael Kainer <kaini1123@gmail.com>
Michael Layzell <michael@thelayzells.com>
Michael Letterle <michael.letterle@gmail.com>
Michael Macias <zaeleus@gmail.com>
Michael Matuzak <mmatuzak@gmail.com>
Michael Neumann <mneumann@ntecs.de>
Michael Pankov <work@michaelpankov.com>
@ -715,6 +763,7 @@ Mike Sampson <mike@sambodata.com>
Mikhail Zabaluev <mikhail.zabaluev@gmail.com>
Mikko Perttunen <cyndis@kapsi.fi>
mitchmindtree <mitchell.nordine@gmail.com>
Mohammed Attia <skeuomorf@gmail.com>
moonglum <moonglum@moonbeamlabs.com>
mrec <mike.capp@gmail.com>
mr.Shu <mr@shu.io>
@ -727,6 +776,7 @@ nathan dotz <nathan.dotz@gmail.com>
Nathan Froyd <froydnj@gmail.com>
Nathaniel Herman <nherman@post.harvard.edu>
Nathaniel Theis <nttheis@gmail.com>
Nathan Long <nathanmlong@gmail.com>
Nathan Stoddard <nstodda@purdue.edu>
Nathan Typanski <ntypanski@gmail.com>
Nathan Wilson <wilnathan@gmail.com>
@ -739,6 +789,7 @@ Nicholas Bishop <nicholasbishop@gmail.com>
Nicholas Mazzuca <npmazzuca@gmail.com>
Nick Cameron <ncameron@mozilla.com>
Nick Desaulniers <ndesaulniers@mozilla.com>
Nick Fitzgerald <fitzgen@gmail.com>
Nick Hamann <nick@wabbo.org>
Nick Howell <howellnick@gmail.com>
Nick Platt <platt.nicholas@gmail.com>
@ -750,6 +801,7 @@ Nif Ward <nif.ward@gmail.com>
Nikita Pekin <contact@nikitapek.in>
Niklas Koep <niklas.koep@gmail.com>
Niko Matsakis <niko@alum.mit.edu>
Nils Liberg <nils@nilsliberg.se>
Nils Winter <nils.winter@gmail.com>
noam <noam@clusterfoo.com>
Noam Yorav-Raphael <noamraph@gmail.com>
@ -760,10 +812,13 @@ nsf <no.smile.face@gmail.com>
nwin <nwin@users.noreply.github.com>
Oak <White-Oak@users.noreply.github.com>
OGINO Masanori <masanori.ogino@gmail.com>
OlegTsyba <idethrone1@gmail.com>
Oliver Schneider <git1984941651981@oli-obk.de>
Oliver Schneider <github6541940@oli-obk.de>
Olivier Saut <osaut@airpost.net>
olivren <o.renaud@gmx.fr>
Olle Jonsson <olle.jonsson@gmail.com>
olombard <lombard-olivier@bbox.fr>
Or Brostovski <tohava@gmail.com>
Oren Hazi <oren.hazi@gmail.com>
Or Neeman <oneeman@gmail.com>
@ -776,6 +831,7 @@ P1start <rewi-github@whanau.org>
Pablo Brasero <pablo@pablobm.com>
Palmer Cox <p@lmercox.com>
Paolo Falabella <paolo.falabella@gmail.com>
Parker Moore <parkrmoore@gmail.com>
Pascal Hertleif <killercup@gmail.com>
Patrick Reisert <kpreisert@gmail.com>
Patrick Walton <pcwalton@mimiga.net>
@ -787,6 +843,7 @@ Paul Collier <paul@paulcollier.ca>
Paul Collins <paul@ondioline.org>
Paul Crowley <paulcrowley@google.com>
Paul Faria <paul_faria@ultimatesoftware.com>
Paul Oliver <puzza007@gmail.com>
Paul Osborne <osbpau@gmail.com>
Paul Quint <DrKwint@gmail.com>
Paul Stansifer <paul.stansifer@gmail.com>
@ -795,9 +852,10 @@ Pavel Panchekha <me@pavpanchekha.com>
Pawel Olzacki <p.olzacki2@samsung.com>
Pedro Larroy <pedro.larroy@here.com>
Peer Aramillo Irizar <peer.aramillo.irizar@gmail.com>
peferron <pe.ferron@gmail.com>
Pete Hunt <petehunt@users.noreply.github.com>
Peter Atashian <retep998@gmail.com>
Peter Elmers <peter.elmers@rice.edu>
Peter Elmers <peter.elmers@yahoo.com>
Peter Hull <peterhull90@gmail.com>
Peter Marheine <peter@taricorp.net>
Peter Minten <peter@pminten.nl>
@ -839,6 +897,8 @@ Ray Clanan <rclanan@utopianconcept.com>
ray glover <ray@rayglover.net>
reedlepee <reedlepee123@gmail.com>
Reilly Watson <reillywatson@gmail.com>
Rein Henrichs <reinh@reinh.com>
Rémi Audebert <halfr@lse.epita.fr>
Remi Rampin <remirampin@gmail.com>
Renato Alves <alves.rjc@gmail.com>
Renato Riccieri Santos Zannon <renato@rrsz.com.br>
@ -876,15 +936,18 @@ Roy Frostig <rfrostig@mozilla.com>
Rüdiger Sonderfeld <ruediger@c-plusplus.de>
rundrop1 <rundrop1@zoho.com>
Russell Johnston <rpjohnst@gmail.com>
Russell McClellan <russell.mcclellan@gmail.com>
Ruud van Asseldonk <dev@veniogames.com>
Ryan Levick <ryan@6wunderkinder.com>
Ryan Mulligan <ryan@ryantm.com>
Ryan Prichard <ryan.prichard@gmail.com>
Ryan Riginding <marc.riginding@gmail.com>
Ryan Scheel <ryan.havvy@gmail.com>
Ryman <haqkrs@gmail.com>
らいどっと <ryogo.yoshimura@gmail.com>
Sae-bom Kim <sae-bom.kim@samsung.com>
Salem Talha <salem.a.talha@gmail.com>
saml <saml@users.noreply.github.com>
Samuel Chase <samebchase@gmail.com>
Samuel Neves <sneves@dei.uc.pt>
Sander Mathijs van Veen <smvv@kompiler.org>
@ -895,7 +958,7 @@ Santiago Rodriguez <sanrodari@gmail.com>
Saurabh Anand <saurabhanandiit@gmail.com>
Scott Jenkins <scottdjwales@gmail.com>
Scott Lawrence <bytbox@gmail.com>
Scott Olson <scott@scott-olson.org>
Scott Olson <scott@solson.me>
Sean Bowe <ewillbefull@gmail.com>
Sean Chalmers <sclhiannan@gmail.com>
Sean Collins <sean@cllns.com>
@ -932,6 +995,7 @@ Simon Kern <simon.kern@rwth-aachen.de>
Simon Persson <simon@flaskpost.org>
Simon Sapin <simon@exyr.org>
Simon Wollwage <mail.wollwage@gmail.com>
simplex <theemptystring@gmail.com>
Sindre Johansen <sindre@sindrejohansen.no>
sinkuu <sinkuupump@gmail.com>
Skyler <skyler.lipthay@gmail.com>
@ -945,6 +1009,7 @@ Stefan Bucur <stefan.bucur@epfl.ch>
Stefan Plantikow <stefan.plantikow@googlemail.com>
Stepan Koltsov <stepan.koltsov@gmail.com>
Sterling Greene <sterling.greene@gmail.com>
Steve Gury <steve.gury@gmail.com>
Steve Klabnik <steve@steveklabnik.com>
Steven Allen <steven@stebalien.com>
Steven Crockett <crockett.j.steven@gmail.com>
@ -952,9 +1017,11 @@ Steven De Coeyer <steven@banteng.be>
Steven Fackler <sfackler@gmail.com>
Steven Sheldon <steven@sasheldon.com>
Steven Stewart-Gallus <sstewartgallus00@langara.bc.ca>
Steven Walter <stevenrwalter@gmail.com>
Strahinja Val Markovic <val@markovic.io>
Stuart Pernsteiner <stuart@pernsteiner.org>
Subhash Bhushan <subhash.bhushan@kaybus.com>
sumito3478 <sumito3478@gmail.com>
Swaroop C H <swaroop@swaroopch.com>
Sylvestre Ledru <sylvestre@debian.org>
Tamir Duberstein <tamird@gmail.com>
@ -975,6 +1042,7 @@ Thomas Backman <serenity@exscape.org>
Thomas Bracht Laumann Jespersen <laumann.thomas@gmail.com>
Thomas Daede <daede003@umn.edu>
Thomas Jespersen <laumann.thomas@gmail.com>
Thomas Karpiniec <tk@1.21jiggawatts.net>
Tiago Nobrega <tigarmo@gmail.com>
Tibor Benke <ihrwein@gmail.com>
Till Hoeppner <till@hoeppner.ws>
@ -986,6 +1054,7 @@ Tim Kuehn <tkuehn@cmu.edu>
Timon Rapp <timon@zaeda.net>
Timothée Ravier <tim@siosm.fr>
Tim Parenti <timparenti@gmail.com>
Tim Ringenbach <tim.ringenbach@gmail.com>
Tim Taubert <tim@timtaubert.de>
tinaun <tinagma@gmail.com>
Tincan <tincann@users.noreply.github.com>
@ -1046,11 +1115,15 @@ Volker Mische <volker.mische@gmail.com>
Wade Mealing <wmealing@gmail.com>
Wangshan Lu <wisagan@gmail.com>
WebeWizard <webewizard@gmail.com>
webmobster <webmobster@users.noreply.github.com>
Wei-Ming Yang <rick68@users.noreply.github.com>
Wendell Smith <wendell.smith@yale.edu>
Wesley Wiser <wwiser@gmail.com>
whataloadofwhat <unusualmoniker@gmail.com>
wickerwaka <martin.donlon@gmail.com>
Wilfred Hughes <me@wilfred.me.uk>
Will Andrews <will@firepipe.net>
Will Engler <engler.will@gmail.com>
Will Hipschman <whipsch@gmail.com>
William Ting <io@williamting.com>
Willson Mock <willson.mock@gmail.com>
@ -1058,12 +1131,15 @@ Will <will@glozer.net>
Wojciech Ogrodowczyk <github@haikuco.de>
wonyong kim <wonyong.kim@samsung.com>
xales <xales@naveria.com>
Xuefeng Wu <benewu@gmail.com>
XuefengWu <benewu@gmail.com>
Xuefeng Wu <xfwu@thoughtworks.com>
Xue Fuqiao <xfq.free@gmail.com>
Yasuhiro Fujii <y-fujii@mimosa-pudica.net>
YawarRaza7349 <YawarRaza7349@gmail.com>
Yazhong Liu <yorkiefixer@gmail.com>
Yehuda Katz <wycats@gmail.com>
Yongqian Li <yongqli@kerrmetric.com>
York Xiang <bombless@126.com>
Young-il Choi <duddlf.choi@samsung.com>
Youngmin Yoo <youngmin.yoo@samsung.com>
@ -1071,6 +1147,7 @@ Youngsoo Son <ysson83@gmail.com>
Young Wu <doomsplayer@gmail.com>
Yuri Albuquerque <yuridenommus@gmail.com>
Yuri Kunde Schlesner <yuriks@yuriks.net>
Z1 <MazinZ1@users.noreply.github.com>
Zach Kamsler <smoo.master@gmail.com>
Zach Pomerantz <zmp@umich.edu>
Zack Corr <zack@z0w0.me>

View File

@ -83,6 +83,21 @@ feature. We use the 'fork and pull' model described there.
Please make pull requests against the `master` branch.
Compiling all of `make check` can take a while. When testing your pull request,
consider using one of the more specialized `make` targets to cut down on the
amount of time you have to wait. You need to have built the compiler at least
once before running these will work, but thats only one full build rather than
one each time.
$ make -j8 rustc-stage1 && make check-stage1
is one such example, which builds just `rustc`, and then runs the tests. If
youre adding something to the standard library, try
$ make -j8 check-stage1-std NO_REBUILD=1
This will not rebuild the compiler, but will run the tests.
All pull requests are reviewed by another person. We have a bot,
@rust-highfive, that will automatically assign a random person to review your
request.
@ -108,14 +123,18 @@ will run all the tests on every platform we support. If it all works out,
[merge-queue]: http://buildbot.rust-lang.org/homu/queue/rust
Speaking of tests, Rust has a comprehensive test suite. More information about
it can be found
[here](https://github.com/rust-lang/rust-wiki-backup/blob/master/Note-testsuite.md).
## Writing Documentation
Documentation improvements are very welcome. The source of `doc.rust-lang.org`
is located in `src/doc` in the tree, and standard API documentation is generated
from the source code itself.
Documentation pull requests function in the same as other pull requests, though
you may see a slightly different form of `r+`:
Documentation pull requests function in the same way as other pull requests,
though you may see a slightly different form of `r+`:
@bors: r+ 38fe8d2 rollup

View File

@ -62,6 +62,7 @@
# * tidy-basic - show file / line stats
# * tidy-errors - show the highest rustc error code
# * tidy-features - show the status of language and lib features
# * rustc-stage$(stage) - Only build up to a specific stage
#
# Then mix in some of these environment variables to harness the
# ultimate power of The Rust Build System.
@ -90,7 +91,7 @@
#
# # Rust recipes for build system success
#
# // Modifying libstd? Use this comment to run unit tests just on your change
# // Modifying libstd? Use this command to run unit tests just on your change
# make check-stage1-std NO_REBUILD=1 NO_BENCH=1
#
# // Added a run-pass test? Use this to test running your test

View File

@ -4,7 +4,7 @@ Rust is a fast systems programming language that guarantees
memory safety and offers painless concurrency ([no data races]).
It does not employ a garbage collector and has minimal runtime overhead.
This repo contains the code for `rustc`, the Rust compiler, as well
This repo contains the code for the compiler (`rustc`), as well
as standard libraries, tools and documentation for Rust.
[no data races]: http://blog.rust-lang.org/2015/04/10/Fearless-Concurrency.html
@ -73,7 +73,7 @@ Read ["Installing Rust"] from [The Book].
```
3. Run `mingw32_shell.bat` or `mingw64_shell.bat` from wherever you installed
MYSY2 (i.e. `C:\msys`), depending on whether you want 32-bit or 64-bit Rust.
MSYS2 (i.e. `C:\msys`), depending on whether you want 32-bit or 64-bit Rust.
4. Navigate to Rust's source code, configure and build it:

View File

@ -1,3 +1,150 @@
Version 1.2.0 (August 2015)
===========================
* ~1200 changes, numerous bugfixes
Highlights
----------
* [Dynamically-sized-type coercions][dst] allow smart pointer types
like `Rc` to contain types without a fixed size, arrays and trait
objects, finally enabling use of `Rc<[T]>` and completing the
implementation of DST.
* [Parallel codegen][parcodegen] is now working again, which can
substantially speed up large builds in debug mode; It also gets
another ~33% speedup when bootstrapping on a 4 core machine (using 8
jobs). It's not enabled by default, but will be "in the near
future". It can be activated with the `-C codegen-units=N` flag to
`rustc`.
Breaking Changes
----------------
* The [`to_uppercase`] and [`to_lowercase`] methods on `char` now do
unicode case mapping, which is a previously-planned change in
behavior and considered a bugfix.
* [`mem::align_of`] now specifies [the *minimum alignment* for
T][align], which is usually the alignment programs are interested
in, and the same value reported by clang's
`alignof`. [`mem::min_align_of`] is deprecated. This is not known to
break real code.
* [The `#[packed]` attribute is no longer silently accepted by the
compiler][packed]. This attribute did nothing and code that
mentioned it likely did not work as intended.
Language
--------
* Patterns with `ref mut` now correctly invoke [`DerefMut`] when
matching against dereferencable values.
Libraries
---------
* The [`Extend`] trait, which grows a collection from an iterator, is
implemented over iterators of references, for `String`, `Vec`,
`LinkedList`, `VecDeque`, `EnumSet`, `BinaryHeap`, `VecMap`,
`BTreeSet` and `BTreeMap`. [RFC][extend-rfc].
* The [`iter::once`] function returns an iterator that yields a single
element.
* The [`iter::empty`] function returns an iterator that yields no
elements.
* The [`matches`] and [`rmatches`] methods on `str` return iterators
over substring matches.
* [`Cell`] and [`RefCell`] both implement [`Eq`].
* A number of methods for wrapping arithmetic are added to the
integral types, [`wrapping_div`], [`wrapping_rem`],
[`wrapping_neg`], [`wrapping_shl`], [`wrapping_shr`]. These are in
addition to the existing [`wrapping_add`], [`wrapping_sub`], and
[`wrapping_mul`] methods, and alternatives to the [`Wrapping`]
type.. It is illegal for the default arithmetic operations in Rust
to overflow; the desire to wrap must be explicit.
* The `{:#?}` formatting specifier [displays the alternate,
pretty-printed][debugfmt] form of the `Debug` formatter. This
feature was actually introduced prior to 1.0 with little
fanfare.
* [`fmt::Formatter`] implements [`fmt::Write`], a `fmt`-specific trait
for writing data to formatted strings, similar to [`io::Write`].
* [`fmt::Formatter`] adds 'debug builder' methods, [`debug_struct`],
[`debug_tuple`], [`debug_list`], [`debug_set`], [`debug_map`]. These
are used by code generators to emit implementations of [`Debug`].
* `str` has new [`to_uppercase`][strup] and [`to_lowercase`][strlow]
methods that convert case, following Unicode case mapping.
* It is now easier to handle to poisoned locks. The [`PoisonError`]
type, returned by failing lock operations, exposes `into_inner`,
`get_ref`, and `get_mut`, which all give access to the inner lock
guard, and allow the poisoned lock to continue to operate. The
`is_poisoned` method of [`RwLock`] and [`Mutex`] can poll for a
poisoned lock without attempting to take the lock.
* On Unix the [`FromRawFd`] trait is implemented for [`Stdio`], and
[`AsRawFd`] for [`ChildStdin`], [`ChildStdout`], [`ChildStderr`].
On Windows the `FromRawHandle` trait is implemented for `Stdio`,
and `AsRawHandle` for `ChildStdin`, `ChildStdout`,
`ChildStderr`.
* [`io::ErrorKind`] has a new variant, `InvalidData`, which indicates
malformed input.
Misc
----
* `rustc` employs smarter heuristics for guessing at [typos].
* `rustc` emits more efficient code for [no-op conversions between
unsafe pointers][nop].
* Fat pointers are now [passed in pairs of immediate arguments][fat],
resulting in faster compile times and smaller code.
[`Extend`]: http://doc.rust-lang.org/nightly/std/iter/trait.Extend.html
[extend-rfc]: https://github.com/rust-lang/rfcs/blob/master/text/0839-embrace-extend-extinguish.md
[`iter::once`]: http://doc.rust-lang.org/nightly/std/iter/fn.once.html
[`iter::empty`]: http://doc.rust-lang.org/nightly/std/iter/fn.empty.html
[`matches`]: http://doc.rust-lang.org/nightly/std/primitive.str.html#method.matches
[`rmatches`]: http://doc.rust-lang.org/nightly/std/primitive.str.html#method.rmatches
[`Cell`]: http://doc.rust-lang.org/nightly/std/cell/struct.Cell.html
[`RefCell`]: http://doc.rust-lang.org/nightly/std/cell/struct.RefCell.html
[`wrapping_add`]: http://doc.rust-lang.org/nightly/std/primitive.i8.html#method.wrapping_add
[`wrapping_sub`]: http://doc.rust-lang.org/nightly/std/primitive.i8.html#method.wrapping_sub
[`wrapping_mul`]: http://doc.rust-lang.org/nightly/std/primitive.i8.html#method.wrapping_mul
[`wrapping_div`]: http://doc.rust-lang.org/nightly/std/primitive.i8.html#method.wrapping_div
[`wrapping_rem`]: http://doc.rust-lang.org/nightly/std/primitive.i8.html#method.wrapping_rem
[`wrapping_neg`]: http://doc.rust-lang.org/nightly/std/primitive.i8.html#method.wrapping_neg
[`wrapping_shl`]: http://doc.rust-lang.org/nightly/std/primitive.i8.html#method.wrapping_shl
[`wrapping_shr`]: http://doc.rust-lang.org/nightly/std/primitive.i8.html#method.wrapping_shr
[`Wrapping`]: http://doc.rust-lang.org/nightly/std/num/struct.Wrapping.html
[`fmt::Formatter`]: http://doc.rust-lang.org/nightly/std/fmt/struct.Formatter.html
[`fmt::Write`]: http://doc.rust-lang.org/nightly/std/fmt/trait.Write.html
[`io::Write`]: http://doc.rust-lang.org/nightly/std/io/trait.Write.html
[`debug_struct`]: http://doc.rust-lang.org/nightly/core/fmt/struct.Formatter.html#method.debug_struct
[`debug_tuple`]: http://doc.rust-lang.org/nightly/core/fmt/struct.Formatter.html#method.debug_tuple
[`debug_list`]: http://doc.rust-lang.org/nightly/core/fmt/struct.Formatter.html#method.debug_list
[`debug_set`]: http://doc.rust-lang.org/nightly/core/fmt/struct.Formatter.html#method.debug_set
[`debug_map`]: http://doc.rust-lang.org/nightly/core/fmt/struct.Formatter.html#method.debug_map
[`Debug`]: http://doc.rust-lang.org/nightly/std/fmt/trait.Debug.html
[strup]: http://doc.rust-lang.org/nightly/std/primitive.str.html#method.to_uppercase
[strlow]: http://doc.rust-lang.org/nightly/std/primitive.str.html#method.to_lowercase
[`to_uppercase`]: http://doc.rust-lang.org/nightly/std/primitive.char.html#method.to_uppercase
[`to_lowercase`]: http://doc.rust-lang.org/nightly/std/primitive.char.html#method.to_lowercase
[`PoisonError`]: http://doc.rust-lang.org/nightly/std/sync/struct.PoisonError.html
[`RwLock`]: http://doc.rust-lang.org/nightly/std/sync/struct.RwLock.html
[`Mutex`]: http://doc.rust-lang.org/nightly/std/sync/struct.Mutex.html
[`FromRawFd`]: http://doc.rust-lang.org/nightly/std/os/unix/io/trait.FromRawFd.html
[`AsRawFd`]: http://doc.rust-lang.org/nightly/std/os/unix/io/trait.AsRawFd.html
[`Stdio`]: http://doc.rust-lang.org/nightly/std/process/struct.Stdio.html
[`ChildStdin`]: http://doc.rust-lang.org/nightly/std/process/struct.ChildStdin.html
[`ChildStdout`]: http://doc.rust-lang.org/nightly/std/process/struct.ChildStdout.html
[`ChildStderr`]: http://doc.rust-lang.org/nightly/std/process/struct.ChildStderr.html
[`io::ErrorKind`]: http://doc.rust-lang.org/nightly/std/io/enum.ErrorKind.html
[debugfmt]: https://www.reddit.com/r/rust/comments/3ceaui/psa_produces_prettyprinted_debug_output/
[`DerefMut`]: http://doc.rust-lang.org/nightly/std/ops/trait.DerefMut.html
[`mem::align_of`]: http://doc.rust-lang.org/nightly/std/mem/fn.align_of.html
[align]: https://github.com/rust-lang/rust/pull/25646
[`mem::min_align_of`]: http://doc.rust-lang.org/nightly/std/mem/fn.min_align_of.html
[typos]: https://github.com/rust-lang/rust/pull/26087
[nop]: https://github.com/rust-lang/rust/pull/26336
[fat]: https://github.com/rust-lang/rust/pull/26411
[dst]: https://github.com/rust-lang/rfcs/blob/master/text/0982-dst-coercion.md
[parcodegen]: https://github.com/rust-lang/rust/pull/26018
[packed]: https://github.com/rust-lang/rust/pull/25541
Version 1.1.0 (June 2015)
=========================
@ -6,17 +153,16 @@ Version 1.1.0 (June 2015)
Highlights
----------
* The [`std::fs` module has been expanded][fs-expand] to expand the set of
* The [`std::fs` module has been expanded][fs] to expand the set of
functionality exposed:
* `DirEntry` now supports optimizations like `file_type` and `metadata` which
don't incur a syscall on some platforms.
* A `symlink_metadata` function has been added.
* The `fs::Metadata` structure now lowers to its OS counterpart, providing
access to all underlying information.
* The compiler contains extended explanations of many errors. When it
emits such an error it also suggests using the `--explain` flag to
read the extended explanations, which are also [cataloged on the web
site][err].
* The compiler now contains extended explanations of many errors. When an error
with an explanation occurs the compiler suggests using the `--explain` flag
to read the explanation. Error explanations are also [available online][err-index].
* Thanks to multiple [improvements][sk] to [type checking][pre], as
well as other work, the time to bootstrap the compiler decreased by
32%.
@ -24,11 +170,11 @@ Highlights
Libraries
---------
* The `str::split_whitespace` method splits a string on unicode
* The [`str::split_whitespace`] method splits a string on unicode
whitespace boundaries.
* On both Windows and Unix, new extension traits provide conversion of
I/O types to and from the underlying system handles. On Unix, these
traits are [`FrowRawFd`] and [`AsRawFd`], on Windows `FromRawHandle`
traits are [`FromRawFd`] and [`AsRawFd`], on Windows `FromRawHandle`
and `AsRawHandle`. These are implemented for `File`, `TcpStream`,
`TcpListener`, and `UpdSocket`. Further implementations for
`std::process` will be stabilized later.
@ -80,15 +226,14 @@ Misc
* [The `drop_with_repr_extern` lint warns about mixing `repr(C)`
with `Drop`][drop].
[`split_whitespace`]: http://doc.rust-lang.org/nightly/std/primitive.str.html#method.split_whitespace
[`Iterator::cloned`]: http://doc.rust-lang.org/nightly/core/iter/trait.Iterator.html#method.cloned
[`str::split_whitespace`]: http://doc.rust-lang.org/nightly/std/primitive.str.html#method.split_whitespace
[`FromRawFd`]: http://doc.rust-lang.org/nightly/std/os/unix/io/trait.FromRawFd.html
[`AsRawFd`]: http://doc.rust-lang.org/nightly/std/os/unix/io/trait.AsRawFd.html
[`std::os::unix::symlink`]: http://doc.rust-lang.org/nightly/std/os/unix/fs/fn.symlink.html
[`IntoIterator`]: http://doc.rust-lang.org/nightly/std/iter/trait.IntoIterator.html
[`From`]: http://doc.rust-lang.org/nightly/std/convert/trait.From.html
[rf]: https://github.com/rust-lang/rust/pull/24491
[err]: http://doc.rust-lang.org/error-index.html
[err-index]: http://doc.rust-lang.org/error-index.html
[sk]: https://github.com/rust-lang/rust/pull/24615
[pre]: https://github.com/rust-lang/rust/pull/25323
[file]: https://github.com/rust-lang/rust/pull/24598
@ -251,7 +396,6 @@ Misc
[sw]: https://github.com/rust-lang/rfcs/blob/master/text/1054-str-words.md
[th]: https://github.com/rust-lang/rfcs/blob/master/text/0909-move-thread-local-to-std-thread.md
[send-rfc]: https://github.com/rust-lang/rfcs/blob/master/text/0458-send-improvements.md
[scoped]: http://static.rust-lang.org/doc/master/std/thread/fn.scoped.html
[moar-ufcs]: https://github.com/rust-lang/rust/pull/22172
[prim-inherent]: https://github.com/rust-lang/rust/pull/23104
[overflow]: https://github.com/rust-lang/rfcs/blob/master/text/0560-integer-overflow.md
@ -261,12 +405,10 @@ Misc
[string-pattern]: https://github.com/rust-lang/rust/pull/22466
[oibit-final]: https://github.com/rust-lang/rust/pull/21689
[reflect]: https://github.com/rust-lang/rust/pull/23712
[debug-builder]: https://github.com/rust-lang/rfcs/blob/master/text/0640-debug-improvements.md
[conversion]: https://github.com/rust-lang/rfcs/pull/529
[num-traits]: https://github.com/rust-lang/rust/pull/23549
[index-value]: https://github.com/rust-lang/rust/pull/23601
[dropck]: https://github.com/rust-lang/rfcs/pull/769
[fundamental]: https://github.com/rust-lang/rfcs/pull/1023
[ci-compare]: https://gist.github.com/brson/a30a77836fbec057cbee
[fn-inherit]: https://github.com/rust-lang/rust/pull/23282
[fn-blanket]: https://github.com/rust-lang/rust/pull/23895
@ -369,7 +511,6 @@ Version 1.0.0-alpha.2 (February 2015)
[osstr]: https://github.com/rust-lang/rust/pull/21488
[osstr-rfc]: https://github.com/rust-lang/rfcs/blob/master/text/0517-io-os-reform.md
[Self]: https://github.com/rust-lang/rust/pull/22158
[ufcs]: https://github.com/rust-lang/rust/pull/21077
[ufcs-rfc]: https://github.com/rust-lang/rfcs/blob/master/text/0132-ufcs.md
[un]: https://github.com/rust-lang/rust/pull/22256

234
configure vendored
View File

@ -283,7 +283,7 @@ opt_core() {
fi
done
else
if [ ! -z "$META" ]
if [ -n "$META" ]
then
OP="$OP=<$META>"
fi
@ -317,12 +317,23 @@ envopt() {
fi
# If script or environment provided a value, save it.
if [ ! -z "$VV" ]
if [ -n "$VV" ]
then
putvar $V
fi
}
enable_if_not_disabled() {
local OP=$1
local UOP=$(echo $OP | tr '[:lower:]' '[:upper:]' | tr '\-' '\_')
local ENAB_V="CFG_ENABLE_$UOP"
local EXPLICITLY_DISABLED="CFG_DISABLE_${UOP}_PROVIDED"
eval VV=\$$EXPLICITLY_DISABLED
if [ -z "$VV" ]; then
eval $ENAB_V=1
fi
}
to_llvm_triple() {
case $1 in
i686-w64-mingw32) echo i686-pc-windows-gnu ;;
@ -405,6 +416,10 @@ case $CFG_OSTYPE in
CFG_OSTYPE=unknown-openbsd
;;
NetBSD)
CFG_OSTYPE=unknown-netbsd
;;
Darwin)
CFG_OSTYPE=apple-darwin
;;
@ -667,10 +682,12 @@ if [ -n "$CFG_ENABLE_DEBUG" ]; then
CFG_DISABLE_OPTIMIZE=1
CFG_DISABLE_OPTIMIZE_CXX=1
fi
CFG_ENABLE_DEBUG_ASSERTIONS=1
CFG_ENABLE_DEBUG_JEMALLOC=1
CFG_ENABLE_DEBUGINFO=1
CFG_ENABLE_LLVM_ASSERTIONS=1
# Set following variables to 1 unless setting already provided
enable_if_not_disabled debug-assertions
enable_if_not_disabled debug-jemalloc
enable_if_not_disabled debuginfo
enable_if_not_disabled llvm-assertions
fi
# OK, now write the debugging options
@ -750,7 +767,7 @@ probe CFG_LLDB lldb
# On MacOS X, invoking `javac` pops up a dialog if the JDK is not
# installed. Since `javac` is only used if `antlr4` is available,
# probe for it only in this case.
if [ ! -z "$CFG_ANTLR4" ]
if [ -n "$CFG_ANTLR4" ]
then
probe CFG_JAVAC javac
fi
@ -769,14 +786,14 @@ then
fi
fi
if [ ! -z "$CFG_GDB" ]
if [ -n "$CFG_GDB" ]
then
# Store GDB's version
CFG_GDB_VERSION=$($CFG_GDB --version 2>/dev/null | head -1)
putvar CFG_GDB_VERSION
fi
if [ ! -z "$CFG_LLDB" ]
if [ -n "$CFG_LLDB" ]
then
# Store LLDB's version
CFG_LLDB_VERSION=$($CFG_LLDB --version 2>/dev/null | head -1)
@ -802,7 +819,7 @@ step_msg "looking for target specific programs"
probe CFG_ADB adb
if [ ! -z "$CFG_PANDOC" ]
if [ -n "$CFG_PANDOC" ]
then
# Extract "MAJOR MINOR" from Pandoc's version number
PV_MAJOR_MINOR=$(pandoc --version | grep '^pandoc' |
@ -828,7 +845,7 @@ then
BIN_SUF=.exe
fi
if [ ! -z "$CFG_ENABLE_LOCAL_RUST" ]
if [ -n "$CFG_ENABLE_LOCAL_RUST" ]
then
system_rustc=$(which rustc)
if [ -f ${CFG_LOCAL_RUST_ROOT}/bin/rustc${BIN_SUF} ]
@ -899,20 +916,32 @@ then
fi
fi
# If the clang isn't already enabled, check for GCC, and if it is missing, turn
# on clang as a backup.
if [ -z "$CFG_ENABLE_CLANG" ]
then
CFG_GCC_VERSION=$("$CFG_GCC" --version 2>&1)
if [ $? -ne 0 ]
then
step_msg "GCC not installed, will try using Clang"
CFG_ENABLE_CLANG=1
fi
fi
# Okay, at this point, we have made up our minds about whether we are
# going to force CFG_ENABLE_CLANG or not; save the setting if so.
if [ ! -z "$CFG_ENABLE_CLANG" ]
if [ -n "$CFG_ENABLE_CLANG" ]
then
putvar CFG_ENABLE_CLANG
fi
# Same with jemalloc. save the setting here.
if [ ! -z "$CFG_DISABLE_JEMALLOC" ]
if [ -n "$CFG_DISABLE_JEMALLOC" ]
then
putvar CFG_DISABLE_JEMALLOC
fi
if [ ! -z "$CFG_LLVM_ROOT" -a -z "$CFG_DISABLE_LLVM_VERSION_CHECK" -a -e "$CFG_LLVM_ROOT/bin/llvm-config" ]
if [ -n "$CFG_LLVM_ROOT" -a -z "$CFG_DISABLE_LLVM_VERSION_CHECK" -a -e "$CFG_LLVM_ROOT/bin/llvm-config" ]
then
step_msg "using custom LLVM at $CFG_LLVM_ROOT"
@ -941,7 +970,7 @@ fi
# CFG_ENABLE_CLANG is set, that indicates that we are opting into
# running such safeguards.
if [ ! -z "$CC" ]
if [ -n "$CC" ]
then
msg "skipping compiler inference steps; using provided CC=$CC"
CFG_CC="$CC"
@ -954,7 +983,7 @@ then
putvar CFG_USING_CLANG
fi
else
if [ ! -z "$CFG_ENABLE_CLANG" ]
if [ -n "$CFG_ENABLE_CLANG" ]
then
if [ -z "$CFG_CLANG" ]
then
@ -968,47 +997,59 @@ else
fi
fi
if [ ! -z "$CFG_ENABLE_CLANG" ]
if [ -n "$CFG_ENABLE_CLANG" ]
then
case "$CC" in
(''|*clang)
CFG_CLANG_VERSION=$($CFG_CC \
--version \
| grep version \
| sed 's/.*\(version .*\)/\1/; s/.*based on \(LLVM .*\))/\1/' \
| cut -d ' ' -f 2)
CFG_CLANG_REPORTED_VERSION=$($CFG_CC --version | grep version)
case $CFG_CLANG_VERSION in
(3.2* | 3.3* | 3.4* | 3.5* | 3.6* | 3.7*)
step_msg "found ok version of CLANG: $CFG_CLANG_VERSION"
if [ -z "$CC" ]
then
CFG_CC="clang"
CFG_CXX="clang++"
fi
;;
(*)
err "bad CLANG version: $CFG_CLANG_VERSION, need >=3.0svn"
;;
esac
;;
(*)
msg "skipping CFG_ENABLE_CLANG version check; provided CC=$CC"
;;
if [[ $CFG_CLANG_REPORTED_VERSION == *"(based on LLVM "* ]]
then
CFG_CLANG_VERSION=$(echo $CFG_CLANG_REPORTED_VERSION | sed 's/.*(based on LLVM \(.*\))/\1/')
elif [[ $CFG_CLANG_REPORTED_VERSION == "Apple LLVM"* ]]
then
CFG_OSX_CLANG_VERSION=$(echo $CFG_CLANG_REPORTED_VERSION | sed 's/.*version \(.*\) .*/\1/')
else
CFG_CLANG_VERSION=$(echo $CFG_CLANG_REPORTED_VERSION | sed 's/.*version \(.*\) .*/\1/')
fi
if [ -n "$CFG_OSX_CLANG_VERSION" ]
then
case $CFG_OSX_CLANG_VERSION in
(7.0*)
step_msg "found ok version of APPLE CLANG: $CFG_OSX_CLANG_VERSION"
;;
(*)
err "bad APPLE CLANG version: $CFG_OSX_CLANG_VERSION, need >=7.0"
;;
esac
else
case $CFG_CLANG_VERSION in
(3.2* | 3.3* | 3.4* | 3.5* | 3.6* | 3.7*)
step_msg "found ok version of CLANG: $CFG_CLANG_VERSION"
;;
(*)
err "bad CLANG version: $CFG_CLANG_VERSION, need >=3.0svn"
;;
esac
fi
if [ -z "$CC" ]
then
CFG_CC="clang"
CFG_CXX="clang++"
fi
esac
fi
if [ ! -z "$CFG_ENABLE_CCACHE" ]
if [ -n "$CFG_ENABLE_CCACHE" ]
then
if [ -z "$CC" ]
if [ -z "$CFG_CCACHE" ]
then
if [ -z "$CFG_CCACHE" ]
then
err "ccache requested but not found"
fi
CFG_CC="ccache $CFG_CC"
err "ccache requested but not found"
fi
CFG_CC="ccache $CFG_CC"
fi
if [ -z "$CC" -a -z "$CFG_ENABLE_CLANG" -a -z "$CFG_GCC" ]
@ -1102,7 +1143,7 @@ do
fi
;;
x86_64-*-msvc)
*-msvc)
# Currently the build system is not configured to build jemalloc
# with MSVC, so we omit this optional dependency.
step_msg "targeting MSVC, disabling jemalloc"
@ -1142,22 +1183,45 @@ do
CFG_MSVC_ROOT=$(echo "$install" | grep InstallDir | sed 's/.*REG_SZ[ ]*//')
CFG_MSVC_ROOT=$(dirname "$CFG_MSVC_ROOT")
CFG_MSVC_ROOT=$(dirname "$CFG_MSVC_ROOT")
CFG_MSVC_CL="${CFG_MSVC_ROOT}/VC/bin/amd64/cl.exe"
CFG_MSVC_LIB="${CFG_MSVC_ROOT}/VC/bin/amd64/lib.exe"
CFG_MSVC_LINK="${CFG_MSVC_ROOT}/VC/bin/amd64/link.exe"
putvar CFG_MSVC_ROOT
case $i in
x86_64-*)
bits=x86_64
msvc_part=amd64
;;
i686-*)
bits=i386
msvc_part=
;;
*)
err "can only target x86 targets for MSVC"
;;
esac
bindir="${CFG_MSVC_ROOT}/VC/bin"
if [ -n "$msvc_part" ]; then
bindir="$bindir/$msvc_part"
fi
eval CFG_MSVC_BINDIR_$bits="\"$bindir\""
eval CFG_MSVC_CL_$bits="\"$bindir/cl.exe\""
eval CFG_MSVC_LIB_$bits="\"$bindir/lib.exe\""
eval CFG_MSVC_LINK_$bits="\"$bindir/link.exe\""
vcvarsall="${CFG_MSVC_ROOT}/VC/vcvarsall.bat"
CFG_MSVC_INCLUDE_PATH=$(cmd /c "\"$vcvarsall\" amd64 && cmd /c echo %INCLUDE%")
include_path=$(cmd /c "\"$vcvarsall\" $msvc_part && cmd /c echo %INCLUDE%")
need_ok "failed to learn about MSVC's INCLUDE"
CFG_MSVC_LIB_PATH=$(cmd /c "\"$vcvarsall\" amd64 && cmd /c echo %LIB%")
lib_path=$(cmd /c "\"$vcvarsall\" $msvc_part && cmd /c echo %LIB%")
need_ok "failed to learn about MSVC's LIB"
putvar CFG_MSVC_ROOT
putvar CFG_MSVC_CL
putvar CFG_MSVC_LIB
putvar CFG_MSVC_LINK
putvar CFG_MSVC_INCLUDE_PATH
putvar CFG_MSVC_LIB_PATH
eval CFG_MSVC_INCLUDE_PATH_${bits}="\"$include_path\""
eval CFG_MSVC_LIB_PATH_${bits}="\"$lib_path\""
putvar CFG_MSVC_BINDIR_${bits}
putvar CFG_MSVC_CL_${bits}
putvar CFG_MSVC_LIB_${bits}
putvar CFG_MSVC_LINK_${bits}
putvar CFG_MSVC_INCLUDE_PATH_${bits}
putvar CFG_MSVC_LIB_PATH_${bits}
;;
*)
@ -1165,7 +1229,7 @@ do
esac
done
if [ ! -z "$CFG_PERF" ]
if [ -n "$CFG_PERF" ]
then
HAVE_PERF_LOGFD=`$CFG_PERF stat --log-fd 2>&1 | grep 'unknown option'`
if [ -z "$HAVE_PERF_LOGFD" ];
@ -1275,11 +1339,11 @@ then
"${CFG_GIT}" submodule init
# Disable submodules that we're not using
if [ ! -z "${CFG_LLVM_ROOT}" ]; then
if [ -n "${CFG_LLVM_ROOT}" ]; then
msg "git: submodule deinit src/llvm"
"${CFG_GIT}" submodule deinit src/llvm
fi
if [ ! -z "${CFG_JEMALLOC_ROOT}" ]; then
if [ -n "${CFG_JEMALLOC_ROOT}" ]; then
msg "git: submodule deinit src/jemalloc"
"${CFG_GIT}" submodule deinit src/jemalloc
fi
@ -1326,7 +1390,7 @@ do
if [ -z $CFG_LLVM_ROOT ]
then
LLVM_BUILD_DIR=${CFG_BUILD_DIR}$t/llvm
if [ ! -z "$CFG_DISABLE_OPTIMIZE_LLVM" ]
if [ -n "$CFG_DISABLE_OPTIMIZE_LLVM" ]
then
LLVM_DBG_OPTS="--enable-debug-symbols --disable-optimized"
# Just use LLVM straight from its build directory to
@ -1382,7 +1446,7 @@ do
msg "configuring LLVM for $t with cmake"
CMAKE_ARGS="-DLLVM_INCLUDE_TESTS=OFF"
if [ ! -z "$CFG_DISABLE_OPTIMIZE_LLVM" ]; then
if [ -n "$CFG_DISABLE_OPTIMIZE_LLVM" ]; then
CMAKE_ARGS="$CMAKE_ARGS -DCMAKE_BUILD_TYPE=Debug"
else
CMAKE_ARGS="$CMAKE_ARGS -DCMAKE_BUILD_TYPE=Release"
@ -1396,8 +1460,19 @@ do
msg "configuring LLVM with:"
msg "$CMAKE_ARGS"
case "$t" in
x86_64-*)
generator="Visual Studio 12 2013 Win64"
;;
i686-*)
generator="Visual Studio 12 2013"
;;
*)
err "can only build LLVM for x86 platforms"
;;
esac
(cd $LLVM_BUILD_DIR && "$CFG_CMAKE" $CFG_LLVM_SRC_DIR \
-G "Visual Studio 12 2013 Win64" \
-G "$generator" \
$CMAKE_ARGS)
need_ok "LLVM cmake configure failed"
fi
@ -1463,11 +1538,26 @@ do
(*)
msg "inferring LLVM_CXX/CC from CXX/CC = $CXX/$CC"
LLVM_CXX_32="$CXX"
LLVM_CC_32="$CC"
if [ -n "$CFG_ENABLE_CCACHE" ]
then
if [ -z "$CFG_CCACHE" ]
then
err "ccache requested but not found"
fi
LLVM_CXX_32="ccache $CXX"
LLVM_CC_32="ccache $CC"
LLVM_CXX_64="ccache $CXX"
LLVM_CC_64="ccache $CC"
else
LLVM_CXX_32="$CXX"
LLVM_CC_32="$CC"
LLVM_CXX_64="$CXX"
LLVM_CC_64="$CC"
fi
LLVM_CXX_64="$CXX"
LLVM_CC_64="$CC"
;;
esac
@ -1582,20 +1672,20 @@ putvar CFG_MANDIR
# Avoid spurious warnings from clang by feeding it original source on
# ccache-miss rather than preprocessed input.
if [ ! -z "$CFG_ENABLE_CCACHE" ] && [ ! -z "$CFG_USING_CLANG" ]
if [ -n "$CFG_ENABLE_CCACHE" ] && [ -n "$CFG_USING_CLANG" ]
then
CFG_CCACHE_CPP2=1
putvar CFG_CCACHE_CPP2
fi
if [ ! -z "$CFG_ENABLE_CCACHE" ]
if [ -n "$CFG_ENABLE_CCACHE" ]
then
CFG_CCACHE_BASEDIR=${CFG_SRC_DIR}
putvar CFG_CCACHE_BASEDIR
fi
if [ ! -z $BAD_PANDOC ]
if [ -n $BAD_PANDOC ]
then
CFG_PANDOC=
putvar CFG_PANDOC

View File

@ -0,0 +1,29 @@
# i686-pc-windows-msvc configuration
CC_i686-pc-windows-msvc="$(CFG_MSVC_CL_i386)" -nologo
LINK_i686-pc-windows-msvc="$(CFG_MSVC_LINK_i386)" -nologo
CXX_i686-pc-windows-msvc="$(CFG_MSVC_CL_i386)" -nologo
CPP_i686-pc-windows-msvc="$(CFG_MSVC_CL_i386)" -nologo
AR_i686-pc-windows-msvc="$(CFG_MSVC_LIB_i386)" -nologo
CFG_LIB_NAME_i686-pc-windows-msvc=$(1).dll
CFG_STATIC_LIB_NAME_i686-pc-windows-msvc=$(1).lib
CFG_LIB_GLOB_i686-pc-windows-msvc=$(1)-*.{dll,lib}
CFG_LIB_DSYM_GLOB_i686-pc-windows-msvc=$(1)-*.dylib.dSYM
CFG_JEMALLOC_CFLAGS_i686-pc-windows-msvc :=
CFG_GCCISH_CFLAGS_i686-pc-windows-msvc := -MD
CFG_GCCISH_CXXFLAGS_i686-pc-windows-msvc := -MD
CFG_GCCISH_LINK_FLAGS_i686-pc-windows-msvc :=
CFG_GCCISH_DEF_FLAG_i686-pc-windows-msvc :=
CFG_LLC_FLAGS_i686-pc-windows-msvc :=
CFG_INSTALL_NAME_i686-pc-windows-msvc =
CFG_EXE_SUFFIX_i686-pc-windows-msvc := .exe
CFG_WINDOWSY_i686-pc-windows-msvc := 1
CFG_UNIXY_i686-pc-windows-msvc :=
CFG_LDPATH_i686-pc-windows-msvc :=
CFG_RUN_i686-pc-windows-msvc=$(2)
CFG_RUN_TARG_i686-pc-windows-msvc=$(call CFG_RUN_i686-pc-windows-msvc,,$(2))
CFG_GNU_TRIPLE_i686-pc-windows-msvc := i686-pc-win32
# All windows nightiles are currently a GNU triple, so this MSVC triple is not
# bootstrapping from itself. This is relevant during stage0, and other parts of
# the build system take this into account.
BOOTSTRAP_FROM_i686-pc-windows-msvc := i686-pc-windows-gnu

View File

@ -0,0 +1,22 @@
# i686-unknown-freebsd configuration
CC_i686-unknown-freebsd=$(CC)
CXX_i686-unknown-freebsd=$(CXX)
CPP_i686-unknown-freebsd=$(CPP)
AR_i686-unknown-freebsd=$(AR)
CFG_LIB_NAME_i686-unknown-freebsd=lib$(1).so
CFG_STATIC_LIB_NAME_i686-unknown-freebsd=lib$(1).a
CFG_LIB_GLOB_i686-unknown-freebsd=lib$(1)-*.so
CFG_LIB_DSYM_GLOB_i686-unknown-freebsd=$(1)-*.dylib.dSYM
CFG_JEMALLOC_CFLAGS_i686-unknown-freebsd := -m32 -arch i386 -I/usr/local/include $(CFLAGS)
CFG_GCCISH_CFLAGS_i686-unknown-freebsd := -Wall -Werror -g -fPIC -m32 -arch i386 -I/usr/local/include $(CFLAGS)
CFG_GCCISH_LINK_FLAGS_i686-unknown-freebsd := -m32 -shared -fPIC -g -pthread -lrt
CFG_GCCISH_DEF_FLAG_i686-unknown-freebsd := -Wl,--export-dynamic,--dynamic-list=
CFG_LLC_FLAGS_i686-unknown-freebsd :=
CFG_INSTALL_NAME_i686-unknown-freebsd =
CFG_EXE_SUFFIX_i686-unknown-freebsd :=
CFG_WINDOWSY_i686-unknown-freebsd :=
CFG_UNIXY_i686-unknown-freebsd := 1
CFG_LDPATH_i686-unknown-freebsd :=
CFG_RUN_i686-unknown-freebsd=$(2)
CFG_RUN_TARG_i686-unknown-freebsd=$(call CFG_RUN_i686-unknown-freebsd,,$(2))
CFG_GNU_TRIPLE_i686-unknown-freebsd := i686-unknown-freebsd

View File

@ -1,9 +1,9 @@
# x86_64-pc-windows-msvc configuration
CC_x86_64-pc-windows-msvc="$(CFG_MSVC_CL)" -nologo
LINK_x86_64-pc-windows-msvc="$(CFG_MSVC_LINK)" -nologo
CXX_x86_64-pc-windows-msvc="$(CFG_MSVC_CL)" -nologo
CPP_x86_64-pc-windows-msvc="$(CFG_MSVC_CL)" -nologo
AR_x86_64-pc-windows-msvc="$(CFG_MSVC_LIB)" -nologo
CC_x86_64-pc-windows-msvc="$(CFG_MSVC_CL_x86_64)" -nologo
LINK_x86_64-pc-windows-msvc="$(CFG_MSVC_LINK_x86_64)" -nologo
CXX_x86_64-pc-windows-msvc="$(CFG_MSVC_CL_x86_64)" -nologo
CPP_x86_64-pc-windows-msvc="$(CFG_MSVC_CL_x86_64)" -nologo
AR_x86_64-pc-windows-msvc="$(CFG_MSVC_LIB_x86_64)" -nologo
CFG_LIB_NAME_x86_64-pc-windows-msvc=$(1).dll
CFG_STATIC_LIB_NAME_x86_64-pc-windows-msvc=$(1).lib
CFG_LIB_GLOB_x86_64-pc-windows-msvc=$(1)-*.{dll,lib}
@ -23,64 +23,6 @@ CFG_RUN_x86_64-pc-windows-msvc=$(2)
CFG_RUN_TARG_x86_64-pc-windows-msvc=$(call CFG_RUN_x86_64-pc-windows-msvc,,$(2))
CFG_GNU_TRIPLE_x86_64-pc-windows-msvc := x86_64-pc-win32
# These two environment variables are scraped by the `./configure` script and
# are necessary for `cl.exe` to find standard headers (the INCLUDE variable) and
# for `link.exe` to find standard libraries (the LIB variable).
ifdef CFG_MSVC_INCLUDE_PATH
export INCLUDE := $(CFG_MSVC_INCLUDE_PATH)
endif
ifdef CFG_MSVC_LIB_PATH
export LIB := $(CFG_MSVC_LIB_PATH)
endif
# Unfortunately `link.exe` is also a program in `/usr/bin` on MinGW installs,
# but it's not the one that we want. As a result we make sure that our detected
# `link.exe` shows up in PATH first.
ifdef CFG_MSVC_LINK
export PATH := $(CFG_MSVC_ROOT)/VC/bin/amd64:$(PATH)
endif
# There are more comments about this available in the target specification for
# Windows MSVC in the compiler, but the gist of it is that we use `llvm-ar.exe`
# instead of `lib.exe` for assembling archives, so we need to inject this custom
# dependency here.
NATIVE_TOOL_DEPS_core_T_x86_64-pc-windows-msvc += llvm-ar.exe
INSTALLED_BINS_x86_64-pc-windows-msvc += llvm-ar.exe
# When working with MSVC on windows, each DLL needs to explicitly declare its
# interface to the outside world through some means. The options for doing so
# include:
#
# 1. A custom attribute on each function itself
# 2. A linker argument saying what to export
# 3. A file which lists all symbols that need to be exported
#
# The Rust compiler takes care (1) for us for all Rust code by annotating all
# public-facing functions with dllexport, but we have a few native dependencies
# which need to cross the DLL boundary. The most important of these dependencies
# is LLVM which is linked into `rustc_llvm.dll` but primarily used from
# `rustc_trans.dll`. This means that many of LLVM's C API functions need to be
# exposed from `rustc_llvm.dll` to be forwarded over the boundary.
#
# Unfortunately, at this time, LLVM does not handle this sort of exportation on
# Windows for us, so we're forced to do it ourselves if we want it (which seems
# like the path of least resistance right now). To do this we generate a `.DEF`
# file [1] which we then custom-pass to the linker when building the rustc_llvm
# crate. This DEF file list all symbols that are exported from
# `src/librustc_llvm/lib.rs` and is generated by a small python script.
#
# Fun times!
#
# [1]: https://msdn.microsoft.com/en-us/library/28d6s79h.aspx
RUSTFLAGS_rustc_llvm_T_x86_64-pc-windows-msvc += \
-C link-args="-DEF:x86_64-pc-windows-msvc/rt/rustc_llvm.def"
CUSTOM_DEPS_rustc_llvm_T_x86_64-pc-windows-msvc += \
x86_64-pc-windows-msvc/rt/rustc_llvm.def
x86_64-pc-windows-msvc/rt/rustc_llvm.def: $(S)src/etc/mklldef.py \
$(S)src/librustc_llvm/lib.rs
$(CFG_PYTHON) $^ $@ rustc_llvm-$(CFG_FILENAME_EXTRA)
# All windows nightiles are currently a GNU triple, so this MSVC triple is not
# bootstrapping from itself. This is relevant during stage0, and other parts of
# the build system take this into account.

View File

@ -0,0 +1,22 @@
# x86_64-unknown-netbsd configuration
CC_x86_64-unknown-netbsd=$(CC)
CXX_x86_64-unknown-netbsd=$(CXX)
CPP_x86_64-unknown-netbsd=$(CPP)
AR_x86_64-unknown-netbsd=$(AR)
CFG_LIB_NAME_x86_64-unknown-netbsd=lib$(1).so
CFG_STATIC_LIB_NAME_x86_64-unknown-netbsd=lib$(1).a
CFG_LIB_GLOB_x86_64-unknown-netbsd=lib$(1)-*.so
CFG_LIB_DSYM_GLOB_x86_64-unknown-netbsd=$(1)-*.dylib.dSYM
CFG_JEMALLOC_CFLAGS_x86_64-unknown-netbsd := -I/usr/local/include $(CFLAGS)
CFG_GCCISH_CFLAGS_x86_64-unknown-netbsd := -Wall -Werror -g -fPIC -I/usr/local/include $(CFLAGS)
CFG_GCCISH_LINK_FLAGS_x86_64-unknown-netbsd := -shared -fPIC -g -pthread -lrt
CFG_GCCISH_DEF_FLAG_x86_64-unknown-netbsd := -Wl,--export-dynamic,--dynamic-list=
CFG_LLC_FLAGS_x86_64-unknown-netbsd :=
CFG_INSTALL_NAME_x86_64-unknown-netbsd =
CFG_EXE_SUFFIX_x86_64-unknown-netbsd :=
CFG_WINDOWSY_x86_64-unknown-netbsd :=
CFG_UNIXY_x86_64-unknown-netbsd := 1
CFG_LDPATH_x86_64-unknown-netbsd :=
CFG_RUN_x86_64-unknown-netbsd=$(2)
CFG_RUN_TARG_x86_64-unknown-netbsd=$(call CFG_RUN_x86_64-unknown-netbsd,,$(2))
CFG_GNU_TRIPLE_x86_64-unknown-netbsd := x86_64-unknown-netbsd

View File

@ -295,7 +295,6 @@ LLVM_BINDIR_$(1)=$$(shell "$$(LLVM_CONFIG_$(1))" --bindir)
LLVM_INCDIR_$(1)=$$(shell "$$(LLVM_CONFIG_$(1))" --includedir)
LLVM_LIBDIR_$(1)=$$(shell "$$(LLVM_CONFIG_$(1))" --libdir)
LLVM_LIBDIR_RUSTFLAGS_$(1)=-L "$$(LLVM_LIBDIR_$(1))"
LLVM_LIBS_$(1)=$$(shell "$$(LLVM_CONFIG_$(1))" --libs $$(LLVM_COMPONENTS))
LLVM_LDFLAGS_$(1)=$$(shell "$$(LLVM_CONFIG_$(1))" --ldflags)
ifeq ($$(findstring freebsd,$(1)),freebsd)
# On FreeBSD, it may search wrong headers (that are for pre-installed LLVM),

View File

@ -238,3 +238,56 @@ endef
$(foreach target,$(CFG_TARGET), \
$(eval $(call CFG_MAKE_TOOLCHAIN,$(target))))
# There are more comments about this available in the target specification for
# Windows MSVC in the compiler, but the gist of it is that we use `llvm-ar.exe`
# instead of `lib.exe` for assembling archives, so we need to inject this custom
# dependency here.
define ADD_LLVM_AR_TO_MSVC_DEPS
ifeq ($$(findstring msvc,$(1)),msvc)
NATIVE_TOOL_DEPS_core_T_$(1) += llvm-ar.exe
INSTALLED_BINS_$(1) += llvm-ar.exe
endif
endef
$(foreach target,$(CFG_TARGET), \
$(eval $(call ADD_LLVM_AR_TO_MSVC_DEPS,$(target))))
# When working with MSVC on windows, each DLL needs to explicitly declare its
# interface to the outside world through some means. The options for doing so
# include:
#
# 1. A custom attribute on each function itself
# 2. A linker argument saying what to export
# 3. A file which lists all symbols that need to be exported
#
# The Rust compiler takes care (1) for us for all Rust code by annotating all
# public-facing functions with dllexport, but we have a few native dependencies
# which need to cross the DLL boundary. The most important of these dependencies
# is LLVM which is linked into `rustc_llvm.dll` but primarily used from
# `rustc_trans.dll`. This means that many of LLVM's C API functions need to be
# exposed from `rustc_llvm.dll` to be forwarded over the boundary.
#
# Unfortunately, at this time, LLVM does not handle this sort of exportation on
# Windows for us, so we're forced to do it ourselves if we want it (which seems
# like the path of least resistance right now). To do this we generate a `.DEF`
# file [1] which we then custom-pass to the linker when building the rustc_llvm
# crate. This DEF file list all symbols that are exported from
# `src/librustc_llvm/lib.rs` and is generated by a small python script.
#
# Fun times!
#
# [1]: https://msdn.microsoft.com/en-us/library/28d6s79h.aspx
define ADD_RUSTC_LLVM_DEF_TO_MSVC
ifeq ($$(findstring msvc,$(1)),msvc)
RUSTFLAGS_rustc_llvm_T_$(1) += -C link-args="-DEF:$(1)/rt/rustc_llvm.def"
CUSTOM_DEPS_rustc_llvm_T_$(1) += $(1)/rt/rustc_llvm.def
$(1)/rt/rustc_llvm.def: $$(S)src/etc/mklldef.py $$(S)src/librustc_llvm/lib.rs
$$(CFG_PYTHON) $$^ $$@ rustc_llvm-$$(CFG_FILENAME_EXTRA)
endif
endef
$(foreach target,$(CFG_TARGET), \
$(eval $(call ADD_RUSTC_LLVM_DEF_TO_MSVC,$(target))))

View File

@ -53,9 +53,7 @@ NATIVE_DEPS_hoedown_$(1) := hoedown/src/autolink.c \
NATIVE_DEPS_miniz_$(1) = miniz.c
NATIVE_DEPS_rust_builtin_$(1) := rust_builtin.c \
rust_android_dummy.c
NATIVE_DEPS_rustrt_native_$(1) := \
rust_try.ll \
arch/$$(HOST_$(1))/record_sp.S
NATIVE_DEPS_rustrt_native_$(1) := arch/$$(HOST_$(1))/record_sp.S
NATIVE_DEPS_rust_test_helpers_$(1) := rust_test_helpers.c
NATIVE_DEPS_morestack_$(1) := arch/$$(HOST_$(1))/morestack.S
@ -69,14 +67,6 @@ NATIVE_DEPS_morestack_$(1) := arch/$$(HOST_$(1))/morestack.S
RT_OUTPUT_DIR_$(1) := $(1)/rt
$$(RT_OUTPUT_DIR_$(1))/%.o: $(S)src/rt/%.ll $$(MKFILE_DEPS) \
$$(LLVM_CONFIG_$$(CFG_BUILD))
@mkdir -p $$(@D)
@$$(call E, compile: $$@)
$$(Q)$$(LLC_$$(CFG_BUILD)) $$(CFG_LLC_FLAGS_$(1)) \
-filetype=obj -mtriple=$$(CFG_LLVM_TARGET_$(1)) \
-relocation-model=pic -o $$@ $$<
$$(RT_OUTPUT_DIR_$(1))/%.o: $(S)src/rt/%.c $$(MKFILE_DEPS)
@mkdir -p $$(@D)
@$$(call E, compile: $$@)
@ -90,6 +80,17 @@ $$(RT_OUTPUT_DIR_$(1))/%.o: $(S)src/rt/%.S $$(MKFILE_DEPS) \
@mkdir -p $$(@D)
@$$(call E, compile: $$@)
$$(Q)$$(call CFG_ASSEMBLE_$(1),$$@,$$<)
# On MSVC targets the compiler's default include path (e.g. where to find system
# headers) is specified by the INCLUDE environment variable. This may not be set
# so the ./configure script scraped the relevant values and this is the location
# that we put them into cl.exe's environment.
ifeq ($$(findstring msvc,$(1)),msvc)
$$(RT_OUTPUT_DIR_$(1))/%.o: \
export INCLUDE := $$(CFG_MSVC_INCLUDE_PATH_$$(HOST_$(1)))
$(1)/rustllvm/%.o: \
export INCLUDE := $$(CFG_MSVC_INCLUDE_PATH_$$(HOST_$(1)))
endif
endef
$(foreach target,$(CFG_TARGET),$(eval $(call NATIVE_LIBRARIES,$(target))))
@ -104,7 +105,6 @@ define THIRD_PARTY_LIB
OBJS_$(2)_$(1) := $$(NATIVE_DEPS_$(2)_$(1):%=$$(RT_OUTPUT_DIR_$(1))/%)
OBJS_$(2)_$(1) := $$(OBJS_$(2)_$(1):.c=.o)
OBJS_$(2)_$(1) := $$(OBJS_$(2)_$(1):.cpp=.o)
OBJS_$(2)_$(1) := $$(OBJS_$(2)_$(1):.ll=.o)
OBJS_$(2)_$(1) := $$(OBJS_$(2)_$(1):.S=.o)
NATIVE_$(2)_$(1) := $$(call CFG_STATIC_LIB_NAME_$(1),$(2))
$$(RT_OUTPUT_DIR_$(1))/$$(NATIVE_$(2)_$(1)): $$(OBJS_$(2)_$(1))
@ -237,8 +237,12 @@ COMPRT_CFLAGS_$(1) := $$(CFG_GCCISH_CFLAGS_$(1))
ifeq ($$(findstring msvc,$(1)),msvc)
COMPRT_CC_$(1) := gcc
COMPRT_AR_$(1) := ar
ifeq ($$(findstring i686,$(1)),i686)
COMPRT_CFLAGS_$(1) := $$(CFG_GCCISH_CFLAGS_$(1)) -m32
else
COMPRT_CFLAGS_$(1) := $$(CFG_GCCISH_CFLAGS_$(1)) -m64
endif
endif
$$(COMPRT_LIB_$(1)): $$(COMPRT_DEPS) $$(MKFILE_DEPS)
@$$(call E, make: compiler-rt)

View File

@ -24,7 +24,8 @@ LLVM_EXTRA_INCDIRS_$(1)= $$(call CFG_CC_INCLUDE_$(1),$(S)src/llvm/include) \
endif
RUSTLLVM_OBJS_CS_$(1) := $$(addprefix rustllvm/, \
ExecutionEngineWrapper.cpp RustWrapper.cpp PassWrapper.cpp)
ExecutionEngineWrapper.cpp RustWrapper.cpp PassWrapper.cpp \
ArchiveWrapper.cpp)
RUSTLLVM_INCS_$(1) = $$(LLVM_EXTRA_INCDIRS_$(1)) \
$$(call CFG_CC_INCLUDE_$(1),$$(LLVM_INCDIR_$(1))) \

View File

@ -220,3 +220,38 @@ $(foreach target,$(CFG_TARGET), \
$(foreach crate,$(CRATES), \
$(foreach tool,$(NATIVE_TOOL_DEPS_$(crate)_T_$(target)), \
$(eval $(call MOVE_TOOLS_TO_SNAPSHOT_HOST_DIR,0,$(target),$(BOOTSTRAP_FROM_$(target)),$(crate),$(tool))))))
# For MSVC targets we need to set up some environment variables for the linker
# to work correctly when building Rust crates. These two variables are:
#
# - LIB tells the linker the default search path for finding system libraries,
# for example kernel32.dll
# - PATH needs to be modified to ensure that MSVC's link.exe is first in the
# path instead of MinGW's /usr/bin/link.exe (entirely unrelated)
#
# The values for these variables are detected by the configure script.
define SETUP_LIB_MSVC_ENV_VARS
ifeq ($$(findstring msvc,$(2)),msvc)
$$(TLIB$(1)_T_$(2)_H_$(3))/stamp.$(4): \
export LIB := $$(CFG_MSVC_LIB_PATH_$$(HOST_$(2)))
$$(TLIB$(1)_T_$(2)_H_$(3))/stamp.$(4): \
export PATH := $$(CFG_MSVC_BINDIR_$$(HOST_$(2))):$$(PATH)
endif
endef
define SETUP_TOOL_MSVC_ENV_VARS
ifeq ($$(findstring msvc,$(2)),msvc)
$$(TBIN$(1)_T_$(2)_H_$(3))/$(4)$$(X_$(2)): \
export LIB := $$(CFG_MSVC_LIB_PATH_$$(HOST_$(2)))
$$(TBIN$(1)_T_$(2)_H_$(3))/$(4)$$(X_$(2)): \
export PATH := $$(CFG_MSVC_BINDIR_$$(HOST_$(2))):$$(PATH)
endif
endef
$(foreach host,$(CFG_HOST), \
$(foreach target,$(CFG_TARGET), \
$(foreach crate,$(CRATES), \
$(eval $(call SETUP_LIB_MSVC_ENV_VARS,0,$(target),$(host),$(crate))))))
$(foreach host,$(CFG_HOST), \
$(foreach target,$(CFG_TARGET), \
$(foreach tool,$(TOOLS), \
$(eval $(call SETUP_TOOL_MSVC_ENV_VARS,0,$(target),$(host),$(tool))))))

View File

@ -15,7 +15,7 @@
#![feature(libc)]
#![feature(path_ext)]
#![feature(rustc_private)]
#![feature(slice_extras)]
#![feature(slice_splits)]
#![feature(str_char)]
#![feature(test)]
#![feature(vec_push_all)]
@ -90,9 +90,7 @@ pub fn parse_config(args: Vec<String> ) -> Config {
optopt("", "lldb-python-dir", "directory containing LLDB's python module", "PATH"),
optflag("h", "help", "show this message"));
assert!(!args.is_empty());
let argv0 = args[0].clone();
let args_ = args.tail();
let (argv0, args_) = args.split_first().unwrap();
if args[1] == "-h" || args[1] == "--help" {
let message = format!("Usage: {} [OPTIONS] [TESTNAME...]", argv0);
println!("{}", getopts::usage(&message, &groups));

View File

@ -344,7 +344,7 @@ fn run_debuginfo_gdb_test(config: &Config, props: &TestProps, testfile: &Path) {
check_lines,
breakpoint_lines
} = parse_debugger_commands(testfile, "gdb");
let mut cmds = commands.connect("\n");
let mut cmds = commands.join("\n");
// compile test file (it should have 'compile-flags:-g' in the header)
let compiler_run_result = compile_test(config, props, testfile);
@ -799,7 +799,7 @@ fn cleanup_debug_info_options(options: &Option<String>) -> Option<String> {
split_maybe_args(options).into_iter()
.filter(|x| !options_to_remove.contains(x))
.collect::<Vec<String>>()
.connect(" ");
.join(" ");
Some(new_options)
}
@ -1126,16 +1126,10 @@ impl fmt::Display for Status {
fn compile_test(config: &Config, props: &TestProps,
testfile: &Path) -> ProcRes {
compile_test_(config, props, testfile, &[])
}
fn compile_test_(config: &Config, props: &TestProps,
testfile: &Path, extra_args: &[String]) -> ProcRes {
let aux_dir = aux_output_dir_name(config, testfile);
// FIXME (#9639): This needs to handle non-utf8 paths
let mut link_args = vec!("-L".to_string(),
aux_dir.to_str().unwrap().to_string());
link_args.extend(extra_args.iter().cloned());
let link_args = vec!("-L".to_string(),
aux_dir.to_str().unwrap().to_string());
let args = make_compile_args(config,
props,
link_args,
@ -1144,7 +1138,7 @@ fn compile_test_(config: &Config, props: &TestProps,
}
fn document(config: &Config, props: &TestProps,
testfile: &Path, extra_args: &[String]) -> (ProcRes, PathBuf) {
testfile: &Path) -> (ProcRes, PathBuf) {
let aux_dir = aux_output_dir_name(config, testfile);
let out_dir = output_base_name(config, testfile);
let _ = fs::remove_dir_all(&out_dir);
@ -1154,7 +1148,6 @@ fn document(config: &Config, props: &TestProps,
"-o".to_string(),
out_dir.to_str().unwrap().to_string(),
testfile.to_str().unwrap().to_string()];
args.extend(extra_args.iter().cloned());
args.extend(split_maybe_args(&props.compile_flags));
let args = ProcArgs {
prog: config.rustdoc_path.to_str().unwrap().to_string(),
@ -1419,7 +1412,7 @@ fn make_cmdline(libpath: &str, prog: &str, args: &[String]) -> String {
// Linux and mac don't require adjusting the library search path
if cfg!(unix) {
format!("{} {}", prog, args.connect(" "))
format!("{} {}", prog, args.join(" "))
} else {
// Build the LD_LIBRARY_PATH variable as it would be seen on the command line
// for diagnostic purposes
@ -1427,7 +1420,7 @@ fn make_cmdline(libpath: &str, prog: &str, args: &[String]) -> String {
format!("{}=\"{}\"", util::lib_path_env_var(), util::make_new_path(path))
}
format!("{} {} {}", lib_path_cmd_prefix(libpath), prog, args.connect(" "))
format!("{} {} {}", lib_path_cmd_prefix(libpath), prog, args.join(" "))
}
}
@ -1709,15 +1702,18 @@ fn run_codegen_test(config: &Config, props: &TestProps, testfile: &Path) {
}
fn charset() -> &'static str {
if cfg!(any(target_os = "bitrig", target_os = "freebsd")) {
// FreeBSD 10.1 defaults to GDB 6.1.1 which doesn't support "auto" charset
if cfg!(target_os = "bitrig") {
"auto"
} else if cfg!(target_os = "freebsd") {
"ISO-8859-1"
} else {
"UTF-8"
}
}
fn run_rustdoc_test(config: &Config, props: &TestProps, testfile: &Path) {
let (proc_res, out_dir) = document(config, props, testfile, &[]);
let (proc_res, out_dir) = document(config, props, testfile);
if !proc_res.status.success() {
fatal_proc_rec("rustdoc failed!", &proc_res);
}

View File

@ -21,6 +21,7 @@ const OS_TABLE: &'static [(&'static str, &'static str)] = &[
("ios", "ios"),
("linux", "linux"),
("mingw32", "windows"),
("netbsd", "netbsd"),
("openbsd", "openbsd"),
("win32", "windows"),
("windows", "windows"),

View File

@ -99,7 +99,7 @@ Second, it makes cost explicit. In general, the only safe way to have a
non-exhaustive match would be to panic the thread if nothing is matched, though
it could fall through if the type of the `match` expression is `()`. This sort
of hidden cost and special casing is against the language's philosophy. It's
easy to ignore certain cases by using the `_` wildcard:
easy to ignore all unspecified cases by using the `_` wildcard:
```rust,ignore
match val.do_something() {

View File

@ -1,4 +1,7 @@
% The (old) Rust Pointer Guide
% The Rust Pointer Guide
This content has moved into
[the Rust Programming Language book](book/pointers.html).
This content has been removed, with no direct replacement. Rust only
has two built-in pointer types now,
[references](book/references-and-borrowing.html) and [raw
pointers](book/raw-pointers.html). Older Rusts had many more pointer
types, theyre gone now.

View File

@ -20,6 +20,13 @@ series of small examples.
[rbe]: http://rustbyexample.com/
# The Standard Library
We have [API documentation for the entire standard
library](std/index.html). There's a list of crates on the left with more
specific sections, or you can use the search bar at the top to search for
something if you know its name.
# Community & Getting Help
If you need help with something, or just want to talk about Rust with others,
@ -75,13 +82,6 @@ There are questions that are asked quite often, so we've made FAQs for them:
* [Project FAQ](complement-project-faq.html)
* [How to submit a bug report](https://github.com/rust-lang/rust/blob/master/CONTRIBUTING.md#bug-reports)
# The Standard Library
We have [API documentation for the entire standard
library](std/index.html). There's a list of crates on the left with more
specific sections, or you can use the search bar at the top to search for
something if you know its name.
# The Error Index
If you encounter an error while compiling your code you may be able to look it

View File

@ -338,12 +338,16 @@ type of the literal. The integer suffix must be the name of one of the
integral types: `u8`, `i8`, `u16`, `i16`, `u32`, `i32`, `u64`, `i64`,
`isize`, or `usize`.
The type of an _unsuffixed_ integer literal is determined by type inference.
If an integer type can be _uniquely_ determined from the surrounding program
context, the unsuffixed integer literal has that type. If the program context
underconstrains the type, it defaults to the signed 32-bit integer `i32`; if
the program context overconstrains the type, it is considered a static type
error.
The type of an _unsuffixed_ integer literal is determined by type inference:
* If an integer type can be _uniquely_ determined from the surrounding
program context, the unsuffixed integer literal has that type.
* If the program context under-constrains the type, it defaults to the
signed 32-bit integer `i32`.
* If the program context over-constrains the type, it is considered a
static type error.
Examples of integer literals of various forms:
@ -371,12 +375,17 @@ The suffix forcibly sets the type of the literal. There are two valid
_floating-point suffixes_, `f32` and `f64` (the 32-bit and 64-bit floating point
types), which explicitly determine the type of the literal.
The type of an _unsuffixed_ floating-point literal is determined by type
inference. If a floating-point type can be _uniquely_ determined from the
surrounding program context, the unsuffixed floating-point literal has that type.
If the program context underconstrains the type, it defaults to double-precision `f64`;
if the program context overconstrains the type, it is considered a static type
error.
The type of an _unsuffixed_ floating-point literal is determined by
type inference:
* If a floating-point type can be _uniquely_ determined from the
surrounding program context, the unsuffixed floating-point literal
has that type.
* If the program context under-constrains the type, it defaults to `f64`.
* If the program context over-constrains the type, it is considered a
static type error.
Examples of floating-point literals of various forms:
@ -582,8 +591,9 @@ always been designed to be compiled. For these reasons, this section assumes a
compiler.
Rust's semantics obey a *phase distinction* between compile-time and
run-time.[^phase-distinction] Those semantic rules that have a *static
interpretation* govern the success or failure of compilation. Those semantics
run-time.[^phase-distinction] Semantic rules that have a *static
interpretation* govern the success or failure of compilation, while
semantic rules
that have a *dynamic interpretation* govern the behavior of the program at
run-time.
@ -1047,11 +1057,8 @@ This is a list of behavior not considered *unsafe* in Rust terms, but that may
be undesired.
* Deadlocks
* Reading data from private fields (`std::repr`)
* Leaks of memory and other resources
* Exiting without calling destructors
* Sending signals
* Accessing/modifying the file system
* Integer overflow
- Overflow is considered "unexpected" behavior and is always user-error,
unless the `wrapping` primitives are used. In non-optimized builds, the compiler
@ -1286,7 +1293,7 @@ All access to a static is safe, but there are a number of restrictions on
statics:
* Statics may not contain any destructors.
* The types of static values must ascribe to `Sync` to allow threadsafe access.
* The types of static values must ascribe to `Sync` to allow thread-safe access.
* Statics may not refer to other statics by value, only by reference.
* Constants cannot refer to statics.
@ -1630,6 +1637,10 @@ The type of a function declared in an extern block is `extern "abi" fn(A1, ...,
An) -> R`, where `A1...An` are the declared types of its arguments and `R` is
the declared return type.
It is valid to add the `link` attribute on an empty extern block. You can use
this to satisfy the linking requirements of extern blocks elsewhere in your code
(including upstream crates) instead of adding the attribute to each extern block.
## Visibility and Privacy
These two terms are often used interchangeably, and what they are attempting to
@ -1688,7 +1699,7 @@ explain, here's a few use cases and what they would entail:
* A crate needs a global available "helper module" to itself, but it doesn't
want to expose the helper module as a public API. To accomplish this, the
root of the crate's hierarchy would have a private module which then
internally has a "public api". Because the entire crate is a descendant of
internally has a "public API". Because the entire crate is a descendant of
the root, then the entire local crate can access this private module through
the second case.
@ -1951,8 +1962,6 @@ macro scope.
object file that this item's contents will be placed into.
- `no_mangle` - on any item, do not apply the standard name mangling. Set the
symbol for this item to its identifier.
- `packed` - on structs or enums, eliminate any padding that would be used to
align fields.
- `simd` - on certain tuple structs, derive the arithmetic operators, which
lower to the target's SIMD instructions, if any; the `simd` feature gate
is necessary to use this attribute.
@ -2026,7 +2035,7 @@ The following configurations must be defined by the implementation:
as a configuration itself, like `unix` or `windows`.
* `target_os = "..."`. Operating system of the target, examples include
`"windows"`, `"macos"`, `"ios"`, `"linux"`, `"android"`, `"freebsd"`, `"dragonfly"`,
`"bitrig"` or `"openbsd"`.
`"bitrig"` , `"openbsd"` or `"netbsd"`.
* `target_pointer_width = "..."`. Target pointer width in bits. This is set
to `"32"` for targets with 32-bit pointers, and likewise set to `"64"` for
64-bit pointers.
@ -2360,6 +2369,8 @@ The currently implemented features of the reference compiler are:
internally without imposing on callers
(i.e. making them behave like function calls in
terms of encapsulation).
* - `default_type_parameter_fallback` - Allows type parameter defaults to
influence type inference.
If a feature is promoted to a language feature, then all existing programs will
start to receive compilation warnings about `#![feature]` directives which enabled
@ -2509,9 +2520,8 @@ Here are some examples:
#### Moved and copied types
When a [local variable](#variables) is used as an
[rvalue](#lvalues,-rvalues-and-temporaries) the variable will either be moved
or copied, depending on its type. All values whose type implements `Copy` are
copied, all others are moved.
[rvalue](#lvalues,-rvalues-and-temporaries), the variable will be copied
if its type implements `Copy`. All others are moved.
### Literal expressions
@ -2876,7 +2886,6 @@ operand.
```
# let mut x = 0;
# let y = 0;
x = y;
```
@ -2966,14 +2975,12 @@ move values (depending on their type) from the environment into the lambda
expression's captured environment.
In this example, we define a function `ten_times` that takes a higher-order
function argument, and call it with a lambda expression as an argument:
function argument, and we then call it with a lambda expression as an argument:
```
fn ten_times<F>(f: F) where F: Fn(i32) {
let mut i = 0i32;
while i < 10 {
f(i);
i += 1;
for index in 0..10 {
f(index);
}
}
@ -3322,10 +3329,13 @@ An example of a tuple type and its use:
```
type Pair<'a> = (i32, &'a str);
let p: Pair<'static> = (10, "hello");
let p: Pair<'static> = (10, "ten");
let (a, b) = p;
assert!(b != "world");
assert!(p.0 == 10);
assert_eq!(a, 10);
assert_eq!(b, "ten");
assert_eq!(p.0, 10);
assert_eq!(p.1, "ten");
```
For historical reasons and convenience, the tuple type with no elements (`()`)
@ -3335,8 +3345,8 @@ is often called unit or the unit type.
Rust has two different types for a list of items:
* `[T; N]`, an 'array'.
* `&[T]`, a 'slice'.
* `[T; N]`, an 'array'
* `&[T]`, a 'slice'
An array has a fixed size, and can be allocated on either the stack or the
heap.
@ -3344,18 +3354,23 @@ heap.
A slice is a 'view' into an array. It doesn't own the data it points
to, it borrows it.
An example of each kind:
Examples:
```{rust}
let vec: Vec<i32> = vec![1, 2, 3];
let arr: [i32; 3] = [1, 2, 3];
let s: &[i32] = &vec[..];
// A stack-allocated array
let array: [i32; 3] = [1, 2, 3];
// A heap-allocated array
let vector: Vec<i32> = vec![1, 2, 3];
// A slice into an array
let slice: &[i32] = &vector[..];
```
As you can see, the `vec!` macro allows you to create a `Vec<T>` easily. The
`vec!` macro is also part of the standard library, rather than the language.
All in-bounds elements of arrays, and slices are always initialized, and access
All in-bounds elements of arrays and slices are always initialized, and access
to an array or slice is always bounds-checked.
### Structure types
@ -3489,7 +3504,7 @@ x = bo(5,7);
#### Function types for specific items
Internally to the compiler, there are also function types that are specific to a particular
Internal to the compiler, there are also function types that are specific to a particular
function item. In the following snippet, for example, the internal types of the functions
`foo` and `bar` are different, despite the fact that they have the same signature:
@ -3517,13 +3532,14 @@ more of the closure traits:
* `FnMut`
: The closure can be called multiple times as mutable. A closure called as
`FnMut` can mutate values from its environment. `FnMut` implies
`FnOnce`.
`FnMut` can mutate values from its environment. `FnMut` inherits from
`FnOnce` (i.e. anything implementing `FnMut` also implements `FnOnce`).
* `Fn`
: The closure can be called multiple times through a shared reference.
A closure called as `Fn` can neither move out from nor mutate values
from its environment. `Fn` implies `FnMut` and `FnOnce`.
from its environment. `Fn` inherits from `FnMut`, which itself
inherits from `FnOnce`.
### Trait objects
@ -3646,53 +3662,77 @@ Coercions are defined in [RFC401]. A coercion is implicit and has no syntax.
### Coercion sites
A coercion can only occur at certain coercion sites in a program; these are
typically places where the desired type is explicit or can be dervied by
typically places where the desired type is explicit or can be derived by
propagation from explicit types (without type inference). Possible coercion
sites are:
* `let` statements where an explicit type is given.
In `let _: U = e;`, `e` is coerced to have type `U`.
For example, `128` is coerced to have type `i8` in the following:
```rust
let _: i8 = 128;
```
* `static` and `const` statements (similar to `let` statements).
* arguments for function calls.
* Arguments for function calls
The value being coerced is the
actual parameter and it is coerced to the type of the formal parameter. For
example, let `foo` be defined as `fn foo(x: U) { ... }` and call it as
`foo(e);`. Then `e` is coerced to have type `U`;
The value being coerced is the actual parameter, and it is coerced to
the type of the formal parameter.
* instantiations of struct or variant fields.
For example, `128` is coerced to have type `i8` in the following:
Assume we have a `struct
Foo { x: U }` and instantiate it as `Foo { x: e }`. Then `e` is coerced to
have type `U`.
```rust
fn bar(_: i8) { }
* function results (either the final line of a block if it is not semicolon
terminated or any expression in a `return` statement).
fn main() {
bar(128);
}
```
In `fn foo() -> U { e }`, `e` is coerced to to have type `U`.
* Instantiations of struct or variant fields
For example, `128` is coerced to have type `i8` in the following:
```rust
struct Foo { x: i8 }
fn main() {
Foo { x: 128 };
}
```
* Function results, either the final line of a block if it is not
semicolon-terminated or any expression in a `return` statement
For example, `128` is coerced to have type `i8` in the following:
```rust
fn foo() -> i8 {
128
}
```
If the expression in one of these coercion sites is a coercion-propagating
expression, then the relevant sub-expressions in that expression are also
coercion sites. Propagation recurses from these new coercion sites.
Propagating expressions and their relevant sub-expressions are:
* array literals, where the array has type `[U; n]`. Each sub-expression in
* Array literals, where the array has type `[U; n]`. Each sub-expression in
the array literal is a coercion site for coercion to type `U`.
* array literals with repeating syntax, where the array has type `[U; n]`. The
* Array literals with repeating syntax, where the array has type `[U; n]`. The
repeated sub-expression is a coercion site for coercion to type `U`.
* tuples, where a tuple is a coercion site to type `(U_0, U_1, ..., U_n)`.
* Tuples, where a tuple is a coercion site to type `(U_0, U_1, ..., U_n)`.
Each sub-expression is a coercion site to the respective type, e.g. the
zeroth sub-expression is a coercion site to type `U_0`.
* parenthesised sub-expressions (`(e)`). If the expression has type `U`, then
* Parenthesised sub-expressions (`(e)`): if the expression has type `U`, then
the sub-expression is a coercion site to `U`.
* blocks. If a block has type `U`, then the last expression in the block (if
* Blocks: if a block has type `U`, then the last expression in the block (if
it is not semicolon-terminated) is a coercion site to `U`. This includes
blocks which are part of control flow statements, such as `if`/`else`, if
the block has a known type.
@ -3701,45 +3741,46 @@ the block has a known type.
Coercion is allowed between the following types:
* `T` to `U` if `T` is a subtype of `U` (*reflexive case*).
* `T` to `U` if `T` is a subtype of `U` (*reflexive case*)
* `T_1` to `T_3` where `T_1` coerces to `T_2` and `T_2` coerces to `T_3`
(*transitive case*).
(*transitive case*)
Note that this is not fully supported yet
* `&mut T` to `&T`.
* `&mut T` to `&T`
* `*mut T` to `*const T`.
* `*mut T` to `*const T`
* `&T` to `*const T`.
* `&T` to `*const T`
* `&mut T` to `*mut T`.
* `&mut T` to `*mut T`
* `&T` to `&U` if `T` implements `Deref<Target = U>`. For example:
```rust
use std::ops::Deref;
```rust
use std::ops::Deref;
struct CharContainer {
value: char
}
struct CharContainer {
value: char
}
impl Deref for CharContainer {
type Target = char;
impl Deref for CharContainer {
type Target = char;
fn deref<'a>(&'a self) -> &'a char {
&self.value
}
}
fn deref<'a>(&'a self) -> &'a char {
&self.value
}
}
fn foo(arg: &char) {}
fn foo(arg: &char) {}
fn main() {
let x = &mut CharContainer { value: 'y' };
foo(x); //&mut CharContainer is coerced to &char.
}
```
fn main() {
let x = &mut CharContainer { value: 'y' };
foo(x); //&mut CharContainer is coerced to &char.
}
```
* `&mut T` to `&mut U` if `T` implements `DerefMut<Target = U>`.
* TyCtor(`T`) to TyCtor(coerce_inner(`T`)), where TyCtor(`T`) is one of
@ -3953,7 +3994,7 @@ In general, `--crate-type=bin` or `--crate-type=lib` should be sufficient for
all compilation needs, and the other options are just available if more
fine-grained control is desired over the output format of a Rust crate.
# Appendix: Rationales and design tradeoffs
# Appendix: Rationales and design trade-offs
*TODO*.
@ -3963,7 +4004,7 @@ Rust is not a particularly original language, with design elements coming from
a wide range of sources. Some of these are listed below (including elements
that have since been removed):
* SML, OCaml: algebraic datatypes, pattern matching, type inference,
* SML, OCaml: algebraic data types, pattern matching, type inference,
semicolon statement separation
* C++: references, RAII, smart pointers, move semantics, monomorphisation,
memory model

View File

@ -221,6 +221,10 @@ a > code {
color: #428BCA;
}
.section-header > a > code {
color: #8D1A38;
}
/* Code highlighting */
pre.rust .kw { color: #8959A8; }
pre.rust .kw-2, pre.rust .prelude-ty { color: #4271AE; }

View File

@ -16,6 +16,7 @@
* [Iterators](iterators.md)
* [Concurrency](concurrency.md)
* [Error Handling](error-handling.md)
* [Choosing your Guarantees](choosing-your-guarantees.md)
* [FFI](ffi.md)
* [Borrow and AsRef](borrow-and-asref.md)
* [Release Channels](release-channels.md)
@ -63,7 +64,7 @@
* [No stdlib](no-stdlib.md)
* [Intrinsics](intrinsics.md)
* [Lang items](lang-items.md)
* [Link args](link-args.md)
* [Advanced linking](advanced-linking.md)
* [Benchmark Tests](benchmark-tests.md)
* [Box Syntax and Patterns](box-syntax-and-patterns.md)
* [Slice Patterns](slice-patterns.md)

View File

@ -12,7 +12,7 @@ Recommended for inspiration and a better understanding of Rust's background.
* [Macros that work together](https://www.cs.utah.edu/plt/publications/jfp12-draft-fcdf.pdf)
* [Traits: composable units of behavior](http://scg.unibe.ch/archive/papers/Scha03aTraits.pdf)
* [Alias burying](http://www.cs.uwm.edu/faculty/boyland/papers/unique-preprint.ps) - We tried something similar and abandoned it.
* [External uniqueness is unique enough](http://www.computingscience.nl/research/techreps/repo/CS-2002/2002-048.pdf)
* [External uniqueness is unique enough](http://www.cs.uu.nl/research/techreps/UU-CS-2002-048.html)
* [Uniqueness and Reference Immutability for Safe Parallelism](https://research.microsoft.com/pubs/170528/msr-tr-2012-79.pdf)
* [Region Based Memory Management](http://www.cs.ucla.edu/~palsberg/tba/papers/tofte-talpin-iandc97.pdf)
@ -26,10 +26,10 @@ Recommended for inspiration and a better understanding of Rust's background.
* [Dynamic circular work stealing deque](http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.170.1097&rep=rep1&type=pdf) - The Chase/Lev deque
* [Work-first and help-first scheduling policies for async-finish task parallelism](http://www.cs.rice.edu/%7Eyguo/pubs/PID824943.pdf) - More general than fully-strict work stealing
* [A Java fork/join calamity](http://www.coopsoft.com/ar/CalamityArticle.html) - critique of Java's fork/join library, particularly its application of work stealing to non-strict computation
* [Scheduling techniques for concurrent systems](http://www.ece.rutgers.edu/%7Eparashar/Classes/ece572-papers/05/ps-ousterhout.pdf)
* [Scheduling techniques for concurrent systems](http://www.stanford.edu/~ouster/cgi-bin/papers/coscheduling.pdf)
* [Contention aware scheduling](http://www.blagodurov.net/files/a8-blagodurov.pdf)
* [Balanced work stealing for time-sharing multicores](http://www.cse.ohio-state.edu/hpcs/WWW/HTML/publications/papers/TR-12-1.pdf)
* [Three layer cake](http://www.upcrc.illinois.edu/workshops/paraplop10/papers/paraplop10_submission_8.pdf)
* [Three layer cake for shared-memory programming](http://dl.acm.org/citation.cfm?id=1953616&dl=ACM&coll=DL&CFID=524387192&CFTOKEN=44362705)
* [Non-blocking steal-half work queues](http://www.cs.bgu.ac.il/%7Ehendlerd/papers/p280-hendler.pdf)
* [Reagents: expressing and composing fine-grained concurrency](http://www.mpi-sws.org/~turon/reagents.pdf)
* [Algorithms for scalable synchronization of shared-memory multiprocessors](https://www.cs.rochester.edu/u/scott/papers/1991_TOCS_synch.pdf)

View File

@ -0,0 +1,151 @@
% Advanced Linking
The common cases of linking with Rust have been covered earlier in this book,
but supporting the range of linking possibilities made available by other
languages is important for Rust to achieve seamless interaction with native
libraries.
# Link args
There is one other way to tell `rustc` how to customize linking, and that is via
the `link_args` attribute. This attribute is applied to `extern` blocks and
specifies raw flags which need to get passed to the linker when producing an
artifact. An example usage would be:
``` no_run
#![feature(link_args)]
#[link_args = "-foo -bar -baz"]
extern {}
# fn main() {}
```
Note that this feature is currently hidden behind the `feature(link_args)` gate
because this is not a sanctioned way of performing linking. Right now `rustc`
shells out to the system linker (`gcc` on most systems, `link.exe` on MSVC),
so it makes sense to provide extra command line
arguments, but this will not always be the case. In the future `rustc` may use
LLVM directly to link native libraries, in which case `link_args` will have no
meaning. You can achieve the same effect as the `link-args` attribute with the
`-C link-args` argument to `rustc`.
It is highly recommended to *not* use this attribute, and rather use the more
formal `#[link(...)]` attribute on `extern` blocks instead.
# Static linking
Static linking refers to the process of creating output that contain all
required libraries and so don't need libraries installed on every system where
you want to use your compiled project. Pure-Rust dependencies are statically
linked by default so you can use created binaries and libraries without
installing the Rust everywhere. By contrast, native libraries
(e.g. `libc` and `libm`) usually dynamically linked, but it is possible to
change this and statically link them as well.
Linking is a very platform dependent topic — on some platforms, static linking
may not be possible at all! This section assumes some basic familiarity with
linking on your platform of choice.
## Linux
By default, all Rust programs on Linux will link to the system `libc` along with
a number of other libraries. Let's look at an example on a 64-bit Linux machine
with GCC and `glibc` (by far the most common `libc` on Linux):
``` text
$ cat example.rs
fn main() {}
$ rustc example.rs
$ ldd example
linux-vdso.so.1 => (0x00007ffd565fd000)
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007fa81889c000)
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007fa81867e000)
librt.so.1 => /lib/x86_64-linux-gnu/librt.so.1 (0x00007fa818475000)
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007fa81825f000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007fa817e9a000)
/lib64/ld-linux-x86-64.so.2 (0x00007fa818cf9000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007fa817b93000)
```
Dynamic linking on Linux can be undesirable if you wish to use new library
features on old systems or target systems which do not have the required
dependencies for your program to run.
Static linking is supported via an alternative `libc`, `musl` - this must be
enabled at Rust compile-time with some prerequisites available. You can compile
your own version of Rust with `musl` enabled and install it into a custom
directory with the instructions below:
```text
$ mkdir musldist
$ PREFIX=$(pwd)/musldist
$
$ # Build musl
$ wget http://www.musl-libc.org/releases/musl-1.1.10.tar.gz
[...]
$ tar xf musl-1.1.10.tar.gz
$ cd musl-1.1.10/
musl-1.1.10 $ ./configure --disable-shared --prefix=$PREFIX
[...]
musl-1.1.10 $ make
[...]
musl-1.1.10 $ make install
[...]
musl-1.1.10 $ cd ..
$ du -h musldist/lib/libc.a
2.2M musldist/lib/libc.a
$
$ # Build libunwind.a
$ wget http://llvm.org/releases/3.6.1/llvm-3.6.1.src.tar.xz
$ tar xf llvm-3.6.1.src.tar.xz
$ cd llvm-3.6.1.src/projects/
llvm-3.6.1.src/projects $ svn co http://llvm.org/svn/llvm-project/libcxxabi/trunk/ libcxxabi
llvm-3.6.1.src/projects $ svn co http://llvm.org/svn/llvm-project/libunwind/trunk/ libunwind
llvm-3.6.1.src/projects $ sed -i 's#^\(include_directories\).*$#\0\n\1(../libcxxabi/include)#' libunwind/CMakeLists.txt
llvm-3.6.1.src/projects $ mkdir libunwind/build
llvm-3.6.1.src/projects $ cd libunwind/build
llvm-3.6.1.src/projects/libunwind/build $ cmake -DLLVM_PATH=../../.. -DLIBUNWIND_ENABLE_SHARED=0 ..
llvm-3.6.1.src/projects/libunwind/build $ make
llvm-3.6.1.src/projects/libunwind/build $ cp lib/libunwind.a $PREFIX/lib/
llvm-3.6.1.src/projects/libunwind/build $ cd cd ../../../../
$ du -h musldist/lib/libunwind.a
164K musldist/lib/libunwind.a
$
$ # Build musl-enabled rust
$ git clone https://github.com/rust-lang/rust.git muslrust
$ cd muslrust
muslrust $ ./configure --target=x86_64-unknown-linux-musl --musl-root=$PREFIX --prefix=$PREFIX
muslrust $ make
muslrust $ make install
muslrust $ cd ..
$ du -h musldist/bin/rustc
12K musldist/bin/rustc
```
You now have a build of a `musl`-enabled Rust! Because we've installed it to a
custom prefix we need to make sure our system can the binaries and appropriate
libraries when we try and run it:
```text
$ export PATH=$PREFIX/bin:$PATH
$ export LD_LIBRARY_PATH=$PREFIX/lib:$LD_LIBRARY_PATH
```
Let's try it out!
```text
$ echo 'fn main() { println!("hi!"); panic!("failed"); }' > example.rs
$ rustc --target=x86_64-unknown-linux-musl example.rs
$ ldd example
not a dynamic executable
$ ./example
hi!
thread '<main>' panicked at 'failed', example.rs:1
```
Success! This binary can be copied to almost any Linux machine with the same
machine architecture and run without issues.
`cargo build` also permits the `--target` option so you should be able to build
your crates as normal. However, you may need to recompile your native libraries
against `musl` before they can be linked against.

View File

@ -0,0 +1,356 @@
% Choosing your Guarantees
One important feature of Rust as language is that it lets us control the costs and guarantees
of a program.
There are various &ldquo;wrapper type&rdquo; abstractions in the Rust standard library which embody
a multitude of tradeoffs between cost, ergonomics, and guarantees. Many let one choose between
run time and compile time enforcement. This section will explain a few selected abstractions in
detail.
Before proceeding, it is highly recommended that one reads about [ownership][ownership] and
[borrowing][borrowing] in Rust.
[ownership]: ownership.html
[borrowing]: references-and-borrowing.html
# Basic pointer types
## `Box<T>`
[`Box<T>`][box] is pointer which is &ldquo;owned&rdquo;, or a &ldquo;box&rdquo;. While it can hand
out references to the contained data, it is the only owner of the data. In particular, when
something like the following occurs:
```rust
let x = Box::new(1);
let y = x;
// x no longer accessible here
```
Here, the box was _moved_ into `y`. As `x` no longer owns it, the compiler will no longer allow the
programmer to use `x` after this. A box can similarly be moved _out_ of a function by returning it.
When a box (that hasn't been moved) goes out of scope, destructors are run. These destructors take
care of deallocating the inner data.
This is a zero-cost abstraction for dynamic allocation. If you want to allocate some memory on the
heap and safely pass around a pointer to that memory, this is ideal. Note that you will only be
allowed to share references to this by the regular borrowing rules, checked at compile time.
[box]: ../std/boxed/struct.Box.html
## `&T` and `&mut T`
These are immutable and mutable references respectively. They follow the &lquo;read-write lock&rquo;
pattern, such that one may either have only one mutable reference to some data, or any number of
immutable ones, but not both. This guarantee is enforced at compile time, and has no visible cost at
runtime. In most cases these two pointer types suffice for sharing cheap references between sections
of code.
These pointers cannot be copied in such a way that they outlive the lifetime associated with them.
## `*const T` and `*mut T`
These are C-like raw pointers with no lifetime or ownership attached to them. They just point to
some location in memory with no other restrictions. The only guarantee that these provide is that
they cannot be dereferenced except in code marked `unsafe`.
These are useful when building safe, low cost abstractions like `Vec<T>`, but should be avoided in
safe code.
## `Rc<T>`
This is the first wrapper we will cover that has a runtime cost.
[`Rc<T>`][rc] is a reference counted pointer. In other words, this lets us have multiple "owning"
pointers to the same data, and the data will be dropped (destructors will be run) when all pointers
are out of scope.
Internally, it contains a shared &ldquo;reference count&rdquo; (also called &ldquo;refcount&rdquo;),
which is incremented each time the `Rc` is cloned, and decremented each time one of the `Rc`s goes
out of scope. The main responsibility of `Rc<T>` is to ensure that destructors are called for shared
data.
The internal data here is immutable, and if a cycle of references is created, the data will be
leaked. If we want data that doesn't leak when there are cycles, we need a garbage collector.
#### Guarantees
The main guarantee provided here is that the data will not be destroyed until all references to it
are out of scope.
This should be used when we wish to dynamically allocate and share some data (read-only) between
various portions of yur program, where it is not certain which portion will finish using the pointer
last. It's a viable alternative to `&T` when `&T` is either impossible to statically check for
correctness, or creates extremely unergonomic code where the programmer does not wish to spend the
development cost of working with.
This pointer is _not_ thread safe, and Rust will not let it be sent or shared with other threads.
This lets one avoid the cost of atomics in situations where they are unnecessary.
There is a sister smart pointer to this one, `Weak<T>`. This is a non-owning, but also non-borrowed,
smart pointer. It is also similar to `&T`, but it is not restricted in lifetime&mdash;a `Weak<T>`
can be held on to forever. However, it is possible that an attempt to access the inner data may fail
and return `None`, since this can outlive the owned `Rc`s. This is useful for cyclic
data structures and other things.
#### Cost
As far as memory goes, `Rc<T>` is a single allocation, though it will allocate two extra words (i.e.
two `usize` values) as compared to a regular `Box<T>` (for "strong" and "weak" refcounts).
`Rc<T>` has the computational cost of incrementing/decrementing the refcount whenever it is cloned
or goes out of scope respectively. Note that a clone will not do a deep copy, rather it will simply
increment the inner reference count and return a copy of the `Rc<T>`.
[rc]: ../std/rc/struct.Rc.html
# Cell types
&lquo;Cell&rquo;s provide interior mutability. In other words, they contain data which can be manipulated even
if the type cannot be obtained in a mutable form (for example, when it is behind an `&`-ptr or
`Rc<T>`).
[The documentation for the `cell` module has a pretty good explanation for these][cell-mod].
These types are _generally_ found in struct fields, but they may be found elsewhere too.
## `Cell<T>`
[`Cell<T>`][cell] is a type that provides zero-cost interior mutability, but only for `Copy` types.
Since the compiler knows that all the data owned by the contained value is on the stack, there's
no worry of leaking any data behind references (or worse!) by simply replacing the data.
It is still possible to violate your own invariants using this wrapper, so be careful when using it.
If a field is wrapped in `Cell`, it's a nice indicator that the chunk of data is mutable and may not
stay the same between the time you first read it and when you intend to use it.
```rust
# use std::cell::Cell;
let x = Cell::new(1);
let y = &x;
let z = &x;
x.set(2);
y.set(3);
z.set(4);
println!("{}", x.get());
```
Note that here we were able to mutate the same value from various immutable references.
This has the same runtime cost as the following:
```rust,ignore
let mut x = 1;
let y = &mut x;
let z = &mut x;
x = 2;
*y = 3;
*z = 4;
println!("{}", x);
```
but it has the added benefit of actually compiling successfully.
#### Guarantees
This relaxes the &ldquo;no aliasing with mutability&rdquo; restriction in places where it's
unnecessary. However, this also relaxes the guarantees that the restriction provides; so if your
invariants depend on data stored within `Cell`, you should be careful.
This is useful for mutating primitives and other `Copy` types when there is no easy way of
doing it in line with the static rules of `&` and `&mut`.
`Cell` does not let you obtain interior references to the data, which makes it safe to freely
mutate.
#### Cost
There is no runtime cost to using `Cell<T>`, however if you are using it to wrap larger (`Copy`)
structs, it might be worthwhile to instead wrap individual fields in `Cell<T>` since each write is
otherwise a full copy of the struct.
## `RefCell<T>`
[`RefCell<T>`][refcell] also provides interior mutability, but isn't restricted to `Copy` types.
Instead, it has a runtime cost. `RefCell<T>` enforces the read-write lock pattern at runtime (it's
like a single-threaded mutex), unlike `&T`/`&mut T` which do so at compile time. This is done by the
`borrow()` and `borrow_mut()` functions, which modify an internal reference count and return smart
pointers which can be dereferenced immutably and mutably respectively. The refcount is restored when
the smart pointers go out of scope. With this system, we can dynamically ensure that there are never
any other borrows active when a mutable borrow is active. If the programmer attempts to make such a
borrow, the thread will panic.
```rust
# use std::cell::RefCell;
let x = RefCell::new(vec![1,2,3,4]);
{
println!("{:?}", *x.borrow())
}
{
let mut my_ref = x.borrow_mut();
my_ref.push(1);
}
```
Similar to `Cell`, this is mainly useful for situations where it's hard or impossible to satisfy the
borrow checker. Generally we know that such mutations won't happen in a nested form, but it's good
to check.
For large, complicated programs, it becomes useful to put some things in `RefCell`s to make things
simpler. For example, a lot of the maps in [the `ctxt` struct][ctxt] in the rust compiler internals
are inside this wrapper. These are only modified once (during creation, which is not right after
initialization) or a couple of times in well-separated places. However, since this struct is
pervasively used everywhere, juggling mutable and immutable pointers would be hard (perhaps
impossible) and probably form a soup of `&`-ptrs which would be hard to extend. On the other hand,
the `RefCell` provides a cheap (not zero-cost) way of safely accessing these. In the future, if
someone adds some code that attempts to modify the cell when it's already borrowed, it will cause a
(usually deterministic) panic which can be traced back to the offending borrow.
Similarly, in Servo's DOM there is a lot of mutation, most of which is local to a DOM type, but some
of which crisscrosses the DOM and modifies various things. Using `RefCell` and `Cell` to guard all
mutation lets us avoid worrying about mutability everywhere, and it simultaneously highlights the
places where mutation is _actually_ happening.
Note that `RefCell` should be avoided if a mostly simple solution is possible with `&` pointers.
#### Guarantees
`RefCell` relaxes the _static_ restrictions preventing aliased mutation, and replaces them with
_dynamic_ ones. As such the guarantees have not changed.
#### Cost
`RefCell` does not allocate, but it contains an additional "borrow state"
indicator (one word in size) along with the data.
At runtime each borrow causes a modification/check of the refcount.
[cell-mod]: ../std/cell/
[cell]: ../std/cell/struct.Cell.html
[refcell]: ../std/cell/struct.RefCell.html
[ctxt]: ../rustc/middle/ty/struct.ctxt.html
# Synchronous types
Many of the types above cannot be used in a threadsafe manner. Particularly, `Rc<T>` and
`RefCell<T>`, which both use non-atomic reference counts (_atomic_ reference counts are those which
can be incremented from multiple threads without causing a data race), cannot be used this way. This
makes them cheaper to use, but we need thread safe versions of these too. They exist, in the form of
`Arc<T>` and `Mutex<T>`/`RWLock<T>`
Note that the non-threadsafe types _cannot_ be sent between threads, and this is checked at compile
time.
There are many useful wrappers for concurrent programming in the [sync][sync] module, but only the
major ones will be covered below.
[sync]: ../std/sync/index.html
## `Arc<T>`
[`Arc<T>`][arc] is just a version of `Rc<T>` that uses an atomic reference count (hence, "Arc").
This can be sent freely between threads.
C++'s `shared_ptr` is similar to `Arc`, however in the case of C++ the inner data is always mutable.
For semantics similar to that from C++, we should use `Arc<Mutex<T>>`, `Arc<RwLock<T>>`, or
`Arc<UnsafeCell<T>>`[^4] (`UnsafeCell<T>` is a cell type that can be used to hold any data and has
no runtime cost, but accessing it requires `unsafe` blocks). The last one should only be used if we
are certain that the usage won't cause any memory unsafety. Remember that writing to a struct is not
an atomic operation, and many functions like `vec.push()` can reallocate internally and cause unsafe
behavior, so even monotonicity may not be enough to justify `UnsafeCell`.
[^4]: `Arc<UnsafeCell<T>>` actually won't compile since `UnsafeCell<T>` isn't `Send` or `Sync`, but we can wrap it in a type and implement `Send`/`Sync` for it manually to get `Arc<Wrapper<T>>` where `Wrapper` is `struct Wrapper<T>(UnsafeCell<T>)`.
#### Guarantees
Like `Rc`, this provides the (thread safe) guarantee that the destructor for the internal data will
be run when the last `Arc` goes out of scope (barring any cycles).
#### Cost
This has the added cost of using atomics for changing the refcount (which will happen whenever it is
cloned or goes out of scope). When sharing data from an `Arc` in a single thread, it is preferable
to share `&` pointers whenever possible.
[arc]: ../std/sync/struct.Arc.html
## `Mutex<T>` and `RwLock<T>`
[`Mutex<T>`][mutex] and [`RwLock<T>`][rwlock] provide mutual-exclusion via RAII guards (guards are
objects which maintain some state, like a lock, until their destructor is called). For both of
these, the mutex is opaque until we call `lock()` on it, at which point the thread will block
until a lock can be acquired, and then a guard will be returned. This guard can be used to access
the inner data (mutably), and the lock will be released when the guard goes out of scope.
```rust,ignore
{
let guard = mutex.lock();
// guard dereferences mutably to the inner type
*guard += 1;
} // lock released when destructor runs
```
`RwLock` has the added benefit of being efficient for multiple reads. It is always safe to have
multiple readers to shared data as long as there are no writers; and `RwLock` lets readers acquire a
"read lock". Such locks can be acquired concurrently and are kept track of via a reference count.
Writers must obtain a "write lock" which can only be obtained when all readers have gone out of
scope.
#### Guarantees
Both of these provide safe shared mutability across threads, however they are prone to deadlocks.
Some level of additional protocol safety can be obtained via the type system.
#### Costs
These use internal atomic-like types to maintain the locks, which are pretty costly (they can block
all memory reads across processors till they're done). Waiting on these locks can also be slow when
there's a lot of concurrent access happening.
[rwlock]: ../std/sync/struct.RwLock.html
[mutex]: ../std/sync/struct.Mutex.html
[sessions]: https://github.com/Munksgaard/rust-sessions
# Composition
A common gripe when reading Rust code is with types like `Rc<RefCell<Vec<T>>>` (or even more more
complicated compositions of such types). It's not always clear what the composition does, or why the
author chose one like this (and when one should be using such a composition in one's own code)
Usually, it's a case of composing together the guarantees that you need, without paying for stuff
that is unnecessary.
For example, `Rc<RefCell<T>>` is one such composition. `Rc<T>` itself can't be dereferenced mutably;
because `Rc<T>` provides sharing and shared mutability can lead to unsafe behavior, so we put
`RefCell<T>` inside to get dynamically verified shared mutability. Now we have shared mutable data,
but it's shared in a way that there can only be one mutator (and no readers) or multiple readers.
Now, we can take this a step further, and have `Rc<RefCell<Vec<T>>>` or `Rc<Vec<RefCell<T>>>`. These
are both shareable, mutable vectors, but they're not the same.
With the former, the `RefCell<T>` is wrapping the `Vec<T>`, so the `Vec<T>` in its entirety is
mutable. At the same time, there can only be one mutable borrow of the whole `Vec` at a given time.
This means that your code cannot simultaneously work on different elements of the vector from
different `Rc` handles. However, we are able to push and pop from the `Vec<T>` at will. This is
similar to an `&mut Vec<T>` with the borrow checking done at runtime.
With the latter, the borrowing is of individual elements, but the overall vector is immutable. Thus,
we can independently borrow separate elements, but we cannot push or pop from the vector. This is
similar to an `&mut [T]`[^3], but, again, the borrow checking is at runtime.
In concurrent programs, we have a similar situation with `Arc<Mutex<T>>`, which provides shared
mutability and ownership.
When reading code that uses these, go in step by step and look at the guarantees/costs provided.
When choosing a composed type, we must do the reverse; figure out which guarantees we want, and at
which point of the composition we need them. For example, if there is a choice between
`Vec<RefCell<T>>` and `RefCell<Vec<T>>`, we should figure out the tradeoffs as done above and pick
one.
[^3]: `&[T]` and `&mut [T]` are _slices_; they consist of a pointer and a length and can refer to a portion of a vector or array. `&mut [T]` can have its elements mutated, however its length cannot be touched.

View File

@ -38,6 +38,17 @@ fn add_one(x: i32) -> i32 {
}
```
There is another style of doc comment, `//!`, to comment containing items (e.g.
crates, modules or functions), instead of the items following it. Commonly used
inside crates root (lib.rs) or modules root (mod.rs):
```
//! # The Rust Standard Library
//!
//! The Rust Standard Library provides the essential runtime
//! functionality for building portable Rust software.
```
When writing doc comments, providing some examples of usage is very, very
helpful. Youll notice weve used a new macro here: `assert_eq!`. This compares
two values, and `panic!`s if theyre not equal to each other. Its very helpful

View File

@ -10,11 +10,12 @@ system is up to the task, and gives you powerful ways to reason about
concurrent code at compile time.
Before we talk about the concurrency features that come with Rust, it's important
to understand something: Rust is low-level enough that all of this is provided
by the standard library, not by the language. This means that if you don't like
some aspect of the way Rust handles concurrency, you can implement an alternative
way of doing things. [mio](https://github.com/carllerche/mio) is a real-world
example of this principle in action.
to understand something: Rust is low-level enough that the vast majority of
this is provided by the standard library, not by the language. This means that
if you don't like some aspect of the way Rust handles concurrency, you can
implement an alternative way of doing things.
[mio](https://github.com/carllerche/mio) is a real-world example of this
principle in action.
## Background: `Send` and `Sync`

View File

@ -151,7 +151,7 @@ look at `main()` again:
# struct Philosopher {
# name: String,
# }
#
#
# impl Philosopher {
# fn new(name: &str) -> Philosopher {
# Philosopher {
@ -159,7 +159,7 @@ look at `main()` again:
# }
# }
# }
#
#
fn main() {
let p1 = Philosopher::new("Judith Butler");
let p2 = Philosopher::new("Gilles Deleuze");
@ -197,15 +197,15 @@ a method, and then loop through all the philosophers, calling it:
```rust
struct Philosopher {
name: String,
}
}
impl Philosopher {
impl Philosopher {
fn new(name: &str) -> Philosopher {
Philosopher {
name: name.to_string(),
}
}
fn eat(&self) {
println!("{} is done eating.", self.name);
}
@ -267,15 +267,15 @@ use std::thread;
struct Philosopher {
name: String,
}
}
impl Philosopher {
impl Philosopher {
fn new(name: &str) -> Philosopher {
Philosopher {
name: name.to_string(),
}
}
fn eat(&self) {
println!("{} is eating.", self.name);
@ -348,9 +348,9 @@ use std::thread;
struct Philosopher {
name: String,
}
}
impl Philosopher {
impl Philosopher {
fn new(name: &str) -> Philosopher {
Philosopher {
name: name.to_string(),
@ -401,7 +401,7 @@ let handles: Vec<_> = philosophers.into_iter().map(|p| {
While this is only five lines, theyre a dense five. Lets break it down.
```rust,ignore
let handles: Vec<_> =
let handles: Vec<_> =
```
We introduce a new binding, called `handles`. Weve given it this name because
@ -460,15 +460,15 @@ If you run this program, youll see that the philosophers eat out of order!
We have multi-threading!
```text
Gilles Deleuze is eating.
Gilles Deleuze is done eating.
Emma Goldman is eating.
Emma Goldman is done eating.
Michel Foucault is eating.
Judith Butler is eating.
Judith Butler is done eating.
Gilles Deleuze is eating.
Karl Marx is eating.
Emma Goldman is eating.
Michel Foucault is eating.
Judith Butler is done eating.
Gilles Deleuze is done eating.
Karl Marx is done eating.
Emma Goldman is done eating.
Michel Foucault is done eating.
```

View File

@ -33,8 +33,10 @@ pub fn new(value: T) -> Rc<T> {
```
This code generates documentation that looks [like this][rc-new]. I've left the
implementation out, with a regular comment in its place. That's the first thing
to notice about this annotation: it uses `///`, instead of `//`. The triple slash
implementation out, with a regular comment in its place.
The first thing to notice about this annotation is that it uses
`///` instead of `//`. The triple slash
indicates a documentation comment.
Documentation comments are written in Markdown.
@ -375,7 +377,7 @@ $ rustdoc --test path/to/my/crate/root.rs
$ cargo test
```
That's right, `cargo test` tests embedded documentation too. However,
That's right, `cargo test` tests embedded documentation too. However,
`cargo test` will not test binary crates, only library ones. This is
due to the way `rustdoc` works: it links against the library to be tested,
but with a binary, theres nothing to link to.

View File

@ -50,6 +50,8 @@ is very wrong. Wrong enough that we can't continue with things in the current
state. Another example is using the `unreachable!()` macro:
```rust,ignore
use Event::NewRelease;
enum Event {
NewRelease,
}
@ -71,7 +73,7 @@ fn descriptive_probability(event: Event) -> &'static str {
}
fn main() {
std::io::println(descriptive_probability(NewRelease));
println!("{}", descriptive_probability(NewRelease));
}
```

View File

@ -309,8 +309,8 @@ and invokes callbacks from there.
In these cases access to Rust data structures inside the callbacks is
especially unsafe and proper synchronization mechanisms must be used.
Besides classical synchronization mechanisms like mutexes, one possibility in
Rust is to use channels (in `std::comm`) to forward data from the C thread
that invoked the callback into a Rust thread.
Rust is to use channels (in `std::sync::mpsc`) to forward data from the C
thread that invoked the callback into a Rust thread.
If an asynchronous callback targets a special object in the Rust address space
it is also absolutely necessary that no more callbacks are performed by the
@ -340,7 +340,7 @@ libraries:
Note that frameworks are only available on OSX targets.
The different `kind` values are meant to differentiate how the native library
participates in linkage. From a linkage perspective, the rust compiler creates
participates in linkage. From a linkage perspective, the Rust compiler creates
two flavors of artifacts: partial (rlib/staticlib) and final (dylib/binary).
Native dynamic library and framework dependencies are propagated to the final
artifact boundary, while static library dependencies are not propagated at
@ -350,9 +350,9 @@ artifact.
A few examples of how this model can be used are:
* A native build dependency. Sometimes some C/C++ glue is needed when writing
some rust code, but distribution of the C/C++ code in a library format is just
some Rust code, but distribution of the C/C++ code in a library format is just
a burden. In this case, the code will be archived into `libfoo.a` and then the
rust crate would declare a dependency via `#[link(name = "foo", kind =
Rust crate would declare a dependency via `#[link(name = "foo", kind =
"static")]`.
Regardless of the flavor of output for the crate, the native static library
@ -361,7 +361,7 @@ A few examples of how this model can be used are:
* A normal dynamic dependency. Common system libraries (like `readline`) are
available on a large number of systems, and often a static copy of these
libraries cannot be found. When this dependency is included in a rust crate,
libraries cannot be found. When this dependency is included in a Rust crate,
partial targets (like rlibs) will not link to the library, but when the rlib
is included in a final target (like a binary), the native library will be
linked in.
@ -533,19 +533,10 @@ attribute turns off Rust's name mangling, so that it is easier to link to.
# FFI and panics
Its important to be mindful of `panic!`s when working with FFI. This code,
when called from C, will `abort`:
```rust
#[no_mangle]
pub extern fn oh_no() -> ! {
panic!("Oops!");
}
# fn main() {}
```
If youre writing code that may panic, you should run it in another thread,
so that the panic doesnt bubble up to C:
Its important to be mindful of `panic!`s when working with FFI. A `panic!`
across an FFI boundary is undefined behavior. If youre writing code that may
panic, you should run it in another thread, so that the panic doesnt bubble up
to C:
```rust
use std::thread;

View File

@ -360,10 +360,12 @@ rand="0.3.0"
The `[dependencies]` section of `Cargo.toml` is like the `[package]` section:
everything that follows it is part of it, until the next section starts.
Cargo uses the dependencies section to know what dependencies on external
crates you have, and what versions you require. In this case, weve used version `0.3.0`.
crates you have, and what versions you require. In this case, weve specified version `0.3.0`,
which Cargo understands to be any release thats compatible with this specific version.
Cargo understands [Semantic Versioning][semver], which is a standard for writing version
numbers. If we wanted to use the latest version we could use `*` or we could use a range
of versions. [Cargos documentation][cargodoc] contains more details.
numbers. If we wanted to use only `0.3.0` exactly, we could use `=0.3.0`. If we
wanted to use the latest version we could use `*`; We could use a range of
versions. [Cargos documentation][cargodoc] contains more details.
[semver]: http://semver.org
[cargodoc]: http://doc.crates.io/crates-io.html

View File

@ -103,7 +103,7 @@ fn main() {
If you would like to use real operands in this position, however,
you are required to put curly braces `{}` around the register that
you want, and you are required to put the specific size of the
operand. This is useful for very low level programming, where
operand. This is useful for very low level programming, where
which register you use is important:
```rust
@ -166,3 +166,12 @@ unsafe {
println!("eax is currently {}", result);
# }
```
## More Information
The current implementation of the `asm!` macro is a direct binding to [LLVM's
inline assembler expressions][llvm-docs], so be sure to check out [their
documentation as well][llvm-docs] for more information about clobbers,
constraints, etc.
[llvm-docs]: http://llvm.org/docs/LangRef.html#inline-assembler-expressions

View File

@ -2,7 +2,7 @@
The first step to using Rust is to install it! There are a number of ways to
install Rust, but the easiest is to use the `rustup` script. If you're on Linux
or a Mac, all you need to do is this:
or a Mac, all you need to do is this:
> Note: you don't need to type in the `$`s, they just indicate the start of
> each command. Youll see many tutorials and examples around the web that
@ -25,6 +25,12 @@ $ sh rustup.sh
[insecurity]: http://curlpipesh.tumblr.com
If you're on Windows, please download the appropriate [installer][install-page].
**NOTE:** By default, the Windows installer will not add Rust to the %PATH%
system variable. If this is the only version of Rust you are installing and you
want to be able to run it from the command line, click on "Advanced" on the
install dialog and on the "Product Features" page ensure "Add to PATH" is
installed on the local hard drive.
[install-page]: http://www.rust-lang.org/install.html
@ -87,6 +93,11 @@ rustc 1.0.0 (a59de37e9 2015-05-13)
If you did, Rust has been installed successfully! Congrats!
If you didn't and you're on Windows, check that Rust is in your %PATH% system
variable. If it isn't, run the installer again, select "Change" on the "Change,
repair, or remove installation" page and ensure "Add to PATH" is installed on
the local hard drive.
This installer also installs a copy of the documentation locally, so you can
read it offline. On UNIX systems, `/usr/local/share/doc/rust` is the location.
On Windows, it's in a `share/doc` directory, inside wherever you installed Rust
@ -101,5 +112,5 @@ resources include [the users forum][users], and
[irc]: irc://irc.mozilla.org/#rust
[mibbit]: http://chat.mibbit.com/?server=irc.mozilla.org&channel=%23rust
[users]: http://users.rust-lang.org/
[users]: http://users.rust-lang.org/
[stackoverflow]: http://stackoverflow.com/questions/tagged/rust

View File

@ -101,6 +101,8 @@ the lifetime `'a` has snuck in between the `&` and the `mut i32`. We read `&mut
i32` as a mutable reference to an i32 and `&'a mut i32` as a mutable
reference to an `i32` with the lifetime `'a`.
# In `struct`s
Youll also need explicit lifetimes when working with [`struct`][structs]s:
```rust
@ -137,6 +139,33 @@ x: &'a i32,
uses it. So why do we need a lifetime here? We need to ensure that any reference
to a `Foo` cannot outlive the reference to an `i32` it contains.
## `impl` blocks
Lets implement a method on `Foo`:
```rust
struct Foo<'a> {
x: &'a i32,
}
impl<'a> Foo<'a> {
fn x(&self) -> &'a i32 { self.x }
}
fn main() {
let y = &5; // this is the same as `let _y = 5; let y = &_y;`
let f = Foo { x: y };
println!("x is: {}", f.x());
}
```
As you can see, we need to declare a lifetime for `Foo` in the `impl` line. We repeat
`'a` twice, just like on functions: `impl<'a>` defines a lifetime `'a`, and `Foo<'a>`
uses it.
## Multiple lifetimes
If you have multiple references, you can use the same lifetime multiple times:
```rust

View File

@ -1,25 +0,0 @@
% Link args
There is one other way to tell rustc how to customize linking, and that is via
the `link_args` attribute. This attribute is applied to `extern` blocks and
specifies raw flags which need to get passed to the linker when producing an
artifact. An example usage would be:
``` no_run
#![feature(link_args)]
#[link_args = "-foo -bar -baz"]
extern {}
# fn main() {}
```
Note that this feature is currently hidden behind the `feature(link_args)` gate
because this is not a sanctioned way of performing linking. Right now rustc
shells out to the system linker, so it makes sense to provide extra command line
arguments, but this will not always be the case. In the future rustc may use
LLVM directly to link native libraries in which case `link_args` will have no
meaning.
It is highly recommended to *not* use this attribute, and rather use the more
formal `#[link(...)]` attribute on `extern` blocks instead.

View File

@ -42,8 +42,8 @@ With that in mind, lets learn about ownership.
# Ownership
[Variable bindings][bindings] have a property in Rust: they have ownership
of what theyre bound to. This means that when a binding goes out of scope, the
resource that theyre bound to are freed. For example:
of what theyre bound to. This means that when a binding goes out of scope,
Rust will free the bound resources. For example:
```rust
fn foo() {

View File

@ -282,6 +282,38 @@ This destructuring behavior works on any compound data type, like
[tuples]: primitive-types.html#tuples
[enums]: enums.html
# Ignoring bindings
You can use `_` in a pattern to disregard the value. For example, heres a
`match` against a `Result<T, E>`:
```rust
# let some_value: Result<i32, &'static str> = Err("There was an error");
match some_value {
Ok(value) => println!("got a value: {}", value),
Err(_) => println!("an error occurred"),
}
```
In the first arm, we bind the value inside the `Ok` variant to `value`. But
in the `Err` arm, we use `_` to disregard the specific error, and just print
a general error message.
`_` is valid in any pattern that creates a binding. This can be useful to
ignore parts of a larger structure:
```rust
fn coordinate() -> (i32, i32, i32) {
// generate and return some sort of triple tuple
# (1, 2, 3)
}
let (x, _, z) = coordinate();
```
Here, we bind the first and last element of the tuple to `x` and `z`, but
ignore the middle element.
# Mix and Match
Whew! Thats a lot of different ways to match things, and they can all be

View File

@ -336,7 +336,9 @@ In other words, `y` is only valid for the scope where `x` exists. As soon as
the borrow doesnt live long enough because its not valid for the right
amount of time.
The same problem occurs when the reference is declared _before_ the variable it refers to:
The same problem occurs when the reference is declared _before_ the variable it
refers to. This is because resources within the same scope are freed in the
opposite order they were declared:
```rust,ignore
let y: &i32;
@ -369,3 +371,6 @@ statement 1 at 3:14
println!("{}", y);
}
```
In the above example, `y` is declared before `x`, meaning that `y` lives longer
than `x`, which is not allowed.

View File

@ -43,3 +43,26 @@ This will help alert the team in case theres an accidental regression.
Additionally, testing against nightly can catch regressions even sooner, and so
if you dont mind a third build, wed appreciate testing against all channels.
As an example, many Rust programmers use [Travis](https://travis-ci.org/) to
test their crates, which is free for open source projects. Travis [supports
Rust directly][travis], and you can use a `.travis.yml` file like this to
test on all channels:
```yaml
language: rust
rust:
- nightly
- beta
- stable
matrix:
allow_failures:
- rust: nightly
```
[travis]: http://docs.travis-ci.com/user/languages/rust/
With this configuration, Travis will test all three channels, but if something
breaks on nightly, it wont fail your build. A similar configuration is
recommended for any CI system, check the documentation of the one youre
using for more details.

View File

@ -250,11 +250,10 @@ that our tests are entirely left out of a normal build.
The second change is the `use` declaration. Because we're in an inner module,
we need to bring our test function into scope. This can be annoying if you have
a large module, and so this is a common use of the `glob` feature. Let's change
our `src/lib.rs` to make use of it:
a large module, and so this is a common use of globs. Let's change our
`src/lib.rs` to make use of it:
```rust,ignore
pub fn add_two(a: i32) -> i32 {
a + 2
}

View File

@ -176,7 +176,7 @@ After `bar()` is over, its frame is deallocated, leaving just `foo()` and
| 1 | a | 5 |
| 0 | x | 42 |
And then `foo()` ends, leaving just `main()`
And then `foo()` ends, leaving just `main()`:
| Address | Name | Value |
|---------|------|-------|
@ -537,7 +537,7 @@ Generally, you should prefer stack allocation, and so, Rust stack-allocates by
default. The LIFO model of the stack is simpler, at a fundamental level. This
has two big impacts: runtime efficiency and semantic impact.
## Runtime Efficiency.
## Runtime Efficiency
Managing the memory for the stack is trivial: The machine just
increments or decrements a single value, the so-called “stack pointer”.

View File

@ -8,11 +8,11 @@ this, Rust has a keyword, `unsafe`. Code using `unsafe` has less restrictions
than normal code does.
Lets go over the syntax, and then well talk semantics. `unsafe` is used in
two contexts. The first one is to mark a function as unsafe:
four contexts. The first one is to mark a function as unsafe:
```rust
unsafe fn danger_will_robinson() {
// scary stuff
// scary stuff
}
```
@ -27,15 +27,40 @@ unsafe {
}
```
The third is for unsafe traits:
```rust
unsafe trait Scary { }
```
And the fourth is for `impl`ementing one of those traits:
```rust
# unsafe trait Scary { }
unsafe impl Scary for i32 {}
```
Its important to be able to explicitly delineate code that may have bugs that
cause big problems. If a Rust program segfaults, you can be sure its somewhere
in the sections marked `unsafe`.
# What does safe mean?
Safe, in the context of Rust, means “doesnt do anything unsafe.” Easy!
Safe, in the context of Rust, means doesnt do anything unsafe. Its also
important to know that there are certain behaviors that are probably not
desirable in your code, but are expressly _not_ unsafe:
Okay, lets try again: what is not safe to do? Heres a list:
* Deadlocks
* Leaks of memory or other resources
* Exiting without calling destructors
* Integer overflow
Rust cannot prevent all kinds of software problems. Buggy code can and will be
written in Rust. These things arent great, but they dont qualify as `unsafe`
specifically.
In addition, the following are all undefined behaviors in Rust, and must be
avoided, even when writing `unsafe` code:
* Data races
* Dereferencing a null/dangling raw pointer
@ -64,21 +89,6 @@ Okay, lets try again: what is not safe to do? Heres a list:
[undef]: http://llvm.org/docs/LangRef.html#undefined-values
[aliasing]: http://llvm.org/docs/LangRef.html#pointer-aliasing-rules
Whew! Thats a bunch of stuff. Its also important to notice all kinds of
behaviors that are certainly bad, but are expressly _not_ unsafe:
* Deadlocks
* Reading data from private fields
* Leaks due to reference count cycles
* Exiting without calling destructors
* Sending signals
* Accessing/modifying the file system
* Integer overflow
Rust cannot prevent all kinds of software problems. Buggy code can and will be
written in Rust. These things arent great, but they dont qualify as `unsafe`
specifically.
# Unsafe Superpowers
In both unsafe functions and unsafe blocks, Rust will let you do three things
@ -90,10 +100,14 @@ that you normally can not do. Just three. Here they are:
Thats it. Its important that `unsafe` does not, for example, turn off the
borrow checker. Adding `unsafe` to some random Rust code doesnt change its
semantics, it wont just start accepting anything.
semantics, it wont just start accepting anything. But it will let you write
things that _do_ break some of the rules.
But it will let you write things that _do_ break some of the rules. Lets go
over these three abilities in order.
You will also encounter the `unsafe` keyword when writing bindings to foreign
(non-Rust) interfaces. You're encouraged to write a safe, native Rust interface
around the methods provided by the library.
Lets go over the basic three abilities listed, in order.
## Access or update a `static mut`

View File

@ -88,6 +88,24 @@ for x in 0..10 {
}
```
You may also encounter situations where you have nested loops and need to
specify which one your `break` or `continue` statement is for. Like most
other languages, by default a `break` or `continue` will apply to innermost
loop. In a sitation where you would like to a `break` or `continue` for one
of the outer loops, you can use labels to specify which loop the `break` or
`continue` statement applies to. This will only print when both `x` and `y` are
odd:
```rust
'outer: for x in 0..10 {
'inner: for y in 0..10 {
if x % 2 == 0 { continue 'outer; } // continues the loop over x
if y % 2 == 0 { continue 'inner; } // continues the loop over y
println!("x: {}, y: {}", x, y);
}
}
```
Both `continue` and `break` are valid in both `while` loops and [`for` loops][for].
[for]: for-loops.html

View File

@ -55,12 +55,10 @@ SLICE_FIELD_NAME_LENGTH = "length"
SLICE_FIELD_NAMES = [SLICE_FIELD_NAME_DATA_PTR, SLICE_FIELD_NAME_LENGTH]
# std::Vec<> related constants
STD_VEC_FIELD_NAME_DATA_PTR = "ptr"
STD_VEC_FIELD_NAME_LENGTH = "len"
STD_VEC_FIELD_NAME_CAPACITY = "cap"
STD_VEC_FIELD_NAMES = [STD_VEC_FIELD_NAME_DATA_PTR,
STD_VEC_FIELD_NAME_LENGTH,
STD_VEC_FIELD_NAME_CAPACITY]
STD_VEC_FIELD_NAME_BUF = "buf"
STD_VEC_FIELD_NAMES = [STD_VEC_FIELD_NAME_BUF,
STD_VEC_FIELD_NAME_LENGTH]
# std::String related constants
STD_STRING_FIELD_NAMES = ["vec"]
@ -302,13 +300,13 @@ def get_discriminant_value_as_integer(enum_val):
def extract_length_ptr_and_cap_from_std_vec(vec_val):
assert vec_val.type.get_type_kind() == TYPE_KIND_STD_VEC
length_field_index = STD_VEC_FIELD_NAMES.index(STD_VEC_FIELD_NAME_LENGTH)
ptr_field_index = STD_VEC_FIELD_NAMES.index(STD_VEC_FIELD_NAME_DATA_PTR)
cap_field_index = STD_VEC_FIELD_NAMES.index(STD_VEC_FIELD_NAME_CAPACITY)
buf_field_index = STD_VEC_FIELD_NAMES.index(STD_VEC_FIELD_NAME_BUF)
length = vec_val.get_child_at_index(length_field_index).as_integer()
vec_ptr_val = vec_val.get_child_at_index(ptr_field_index)
capacity = vec_val.get_child_at_index(cap_field_index).as_integer()
buf = vec_val.get_child_at_index(buf_field_index)
vec_ptr_val = buf.get_child_at_index(0)
capacity = buf.get_child_at_index(1).as_integer()
unique_ptr_val = vec_ptr_val.get_child_at_index(0)
data_ptr = unique_ptr_val.get_child_at_index(0)
assert data_ptr.type.get_dwarf_type_kind() == DWARF_TYPE_CODE_PTR

View File

@ -23,6 +23,18 @@ src_dir = sys.argv[1]
errcode_map = {}
error_re = re.compile("(E\d\d\d\d)")
# In the register_long_diagnostics! macro, entries look like this:
#
# EXXXX: r##"
# <Long diagnostic message>
# "##,
#
# These two variables are for detecting the beginning and end of diagnostic
# messages so that duplicate error codes are not reported when a code occurs
# inside a diagnostic message
long_diag_begin = "r##\""
long_diag_end = "\"##"
for (dirpath, dirnames, filenames) in os.walk(src_dir):
if "src/test" in dirpath or "src/llvm" in dirpath:
# Short circuit for fast
@ -35,7 +47,14 @@ for (dirpath, dirnames, filenames) in os.walk(src_dir):
path = os.path.join(dirpath, filename)
with open(path, 'r') as f:
inside_long_diag = False
for line_num, line in enumerate(f, start=1):
if inside_long_diag:
# Skip duplicate error code checking for this line
if long_diag_end in line:
inside_long_diag = False
continue
match = error_re.search(line)
if match:
errcode = match.group(1)
@ -47,6 +66,9 @@ for (dirpath, dirnames, filenames) in os.walk(src_dir):
else:
errcode_map[errcode] = new_record
if long_diag_begin in line:
inside_long_diag = True
errors = False
all_errors = []

View File

@ -14,10 +14,9 @@ import subprocess
f = open(sys.argv[1], 'wb')
components = sys.argv[2].split(' ')
components = [i for i in components if i] # ignore extra whitespaces
components = sys.argv[2].split() # splits on whitespace
enable_static = sys.argv[3]
llconfig = sys.argv[4]
llvm_config = sys.argv[4]
f.write("""// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
@ -39,7 +38,7 @@ def run(args):
out, err = proc.communicate()
if err:
print("failed to run llconfig: args = `{}`".format(args))
print("failed to run llvm_config: args = `{}`".format(args))
print(err)
sys.exit(1)
return out
@ -47,7 +46,7 @@ def run(args):
f.write("\n")
# LLVM libs
args = [llconfig, '--libs', '--system-libs']
args = [llvm_config, '--libs', '--system-libs']
args.extend(components)
out = run(args)
@ -69,13 +68,13 @@ for lib in out.strip().replace("\n", ' ').split(' '):
f.write(")]\n")
# LLVM ldflags
out = run([llconfig, '--ldflags'])
out = run([llvm_config, '--ldflags'])
for lib in out.strip().split(' '):
if lib[:2] == "-l":
f.write("#[link(name = \"" + lib[2:] + "\")]\n")
# C++ runtime library
out = run([llconfig, '--cxxflags'])
out = run([llvm_config, '--cxxflags'])
if enable_static == '1':
assert('stdlib=libc++' not in out)
f.write("#[link(name = \"stdc++\", kind = \"static\")]\n")

View File

@ -41,13 +41,14 @@ download_dir_base = "dl"
download_unpack_base = os.path.join(download_dir_base, "unpack")
snapshot_files = {
"bitrig": ["bin/rustc"],
"dragonfly": ["bin/rustc"],
"freebsd": ["bin/rustc"],
"linux": ["bin/rustc"],
"macos": ["bin/rustc"],
"winnt": ["bin/rustc.exe"],
"freebsd": ["bin/rustc"],
"dragonfly": ["bin/rustc"],
"bitrig": ["bin/rustc"],
"netbsd": ["bin/rustc"],
"openbsd": ["bin/rustc"],
"winnt": ["bin/rustc.exe"],
}
winnt_runtime_deps_32 = ["libgcc_s_dw2-1.dll", "libstdc++-6.dll"]
@ -103,6 +104,8 @@ def get_kernel(triple):
return "dragonfly"
if os_name == "bitrig":
return "bitrig"
if os_name == "netbsd":
return "netbsd"
if os_name == "openbsd":
return "openbsd"
return "linux"

View File

@ -372,13 +372,6 @@ def emit_conversions_module(f, to_upper, to_lower, to_title):
}
}
pub fn to_title(c: char) -> [char; 3] {
match bsearch_case_table(c, to_titlecase_table) {
None => [c, '\\0', '\\0'],
Some(index) => to_titlecase_table[index].1
}
}
fn bsearch_case_table(c: char, table: &'static [(char, [char; 3])]) -> Option<usize> {
match table.binary_search_by(|&(key, _)| {
if c == key { Equal }
@ -400,9 +393,6 @@ def emit_conversions_module(f, to_upper, to_lower, to_title):
emit_table(f, "to_uppercase_table",
sorted(to_upper.iteritems(), key=operator.itemgetter(0)),
is_pub=False, t_type = t_type, pfun=pfun)
emit_table(f, "to_titlecase_table",
sorted(to_title.iteritems(), key=operator.itemgetter(0)),
is_pub=False, t_type = t_type, pfun=pfun)
f.write("}\n\n")
def emit_grapheme_module(f, grapheme_table, grapheme_cats):

View File

@ -77,13 +77,15 @@ use core::atomic;
use core::atomic::Ordering::{Relaxed, Release, Acquire, SeqCst};
use core::fmt;
use core::cmp::Ordering;
use core::mem::{min_align_of_val, size_of_val};
use core::mem::{align_of_val, size_of_val};
use core::intrinsics::drop_in_place;
use core::mem;
use core::nonzero::NonZero;
use core::ops::{Deref, CoerceUnsized};
use core::ptr;
use core::marker::Unsize;
use core::hash::{Hash, Hasher};
use core::usize;
use heap::deallocate;
/// An atomically reference counted wrapper for shared state.
@ -145,6 +147,8 @@ pub struct Weak<T: ?Sized> {
unsafe impl<T: ?Sized + Sync + Send> Send for Weak<T> { }
unsafe impl<T: ?Sized + Sync + Send> Sync for Weak<T> { }
impl<T: ?Sized + Unsize<U>, U: ?Sized> CoerceUnsized<Weak<U>> for Weak<T> {}
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized + fmt::Debug> fmt::Debug for Weak<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
@ -154,7 +158,12 @@ impl<T: ?Sized + fmt::Debug> fmt::Debug for Weak<T> {
struct ArcInner<T: ?Sized> {
strong: atomic::AtomicUsize,
// the value usize::MAX acts as a sentinel for temporarily "locking" the
// ability to upgrade weak pointers or downgrade strong ones; this is used
// to avoid races in `make_unique` and `get_mut`.
weak: atomic::AtomicUsize,
data: T,
}
@ -201,9 +210,25 @@ impl<T: ?Sized> Arc<T> {
#[unstable(feature = "arc_weak",
reason = "Weak pointers may not belong in this module.")]
pub fn downgrade(&self) -> Weak<T> {
// See the clone() impl for why this is relaxed
self.inner().weak.fetch_add(1, Relaxed);
Weak { _ptr: self._ptr }
loop {
// This Relaxed is OK because we're checking the value in the CAS
// below.
let cur = self.inner().weak.load(Relaxed);
// check if the weak counter is currently "locked"; if so, spin.
if cur == usize::MAX { continue }
// NOTE: this code currently ignores the possibility of overflow
// into usize::MAX; in general both Rc and Arc need to be adjusted
// to deal with overflow.
// Unlike with Clone(), we need this to be an Acquire read to
// synchronize with the write coming from `is_unique`, so that the
// events prior to that write happen before this read.
if self.inner().weak.compare_and_swap(cur, cur + 1, Acquire) == cur {
return Weak { _ptr: self._ptr }
}
}
}
/// Get the number of weak references to this value.
@ -241,7 +266,7 @@ impl<T: ?Sized> Arc<T> {
if self.inner().weak.fetch_sub(1, Release) == 1 {
atomic::fence(Acquire);
deallocate(ptr as *mut u8, size_of_val(&*ptr), min_align_of_val(&*ptr))
deallocate(ptr as *mut u8, size_of_val(&*ptr), align_of_val(&*ptr))
}
}
}
@ -258,51 +283,6 @@ pub fn weak_count<T: ?Sized>(this: &Arc<T>) -> usize { Arc::weak_count(this) }
#[deprecated(since = "1.2.0", reason = "renamed to Arc::strong_count")]
pub fn strong_count<T: ?Sized>(this: &Arc<T>) -> usize { Arc::strong_count(this) }
/// Returns a mutable reference to the contained value if the `Arc<T>` is unique.
///
/// Returns `None` if the `Arc<T>` is not unique.
///
/// This function is marked **unsafe** because it is racy if weak pointers
/// are active.
///
/// # Examples
///
/// ```
/// # #![feature(arc_unique, alloc)]
/// extern crate alloc;
/// # fn main() {
/// use alloc::arc::{Arc, get_mut};
///
/// # unsafe {
/// let mut x = Arc::new(3);
/// *get_mut(&mut x).unwrap() = 4;
/// assert_eq!(*x, 4);
///
/// let _y = x.clone();
/// assert!(get_mut(&mut x).is_none());
/// # }
/// # }
/// ```
#[inline]
#[unstable(feature = "arc_unique")]
#[deprecated(since = "1.2.0",
reason = "this function is unsafe with weak pointers")]
pub unsafe fn get_mut<T: ?Sized>(this: &mut Arc<T>) -> Option<&mut T> {
// FIXME(#24880) potential race with upgraded weak pointers here
if Arc::strong_count(this) == 1 && Arc::weak_count(this) == 0 {
// This unsafety is ok because we're guaranteed that the pointer
// returned is the *only* pointer that will ever be returned to T. Our
// reference count is guaranteed to be 1 at this point, and we required
// the Arc itself to be `mut`, so we're returning the only possible
// reference to the inner data.
let inner = &mut **this._ptr;
Some(&mut inner.data)
} else {
None
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: ?Sized> Clone for Arc<T> {
/// Makes a clone of the `Arc<T>`.
@ -350,10 +330,9 @@ impl<T: Clone> Arc<T> {
/// Make a mutable reference from the given `Arc<T>`.
///
/// This is also referred to as a copy-on-write operation because the inner
/// data is cloned if the reference count is greater than one.
///
/// This method is marked **unsafe** because it is racy if weak pointers
/// are active.
/// data is cloned if the (strong) reference count is greater than one. If
/// we hold the only strong reference, any existing weak references will no
/// longer be upgradeable.
///
/// # Examples
///
@ -361,31 +340,138 @@ impl<T: Clone> Arc<T> {
/// # #![feature(arc_unique)]
/// use std::sync::Arc;
///
/// # unsafe {
/// let mut five = Arc::new(5);
///
/// let mut_five = five.make_unique();
/// let mut_five = Arc::make_unique(&mut five);
/// ```
#[inline]
#[unstable(feature = "arc_unique")]
pub fn make_unique(this: &mut Arc<T>) -> &mut T {
// Note that we hold both a strong reference and a weak reference.
// Thus, releasing our strong reference only will not, by itself, cause
// the memory to be deallocated.
//
// Use Acquire to ensure that we see any writes to `weak` that happen
// before release writes (i.e., decrements) to `strong`. Since we hold a
// weak count, there's no chance the ArcInner itself could be
// deallocated.
if this.inner().strong.compare_and_swap(1, 0, Acquire) != 1 {
// Another srong pointer exists; clone
*this = Arc::new((**this).clone());
} else if this.inner().weak.load(Relaxed) != 1 {
// Relaxed suffices in the above because this is fundamentally an
// optimization: we are always racing with weak pointers being
// dropped. Worst case, we end up allocated a new Arc unnecessarily.
// We removed the last strong ref, but there are additional weak
// refs remaining. We'll move the contents to a new Arc, and
// invalidate the other weak refs.
// Note that it is not possible for the read of `weak` to yield
// usize::MAX (i.e., locked), since the weak count can only be
// locked by a thread with a strong reference.
// Materialize our own implicit weak pointer, so that it can clean
// up the ArcInner as needed.
let weak = Weak { _ptr: this._ptr };
// mark the data itself as already deallocated
unsafe {
// there is no data race in the implicit write caused by `read`
// here (due to zeroing) because data is no longer accessed by
// other threads (due to there being no more strong refs at this
// point).
let mut swap = Arc::new(ptr::read(&(**weak._ptr).data));
mem::swap(this, &mut swap);
mem::forget(swap);
}
} else {
// We were the sole reference of either kind; bump back up the
// strong ref count.
this.inner().strong.store(1, Release);
}
// As with `get_mut()`, the unsafety is ok because our reference was
// either unique to begin with, or became one upon cloning the contents.
unsafe {
let inner = &mut **this._ptr;
&mut inner.data
}
}
}
impl<T: ?Sized> Arc<T> {
/// Returns a mutable reference to the contained value if the `Arc<T>` is unique.
///
/// Returns `None` if the `Arc<T>` is not unique.
///
/// # Examples
///
/// ```
/// # #![feature(arc_unique, alloc)]
/// extern crate alloc;
/// # fn main() {
/// use alloc::arc::Arc;
///
/// let mut x = Arc::new(3);
/// *Arc::get_mut(&mut x).unwrap() = 4;
/// assert_eq!(*x, 4);
///
/// let _y = x.clone();
/// assert!(Arc::get_mut(&mut x).is_none());
/// # }
/// ```
#[inline]
#[unstable(feature = "arc_unique")]
#[deprecated(since = "1.2.0",
reason = "this function is unsafe with weak pointers")]
pub unsafe fn make_unique(&mut self) -> &mut T {
// FIXME(#24880) potential race with upgraded weak pointers here
//
// Note that we hold a strong reference, which also counts as a weak
// reference, so we only clone if there is an additional reference of
// either kind.
if self.inner().strong.load(SeqCst) != 1 ||
self.inner().weak.load(SeqCst) != 1 {
*self = Arc::new((**self).clone())
pub fn get_mut(this: &mut Arc<T>) -> Option<&mut T> {
if this.is_unique() {
// This unsafety is ok because we're guaranteed that the pointer
// returned is the *only* pointer that will ever be returned to T. Our
// reference count is guaranteed to be 1 at this point, and we required
// the Arc itself to be `mut`, so we're returning the only possible
// reference to the inner data.
unsafe {
let inner = &mut **this._ptr;
Some(&mut inner.data)
}
} else {
None
}
// As with `get_mut()`, the unsafety is ok because our reference was
// either unique to begin with, or became one upon cloning the contents.
let inner = &mut **self._ptr;
&mut inner.data
}
/// Determine whether this is the unique reference (including weak refs) to
/// the underlying data.
///
/// Note that this requires locking the weak ref count.
fn is_unique(&mut self) -> bool {
// lock the weak pointer count if we appear to be the sole weak pointer
// holder.
//
// The acquire label here ensures a happens-before relationship with any
// writes to `strong` prior to decrements of the `weak` count (via drop,
// which uses Release).
if self.inner().weak.compare_and_swap(1, usize::MAX, Acquire) == 1 {
// Due to the previous acquire read, this will observe any writes to
// `strong` that were due to upgrading weak pointers; only strong
// clones remain, which require that the strong count is > 1 anyway.
let unique = self.inner().strong.load(Relaxed) == 1;
// The release write here synchronizes with a read in `downgrade`,
// effectively preventing the above read of `strong` from happening
// after the write.
self.inner().weak.store(1, Release); // release the lock
unique
} else {
false
}
}
}
#[inline]
#[unstable(feature = "arc_unique")]
#[deprecated(since = "1.2", reason = "use Arc::get_mut instead")]
pub fn get_mut<T: ?Sized>(this: &mut Arc<T>) -> Option<&mut T> {
Arc::get_mut(this)
}
#[stable(feature = "rust1", since = "1.0.0")]
@ -483,9 +569,15 @@ impl<T: ?Sized> Weak<T> {
// fetch_add because once the count hits 0 it must never be above 0.
let inner = self.inner();
loop {
let n = inner.strong.load(SeqCst);
// Relaxed load because any write of 0 that we can observe
// leaves the field in a permanently zero state (so a
// "stale" read of 0 is fine), and any other value is
// confirmed via the CAS below.
let n = inner.strong.load(Relaxed);
if n == 0 { return None }
let old = inner.strong.compare_and_swap(n, n + 1, SeqCst);
// Relaxed is valid for the same reason it is on Arc's Clone impl
let old = inner.strong.compare_and_swap(n, n + 1, Relaxed);
if old == n { return Some(Arc { _ptr: self._ptr }) }
}
}
@ -516,9 +608,12 @@ impl<T: ?Sized> Clone for Weak<T> {
/// ```
#[inline]
fn clone(&self) -> Weak<T> {
// See comments in Arc::clone() for why this is relaxed
// See comments in Arc::clone() for why this is relaxed. This can use a
// fetch_add (ignoring the lock) because the weak count is only locked
// where are *no other* weak pointers in existence. (So we can't be
// running this code in that case).
self.inner().weak.fetch_add(1, Relaxed);
Weak { _ptr: self._ptr }
return Weak { _ptr: self._ptr }
}
}
@ -561,11 +656,16 @@ impl<T: ?Sized> Drop for Weak<T> {
// If we find out that we were the last weak pointer, then its time to
// deallocate the data entirely. See the discussion in Arc::drop() about
// the memory orderings
//
// It's not necessary to check for the locked state here, because the
// weak count can only be locked if there was precisely one weak ref,
// meaning that drop could only subsequently run ON that remaining weak
// ref, which can only happen after the lock is released.
if self.inner().weak.fetch_sub(1, Release) == 1 {
atomic::fence(Acquire);
unsafe { deallocate(ptr as *mut u8,
size_of_val(&*ptr),
min_align_of_val(&*ptr)) }
align_of_val(&*ptr)) }
}
}
}
@ -792,13 +892,13 @@ mod tests {
let mut cow1 = cow0.clone();
let mut cow2 = cow1.clone();
assert!(75 == *cow0.make_unique());
assert!(75 == *cow1.make_unique());
assert!(75 == *cow2.make_unique());
assert!(75 == *Arc::make_unique(&mut cow0));
assert!(75 == *Arc::make_unique(&mut cow1));
assert!(75 == *Arc::make_unique(&mut cow2));
*cow0.make_unique() += 1;
*cow1.make_unique() += 2;
*cow2.make_unique() += 3;
*Arc::make_unique(&mut cow0) += 1;
*Arc::make_unique(&mut cow1) += 2;
*Arc::make_unique(&mut cow2) += 3;
assert!(76 == *cow0);
assert!(77 == *cow1);
@ -822,7 +922,7 @@ mod tests {
assert!(75 == *cow2);
unsafe {
*cow0.make_unique() += 1;
*Arc::make_unique(&mut cow0) += 1;
}
assert!(76 == *cow0);
@ -845,7 +945,7 @@ mod tests {
assert!(75 == *cow1_weak.upgrade().unwrap());
unsafe {
*cow0.make_unique() += 1;
*Arc::make_unique(&mut cow0) += 1;
}
assert!(76 == *cow0);

View File

@ -55,14 +55,17 @@
use core::prelude::*;
use heap;
use core::any::Any;
use core::cmp::Ordering;
use core::fmt;
use core::hash::{self, Hash};
use core::marker::Unsize;
use core::marker::{self, Unsize};
use core::mem;
use core::ops::{CoerceUnsized, Deref, DerefMut};
use core::ptr::{Unique};
use core::ops::{Placer, Boxed, Place, InPlace, BoxPlace};
use core::ptr::Unique;
use core::raw::{TraitObject};
/// A value that represents the heap. This is the default place that the `box`
@ -72,7 +75,7 @@ use core::raw::{TraitObject};
///
/// ```
/// # #![feature(box_heap)]
/// #![feature(box_syntax)]
/// #![feature(box_syntax, placement_in_syntax)]
/// use std::boxed::HEAP;
///
/// fn main() {
@ -83,7 +86,12 @@ use core::raw::{TraitObject};
#[lang = "exchange_heap"]
#[unstable(feature = "box_heap",
reason = "may be renamed; uncertain about custom allocator design")]
pub const HEAP: () = ();
pub const HEAP: ExchangeHeapSingleton =
ExchangeHeapSingleton { _force_singleton: () };
/// This the singleton type used solely for `boxed::HEAP`.
#[derive(Copy, Clone)]
pub struct ExchangeHeapSingleton { _force_singleton: () }
/// A pointer type for heap allocation.
///
@ -91,7 +99,97 @@ pub const HEAP: () = ();
#[lang = "owned_box"]
#[stable(feature = "rust1", since = "1.0.0")]
#[fundamental]
pub struct Box<T>(Unique<T>);
pub struct Box<T: ?Sized>(Unique<T>);
/// `IntermediateBox` represents uninitialized backing storage for `Box`.
///
/// FIXME (pnkfelix): Ideally we would just reuse `Box<T>` instead of
/// introducing a separate `IntermediateBox<T>`; but then you hit
/// issues when you e.g. attempt to destructure an instance of `Box`,
/// since it is a lang item and so it gets special handling by the
/// compiler. Easier just to make this parallel type for now.
///
/// FIXME (pnkfelix): Currently the `box` protocol only supports
/// creating instances of sized types. This IntermediateBox is
/// designed to be forward-compatible with a future protocol that
/// supports creating instances of unsized types; that is why the type
/// parameter has the `?Sized` generalization marker, and is also why
/// this carries an explicit size. However, it probably does not need
/// to carry the explicit alignment; that is just a work-around for
/// the fact that the `align_of` intrinsic currently requires the
/// input type to be Sized (which I do not think is strictly
/// necessary).
#[unstable(feature = "placement_in", reason = "placement box design is still being worked out.")]
pub struct IntermediateBox<T: ?Sized>{
ptr: *mut u8,
size: usize,
align: usize,
marker: marker::PhantomData<*mut T>,
}
impl<T> Place<T> for IntermediateBox<T> {
fn pointer(&mut self) -> *mut T {
unsafe { ::core::mem::transmute(self.ptr) }
}
}
unsafe fn finalize<T>(b: IntermediateBox<T>) -> Box<T> {
let p = b.ptr as *mut T;
mem::forget(b);
mem::transmute(p)
}
fn make_place<T>() -> IntermediateBox<T> {
let size = mem::size_of::<T>();
let align = mem::align_of::<T>();
let p = if size == 0 {
heap::EMPTY as *mut u8
} else {
let p = unsafe {
heap::allocate(size, align)
};
if p.is_null() {
panic!("Box make_place allocation failure.");
}
p
};
IntermediateBox { ptr: p, size: size, align: align, marker: marker::PhantomData }
}
impl<T> BoxPlace<T> for IntermediateBox<T> {
fn make_place() -> IntermediateBox<T> { make_place() }
}
impl<T> InPlace<T> for IntermediateBox<T> {
type Owner = Box<T>;
unsafe fn finalize(self) -> Box<T> { finalize(self) }
}
impl<T> Boxed for Box<T> {
type Data = T;
type Place = IntermediateBox<T>;
unsafe fn finalize(b: IntermediateBox<T>) -> Box<T> { finalize(b) }
}
impl<T> Placer<T> for ExchangeHeapSingleton {
type Place = IntermediateBox<T>;
fn make_place(self) -> IntermediateBox<T> {
make_place()
}
}
impl<T: ?Sized> Drop for IntermediateBox<T> {
fn drop(&mut self) {
if self.size > 0 {
unsafe {
heap::deallocate(self.ptr, self.size, self.align)
}
}
}
}
impl<T> Box<T> {
/// Allocates memory on the heap and then moves `x` into it.
@ -116,7 +214,7 @@ impl<T : ?Sized> Box<T> {
/// of `T` and releases memory. Since the way `Box` allocates and
/// releases memory is unspecified, the only valid pointer to pass
/// to this function is the one taken from another `Box` with
/// `boxed::into_raw` function.
/// `Box::into_raw` function.
///
/// Function is unsafe, because improper use of this function may
/// lead to memory problems like double-free, for example if the
@ -140,10 +238,8 @@ impl<T : ?Sized> Box<T> {
/// # Examples
/// ```
/// # #![feature(box_raw)]
/// use std::boxed;
///
/// let seventeen = Box::new(17u32);
/// let raw = boxed::into_raw(seventeen);
/// let raw = Box::into_raw(seventeen);
/// let boxed_again = unsafe { Box::from_raw(raw) };
/// ```
#[unstable(feature = "box_raw", reason = "may be renamed")]
@ -201,8 +297,7 @@ impl<T: Clone> Clone for Box<T> {
/// let y = x.clone();
/// ```
#[inline]
fn clone(&self) -> Box<T> { box {(**self).clone()} }
fn clone(&self) -> Box<T> { box (HEAP) {(**self).clone()} }
/// Copies `source`'s contents into `self` without creating a new allocation.
///
/// # Examples

View File

@ -76,9 +76,9 @@ fn deref() {
#[test]
fn raw_sized() {
let x = Box::new(17);
let p = Box::into_raw(x);
unsafe {
let x = Box::new(17);
let p = boxed::into_raw(x);
assert_eq!(17, *p);
*p = 19;
let y = Box::from_raw(p);
@ -105,9 +105,9 @@ fn raw_trait() {
}
}
let x: Box<Foo> = Box::new(Bar(17));
let p = Box::into_raw(x);
unsafe {
let x: Box<Foo> = Box::new(Bar(17));
let p = boxed::into_raw(x);
assert_eq!(17, (*p).get());
(*p).set(19);
let y: Box<Foo> = Box::from_raw(p);

View File

@ -70,6 +70,8 @@
test(no_crate_inject))]
#![no_std]
// SNAP d4432b3
#![allow(unused_features)] // until feature(placement_in_syntax) is in snap
#![feature(allocator)]
#![feature(box_syntax)]
#![feature(coerce_unsized)]
@ -82,12 +84,15 @@
#![feature(no_std)]
#![feature(nonzero)]
#![feature(optin_builtin_traits)]
#![feature(placement_in_syntax)]
#![feature(placement_new_protocol)]
#![feature(raw)]
#![feature(staged_api)]
#![feature(unboxed_closures)]
#![feature(unique)]
#![feature(unsafe_no_drop_flag, filling_drop)]
#![feature(unsize)]
#![feature(core_slice_ext)]
#![cfg_attr(test, feature(test, alloc, rustc_private, box_raw))]
#![cfg_attr(all(not(feature = "external_funcs"), not(feature = "external_crate")),
@ -122,6 +127,7 @@ mod boxed { pub use std::boxed::{Box, HEAP}; }
mod boxed_test;
pub mod arc;
pub mod rc;
pub mod raw_vec;
/// Common out-of-memory routine
#[cold]
@ -133,19 +139,3 @@ pub fn oom() -> ! {
// allocate.
unsafe { core::intrinsics::abort() }
}
// FIXME(#14344): When linking liballoc with libstd, this library will be linked
// as an rlib (it only exists as an rlib). It turns out that an
// optimized standard library doesn't actually use *any* symbols
// from this library. Everything is inlined and optimized away.
// This means that linkers will actually omit the object for this
// file, even though it may be needed in the future.
//
// To get around this for now, we define a dummy symbol which
// will never get inlined so the stdlib can call it. The stdlib's
// reference to this symbol will cause this library's object file
// to get linked in to libstd successfully (the linker won't
// optimize it out).
#[doc(hidden)]
#[unstable(feature = "issue_14344_fixme")]
pub fn fixme_14344_be_sure_to_link_to_collections() {}

453
src/liballoc/raw_vec.rs Normal file
View File

@ -0,0 +1,453 @@
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use core::ptr::Unique;
use core::mem;
use core::slice::{self, SliceExt};
use heap;
use super::oom;
use super::boxed::Box;
use core::ops::Drop;
/// A low-level utility for more ergonomically allocating, reallocating, and deallocating a
/// a buffer of memory on the heap without having to worry about all the corner cases
/// involved. This type is excellent for building your own data structures like Vec and VecDeque.
/// In particular:
///
/// * Produces heap::EMPTY on zero-sized types
/// * Produces heap::EMPTY on zero-length allocations
/// * Catches all overflows in capacity computations (promotes them to "capacity overflow" panics)
/// * Guards against 32-bit systems allocating more than isize::MAX bytes
/// * Guards against overflowing your length
/// * Aborts on OOM
/// * Avoids freeing heap::EMPTY
/// * Contains a ptr::Unique and thus endows the user with all related benefits
///
/// This type does not in anyway inspect the memory that it manages. When dropped it *will*
/// free its memory, but it *won't* try to Drop its contents. It is up to the user of RawVec
/// to handle the actual things *stored* inside of a RawVec.
///
/// Note that a RawVec always forces its capacity to be usize::MAX for zero-sized types.
/// This enables you to use capacity growing logic catch the overflows in your length
/// that might occur with zero-sized types.
///
/// However this means that you need to be careful when roundtripping this type
/// with a `Box<[T]>`: `cap()` won't yield the len. However `with_capacity`,
/// `shrink_to_fit`, and `from_box` will actually set RawVec's private capacity
/// field. This allows zero-sized types to not be special-cased by consumers of
/// this type.
#[unsafe_no_drop_flag]
pub struct RawVec<T> {
ptr: Unique<T>,
cap: usize,
}
impl<T> RawVec<T> {
/// Creates the biggest possible RawVec without allocating. If T has positive
/// size, then this makes a RawVec with capacity 0. If T has 0 size, then it
/// it makes a RawVec with capacity `usize::MAX`. Useful for implementing
/// delayed allocation.
pub fn new() -> Self {
unsafe {
// !0 is usize::MAX. This branch should be stripped at compile time.
let cap = if mem::size_of::<T>() == 0 { !0 } else { 0 };
// heap::EMPTY doubles as "unallocated" and "zero-sized allocation"
RawVec { ptr: Unique::new(heap::EMPTY as *mut T), cap: cap }
}
}
/// Creates a RawVec with exactly the capacity and alignment requirements
/// for a `[T; cap]`. This is equivalent to calling RawVec::new when `cap` is 0
/// or T is zero-sized. Note that if `T` is zero-sized this means you will *not*
/// get a RawVec with the requested capacity!
///
/// # Panics
///
/// * Panics if the requested capacity exceeds `usize::MAX` bytes.
/// * Panics on 32-bit platforms if the requested capacity exceeds
/// `isize::MAX` bytes.
///
/// # Aborts
///
/// Aborts on OOM
pub fn with_capacity(cap: usize) -> Self {
unsafe {
let elem_size = mem::size_of::<T>();
let alloc_size = cap.checked_mul(elem_size).expect("capacity overflow");
alloc_guard(alloc_size);
// handles ZSTs and `cap = 0` alike
let ptr = if alloc_size == 0 {
heap::EMPTY as *mut u8
} else {
let align = mem::align_of::<T>();
let ptr = heap::allocate(alloc_size, align);
if ptr.is_null() { oom() }
ptr
};
RawVec { ptr: Unique::new(ptr as *mut _), cap: cap }
}
}
/// Reconstitutes a RawVec from a pointer and capacity.
///
/// # Undefined Behaviour
///
/// The ptr must be allocated, and with the given capacity. The
/// capacity cannot exceed `isize::MAX` (only a concern on 32-bit systems).
/// If the ptr and capacity come from a RawVec, then this is guaranteed.
pub unsafe fn from_raw_parts(ptr: *mut T, cap: usize) -> Self {
RawVec { ptr: Unique::new(ptr), cap: cap }
}
/// Converts a `Box<[T]>` into a `RawVec<T>`.
pub fn from_box(mut slice: Box<[T]>) -> Self {
unsafe {
let result = RawVec::from_raw_parts(slice.as_mut_ptr(), slice.len());
mem::forget(slice);
result
}
}
}
impl<T> RawVec<T> {
/// Gets a raw pointer to the start of the allocation. Note that this is
/// heap::EMPTY if `cap = 0` or T is zero-sized. In the former case, you must
/// be careful.
pub fn ptr(&self) -> *mut T {
*self.ptr
}
/// Gets the capacity of the allocation.
///
/// This will always be `usize::MAX` if `T` is zero-sized.
pub fn cap(&self) -> usize {
if mem::size_of::<T>() == 0 { !0 } else { self.cap }
}
/// Doubles the size of the type's backing allocation. This is common enough
/// to want to do that it's easiest to just have a dedicated method. Slightly
/// more efficient logic can be provided for this than the general case.
///
/// This function is ideal for when pushing elements one-at-a-time because
/// you don't need to incur the costs of the more general computations
/// reserve needs to do to guard against overflow. You do however need to
/// manually check if your `len == cap`.
///
/// # Panics
///
/// * Panics if T is zero-sized on the assumption that you managed to exhaust
/// all `usize::MAX` slots in your imaginary buffer.
/// * Panics on 32-bit platforms if the requested capacity exceeds
/// `isize::MAX` bytes.
///
/// # Aborts
///
/// Aborts on OOM
///
/// # Examples
///
/// ```ignore
/// struct MyVec<T> {
/// buf: RawVec<T>,
/// len: usize,
/// }
///
/// impl<T> MyVec<T> {
/// pub fn push(&mut self, elem: T) {
/// if self.len == self.buf.cap() { self.buf.double(); }
/// // double would have aborted or panicked if the len exceeded
/// // `isize::MAX` so this is safe to do unchecked now.
/// unsafe {
/// ptr::write(self.buf.ptr().offset(self.len as isize), elem);
/// }
/// self.len += 1;
/// }
/// }
/// ```
#[inline(never)]
#[cold]
pub fn double(&mut self) {
unsafe {
let elem_size = mem::size_of::<T>();
// since we set the capacity to usize::MAX when elem_size is
// 0, getting to here necessarily means the RawVec is overfull.
assert!(elem_size != 0, "capacity overflow");
let align = mem::align_of::<T>();
let (new_cap, ptr) = if self.cap == 0 {
// skip to 4 because tiny Vec's are dumb; but not if that would cause overflow
let new_cap = if elem_size > (!0) / 8 { 1 } else { 4 };
let ptr = heap::allocate(new_cap * elem_size, align);
(new_cap, ptr)
} else {
// Since we guarantee that we never allocate more than isize::MAX bytes,
// `elem_size * self.cap <= isize::MAX` as a precondition, so this can't overflow
let new_cap = 2 * self.cap;
let new_alloc_size = new_cap * elem_size;
alloc_guard(new_alloc_size);
let ptr = heap::reallocate(self.ptr() as *mut _,
self.cap * elem_size,
new_alloc_size,
align);
(new_cap, ptr)
};
// If allocate or reallocate fail, we'll get `null` back
if ptr.is_null() { oom() }
self.ptr = Unique::new(ptr as *mut _);
self.cap = new_cap;
}
}
/// Ensures that the buffer contains at least enough space to hold
/// `used_cap + needed_extra_cap` elements. If it doesn't already,
/// will reallocate the minimum possible amount of memory necessary.
/// Generally this will be exactly the amount of memory necessary,
/// but in principle the allocator is free to give back more than
/// we asked for.
///
/// If `used_cap` exceeds `self.cap()`, this may fail to actually allocate
/// the requested space. This is not really unsafe, but the unsafe
/// code *you* write that relies on the behaviour of this function may break.
///
/// # Panics
///
/// * Panics if the requested capacity exceeds `usize::MAX` bytes.
/// * Panics on 32-bit platforms if the requested capacity exceeds
/// `isize::MAX` bytes.
///
/// # Aborts
///
/// Aborts on OOM
pub fn reserve_exact(&mut self, used_cap: usize, needed_extra_cap: usize) {
unsafe {
let elem_size = mem::size_of::<T>();
let align = mem::align_of::<T>();
// NOTE: we don't early branch on ZSTs here because we want this
// to actually catch "asking for more than usize::MAX" in that case.
// If we make it past the first branch then we are guaranteed to
// panic.
// Don't actually need any more capacity.
// Wrapping in case they gave a bad `used_cap`.
if self.cap().wrapping_sub(used_cap) >= needed_extra_cap { return; }
// Nothing we can really do about these checks :(
let new_cap = used_cap.checked_add(needed_extra_cap).expect("capacity overflow");
let new_alloc_size = new_cap.checked_mul(elem_size).expect("capacity overflow");
alloc_guard(new_alloc_size);
let ptr = if self.cap == 0 {
heap::allocate(new_alloc_size, align)
} else {
heap::reallocate(self.ptr() as *mut _,
self.cap * elem_size,
new_alloc_size,
align)
};
// If allocate or reallocate fail, we'll get `null` back
if ptr.is_null() { oom() }
self.ptr = Unique::new(ptr as *mut _);
self.cap = new_cap;
}
}
/// Ensures that the buffer contains at least enough space to hold
/// `used_cap + needed_extra_cap` elements. If it doesn't already have
/// enough capacity, will reallocate enough space plus comfortable slack
/// space to get amortized `O(1)` behaviour. Will limit this behaviour
/// if it would needlessly cause itself to panic.
///
/// If `used_cap` exceeds `self.cap()`, this may fail to actually allocate
/// the requested space. This is not really unsafe, but the unsafe
/// code *you* write that relies on the behaviour of this function may break.
///
/// This is ideal for implementing a bulk-push operation like `extend`.
///
/// # Panics
///
/// * Panics if the requested capacity exceeds `usize::MAX` bytes.
/// * Panics on 32-bit platforms if the requested capacity exceeds
/// `isize::MAX` bytes.
///
/// # Aborts
///
/// Aborts on OOM
///
/// # Examples
///
/// ```ignore
/// struct MyVec<T> {
/// buf: RawVec<T>,
/// len: usize,
/// }
///
/// impl<T> MyVec<T> {
/// pub fn push_all(&mut self, elems: &[T]) {
/// self.buf.reserve(self.len, elems.len());
/// // reserve would have aborted or panicked if the len exceeded
/// // `isize::MAX` so this is safe to do unchecked now.
/// for x in elems {
/// unsafe {
/// ptr::write(self.buf.ptr().offset(self.len as isize), x.clone());
/// }
/// self.len += 1;
/// }
/// }
/// }
/// ```
pub fn reserve(&mut self, used_cap: usize, needed_extra_cap: usize) {
unsafe {
let elem_size = mem::size_of::<T>();
let align = mem::align_of::<T>();
// NOTE: we don't early branch on ZSTs here because we want this
// to actually catch "asking for more than usize::MAX" in that case.
// If we make it past the first branch then we are guaranteed to
// panic.
// Don't actually need any more capacity.
// Wrapping in case they give a bas `used_cap`
if self.cap().wrapping_sub(used_cap) >= needed_extra_cap { return; }
// Nothing we can really do about these checks :(
let new_cap = used_cap.checked_add(needed_extra_cap)
.and_then(|cap| cap.checked_mul(2))
.expect("capacity overflow");
let new_alloc_size = new_cap.checked_mul(elem_size).expect("capacity overflow");
// FIXME: may crash and burn on over-reserve
alloc_guard(new_alloc_size);
let ptr = if self.cap == 0 {
heap::allocate(new_alloc_size, align)
} else {
heap::reallocate(self.ptr() as *mut _,
self.cap * elem_size,
new_alloc_size,
align)
};
// If allocate or reallocate fail, we'll get `null` back
if ptr.is_null() { oom() }
self.ptr = Unique::new(ptr as *mut _);
self.cap = new_cap;
}
}
/// Shrinks the allocation down to the specified amount. If the given amount
/// is 0, actually completely deallocates.
///
/// # Panics
///
/// Panics if the given amount is *larger* than the current capacity.
///
/// # Aborts
///
/// Aborts on OOM.
pub fn shrink_to_fit(&mut self, amount: usize) {
let elem_size = mem::size_of::<T>();
let align = mem::align_of::<T>();
// Set the `cap` because they might be about to promote to a `Box<[T]>`
if elem_size == 0 {
self.cap = amount;
return;
}
// This check is my waterloo; it's the only thing Vec wouldn't have to do.
assert!(self.cap >= amount, "Tried to shrink to a larger capacity");
if amount == 0 {
mem::replace(self, RawVec::new());
} else if self.cap != amount {
unsafe {
// Overflow check is unnecessary as the vector is already at
// least this large.
let ptr = heap::reallocate(self.ptr() as *mut _,
self.cap * elem_size,
amount * elem_size,
align);
if ptr.is_null() { oom() }
self.ptr = Unique::new(ptr as *mut _);
}
self.cap = amount;
}
}
/// Converts the entire buffer into `Box<[T]>`.
///
/// While it is not *strictly* Undefined Behaviour to call
/// this procedure while some of the RawVec is unintialized,
/// it cetainly makes it trivial to trigger it.
///
/// Note that this will correctly reconstitute any `cap` changes
/// that may have been performed. (see description of type for details)
pub unsafe fn into_box(self) -> Box<[T]> {
// NOTE: not calling `cap()` here, actually using the real `cap` field!
let slice = slice::from_raw_parts_mut(self.ptr(), self.cap);
let output: Box<[T]> = Box::from_raw(slice);
mem::forget(self);
output
}
/// This is a stupid name in the hopes that someone will find this in the
/// not too distant future and remove it with the rest of
/// #[unsafe_no_drop_flag]
pub fn unsafe_no_drop_flag_needs_drop(&self) -> bool {
self.cap != mem::POST_DROP_USIZE
}
}
impl<T> Drop for RawVec<T> {
/// Frees the memory owned by the RawVec *without* trying to Drop its contents.
fn drop(&mut self) {
let elem_size = mem::size_of::<T>();
if elem_size != 0 && self.cap != 0 && self.unsafe_no_drop_flag_needs_drop() {
let align = mem::align_of::<T>();
let num_bytes = elem_size * self.cap;
unsafe {
heap::deallocate(*self.ptr as *mut _, num_bytes, align);
}
}
}
}
// We need to guarantee the following:
// * We don't ever allocate `> isize::MAX` byte-size objects
// * We don't overflow `usize::MAX` and actually allocate too little
//
// On 64-bit we just need to check for overflow since trying to allocate
// `> isize::MAX` bytes will surely fail. On 32-bit we need to add an extra
// guard for this in case we're running on a platform which can use all 4GB in
// user-space. e.g. PAE or x32
#[inline]
#[cfg(target_pointer_width = "64")]
fn alloc_guard(_alloc_size: usize) { }
#[inline]
#[cfg(target_pointer_width = "32")]
fn alloc_guard(alloc_size: usize) {
assert!(alloc_size <= ::core::isize::MAX as usize, "capacity overflow");
}

View File

@ -162,7 +162,7 @@ use core::fmt;
use core::hash::{Hasher, Hash};
use core::intrinsics::{assume, drop_in_place};
use core::marker::{self, Unsize};
use core::mem::{self, min_align_of, size_of, min_align_of_val, size_of_val, forget};
use core::mem::{self, align_of, size_of, align_of_val, size_of_val, forget};
use core::nonzero::NonZero;
use core::ops::{CoerceUnsized, Deref};
use core::ptr;
@ -246,7 +246,7 @@ impl<T> Rc<T> {
// destruct the box and skip our Drop
// we can ignore the refcounts because we know we're unique
deallocate(*rc._ptr as *mut u8, size_of::<RcBox<T>>(),
min_align_of::<RcBox<T>>());
align_of::<RcBox<T>>());
forget(rc);
Ok(val)
}
@ -496,7 +496,7 @@ impl<T: ?Sized> Drop for Rc<T> {
if self.weak() == 0 {
deallocate(ptr as *mut u8,
size_of_val(&*ptr),
min_align_of_val(&*ptr))
align_of_val(&*ptr))
}
}
}
@ -734,6 +734,8 @@ pub struct Weak<T: ?Sized> {
impl<T: ?Sized> !marker::Send for Weak<T> {}
impl<T: ?Sized> !marker::Sync for Weak<T> {}
impl<T: ?Sized+Unsize<U>, U: ?Sized> CoerceUnsized<Weak<U>> for Weak<T> {}
#[unstable(feature = "rc_weak",
reason = "Weak pointers may not belong in this module.")]
impl<T: ?Sized> Weak<T> {
@ -805,7 +807,7 @@ impl<T: ?Sized> Drop for Weak<T> {
// the strong pointers have disappeared.
if self.weak() == 0 {
deallocate(ptr as *mut u8, size_of_val(&*ptr),
min_align_of_val(&*ptr))
align_of_val(&*ptr))
}
}
}

View File

@ -244,7 +244,7 @@ impl<'longer_than_self> Arena<'longer_than_self> {
fn alloc_copy<T, F>(&self, op: F) -> &mut T where F: FnOnce() -> T {
unsafe {
let ptr = self.alloc_copy_inner(mem::size_of::<T>(),
mem::min_align_of::<T>());
mem::align_of::<T>());
let ptr = ptr as *mut T;
ptr::write(&mut (*ptr), op());
return &mut *ptr;
@ -300,7 +300,7 @@ impl<'longer_than_self> Arena<'longer_than_self> {
let tydesc = get_tydesc::<T>();
let (ty_ptr, ptr) =
self.alloc_noncopy_inner(mem::size_of::<T>(),
mem::min_align_of::<T>());
mem::align_of::<T>());
let ty_ptr = ty_ptr as *mut usize;
let ptr = ptr as *mut T;
// Write in our tydesc along with a bit indicating that it
@ -393,7 +393,7 @@ struct TypedArenaChunk<T> {
fn calculate_size<T>(capacity: usize) -> usize {
let mut size = mem::size_of::<TypedArenaChunk<T>>();
size = round_up(size, mem::min_align_of::<T>());
size = round_up(size, mem::align_of::<T>());
let elem_size = mem::size_of::<T>();
let elems_size = elem_size.checked_mul(capacity).unwrap();
size = size.checked_add(elems_size).unwrap();
@ -405,7 +405,7 @@ impl<T> TypedArenaChunk<T> {
unsafe fn new(next: *mut TypedArenaChunk<T>, capacity: usize)
-> *mut TypedArenaChunk<T> {
let size = calculate_size::<T>(capacity);
let chunk = allocate(size, mem::min_align_of::<TypedArenaChunk<T>>())
let chunk = allocate(size, mem::align_of::<TypedArenaChunk<T>>())
as *mut TypedArenaChunk<T>;
if chunk.is_null() { alloc::oom() }
(*chunk).next = next;
@ -431,7 +431,7 @@ impl<T> TypedArenaChunk<T> {
let size = calculate_size::<T>(self.capacity);
let self_ptr: *mut TypedArenaChunk<T> = self;
deallocate(self_ptr as *mut u8, size,
mem::min_align_of::<TypedArenaChunk<T>>());
mem::align_of::<TypedArenaChunk<T>>());
if !next.is_null() {
let capacity = (*next).capacity;
(*next).destroy(capacity);
@ -444,7 +444,7 @@ impl<T> TypedArenaChunk<T> {
let this: *const TypedArenaChunk<T> = self;
unsafe {
mem::transmute(round_up(this.offset(1) as usize,
mem::min_align_of::<T>()))
mem::align_of::<T>()))
}
}

View File

@ -8,6 +8,11 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![deprecated(reason = "BitVec and BitSet have been migrated to cargo as bit-vec and bit-set",
since = "1.3.0")]
#![unstable(feature = "collections", reason = "deprecated")]
#![allow(deprecated)]
// FIXME(Gankro): BitVec and BitSet are very tightly coupled. Ideally (for
// maintenance), they should be in separate files/modules, with BitSet only
// using BitVec's public API. This will be hard for performance though, because
@ -278,7 +283,7 @@ impl BitVec {
pub fn from_elem(nbits: usize, bit: bool) -> BitVec {
let nblocks = blocks_for_bits(nbits);
let mut bit_vec = BitVec {
storage: repeat(if bit { !0 } else { 0 }).take(nblocks).collect(),
storage: vec![if bit { !0 } else { 0 }; nblocks],
nbits: nbits
};
bit_vec.fix_last_block();

View File

@ -215,7 +215,7 @@ impl<'a, B: ?Sized> Clone for Cow<'a, B> where B: ToOwned {
impl<'a, B: ?Sized> Cow<'a, B> where B: ToOwned {
/// Acquires a mutable reference to the owned form of the data.
///
/// Copies the data if it is not already owned.
/// Clones the data if it is not already owned.
///
/// # Examples
///
@ -241,7 +241,7 @@ impl<'a, B: ?Sized> Cow<'a, B> where B: ToOwned {
/// Extracts the owned data.
///
/// Copies the data if it is not already owned.
/// Clones the data if it is not already owned.
///
/// # Examples
///

View File

@ -163,12 +163,12 @@ fn test_offset_calculation() {
}
fn calculate_allocation_generic<K, V>(capacity: usize, is_leaf: bool) -> (usize, usize) {
let (keys_size, keys_align) = (capacity * mem::size_of::<K>(), mem::min_align_of::<K>());
let (vals_size, vals_align) = (capacity * mem::size_of::<V>(), mem::min_align_of::<V>());
let (keys_size, keys_align) = (capacity * mem::size_of::<K>(), mem::align_of::<K>());
let (vals_size, vals_align) = (capacity * mem::size_of::<V>(), mem::align_of::<V>());
let (edges_size, edges_align) = if is_leaf {
(0, 1)
} else {
((capacity + 1) * mem::size_of::<Node<K, V>>(), mem::min_align_of::<Node<K, V>>())
((capacity + 1) * mem::size_of::<Node<K, V>>(), mem::align_of::<Node<K, V>>())
};
calculate_allocation(
@ -181,11 +181,11 @@ fn calculate_allocation_generic<K, V>(capacity: usize, is_leaf: bool) -> (usize,
fn calculate_offsets_generic<K, V>(capacity: usize, is_leaf: bool) -> (usize, usize) {
let keys_size = capacity * mem::size_of::<K>();
let vals_size = capacity * mem::size_of::<V>();
let vals_align = mem::min_align_of::<V>();
let vals_align = mem::align_of::<V>();
let edges_align = if is_leaf {
1
} else {
mem::min_align_of::<Node<K, V>>()
mem::align_of::<Node<K, V>>()
};
calculate_offsets(

View File

@ -128,15 +128,15 @@
//! This allows multiple actual types to be formatted via `{:x}` (like `i8` as
//! well as `isize`). The current mapping of types to traits is:
//!
//! * *nothing* ⇒ `Display`
//! * `?` ⇒ `Debug`
//! * `o` ⇒ `Octal`
//! * `x` ⇒ `LowerHex`
//! * `X` ⇒ `UpperHex`
//! * `p` ⇒ `Pointer`
//! * `b` ⇒ `Binary`
//! * `e` ⇒ `LowerExp`
//! * `E` ⇒ `UpperExp`
//! * *nothing* ⇒ [`Display`](trait.Display.html)
//! * `?` ⇒ [`Debug`](trait.Debug.html)
//! * `o` ⇒ [`Octal`](trait.Octal.html)
//! * `x` ⇒ [`LowerHex`](trait.LowerHex.html)
//! * `X` ⇒ [`UpperHex`](trait.UpperHex.html)
//! * `p` ⇒ [`Pointer`](trait.Pointer.html)
//! * `b` ⇒ [`Binary`](trait.Binary.html)
//! * `e` ⇒ [`LowerExp`](trait.LowerExp.html)
//! * `E` ⇒ [`UpperExp`](trait.UpperExp.html)
//!
//! What this means is that any type of argument which implements the
//! `fmt::Binary` trait can then be formatted with `{:b}`. Implementations
@ -367,11 +367,11 @@
//! should always be printed.
//! * '-' - Currently not used
//! * '#' - This flag is indicates that the "alternate" form of printing should
//! be used. For array slices, the alternate form omits the brackets.
//! For the integer formatting traits, the alternate forms are:
//! be used. The alternate forms are:
//! * `#?` - pretty-print the `Debug` formatting
//! * `#x` - precedes the argument with a "0x"
//! * `#X` - precedes the argument with a "0x"
//! * `#t` - precedes the argument with a "0b"
//! * `#b` - precedes the argument with a "0b"
//! * `#o` - precedes the argument with a "0o"
//! * '0' - This is used to indicate for integer formats that the padding should
//! both be done with a `0` character as well as be sign-aware. A format
@ -408,19 +408,20 @@
//!
//! There are three possible ways to specify the desired `precision`:
//!
//! There are three possible ways to specify the desired `precision`:
//! 1. An integer `.N`,
//! 2. an integer followed by dollar sign `.N$`, or
//! 3. an asterisk `.*`.
//! 1. An integer `.N`:
//!
//! The first specification, `.N`, means the integer `N` itself is the precision.
//! the integer `N` itself is the precision.
//!
//! The second, `.N$`, means use format *argument* `N` (which must be a `usize`) as the precision.
//! 2. An integer followed by dollar sign `.N$`:
//!
//! Finally, `.*` means that this `{...}` is associated with *two* format inputs rather than one:
//! the first input holds the `usize` precision, and the second holds the value to print. Note
//! that in this case, if one uses the format string `{<arg>:<spec>.*}`, then the `<arg>` part
//! refers to the *value* to print, and the `precision` must come in the input preceding `<arg>`.
//! use format *argument* `N` (which must be a `usize`) as the precision.
//!
//! 3. An asterisk `.*`:
//!
//! `.*` means that this `{...}` is associated with *two* format inputs rather than one: the
//! first input holds the `usize` precision, and the second holds the value to print. Note that
//! in this case, if one uses the format string `{<arg>:<spec>.*}`, then the `<arg>` part refers
//! to the *value* to print, and the `precision` must come in the input preceding `<arg>`.
//!
//! For example, these:
//!

View File

@ -32,7 +32,6 @@
#![feature(alloc)]
#![feature(box_patterns)]
#![feature(box_raw)]
#![feature(box_syntax)]
#![feature(core)]
#![feature(core_intrinsics)]
@ -77,7 +76,9 @@ extern crate alloc;
#[cfg(test)] extern crate test;
pub use binary_heap::BinaryHeap;
#[allow(deprecated)]
pub use bit_vec::BitVec;
#[allow(deprecated)]
pub use bit_set::BitSet;
pub use btree_map::BTreeMap;
pub use btree_set::BTreeSet;
@ -111,11 +112,13 @@ pub mod vec_map;
#[unstable(feature = "bitvec", reason = "RFC 509")]
pub mod bit_vec {
#![allow(deprecated)]
pub use bit::{BitVec, Iter};
}
#[unstable(feature = "bitset", reason = "RFC 509")]
pub mod bit_set {
#![allow(deprecated)]
pub use bit::{BitSet, Union, Intersection, Difference, SymmetricDifference};
pub use bit::SetIter as Iter;
}
@ -130,12 +133,6 @@ pub mod btree_set {
pub use btree::set::*;
}
// FIXME(#14344) this shouldn't be necessary
#[doc(hidden)]
#[unstable(feature = "issue_14344_fixme")]
pub fn fixme_14344_be_sure_to_link_to_collections() {}
#[cfg(not(test))]
mod std {
pub use core::ops; // RangeFull

View File

@ -8,9 +8,8 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
//! Utilities for slice manipulation
//! A dynamically-sized view into a contiguous sequence, `[T]`.
//!
//! The `slice` module contains useful code to help work with slice values.
//! Slices are a view into a block of memory represented as a pointer and a
//! length.
//!
@ -78,7 +77,8 @@
//! iterators.
//! * Further methods that return iterators are `.split()`, `.splitn()`,
//! `.chunks()`, `.windows()` and more.
#![doc(primitive = "slice")]
//!
//! *[See also the slice primitive type](../primitive.slice.html).*
#![stable(feature = "rust1", since = "1.0.0")]
// Many of the usings in this module are only used in the test configuration.
@ -282,34 +282,65 @@ impl<T> [T] {
/// Returns all but the first element of a slice.
#[unstable(feature = "slice_extras", reason = "likely to be renamed")]
#[deprecated(since = "1.3.0", reason = "superseded by split_first")]
#[inline]
pub fn tail(&self) -> &[T] {
core_slice::SliceExt::tail(self)
}
/// Returns the first and all the rest of the elements of a slice.
#[unstable(feature = "slice_splits", reason = "new API")]
#[inline]
pub fn split_first(&self) -> Option<(&T, &[T])> {
core_slice::SliceExt::split_first(self)
}
/// Returns all but the first element of a mutable slice
#[unstable(feature = "slice_extras",
reason = "likely to be renamed or removed")]
#[unstable(feature = "slice_extras", reason = "likely to be renamed or removed")]
#[deprecated(since = "1.3.0", reason = "superseded by split_first_mut")]
#[inline]
pub fn tail_mut(&mut self) -> &mut [T] {
core_slice::SliceExt::tail_mut(self)
}
/// Returns the first and all the rest of the elements of a slice.
#[unstable(feature = "slice_splits", reason = "new API")]
#[inline]
pub fn split_first_mut(&mut self) -> Option<(&mut T, &mut [T])> {
core_slice::SliceExt::split_first_mut(self)
}
/// Returns all but the last element of a slice.
#[unstable(feature = "slice_extras", reason = "likely to be renamed")]
#[deprecated(since = "1.3.0", reason = "superseded by split_last")]
#[inline]
pub fn init(&self) -> &[T] {
core_slice::SliceExt::init(self)
}
/// Returns the last and all the rest of the elements of a slice.
#[unstable(feature = "slice_splits", reason = "new API")]
#[inline]
pub fn split_last(&self) -> Option<(&T, &[T])> {
core_slice::SliceExt::split_last(self)
}
/// Returns all but the last element of a mutable slice
#[unstable(feature = "slice_extras",
reason = "likely to be renamed or removed")]
#[unstable(feature = "slice_extras", reason = "likely to be renamed or removed")]
#[deprecated(since = "1.3.0", reason = "superseded by split_last_mut")]
#[inline]
pub fn init_mut(&mut self) -> &mut [T] {
core_slice::SliceExt::init_mut(self)
}
/// Returns the last and all the rest of the elements of a slice.
#[unstable(feature = "slice_splits", since = "1.3.0")]
#[inline]
pub fn split_last_mut(&mut self) -> Option<(&mut T, &mut [T])> {
core_slice::SliceExt::split_last_mut(self)
}
/// Returns the last element of a slice, or `None` if it is empty.
///
/// # Examples
@ -1025,6 +1056,17 @@ pub trait SliceConcatExt<T: ?Sized> {
#[stable(feature = "rust1", since = "1.0.0")]
fn concat(&self) -> Self::Output;
/// Flattens a slice of `T` into a single value `Self::Output`, placing a
/// given separator between each.
///
/// # Examples
///
/// ```
/// assert_eq!(["hello", "world"].join(" "), "hello world");
/// ```
#[stable(feature = "rename_connect_to_join", since = "1.3.0")]
fn join(&self, sep: &T) -> Self::Output;
/// Flattens a slice of `T` into a single value `Self::Output`, placing a
/// given separator between each.
///
@ -1034,6 +1076,7 @@ pub trait SliceConcatExt<T: ?Sized> {
/// assert_eq!(["hello", "world"].connect(" "), "hello world");
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[deprecated(since = "1.3.0", reason = "renamed to join")]
fn connect(&self, sep: &T) -> Self::Output;
}
@ -1049,7 +1092,7 @@ impl<T: Clone, V: Borrow<[T]>> SliceConcatExt<T> for [V] {
result
}
fn connect(&self, sep: &T) -> Vec<T> {
fn join(&self, sep: &T) -> Vec<T> {
let size = self.iter().fold(0, |acc, v| acc + v.borrow().len());
let mut result = Vec::with_capacity(size + self.len());
let mut first = true;
@ -1059,6 +1102,10 @@ impl<T: Clone, V: Borrow<[T]>> SliceConcatExt<T> for [V] {
}
result
}
fn connect(&self, sep: &T) -> Vec<T> {
self.join(sep)
}
}
/// An iterator that yields the element swaps needed to produce

View File

@ -8,43 +8,11 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
//! Unicode string manipulation (the `str` type).
//! Unicode string slices
//!
//! Rust's `str` type is one of the core primitive types of the language. `&str`
//! is the borrowed string type. This type of string can only be created from
//! other strings, unless it is a `&'static str` (see below). It is not possible
//! to move out of borrowed strings because they are owned elsewhere.
//!
//! # Examples
//!
//! Here's some code that uses a `&str`:
//!
//! ```
//! let s = "Hello, world.";
//! ```
//!
//! This `&str` is a `&'static str`, which is the type of string literals.
//! They're `'static` because literals are available for the entire lifetime of
//! the program.
//!
//! You can get a non-`'static` `&str` by taking a slice of a `String`:
//!
//! ```
//! let some_string = "Hello, world.".to_string();
//! let s = &some_string;
//! ```
//!
//! # Representation
//!
//! Rust's string type, `str`, is a sequence of Unicode scalar values encoded as
//! a stream of UTF-8 bytes. All [strings](../../reference.html#literals) are
//! guaranteed to be validly encoded UTF-8 sequences. Additionally, strings are
//! not null-terminated and can thus contain null bytes.
//!
//! The actual representation of `str`s have direct mappings to slices: `&str`
//! is the same as `&[u8]`.
//! *[See also the `str` primitive type](../primitive.str.html).*
#![doc(primitive = "str")]
#![stable(feature = "rust1", since = "1.0.0")]
// Many of the usings in this module are only used in the test configuration.
@ -61,6 +29,7 @@ use core::result::Result;
use core::str as core_str;
use core::str::pattern::Pattern;
use core::str::pattern::{Searcher, ReverseSearcher, DoubleEndedSearcher};
use core::mem;
use rustc_unicode::str::{UnicodeStr, Utf16Encoder};
use vec_deque::VecDeque;
@ -69,6 +38,7 @@ use string::String;
use rustc_unicode;
use vec::Vec;
use slice::SliceConcatExt;
use boxed::Box;
pub use core::str::{FromStr, Utf8Error};
pub use core::str::{Lines, LinesAny, CharRange};
@ -82,10 +52,6 @@ pub use core::str::{from_utf8_unchecked, ParseBoolError};
pub use rustc_unicode::str::{SplitWhitespace, Words, Graphemes, GraphemeIndices};
pub use core::str::pattern;
/*
Section: Creating a string
*/
impl<S: Borrow<str>> SliceConcatExt<str> for [S] {
type Output = String;
@ -105,7 +71,7 @@ impl<S: Borrow<str>> SliceConcatExt<str> for [S] {
result
}
fn connect(&self, sep: &str) -> String {
fn join(&self, sep: &str) -> String {
if self.is_empty() {
return String::new();
}
@ -132,11 +98,11 @@ impl<S: Borrow<str>> SliceConcatExt<str> for [S] {
}
result
}
}
/*
Section: Iterators
*/
fn connect(&self, sep: &str) -> String {
self.join(sep)
}
}
// Helper functions used for Unicode normalization
fn canonical_sort(comb: &mut [(char, u8)]) {
@ -382,10 +348,6 @@ impl<'a> Iterator for Utf16Units<'a> {
fn size_hint(&self) -> (usize, Option<usize>) { self.encoder.size_hint() }
}
/*
Section: Misc
*/
// Return the initial codepoint accumulator for the first byte.
// The first byte is special, only want bottom 5 bits for width 2, 4 bits
// for width 3, and 3 bits for width 4
@ -414,15 +376,6 @@ impl ToOwned for str {
}
}
/*
Section: CowString
*/
/*
Section: Trait implementations
*/
/// Any string that can be represented as a slice.
#[lang = "str"]
#[cfg(not(test))]
@ -483,9 +436,7 @@ impl str {
/// considered to be
/// boundaries.
///
/// # Panics
///
/// Panics if `index` is greater than `self.len()`.
/// Returns `false` if `index` is greater than `self.len()`.
///
/// # Examples
///
@ -549,7 +500,7 @@ impl str {
///
/// # Unsafety
///
/// Caller must check both UTF-8 character boundaries and the boundaries
/// Caller must check both UTF-8 sequence boundaries and the boundaries
/// of the entire slice as
/// well.
///
@ -567,15 +518,24 @@ impl str {
core_str::StrExt::slice_unchecked(self, begin, end)
}
/// Returns a slice of the string from the character range [`begin`..`end`).
/// Takes a bytewise mutable slice from a string.
///
/// Same as `slice_unchecked`, but works with `&mut str` instead of `&str`.
#[unstable(feature = "str_slice_mut", reason = "recently added")]
pub unsafe fn slice_mut_unchecked(&mut self, begin: usize, end: usize) -> &mut str {
core_str::StrExt::slice_mut_unchecked(self, begin, end)
}
/// Returns a slice of the string from the range [`begin`..`end`) where indices
/// are counted in code points.
///
/// That is, start at the `begin`-th code point of the string and continue
/// to the `end`-th code point. This does not detect or handle edge cases
/// such as leaving a combining character as the first code point of the
/// such as leaving a combining character as the first `char` of the
/// string.
///
/// Due to the design of UTF-8, this operation is `O(end)`. Use slicing
/// syntax if you want to use byte indices rather than codepoint indices.
/// syntax if you want to use `O(1)` byte indices instead.
///
/// # Panics
///
@ -597,18 +557,18 @@ impl str {
core_str::StrExt::slice_chars(self, begin, end)
}
/// Given a byte position, return the next char and its index.
/// Given a byte position, return the next code point and its index.
///
/// This can be used to iterate over the Unicode characters of a string.
/// This can be used to iterate over the Unicode code points of a string.
///
/// # Panics
///
/// If `i` is greater than or equal to the length of the string.
/// If `i` is not the index of the beginning of a valid UTF-8 character.
/// If `i` is not the index of the beginning of a valid UTF-8 sequence.
///
/// # Examples
///
/// This example manually iterates through the characters of a string;
/// This example manually iterates through the code points of a string;
/// this should normally be
/// done by `.chars()` or `.char_indices()`.
///
@ -616,7 +576,7 @@ impl str {
/// # #![feature(str_char, core)]
/// use std::str::CharRange;
///
/// let s = "中华Vit Nam";
/// let s = "中华Việt Nam";
/// let mut i = 0;
/// while i < s.len() {
/// let CharRange {ch, next} = s.char_range_at(i);
@ -632,12 +592,14 @@ impl str {
/// 3: 华
/// 6: V
/// 7: i
/// 8: ệ
/// 11: t
/// 12:
/// 13: N
/// 14: a
/// 15: m
/// 8: e
/// 9: ̣
/// 11: ̂
/// 13: t
/// 14:
/// 15: N
/// 16: a
/// 17: m
/// ```
#[unstable(feature = "str_char",
reason = "often replaced by char_indices, this method may \
@ -649,18 +611,21 @@ impl str {
/// Given a byte position, return the previous `char` and its position.
///
/// This function can be used to iterate over a Unicode string in reverse.
/// This function can be used to iterate over a Unicode code points in reverse.
///
/// Note that Unicode has many features, such as combining marks, ligatures,
/// and direction marks, that need to be taken into account to correctly reverse a string.
///
/// Returns 0 for next index if called on start index 0.
///
/// # Panics
///
/// If `i` is greater than the length of the string.
/// If `i` is not an index following a valid UTF-8 character.
/// If `i` is not an index following a valid UTF-8 sequence.
///
/// # Examples
///
/// This example manually iterates through the characters of a string;
/// This example manually iterates through the code points of a string;
/// this should normally be
/// done by `.chars().rev()` or `.char_indices()`.
///
@ -668,7 +633,7 @@ impl str {
/// # #![feature(str_char, core)]
/// use std::str::CharRange;
///
/// let s = "中华Vit Nam";
/// let s = "中华Việt Nam";
/// let mut i = s.len();
/// while i > 0 {
/// let CharRange {ch, next} = s.char_range_at_reverse(i);
@ -680,12 +645,14 @@ impl str {
/// This outputs:
///
/// ```text
/// 16: m
/// 15: a
/// 14: N
/// 13:
/// 12: t
/// 11: ệ
/// 18: m
/// 17: a
/// 16: N
/// 15:
/// 14: t
/// 13: ̂
/// 11: ̣
/// 9: e
/// 8: i
/// 7: V
/// 6: 华
@ -704,7 +671,7 @@ impl str {
/// # Panics
///
/// If `i` is greater than or equal to the length of the string.
/// If `i` is not the index of the beginning of a valid UTF-8 character.
/// If `i` is not the index of the beginning of a valid UTF-8 sequence.
///
/// # Examples
///
@ -713,6 +680,7 @@ impl str {
/// let s = "abπc";
/// assert_eq!(s.char_at(1), 'b');
/// assert_eq!(s.char_at(2), 'π');
/// assert_eq!(s.char_at(4), 'c');
/// ```
#[unstable(feature = "str_char",
reason = "frequently replaced by the chars() iterator, this \
@ -730,7 +698,7 @@ impl str {
/// # Panics
///
/// If `i` is greater than the length of the string.
/// If `i` is not an index following a valid UTF-8 character.
/// If `i` is not an index following a valid UTF-8 sequence.
///
/// # Examples
///
@ -739,6 +707,7 @@ impl str {
/// let s = "abπc";
/// assert_eq!(s.char_at_reverse(1), 'a');
/// assert_eq!(s.char_at_reverse(2), 'b');
/// assert_eq!(s.char_at_reverse(3), 'π');
/// ```
#[unstable(feature = "str_char",
reason = "see char_at for more details, but reverse semantics \
@ -748,28 +717,30 @@ impl str {
core_str::StrExt::char_at_reverse(self, i)
}
/// Retrieves the first character from a `&str` and returns it.
/// Retrieves the first code point from a `&str` and returns it.
///
/// Note that a single Unicode character (grapheme cluster)
/// can be composed of multiple `char`s.
///
/// This does not allocate a new string; instead, it returns a slice that
/// points one character
/// beyond the character that was shifted.
/// points one code point beyond the code point that was shifted.
///
/// If the slice does not contain any characters, None is returned instead.
/// `None` is returned if the slice is empty.
///
/// # Examples
///
/// ```
/// # #![feature(str_char)]
/// let s = "Löwe 老虎 Léopard";
/// let s = "Łódź"; // \u{141}o\u{301}dz\u{301}
/// let (c, s1) = s.slice_shift_char().unwrap();
///
/// assert_eq!(c, 'L');
/// assert_eq!(s1, "öwe 老虎 Léopard");
/// assert_eq!(c, 'Ł');
/// assert_eq!(s1, "ódź");
///
/// let (c, s2) = s1.slice_shift_char().unwrap();
///
/// assert_eq!(c, 'ö');
/// assert_eq!(s2, "we 老虎 Léopard");
/// assert_eq!(c, 'o');
/// assert_eq!(s2, "\u{301}dz\u{301}");
/// ```
#[unstable(feature = "str_char",
reason = "awaiting conventions about shifting and slices and \
@ -782,18 +753,18 @@ impl str {
/// Divide one string slice into two at an index.
///
/// The index `mid` is a byte offset from the start of the string
/// that must be on a character boundary.
/// that must be on a `char` boundary.
///
/// Return slices `&self[..mid]` and `&self[mid..]`.
///
/// # Panics
///
/// Panics if `mid` is beyond the last character of the string,
/// or if it is not on a character boundary.
/// Panics if `mid` is beyond the last code point of the string,
/// or if it is not on a `char` boundary.
///
/// # Examples
/// ```
/// # #![feature(collections)]
/// # #![feature(str_split_at)]
/// let s = "Löwe 老虎 Léopard";
/// let first_space = s.find(' ').unwrap_or(s.len());
/// let (a, b) = s.split_at(first_space);
@ -802,31 +773,51 @@ impl str {
/// assert_eq!(b, " 老虎 Léopard");
/// ```
#[inline]
#[unstable(feature = "str_split_at", reason = "recently added")]
pub fn split_at(&self, mid: usize) -> (&str, &str) {
core_str::StrExt::split_at(self, mid)
}
/// An iterator over the codepoints of `self`.
/// Divide one mutable string slice into two at an index.
#[inline]
#[unstable(feature = "str_split_at", reason = "recently added")]
pub fn split_at_mut(&mut self, mid: usize) -> (&mut str, &mut str) {
core_str::StrExt::split_at_mut(self, mid)
}
/// An iterator over the code points of `self`.
///
/// In Unicode relationship between code points and characters is complex.
/// A single character may be composed of multiple code points
/// (e.g. diacritical marks added to a letter), and a single code point
/// (e.g. Hangul syllable) may contain multiple characters.
///
/// For iteration over human-readable characters a grapheme cluster iterator
/// may be more appropriate. See the [unicode-segmentation crate][1].
///
/// [1]: https://crates.io/crates/unicode-segmentation
///
/// # Examples
///
/// ```
/// let v: Vec<char> = "abc åäö".chars().collect();
/// let v: Vec<char> = "ASCII żółć 🇨🇭 한".chars().collect();
///
/// assert_eq!(v, ['a', 'b', 'c', ' ', 'å', 'ä', 'ö']);
/// assert_eq!(v, ['A', 'S', 'C', 'I', 'I', ' ',
/// 'z', '\u{307}', 'o', '\u{301}', 'ł', 'c', '\u{301}', ' ',
/// '\u{1f1e8}', '\u{1f1ed}', ' ', '한']);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn chars(&self) -> Chars {
core_str::StrExt::chars(self)
}
/// An iterator over the characters of `self` and their byte offsets.
/// An iterator over the `char`s of `self` and their byte offsets.
///
/// # Examples
///
/// ```
/// let v: Vec<(usize, char)> = "abc".char_indices().collect();
/// let b = vec![(0, 'a'), (1, 'b'), (2, 'c')];
/// let v: Vec<(usize, char)> = "A🇨🇭".char_indices().collect();
/// let b = vec![(0, 'A'), (1, '\u{1f1e8}'), (5, '\u{1f1ed}')];
///
/// assert_eq!(v, b);
/// ```
@ -855,7 +846,7 @@ impl str {
/// # Examples
///
/// ```
/// let some_words = " Mary had\ta little \n\t lamb";
/// let some_words = " Mary had\ta\u{2009}little \n\t lamb";
/// let v: Vec<&str> = some_words.split_whitespace().collect();
///
/// assert_eq!(v, ["Mary", "had", "a", "little", "lamb"]);
@ -873,7 +864,7 @@ impl str {
/// ```
/// # #![feature(str_words)]
/// # #![allow(deprecated)]
/// let some_words = " Mary had\ta little \n\t lamb";
/// let some_words = " Mary had\ta\u{2009}little \n\t lamb";
/// let v: Vec<&str> = some_words.words().collect();
///
/// assert_eq!(v, ["Mary", "had", "a", "little", "lamb"]);
@ -1859,8 +1850,6 @@ impl str {
/// # Examples
///
/// ```
/// #![feature(str_casing)]
///
/// let s = "HELLO";
/// assert_eq!(s.to_lowercase(), "hello");
/// ```
@ -1905,8 +1894,6 @@ impl str {
/// # Examples
///
/// ```
/// #![feature(str_casing)]
///
/// let s = "hello";
/// assert_eq!(s.to_uppercase(), "HELLO");
/// ```
@ -1930,4 +1917,14 @@ impl str {
pub fn escape_unicode(&self) -> String {
self.chars().flat_map(|c| c.escape_unicode()).collect()
}
/// Converts the `Box<str>` into a `String` without copying or allocating.
#[unstable(feature = "box_str",
reason = "recently added, matches RFC")]
pub fn into_string(self: Box<str>) -> String {
unsafe {
let slice = mem::transmute::<Box<str>, Box<[u8]>>(self);
String::from_utf8_unchecked(slice.into_vec())
}
}
}

View File

@ -28,7 +28,8 @@ use rustc_unicode::str::Utf16Item;
use borrow::{Cow, IntoCow};
use range::RangeArgument;
use str::{self, FromStr, Utf8Error, Chars};
use vec::{DerefVec, Vec, as_vec};
use vec::Vec;
use boxed::Box;
/// A growable string stored as a UTF-8 encoded buffer.
#[derive(Clone, PartialOrd, Eq, Ord)]
@ -317,9 +318,14 @@ impl String {
/// Creates a new `String` from a length, capacity, and pointer.
///
/// This is unsafe because:
/// # Unsafety
///
/// * We call `Vec::from_raw_parts` to get a `Vec<u8>`;
/// This is _very_ unsafe because:
///
/// * We call `Vec::from_raw_parts` to get a `Vec<u8>`. Therefore, this
/// function inherits all of its unsafety, see [its
/// documentation](../vec/struct.Vec.html#method.from_raw_parts)
/// for the invariants it expects, they also apply to this function.
/// * We assume that the `Vec` contains valid UTF-8.
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
@ -736,6 +742,16 @@ impl String {
string: self_ptr,
}
}
/// Converts the string into `Box<str>`.
///
/// Note that this will drop any excess capacity.
#[unstable(feature = "box_str",
reason = "recently added, matches RFC")]
pub fn into_boxed_slice(self) -> Box<str> {
let slice = self.vec.into_boxed_slice();
unsafe { mem::transmute::<Box<[u8]>, Box<str>>(slice) }
}
}
impl FromUtf8Error {
@ -963,6 +979,35 @@ impl ops::Index<ops::RangeFull> for String {
}
}
#[stable(feature = "derefmut_for_string", since = "1.2.0")]
impl ops::IndexMut<ops::Range<usize>> for String {
#[inline]
fn index_mut(&mut self, index: ops::Range<usize>) -> &mut str {
&mut self[..][index]
}
}
#[stable(feature = "derefmut_for_string", since = "1.2.0")]
impl ops::IndexMut<ops::RangeTo<usize>> for String {
#[inline]
fn index_mut(&mut self, index: ops::RangeTo<usize>) -> &mut str {
&mut self[..][index]
}
}
#[stable(feature = "derefmut_for_string", since = "1.2.0")]
impl ops::IndexMut<ops::RangeFrom<usize>> for String {
#[inline]
fn index_mut(&mut self, index: ops::RangeFrom<usize>) -> &mut str {
&mut self[..][index]
}
}
#[stable(feature = "derefmut_for_string", since = "1.2.0")]
impl ops::IndexMut<ops::RangeFull> for String {
#[inline]
fn index_mut(&mut self, _index: ops::RangeFull) -> &mut str {
unsafe { mem::transmute(&mut *self.vec) }
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl ops::Deref for String {
type Target = str;
@ -973,49 +1018,14 @@ impl ops::Deref for String {
}
}
/// Wrapper type providing a `&String` reference via `Deref`.
#[unstable(feature = "collections")]
#[deprecated(since = "1.2.0",
reason = "replaced with deref coercions or Borrow")]
#[allow(deprecated)]
pub struct DerefString<'a> {
x: DerefVec<'a, u8>
}
#[allow(deprecated)]
impl<'a> Deref for DerefString<'a> {
type Target = String;
#[stable(feature = "derefmut_for_string", since = "1.2.0")]
impl ops::DerefMut for String {
#[inline]
fn deref<'b>(&'b self) -> &'b String {
unsafe { mem::transmute(&*self.x) }
fn deref_mut(&mut self) -> &mut str {
unsafe { mem::transmute(&mut self.vec[..]) }
}
}
/// Converts a string slice to a wrapper type providing a `&String` reference.
///
/// # Examples
///
/// ```
/// # #![feature(collections)]
/// use std::string::as_string;
///
/// // Let's pretend we have a function that requires `&String`
/// fn string_consumer(s: &String) {
/// assert_eq!(s, "foo");
/// }
///
/// // Provide a `&String` from a `&str` without allocating
/// string_consumer(&as_string("foo"));
/// ```
#[unstable(feature = "collections")]
#[deprecated(since = "1.2.0",
reason = "replaced with deref coercions or Borrow")]
#[allow(deprecated)]
pub fn as_string<'a>(x: &'a str) -> DerefString<'a> {
DerefString { x: as_vec(x.as_bytes()) }
}
/// Error returned from `String::from`
#[unstable(feature = "str_parse_error", reason = "may want to be replaced with \
Void if it ever exists")]

View File

@ -59,32 +59,25 @@
#![stable(feature = "rust1", since = "1.0.0")]
use core::prelude::*;
use alloc::raw_vec::RawVec;
use alloc::boxed::Box;
use alloc::heap::{EMPTY, allocate, reallocate, deallocate};
use core::cmp::max;
use alloc::heap::EMPTY;
use core::cmp::Ordering;
use core::fmt;
use core::hash::{self, Hash};
use core::intrinsics::{arith_offset, assume};
use core::iter::{repeat, FromIterator};
use core::intrinsics::{arith_offset, assume, drop_in_place};
use core::iter::FromIterator;
use core::marker::PhantomData;
use core::mem;
use core::ops::{Index, IndexMut, Deref};
use core::ops;
use core::ptr;
use core::ptr::Unique;
use core::slice;
use core::isize;
use core::usize;
use borrow::{Cow, IntoCow};
use super::range::RangeArgument;
// FIXME- fix places which assume the max vector allowed has memory usize::MAX.
const MAX_MEMORY_SIZE: usize = isize::MAX as usize;
/// A growable list type, written `Vec<T>` but pronounced 'vector.'
///
/// # Examples
@ -152,14 +145,10 @@ const MAX_MEMORY_SIZE: usize = isize::MAX as usize;
#[unsafe_no_drop_flag]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Vec<T> {
ptr: Unique<T>,
buf: RawVec<T>,
len: usize,
cap: usize,
}
unsafe impl<T: Send> Send for Vec<T> { }
unsafe impl<T: Sync> Sync for Vec<T> { }
////////////////////////////////////////////////////////////////////////////////
// Inherent methods
////////////////////////////////////////////////////////////////////////////////
@ -177,11 +166,7 @@ impl<T> Vec<T> {
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn new() -> Vec<T> {
// We want ptr to never be NULL so instead we set it to some arbitrary
// non-null value which is fine since we never call deallocate on the ptr
// if cap is 0. The reason for this is because the pointer of a slice
// being NULL would break the null pointer optimization for enums.
unsafe { Vec::from_raw_parts(EMPTY as *mut T, 0, 0) }
Vec { buf: RawVec::new(), len: 0 }
}
/// Constructs a new, empty `Vec<T>` with the specified capacity.
@ -212,22 +197,23 @@ impl<T> Vec<T> {
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn with_capacity(capacity: usize) -> Vec<T> {
if mem::size_of::<T>() == 0 {
unsafe { Vec::from_raw_parts(EMPTY as *mut T, 0, usize::MAX) }
} else if capacity == 0 {
Vec::new()
} else {
let size = capacity.checked_mul(mem::size_of::<T>())
.expect("capacity overflow");
let ptr = unsafe { allocate(size, mem::min_align_of::<T>()) };
if ptr.is_null() { ::alloc::oom() }
unsafe { Vec::from_raw_parts(ptr as *mut T, 0, capacity) }
}
Vec { buf: RawVec::with_capacity(capacity), len: 0 }
}
/// Creates a `Vec<T>` directly from the raw components of another vector.
///
/// This is highly unsafe, due to the number of invariants that aren't checked.
/// # Unsafety
///
/// This is highly unsafe, due to the number of invariants that aren't
/// checked:
///
/// * `ptr` needs to have been previously allocated via `String`/`Vec<T>`
/// (at least, it's highly likely to be incorrect if it wasn't).
/// * `length` needs to be the length that less than or equal to `capacity`.
/// * `capacity` needs to be the capacity that the pointer was allocated with.
///
/// Violating these may cause problems like corrupting the allocator's
/// internal datastructures.
///
/// # Examples
///
@ -263,9 +249,8 @@ impl<T> Vec<T> {
pub unsafe fn from_raw_parts(ptr: *mut T, length: usize,
capacity: usize) -> Vec<T> {
Vec {
ptr: Unique::new(ptr),
buf: RawVec::from_raw_parts(ptr, capacity),
len: length,
cap: capacity,
}
}
@ -299,7 +284,7 @@ impl<T> Vec<T> {
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn capacity(&self) -> usize {
self.cap
self.buf.cap()
}
/// Reserves capacity for at least `additional` more elements to be inserted
@ -319,17 +304,7 @@ impl<T> Vec<T> {
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn reserve(&mut self, additional: usize) {
if self.cap - self.len < additional {
const ERR_MSG: &'static str = "Vec::reserve: `isize` overflow";
let new_min_cap = self.len.checked_add(additional).expect(ERR_MSG);
if new_min_cap > MAX_MEMORY_SIZE { panic!(ERR_MSG) }
self.grow_capacity(match new_min_cap.checked_next_power_of_two() {
Some(x) if x > MAX_MEMORY_SIZE => MAX_MEMORY_SIZE,
None => MAX_MEMORY_SIZE,
Some(x) => x,
});
}
self.buf.reserve(self.len, additional);
}
/// Reserves the minimum capacity for exactly `additional` more elements to
@ -353,12 +328,7 @@ impl<T> Vec<T> {
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn reserve_exact(&mut self, additional: usize) {
if self.cap - self.len < additional {
match self.len.checked_add(additional) {
None => panic!("Vec::reserve: `usize` overflow"),
Some(new_cap) => self.grow_capacity(new_cap)
}
}
self.buf.reserve_exact(self.len, additional);
}
/// Shrinks the capacity of the vector as much as possible.
@ -377,28 +347,7 @@ impl<T> Vec<T> {
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn shrink_to_fit(&mut self) {
if mem::size_of::<T>() == 0 { return }
if self.len == 0 {
if self.cap != 0 {
unsafe {
dealloc(*self.ptr, self.cap)
}
self.cap = 0;
}
} else if self.cap != self.len {
unsafe {
// Overflow check is unnecessary as the vector is already at
// least this large.
let ptr = reallocate(*self.ptr as *mut u8,
self.cap * mem::size_of::<T>(),
self.len * mem::size_of::<T>(),
mem::min_align_of::<T>()) as *mut T;
if ptr.is_null() { ::alloc::oom() }
self.ptr = Unique::new(ptr);
}
self.cap = self.len;
}
self.buf.shrink_to_fit(self.len);
}
/// Converts the vector into Box<[T]>.
@ -408,11 +357,11 @@ impl<T> Vec<T> {
/// `shrink_to_fit()`.
#[stable(feature = "rust1", since = "1.0.0")]
pub fn into_boxed_slice(mut self) -> Box<[T]> {
self.shrink_to_fit();
unsafe {
let xs: Box<[T]> = Box::from_raw(&mut *self);
self.shrink_to_fit();
let buf = ptr::read(&self.buf);
mem::forget(self);
xs
buf.into_box()
}
}
@ -529,8 +478,9 @@ impl<T> Vec<T> {
pub fn insert(&mut self, index: usize, element: T) {
let len = self.len();
assert!(index <= len);
// space for the new element
self.reserve(1);
if len == self.buf.cap() { self.buf.double(); }
unsafe { // infallible
// The spot to put the new value
@ -538,10 +488,10 @@ impl<T> Vec<T> {
let p = self.as_mut_ptr().offset(index as isize);
// Shift everything over to make space. (Duplicating the
// `index`th element into two consecutive places.)
ptr::copy(&*p, p.offset(1), len - index);
ptr::copy(p, p.offset(1), len - index);
// Write it in, overwriting the first copy of the `index`th
// element.
ptr::write(&mut *p, element);
ptr::write(p, element);
}
self.set_len(len + 1);
}
@ -575,7 +525,7 @@ impl<T> Vec<T> {
ret = ptr::read(ptr);
// Shift everything down to fill in that spot.
ptr::copy(&*ptr.offset(1), ptr, len - index - 1);
ptr::copy(ptr.offset(1), ptr, len - index - 1);
}
self.set_len(len - 1);
ret
@ -631,38 +581,12 @@ impl<T> Vec<T> {
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn push(&mut self, value: T) {
#[cold]
#[inline(never)]
fn resize<T>(vec: &mut Vec<T>) {
let old_size = vec.cap * mem::size_of::<T>();
if old_size >= MAX_MEMORY_SIZE { panic!("capacity overflow") }
let mut size = max(old_size, 2 * mem::size_of::<T>()) * 2;
if old_size > size || size > MAX_MEMORY_SIZE {
size = MAX_MEMORY_SIZE;
}
unsafe {
let ptr = alloc_or_realloc(*vec.ptr, old_size, size);
if ptr.is_null() { ::alloc::oom() }
vec.ptr = Unique::new(ptr);
}
vec.cap = max(vec.cap, 2) * 2;
}
if mem::size_of::<T>() == 0 {
// zero-size types consume no memory, so we can't rely on the
// address space running out
self.len = self.len.checked_add(1).expect("length overflow");
mem::forget(value);
return
}
if self.len == self.cap {
resize(self);
}
// This will panic or abort if we would allocate > isize::MAX bytes
// or if the length increment would overflow for zero-sized types.
if self.len == self.buf.cap() { self.buf.double(); }
unsafe {
let end = (*self.ptr).offset(self.len as isize);
ptr::write(&mut *end, value);
let end = self.as_mut_ptr().offset(self.len as isize);
ptr::write(end, value);
self.len += 1;
}
}
@ -709,13 +633,6 @@ impl<T> Vec<T> {
#[unstable(feature = "append",
reason = "new API, waiting for dust to settle")]
pub fn append(&mut self, other: &mut Self) {
if mem::size_of::<T>() == 0 {
// zero-size types consume no memory, so we can't rely on the
// address space running out
self.len = self.len.checked_add(other.len()).expect("length overflow");
unsafe { other.set_len(0) }
return;
}
self.reserve(other.len());
let len = self.len();
unsafe {
@ -866,9 +783,9 @@ impl<T> Vec<T> {
// FIXME: Assert statically that the types `T` and `U` have the
// same minimal alignment in case they are not zero-sized.
// These asserts are necessary because the `min_align_of` of the
// These asserts are necessary because the `align_of` of the
// types are passed to the allocator by `Vec`.
assert!(mem::min_align_of::<T>() == mem::min_align_of::<U>());
assert!(mem::align_of::<T>() == mem::align_of::<U>());
// This `as isize` cast is safe, because the size of the elements of the
// vector is not 0, and:
@ -1099,12 +1016,35 @@ impl<T: Clone> Vec<T> {
let len = self.len();
if new_len > len {
self.extend(repeat(value).take(new_len - len));
self.extend_with_element(new_len - len, value);
} else {
self.truncate(new_len);
}
}
/// Extend the vector by `n` additional clones of `value`.
fn extend_with_element(&mut self, n: usize, value: T) {
self.reserve(n);
unsafe {
let len = self.len();
let mut ptr = self.as_mut_ptr().offset(len as isize);
// Write all elements except the last one
for i in 1..n {
ptr::write(ptr, value.clone());
ptr = ptr.offset(1);
// Increment the length in every step in case clone() panics
self.set_len(len + i);
}
if n > 0 {
// We can write the last element directly without cloning needlessly
ptr::write(ptr, value);
self.set_len(len + n);
}
}
}
/// Appends all elements in a slice to the `Vec`.
///
/// Iterates over the slice `other`, clones each element, and then appends
@ -1244,68 +1184,12 @@ impl<T: PartialEq> Vec<T> {
// Internal methods and functions
////////////////////////////////////////////////////////////////////////////////
impl<T> Vec<T> {
/// Reserves capacity for exactly `capacity` elements in the given vector.
///
/// If the capacity for `self` is already equal to or greater than the
/// requested capacity, then no action is taken.
fn grow_capacity(&mut self, capacity: usize) {
if mem::size_of::<T>() == 0 { return }
if capacity > self.cap {
let size = capacity.checked_mul(mem::size_of::<T>())
.expect("capacity overflow");
unsafe {
let ptr = alloc_or_realloc(*self.ptr, self.cap * mem::size_of::<T>(), size);
if ptr.is_null() { ::alloc::oom() }
self.ptr = Unique::new(ptr);
}
self.cap = capacity;
}
}
}
// FIXME: #13996: need a way to mark the return value as `noalias`
#[inline(never)]
unsafe fn alloc_or_realloc<T>(ptr: *mut T, old_size: usize, size: usize) -> *mut T {
if old_size == 0 {
allocate(size, mem::min_align_of::<T>()) as *mut T
} else {
reallocate(ptr as *mut u8, old_size, size, mem::min_align_of::<T>()) as *mut T
}
}
#[inline]
unsafe fn dealloc<T>(ptr: *mut T, len: usize) {
if mem::size_of::<T>() != 0 {
deallocate(ptr as *mut u8,
len * mem::size_of::<T>(),
mem::min_align_of::<T>())
}
}
#[doc(hidden)]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn from_elem<T: Clone>(elem: T, n: usize) -> Vec<T> {
unsafe {
let mut v = Vec::with_capacity(n);
let mut ptr = v.as_mut_ptr();
// Write all elements except the last one
for i in 1..n {
ptr::write(ptr, Clone::clone(&elem));
ptr = ptr.offset(1);
v.set_len(i); // Increment the length in every step in case Clone::clone() panics
}
if n > 0 {
// We can write the last element directly without cloning needlessly
ptr::write(ptr, elem);
v.set_len(n);
}
v
}
let mut v = Vec::with_capacity(n);
v.extend_with_element(n, elem);
v
}
////////////////////////////////////////////////////////////////////////////////
@ -1449,7 +1333,7 @@ impl<T> ops::Deref for Vec<T> {
fn deref(&self) -> &[T] {
unsafe {
let p = *self.ptr;
let p = self.buf.ptr();
assume(p != 0 as *mut T);
slice::from_raw_parts(p, self.len)
}
@ -1460,7 +1344,7 @@ impl<T> ops::Deref for Vec<T> {
impl<T> ops::DerefMut for Vec<T> {
fn deref_mut(&mut self) -> &mut [T] {
unsafe {
let ptr = *self.ptr;
let ptr = self.buf.ptr();
assume(!ptr.is_null());
slice::from_raw_parts_mut(ptr, self.len)
}
@ -1482,7 +1366,7 @@ impl<T> FromIterator<T> for Vec<T> {
None => return Vec::new(),
Some(element) => {
let (lower, _) = iterator.size_hint();
let mut vector = Vec::with_capacity(1 + lower);
let mut vector = Vec::with_capacity(lower.saturating_add(1));
unsafe {
ptr::write(vector.get_unchecked_mut(0), element);
vector.set_len(1);
@ -1514,19 +1398,19 @@ impl<T> IntoIterator for Vec<T> {
/// }
/// ```
#[inline]
fn into_iter(self) -> IntoIter<T> {
fn into_iter(mut self) -> IntoIter<T> {
unsafe {
let ptr = *self.ptr;
let ptr = self.as_mut_ptr();
assume(!ptr.is_null());
let cap = self.cap;
let begin = ptr as *const T;
let end = if mem::size_of::<T>() == 0 {
arith_offset(ptr as *const i8, self.len() as isize) as *const T
} else {
ptr.offset(self.len() as isize) as *const T
};
let buf = ptr::read(&self.buf);
mem::forget(self);
IntoIter { allocation: ptr, cap: cap, ptr: begin, end: end }
IntoIter { buf: buf, ptr: begin, end: end }
}
}
}
@ -1570,10 +1454,11 @@ impl<T> Vec<T> {
let len = self.len();
if len == self.capacity() {
let (lower, _) = iterator.size_hint();
self.reserve(lower + 1);
self.reserve(lower.saturating_add(1));
}
unsafe {
ptr::write(self.get_unchecked_mut(len), element);
// NB can't overflow since we would have had to alloc the address space
self.set_len(len + 1);
}
}
@ -1637,16 +1522,16 @@ impl<T: Ord> Ord for Vec<T> {
#[stable(feature = "rust1", since = "1.0.0")]
impl<T> Drop for Vec<T> {
fn drop(&mut self) {
// This is (and should always remain) a no-op if the fields are
// zeroed (when moving out, because of #[unsafe_no_drop_flag]).
if self.cap != 0 && self.cap != mem::POST_DROP_USIZE {
unsafe {
for x in self.iter() {
ptr::read(x);
}
dealloc(*self.ptr, self.cap)
// NOTE: this is currently abusing the fact that ZSTs can't impl Drop.
// Or rather, that impl'ing Drop makes them not zero-sized. This is
// OK because exactly when this stops being a valid assumption, we
// don't need unsafe_no_drop_flag shenanigans anymore.
if self.buf.unsafe_no_drop_flag_needs_drop() {
for x in self.iter_mut() {
unsafe { drop_in_place(x); }
}
}
// RawVec handles deallocation
}
}
@ -1730,8 +1615,7 @@ impl<'a, T> IntoCow<'a, [T]> for &'a [T] where T: Clone {
/// An iterator that moves out of a vector.
#[stable(feature = "rust1", since = "1.0.0")]
pub struct IntoIter<T> {
allocation: *mut T, // the block of memory allocated for the vector
cap: usize, // the capacity of the vector
buf: RawVec<T>,
ptr: *const T,
end: *const T
}
@ -1746,9 +1630,9 @@ impl<T> IntoIter<T> {
pub fn into_inner(mut self) -> Vec<T> {
unsafe {
for _x in self.by_ref() { }
let IntoIter { allocation, cap, ptr: _ptr, end: _end } = self;
let buf = ptr::read(&self.buf);
mem::forget(self);
Vec::from_raw_parts(allocation, 0, cap)
Vec { buf: buf, len: 0 }
}
}
}
@ -1826,12 +1710,9 @@ impl<T> ExactSizeIterator for IntoIter<T> {}
impl<T> Drop for IntoIter<T> {
fn drop(&mut self) {
// destroy the remaining elements
if self.cap != 0 {
for _x in self.by_ref() {}
unsafe {
dealloc(self.allocation, self.cap);
}
}
for _x in self.by_ref() {}
// RawVec handles deallocation
}
}
@ -1905,73 +1786,6 @@ impl<'a, T> Drop for Drain<'a, T> {
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T> ExactSizeIterator for Drain<'a, T> {}
////////////////////////////////////////////////////////////////////////////////
// Conversion from &[T] to &Vec<T>
////////////////////////////////////////////////////////////////////////////////
/// Wrapper type providing a `&Vec<T>` reference via `Deref`.
#[unstable(feature = "collections")]
#[deprecated(since = "1.2.0",
reason = "replaced with deref coercions or Borrow")]
pub struct DerefVec<'a, T:'a> {
x: Vec<T>,
l: PhantomData<&'a T>,
}
#[unstable(feature = "collections")]
#[deprecated(since = "1.2.0",
reason = "replaced with deref coercions or Borrow")]
#[allow(deprecated)]
impl<'a, T> Deref for DerefVec<'a, T> {
type Target = Vec<T>;
fn deref<'b>(&'b self) -> &'b Vec<T> {
&self.x
}
}
// Prevent the inner `Vec<T>` from attempting to deallocate memory.
#[stable(feature = "rust1", since = "1.0.0")]
#[deprecated(since = "1.2.0",
reason = "replaced with deref coercions or Borrow")]
#[allow(deprecated)]
impl<'a, T> Drop for DerefVec<'a, T> {
fn drop(&mut self) {
self.x.len = 0;
self.x.cap = 0;
}
}
/// Converts a slice to a wrapper type providing a `&Vec<T>` reference.
///
/// # Examples
///
/// ```
/// # #![feature(collections)]
/// use std::vec::as_vec;
///
/// // Let's pretend we have a function that requires `&Vec<i32>`
/// fn vec_consumer(s: &Vec<i32>) {
/// assert_eq!(s, &[1, 2, 3]);
/// }
///
/// // Provide a `&Vec<i32>` from a `&[i32]` without allocating
/// let values = [1, 2, 3];
/// vec_consumer(&as_vec(&values));
/// ```
#[unstable(feature = "collections")]
#[deprecated(since = "1.2.0",
reason = "replaced with deref coercions or Borrow")]
#[allow(deprecated)]
pub fn as_vec<'a, T>(x: &'a [T]) -> DerefVec<'a, T> {
unsafe {
DerefVec {
x: Vec::from_raw_parts(x.as_ptr() as *mut T, x.len(), x.len()),
l: PhantomData,
}
}
}
////////////////////////////////////////////////////////////////////////////////
// Partial vec, used for map_in_place
////////////////////////////////////////////////////////////////////////////////

View File

@ -23,33 +23,35 @@ use core::prelude::*;
use core::cmp::Ordering;
use core::fmt;
use core::iter::{self, repeat, FromIterator, RandomAccessIterator};
use core::mem;
use core::ops::{Index, IndexMut};
use core::ptr::{self, Unique};
use core::ptr;
use core::slice;
use core::hash::{Hash, Hasher};
use core::cmp;
use alloc::heap;
use alloc::raw_vec::RawVec;
const INITIAL_CAPACITY: usize = 7; // 2^3 - 1
const MINIMUM_CAPACITY: usize = 1; // 2 - 1
/// `VecDeque` is a growable ring buffer, which can be used as a
/// double-ended queue efficiently.
///
/// The "default" usage of this type as a queue is to use `push_back` to add to the queue, and
/// `pop_front` to remove from the queue. `extend` and `append` push onto the back in this manner,
/// and iterating over `VecDeque` goes front to back.
#[stable(feature = "rust1", since = "1.0.0")]
pub struct VecDeque<T> {
// tail and head are pointers into the buffer. Tail always points
// to the first element that could be read, Head always points
// to where data should be written.
// If tail == head the buffer is empty. The length of the ringbuf
// If tail == head the buffer is empty. The length of the ringbuffer
// is defined as the distance between the two.
tail: usize,
head: usize,
cap: usize,
ptr: Unique<T>,
buf: RawVec<T>,
}
#[stable(feature = "rust1", since = "1.0.0")]
@ -63,13 +65,7 @@ impl<T: Clone> Clone for VecDeque<T> {
impl<T> Drop for VecDeque<T> {
fn drop(&mut self) {
self.clear();
unsafe {
if mem::size_of::<T>() != 0 {
heap::deallocate(*self.ptr as *mut u8,
self.cap * mem::size_of::<T>(),
mem::min_align_of::<T>())
}
}
// RawVec handles deallocation
}
}
@ -80,78 +76,127 @@ impl<T> Default for VecDeque<T> {
}
impl<T> VecDeque<T> {
/// Marginally more convenient
#[inline]
fn ptr(&self) -> *mut T {
self.buf.ptr()
}
/// Marginally more convenient
#[inline]
fn cap(&self) -> usize {
self.buf.cap()
}
/// Turn ptr into a slice
#[inline]
unsafe fn buffer_as_slice(&self) -> &[T] {
slice::from_raw_parts(*self.ptr, self.cap)
slice::from_raw_parts(self.ptr(), self.cap())
}
/// Turn ptr into a mut slice
#[inline]
unsafe fn buffer_as_mut_slice(&mut self) -> &mut [T] {
slice::from_raw_parts_mut(*self.ptr, self.cap)
slice::from_raw_parts_mut(self.ptr(), self.cap())
}
/// Moves an element out of the buffer
#[inline]
unsafe fn buffer_read(&mut self, off: usize) -> T {
ptr::read(self.ptr.offset(off as isize))
ptr::read(self.ptr().offset(off as isize))
}
/// Writes an element into the buffer, moving it.
#[inline]
unsafe fn buffer_write(&mut self, off: usize, t: T) {
ptr::write(self.ptr.offset(off as isize), t);
unsafe fn buffer_write(&mut self, off: usize, value: T) {
ptr::write(self.ptr().offset(off as isize), value);
}
/// Returns true iff the buffer is at capacity
/// Returns true if and only if the buffer is at capacity
#[inline]
fn is_full(&self) -> bool { self.cap - self.len() == 1 }
fn is_full(&self) -> bool { self.cap() - self.len() == 1 }
/// Returns the index in the underlying buffer for a given logical element
/// index.
#[inline]
fn wrap_index(&self, idx: usize) -> usize { wrap_index(idx, self.cap) }
fn wrap_index(&self, idx: usize) -> usize { wrap_index(idx, self.cap()) }
/// Returns the index in the underlying buffer for a given logical element
/// index + addend.
#[inline]
fn wrap_add(&self, idx: usize, addend: usize) -> usize {
wrap_index(idx.wrapping_add(addend), self.cap)
wrap_index(idx.wrapping_add(addend), self.cap())
}
/// Returns the index in the underlying buffer for a given logical element
/// index - subtrahend.
#[inline]
fn wrap_sub(&self, idx: usize, subtrahend: usize) -> usize {
wrap_index(idx.wrapping_sub(subtrahend), self.cap)
wrap_index(idx.wrapping_sub(subtrahend), self.cap())
}
/// Copies a contiguous block of memory len long from src to dst
#[inline]
unsafe fn copy(&self, dst: usize, src: usize, len: usize) {
debug_assert!(dst + len <= self.cap, "dst={} src={} len={} cap={}", dst, src, len,
self.cap);
debug_assert!(src + len <= self.cap, "dst={} src={} len={} cap={}", dst, src, len,
self.cap);
debug_assert!(dst + len <= self.cap(), "dst={} src={} len={} cap={}", dst, src, len,
self.cap());
debug_assert!(src + len <= self.cap(), "dst={} src={} len={} cap={}", dst, src, len,
self.cap());
ptr::copy(
self.ptr.offset(src as isize),
self.ptr.offset(dst as isize),
self.ptr().offset(src as isize),
self.ptr().offset(dst as isize),
len);
}
/// Copies a contiguous block of memory len long from src to dst
#[inline]
unsafe fn copy_nonoverlapping(&self, dst: usize, src: usize, len: usize) {
debug_assert!(dst + len <= self.cap, "dst={} src={} len={} cap={}", dst, src, len,
self.cap);
debug_assert!(src + len <= self.cap, "dst={} src={} len={} cap={}", dst, src, len,
self.cap);
debug_assert!(dst + len <= self.cap(), "dst={} src={} len={} cap={}", dst, src, len,
self.cap());
debug_assert!(src + len <= self.cap(), "dst={} src={} len={} cap={}", dst, src, len,
self.cap());
ptr::copy_nonoverlapping(
self.ptr.offset(src as isize),
self.ptr.offset(dst as isize),
self.ptr().offset(src as isize),
self.ptr().offset(dst as isize),
len);
}
/// Frobs the head and tail sections around to handle the fact that we
/// just reallocated. Unsafe because it trusts old_cap.
#[inline]
unsafe fn handle_cap_increase(&mut self, old_cap: usize) {
let new_cap = self.cap();
// Move the shortest contiguous section of the ring buffer
// T H
// [o o o o o o o . ]
// T H
// A [o o o o o o o . . . . . . . . . ]
// H T
// [o o . o o o o o ]
// T H
// B [. . . o o o o o o o . . . . . . ]
// H T
// [o o o o o . o o ]
// H T
// C [o o o o o . . . . . . . . . o o ]
if self.tail <= self.head { // A
// Nop
} else if self.head < old_cap - self.tail { // B
self.copy_nonoverlapping(old_cap, 0, self.head);
self.head += old_cap;
debug_assert!(self.head > self.tail);
} else { // C
let new_tail = new_cap - (old_cap - self.tail);
self.copy_nonoverlapping(new_tail, self.tail, old_cap - self.tail);
self.tail = new_tail;
debug_assert!(self.head < self.tail);
}
debug_assert!(self.head < self.cap());
debug_assert!(self.tail < self.cap());
debug_assert!(self.cap().count_ones() == 1);
}
}
impl<T> VecDeque<T> {
@ -167,24 +212,11 @@ impl<T> VecDeque<T> {
// +1 since the ringbuffer always leaves one space empty
let cap = cmp::max(n + 1, MINIMUM_CAPACITY + 1).next_power_of_two();
assert!(cap > n, "capacity overflow");
let size = cap.checked_mul(mem::size_of::<T>())
.expect("capacity overflow");
let ptr = unsafe {
if mem::size_of::<T>() != 0 {
let ptr = heap::allocate(size, mem::min_align_of::<T>()) as *mut T;;
if ptr.is_null() { ::alloc::oom() }
Unique::new(ptr)
} else {
Unique::new(heap::EMPTY as *mut T)
}
};
VecDeque {
tail: 0,
head: 0,
cap: cap,
ptr: ptr,
buf: RawVec::with_capacity(cap),
}
}
@ -202,10 +234,10 @@ impl<T> VecDeque<T> {
/// assert_eq!(buf.get(1).unwrap(), &4);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn get(&self, i: usize) -> Option<&T> {
if i < self.len() {
let idx = self.wrap_add(self.tail, i);
unsafe { Some(&*self.ptr.offset(idx as isize)) }
pub fn get(&self, index: usize) -> Option<&T> {
if index < self.len() {
let idx = self.wrap_add(self.tail, index);
unsafe { Some(&*self.ptr().offset(idx as isize)) }
} else {
None
}
@ -229,10 +261,10 @@ impl<T> VecDeque<T> {
/// assert_eq!(buf[1], 7);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn get_mut(&mut self, i: usize) -> Option<&mut T> {
if i < self.len() {
let idx = self.wrap_add(self.tail, i);
unsafe { Some(&mut *self.ptr.offset(idx as isize)) }
pub fn get_mut(&mut self, index: usize) -> Option<&mut T> {
if index < self.len() {
let idx = self.wrap_add(self.tail, index);
unsafe { Some(&mut *self.ptr().offset(idx as isize)) }
} else {
None
}
@ -264,7 +296,7 @@ impl<T> VecDeque<T> {
let ri = self.wrap_add(self.tail, i);
let rj = self.wrap_add(self.tail, j);
unsafe {
ptr::swap(self.ptr.offset(ri as isize), self.ptr.offset(rj as isize))
ptr::swap(self.ptr().offset(ri as isize), self.ptr().offset(rj as isize))
}
}
@ -281,7 +313,7 @@ impl<T> VecDeque<T> {
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn capacity(&self) -> usize { self.cap - 1 }
pub fn capacity(&self) -> usize { self.cap() - 1 }
/// Reserves the minimum capacity for exactly `additional` more elements to be inserted in the
/// given `VecDeque`. Does nothing if the capacity is already sufficient.
@ -309,7 +341,7 @@ impl<T> VecDeque<T> {
}
/// Reserves capacity for at least `additional` more elements to be inserted in the given
/// `Ringbuf`. The collection may reserve more space to avoid frequent reallocations.
/// `VecDeque`. The collection may reserve more space to avoid frequent reallocations.
///
/// # Panics
///
@ -326,69 +358,23 @@ impl<T> VecDeque<T> {
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn reserve(&mut self, additional: usize) {
let new_len = self.len() + additional;
assert!(new_len + 1 > self.len(), "capacity overflow");
if new_len > self.capacity() {
let count = (new_len + 1).next_power_of_two();
assert!(count >= new_len + 1);
let old_cap = self.cap();
let used_cap = self.len() + 1;
let new_cap = used_cap
.checked_add(additional)
.and_then(|needed_cap| needed_cap.checked_next_power_of_two())
.expect("capacity overflow");
if mem::size_of::<T>() != 0 {
let old = self.cap * mem::size_of::<T>();
let new = count.checked_mul(mem::size_of::<T>())
.expect("capacity overflow");
unsafe {
let ptr = heap::reallocate(*self.ptr as *mut u8,
old,
new,
mem::min_align_of::<T>()) as *mut T;
if ptr.is_null() { ::alloc::oom() }
self.ptr = Unique::new(ptr);
}
}
// Move the shortest contiguous section of the ring buffer
// T H
// [o o o o o o o . ]
// T H
// A [o o o o o o o . . . . . . . . . ]
// H T
// [o o . o o o o o ]
// T H
// B [. . . o o o o o o o . . . . . . ]
// H T
// [o o o o o . o o ]
// H T
// C [o o o o o . . . . . . . . . o o ]
let oldcap = self.cap;
self.cap = count;
if self.tail <= self.head { // A
// Nop
} else if self.head < oldcap - self.tail { // B
unsafe {
self.copy_nonoverlapping(oldcap, 0, self.head);
}
self.head += oldcap;
debug_assert!(self.head > self.tail);
} else { // C
let new_tail = count - (oldcap - self.tail);
unsafe {
self.copy_nonoverlapping(new_tail, self.tail, oldcap - self.tail);
}
self.tail = new_tail;
debug_assert!(self.head < self.tail);
}
debug_assert!(self.head < self.cap);
debug_assert!(self.tail < self.cap);
debug_assert!(self.cap.count_ones() == 1);
if new_cap > self.capacity() {
self.buf.reserve_exact(used_cap, new_cap - used_cap);
unsafe { self.handle_cap_increase(old_cap); }
}
}
/// Shrinks the capacity of the ringbuf as much as possible.
/// Shrinks the capacity of the `VecDeque` as much as possible.
///
/// It will drop down as close as possible to the length but the allocator may still inform the
/// ringbuf that there is space for a few more elements.
/// `VecDeque` that there is space for a few more elements.
///
/// # Examples
///
@ -404,9 +390,9 @@ impl<T> VecDeque<T> {
/// ```
pub fn shrink_to_fit(&mut self) {
// +1 since the ringbuffer always leaves one space empty
// len + 1 can't overflow for an existing, well-formed ringbuf.
// len + 1 can't overflow for an existing, well-formed ringbuffer.
let target_cap = cmp::max(self.len() + 1, MINIMUM_CAPACITY + 1).next_power_of_two();
if target_cap < self.cap {
if target_cap < self.cap() {
// There are three cases of interest:
// All elements are out of desired bounds
// Elements are contiguous, and head is out of desired bounds
@ -444,7 +430,7 @@ impl<T> VecDeque<T> {
// H T
// [o o o o o . o o ]
debug_assert!(self.wrap_sub(self.head, 1) < target_cap);
let len = self.cap - self.tail;
let len = self.cap() - self.tail;
let new_tail = target_cap - len;
unsafe {
self.copy_nonoverlapping(new_tail, self.tail, len);
@ -453,28 +439,17 @@ impl<T> VecDeque<T> {
debug_assert!(self.head < self.tail);
}
if mem::size_of::<T>() != 0 {
let old = self.cap * mem::size_of::<T>();
let new_size = target_cap * mem::size_of::<T>();
unsafe {
let ptr = heap::reallocate(*self.ptr as *mut u8,
old,
new_size,
mem::min_align_of::<T>()) as *mut T;
if ptr.is_null() { ::alloc::oom() }
self.ptr = Unique::new(ptr);
}
}
self.cap = target_cap;
debug_assert!(self.head < self.cap);
debug_assert!(self.tail < self.cap);
debug_assert!(self.cap.count_ones() == 1);
self.buf.shrink_to_fit(target_cap);
debug_assert!(self.head < self.cap());
debug_assert!(self.tail < self.cap());
debug_assert!(self.cap().count_ones() == 1);
}
}
/// Shortens a ringbuf, dropping excess elements from the back.
/// Shortens a `VecDeque`, dropping excess elements from the back.
///
/// If `len` is greater than the ringbuf's current length, this has no
/// If `len` is greater than the `VecDeque`'s current length, this has no
/// effect.
///
/// # Examples
@ -606,7 +581,7 @@ impl<T> VecDeque<T> {
/// assert_eq!(v.len(), 1);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn len(&self) -> usize { count(self.tail, self.head, self.cap) }
pub fn len(&self) -> usize { count(self.tail, self.head, self.cap()) }
/// Returns true if the buffer contains no elements
///
@ -793,15 +768,17 @@ impl<T> VecDeque<T> {
/// assert_eq!(d.front(), Some(&2));
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn push_front(&mut self, t: T) {
pub fn push_front(&mut self, value: T) {
if self.is_full() {
self.reserve(1);
let old_cap = self.cap();
self.buf.double();
unsafe { self.handle_cap_increase(old_cap); }
debug_assert!(!self.is_full());
}
self.tail = self.wrap_sub(self.tail, 1);
let tail = self.tail;
unsafe { self.buffer_write(tail, t); }
unsafe { self.buffer_write(tail, value); }
}
/// Appends an element to the back of a buffer
@ -817,15 +794,17 @@ impl<T> VecDeque<T> {
/// assert_eq!(3, *buf.back().unwrap());
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn push_back(&mut self, t: T) {
pub fn push_back(&mut self, value: T) {
if self.is_full() {
self.reserve(1);
let old_cap = self.cap();
self.buf.double();
unsafe { self.handle_cap_increase(old_cap); }
debug_assert!(!self.is_full());
}
let head = self.head;
self.head = self.wrap_add(self.head, 1);
unsafe { self.buffer_write(head, t) }
unsafe { self.buffer_write(head, value) }
}
/// Removes the last element from a buffer and returns it, or `None` if
@ -858,8 +837,8 @@ impl<T> VecDeque<T> {
self.tail <= self.head
}
/// Removes an element from anywhere in the ringbuf and returns it, replacing it with the last
/// element.
/// Removes an element from anywhere in the `VecDeque` and returns it, replacing it with the
/// last element.
///
/// This does not preserve ordering, but is O(1).
///
@ -892,7 +871,7 @@ impl<T> VecDeque<T> {
self.pop_back()
}
/// Removes an element from anywhere in the ringbuf and returns it,
/// Removes an element from anywhere in the `VecDeque` and returns it,
/// replacing it with the first element.
///
/// This does not preserve ordering, but is O(1).
@ -926,13 +905,13 @@ impl<T> VecDeque<T> {
self.pop_front()
}
/// Inserts an element at position `i` within the ringbuf. Whichever
/// Inserts an element at `index` within the `VecDeque`. Whichever
/// end is closer to the insertion point will be moved to make room,
/// and all the affected elements will be moved to new positions.
///
/// # Panics
///
/// Panics if `i` is greater than ringbuf's length
/// Panics if `index` is greater than `VecDeque`'s length
///
/// # Examples
/// ```
@ -942,13 +921,15 @@ impl<T> VecDeque<T> {
/// let mut buf = VecDeque::new();
/// buf.push_back(10);
/// buf.push_back(12);
/// buf.insert(1,11);
/// buf.insert(1, 11);
/// assert_eq!(Some(&11), buf.get(1));
/// ```
pub fn insert(&mut self, i: usize, t: T) {
assert!(i <= self.len(), "index out of bounds");
pub fn insert(&mut self, index: usize, value: T) {
assert!(index <= self.len(), "index out of bounds");
if self.is_full() {
self.reserve(1);
let old_cap = self.cap();
self.buf.double();
unsafe { self.handle_cap_increase(old_cap); }
debug_assert!(!self.is_full());
}
@ -974,15 +955,15 @@ impl<T> VecDeque<T> {
// A - The element that should be after the insertion point
// M - Indicates element was moved
let idx = self.wrap_add(self.tail, i);
let idx = self.wrap_add(self.tail, index);
let distance_to_tail = i;
let distance_to_head = self.len() - i;
let distance_to_tail = index;
let distance_to_head = self.len() - index;
let contiguous = self.is_contiguous();
match (contiguous, distance_to_tail <= distance_to_head, idx >= self.tail) {
(true, true, _) if i == 0 => {
(true, true, _) if index == 0 => {
// push_front
//
// T
@ -1018,8 +999,8 @@ impl<T> VecDeque<T> {
let new_tail = self.wrap_sub(self.tail, 1);
self.copy(new_tail, self.tail, 1);
// Already moved the tail, so we only copy `i - 1` elements.
self.copy(self.tail, self.tail + 1, i - 1);
// Already moved the tail, so we only copy `index - 1` elements.
self.copy(self.tail, self.tail + 1, index - 1);
self.tail = new_tail;
},
@ -1046,7 +1027,7 @@ impl<T> VecDeque<T> {
// [o o o o o o . . . . o o I A o o]
// M M
self.copy(self.tail - 1, self.tail, i);
self.copy(self.tail - 1, self.tail, index);
self.tail -= 1;
},
(false, false, true) => unsafe {
@ -1063,10 +1044,10 @@ impl<T> VecDeque<T> {
self.copy(1, 0, self.head);
// copy last element into empty spot at bottom of buffer
self.copy(0, self.cap - 1, 1);
self.copy(0, self.cap() - 1, 1);
// move elements from idx to end forward not including ^ element
self.copy(idx + 1, idx, self.cap - 1 - idx);
self.copy(idx + 1, idx, self.cap() - 1 - idx);
self.head += 1;
},
@ -1082,10 +1063,10 @@ impl<T> VecDeque<T> {
// M M M
// copy elements up to new tail
self.copy(self.tail - 1, self.tail, self.cap - self.tail);
self.copy(self.tail - 1, self.tail, self.cap() - self.tail);
// copy last element into empty spot at bottom of buffer
self.copy(self.cap - 1, 0, 1);
self.copy(self.cap() - 1, 0, 1);
self.tail -= 1;
},
@ -1100,10 +1081,10 @@ impl<T> VecDeque<T> {
// M M M M M M
// copy elements up to new tail
self.copy(self.tail - 1, self.tail, self.cap - self.tail);
self.copy(self.tail - 1, self.tail, self.cap() - self.tail);
// copy last element into empty spot at bottom of buffer
self.copy(self.cap - 1, 0, 1);
self.copy(self.cap() - 1, 0, 1);
// move elements from idx-1 to end forward not including ^ element
self.copy(0, 1, idx - 1);
@ -1126,16 +1107,16 @@ impl<T> VecDeque<T> {
}
// tail might've been changed so we need to recalculate
let new_idx = self.wrap_add(self.tail, i);
let new_idx = self.wrap_add(self.tail, index);
unsafe {
self.buffer_write(new_idx, t);
self.buffer_write(new_idx, value);
}
}
/// Removes and returns the element at position `i` from the ringbuf.
/// Removes and returns the element at `index` from the `VecDeque`.
/// Whichever end is closer to the removal point will be moved to make
/// room, and all the affected elements will be moved to new positions.
/// Returns `None` if `i` is out of bounds.
/// Returns `None` if `index` is out of bounds.
///
/// # Examples
/// ```
@ -1150,8 +1131,8 @@ impl<T> VecDeque<T> {
/// assert_eq!(Some(&15), buf.get(2));
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn remove(&mut self, i: usize) -> Option<T> {
if self.is_empty() || self.len() <= i {
pub fn remove(&mut self, index: usize) -> Option<T> {
if self.is_empty() || self.len() <= index {
return None;
}
@ -1173,14 +1154,14 @@ impl<T> VecDeque<T> {
// R - Indicates element that is being removed
// M - Indicates element was moved
let idx = self.wrap_add(self.tail, i);
let idx = self.wrap_add(self.tail, index);
let elem = unsafe {
Some(self.buffer_read(idx))
};
let distance_to_tail = i;
let distance_to_head = self.len() - i;
let distance_to_tail = index;
let distance_to_head = self.len() - index;
let contiguous = self.is_contiguous();
@ -1195,7 +1176,7 @@ impl<T> VecDeque<T> {
// [. . . . o o o o o o . . . . . .]
// M M
self.copy(self.tail + 1, self.tail, i);
self.copy(self.tail + 1, self.tail, index);
self.tail += 1;
},
(true, false, _) => unsafe {
@ -1221,7 +1202,7 @@ impl<T> VecDeque<T> {
// [o o o o o o . . . . . . o o o o]
// M M
self.copy(self.tail + 1, self.tail, i);
self.copy(self.tail + 1, self.tail, index);
self.tail = self.wrap_add(self.tail, 1);
},
(false, false, false) => unsafe {
@ -1257,12 +1238,12 @@ impl<T> VecDeque<T> {
// M
// draw in elements in the tail section
self.copy(idx, idx + 1, self.cap - idx - 1);
self.copy(idx, idx + 1, self.cap() - idx - 1);
// Prevents underflow.
if self.head != 0 {
// copy first element into empty spot
self.copy(self.cap - 1, 0, 1);
self.copy(self.cap() - 1, 0, 1);
// move elements in the head section backwards
self.copy(0, 1, self.head - 1);
@ -1284,10 +1265,10 @@ impl<T> VecDeque<T> {
self.copy(1, 0, idx);
// copy last element into empty spot
self.copy(0, self.cap - 1, 1);
self.copy(0, self.cap() - 1, 1);
// move elements from tail to end forward, excluding the last one
self.copy(self.tail + 1, self.tail, self.cap - self.tail - 1);
self.copy(self.tail + 1, self.tail, self.cap() - self.tail - 1);
self.tail = self.wrap_add(self.tail, 1);
}
@ -1339,12 +1320,12 @@ impl<T> VecDeque<T> {
let amount_in_first = first_len - at;
ptr::copy_nonoverlapping(first_half.as_ptr().offset(at as isize),
*other.ptr,
other.ptr(),
amount_in_first);
// just take all of the second half.
ptr::copy_nonoverlapping(second_half.as_ptr(),
other.ptr.offset(amount_in_first as isize),
other.ptr().offset(amount_in_first as isize),
second_len);
} else {
// `at` lies in the second half, need to factor in the elements we skipped
@ -1352,7 +1333,7 @@ impl<T> VecDeque<T> {
let offset = at - first_len;
let amount_in_second = second_len - offset;
ptr::copy_nonoverlapping(second_half.as_ptr().offset(offset as isize),
*other.ptr,
other.ptr(),
amount_in_second);
}
}
@ -1428,7 +1409,7 @@ impl<T> VecDeque<T> {
}
impl<T: Clone> VecDeque<T> {
/// Modifies the ringbuf in-place so that `len()` is equal to new_len,
/// Modifies the `VecDeque` in-place so that `len()` is equal to new_len,
/// either by removing excess elements or by appending copies of a value to the back.
///
/// # Examples
@ -1719,16 +1700,16 @@ impl<A> Index<usize> for VecDeque<A> {
type Output = A;
#[inline]
fn index(&self, i: usize) -> &A {
self.get(i).expect("Out of bounds access")
fn index(&self, index: usize) -> &A {
self.get(index).expect("Out of bounds access")
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<A> IndexMut<usize> for VecDeque<A> {
#[inline]
fn index_mut(&mut self, i: usize) -> &mut A {
self.get_mut(i).expect("Out of bounds access")
fn index_mut(&mut self, index: usize) -> &mut A {
self.get_mut(index).expect("Out of bounds access")
}
}
@ -1900,8 +1881,8 @@ mod tests {
assert_eq!(tester.swap_front_remove(idx), Some(len * 2 - 1 - i));
}
}
assert!(tester.tail < tester.cap);
assert!(tester.head < tester.cap);
assert!(tester.tail < tester.cap());
assert!(tester.head < tester.cap());
assert_eq!(tester, expected);
}
}
@ -1936,8 +1917,8 @@ mod tests {
}
}
tester.insert(to_insert, to_insert);
assert!(tester.tail < tester.cap);
assert!(tester.head < tester.cap);
assert!(tester.tail < tester.cap());
assert!(tester.head < tester.cap());
assert_eq!(tester, expected);
}
}
@ -1973,8 +1954,8 @@ mod tests {
tester.push_back(1234);
}
tester.remove(to_remove);
assert!(tester.tail < tester.cap);
assert!(tester.head < tester.cap);
assert!(tester.tail < tester.cap());
assert!(tester.head < tester.cap());
assert_eq!(tester, expected);
}
}
@ -2006,8 +1987,8 @@ mod tests {
}
tester.shrink_to_fit();
assert!(tester.capacity() <= cap);
assert!(tester.tail < tester.cap);
assert!(tester.head < tester.cap);
assert!(tester.tail < tester.cap());
assert!(tester.head < tester.cap());
assert_eq!(tester, expected);
}
}
@ -2040,10 +2021,10 @@ mod tests {
tester.push_back(i);
}
let result = tester.split_off(at);
assert!(tester.tail < tester.cap);
assert!(tester.head < tester.cap);
assert!(result.tail < result.cap);
assert!(result.head < result.cap);
assert!(tester.tail < tester.cap());
assert!(tester.head < tester.cap());
assert!(result.tail < result.cap());
assert!(result.head < result.cap());
assert_eq!(tester, expected_self);
assert_eq!(result, expected_other);
}

View File

@ -8,8 +8,8 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![feature(ascii)]
#![feature(append)]
#![feature(bit_vec_append_split_off)]
#![feature(bitset)]
#![feature(bitvec)]
#![feature(box_syntax)]
@ -37,14 +37,16 @@
#![feature(rustc_private)]
#![feature(slice_bytes)]
#![feature(slice_chars)]
#![feature(slice_extras)]
#![feature(slice_splits)]
#![feature(slice_position_elem)]
#![feature(split_off)]
#![feature(step_by)]
#![feature(str_char)]
#![feature(str_escape)]
#![feature(str_match_indices)]
#![feature(str_split_at)]
#![feature(str_utf16)]
#![feature(box_str)]
#![feature(subslice_offset)]
#![feature(test)]
#![feature(unboxed_closures)]
@ -52,9 +54,10 @@
#![feature(vec_deque_retain)]
#![feature(vec_from_raw_buf)]
#![feature(vec_push_all)]
#![feature(vec_split_off)]
#![feature(vecmap)]
#![allow(deprecated)]
#[macro_use] extern crate log;
extern crate collections;

View File

@ -119,71 +119,48 @@ fn test_first_mut() {
}
#[test]
fn test_tail() {
fn test_split_first() {
let mut a = vec![11];
let b: &[i32] = &[];
assert_eq!(a.tail(), b);
assert!(b.split_first().is_none());
assert_eq!(a.split_first(), Some((&11, b)));
a = vec![11, 12];
let b: &[i32] = &[12];
assert_eq!(a.tail(), b);
assert_eq!(a.split_first(), Some((&11, b)));
}
#[test]
fn test_tail_mut() {
fn test_split_first_mut() {
let mut a = vec![11];
let b: &mut [i32] = &mut [];
assert!(a.tail_mut() == b);
assert!(b.split_first_mut().is_none());
assert!(a.split_first_mut() == Some((&mut 11, b)));
a = vec![11, 12];
let b: &mut [_] = &mut [12];
assert!(a.tail_mut() == b);
assert!(a.split_first_mut() == Some((&mut 11, b)));
}
#[test]
#[should_panic]
fn test_tail_empty() {
let a = Vec::<i32>::new();
a.tail();
}
#[test]
#[should_panic]
fn test_tail_mut_empty() {
let mut a = Vec::<i32>::new();
a.tail_mut();
}
#[test]
fn test_init() {
fn test_split_last() {
let mut a = vec![11];
let b: &[i32] = &[];
assert_eq!(a.init(), b);
assert!(b.split_last().is_none());
assert_eq!(a.split_last(), Some((&11, b)));
a = vec![11, 12];
let b: &[_] = &[11];
assert_eq!(a.init(), b);
assert_eq!(a.split_last(), Some((&12, b)));
}
#[test]
fn test_init_mut() {
fn test_split_last_mut() {
let mut a = vec![11];
let b: &mut [i32] = &mut [];
assert!(a.init_mut() == b);
assert!(b.split_last_mut().is_none());
assert!(a.split_last_mut() == Some((&mut 11, b)));
a = vec![11, 12];
let b: &mut [_] = &mut [11];
assert!(a.init_mut() == b);
}
#[test]
#[should_panic]
fn test_init_empty() {
let a = Vec::<i32>::new();
a.init();
}
#[test]
#[should_panic]
fn test_init_mut_empty() {
let mut a = Vec::<i32>::new();
a.init_mut();
assert!(a.split_last_mut() == Some((&mut 12, b)));
}
#[test]
@ -606,22 +583,22 @@ fn test_concat() {
assert_eq!(d, [1, 2, 3]);
let v: &[&[_]] = &[&[1], &[2, 3]];
assert_eq!(v.connect(&0), [1, 0, 2, 3]);
assert_eq!(v.join(&0), [1, 0, 2, 3]);
let v: &[&[_]] = &[&[1], &[2], &[3]];
assert_eq!(v.connect(&0), [1, 0, 2, 0, 3]);
assert_eq!(v.join(&0), [1, 0, 2, 0, 3]);
}
#[test]
fn test_connect() {
fn test_join() {
let v: [Vec<i32>; 0] = [];
assert_eq!(v.connect(&0), []);
assert_eq!([vec![1], vec![2, 3]].connect(&0), [1, 0, 2, 3]);
assert_eq!([vec![1], vec![2], vec![3]].connect(&0), [1, 0, 2, 0, 3]);
assert_eq!(v.join(&0), []);
assert_eq!([vec![1], vec![2, 3]].join(&0), [1, 0, 2, 3]);
assert_eq!([vec![1], vec![2], vec![3]].join(&0), [1, 0, 2, 0, 3]);
let v: [&[_]; 2] = [&[1], &[2, 3]];
assert_eq!(v.connect(&0), [1, 0, 2, 3]);
assert_eq!(v.join(&0), [1, 0, 2, 3]);
let v: [&[_]; 3] = [&[1], &[2], &[3]];
assert_eq!(v.connect(&0), [1, 0, 2, 0, 3]);
assert_eq!(v.join(&0), [1, 0, 2, 0, 3]);
}
#[test]
@ -1318,7 +1295,7 @@ mod bench {
#[bench]
fn mut_iterator(b: &mut Bencher) {
let mut v: Vec<_> = repeat(0).take(100).collect();
let mut v = vec![0; 100];
b.iter(|| {
let mut i = 0;
@ -1339,11 +1316,11 @@ mod bench {
}
#[bench]
fn connect(b: &mut Bencher) {
fn join(b: &mut Bencher) {
let xss: Vec<Vec<i32>> =
(0..100).map(|i| (0..i).collect()).collect();
b.iter(|| {
xss.connect(&0)
xss.join(&0)
});
}
@ -1419,7 +1396,7 @@ mod bench {
#[bench]
fn zero_1kb_from_elem(b: &mut Bencher) {
b.iter(|| {
repeat(0u8).take(1024).collect::<Vec<_>>()
vec![0u8; 1024]
});
}
@ -1467,7 +1444,7 @@ mod bench {
fn random_inserts(b: &mut Bencher) {
let mut rng = thread_rng();
b.iter(|| {
let mut v: Vec<_> = repeat((0, 0)).take(30).collect();
let mut v = vec![(0, 0); 30];
for _ in 0..100 {
let l = v.len();
v.insert(rng.gen::<usize>() % (l + 1),
@ -1479,7 +1456,7 @@ mod bench {
fn random_removes(b: &mut Bencher) {
let mut rng = thread_rng();
b.iter(|| {
let mut v: Vec<_> = repeat((0, 0)).take(130).collect();
let mut v = vec![(0, 0); 130];
for _ in 0..100 {
let l = v.len();
v.remove(rng.gen::<usize>() % l);

View File

@ -158,32 +158,32 @@ fn test_concat_for_different_lengths() {
test_concat!("abc", ["", "a", "bc"]);
}
macro_rules! test_connect {
macro_rules! test_join {
($expected: expr, $string: expr, $delim: expr) => {
{
let s = $string.connect($delim);
let s = $string.join($delim);
assert_eq!($expected, s);
}
}
}
#[test]
fn test_connect_for_different_types() {
test_connect!("a-b", ["a", "b"], "-");
fn test_join_for_different_types() {
test_join!("a-b", ["a", "b"], "-");
let hyphen = "-".to_string();
test_connect!("a-b", [s("a"), s("b")], &*hyphen);
test_connect!("a-b", vec!["a", "b"], &*hyphen);
test_connect!("a-b", &*vec!["a", "b"], "-");
test_connect!("a-b", vec![s("a"), s("b")], "-");
test_join!("a-b", [s("a"), s("b")], &*hyphen);
test_join!("a-b", vec!["a", "b"], &*hyphen);
test_join!("a-b", &*vec!["a", "b"], "-");
test_join!("a-b", vec![s("a"), s("b")], "-");
}
#[test]
fn test_connect_for_different_lengths() {
fn test_join_for_different_lengths() {
let empty: &[&str] = &[];
test_connect!("", empty, "-");
test_connect!("a", ["a"], "-");
test_connect!("a-b", ["a", "b"], "-");
test_connect!("-a-bc", ["", "a", "bc"], "-");
test_join!("", empty, "-");
test_join!("a", ["a"], "-");
test_join!("a-b", ["a", "b"], "-");
test_join!("-a-bc", ["", "a", "bc"], "-");
}
#[test]
@ -701,11 +701,23 @@ fn test_split_at() {
assert_eq!(b, "");
}
#[test]
fn test_split_at_mut() {
use std::ascii::AsciiExt;
let mut s = "Hello World".to_string();
{
let (a, b) = s.split_at_mut(5);
a.make_ascii_uppercase();
b.make_ascii_lowercase();
}
assert_eq!(s, "HELLO world");
}
#[test]
#[should_panic]
fn test_split_at_boundscheck() {
let s = "ศไทย中华Việt Nam";
let (a, b) = s.split_at(1);
s.split_at(1);
}
#[test]
@ -1746,6 +1758,14 @@ fn to_uppercase() {
assert_eq!("aéDžßfiᾀ".to_uppercase(), "AÉDŽSSFIἈΙ");
}
#[test]
fn test_into_string() {
// The only way to acquire a Box<str> in the first place is through a String, so just
// test that we can round-trip between Box<str> and String.
let string = String::from("Some text goes here");
assert_eq!(string.clone().into_boxed_slice().into_string(), string);
}
mod pattern {
use std::str::pattern::Pattern;
use std::str::pattern::{Searcher, ReverseSearcher};
@ -1820,6 +1840,14 @@ mod pattern {
Match (4, 6),
Reject(6, 7),
]);
make_test!(str_searcher_ascii_haystack_seq, "bb", "abbcbbbbd", [
Reject(0, 1),
Match (1, 3),
Reject(3, 4),
Match (4, 6),
Match (6, 8),
Reject(8, 9),
]);
make_test!(str_searcher_empty_needle_ascii_haystack, "", "abbcbbd", [
Match (0, 0),
Reject(0, 1),
@ -2073,12 +2101,12 @@ mod bench {
}
#[bench]
fn bench_connect(b: &mut Bencher) {
fn bench_join(b: &mut Bencher) {
let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb";
let sep = "";
let v = vec![s, s, s, s, s, s, s, s, s, s];
b.iter(|| {
assert_eq!(v.connect(sep).len(), s.len() * 10 + sep.len() * 9);
assert_eq!(v.join(sep).len(), s.len() * 10 + sep.len() * 9);
})
}

View File

@ -10,18 +10,9 @@
use std::borrow::{IntoCow, Cow};
use std::iter::repeat;
#[allow(deprecated)]
use std::string::as_string;
use test::Bencher;
#[test]
#[allow(deprecated)]
fn test_as_string() {
let x = "foo";
assert_eq!(x, &**as_string(x));
}
#[test]
fn test_from_str() {
let owned: Option<::std::string::String> = "string".parse().ok();
@ -374,6 +365,13 @@ fn test_extend_ref() {
assert_eq!(&a, "foobar");
}
#[test]
fn test_into_boxed_slice() {
let xs = String::from("hello my name is bob");
let ys = xs.into_boxed_slice();
assert_eq!(&*ys, "hello my name is bob");
}
#[bench]
fn bench_with_capacity(b: &mut Bencher) {
b.iter(|| {

View File

@ -10,8 +10,6 @@
use std::iter::{FromIterator, repeat};
use std::mem::size_of;
#[allow(deprecated)]
use std::vec::as_vec;
use test::Bencher;
@ -25,25 +23,6 @@ impl<'a> Drop for DropCounter<'a> {
}
}
#[test]
#[allow(deprecated)]
fn test_as_vec() {
let xs = [1u8, 2u8, 3u8];
assert_eq!(&**as_vec(&xs), xs);
}
#[test]
#[allow(deprecated)]
fn test_as_vec_dtor() {
let (mut count_x, mut count_y) = (0, 0);
{
let xs = &[DropCounter { count: &mut count_x }, DropCounter { count: &mut count_y }];
assert_eq!(as_vec(xs).len(), 2);
}
assert_eq!(count_x, 1);
assert_eq!(count_y, 1);
}
#[test]
fn test_small_vec_struct() {
assert!(size_of::<Vec<u8>>() == size_of::<usize>() * 3);

View File

@ -8,15 +8,13 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
//! Traits for dynamic typing of any `'static` type (through runtime reflection)
//!
//! This module implements the `Any` trait, which enables dynamic typing
//! of any `'static` type through runtime reflection.
//!
//! `Any` itself can be used to get a `TypeId`, and has more features when used
//! as a trait object. As `&Any` (a borrowed trait object), it has the `is` and
//! `as_ref` methods, to test if the contained value is of a given type, and to
//! get a reference to the inner value as a type. As`&mut Any`, there is also
//! get a reference to the inner value as a type. As `&mut Any`, there is also
//! the `as_mut` method, for getting a mutable reference to the inner value.
//! `Box<Any>` adds the `move` method, which will unwrap a `Box<T>` from the
//! object. See the extension traits (`*Ext`) for the full details.

View File

@ -11,8 +11,9 @@
//! Implementations of things like `Eq` for fixed-length arrays
//! up to a certain length. Eventually we should able to generalize
//! to all lengths.
//!
//! *[See also the array primitive type](../primitive.array.html).*
#![doc(primitive = "array")]
#![unstable(feature = "fixed_size_array",
reason = "traits and impls are better expressed through generic \
integer constants")]

View File

@ -78,6 +78,7 @@ use intrinsics;
use cell::UnsafeCell;
use default::Default;
use fmt;
/// A boolean type which can be safely shared between threads.
#[stable(feature = "rust1", since = "1.0.0")]
@ -272,13 +273,13 @@ impl AtomicBool {
unsafe { atomic_swap(self.v.get(), val, order) > 0 }
}
/// Stores a value into the bool if the current value is the same as the expected value.
/// Stores a value into the `bool` if the current value is the same as the `current` value.
///
/// The return value is always the previous value. If it is equal to `old`, then the value was
/// updated.
/// The return value is always the previous value. If it is equal to `current`, then the value
/// was updated.
///
/// `swap` also takes an `Ordering` argument which describes the memory ordering of this
/// operation.
/// `compare_and_swap` also takes an `Ordering` argument which describes the memory ordering of
/// this operation.
///
/// # Examples
///
@ -295,11 +296,11 @@ impl AtomicBool {
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn compare_and_swap(&self, old: bool, new: bool, order: Ordering) -> bool {
let old = if old { UINT_TRUE } else { 0 };
pub fn compare_and_swap(&self, current: bool, new: bool, order: Ordering) -> bool {
let current = if current { UINT_TRUE } else { 0 };
let new = if new { UINT_TRUE } else { 0 };
unsafe { atomic_compare_and_swap(self.v.get(), old, new, order) > 0 }
unsafe { atomic_compare_and_swap(self.v.get(), current, new, order) > 0 }
}
/// Logical "and" with a boolean value.
@ -515,10 +516,10 @@ impl AtomicIsize {
unsafe { atomic_swap(self.v.get(), val, order) }
}
/// Stores a value into the isize if the current value is the same as the expected value.
/// Stores a value into the `isize` if the current value is the same as the `current` value.
///
/// The return value is always the previous value. If it is equal to `old`, then the value was
/// updated.
/// The return value is always the previous value. If it is equal to `current`, then the value
/// was updated.
///
/// `compare_and_swap` also takes an `Ordering` argument which describes the memory ordering of
/// this operation.
@ -538,8 +539,8 @@ impl AtomicIsize {
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn compare_and_swap(&self, old: isize, new: isize, order: Ordering) -> isize {
unsafe { atomic_compare_and_swap(self.v.get(), old, new, order) }
pub fn compare_and_swap(&self, current: isize, new: isize, order: Ordering) -> isize {
unsafe { atomic_compare_and_swap(self.v.get(), current, new, order) }
}
/// Add an isize to the current value, returning the previous value.
@ -709,10 +710,10 @@ impl AtomicUsize {
unsafe { atomic_swap(self.v.get(), val, order) }
}
/// Stores a value into the usize if the current value is the same as the expected value.
/// Stores a value into the `usize` if the current value is the same as the `current` value.
///
/// The return value is always the previous value. If it is equal to `old`, then the value was
/// updated.
/// The return value is always the previous value. If it is equal to `current`, then the value
/// was updated.
///
/// `compare_and_swap` also takes an `Ordering` argument which describes the memory ordering of
/// this operation.
@ -732,8 +733,8 @@ impl AtomicUsize {
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn compare_and_swap(&self, old: usize, new: usize, order: Ordering) -> usize {
unsafe { atomic_compare_and_swap(self.v.get(), old, new, order) }
pub fn compare_and_swap(&self, current: usize, new: usize, order: Ordering) -> usize {
unsafe { atomic_compare_and_swap(self.v.get(), current, new, order) }
}
/// Add to the current usize, returning the previous value.
@ -910,10 +911,10 @@ impl<T> AtomicPtr<T> {
unsafe { atomic_swap(self.p.get() as *mut usize, ptr as usize, order) as *mut T }
}
/// Stores a value into the pointer if the current value is the same as the expected value.
/// Stores a value into the pointer if the current value is the same as the `current` value.
///
/// The return value is always the previous value. If it is equal to `old`, then the value was
/// updated.
/// The return value is always the previous value. If it is equal to `current`, then the value
/// was updated.
///
/// `compare_and_swap` also takes an `Ordering` argument which describes the memory ordering of
/// this operation.
@ -933,9 +934,9 @@ impl<T> AtomicPtr<T> {
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn compare_and_swap(&self, old: *mut T, new: *mut T, order: Ordering) -> *mut T {
pub fn compare_and_swap(&self, current: *mut T, new: *mut T, order: Ordering) -> *mut T {
unsafe {
atomic_compare_and_swap(self.p.get() as *mut usize, old as usize,
atomic_compare_and_swap(self.p.get() as *mut usize, current as usize,
new as usize, order) as *mut T
}
}
@ -953,7 +954,6 @@ unsafe fn atomic_store<T>(dst: *mut T, val: T, order:Ordering) {
}
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
unsafe fn atomic_load<T>(dst: *const T, order:Ordering) -> T {
match order {
Acquire => intrinsics::atomic_load_acq(dst),
@ -965,7 +965,6 @@ unsafe fn atomic_load<T>(dst: *const T, order:Ordering) -> T {
}
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
unsafe fn atomic_swap<T>(dst: *mut T, val: T, order: Ordering) -> T {
match order {
Acquire => intrinsics::atomic_xchg_acq(dst, val),
@ -978,7 +977,6 @@ unsafe fn atomic_swap<T>(dst: *mut T, val: T, order: Ordering) -> T {
/// Returns the old value (like __sync_fetch_and_add).
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
unsafe fn atomic_add<T>(dst: *mut T, val: T, order: Ordering) -> T {
match order {
Acquire => intrinsics::atomic_xadd_acq(dst, val),
@ -991,7 +989,6 @@ unsafe fn atomic_add<T>(dst: *mut T, val: T, order: Ordering) -> T {
/// Returns the old value (like __sync_fetch_and_sub).
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
unsafe fn atomic_sub<T>(dst: *mut T, val: T, order: Ordering) -> T {
match order {
Acquire => intrinsics::atomic_xsub_acq(dst, val),
@ -1003,7 +1000,6 @@ unsafe fn atomic_sub<T>(dst: *mut T, val: T, order: Ordering) -> T {
}
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
unsafe fn atomic_compare_and_swap<T>(dst: *mut T, old:T, new:T, order: Ordering) -> T {
match order {
Acquire => intrinsics::atomic_cxchg_acq(dst, old, new),
@ -1015,7 +1011,6 @@ unsafe fn atomic_compare_and_swap<T>(dst: *mut T, old:T, new:T, order: Ordering)
}
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
unsafe fn atomic_and<T>(dst: *mut T, val: T, order: Ordering) -> T {
match order {
Acquire => intrinsics::atomic_and_acq(dst, val),
@ -1027,7 +1022,6 @@ unsafe fn atomic_and<T>(dst: *mut T, val: T, order: Ordering) -> T {
}
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
unsafe fn atomic_nand<T>(dst: *mut T, val: T, order: Ordering) -> T {
match order {
Acquire => intrinsics::atomic_nand_acq(dst, val),
@ -1040,7 +1034,6 @@ unsafe fn atomic_nand<T>(dst: *mut T, val: T, order: Ordering) -> T {
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
unsafe fn atomic_or<T>(dst: *mut T, val: T, order: Ordering) -> T {
match order {
Acquire => intrinsics::atomic_or_acq(dst, val),
@ -1053,7 +1046,6 @@ unsafe fn atomic_or<T>(dst: *mut T, val: T, order: Ordering) -> T {
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
unsafe fn atomic_xor<T>(dst: *mut T, val: T, order: Ordering) -> T {
match order {
Acquire => intrinsics::atomic_xor_acq(dst, val),
@ -1098,3 +1090,23 @@ pub fn fence(order: Ordering) {
}
}
}
macro_rules! impl_Debug {
($($t:ident)*) => ($(
#[stable(feature = "atomic_debug", since = "1.3.0")]
impl fmt::Debug for $t {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_tuple(stringify!($t)).field(&self.load(Ordering::SeqCst)).finish()
}
}
)*);
}
impl_Debug!{ AtomicUsize AtomicIsize AtomicBool }
#[stable(feature = "atomic_debug", since = "1.3.0")]
impl<T> fmt::Debug for AtomicPtr<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_tuple("AtomicPtr").field(&self.load(Ordering::SeqCst)).finish()
}
}

View File

@ -36,16 +36,16 @@
//! would otherwise be disallowed though, there are occasions when interior mutability might be
//! appropriate, or even *must* be used, e.g.
//!
//! * Introducing inherited mutability roots to shared types.
//! * Introducing mutability 'inside' of something immutable
//! * Implementation details of logically-immutable methods.
//! * Mutating implementations of `Clone`.
//!
//! ## Introducing inherited mutability roots to shared types
//! ## Introducing mutability 'inside' of something immutable
//!
//! Shared smart pointer types, including `Rc<T>` and `Arc<T>`, provide containers that can be
//! Many shared smart pointer types, including `Rc<T>` and `Arc<T>`, provide containers that can be
//! cloned and shared between multiple parties. Because the contained values may be
//! multiply-aliased, they can only be borrowed as shared references, not mutable references.
//! Without cells it would be impossible to mutate data inside of shared boxes at all!
//! multiply-aliased, they can only be borrowed with `&`, not `&mut`. Without cells it would be
//! impossible to mutate data inside of these smart pointers at all.
//!
//! It's very common then to put a `RefCell<T>` inside shared pointer types to reintroduce
//! mutability:
@ -65,8 +65,8 @@
//! ```
//!
//! Note that this example uses `Rc<T>` and not `Arc<T>`. `RefCell<T>`s are for single-threaded
//! scenarios. Consider using `Mutex<T>` if you need shared mutability in a multi-threaded
//! situation.
//! scenarios. Consider using `RwLock<T>` or `Mutex<T>` if you need shared mutability in a
//! multi-threaded situation.
//!
//! ## Implementation details of logically-immutable methods
//!

View File

@ -13,7 +13,6 @@
//! For more details, see ::rustc_unicode::char (a.k.a. std::char)
#![allow(non_snake_case)]
#![doc(primitive = "char")]
#![stable(feature = "core_char", since = "1.2.0")]
use iter::Iterator;
@ -85,10 +84,18 @@ pub fn from_u32(i: u32) -> Option<char> {
if (i > MAX as u32) || (i >= 0xD800 && i <= 0xDFFF) {
None
} else {
Some(unsafe { transmute(i) })
Some(unsafe { from_u32_unchecked(i) })
}
}
/// Converts a `u32` to an `char`, not checking whether it is a valid unicode
/// codepoint.
#[inline]
#[unstable(feature = "char_from_unchecked", reason = "recently added API")]
pub unsafe fn from_u32_unchecked(i: u32) -> char {
transmute(i)
}
/// Converts a number to the character representing it.
///
/// # Return value
@ -116,12 +123,11 @@ pub fn from_digit(num: u32, radix: u32) -> Option<char> {
panic!("from_digit: radix is too high (maximum 36)");
}
if num < radix {
unsafe {
if num < 10 {
Some(transmute('0' as u32 + num))
} else {
Some(transmute('a' as u32 + num - 10))
}
let num = num as u8;
if num < 10 {
Some((b'0' + num) as char)
} else {
Some((b'a' + num - 10) as char)
}
} else {
None
@ -319,16 +325,13 @@ impl Iterator for EscapeUnicode {
Some('{')
}
EscapeUnicodeState::Value(offset) => {
let v = match ((self.c as i32) >> (offset * 4)) & 0xf {
i @ 0 ... 9 => '0' as i32 + i,
i => 'a' as i32 + (i - 10)
};
let c = from_digit(((self.c as u32) >> (offset * 4)) & 0xf, 16).unwrap();
if offset == 0 {
self.state = EscapeUnicodeState::RightBrace;
} else {
self.state = EscapeUnicodeState::Value(offset - 1);
}
Some(unsafe { transmute(v) })
Some(c)
}
EscapeUnicodeState::RightBrace => {
self.state = EscapeUnicodeState::Done;

View File

@ -166,6 +166,8 @@ impl Ordering {
///
/// - total and antisymmetric: exactly one of `a < b`, `a == b` or `a > b` is true; and
/// - transitive, `a < b` and `b < c` implies `a < c`. The same must hold for both `==` and `>`.
///
/// When this trait is `derive`d, it produces a lexicographic ordering.
#[stable(feature = "rust1", since = "1.0.0")]
pub trait Ord: Eq + PartialOrd<Self> {
/// This method returns an `Ordering` between `self` and `other`.

View File

@ -175,6 +175,12 @@ impl<'a, 'b: 'a> DebugTuple<'a, 'b> {
fn is_pretty(&self) -> bool {
self.fmt.flags() & (1 << (FlagV1::Alternate as usize)) != 0
}
/// Returns the wrapped `Formatter`.
#[unstable(feature = "debug_builder_formatter", reason = "recently added")]
pub fn formatter(&mut self) -> &mut fmt::Formatter<'b> {
&mut self.fmt
}
}
struct DebugInner<'a, 'b: 'a> {

View File

@ -267,11 +267,18 @@ impl<'a> Display for Arguments<'a> {
}
}
/// Format trait for the `:?` format. Useful for debugging, all types
/// should implement this.
/// Format trait for the `?` character.
///
/// `Debug` should format the output in a programmer-facing, debugging context.
///
/// Generally speaking, you should just `derive` a `Debug` implementation.
///
/// When used with the alternate format specifier `#?`, the output is pretty-printed.
///
/// For more information on formatters, see [the module-level documentation][module].
///
/// [module]: ../index.html
///
/// # Examples
///
/// Deriving an implementation:
@ -309,10 +316,42 @@ impl<'a> Display for Arguments<'a> {
/// println!("The origin is: {:?}", origin);
/// ```
///
/// This outputs:
///
/// ```text
/// The origin is: Point { x: 0, y: 0 }
/// ```
///
/// There are a number of `debug_*` methods on `Formatter` to help you with manual
/// implementations, such as [`debug_struct`][debug_struct].
///
/// `Debug` implementations using either `derive` or the debug builder API
/// on `Formatter` support pretty printing using the alternate flag: `{:#?}`.
///
/// [debug_struct]: ../std/fmt/struct.Formatter.html#method.debug_struct
///
/// Pretty printing with `#?`:
///
/// ```
/// #[derive(Debug)]
/// struct Point {
/// x: i32,
/// y: i32,
/// }
///
/// let origin = Point { x: 0, y: 0 };
///
/// println!("The origin is: {:#?}", origin);
/// ```
///
/// This outputs:
///
/// ```text
/// The origin is: Point {
/// x: 0,
/// y: 0
/// }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_on_unimplemented = "`{Self}` cannot be formatted using `:?`; if it is \
defined in your crate, add `#[derive(Debug)]` or \
@ -324,8 +363,39 @@ pub trait Debug {
fn fmt(&self, &mut Formatter) -> Result;
}
/// When a value can be semantically expressed as a String, this trait may be
/// used. It corresponds to the default format, `{}`.
/// Format trait for an empty format, `{}`.
///
/// `Display` is similar to [`Debug`][debug], but `Display` is for user-facing
/// output, and so cannot be derived.
///
/// [debug]: trait.Debug.html
///
/// For more information on formatters, see [the module-level documentation][module].
///
/// [module]: ../index.html
///
/// # Examples
///
/// Implementing `Display` on a type:
///
/// ```
/// use std::fmt;
///
/// struct Point {
/// x: i32,
/// y: i32,
/// }
///
/// impl fmt::Display for Point {
/// fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
/// write!(f, "({}, {})", self.x, self.y)
/// }
/// }
///
/// let origin = Point { x: 0, y: 0 };
///
/// println!("The origin is: {}", origin);
/// ```
#[rustc_on_unimplemented = "`{Self}` cannot be formatted with the default \
formatter; try using `:?` instead if you are using \
a format string"]
@ -336,7 +406,46 @@ pub trait Display {
fn fmt(&self, &mut Formatter) -> Result;
}
/// Format trait for the `o` character
/// Format trait for the `o` character.
///
/// The `Octal` trait should format its output as a number in base-8.
///
/// The alternate flag, `#`, adds a `0o` in front of the output.
///
/// For more information on formatters, see [the module-level documentation][module].
///
/// [module]: ../index.html
///
/// # Examples
///
/// Basic usage with `i32`:
///
/// ```
/// let x = 42; // 42 is '52' in octal
///
/// assert_eq!(format!("{:o}", x), "52");
/// assert_eq!(format!("{:#o}", x), "0o52");
/// ```
///
/// Implementing `Octal` on a type:
///
/// ```
/// use std::fmt;
///
/// struct Length(i32);
///
/// impl fmt::Octal for Length {
/// fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
/// let val = self.0;
///
/// write!(f, "{:o}", val) // delegate to i32's implementation
/// }
/// }
///
/// let l = Length(9);
///
/// println!("l as octal is: {:o}", l);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub trait Octal {
/// Formats the value using the given formatter.
@ -344,7 +453,46 @@ pub trait Octal {
fn fmt(&self, &mut Formatter) -> Result;
}
/// Format trait for the `b` character
/// Format trait for the `b` character.
///
/// The `Binary` trait should format its output as a number in binary.
///
/// The alternate flag, `#`, adds a `0b` in front of the output.
///
/// For more information on formatters, see [the module-level documentation][module].
///
/// [module]: ../index.html
///
/// # Examples
///
/// Basic usage with `i32`:
///
/// ```
/// let x = 42; // 42 is '101010' in binary
///
/// assert_eq!(format!("{:b}", x), "101010");
/// assert_eq!(format!("{:#b}", x), "0b101010");
/// ```
///
/// Implementing `Binary` on a type:
///
/// ```
/// use std::fmt;
///
/// struct Length(i32);
///
/// impl fmt::Binary for Length {
/// fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
/// let val = self.0;
///
/// write!(f, "{:b}", val) // delegate to i32's implementation
/// }
/// }
///
/// let l = Length(107);
///
/// println!("l as binary is: {:b}", l);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub trait Binary {
/// Formats the value using the given formatter.
@ -352,7 +500,47 @@ pub trait Binary {
fn fmt(&self, &mut Formatter) -> Result;
}
/// Format trait for the `x` character
/// Format trait for the `x` character.
///
/// The `LowerHex` trait should format its output as a number in hexidecimal, with `a` through `f`
/// in lower case.
///
/// The alternate flag, `#`, adds a `0x` in front of the output.
///
/// For more information on formatters, see [the module-level documentation][module].
///
/// [module]: ../index.html
///
/// # Examples
///
/// Basic usage with `i32`:
///
/// ```
/// let x = 42; // 42 is '2a' in hex
///
/// assert_eq!(format!("{:x}", x), "2a");
/// assert_eq!(format!("{:#x}", x), "0x2a");
/// ```
///
/// Implementing `LowerHex` on a type:
///
/// ```
/// use std::fmt;
///
/// struct Length(i32);
///
/// impl fmt::LowerHex for Length {
/// fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
/// let val = self.0;
///
/// write!(f, "{:x}", val) // delegate to i32's implementation
/// }
/// }
///
/// let l = Length(9);
///
/// println!("l as hex is: {:x}", l);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub trait LowerHex {
/// Formats the value using the given formatter.
@ -360,7 +548,47 @@ pub trait LowerHex {
fn fmt(&self, &mut Formatter) -> Result;
}
/// Format trait for the `X` character
/// Format trait for the `X` character.
///
/// The `UpperHex` trait should format its output as a number in hexidecimal, with `A` through `F`
/// in upper case.
///
/// The alternate flag, `#`, adds a `0x` in front of the output.
///
/// For more information on formatters, see [the module-level documentation][module].
///
/// [module]: ../index.html
///
/// # Examples
///
/// Basic usage with `i32`:
///
/// ```
/// let x = 42; // 42 is '2A' in hex
///
/// assert_eq!(format!("{:X}", x), "2A");
/// assert_eq!(format!("{:#X}", x), "0x2A");
/// ```
///
/// Implementing `UpperHex` on a type:
///
/// ```
/// use std::fmt;
///
/// struct Length(i32);
///
/// impl fmt::UpperHex for Length {
/// fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
/// let val = self.0;
///
/// write!(f, "{:X}", val) // delegate to i32's implementation
/// }
/// }
///
/// let l = Length(9);
///
/// println!("l as hex is: {:X}", l);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub trait UpperHex {
/// Formats the value using the given formatter.
@ -368,7 +596,44 @@ pub trait UpperHex {
fn fmt(&self, &mut Formatter) -> Result;
}
/// Format trait for the `p` character
/// Format trait for the `p` character.
///
/// The `Pointer` trait should format its output as a memory location. This is commonly presented
/// as hexidecimal.
///
/// For more information on formatters, see [the module-level documentation][module].
///
/// [module]: ../index.html
///
/// # Examples
///
/// Basic usage with `&i32`:
///
/// ```
/// let x = &42;
///
/// let address = format!("{:p}", x); // this produces something like '0x7f06092ac6d0'
/// ```
///
/// Implementing `Pointer` on a type:
///
/// ```
/// use std::fmt;
///
/// struct Length(i32);
///
/// impl fmt::Pointer for Length {
/// fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
/// // use `as` to convert to a `*const T`, which implements Pointer, which we can use
///
/// write!(f, "{:p}", self as *const Length)
/// }
/// }
///
/// let l = Length(42);
///
/// println!("l is in memory here: {:p}", l);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub trait Pointer {
/// Formats the value using the given formatter.
@ -376,7 +641,42 @@ pub trait Pointer {
fn fmt(&self, &mut Formatter) -> Result;
}
/// Format trait for the `e` character
/// Format trait for the `e` character.
///
/// The `LowerExp` trait should format its output in scientific notation with a lower-case `e`.
///
/// For more information on formatters, see [the module-level documentation][module].
///
/// [module]: ../index.html
///
/// # Examples
///
/// Basic usage with `i32`:
///
/// ```
/// let x = 42.0; // 42.0 is '4.2e1' in scientific notation
///
/// assert_eq!(format!("{:e}", x), "4.2e1");
/// ```
///
/// Implementing `LowerExp` on a type:
///
/// ```
/// use std::fmt;
///
/// struct Length(i32);
///
/// impl fmt::LowerExp for Length {
/// fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
/// let val = self.0;
/// write!(f, "{}e1", val / 10)
/// }
/// }
///
/// let l = Length(100);
///
/// println!("l in scientific notation is: {:e}", l);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub trait LowerExp {
/// Formats the value using the given formatter.
@ -384,7 +684,42 @@ pub trait LowerExp {
fn fmt(&self, &mut Formatter) -> Result;
}
/// Format trait for the `E` character
/// Format trait for the `E` character.
///
/// The `UpperExp` trait should format its output in scientific notation with an upper-case `E`.
///
/// For more information on formatters, see [the module-level documentation][module].
///
/// [module]: ../index.html
///
/// # Examples
///
/// Basic usage with `f32`:
///
/// ```
/// let x = 42.0; // 42.0 is '4.2E1' in scientific notation
///
/// assert_eq!(format!("{:E}", x), "4.2E1");
/// ```
///
/// Implementing `UpperExp` on a type:
///
/// ```
/// use std::fmt;
///
/// struct Length(i32);
///
/// impl fmt::UpperExp for Length {
/// fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
/// let val = self.0;
/// write!(f, "{}E1", val / 10)
/// }
/// }
///
/// let l = Length(100);
///
/// println!("l in scientific notation is: {:E}", l);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub trait UpperExp {
/// Formats the value using the given formatter.
@ -980,7 +1315,14 @@ impl Debug for char {
#[stable(feature = "rust1", since = "1.0.0")]
impl Display for char {
fn fmt(&self, f: &mut Formatter) -> Result {
f.write_char(*self)
if f.width.is_none() && f.precision.is_none() {
f.write_char(*self)
} else {
let mut utf8 = [0; 4];
let amt = self.encode_utf8(&mut utf8).unwrap_or(0);
let s: &str = unsafe { mem::transmute(&utf8[..amt]) };
f.pad(s)
}
}
}
@ -1146,20 +1488,19 @@ macro_rules! tuple {
impl<$($name:Debug),*> Debug for ($($name,)*) {
#[allow(non_snake_case, unused_assignments)]
fn fmt(&self, f: &mut Formatter) -> Result {
try!(write!(f, "("));
let mut builder = f.debug_tuple("");
let ($(ref $name,)*) = *self;
let mut n = 0;
$(
if n > 0 {
try!(write!(f, ", "));
}
try!(write!(f, "{:?}", *$name));
builder.field($name);
n += 1;
)*
if n == 1 {
try!(write!(f, ","));
try!(write!(builder.formatter(), ","));
}
write!(f, ")")
builder.finish()
}
}
peel! { $($name,)* }

View File

@ -12,26 +12,31 @@
// FIXME: #6220 Implement floating point formatting
#![allow(unsigned_negation)]
use prelude::*;
use fmt;
use num::Zero;
use ops::{Div, Rem, Sub};
use str;
use slice;
use ptr;
use mem;
#[doc(hidden)]
trait Int: Zero + PartialEq + PartialOrd + Div<Output=Self> + Rem<Output=Self> +
Sub<Output=Self> + Copy {
fn from_u8(u: u8) -> Self;
fn to_u8(&self) -> u8;
fn to_u32(&self) -> u32;
fn to_u64(&self) -> u64;
}
macro_rules! doit {
($($t:ident)*) => ($(impl Int for $t {
fn from_u8(u: u8) -> $t { u as $t }
fn to_u8(&self) -> u8 { *self as u8 }
fn to_u32(&self) -> u32 { *self as u32 }
fn to_u64(&self) -> u64 { *self as u64 }
})*)
}
doit! { i8 i16 i32 i64 isize u8 u16 u32 u64 usize }
@ -188,6 +193,7 @@ macro_rules! radix_fmt {
}
}
}
macro_rules! int_base {
($Trait:ident for $T:ident as $U:ident -> $Radix:ident) => {
#[stable(feature = "rust1", since = "1.0.0")]
@ -209,9 +215,9 @@ macro_rules! debug {
}
}
}
macro_rules! integer {
($Int:ident, $Uint:ident) => {
int_base! { Display for $Int as $Int -> Decimal }
int_base! { Binary for $Int as $Uint -> Binary }
int_base! { Octal for $Int as $Uint -> Octal }
int_base! { LowerHex for $Int as $Uint -> LowerHex }
@ -219,7 +225,6 @@ macro_rules! integer {
radix_fmt! { $Int as $Int, fmt_int }
debug! { $Int }
int_base! { Display for $Uint as $Uint -> Decimal }
int_base! { Binary for $Uint as $Uint -> Binary }
int_base! { Octal for $Uint as $Uint -> Octal }
int_base! { LowerHex for $Uint as $Uint -> LowerHex }
@ -233,3 +238,80 @@ integer! { i8, u8 }
integer! { i16, u16 }
integer! { i32, u32 }
integer! { i64, u64 }
const DEC_DIGITS_LUT: &'static[u8] =
b"0001020304050607080910111213141516171819\
2021222324252627282930313233343536373839\
4041424344454647484950515253545556575859\
6061626364656667686970717273747576777879\
8081828384858687888990919293949596979899";
macro_rules! impl_Display {
($($t:ident),*: $conv_fn:ident) => ($(
impl fmt::Display for $t {
#[allow(unused_comparisons)]
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let is_positive = *self >= 0;
let mut n = if is_positive {
self.$conv_fn()
} else {
// convert the negative num to positive by summing 1 to it's 2 complement
(!self.$conv_fn()).wrapping_add(1)
};
let mut buf: [u8; 20] = unsafe { mem::uninitialized() };
let mut curr = buf.len() as isize;
let buf_ptr = buf.as_mut_ptr();
let lut_ptr = DEC_DIGITS_LUT.as_ptr();
unsafe {
// eagerly decode 4 characters at a time
if <$t>::max_value() as u64 >= 10000 {
while n >= 10000 {
let rem = (n % 10000) as isize;
n /= 10000;
let d1 = (rem / 100) << 1;
let d2 = (rem % 100) << 1;
curr -= 4;
ptr::copy_nonoverlapping(lut_ptr.offset(d1), buf_ptr.offset(curr), 2);
ptr::copy_nonoverlapping(lut_ptr.offset(d2), buf_ptr.offset(curr + 2), 2);
}
}
// if we reach here numbers are <= 9999, so at most 4 chars long
let mut n = n as isize; // possibly reduce 64bit math
// decode 2 more chars, if > 2 chars
if n >= 100 {
let d1 = (n % 100) << 1;
n /= 100;
curr -= 2;
ptr::copy_nonoverlapping(lut_ptr.offset(d1), buf_ptr.offset(curr), 2);
}
// decode last 1 or 2 chars
if n < 10 {
curr -= 1;
*buf_ptr.offset(curr) = (n as u8) + 48;
} else {
let d1 = n << 1;
curr -= 2;
ptr::copy_nonoverlapping(lut_ptr.offset(d1), buf_ptr.offset(curr), 2);
}
}
let buf_slice = unsafe {
str::from_utf8_unchecked(
slice::from_raw_parts(buf_ptr.offset(curr), buf.len() - curr as usize))
};
f.pad_integral(is_positive, "", buf_slice)
}
})*);
}
impl_Display!(i8, u8, i16, u16, i32, u32: to_u32);
impl_Display!(i64, u64: to_u64);
#[cfg(target_pointer_width = "32")]
impl_Display!(isize, usize: to_u32);
#[cfg(target_pointer_width = "64")]
impl_Display!(isize, usize: to_u64);

View File

@ -10,8 +10,6 @@
//! An implementation of SipHash 2-4.
#![allow(deprecated)] // until the next snapshot for inherent wrapping ops
use prelude::*;
use super::Hasher;

View File

@ -184,6 +184,14 @@ extern "rust-intrinsic" {
/// elements.
pub fn size_of<T>() -> usize;
#[cfg(not(stage0))]
/// Moves a value to an uninitialized memory location.
///
/// Drop glue is not run on the destination.
pub fn move_val_init<T>(dst: *mut T, src: T);
// SNAP d4432b3
#[cfg(stage0)]
/// Moves a value to an uninitialized memory location.
///
/// Drop glue is not run on the destination.
@ -586,20 +594,26 @@ extern "rust-intrinsic" {
pub fn overflowing_mul<T>(a: T, b: T) -> T;
/// Performs an unchecked signed division, which results in undefined behavior,
/// in cases where y == 0, or x == int::MIN and y == -1
/// in cases where y == 0, or x == isize::MIN and y == -1
pub fn unchecked_sdiv<T>(x: T, y: T) -> T;
/// Performs an unchecked unsigned division, which results in undefined behavior,
/// in cases where y == 0
pub fn unchecked_udiv<T>(x: T, y: T) -> T;
/// Returns the remainder of an unchecked signed division, which results in
/// undefined behavior, in cases where y == 0, or x == int::MIN and y == -1
pub fn unchecked_urem<T>(x: T, y: T) -> T;
/// Returns the remainder of an unchecked signed division, which results in
/// undefined behavior, in cases where y == 0
/// undefined behavior, in cases where y == 0, or x == isize::MIN and y == -1
pub fn unchecked_srem<T>(x: T, y: T) -> T;
/// Returns the remainder of an unchecked unsigned division, which results in
/// undefined behavior, in cases where y == 0
pub fn unchecked_urem<T>(x: T, y: T) -> T;
/// Returns the value of the discriminant for the variant in 'v',
/// cast to a `u64`; if `T` has no discriminant, returns 0.
pub fn discriminant_value<T>(v: &T) -> u64;
/// Rust's "try catch" construct which invokes the function pointer `f` with
/// the data pointer `data`, returning the exception payload if an exception
/// is thrown (aka the thread panics).
#[cfg(not(stage0))]
pub fn try(f: fn(*mut u8), data: *mut u8) -> *mut u8;
}

View File

@ -2555,7 +2555,7 @@ impl<I: RandomAccessIterator, F> RandomAccessIterator for Inspect<I, F>
#[unstable(feature = "iter_unfold")]
#[derive(Clone)]
#[deprecated(since = "1.2.0",
reason = "has gained enough traction to retain its position \
reason = "has not gained enough traction to retain its position \
in the standard library")]
#[allow(deprecated)]
pub struct Unfold<St, F> {
@ -2567,7 +2567,7 @@ pub struct Unfold<St, F> {
#[unstable(feature = "iter_unfold")]
#[deprecated(since = "1.2.0",
reason = "has gained enough traction to retain its position \
reason = "has not gained enough traction to retain its position \
in the standard library")]
#[allow(deprecated)]
impl<A, St, F> Unfold<St, F> where F: FnMut(&mut St) -> Option<A> {
@ -2655,8 +2655,8 @@ macro_rules! step_impl_signed {
#[allow(trivial_numeric_casts)]
fn steps_between(start: &$t, end: &$t, by: &$t) -> Option<usize> {
if *by == 0 { return None; }
let mut diff: usize;
let mut by_u: usize;
let diff: usize;
let by_u: usize;
if *by > 0 {
if *start >= *end {
return Some(0);
@ -3018,7 +3018,7 @@ type IterateState<T, F> = (F, Option<T>, bool);
/// from a given seed value.
#[unstable(feature = "iter_iterate")]
#[deprecated(since = "1.2.0",
reason = "has gained enough traction to retain its position \
reason = "has not gained enough traction to retain its position \
in the standard library")]
#[allow(deprecated)]
pub type Iterate<T, F> = Unfold<IterateState<T, F>, fn(&mut IterateState<T, F>) -> Option<T>>;
@ -3027,7 +3027,7 @@ pub type Iterate<T, F> = Unfold<IterateState<T, F>, fn(&mut IterateState<T, F>)
/// repeated applications of the given function `f`.
#[unstable(feature = "iter_iterate")]
#[deprecated(since = "1.2.0",
reason = "has gained enough traction to retain its position \
reason = "has not gained enough traction to retain its position \
in the standard library")]
#[allow(deprecated)]
pub fn iterate<T, F>(seed: T, f: F) -> Iterate<T, F> where

View File

@ -154,10 +154,6 @@ pub mod str;
pub mod hash;
pub mod fmt;
#[doc(primitive = "bool")]
mod bool {
}
// note: does not need to be public
mod tuple;

View File

@ -155,6 +155,7 @@ pub fn size_of_val<T: ?Sized>(val: &T) -> usize {
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
#[deprecated(reason = "use `align_of` instead", since = "1.2.0")]
pub fn min_align_of<T>() -> usize {
unsafe { intrinsics::min_align_of::<T>() }
}
@ -170,14 +171,14 @@ pub fn min_align_of<T>() -> usize {
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
#[deprecated(reason = "use `align_of_val` instead", since = "1.2.0")]
pub fn min_align_of_val<T: ?Sized>(val: &T) -> usize {
unsafe { intrinsics::min_align_of_val(val) }
}
/// Returns the alignment in memory for a type.
///
/// This function will return the alignment, in bytes, of a type in memory. If the alignment
/// returned is adhered to, then the type is guaranteed to function properly.
/// This is the alignment used for struct fields. It may be smaller than the preferred alignment.
///
/// # Examples
///
@ -189,17 +190,10 @@ pub fn min_align_of_val<T: ?Sized>(val: &T) -> usize {
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn align_of<T>() -> usize {
// We use the preferred alignment as the default alignment for a type. This
// appears to be what clang migrated towards as well:
//
// http://lists.cs.uiuc.edu/pipermail/cfe-commits/Week-of-Mon-20110725/044411.html
unsafe { intrinsics::pref_align_of::<T>() }
unsafe { intrinsics::min_align_of::<T>() }
}
/// Returns the alignment of the type of the value that `_val` points to.
///
/// This is similar to `align_of`, but function will properly handle types such as trait objects
/// (in the future), returning the alignment for an arbitrary value at runtime.
/// Returns the ABI-required minimum alignment of the type of the value that `val` points to
///
/// # Examples
///
@ -210,8 +204,8 @@ pub fn align_of<T>() -> usize {
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn align_of_val<T>(_val: &T) -> usize {
align_of::<T>()
pub fn align_of_val<T: ?Sized>(val: &T) -> usize {
unsafe { intrinsics::min_align_of_val(val) }
}
/// Creates a value initialized to zero.
@ -371,11 +365,48 @@ pub fn replace<T>(dest: &mut T, mut src: T) -> T {
/// Disposes of a value.
///
/// This function can be used to destroy any value by allowing `drop` to take ownership of its
/// argument.
/// While this does call the argument's implementation of `Drop`, it will not
/// release any borrows, as borrows are based on lexical scope.
///
/// # Examples
///
/// Basic usage:
///
/// ```
/// let v = vec![1, 2, 3];
///
/// drop(v); // explicitly drop the vector
/// ```
///
/// Borrows are based on lexical scope, so this produces an error:
///
/// ```ignore
/// let mut v = vec![1, 2, 3];
/// let x = &v[0];
///
/// drop(x); // explicitly drop the reference, but the borrow still exists
///
/// v.push(4); // error: cannot borrow `v` as mutable because it is also
/// // borrowed as immutable
/// ```
///
/// An inner scope is needed to fix this:
///
/// ```
/// let mut v = vec![1, 2, 3];
///
/// {
/// let x = &v[0];
///
/// drop(x); // this is now redundant, as `x` is going out of scope anyway
/// }
///
/// v.push(4); // no problems
/// ```
///
/// Since `RefCell` enforces the borrow rules at runtime, `drop()` can
/// seemingly release a borrow of one:
///
/// ```
/// use std::cell::RefCell;
///
@ -414,17 +445,22 @@ macro_rules! repeat_u8_as_u64 {
//
// And of course, 0x00 brings back the old world of zero'ing on drop.
#[unstable(feature = "filling_drop")]
#[allow(missing_docs)]
pub const POST_DROP_U8: u8 = 0x1d;
#[unstable(feature = "filling_drop")]
#[allow(missing_docs)]
pub const POST_DROP_U32: u32 = repeat_u8_as_u32!(POST_DROP_U8);
#[unstable(feature = "filling_drop")]
#[allow(missing_docs)]
pub const POST_DROP_U64: u64 = repeat_u8_as_u64!(POST_DROP_U8);
#[cfg(target_pointer_width = "32")]
#[unstable(feature = "filling_drop")]
#[allow(missing_docs)]
pub const POST_DROP_USIZE: usize = POST_DROP_U32 as usize;
#[cfg(target_pointer_width = "64")]
#[unstable(feature = "filling_drop")]
#[allow(missing_docs)]
pub const POST_DROP_USIZE: usize = POST_DROP_U64 as usize;
/// Interprets `src` as `&U`, and then reads `src` without moving the contained

View File

@ -10,7 +10,6 @@
//! Operations and constants for 32-bits floats (`f32` type)
#![doc(primitive = "f32")]
// FIXME: MIN_VALUE and MAX_VALUE literals are parsed as -inf and inf #14353
#![allow(overflowing_literals)]
@ -24,14 +23,18 @@ use num::{Float, ParseFloatError};
use num::FpCategory as Fp;
#[stable(feature = "rust1", since = "1.0.0")]
#[allow(missing_docs)]
pub const RADIX: u32 = 2;
#[stable(feature = "rust1", since = "1.0.0")]
#[allow(missing_docs)]
pub const MANTISSA_DIGITS: u32 = 24;
#[stable(feature = "rust1", since = "1.0.0")]
#[allow(missing_docs)]
pub const DIGITS: u32 = 6;
#[stable(feature = "rust1", since = "1.0.0")]
#[allow(missing_docs)]
pub const EPSILON: f32 = 1.19209290e-07_f32;
/// Smallest finite f32 value
@ -45,20 +48,27 @@ pub const MIN_POSITIVE: f32 = 1.17549435e-38_f32;
pub const MAX: f32 = 3.40282347e+38_f32;
#[stable(feature = "rust1", since = "1.0.0")]
#[allow(missing_docs)]
pub const MIN_EXP: i32 = -125;
#[stable(feature = "rust1", since = "1.0.0")]
#[allow(missing_docs)]
pub const MAX_EXP: i32 = 128;
#[stable(feature = "rust1", since = "1.0.0")]
#[allow(missing_docs)]
pub const MIN_10_EXP: i32 = -37;
#[stable(feature = "rust1", since = "1.0.0")]
#[allow(missing_docs)]
pub const MAX_10_EXP: i32 = 38;
#[stable(feature = "rust1", since = "1.0.0")]
#[allow(missing_docs)]
pub const NAN: f32 = 0.0_f32/0.0_f32;
#[stable(feature = "rust1", since = "1.0.0")]
#[allow(missing_docs)]
pub const INFINITY: f32 = 1.0_f32/0.0_f32;
#[stable(feature = "rust1", since = "1.0.0")]
#[allow(missing_docs)]
pub const NEG_INFINITY: f32 = -1.0_f32/0.0_f32;
/// Basic mathematial constants.
@ -215,13 +225,37 @@ impl Float for f32 {
/// Rounds towards minus infinity.
#[inline]
fn floor(self) -> f32 {
unsafe { intrinsics::floorf32(self) }
return floorf(self);
// On MSVC LLVM will lower many math intrinsics to a call to the
// corresponding function. On MSVC, however, many of these functions
// aren't actually available as symbols to call, but rather they are all
// `static inline` functions in header files. This means that from a C
// perspective it's "compatible", but not so much from an ABI
// perspective (which we're worried about).
//
// The inline header functions always just cast to a f64 and do their
// operation, so we do that here as well, but only for MSVC targets.
//
// Note that there are many MSVC-specific float operations which
// redirect to this comment, so `floorf` is just one case of a missing
// function on MSVC, but there are many others elsewhere.
#[cfg(target_env = "msvc")]
fn floorf(f: f32) -> f32 { (f as f64).floor() as f32 }
#[cfg(not(target_env = "msvc"))]
fn floorf(f: f32) -> f32 { unsafe { intrinsics::floorf32(f) } }
}
/// Rounds towards plus infinity.
#[inline]
fn ceil(self) -> f32 {
unsafe { intrinsics::ceilf32(self) }
return ceilf(self);
// see notes above in `floor`
#[cfg(target_env = "msvc")]
fn ceilf(f: f32) -> f32 { (f as f64).ceil() as f32 }
#[cfg(not(target_env = "msvc"))]
fn ceilf(f: f32) -> f32 { unsafe { intrinsics::ceilf32(f) } }
}
/// Rounds to nearest integer. Rounds half-way cases away from zero.
@ -299,7 +333,13 @@ impl Float for f32 {
#[inline]
fn powf(self, n: f32) -> f32 {
unsafe { intrinsics::powf32(self, n) }
return powf(self, n);
// see notes above in `floor`
#[cfg(target_env = "msvc")]
fn powf(f: f32, n: f32) -> f32 { (f as f64).powf(n as f64) as f32 }
#[cfg(not(target_env = "msvc"))]
fn powf(f: f32, n: f32) -> f32 { unsafe { intrinsics::powf32(f, n) } }
}
#[inline]
@ -317,7 +357,13 @@ impl Float for f32 {
/// Returns the exponential of the number.
#[inline]
fn exp(self) -> f32 {
unsafe { intrinsics::expf32(self) }
return expf(self);
// see notes above in `floor`
#[cfg(target_env = "msvc")]
fn expf(f: f32) -> f32 { (f as f64).exp() as f32 }
#[cfg(not(target_env = "msvc"))]
fn expf(f: f32) -> f32 { unsafe { intrinsics::expf32(f) } }
}
/// Returns 2 raised to the power of the number.
@ -329,7 +375,13 @@ impl Float for f32 {
/// Returns the natural logarithm of the number.
#[inline]
fn ln(self) -> f32 {
unsafe { intrinsics::logf32(self) }
return logf(self);
// see notes above in `floor`
#[cfg(target_env = "msvc")]
fn logf(f: f32) -> f32 { (f as f64).ln() as f32 }
#[cfg(not(target_env = "msvc"))]
fn logf(f: f32) -> f32 { unsafe { intrinsics::logf32(f) } }
}
/// Returns the logarithm of the number with respect to an arbitrary base.
@ -345,7 +397,13 @@ impl Float for f32 {
/// Returns the base 10 logarithm of the number.
#[inline]
fn log10(self) -> f32 {
unsafe { intrinsics::log10f32(self) }
return log10f(self);
// see notes above in `floor`
#[cfg(target_env = "msvc")]
fn log10f(f: f32) -> f32 { (f as f64).log10() as f32 }
#[cfg(not(target_env = "msvc"))]
fn log10f(f: f32) -> f32 { unsafe { intrinsics::log10f32(f) } }
}
/// Converts to degrees, assuming the number is in radians.

View File

@ -10,7 +10,6 @@
//! Operations and constants for 64-bits floats (`f64` type)
#![doc(primitive = "f64")]
// FIXME: MIN_VALUE and MAX_VALUE literals are parsed as -inf and inf #14353
#![allow(overflowing_literals)]
@ -24,14 +23,18 @@ use num::FpCategory as Fp;
use num::{Float, ParseFloatError};
#[stable(feature = "rust1", since = "1.0.0")]
#[allow(missing_docs)]
pub const RADIX: u32 = 2;
#[stable(feature = "rust1", since = "1.0.0")]
#[allow(missing_docs)]
pub const MANTISSA_DIGITS: u32 = 53;
#[stable(feature = "rust1", since = "1.0.0")]
#[allow(missing_docs)]
pub const DIGITS: u32 = 15;
#[stable(feature = "rust1", since = "1.0.0")]
#[allow(missing_docs)]
pub const EPSILON: f64 = 2.2204460492503131e-16_f64;
/// Smallest finite f64 value
@ -45,20 +48,27 @@ pub const MIN_POSITIVE: f64 = 2.2250738585072014e-308_f64;
pub const MAX: f64 = 1.7976931348623157e+308_f64;
#[stable(feature = "rust1", since = "1.0.0")]
#[allow(missing_docs)]
pub const MIN_EXP: i32 = -1021;
#[stable(feature = "rust1", since = "1.0.0")]
#[allow(missing_docs)]
pub const MAX_EXP: i32 = 1024;
#[stable(feature = "rust1", since = "1.0.0")]
#[allow(missing_docs)]
pub const MIN_10_EXP: i32 = -307;
#[stable(feature = "rust1", since = "1.0.0")]
#[allow(missing_docs)]
pub const MAX_10_EXP: i32 = 308;
#[stable(feature = "rust1", since = "1.0.0")]
#[allow(missing_docs)]
pub const NAN: f64 = 0.0_f64/0.0_f64;
#[stable(feature = "rust1", since = "1.0.0")]
#[allow(missing_docs)]
pub const INFINITY: f64 = 1.0_f64/0.0_f64;
#[stable(feature = "rust1", since = "1.0.0")]
#[allow(missing_docs)]
pub const NEG_INFINITY: f64 = -1.0_f64/0.0_f64;
/// Basic mathematial constants.

View File

@ -11,6 +11,5 @@
//! Operations and constants for signed 16-bits integers (`i16` type)
#![stable(feature = "rust1", since = "1.0.0")]
#![doc(primitive = "i16")]
int_module! { i16, 16 }

View File

@ -11,6 +11,5 @@
//! Operations and constants for signed 32-bits integers (`i32` type)
#![stable(feature = "rust1", since = "1.0.0")]
#![doc(primitive = "i32")]
int_module! { i32, 32 }

View File

@ -11,6 +11,5 @@
//! Operations and constants for signed 64-bits integers (`i64` type)
#![stable(feature = "rust1", since = "1.0.0")]
#![doc(primitive = "i64")]
int_module! { i64, 64 }

View File

@ -11,6 +11,5 @@
//! Operations and constants for signed 8-bits integers (`i8` type)
#![stable(feature = "rust1", since = "1.0.0")]
#![doc(primitive = "i8")]
int_module! { i8, 8 }

View File

@ -16,21 +16,25 @@ macro_rules! int_module { ($T:ty, $bits:expr) => (
// calling the `mem::size_of` function.
#[unstable(feature = "num_bits_bytes",
reason = "may want to be an associated function")]
#[allow(missing_docs)]
pub const BITS : usize = $bits;
// FIXME(#11621): Should be deprecated once CTFE is implemented in favour of
// calling the `mem::size_of` function.
#[unstable(feature = "num_bits_bytes",
reason = "may want to be an associated function")]
#[allow(missing_docs)]
pub const BYTES : usize = ($bits / 8);
// FIXME(#11621): Should be deprecated once CTFE is implemented in favour of
// calling the `Bounded::min_value` function.
#[stable(feature = "rust1", since = "1.0.0")]
#[allow(missing_docs)]
pub const MIN: $T = (-1 as $T) << (BITS - 1);
// FIXME(#9837): Compute MIN like this so the high bits that shouldn't exist are 0.
// FIXME(#11621): Should be deprecated once CTFE is implemented in favour of
// calling the `Bounded::max_value` function.
#[stable(feature = "rust1", since = "1.0.0")]
#[allow(missing_docs)]
pub const MAX: $T = !MIN;
) }

View File

@ -11,7 +11,6 @@
//! Operations and constants for pointer-sized signed integers (`isize` type)
#![stable(feature = "rust1", since = "1.0.0")]
#![doc(primitive = "isize")]
#[cfg(target_pointer_width = "32")]
int_module! { isize, 32 }

View File

@ -24,6 +24,7 @@ use mem::size_of;
use option::Option::{self, Some, None};
use result::Result::{self, Ok, Err};
use str::{FromStr, StrExt};
use slice::SliceExt;
/// Provides intentionally-wrapped arithmetic on `T`.
///
@ -459,7 +460,7 @@ macro_rules! int_impl {
}
}
/// Wrapping (modular) division. Computes `floor(self / other)`,
/// Wrapping (modular) division. Computes `self / other`,
/// wrapping around at the boundary of the type.
///
/// The only case where such wrapping can occur is when one
@ -467,7 +468,7 @@ macro_rules! int_impl {
/// negative minimal value for the type); this is equivalent
/// to `-MIN`, a positive value that is too large to represent
/// in the type. In such a case, this function returns `MIN`
/// itself..
/// itself.
#[stable(feature = "num_wrapping", since = "1.2.0")]
#[inline(always)]
pub fn wrapping_div(self, rhs: Self) -> Self {
@ -668,10 +669,12 @@ macro_rules! uint_impl {
$mul_with_overflow:path) => {
/// Returns the smallest value that can be represented by this integer type.
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn min_value() -> Self { 0 }
/// Returns the largest value that can be represented by this integer type.
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn max_value() -> Self { !0 }
/// Converts a string slice in a given base to an integer.
@ -1029,7 +1032,7 @@ macro_rules! uint_impl {
}
}
/// Wrapping (modular) division. Computes `floor(self / other)`,
/// Wrapping (modular) division. Computes `self / other`,
/// wrapping around at the boundary of the type.
///
/// The only case where such wrapping can occur is when one
@ -1037,7 +1040,7 @@ macro_rules! uint_impl {
/// negative minimal value for the type); this is equivalent
/// to `-MIN`, a positive value that is too large to represent
/// in the type. In such a case, this function returns `MIN`
/// itself..
/// itself.
#[stable(feature = "num_wrapping", since = "1.2.0")]
#[inline(always)]
pub fn wrapping_div(self, rhs: Self) -> Self {
@ -1124,7 +1127,7 @@ macro_rules! uint_impl {
acc
}
/// Returns `true` iff `self == 2^k` for some `k`.
/// Returns `true` if and only if `self == 2^k` for some `k`.
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn is_power_of_two(self) -> bool {
@ -1446,19 +1449,30 @@ fn from_str_radix<T: FromStrRadixHelper>(src: &str, radix: u32)
-> Result<T, ParseIntError> {
use self::IntErrorKind::*;
use self::ParseIntError as PIE;
assert!(radix >= 2 && radix <= 36,
"from_str_radix_int: must lie in the range `[2, 36]` - found {}",
radix);
if src.is_empty() {
return Err(PIE { kind: Empty });
}
let is_signed_ty = T::from_u32(0) > T::min_value();
match src.slice_shift_char() {
Some(('-', "")) => Err(PIE { kind: Empty }),
Some(('-', src)) if is_signed_ty => {
// all valid digits are ascii, so we will just iterate over the utf8 bytes
// and cast them to chars. .to_digit() will safely return None for anything
// other than a valid ascii digit for a the given radix, including the first-byte
// of multi-byte sequences
let src = src.as_bytes();
match (src[0], &src[1..]) {
(b'-', digits) if digits.is_empty() => Err(PIE { kind: Empty }),
(b'-', digits) if is_signed_ty => {
// The number is negative
let mut result = T::from_u32(0);
for c in src.chars() {
let x = match c.to_digit(radix) {
for &c in digits {
let x = match (c as char).to_digit(radix) {
Some(x) => x,
None => return Err(PIE { kind: InvalidDigit }),
};
@ -1473,11 +1487,14 @@ fn from_str_radix<T: FromStrRadixHelper>(src: &str, radix: u32)
}
Ok(result)
},
Some((_, _)) => {
(c, digits) => {
// The number is signed
let mut result = T::from_u32(0);
for c in src.chars() {
let x = match c.to_digit(radix) {
let mut result = match (c as char).to_digit(radix) {
Some(x) => T::from_u32(x),
None => return Err(PIE { kind: InvalidDigit }),
};
for &c in digits {
let x = match (c as char).to_digit(radix) {
Some(x) => x,
None => return Err(PIE { kind: InvalidDigit }),
};
@ -1491,8 +1508,7 @@ fn from_str_radix<T: FromStrRadixHelper>(src: &str, radix: u32)
};
}
Ok(result)
},
None => Err(ParseIntError { kind: Empty }),
}
}
}

View File

@ -11,6 +11,5 @@
//! Operations and constants for unsigned 16-bits integers (`u16` type)
#![stable(feature = "rust1", since = "1.0.0")]
#![doc(primitive = "u16")]
uint_module! { u16, i16, 16 }

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