# email addresses.
#
-Elly Jones <elly@leptoquark.net>
-ILyoan <ilyoan@gmail.com>
+Aaron Todd <github@opprobrio.us>
+Ahmed Charles <ahmedcharles@gmail.com> <acharles@outlook.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>
+Austin Seipp <mad.one@gmail.com> <as@hacks.yi.org>
+Ben Alpert <ben@benalpert.com> <spicyjalapeno@gmail.com>
+Benjamin Jackman <ben@jackman.biz>
+Björn Steinbrink <bsteinbr@gmail.com> <B.Steinbrink@gmx.de>
+blake2-ppc <ulrik.sverdrup@gmail.com> <blake2-ppc>
+Boris Egorov <jightuse@gmail.com> <egorov@linux.com>
+Brian Anderson <banderson@mozilla.com> <andersrb@gmail.com>
+Brian Dawn <brian.t.dawn@gmail.com>
+Carl-Anton Ingmarsson <mail@carlanton.se> <ca.ingmarsson@gmail.com>
+Carol Willing <carolcode@willingconsulting.com>
+Chris Pressey <cpressey@gmail.com>
+Clark Gaebel <cg.wowus.cg@gmail.com> <cgaebel@mozilla.com>
+David Klein <david.klein@baesystemsdetica.com>
+David Manescu <david.manescu@gmail.com> <dman2626@uni.sydney.edu.au>
+Damien Schoof <damien.schoof@gmail.com>
+Derek Chiang <derekchiang93@gmail.com> Derek Chiang (Enchi Jiang) <derekchiang93@gmail.com>
+Dylan Braithwaite <dylanbraithwaite1@gmail.com> <mail@dylanb.me>
+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>
+Eric Holk <eric.holk@gmail.com> <eholk@mozilla.com>
+Eric Holk <eric.holk@gmail.com> <eholk@cs.indiana.edu>
+Eric Holmes <eric@ejholmes.net>
+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>
+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>
+Graydon Hoare <graydon@mozilla.com> <graydon@pobox.com>
+Heather <heather@cynede.net> <Heather@cynede.net>
+Heather <heather@cynede.net> <Cynede@Gentoo.org>
+Ilyong Cho <ilyoan@gmail.com>
+J. J. Weber <jjweber@gmail.com>
+Jakub Bukaj <jakub@jakub.cc>
+Jakub Bukaj <jakub@jakub.cc> <jakubw@jakubw.net>
+James Deng <cnjamesdeng@gmail.com> <cnJamesDeng@gmail.com>
+James Miller <bladeon@gmail.com> <james@aatch.net>
+Jason Orendorff <jorendorff@mozilla.com> <jason@mozmac-2.local>
+Jason Orendorff <jorendorff@mozilla.com> <jason.orendorff@gmail.com>
+Jeremy Letang <letang.jeremy@gmail.com>
+Jihyun Yu <jihyun@nclab.kaist.ac.kr> jihyun <jihyun@nablecomm.com>
+Jihyun Yu <jihyun@nclab.kaist.ac.kr> <yjh0502@gmail.com>
+John Clements <clements@racket-lang.org> <clements@brinckerhoff.org>
+Jorge Aparicio <japaric@linux.com> <japaricious@gmail.com>
+Jonathan Bailey <jbailey@mozilla.com> <jbailey@jbailey-20809.local>
Junyoung Cho <june0.cho@samsung.com>
+Jyun-Yan You <jyyou.tw@gmail.com> <jyyou@cs.nctu.edu.tw>
+Kang Seonghoon <kang.seonghoon@mearie.org> <public+git@mearie.org>
+Keegan McAllister <kmcallister@mozilla.com> <mcallister.keegan@gmail.com>
+Kyeongwoon Lee <kyeongwoon.lee@samsung.com>
+Lee Wondong <wdlee91@gmail.com>
+Lennart Kudling <github@kudling.de>
+Lindsey Kuper <lindsey@composition.al> <lindsey@rockstargirl.org>
+Lindsey Kuper <lindsey@composition.al> <lkuper@mozilla.com>
+Luqman Aden <me@luqman.ca> <laden@mozilla.com>
+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>
+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>
+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>
+Neil Pankey <npankey@gmail.com> <neil@wire.im>
+Philipp Brüschweiler <blei42@gmail.com> <blei42@gmail.com>
+Philipp Brüschweiler <blei42@gmail.com> <bruphili@student.ethz.ch>
+Pradeep Kumar <gohanpra@gmail.com>
+Richard Diamond <wichard@vitalitystudios.com> <wichard@hahbee.co>
Rob Arnold <robarnold@cs.cmu.edu>
+Robert Gawdzik <rgawdzik@hotmail.com> Robert Gawdzik ☢ <rgawdzik@hotmail.com>
+Robert Millar <robert.millar@cantab.net>
+Ryan Scheel <ryan.havvy@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>
+startling <tdixon51793@gmail.com>
+Steven Fackler <sfackler@gmail.com> <sfackler@palantir.com>
+Steven Stewart-Gallus <sstewartgallus00@langara.bc.ca> <sstewartgallus00@mylangara.bc.ca>
+Tim Chevalier <chevalier@alum.wellesley.edu> <catamorphism@gmail.com>
+Torsten Weber <TorstenWeber12@gmail.com> <torstenweber12@gmail.com>
+William Ting <io@williamting.com> <william.h.ting@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>
CFG_MANDIR=${CFG_MANDIR%/}
CFG_HOST="$(echo $CFG_HOST | tr ',' ' ')"
CFG_TARGET="$(echo $CFG_TARGET | tr ',' ' ')"
-CFG_SUPPORTED_TARGET="$(grep ^CC_*=* ${CFG_SRC_DIR}mk/platform.mk | sed -e 's/^CC_//' -e 's/\([^=]*\).*/\1/' | xargs)"
+CFG_SUPPORTED_TARGET="$(ls ${CFG_SRC_DIR}mk/cfg)"
# copy host-triples to target-triples so that hosts are a subset of targets
V_TEMP=""
make_dir $h/test/doc-guide-container
make_dir $h/test/doc-guide-tasks
make_dir $h/test/doc-guide-plugin
+ make_dir $h/test/doc-guide-crates
make_dir $h/test/doc-rust
done
--- /dev/null
+# arm-apple-ios configuration
+CFG_SDK_NAME_arm-apple-ios = iphoneos
+CFG_SDK_ARCHS_arm-apple-ios = armv7
+ifneq ($(findstring darwin,$(CFG_OSTYPE)),)
+CFG_IOS_SDK = $(shell xcrun --show-sdk-path -sdk iphoneos 2>/dev/null)
+CFG_IOS_FLAGS = -target armv7-apple-darwin -isysroot $(CFG_IOS_SDK) -mios-version-min=7.0
+CC_arm-apple-ios = $(shell xcrun -find -sdk iphoneos clang)
+CXX_arm-apple-ios = $(shell xcrun -find -sdk iphoneos clang++)
+CPP_arm-apple-ios = $(shell xcrun -find -sdk iphoneos clang++)
+AR_arm-apple-ios = $(shell xcrun -find -sdk iphoneos ar)
+endif
+CFG_LIB_NAME_arm-apple-ios = lib$(1).a
+CFG_LIB_GLOB_arm-apple-ios = lib$(1)-*.a
+CFG_STATIC_LIB_NAME_arm-apple-ios=lib$(1).a
+CFG_LIB_DSYM_GLOB_arm-apple-ios = lib$(1)-*.a.dSYM
+CFG_CFLAGS_arm-apple-ios := -arch armv7 -mfpu=vfp3 $(CFG_IOS_FLAGS)
+CFG_GCCISH_CFLAGS_arm-apple-ios := -Wall -Werror -g -fPIC $(CFG_IOS_FLAGS) -mfpu=vfp3 -arch armv7
+CFG_GCCISH_CXXFLAGS_arm-apple-ios := -fno-rtti $(CFG_IOS_FLAGS) -I$(CFG_IOS_SDK)/usr/include/c++/4.2.1
+CFG_GCCISH_LINK_FLAGS_arm-apple-ios := -lpthread -syslibroot $(CFG_IOS_SDK) -Wl,-no_compact_unwind
+CFG_GCCISH_DEF_FLAG_arm-apple-ios := -Wl,-exported_symbols_list,
+CFG_GCCISH_PRE_LIB_FLAGS_arm-apple-ios :=
+CFG_GCCISH_POST_LIB_FLAGS_arm-apple-ios :=
+CFG_DEF_SUFFIX_arm-apple-ios := .darwin.def
+CFG_LLC_FLAGS_arm-apple-ios := -mattr=+vfp3,+v7,+thumb2,+neon -march=arm
+CFG_INSTALL_NAME_arm-apple-ios = -Wl,-install_name,@rpath/$(1)
+CFG_EXE_SUFFIX_arm-apple-ios :=
+CFG_WINDOWSY_arm-apple-ios :=
+CFG_UNIXY_arm-apple-ios := 1
+CFG_PATH_MUNGE_arm-apple-ios := true
+CFG_LDPATH_arm-apple-ios :=
+CFG_RUN_arm-apple-ios = $(2)
+CFG_RUN_TARG_arm-apple-ios = $(call CFG_RUN_arm-apple-ios,,$(2))
+RUSTC_FLAGS_arm-apple-ios := -C relocation_model=pic
+RUSTC_CROSS_FLAGS_arm-apple-ios :=-C relocation_model=pic
--- /dev/null
+# arm-linux-androideabi configuration
+CC_arm-linux-androideabi=$(CFG_ANDROID_CROSS_PATH)/bin/arm-linux-androideabi-gcc
+CXX_arm-linux-androideabi=$(CFG_ANDROID_CROSS_PATH)/bin/arm-linux-androideabi-g++
+CPP_arm-linux-androideabi=$(CFG_ANDROID_CROSS_PATH)/bin/arm-linux-androideabi-gcc -E
+AR_arm-linux-androideabi=$(CFG_ANDROID_CROSS_PATH)/bin/arm-linux-androideabi-ar
+CFG_LIB_NAME_arm-linux-androideabi=lib$(1).so
+CFG_STATIC_LIB_NAME_arm-linux-androideabi=lib$(1).a
+CFG_LIB_GLOB_arm-linux-androideabi=lib$(1)-*.so
+CFG_LIB_DSYM_GLOB_arm-linux-androideabi=lib$(1)-*.dylib.dSYM
+CFG_CFLAGS_arm-linux-androideabi := -D__arm__ -DANDROID -D__ANDROID__ $(CFLAGS)
+CFG_GCCISH_CFLAGS_arm-linux-androideabi := -Wall -g -fPIC -D__arm__ -DANDROID -D__ANDROID__ $(CFLAGS)
+CFG_GCCISH_CXXFLAGS_arm-linux-androideabi := -fno-rtti $(CXXFLAGS)
+CFG_GCCISH_LINK_FLAGS_arm-linux-androideabi := -shared -fPIC -ldl -g -lm -lsupc++
+CFG_GCCISH_DEF_FLAG_arm-linux-androideabi := -Wl,--export-dynamic,--dynamic-list=
+CFG_GCCISH_PRE_LIB_FLAGS_arm-linux-androideabi := -Wl,-whole-archive
+CFG_GCCISH_POST_LIB_FLAGS_arm-linux-androideabi := -Wl,-no-whole-archive
+CFG_DEF_SUFFIX_arm-linux-androideabi := .android.def
+CFG_LLC_FLAGS_arm-linux-androideabi :=
+CFG_INSTALL_NAME_arm-linux-androideabi =
+CFG_EXE_SUFFIX_arm-linux-androideabi :=
+CFG_WINDOWSY_arm-linux-androideabi :=
+CFG_UNIXY_arm-linux-androideabi := 1
+CFG_PATH_MUNGE_arm-linux-androideabi := true
+CFG_LDPATH_arm-linux-androideabi :=
+CFG_RUN_arm-linux-androideabi=
+CFG_RUN_TARG_arm-linux-androideabi=
+RUSTC_FLAGS_arm-linux-androideabi :=
+RUSTC_CROSS_FLAGS_arm-linux-androideabi :=
--- /dev/null
+# arm-unknown-linux-gnueabi configuration
+CROSS_PREFIX_arm-unknown-linux-gnueabi=arm-linux-gnueabi-
+CC_arm-unknown-linux-gnueabi=gcc
+CXX_arm-unknown-linux-gnueabi=g++
+CPP_arm-unknown-linux-gnueabi=gcc -E
+AR_arm-unknown-linux-gnueabi=ar
+CFG_LIB_NAME_arm-unknown-linux-gnueabi=lib$(1).so
+CFG_STATIC_LIB_NAME_arm-unknown-linux-gnueabi=lib$(1).a
+CFG_LIB_GLOB_arm-unknown-linux-gnueabi=lib$(1)-*.so
+CFG_LIB_DSYM_GLOB_arm-unknown-linux-gnueabi=lib$(1)-*.dylib.dSYM
+CFG_CFLAGS_arm-unknown-linux-gnueabi := -D__arm__ -mfpu=vfp $(CFLAGS)
+CFG_GCCISH_CFLAGS_arm-unknown-linux-gnueabi := -Wall -g -fPIC -D__arm__ -mfpu=vfp $(CFLAGS)
+CFG_GCCISH_CXXFLAGS_arm-unknown-linux-gnueabi := -fno-rtti $(CXXFLAGS)
+CFG_GCCISH_LINK_FLAGS_arm-unknown-linux-gnueabi := -shared -fPIC -g
+CFG_GCCISH_DEF_FLAG_arm-unknown-linux-gnueabi := -Wl,--export-dynamic,--dynamic-list=
+CFG_GCCISH_PRE_LIB_FLAGS_arm-unknown-linux-gnueabi := -Wl,-whole-archive
+CFG_GCCISH_POST_LIB_FLAGS_arm-unknown-linux-gnueabi := -Wl,-no-whole-archive
+CFG_DEF_SUFFIX_arm-unknown-linux-gnueabi := .linux.def
+CFG_LLC_FLAGS_arm-unknown-linux-gnueabi :=
+CFG_INSTALL_NAME_arm-unknown-linux-gnueabi =
+CFG_EXE_SUFFIX_arm-unknown-linux-gnueabi :=
+CFG_WINDOWSY_arm-unknown-linux-gnueabi :=
+CFG_UNIXY_arm-unknown-linux-gnueabi := 1
+CFG_PATH_MUNGE_arm-unknown-linux-gnueabi := true
+CFG_LDPATH_arm-unknown-linux-gnueabi :=
+CFG_RUN_arm-unknown-linux-gnueabi=$(2)
+CFG_RUN_TARG_arm-unknown-linux-gnueabi=$(call CFG_RUN_arm-unknown-linux-gnueabi,,$(2))
+RUSTC_FLAGS_arm-unknown-linux-gnueabi :=
+RUSTC_CROSS_FLAGS_arm-unknown-linux-gnueabi :=
--- /dev/null
+# arm-unknown-linux-gnueabihf configuration
+CROSS_PREFIX_arm-unknown-linux-gnueabihf=arm-linux-gnueabihf-
+CC_arm-unknown-linux-gnueabihf=gcc
+CXX_arm-unknown-linux-gnueabihf=g++
+CPP_arm-unknown-linux-gnueabihf=gcc -E
+AR_arm-unknown-linux-gnueabihf=ar
+CFG_LIB_NAME_arm-unknown-linux-gnueabihf=lib$(1).so
+CFG_STATIC_LIB_NAME_arm-unknown-linux-gnueabihf=lib$(1).a
+CFG_LIB_GLOB_arm-unknown-linux-gnueabihf=lib$(1)-*.so
+CFG_LIB_DSYM_GLOB_arm-unknown-linux-gnueabihf=lib$(1)-*.dylib.dSYM
+CFG_CFLAGS_arm-unknown-linux-gnueabihf := -D__arm__ $(CFLAGS)
+CFG_GCCISH_CFLAGS_arm-unknown-linux-gnueabihf := -Wall -g -fPIC -D__arm__ $(CFLAGS)
+CFG_GCCISH_CXXFLAGS_arm-unknown-linux-gnueabihf := -fno-rtti $(CXXFLAGS)
+CFG_GCCISH_LINK_FLAGS_arm-unknown-linux-gnueabihf := -shared -fPIC -g
+CFG_GCCISH_DEF_FLAG_arm-unknown-linux-gnueabihf := -Wl,--export-dynamic,--dynamic-list=
+CFG_GCCISH_PRE_LIB_FLAGS_arm-unknown-linux-gnueabihf := -Wl,-whole-archive
+CFG_GCCISH_POST_LIB_FLAGS_arm-unknown-linux-gnueabihf := -Wl,-no-whole-archive
+CFG_DEF_SUFFIX_arm-unknown-linux-gnueabihf := .linux.def
+CFG_LLC_FLAGS_arm-unknown-linux-gnueabihf :=
+CFG_INSTALL_NAME_ar,-unknown-linux-gnueabihf =
+CFG_EXE_SUFFIX_arm-unknown-linux-gnueabihf :=
+CFG_WINDOWSY_arm-unknown-linux-gnueabihf :=
+CFG_UNIXY_arm-unknown-linux-gnueabihf := 1
+CFG_PATH_MUNGE_arm-unknown-linux-gnueabihf := true
+CFG_LDPATH_arm-unknown-linux-gnueabihf :=
+CFG_RUN_arm-unknown-linux-gnueabihf=$(2)
+CFG_RUN_TARG_arm-unknown-linux-gnueabihf=$(call CFG_RUN_arm-unknown-linux-gnueabihf,,$(2))
+RUSTC_FLAGS_arm-unknown-linux-gnueabihf := -C target-feature=+v6,+vfp2
+RUSTC_CROSS_FLAGS_arm-unknown-linux-gnueabihf :=
--- /dev/null
+# i386-apple-ios configuration
+CFG_SDK_NAME_i386-apple-ios = iphonesimulator
+CFG_SDK_ARCHS_i386-apple-ios = i386
+ifneq ($(findstring darwin,$(CFG_OSTYPE)),)
+CFG_IOSSIM_SDK = $(shell xcrun --show-sdk-path -sdk iphonesimulator 2>/dev/null)
+CFG_IOSSIM_FLAGS = -target i386-apple-ios -isysroot $(CFG_IOSSIM_SDK) -mios-simulator-version-min=7.0
+CC_i386-apple-ios = $(shell xcrun -find -sdk iphonesimulator clang)
+CXX_i386-apple-ios = $(shell xcrun -find -sdk iphonesimulator clang++)
+CPP_i386-apple-ios = $(shell xcrun -find -sdk iphonesimulator clang++)
+AR_i386-apple-ios = $(shell xcrun -find -sdk iphonesimulator ar)
+endif
+CFG_LIB_NAME_i386-apple-ios = lib$(1).a
+CFG_LIB_GLOB_i386-apple-ios = lib$(1)-*.dylib
+CFG_STATIC_LIB_NAME_i386-apple-ios=lib$(1).a
+CFG_LIB_DSYM_GLOB_i386-apple-ios = lib$(1)-*.dylib.dSYM
+CFG_CFLAGS_i386-apple-ios = $(CFG_IOSSIM_FLAGS)
+CFG_GCCISH_CFLAGS_i386-apple-ios = -Wall -Werror -g -fPIC -m32 $(CFG_IOSSIM_FLAGS)
+CFG_GCCISH_CXXFLAGS_i386-apple-ios = -fno-rtti $(CFG_IOSSIM_FLAGS) -I$(CFG_IOSSIM_SDK)/usr/include/c++/4.2.1
+CFG_GCCISH_LINK_FLAGS_i386-apple-ios = -lpthread -Wl,-no_compact_unwind -m32 -Wl,-syslibroot $(CFG_IOSSIM_SDK)
+CFG_GCCISH_DEF_FLAG_i386-apple-ios = -Wl,-exported_symbols_list,
+CFG_GCCISH_PRE_LIB_FLAGS_i386-apple-ios =
+CFG_GCCISH_POST_LIB_FLAGS_i386-apple-ios =
+CFG_DEF_SUFFIX_i386-apple-ios = .darwin.def
+CFG_LLC_FLAGS_i386-apple-ios =
+CFG_INSTALL_NAME_i386-apple-ios = -Wl,-install_name,@rpath/$(1)
+CFG_EXE_SUFFIX_i386-apple-ios =
+CFG_WINDOWSY_i386-apple-ios =
+CFG_UNIXY_i386-apple-ios = 1
+CFG_PATH_MUNGE_i386-apple-ios = true
+CFG_LDPATH_i386-apple-ios =
+CFG_RUN_i386-apple-ios = $(2)
+CFG_RUN_TARG_i386-apple-ios = $(call CFG_RUN_i386-apple-ios,,$(2))
+CFG_JEMALLOC_CFLAGS_i386-apple-ios = -target i386-apple-ios -Wl,-syslibroot $(CFG_IOSSIM_SDK) -Wl,-no_compact_unwind
--- /dev/null
+# i586-mingw32msvc configuration
+CC_i586-mingw32msvc=$(CFG_MINGW32_CROSS_PATH)/bin/i586-mingw32msvc-gcc
+CXX_i586-mingw32msvc=$(CFG_MINGW32_CROSS_PATH)/bin/i586-mingw32msvc-g++
+CPP_i586-mingw32msvc=$(CFG_MINGW32_CROSS_PATH)/bin/i586-mingw32msvc-cpp
+AR_i586-mingw32msvc=$(CFG_MINGW32_CROSS_PATH)/bin/i586-mingw32msvc-ar
+CFG_LIB_NAME_i586-mingw32msvc=$(1).dll
+CFG_STATIC_LIB_NAME_i586-mingw32msvc=$(1).lib
+CFG_LIB_GLOB_i586-mingw32msvc=$(1)-*.dll
+CFG_LIB_DSYM_GLOB_i586-mingw32msvc=$(1)-*.dylib.dSYM
+CFG_CFLAGS_i586-mingw32msvc := -march=i586 -m32 $(CFLAGS)
+CFG_GCCISH_CFLAGS_i586-mingw32msvc := -Wall -Werror -g -march=i586 -m32 $(CFLAGS)
+CFG_GCCISH_CXXFLAGS_i586-mingw32msvc := -fno-rtti $(CXXFLAGS)
+CFG_GCCISH_LINK_FLAGS_i586-mingw32msvc := -shared -g -m32
+CFG_GCCISH_DEF_FLAG_i586-mingw32msvc :=
+CFG_GCCISH_PRE_LIB_FLAGS_i586-mingw32msvc :=
+CFG_GCCISH_POST_LIB_FLAGS_i586-mingw32msvc :=
+CFG_DEF_SUFFIX_i586-mingw32msvc := .mingw32.def
+CFG_LLC_FLAGS_i586-mingw32msvc :=
+CFG_INSTALL_NAME_i586-mingw32msvc =
+CFG_EXE_SUFFIX_i586-mingw32msvc := .exe
+CFG_WINDOWSY_i586-mingw32msvc := 1
+CFG_UNIXY_i586-mingw32msvc :=
+CFG_PATH_MUNGE_i586-mingw32msvc := $(strip perl -i.bak -p \
+ -e 's@\\(\S)@/\1@go;' \
+ -e 's@^/([a-zA-Z])/@\1:/@o;')
+CFG_LDPATH_i586-mingw32msvc :=
+CFG_RUN_i586-mingw32msvc=
+CFG_RUN_TARG_i586-mingw32msvc=
+
--- /dev/null
+# i686-apple-darwin configuration
+CC_i686-apple-darwin=$(CC)
+CXX_i686-apple-darwin=$(CXX)
+CPP_i686-apple-darwin=$(CPP)
+AR_i686-apple-darwin=$(AR)
+CFG_LIB_NAME_i686-apple-darwin=lib$(1).dylib
+CFG_STATIC_LIB_NAME_i686-apple-darwin=lib$(1).a
+CFG_LIB_GLOB_i686-apple-darwin=lib$(1)-*.dylib
+CFG_LIB_DSYM_GLOB_i686-apple-darwin=lib$(1)-*.dylib.dSYM
+CFG_CFLAGS_i686-apple-darwin := -m32 -arch i386 $(CFLAGS)
+CFG_GCCISH_CFLAGS_i686-apple-darwin := -Wall -Werror -g -fPIC -m32 -arch i386 $(CFLAGS)
+CFG_GCCISH_CXXFLAGS_i686-apple-darwin := -fno-rtti $(CXXFLAGS)
+CFG_GCCISH_LINK_FLAGS_i686-apple-darwin := -dynamiclib -pthread -framework CoreServices -m32
+CFG_GCCISH_DEF_FLAG_i686-apple-darwin := -Wl,-exported_symbols_list,
+CFG_GCCISH_PRE_LIB_FLAGS_i686-apple-darwin :=
+CFG_GCCISH_POST_LIB_FLAGS_i686-apple-darwin :=
+CFG_DEF_SUFFIX_i686-apple-darwin := .darwin.def
+CFG_LLC_FLAGS_i686-apple-darwin :=
+CFG_INSTALL_NAME_i686-apple-darwin = -Wl,-install_name,@rpath/$(1)
+CFG_EXE_SUFFIX_i686-apple-darwin :=
+CFG_WINDOWSY_i686-apple-darwin :=
+CFG_UNIXY_i686-apple-darwin := 1
+CFG_PATH_MUNGE_i686-apple-darwin := true
+CFG_LDPATH_i686-apple-darwin :=
+CFG_RUN_i686-apple-darwin=$(2)
+CFG_RUN_TARG_i686-apple-darwin=$(call CFG_RUN_i686-apple-darwin,,$(2))
+
--- /dev/null
+# i686-unknown-linux-gnu configuration
+CC_i686-unknown-linux-gnu=$(CC)
+CXX_i686-unknown-linux-gnu=$(CXX)
+CPP_i686-unknown-linux-gnu=$(CPP)
+AR_i686-unknown-linux-gnu=$(AR)
+CFG_LIB_NAME_i686-unknown-linux-gnu=lib$(1).so
+CFG_STATIC_LIB_NAME_i686-unknown-linux-gnu=lib$(1).a
+CFG_LIB_GLOB_i686-unknown-linux-gnu=lib$(1)-*.so
+CFG_LIB_DSYM_GLOB_i686-unknown-linux-gnu=lib$(1)-*.dylib.dSYM
+CFG_CFLAGS_i686-unknown-linux-gnu := -m32 $(CFLAGS)
+CFG_GCCISH_CFLAGS_i686-unknown-linux-gnu := -Wall -Werror -g -fPIC -m32 $(CFLAGS)
+CFG_GCCISH_CXXFLAGS_i686-unknown-linux-gnu := -fno-rtti $(CXXFLAGS)
+CFG_GCCISH_LINK_FLAGS_i686-unknown-linux-gnu := -shared -fPIC -ldl -pthread -lrt -g -m32
+CFG_GCCISH_DEF_FLAG_i686-unknown-linux-gnu := -Wl,--export-dynamic,--dynamic-list=
+CFG_GCCISH_PRE_LIB_FLAGS_i686-unknown-linux-gnu := -Wl,-whole-archive
+CFG_GCCISH_POST_LIB_FLAGS_i686-unknown-linux-gnu := -Wl,-no-whole-archive
+CFG_DEF_SUFFIX_i686-unknown-linux-gnu := .linux.def
+CFG_LLC_FLAGS_i686-unknown-linux-gnu :=
+CFG_INSTALL_NAME_i686-unknown-linux-gnu =
+CFG_EXE_SUFFIX_i686-unknown-linux-gnu =
+CFG_WINDOWSY_i686-unknown-linux-gnu :=
+CFG_UNIXY_i686-unknown-linux-gnu := 1
+CFG_PATH_MUNGE_i686-unknown-linux-gnu := true
+CFG_LDPATH_i686-unknown-linux-gnu :=
+CFG_RUN_i686-unknown-linux-gnu=$(2)
+CFG_RUN_TARG_i686-unknown-linux-gnu=$(call CFG_RUN_i686-unknown-linux-gnu,,$(2))
+
--- /dev/null
+# i686-w64-mingw32 configuration
+CROSS_PREFIX_i686-w64-mingw32=i686-w64-mingw32-
+CC_i686-w64-mingw32=gcc
+CXX_i686-w64-mingw32=g++
+CPP_i686-w64-mingw32=gcc -E
+AR_i686-w64-mingw32=ar
+CFG_LIB_NAME_i686-w64-mingw32=$(1).dll
+CFG_STATIC_LIB_NAME_i686-w64-mingw32=$(1).lib
+CFG_LIB_GLOB_i686-w64-mingw32=$(1)-*.dll
+CFG_LIB_DSYM_GLOB_i686-w64-mingw32=$(1)-*.dylib.dSYM
+CFG_CFLAGS_i686-w64-mingw32 := -march=i686 -m32 -D_WIN32_WINNT=0x0600 $(CFLAGS)
+CFG_GCCISH_CFLAGS_i686-w64-mingw32 := -Wall -Werror -g -m32 -D_WIN32_WINNT=0x0600 $(CFLAGS)
+CFG_GCCISH_CXXFLAGS_i686-w64-mingw32 := -fno-rtti $(CXXFLAGS)
+CFG_GCCISH_LINK_FLAGS_i686-w64-mingw32 := -shared -g -m32
+CFG_GCCISH_DEF_FLAG_i686-w64-mingw32 :=
+CFG_GCCISH_PRE_LIB_FLAGS_i686-w64-mingw32 :=
+CFG_GCCISH_POST_LIB_FLAGS_i686-w64-mingw32 :=
+CFG_DEF_SUFFIX_i686-w64-mingw32 := .mingw32.def
+CFG_LLC_FLAGS_i686-w64-mingw32 :=
+CFG_INSTALL_NAME_i686-w64-mingw32 =
+CFG_EXE_SUFFIX_i686-w64-mingw32 := .exe
+CFG_WINDOWSY_i686-w64-mingw32 := 1
+CFG_UNIXY_i686-w64-mingw32 :=
+CFG_PATH_MUNGE_i686-w64-mingw32 :=
+CFG_LDPATH_i686-w64-mingw32 :=$(CFG_LDPATH_i686-w64-mingw32):$(PATH)
+CFG_RUN_i686-w64-mingw32=PATH="$(CFG_LDPATH_i686-w64-mingw32):$(1)" $(2)
+CFG_RUN_TARG_i686-w64-mingw32=$(call CFG_RUN_i686-w64-mingw32,$(HLIB$(1)_H_$(CFG_BUILD)),$(2))
+# Stop rustc from OOMing when building itself (I think)
+RUSTC_FLAGS_i686-w64-mingw32=-C link-args="-Wl,--large-address-aware"
+RUSTC_CROSS_FLAGS_i686-w64-mingw32 :=
+
--- /dev/null
+# mips-unknown-linux-gnu configuration
+CC_mips-unknown-linux-gnu=mips-linux-gnu-gcc
+CXX_mips-unknown-linux-gnu=mips-linux-gnu-g++
+CPP_mips-unknown-linux-gnu=mips-linux-gnu-gcc -E
+AR_mips-unknown-linux-gnu=mips-linux-gnu-ar
+CFG_LIB_NAME_mips-unknown-linux-gnu=lib$(1).so
+CFG_STATIC_LIB_NAME_mips-unknown-linux-gnu=lib$(1).a
+CFG_LIB_GLOB_mips-unknown-linux-gnu=lib$(1)-*.so
+CFG_LIB_DSYM_GLOB_mips-unknown-linux-gnu=lib$(1)-*.dylib.dSYM
+CFG_CFLAGS_mips-unknown-linux-gnu := -mips32r2 -msoft-float -mabi=32 -mno-compact-eh $(CFLAGS)
+CFG_GCCISH_CFLAGS_mips-unknown-linux-gnu := -Wall -g -fPIC -mips32r2 -msoft-float -mabi=32 -mno-compact-eh $(CFLAGS)
+CFG_GCCISH_CXXFLAGS_mips-unknown-linux-gnu := -fno-rtti $(CXXFLAGS)
+CFG_GCCISH_LINK_FLAGS_mips-unknown-linux-gnu := -shared -fPIC -g -mips32r2 -msoft-float -mabi=32
+CFG_GCCISH_DEF_FLAG_mips-unknown-linux-gnu := -Wl,--export-dynamic,--dynamic-list=
+CFG_GCCISH_PRE_LIB_FLAGS_mips-unknown-linux-gnu := -Wl,-whole-archive
+CFG_GCCISH_POST_LIB_FLAGS_mips-unknown-linux-gnu := -Wl,-no-whole-archive
+CFG_DEF_SUFFIX_mips-unknown-linux-gnu := .linux.def
+CFG_LLC_FLAGS_mips-unknown-linux-gnu :=
+CFG_INSTALL_NAME_mips-unknown-linux-gnu =
+CFG_EXE_SUFFIX_mips-unknown-linux-gnu :=
+CFG_WINDOWSY_mips-unknown-linux-gnu :=
+CFG_UNIXY_mips-unknown-linux-gnu := 1
+CFG_PATH_MUNGE_mips-unknown-linux-gnu := true
+CFG_LDPATH_mips-unknown-linux-gnu :=
+CFG_RUN_mips-unknown-linux-gnu=
+CFG_RUN_TARG_mips-unknown-linux-gnu=
+RUSTC_FLAGS_mips-unknown-linux-gnu := -C target-cpu=mips32r2 -C target-feature="+mips32r2,+o32" -C soft-float
--- /dev/null
+# mipsel-linux configuration
+CC_mipsel-linux=mipsel-linux-gcc
+CXX_mipsel-linux=mipsel-linux-g++
+CPP_mipsel-linux=mipsel-linux-gcc
+AR_mipsel-linux=mipsel-linux-ar
+CFG_LIB_NAME_mipsel-linux=lib$(1).so
+CFG_STATIC_LIB_NAME_mipsel-linux=lib$(1).a
+CFG_LIB_GLOB_mipsel-linux=lib$(1)-*.so
+CFG_LIB_DSYM_GLOB_mipsel-linux=lib$(1)-*.dylib.dSYM
+CFG_CFLAGS_mipsel-linux := -mips32 -mabi=32 $(CFLAGS)
+CFG_GCCISH_CFLAGS_mipsel-linux := -Wall -g -fPIC -mips32 -mabi=32 $(CFLAGS)
+CFG_GCCISH_CXXFLAGS_mipsel-linux := -fno-rtti $(CXXFLAGS)
+CFG_GCCISH_LINK_FLAGS_mipsel-linux := -shared -fPIC -g -mips32
+CFG_GCCISH_DEF_FLAG_mipsel-linux := -Wl,--export-dynamic,--dynamic-list=
+CFG_GCCISH_PRE_LIB_FLAGS_mipsel-linux := -Wl,-whole-archive
+CFG_GCCISH_POST_LIB_FLAGS_mipsel-linux := -Wl,-no-whole-archive
+CFG_DEF_SUFFIX_mipsel-linux := .linux.def
+CFG_LLC_FLAGS_mipsel-linux :=
+CFG_INSTALL_NAME_mipsel-linux =
+CFG_EXE_SUFFIX_mipsel-linux :=
+CFG_WINDOWSY_mipsel-linux :=
+CFG_UNIXY_mipsel-linux := 1
+CFG_PATH_MUNGE_mipsel-linux := true
+CFG_LDPATH_mipsel-linux :=
+CFG_RUN_mipsel-linux=
+CFG_RUN_TARG_mipsel-linux=
+RUSTC_FLAGS_mipsel-linux := -C target-cpu=mips32 -C target-feature="+mips32,+o32"
--- /dev/null
+# x86_64-apple-darwin configuration
+CC_x86_64-apple-darwin=$(CC)
+CXX_x86_64-apple-darwin=$(CXX)
+CPP_x86_64-apple-darwin=$(CPP)
+AR_x86_64-apple-darwin=$(AR)
+CFG_LIB_NAME_x86_64-apple-darwin=lib$(1).dylib
+CFG_STATIC_LIB_NAME_x86_64-apple-darwin=lib$(1).a
+CFG_LIB_GLOB_x86_64-apple-darwin=lib$(1)-*.dylib
+CFG_LIB_DSYM_GLOB_x86_64-apple-darwin=lib$(1)-*.dylib.dSYM
+CFG_CFLAGS_x86_64-apple-darwin := -m64 -arch x86_64 $(CFLAGS)
+CFG_GCCISH_CFLAGS_x86_64-apple-darwin := -Wall -Werror -g -fPIC -m64 -arch x86_64 $(CFLAGS)
+CFG_GCCISH_CXXFLAGS_x86_64-apple-darwin := -fno-rtti $(CXXFLAGS)
+CFG_GCCISH_LINK_FLAGS_x86_64-apple-darwin := -dynamiclib -pthread -framework CoreServices -m64
+CFG_GCCISH_DEF_FLAG_x86_64-apple-darwin := -Wl,-exported_symbols_list,
+CFG_GCCISH_PRE_LIB_FLAGS_x86_64-apple-darwin :=
+CFG_GCCISH_POST_LIB_FLAGS_x86_64-apple-darwin :=
+CFG_DEF_SUFFIX_x86_64-apple-darwin := .darwin.def
+CFG_LLC_FLAGS_x86_64-apple-darwin :=
+CFG_INSTALL_NAME_x86_64-apple-darwin = -Wl,-install_name,@rpath/$(1)
+CFG_EXE_SUFFIX_x86_64-apple-darwin :=
+CFG_WINDOWSY_x86_64-apple-darwin :=
+CFG_UNIXY_x86_64-apple-darwin := 1
+CFG_PATH_MUNGE_x86_64-apple-darwin := true
+CFG_LDPATH_x86_64-apple-darwin :=
+CFG_RUN_x86_64-apple-darwin=$(2)
+CFG_RUN_TARG_x86_64-apple-darwin=$(call CFG_RUN_x86_64-apple-darwin,,$(2))
--- /dev/null
+# x86_64-pc-dragonfly-elf configuration
+CC_x86_64-unknown-dragonfly=$(CC)
+CXX_x86_64-unknown-dragonfly=$(CXX)
+CPP_x86_64-unknown-dragonfly=$(CPP)
+AR_x86_64-unknown-dragonfly=$(AR)
+CFG_LIB_NAME_x86_64-unknown-dragonfly=lib$(1).so
+CFG_STATIC_LIB_NAME_x86_64-unknown-dragonfly=lib$(1).a
+CFG_LIB_GLOB_x86_64-unknown-dragonfly=lib$(1)-*.so
+CFG_LIB_DSYM_GLOB_x86_64-unknown-dragonfly=$(1)-*.dylib.dSYM
+CFG_CFLAGS_x86_64-unknown-dragonfly := -I/usr/include -I/usr/local/include $(CFLAGS)
+CFG_GCCISH_CFLAGS_x86_64-unknown-dragonfly := -Wall -Werror -g -fPIC -I/usr/include -I/usr/local/include $(CFLAGS)
+CFG_GCCISH_LINK_FLAGS_x86_64-unknown-dragonfly := -shared -fPIC -g -pthread -lrt
+CFG_GCCISH_DEF_FLAG_x86_64-unknown-dragonfly := -Wl,--export-dynamic,--dynamic-list=
+CFG_GCCISH_PRE_LIB_FLAGS_x86_64-unknown-dragonfly := -Wl,-whole-archive
+CFG_GCCISH_POST_LIB_FLAGS_x86_64-unknown-dragonfly := -Wl,-no-whole-archive
+CFG_DEF_SUFFIX_x86_64-unknown-dragonfly := .bsd.def
+CFG_LLC_FLAGS_x86_64-unknown-dragonfly :=
+CFG_INSTALL_NAME_x86_64-unknown-dragonfly =
+CFG_EXE_SUFFIX_x86_64-unknown-dragonfly :=
+CFG_WINDOWSY_x86_64-unknown-dragonfly :=
+CFG_UNIXY_x86_64-unknown-dragonfly := 1
+CFG_PATH_MUNGE_x86_64-unknown-dragonfly :=
+CFG_LDPATH_x86_64-unknown-dragonfly :=
+CFG_RUN_x86_64-unknown-dragonfly=$(2)
+CFG_RUN_TARG_x86_64-unknown-dragonfly=$(call CFG_RUN_x86_64-unknown-dragonfly,,$(2))
--- /dev/null
+# x86_64-unknown-freebsd configuration
+CC_x86_64-unknown-freebsd=$(CC)
+CXX_x86_64-unknown-freebsd=$(CXX)
+CPP_x86_64-unknown-freebsd=$(CPP)
+AR_x86_64-unknown-freebsd=$(AR)
+CFG_LIB_NAME_x86_64-unknown-freebsd=lib$(1).so
+CFG_STATIC_LIB_NAME_x86_64-unknown-freebsd=lib$(1).a
+CFG_LIB_GLOB_x86_64-unknown-freebsd=lib$(1)-*.so
+CFG_LIB_DSYM_GLOB_x86_64-unknown-freebsd=$(1)-*.dylib.dSYM
+CFG_CFLAGS_x86_64-unknown-freebsd := -I/usr/local/include $(CFLAGS)
+CFG_GCCISH_CFLAGS_x86_64-unknown-freebsd := -Wall -Werror -g -fPIC -I/usr/local/include $(CFLAGS)
+CFG_GCCISH_LINK_FLAGS_x86_64-unknown-freebsd := -shared -fPIC -g -pthread -lrt
+CFG_GCCISH_DEF_FLAG_x86_64-unknown-freebsd := -Wl,--export-dynamic,--dynamic-list=
+CFG_GCCISH_PRE_LIB_FLAGS_x86_64-unknown-freebsd := -Wl,-whole-archive
+CFG_GCCISH_POST_LIB_FLAGS_x86_64-unknown-freebsd := -Wl,-no-whole-archive
+CFG_DEF_SUFFIX_x86_64-unknown-freebsd := .bsd.def
+CFG_LLC_FLAGS_x86_64-unknown-freebsd :=
+CFG_INSTALL_NAME_x86_64-unknown-freebsd =
+CFG_EXE_SUFFIX_x86_64-unknown-freebsd :=
+CFG_WINDOWSY_x86_64-unknown-freebsd :=
+CFG_UNIXY_x86_64-unknown-freebsd := 1
+CFG_PATH_MUNGE_x86_64-unknown-freebsd :=
+CFG_LDPATH_x86_64-unknown-freebsd :=
+CFG_RUN_x86_64-unknown-freebsd=$(2)
+CFG_RUN_TARG_x86_64-unknown-freebsd=$(call CFG_RUN_x86_64-unknown-freebsd,,$(2))
--- /dev/null
+# x86_64-unknown-linux-gnu configuration
+CC_x86_64-unknown-linux-gnu=$(CC)
+CXX_x86_64-unknown-linux-gnu=$(CXX)
+CPP_x86_64-unknown-linux-gnu=$(CPP)
+AR_x86_64-unknown-linux-gnu=$(AR)
+CFG_LIB_NAME_x86_64-unknown-linux-gnu=lib$(1).so
+CFG_STATIC_LIB_NAME_x86_64-unknown-linux-gnu=lib$(1).a
+CFG_LIB_GLOB_x86_64-unknown-linux-gnu=lib$(1)-*.so
+CFG_LIB_DSYM_GLOB_x86_64-unknown-linux-gnu=lib$(1)-*.dylib.dSYM
+CFG_CFLAGS_x86_64-unknown-linux-gnu := -m64
+CFG_GCCISH_CFLAGS_x86_64-unknown-linux-gnu := -Wall -Werror -g -fPIC -m64
+CFG_GCCISH_CXXFLAGS_x86_64-unknown-linux-gnu := -fno-rtti
+CFG_GCCISH_LINK_FLAGS_x86_64-unknown-linux-gnu := -shared -fPIC -ldl -pthread -lrt -g -m64
+CFG_GCCISH_DEF_FLAG_x86_64-unknown-linux-gnu := -Wl,--export-dynamic,--dynamic-list=
+CFG_GCCISH_PRE_LIB_FLAGS_x86_64-unknown-linux-gnu := -Wl,-whole-archive
+CFG_GCCISH_POST_LIB_FLAGS_x86_64-unknown-linux-gnu := -Wl,-no-whole-archive
+CFG_DEF_SUFFIX_x86_64-unknown-linux-gnu := .linux.def
+CFG_LLC_FLAGS_x86_64-unknown-linux-gnu :=
+CFG_INSTALL_NAME_x86_64-unknown-linux-gnu =
+CFG_EXE_SUFFIX_x86_64-unknown-linux-gnu =
+CFG_WINDOWSY_x86_64-unknown-linux-gnu :=
+CFG_UNIXY_x86_64-unknown-linux-gnu := 1
+CFG_PATH_MUNGE_x86_64-unknown-linux-gnu := true
+CFG_LDPATH_x86_64-unknown-linux-gnu :=
+CFG_RUN_x86_64-unknown-linux-gnu=$(2)
+CFG_RUN_TARG_x86_64-unknown-linux-gnu=$(call CFG_RUN_x86_64-unknown-linux-gnu,,$(2))
--- /dev/null
+# x86_64-w64-mingw32 configuration
+CROSS_PREFIX_x86_64-w64-mingw32=x86_64-w64-mingw32-
+CC_x86_64-w64-mingw32=gcc
+CXX_x86_64-w64-mingw32=g++
+CPP_x86_64-w64-mingw32=gcc -E
+AR_x86_64-w64-mingw32=ar
+CFG_LIB_NAME_x86_64-w64-mingw32=$(1).dll
+CFG_STATIC_LIB_NAME_x86_64-w64-mingw32=$(1).lib
+CFG_LIB_GLOB_x86_64-w64-mingw32=$(1)-*.dll
+CFG_LIB_DSYM_GLOB_x86_64-w64-mingw32=$(1)-*.dylib.dSYM
+CFG_CFLAGS_x86_64-w64-mingw32 := -m64 -D_WIN32_WINNT=0x0600 $(CFLAGS)
+CFG_GCCISH_CFLAGS_x86_64-w64-mingw32 := -Wall -Werror -g -m64 -D_WIN32_WINNT=0x0600 $(CFLAGS)
+CFG_GCCISH_CXXFLAGS_x86_64-w64-mingw32 := -fno-rtti $(CXXFLAGS)
+CFG_GCCISH_LINK_FLAGS_x86_64-w64-mingw32 := -shared -g -m64
+CFG_GCCISH_DEF_FLAG_x86_64-w64-mingw32 :=
+CFG_GCCISH_PRE_LIB_FLAGS_x86_64-w64-mingw32 :=
+CFG_GCCISH_POST_LIB_FLAGS_x86_64-w64-mingw32 :=
+CFG_DEF_SUFFIX_x86_64-w64-mingw32 := .mingw32.def
+CFG_LLC_FLAGS_x86_64-w64-mingw32 :=
+CFG_INSTALL_NAME_x86_64-w64-mingw32 =
+CFG_EXE_SUFFIX_x86_64-w64-mingw32 := .exe
+CFG_WINDOWSY_x86_64-w64-mingw32 := 1
+CFG_UNIXY_x86_64-w64-mingw32 :=
+CFG_PATH_MUNGE_x86_64-w64-mingw32 :=
+CFG_LDPATH_x86_64-w64-mingw32 :=$(CFG_LDPATH_x86_64-w64-mingw32):$(PATH)
+CFG_RUN_x86_64-w64-mingw32=PATH="$(CFG_LDPATH_x86_64-w64-mingw32):$(1)" $(2)
+CFG_RUN_TARG_x86_64-w64-mingw32=$(call CFG_RUN_x86_64-w64-mingw32,$(HLIB$(1)_H_$(CFG_BUILD)),$(2))
+RUSTC_CROSS_FLAGS_x86_64-w64-mingw32 :=
######################################################################
DOCS := index intro tutorial guide guide-ffi guide-macros guide-lifetimes \
guide-tasks guide-container guide-pointers guide-testing \
- guide-plugin complement-bugreport \
+ guide-plugin guide-crates complement-bugreport \
complement-lang-faq complement-design-faq complement-project-faq rust \
rustdoc guide-unsafe guide-strings reference
# the stamp in the source dir.
$$(LLVM_STAMP_$(1)): $(S)src/rustllvm/llvm-auto-clean-trigger
@$$(call E, make: cleaning llvm)
- $(Q)$(MAKE) clean-llvm
+ $(Q)$(MAKE) clean-llvm$(1)
@$$(call E, make: done cleaning llvm)
touch $$@
# by not emitting them.
RUSTFLAGS_STAGE0 += -Z no-landing-pads
-# Go fast for stage0, and also for stage1/stage2 if optimization is off.
-RUSTFLAGS_STAGE0 += -C codegen-units=4
-ifdef CFG_DISABLE_OPTIMIZE
- RUSTFLAGS_STAGE1 += -C codegen-units=4
- RUSTFLAGS_STAGE2 += -C codegen-units=4
-endif
-
# platform-specific auto-configuration
include $(CFG_SRC_DIR)mk/platform.mk
CFG_RLIB_GLOB=lib$(1)-*.rlib
-# x86_64-unknown-linux-gnu configuration
-CC_x86_64-unknown-linux-gnu=$(CC)
-CXX_x86_64-unknown-linux-gnu=$(CXX)
-CPP_x86_64-unknown-linux-gnu=$(CPP)
-AR_x86_64-unknown-linux-gnu=$(AR)
-CFG_LIB_NAME_x86_64-unknown-linux-gnu=lib$(1).so
-CFG_STATIC_LIB_NAME_x86_64-unknown-linux-gnu=lib$(1).a
-CFG_LIB_GLOB_x86_64-unknown-linux-gnu=lib$(1)-*.so
-CFG_LIB_DSYM_GLOB_x86_64-unknown-linux-gnu=lib$(1)-*.dylib.dSYM
-CFG_CFLAGS_x86_64-unknown-linux-gnu := -m64
-CFG_GCCISH_CFLAGS_x86_64-unknown-linux-gnu := -Wall -Werror -g -fPIC -m64
-CFG_GCCISH_CXXFLAGS_x86_64-unknown-linux-gnu := -fno-rtti
-CFG_GCCISH_LINK_FLAGS_x86_64-unknown-linux-gnu := -shared -fPIC -ldl -pthread -lrt -g -m64
-CFG_GCCISH_DEF_FLAG_x86_64-unknown-linux-gnu := -Wl,--export-dynamic,--dynamic-list=
-CFG_GCCISH_PRE_LIB_FLAGS_x86_64-unknown-linux-gnu := -Wl,-whole-archive
-CFG_GCCISH_POST_LIB_FLAGS_x86_64-unknown-linux-gnu := -Wl,-no-whole-archive
-CFG_DEF_SUFFIX_x86_64-unknown-linux-gnu := .linux.def
-CFG_LLC_FLAGS_x86_64-unknown-linux-gnu :=
-CFG_INSTALL_NAME_x86_64-unknown-linux-gnu =
-CFG_EXE_SUFFIX_x86_64-unknown-linux-gnu =
-CFG_WINDOWSY_x86_64-unknown-linux-gnu :=
-CFG_UNIXY_x86_64-unknown-linux-gnu := 1
-CFG_PATH_MUNGE_x86_64-unknown-linux-gnu := true
-CFG_LDPATH_x86_64-unknown-linux-gnu :=
-CFG_RUN_x86_64-unknown-linux-gnu=$(2)
-CFG_RUN_TARG_x86_64-unknown-linux-gnu=$(call CFG_RUN_x86_64-unknown-linux-gnu,,$(2))
-
-# i686-unknown-linux-gnu configuration
-CC_i686-unknown-linux-gnu=$(CC)
-CXX_i686-unknown-linux-gnu=$(CXX)
-CPP_i686-unknown-linux-gnu=$(CPP)
-AR_i686-unknown-linux-gnu=$(AR)
-CFG_LIB_NAME_i686-unknown-linux-gnu=lib$(1).so
-CFG_STATIC_LIB_NAME_i686-unknown-linux-gnu=lib$(1).a
-CFG_LIB_GLOB_i686-unknown-linux-gnu=lib$(1)-*.so
-CFG_LIB_DSYM_GLOB_i686-unknown-linux-gnu=lib$(1)-*.dylib.dSYM
-CFG_CFLAGS_i686-unknown-linux-gnu := -m32 $(CFLAGS)
-CFG_GCCISH_CFLAGS_i686-unknown-linux-gnu := -Wall -Werror -g -fPIC -m32 $(CFLAGS)
-CFG_GCCISH_CXXFLAGS_i686-unknown-linux-gnu := -fno-rtti $(CXXFLAGS)
-CFG_GCCISH_LINK_FLAGS_i686-unknown-linux-gnu := -shared -fPIC -ldl -pthread -lrt -g -m32
-CFG_GCCISH_DEF_FLAG_i686-unknown-linux-gnu := -Wl,--export-dynamic,--dynamic-list=
-CFG_GCCISH_PRE_LIB_FLAGS_i686-unknown-linux-gnu := -Wl,-whole-archive
-CFG_GCCISH_POST_LIB_FLAGS_i686-unknown-linux-gnu := -Wl,-no-whole-archive
-CFG_DEF_SUFFIX_i686-unknown-linux-gnu := .linux.def
-CFG_LLC_FLAGS_i686-unknown-linux-gnu :=
-CFG_INSTALL_NAME_i686-unknown-linux-gnu =
-CFG_EXE_SUFFIX_i686-unknown-linux-gnu =
-CFG_WINDOWSY_i686-unknown-linux-gnu :=
-CFG_UNIXY_i686-unknown-linux-gnu := 1
-CFG_PATH_MUNGE_i686-unknown-linux-gnu := true
-CFG_LDPATH_i686-unknown-linux-gnu :=
-CFG_RUN_i686-unknown-linux-gnu=$(2)
-CFG_RUN_TARG_i686-unknown-linux-gnu=$(call CFG_RUN_i686-unknown-linux-gnu,,$(2))
-
-# arm-apple-ios configuration
-CFG_SDK_NAME_arm-apple-ios = iphoneos
-CFG_SDK_ARCHS_arm-apple-ios = armv7
-ifneq ($(findstring darwin,$(CFG_OSTYPE)),)
-CFG_IOS_SDK = $(shell xcrun --show-sdk-path -sdk iphoneos 2>/dev/null)
-CFG_IOS_FLAGS = -target armv7-apple-darwin -isysroot $(CFG_IOS_SDK) -mios-version-min=7.0
-CC_arm-apple-ios = $(shell xcrun -find -sdk iphoneos clang)
-CXX_arm-apple-ios = $(shell xcrun -find -sdk iphoneos clang++)
-CPP_arm-apple-ios = $(shell xcrun -find -sdk iphoneos clang++)
-AR_arm-apple-ios = $(shell xcrun -find -sdk iphoneos ar)
-endif
-CFG_LIB_NAME_arm-apple-ios = lib$(1).a
-CFG_LIB_GLOB_arm-apple-ios = lib$(1)-*.a
-CFG_STATIC_LIB_NAME_arm-apple-ios=lib$(1).a
-CFG_LIB_DSYM_GLOB_arm-apple-ios = lib$(1)-*.a.dSYM
-CFG_CFLAGS_arm-apple-ios := -arch armv7 -mfpu=vfp3 $(CFG_IOS_FLAGS)
-CFG_GCCISH_CFLAGS_arm-apple-ios := -Wall -Werror -g -fPIC $(CFG_IOS_FLAGS) -mfpu=vfp3 -arch armv7
-CFG_GCCISH_CXXFLAGS_arm-apple-ios := -fno-rtti $(CFG_IOS_FLAGS) -I$(CFG_IOS_SDK)/usr/include/c++/4.2.1
-CFG_GCCISH_LINK_FLAGS_arm-apple-ios := -lpthread -syslibroot $(CFG_IOS_SDK) -Wl,-no_compact_unwind
-CFG_GCCISH_DEF_FLAG_arm-apple-ios := -Wl,-exported_symbols_list,
-CFG_GCCISH_PRE_LIB_FLAGS_arm-apple-ios :=
-CFG_GCCISH_POST_LIB_FLAGS_arm-apple-ios :=
-CFG_DEF_SUFFIX_arm-apple-ios := .darwin.def
-CFG_LLC_FLAGS_arm-apple-ios := -mattr=+vfp3,+v7,+thumb2,+neon -march=arm
-CFG_INSTALL_NAME_arm-apple-ios = -Wl,-install_name,@rpath/$(1)
-CFG_EXE_SUFFIX_arm-apple-ios :=
-CFG_WINDOWSY_arm-apple-ios :=
-CFG_UNIXY_arm-apple-ios := 1
-CFG_PATH_MUNGE_arm-apple-ios := true
-CFG_LDPATH_arm-apple-ios :=
-CFG_RUN_arm-apple-ios = $(2)
-CFG_RUN_TARG_arm-apple-ios = $(call CFG_RUN_arm-apple-ios,,$(2))
-RUSTC_FLAGS_arm-apple-ios := -C relocation_model=pic
-RUSTC_CROSS_FLAGS_arm-apple-ios :=-C relocation_model=pic
-
-# i386-apple-ios configuration
-CFG_SDK_NAME_i386-apple-ios = iphonesimulator
-CFG_SDK_ARCHS_i386-apple-ios = i386
-ifneq ($(findstring darwin,$(CFG_OSTYPE)),)
-CFG_IOSSIM_SDK = $(shell xcrun --show-sdk-path -sdk iphonesimulator 2>/dev/null)
-CFG_IOSSIM_FLAGS = -target i386-apple-ios -isysroot $(CFG_IOSSIM_SDK) -mios-simulator-version-min=7.0
-CC_i386-apple-ios = $(shell xcrun -find -sdk iphonesimulator clang)
-CXX_i386-apple-ios = $(shell xcrun -find -sdk iphonesimulator clang++)
-CPP_i386-apple-ios = $(shell xcrun -find -sdk iphonesimulator clang++)
-AR_i386-apple-ios = $(shell xcrun -find -sdk iphonesimulator ar)
-endif
-CFG_LIB_NAME_i386-apple-ios = lib$(1).a
-CFG_LIB_GLOB_i386-apple-ios = lib$(1)-*.dylib
-CFG_STATIC_LIB_NAME_i386-apple-ios=lib$(1).a
-CFG_LIB_DSYM_GLOB_i386-apple-ios = lib$(1)-*.dylib.dSYM
-CFG_CFLAGS_i386-apple-ios = $(CFG_IOSSIM_FLAGS)
-CFG_GCCISH_CFLAGS_i386-apple-ios = -Wall -Werror -g -fPIC -m32 $(CFG_IOSSIM_FLAGS)
-CFG_GCCISH_CXXFLAGS_i386-apple-ios = -fno-rtti $(CFG_IOSSIM_FLAGS) -I$(CFG_IOSSIM_SDK)/usr/include/c++/4.2.1
-CFG_GCCISH_LINK_FLAGS_i386-apple-ios = -lpthread -Wl,-no_compact_unwind -m32 -Wl,-syslibroot $(CFG_IOSSIM_SDK)
-CFG_GCCISH_DEF_FLAG_i386-apple-ios = -Wl,-exported_symbols_list,
-CFG_GCCISH_PRE_LIB_FLAGS_i386-apple-ios =
-CFG_GCCISH_POST_LIB_FLAGS_i386-apple-ios =
-CFG_DEF_SUFFIX_i386-apple-ios = .darwin.def
-CFG_LLC_FLAGS_i386-apple-ios =
-CFG_INSTALL_NAME_i386-apple-ios = -Wl,-install_name,@rpath/$(1)
-CFG_EXE_SUFFIX_i386-apple-ios =
-CFG_WINDOWSY_i386-apple-ios =
-CFG_UNIXY_i386-apple-ios = 1
-CFG_PATH_MUNGE_i386-apple-ios = true
-CFG_LDPATH_i386-apple-ios =
-CFG_RUN_i386-apple-ios = $(2)
-CFG_RUN_TARG_i386-apple-ios = $(call CFG_RUN_i386-apple-ios,,$(2))
-CFG_JEMALLOC_CFLAGS_i386-apple-ios = -target i386-apple-ios -Wl,-syslibroot $(CFG_IOSSIM_SDK) -Wl,-no_compact_unwind
-
-# x86_64-apple-darwin configuration
-CC_x86_64-apple-darwin=$(CC)
-CXX_x86_64-apple-darwin=$(CXX)
-CPP_x86_64-apple-darwin=$(CPP)
-AR_x86_64-apple-darwin=$(AR)
-CFG_LIB_NAME_x86_64-apple-darwin=lib$(1).dylib
-CFG_STATIC_LIB_NAME_x86_64-apple-darwin=lib$(1).a
-CFG_LIB_GLOB_x86_64-apple-darwin=lib$(1)-*.dylib
-CFG_LIB_DSYM_GLOB_x86_64-apple-darwin=lib$(1)-*.dylib.dSYM
-CFG_CFLAGS_x86_64-apple-darwin := -m64 -arch x86_64 $(CFLAGS)
-CFG_GCCISH_CFLAGS_x86_64-apple-darwin := -Wall -Werror -g -fPIC -m64 -arch x86_64 $(CFLAGS)
-CFG_GCCISH_CXXFLAGS_x86_64-apple-darwin := -fno-rtti $(CXXFLAGS)
-CFG_GCCISH_LINK_FLAGS_x86_64-apple-darwin := -dynamiclib -pthread -framework CoreServices -m64
-CFG_GCCISH_DEF_FLAG_x86_64-apple-darwin := -Wl,-exported_symbols_list,
-CFG_GCCISH_PRE_LIB_FLAGS_x86_64-apple-darwin :=
-CFG_GCCISH_POST_LIB_FLAGS_x86_64-apple-darwin :=
-CFG_DEF_SUFFIX_x86_64-apple-darwin := .darwin.def
-CFG_LLC_FLAGS_x86_64-apple-darwin :=
-CFG_INSTALL_NAME_x86_64-apple-darwin = -Wl,-install_name,@rpath/$(1)
-CFG_EXE_SUFFIX_x86_64-apple-darwin :=
-CFG_WINDOWSY_x86_64-apple-darwin :=
-CFG_UNIXY_x86_64-apple-darwin := 1
-CFG_PATH_MUNGE_x86_64-apple-darwin := true
-CFG_LDPATH_x86_64-apple-darwin :=
-CFG_RUN_x86_64-apple-darwin=$(2)
-CFG_RUN_TARG_x86_64-apple-darwin=$(call CFG_RUN_x86_64-apple-darwin,,$(2))
-
-# i686-apple-darwin configuration
-CC_i686-apple-darwin=$(CC)
-CXX_i686-apple-darwin=$(CXX)
-CPP_i686-apple-darwin=$(CPP)
-AR_i686-apple-darwin=$(AR)
-CFG_LIB_NAME_i686-apple-darwin=lib$(1).dylib
-CFG_STATIC_LIB_NAME_i686-apple-darwin=lib$(1).a
-CFG_LIB_GLOB_i686-apple-darwin=lib$(1)-*.dylib
-CFG_LIB_DSYM_GLOB_i686-apple-darwin=lib$(1)-*.dylib.dSYM
-CFG_CFLAGS_i686-apple-darwin := -m32 -arch i386 $(CFLAGS)
-CFG_GCCISH_CFLAGS_i686-apple-darwin := -Wall -Werror -g -fPIC -m32 -arch i386 $(CFLAGS)
-CFG_GCCISH_CXXFLAGS_i686-apple-darwin := -fno-rtti $(CXXFLAGS)
-CFG_GCCISH_LINK_FLAGS_i686-apple-darwin := -dynamiclib -pthread -framework CoreServices -m32
-CFG_GCCISH_DEF_FLAG_i686-apple-darwin := -Wl,-exported_symbols_list,
-CFG_GCCISH_PRE_LIB_FLAGS_i686-apple-darwin :=
-CFG_GCCISH_POST_LIB_FLAGS_i686-apple-darwin :=
-CFG_DEF_SUFFIX_i686-apple-darwin := .darwin.def
-CFG_LLC_FLAGS_i686-apple-darwin :=
-CFG_INSTALL_NAME_i686-apple-darwin = -Wl,-install_name,@rpath/$(1)
-CFG_EXE_SUFFIX_i686-apple-darwin :=
-CFG_WINDOWSY_i686-apple-darwin :=
-CFG_UNIXY_i686-apple-darwin := 1
-CFG_PATH_MUNGE_i686-apple-darwin := true
-CFG_LDPATH_i686-apple-darwin :=
-CFG_RUN_i686-apple-darwin=$(2)
-CFG_RUN_TARG_i686-apple-darwin=$(call CFG_RUN_i686-apple-darwin,,$(2))
-
-# arm-linux-androideabi configuration
-CC_arm-linux-androideabi=$(CFG_ANDROID_CROSS_PATH)/bin/arm-linux-androideabi-gcc
-CXX_arm-linux-androideabi=$(CFG_ANDROID_CROSS_PATH)/bin/arm-linux-androideabi-g++
-CPP_arm-linux-androideabi=$(CFG_ANDROID_CROSS_PATH)/bin/arm-linux-androideabi-gcc -E
-AR_arm-linux-androideabi=$(CFG_ANDROID_CROSS_PATH)/bin/arm-linux-androideabi-ar
-CFG_LIB_NAME_arm-linux-androideabi=lib$(1).so
-CFG_STATIC_LIB_NAME_arm-linux-androideabi=lib$(1).a
-CFG_LIB_GLOB_arm-linux-androideabi=lib$(1)-*.so
-CFG_LIB_DSYM_GLOB_arm-linux-androideabi=lib$(1)-*.dylib.dSYM
-CFG_CFLAGS_arm-linux-androideabi := -D__arm__ -DANDROID -D__ANDROID__ $(CFLAGS)
-CFG_GCCISH_CFLAGS_arm-linux-androideabi := -Wall -g -fPIC -D__arm__ -DANDROID -D__ANDROID__ $(CFLAGS)
-CFG_GCCISH_CXXFLAGS_arm-linux-androideabi := -fno-rtti $(CXXFLAGS)
-CFG_GCCISH_LINK_FLAGS_arm-linux-androideabi := -shared -fPIC -ldl -g -lm -lsupc++
-CFG_GCCISH_DEF_FLAG_arm-linux-androideabi := -Wl,--export-dynamic,--dynamic-list=
-CFG_GCCISH_PRE_LIB_FLAGS_arm-linux-androideabi := -Wl,-whole-archive
-CFG_GCCISH_POST_LIB_FLAGS_arm-linux-androideabi := -Wl,-no-whole-archive
-CFG_DEF_SUFFIX_arm-linux-androideabi := .android.def
-CFG_LLC_FLAGS_arm-linux-androideabi :=
-CFG_INSTALL_NAME_arm-linux-androideabi =
-CFG_EXE_SUFFIX_arm-linux-androideabi :=
-CFG_WINDOWSY_arm-linux-androideabi :=
-CFG_UNIXY_arm-linux-androideabi := 1
-CFG_PATH_MUNGE_arm-linux-androideabi := true
-CFG_LDPATH_arm-linux-androideabi :=
-CFG_RUN_arm-linux-androideabi=
-CFG_RUN_TARG_arm-linux-androideabi=
-RUSTC_FLAGS_arm-linux-androideabi :=
-RUSTC_CROSS_FLAGS_arm-linux-androideabi :=
-
-# arm-unknown-linux-gnueabihf configuration
-CROSS_PREFIX_arm-unknown-linux-gnueabihf=arm-linux-gnueabihf-
-CC_arm-unknown-linux-gnueabihf=gcc
-CXX_arm-unknown-linux-gnueabihf=g++
-CPP_arm-unknown-linux-gnueabihf=gcc -E
-AR_arm-unknown-linux-gnueabihf=ar
-CFG_LIB_NAME_arm-unknown-linux-gnueabihf=lib$(1).so
-CFG_STATIC_LIB_NAME_arm-unknown-linux-gnueabihf=lib$(1).a
-CFG_LIB_GLOB_arm-unknown-linux-gnueabihf=lib$(1)-*.so
-CFG_LIB_DSYM_GLOB_arm-unknown-linux-gnueabihf=lib$(1)-*.dylib.dSYM
-CFG_CFLAGS_arm-unknown-linux-gnueabihf := -D__arm__ $(CFLAGS)
-CFG_GCCISH_CFLAGS_arm-unknown-linux-gnueabihf := -Wall -g -fPIC -D__arm__ $(CFLAGS)
-CFG_GCCISH_CXXFLAGS_arm-unknown-linux-gnueabihf := -fno-rtti $(CXXFLAGS)
-CFG_GCCISH_LINK_FLAGS_arm-unknown-linux-gnueabihf := -shared -fPIC -g
-CFG_GCCISH_DEF_FLAG_arm-unknown-linux-gnueabihf := -Wl,--export-dynamic,--dynamic-list=
-CFG_GCCISH_PRE_LIB_FLAGS_arm-unknown-linux-gnueabihf := -Wl,-whole-archive
-CFG_GCCISH_POST_LIB_FLAGS_arm-unknown-linux-gnueabihf := -Wl,-no-whole-archive
-CFG_DEF_SUFFIX_arm-unknown-linux-gnueabihf := .linux.def
-CFG_LLC_FLAGS_arm-unknown-linux-gnueabihf :=
-CFG_INSTALL_NAME_ar,-unknown-linux-gnueabihf =
-CFG_EXE_SUFFIX_arm-unknown-linux-gnueabihf :=
-CFG_WINDOWSY_arm-unknown-linux-gnueabihf :=
-CFG_UNIXY_arm-unknown-linux-gnueabihf := 1
-CFG_PATH_MUNGE_arm-unknown-linux-gnueabihf := true
-CFG_LDPATH_arm-unknown-linux-gnueabihf :=
-CFG_RUN_arm-unknown-linux-gnueabihf=$(2)
-CFG_RUN_TARG_arm-unknown-linux-gnueabihf=$(call CFG_RUN_arm-unknown-linux-gnueabihf,,$(2))
-RUSTC_FLAGS_arm-unknown-linux-gnueabihf := -C target-feature=+v6,+vfp2
-RUSTC_CROSS_FLAGS_arm-unknown-linux-gnueabihf :=
-
-# arm-unknown-linux-gnueabi configuration
-CROSS_PREFIX_arm-unknown-linux-gnueabi=arm-linux-gnueabi-
-CC_arm-unknown-linux-gnueabi=gcc
-CXX_arm-unknown-linux-gnueabi=g++
-CPP_arm-unknown-linux-gnueabi=gcc -E
-AR_arm-unknown-linux-gnueabi=ar
-CFG_LIB_NAME_arm-unknown-linux-gnueabi=lib$(1).so
-CFG_STATIC_LIB_NAME_arm-unknown-linux-gnueabi=lib$(1).a
-CFG_LIB_GLOB_arm-unknown-linux-gnueabi=lib$(1)-*.so
-CFG_LIB_DSYM_GLOB_arm-unknown-linux-gnueabi=lib$(1)-*.dylib.dSYM
-CFG_CFLAGS_arm-unknown-linux-gnueabi := -D__arm__ -mfpu=vfp $(CFLAGS)
-CFG_GCCISH_CFLAGS_arm-unknown-linux-gnueabi := -Wall -g -fPIC -D__arm__ -mfpu=vfp $(CFLAGS)
-CFG_GCCISH_CXXFLAGS_arm-unknown-linux-gnueabi := -fno-rtti $(CXXFLAGS)
-CFG_GCCISH_LINK_FLAGS_arm-unknown-linux-gnueabi := -shared -fPIC -g
-CFG_GCCISH_DEF_FLAG_arm-unknown-linux-gnueabi := -Wl,--export-dynamic,--dynamic-list=
-CFG_GCCISH_PRE_LIB_FLAGS_arm-unknown-linux-gnueabi := -Wl,-whole-archive
-CFG_GCCISH_POST_LIB_FLAGS_arm-unknown-linux-gnueabi := -Wl,-no-whole-archive
-CFG_DEF_SUFFIX_arm-unknown-linux-gnueabi := .linux.def
-CFG_LLC_FLAGS_arm-unknown-linux-gnueabi :=
-CFG_INSTALL_NAME_arm-unknown-linux-gnueabi =
-CFG_EXE_SUFFIX_arm-unknown-linux-gnueabi :=
-CFG_WINDOWSY_arm-unknown-linux-gnueabi :=
-CFG_UNIXY_arm-unknown-linux-gnueabi := 1
-CFG_PATH_MUNGE_arm-unknown-linux-gnueabi := true
-CFG_LDPATH_arm-unknown-linux-gnueabi :=
-CFG_RUN_arm-unknown-linux-gnueabi=$(2)
-CFG_RUN_TARG_arm-unknown-linux-gnueabi=$(call CFG_RUN_arm-unknown-linux-gnueabi,,$(2))
-RUSTC_FLAGS_arm-unknown-linux-gnueabi :=
-RUSTC_CROSS_FLAGS_arm-unknown-linux-gnueabi :=
-
-# mipsel-linux configuration
-CC_mipsel-linux=mipsel-linux-gcc
-CXX_mipsel-linux=mipsel-linux-g++
-CPP_mipsel-linux=mipsel-linux-gcc
-AR_mipsel-linux=mipsel-linux-ar
-CFG_LIB_NAME_mipsel-linux=lib$(1).so
-CFG_STATIC_LIB_NAME_mipsel-linux=lib$(1).a
-CFG_LIB_GLOB_mipsel-linux=lib$(1)-*.so
-CFG_LIB_DSYM_GLOB_mipsel-linux=lib$(1)-*.dylib.dSYM
-CFG_CFLAGS_mipsel-linux := -mips32 -mabi=32 $(CFLAGS)
-CFG_GCCISH_CFLAGS_mipsel-linux := -Wall -g -fPIC -mips32 -mabi=32 $(CFLAGS)
-CFG_GCCISH_CXXFLAGS_mipsel-linux := -fno-rtti $(CXXFLAGS)
-CFG_GCCISH_LINK_FLAGS_mipsel-linux := -shared -fPIC -g -mips32
-CFG_GCCISH_DEF_FLAG_mipsel-linux := -Wl,--export-dynamic,--dynamic-list=
-CFG_GCCISH_PRE_LIB_FLAGS_mipsel-linux := -Wl,-whole-archive
-CFG_GCCISH_POST_LIB_FLAGS_mipsel-linux := -Wl,-no-whole-archive
-CFG_DEF_SUFFIX_mipsel-linux := .linux.def
-CFG_LLC_FLAGS_mipsel-linux :=
-CFG_INSTALL_NAME_mipsel-linux =
-CFG_EXE_SUFFIX_mipsel-linux :=
-CFG_WINDOWSY_mipsel-linux :=
-CFG_UNIXY_mipsel-linux := 1
-CFG_PATH_MUNGE_mipsel-linux := true
-CFG_LDPATH_mipsel-linux :=
-CFG_RUN_mipsel-linux=
-CFG_RUN_TARG_mipsel-linux=
-RUSTC_FLAGS_mipsel-linux := -C target-cpu=mips32 -C target-feature="+mips32,+o32"
-
-
-# mips-unknown-linux-gnu configuration
-CC_mips-unknown-linux-gnu=mips-linux-gnu-gcc
-CXX_mips-unknown-linux-gnu=mips-linux-gnu-g++
-CPP_mips-unknown-linux-gnu=mips-linux-gnu-gcc -E
-AR_mips-unknown-linux-gnu=mips-linux-gnu-ar
-CFG_LIB_NAME_mips-unknown-linux-gnu=lib$(1).so
-CFG_STATIC_LIB_NAME_mips-unknown-linux-gnu=lib$(1).a
-CFG_LIB_GLOB_mips-unknown-linux-gnu=lib$(1)-*.so
-CFG_LIB_DSYM_GLOB_mips-unknown-linux-gnu=lib$(1)-*.dylib.dSYM
-CFG_CFLAGS_mips-unknown-linux-gnu := -mips32r2 -msoft-float -mabi=32 -mno-compact-eh $(CFLAGS)
-CFG_GCCISH_CFLAGS_mips-unknown-linux-gnu := -Wall -g -fPIC -mips32r2 -msoft-float -mabi=32 -mno-compact-eh $(CFLAGS)
-CFG_GCCISH_CXXFLAGS_mips-unknown-linux-gnu := -fno-rtti $(CXXFLAGS)
-CFG_GCCISH_LINK_FLAGS_mips-unknown-linux-gnu := -shared -fPIC -g -mips32r2 -msoft-float -mabi=32
-CFG_GCCISH_DEF_FLAG_mips-unknown-linux-gnu := -Wl,--export-dynamic,--dynamic-list=
-CFG_GCCISH_PRE_LIB_FLAGS_mips-unknown-linux-gnu := -Wl,-whole-archive
-CFG_GCCISH_POST_LIB_FLAGS_mips-unknown-linux-gnu := -Wl,-no-whole-archive
-CFG_DEF_SUFFIX_mips-unknown-linux-gnu := .linux.def
-CFG_LLC_FLAGS_mips-unknown-linux-gnu :=
-CFG_INSTALL_NAME_mips-unknown-linux-gnu =
-CFG_EXE_SUFFIX_mips-unknown-linux-gnu :=
-CFG_WINDOWSY_mips-unknown-linux-gnu :=
-CFG_UNIXY_mips-unknown-linux-gnu := 1
-CFG_PATH_MUNGE_mips-unknown-linux-gnu := true
-CFG_LDPATH_mips-unknown-linux-gnu :=
-CFG_RUN_mips-unknown-linux-gnu=
-CFG_RUN_TARG_mips-unknown-linux-gnu=
-RUSTC_FLAGS_mips-unknown-linux-gnu := -C target-cpu=mips32r2 -C target-feature="+mips32r2,+o32" -C soft-float
-
-# i586-mingw32msvc configuration
-CC_i586-mingw32msvc=$(CFG_MINGW32_CROSS_PATH)/bin/i586-mingw32msvc-gcc
-CXX_i586-mingw32msvc=$(CFG_MINGW32_CROSS_PATH)/bin/i586-mingw32msvc-g++
-CPP_i586-mingw32msvc=$(CFG_MINGW32_CROSS_PATH)/bin/i586-mingw32msvc-cpp
-AR_i586-mingw32msvc=$(CFG_MINGW32_CROSS_PATH)/bin/i586-mingw32msvc-ar
-CFG_LIB_NAME_i586-mingw32msvc=$(1).dll
-CFG_STATIC_LIB_NAME_i586-mingw32msvc=$(1).lib
-CFG_LIB_GLOB_i586-mingw32msvc=$(1)-*.dll
-CFG_LIB_DSYM_GLOB_i586-mingw32msvc=$(1)-*.dylib.dSYM
-CFG_CFLAGS_i586-mingw32msvc := -march=i586 -m32 $(CFLAGS)
-CFG_GCCISH_CFLAGS_i586-mingw32msvc := -Wall -Werror -g -march=i586 -m32 $(CFLAGS)
-CFG_GCCISH_CXXFLAGS_i586-mingw32msvc := -fno-rtti $(CXXFLAGS)
-CFG_GCCISH_LINK_FLAGS_i586-mingw32msvc := -shared -g -m32
-CFG_GCCISH_DEF_FLAG_i586-mingw32msvc :=
-CFG_GCCISH_PRE_LIB_FLAGS_i586-mingw32msvc :=
-CFG_GCCISH_POST_LIB_FLAGS_i586-mingw32msvc :=
-CFG_DEF_SUFFIX_i586-mingw32msvc := .mingw32.def
-CFG_LLC_FLAGS_i586-mingw32msvc :=
-CFG_INSTALL_NAME_i586-mingw32msvc =
-CFG_EXE_SUFFIX_i586-mingw32msvc := .exe
-CFG_WINDOWSY_i586-mingw32msvc := 1
-CFG_UNIXY_i586-mingw32msvc :=
-CFG_PATH_MUNGE_i586-mingw32msvc := $(strip perl -i.bak -p \
- -e 's@\\(\S)@/\1@go;' \
- -e 's@^/([a-zA-Z])/@\1:/@o;')
-CFG_LDPATH_i586-mingw32msvc :=
-CFG_RUN_i586-mingw32msvc=
-CFG_RUN_TARG_i586-mingw32msvc=
-
-# i686-w64-mingw32 configuration
-CROSS_PREFIX_i686-w64-mingw32=i686-w64-mingw32-
-CC_i686-w64-mingw32=gcc
-CXX_i686-w64-mingw32=g++
-CPP_i686-w64-mingw32=gcc -E
-AR_i686-w64-mingw32=ar
-CFG_LIB_NAME_i686-w64-mingw32=$(1).dll
-CFG_STATIC_LIB_NAME_i686-w64-mingw32=$(1).lib
-CFG_LIB_GLOB_i686-w64-mingw32=$(1)-*.dll
-CFG_LIB_DSYM_GLOB_i686-w64-mingw32=$(1)-*.dylib.dSYM
-CFG_CFLAGS_i686-w64-mingw32 := -march=i686 -m32 -D_WIN32_WINNT=0x0600 $(CFLAGS)
-CFG_GCCISH_CFLAGS_i686-w64-mingw32 := -Wall -Werror -g -m32 -D_WIN32_WINNT=0x0600 $(CFLAGS)
-CFG_GCCISH_CXXFLAGS_i686-w64-mingw32 := -fno-rtti $(CXXFLAGS)
-CFG_GCCISH_LINK_FLAGS_i686-w64-mingw32 := -shared -g -m32
-CFG_GCCISH_DEF_FLAG_i686-w64-mingw32 :=
-CFG_GCCISH_PRE_LIB_FLAGS_i686-w64-mingw32 :=
-CFG_GCCISH_POST_LIB_FLAGS_i686-w64-mingw32 :=
-CFG_DEF_SUFFIX_i686-w64-mingw32 := .mingw32.def
-CFG_LLC_FLAGS_i686-w64-mingw32 :=
-CFG_INSTALL_NAME_i686-w64-mingw32 =
-CFG_EXE_SUFFIX_i686-w64-mingw32 := .exe
-CFG_WINDOWSY_i686-w64-mingw32 := 1
-CFG_UNIXY_i686-w64-mingw32 :=
-CFG_PATH_MUNGE_i686-w64-mingw32 :=
-CFG_LDPATH_i686-w64-mingw32 :=$(CFG_LDPATH_i686-w64-mingw32):$(PATH)
-CFG_RUN_i686-w64-mingw32=PATH="$(CFG_LDPATH_i686-w64-mingw32):$(1)" $(2)
-CFG_RUN_TARG_i686-w64-mingw32=$(call CFG_RUN_i686-w64-mingw32,$(HLIB$(1)_H_$(CFG_BUILD)),$(2))
-# Stop rustc from OOMing when building itself (I think)
-RUSTC_FLAGS_i686-w64-mingw32=-C link-args="-Wl,--large-address-aware"
-RUSTC_CROSS_FLAGS_i686-w64-mingw32 :=
-
-# x86_64-w64-mingw32 configuration
-CROSS_PREFIX_x86_64-w64-mingw32=x86_64-w64-mingw32-
-CC_x86_64-w64-mingw32=gcc
-CXX_x86_64-w64-mingw32=g++
-CPP_x86_64-w64-mingw32=gcc -E
-AR_x86_64-w64-mingw32=ar
-CFG_LIB_NAME_x86_64-w64-mingw32=$(1).dll
-CFG_STATIC_LIB_NAME_x86_64-w64-mingw32=$(1).lib
-CFG_LIB_GLOB_x86_64-w64-mingw32=$(1)-*.dll
-CFG_LIB_DSYM_GLOB_x86_64-w64-mingw32=$(1)-*.dylib.dSYM
-CFG_CFLAGS_x86_64-w64-mingw32 := -m64 -D_WIN32_WINNT=0x0600 $(CFLAGS)
-CFG_GCCISH_CFLAGS_x86_64-w64-mingw32 := -Wall -Werror -g -m64 -D_WIN32_WINNT=0x0600 $(CFLAGS)
-CFG_GCCISH_CXXFLAGS_x86_64-w64-mingw32 := -fno-rtti $(CXXFLAGS)
-CFG_GCCISH_LINK_FLAGS_x86_64-w64-mingw32 := -shared -g -m64
-CFG_GCCISH_DEF_FLAG_x86_64-w64-mingw32 :=
-CFG_GCCISH_PRE_LIB_FLAGS_x86_64-w64-mingw32 :=
-CFG_GCCISH_POST_LIB_FLAGS_x86_64-w64-mingw32 :=
-CFG_DEF_SUFFIX_x86_64-w64-mingw32 := .mingw32.def
-CFG_LLC_FLAGS_x86_64-w64-mingw32 :=
-CFG_INSTALL_NAME_x86_64-w64-mingw32 =
-CFG_EXE_SUFFIX_x86_64-w64-mingw32 := .exe
-CFG_WINDOWSY_x86_64-w64-mingw32 := 1
-CFG_UNIXY_x86_64-w64-mingw32 :=
-CFG_PATH_MUNGE_x86_64-w64-mingw32 :=
-CFG_LDPATH_x86_64-w64-mingw32 :=$(CFG_LDPATH_x86_64-w64-mingw32):$(PATH)
-CFG_RUN_x86_64-w64-mingw32=PATH="$(CFG_LDPATH_x86_64-w64-mingw32):$(1)" $(2)
-CFG_RUN_TARG_x86_64-w64-mingw32=$(call CFG_RUN_x86_64-w64-mingw32,$(HLIB$(1)_H_$(CFG_BUILD)),$(2))
-RUSTC_CROSS_FLAGS_x86_64-w64-mingw32 :=
-
-# x86_64-unknown-freebsd configuration
-CC_x86_64-unknown-freebsd=$(CC)
-CXX_x86_64-unknown-freebsd=$(CXX)
-CPP_x86_64-unknown-freebsd=$(CPP)
-AR_x86_64-unknown-freebsd=$(AR)
-CFG_LIB_NAME_x86_64-unknown-freebsd=lib$(1).so
-CFG_STATIC_LIB_NAME_x86_64-unknown-freebsd=lib$(1).a
-CFG_LIB_GLOB_x86_64-unknown-freebsd=lib$(1)-*.so
-CFG_LIB_DSYM_GLOB_x86_64-unknown-freebsd=$(1)-*.dylib.dSYM
-CFG_CFLAGS_x86_64-unknown-freebsd := -I/usr/local/include $(CFLAGS)
-CFG_GCCISH_CFLAGS_x86_64-unknown-freebsd := -Wall -Werror -g -fPIC -I/usr/local/include $(CFLAGS)
-CFG_GCCISH_LINK_FLAGS_x86_64-unknown-freebsd := -shared -fPIC -g -pthread -lrt
-CFG_GCCISH_DEF_FLAG_x86_64-unknown-freebsd := -Wl,--export-dynamic,--dynamic-list=
-CFG_GCCISH_PRE_LIB_FLAGS_x86_64-unknown-freebsd := -Wl,-whole-archive
-CFG_GCCISH_POST_LIB_FLAGS_x86_64-unknown-freebsd := -Wl,-no-whole-archive
-CFG_DEF_SUFFIX_x86_64-unknown-freebsd := .bsd.def
-CFG_LLC_FLAGS_x86_64-unknown-freebsd :=
-CFG_INSTALL_NAME_x86_64-unknown-freebsd =
-CFG_EXE_SUFFIX_x86_64-unknown-freebsd :=
-CFG_WINDOWSY_x86_64-unknown-freebsd :=
-CFG_UNIXY_x86_64-unknown-freebsd := 1
-CFG_PATH_MUNGE_x86_64-unknown-freebsd :=
-CFG_LDPATH_x86_64-unknown-freebsd :=
-CFG_RUN_x86_64-unknown-freebsd=$(2)
-CFG_RUN_TARG_x86_64-unknown-freebsd=$(call CFG_RUN_x86_64-unknown-freebsd,,$(2))
-
-# x86_64-pc-dragonfly-elf configuration
-CC_x86_64-unknown-dragonfly=$(CC)
-CXX_x86_64-unknown-dragonfly=$(CXX)
-CPP_x86_64-unknown-dragonfly=$(CPP)
-AR_x86_64-unknown-dragonfly=$(AR)
-CFG_LIB_NAME_x86_64-unknown-dragonfly=lib$(1).so
-CFG_STATIC_LIB_NAME_x86_64-unknown-dragonfly=lib$(1).a
-CFG_LIB_GLOB_x86_64-unknown-dragonfly=lib$(1)-*.so
-CFG_LIB_DSYM_GLOB_x86_64-unknown-dragonfly=$(1)-*.dylib.dSYM
-CFG_CFLAGS_x86_64-unknown-dragonfly := -I/usr/include -I/usr/local/include $(CFLAGS)
-CFG_GCCISH_CFLAGS_x86_64-unknown-dragonfly := -Wall -Werror -g -fPIC -I/usr/include -I/usr/local/include $(CFLAGS)
-CFG_GCCISH_LINK_FLAGS_x86_64-unknown-dragonfly := -shared -fPIC -g -pthread -lrt
-CFG_GCCISH_DEF_FLAG_x86_64-unknown-dragonfly := -Wl,--export-dynamic,--dynamic-list=
-CFG_GCCISH_PRE_LIB_FLAGS_x86_64-unknown-dragonfly := -Wl,-whole-archive
-CFG_GCCISH_POST_LIB_FLAGS_x86_64-unknown-dragonfly := -Wl,-no-whole-archive
-CFG_DEF_SUFFIX_x86_64-unknown-dragonfly := .bsd.def
-CFG_LLC_FLAGS_x86_64-unknown-dragonfly :=
-CFG_INSTALL_NAME_x86_64-unknown-dragonfly =
-CFG_EXE_SUFFIX_x86_64-unknown-dragonfly :=
-CFG_WINDOWSY_x86_64-unknown-dragonfly :=
-CFG_UNIXY_x86_64-unknown-dragonfly := 1
-CFG_PATH_MUNGE_x86_64-unknown-dragonfly :=
-CFG_LDPATH_x86_64-unknown-dragonfly :=
-CFG_RUN_x86_64-unknown-dragonfly=$(2)
-CFG_RUN_TARG_x86_64-unknown-dragonfly=$(call CFG_RUN_x86_64-unknown-dragonfly,,$(2))
-
+include $(wildcard $(CFG_SRC_DIR)mk/cfg/*)
# The -Qunused-arguments sidesteps spurious warnings from clang
define FILTER_FLAGS
ifndef CFG_DISABLE_OPTIMIZE_TESTS
CTEST_RUSTC_FLAGS += -O
endif
-# Force codegen-units=1 for compiletest tests. compiletest does its own
-# parallelization internally, so rustc's default codegen-units=2 will actually
-# slow things down.
-CTEST_RUSTC_FLAGS += -C codegen-units=1
CTEST_COMMON_ARGS$(1)-T-$(2)-H-$(3) := \
let config = parse_config(args);
if config.valgrind_path.is_none() && config.force_valgrind {
- fail!("Can't find Valgrind to run Valgrind tests");
+ panic!("Can't find Valgrind to run Valgrind tests");
}
log_config(&config);
let message = format!("Usage: {} [OPTIONS] [TESTNAME...]", argv0);
println!("{}", getopts::usage(message.as_slice(), groups.as_slice()));
println!("");
- fail!()
+ panic!()
}
let matches =
&match getopts::getopts(args_.as_slice(), groups.as_slice()) {
Ok(m) => m,
- Err(f) => fail!("{}", f)
+ Err(f) => panic!("{}", f)
};
if matches.opt_present("h") || matches.opt_present("help") {
let message = format!("Usage: {} [OPTIONS] [TESTNAME...]", argv0);
println!("{}", getopts::usage(message.as_slice(), groups.as_slice()));
println!("");
- fail!()
+ panic!()
}
fn opt_path(m: &getopts::Matches, nm: &str) -> Path {
Ok(re) => Some(re),
Err(e) => {
println!("failed to parse filter /{}/: {}", s, e);
- fail!()
+ panic!()
}
}
} else {
let res = test::run_tests_console(&opts, tests.into_iter().collect());
match res {
Ok(true) => {}
- Ok(false) => fail!("Some tests failed"),
+ Ok(false) => panic!("Some tests failed"),
Err(e) => {
println!("I/O failure during tests: {}", e);
}
let end = strs.pop().unwrap();
(strs.pop().unwrap(), end)
}
- n => fail!("Expected 1 or 2 strings, not {}", n)
+ n => panic!("Expected 1 or 2 strings, not {}", n)
}
})
}
let components: Vec<&str> = version_string.trim().split('.').collect();
if components.len() != 2 {
- fail!("{}", error_string);
+ panic!("{}", error_string);
}
let major: int = FromStr::from_str(components[0]).expect(error_string);
"arm-linux-androideabi" => {
if !config.adb_device_status {
- fail!("android device not available");
+ panic!("android device not available");
}
}
------------------------------------------\n\
\n",
expected, actual);
- fail!();
+ panic!();
}
}
fn error(err: &str) { println!("\nerror: {}", err); }
-fn fatal(err: &str) -> ! { error(err); fail!(); }
+fn fatal(err: &str) -> ! { error(err); panic!(); }
fn fatal_proc_rec(err: &str, proc_res: &ProcRes) -> ! {
print!("\n\
\n",
err, proc_res.status, proc_res.cmdline, proc_res.stdout,
proc_res.stderr);
- fail!();
+ panic!();
}
fn _arm_exec_compiled_test(config: &Config,
return os
}
}
- fail!("Cannot determine OS from triple");
+ panic!("Cannot determine OS from triple");
}
#[cfg(target_os = "windows")]
`match` being exhaustive has some useful properties. First, if every
possibility is covered by the `match`, adding further variants to the `enum`
-in the future will prompt a compilation failure, rather than runtime failure.
+in the future will prompt a compilation failure, rather than runtime panic.
Second, it makes cost explicit. In general, only safe way to have a
-non-exhaustive match would be to fail the task if nothing is matched, though
+non-exhaustive match would be to panic the task 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:
* There is no global inter-crate namespace; all name management occurs within a crate.
* Using another crate binds the root of _its_ namespace into the user's namespace.
-## Why is failure unwinding non-recoverable within a task? Why not try to "catch exceptions"?
+## Why is panic unwinding non-recoverable within a task? Why not try to "catch exceptions"?
In short, because too few guarantees could be made about the dynamic environment of the catch block, as well as invariants holding in the unwound heap, to be able to safely resume; we believe that other methods of signalling and logging errors are more appropriate, with tasks playing the role of a "hard" isolation boundary between separate heaps.
Rust provides, instead, three predictable and well-defined options for handling any combination of the three main categories of "catch" logic:
* Failure _logging_ is done by the integrated logging subsystem.
-* _Recovery_ after a failure is done by trapping a task failure from _outside_ the task, where other tasks are known to be unaffected.
+* _Recovery_ after a panic is done by trapping a task panic from _outside_
+ the task, where other tasks are known to be unaffected.
* _Cleanup_ of resources is done by RAII-style objects with destructors.
Cleanup through RAII-style destructors is more likely to work than in catch blocks anyways, since it will be better tested (part of the non-error control paths, so executed all the time).
Rust will give us a compile-time error:
-```{rust,ignore}
+```{notrust,ignore}
Compiling phrases v0.0.1 (file:///home/you/projects/phrases)
/home/you/projects/phrases/src/main.rs:4:5: 4:40 error: a value named `hello` has already been imported in this module
/home/you/projects/phrases/src/main.rs:4 use phrases::japanese::greetings::hello;
Foreign libraries often hand off ownership of resources to the calling code.
When this occurs, we must use Rust's destructors to provide safety and guarantee
-the release of these resources (especially in the case of failure).
+the release of these resources (especially in the case of panic).
# Callbacks from C code to Rust functions
fn compute_distance(p1: &Point, p2: &Point) -> f64 {
let x_d = p1.x - p2.x;
let y_d = p1.y - p2.y;
- sqrt(x_d * x_d + y_d * y_d)
+ (x_d * x_d + y_d * y_d).sqrt()
}
~~~
// complicated stuff goes here
return result + val;
},
- _ => fail!("Didn't get good_2")
+ _ => panic!("Didn't get good_2")
}
}
_ => return 0 // default value
biased_match!((x) ~ (Good1(g1, val)) else { return 0 };
binds g1, val )
biased_match!((g1.body) ~ (Good2(result) )
- else { fail!("Didn't get good_2") };
+ else { panic!("Didn't get good_2") };
binds result )
// complicated stuff goes here
return result + val;
# fn f(x: T1) -> uint {
biased_match!(
(x) ~ (Good1(g1, val)) else { return 0 };
- (g1.body) ~ (Good2(result) ) else { fail!("Didn't get Good2") };
+ (g1.body) ~ (Good2(result) ) else { panic!("Didn't get Good2") };
binds val, result )
// complicated stuff goes here
return result + val;
extern crate rustc;
use syntax::codemap::Span;
-use syntax::parse::token::{IDENT, get_ident};
-use syntax::ast::{TokenTree, TTTok};
+use syntax::parse::token;
+use syntax::ast::{TokenTree, TtToken};
use syntax::ext::base::{ExtCtxt, MacResult, DummyResult, MacExpr};
use syntax::ext::build::AstBuilder; // trait for expr_uint
use rustc::plugin::Registry;
("I", 1)];
let text = match args {
- [TTTok(_, IDENT(s, _))] => get_ident(s).to_string(),
+ [TtToken(_, token::Ident(s, _))] => token::get_ident(s).to_string(),
_ => {
cx.span_err(sp, "argument should be a single identifier");
return DummyResult::any(sp);
fn expand_foo(cx: &mut ExtCtxt, sp: Span, args: &[TokenTree])
-> Box<MacResult+'static> {
- let mut parser =
- parse::new_parser_from_tts(cx.parse_sess(), cx.cfg(), args.to_slice())
+ let mut parser = cx.new_parser_from_tts(args);
let expr: P<Expr> = parser.parse_expr();
```
In general, prefer stack allocation over heap allocation. Using references to
stack allocated information is preferred whenever possible. Therefore,
-references are the default pointer type you should use, unless you have
+references are the default pointer type you should use, unless you have a
specific reason to use a different type. The other types of pointers cover when
they're appropriate to use in their own best practices sections.
# &str
-The first kind is a `&str`. This is pronounced a 'string slice.' String literals
-are of the type `&str`:
+The first kind is a `&str`. This is pronounced a 'string slice'.
+String literals are of the type `&str`:
```{rust}
let string = "Hello there.";
To compare a String to a constant string, prefer `as_slice()`...
```{rust}
-fn compare(string: String) {
- if string.as_slice() == "Hello" {
+fn compare(x: String) {
+ if x.as_slice() == "Hello" {
println!("yes");
}
}
... over `to_string()`:
```{rust}
-fn compare(string: String) {
- if string == "Hello".to_string() {
+fn compare(x: String) {
+ if x == "Hello".to_string() {
println!("yes");
}
}
abstractions for constructing concurrent programs.
Tasks provide failure isolation and recovery. When a fatal error occurs in Rust
-code as a result of an explicit call to `fail!()`, an assertion failure, or
+code as a result of an explicit call to `panic!()`, an assertion failure, or
another invalid operation, the runtime system destroys the entire task. Unlike
in languages such as Java and C++, there is no way to `catch` an exception.
-Instead, tasks may monitor each other for failure.
+Instead, tasks may monitor each other to see if they panic.
Tasks use Rust's type system to provide strong memory safety guarantees. In
particular, the type system guarantees that tasks cannot induce a data race
# }
```
-# Handling task failure
+# Handling task panics
-Rust has a built-in mechanism for raising exceptions. The `fail!()` macro
-(which can also be written with an error string as an argument: `fail!(
-~reason)`) and the `assert!` construct (which effectively calls `fail!()` if a
+Rust has a built-in mechanism for raising exceptions. The `panic!()` macro
+(which can also be written with an error string as an argument: `panic!(
+~reason)`) and the `assert!` construct (which effectively calls `panic!()` if a
boolean expression is false) are both ways to raise exceptions. When a task
raises an exception, the task unwinds its stack—running destructors and
freeing memory along the way—and then exits. Unlike exceptions in C++,
-exceptions in Rust are unrecoverable within a single task: once a task fails,
+exceptions in Rust are unrecoverable within a single task: once a task panics,
there is no way to "catch" the exception.
-While it isn't possible for a task to recover from failure, tasks may notify
-each other of failure. The simplest way of handling task failure is with the
+While it isn't possible for a task to recover from panicking, tasks may notify
+each other if they panic. The simplest way of handling a panic is with the
`try` function, which is similar to `spawn`, but immediately blocks and waits
for the child task to finish. `try` returns a value of type
`Result<T, Box<Any + Send>>`. `Result` is an `enum` type with two variants:
if some_condition() {
calculate_result()
} else {
- fail!("oops!");
+ panic!("oops!");
}
});
assert!(result.is_err());
Unlike `spawn`, the function spawned using `try` may return a value, which
`try` will dutifully propagate back to the caller in a [`Result`] enum. If the
child task terminates successfully, `try` will return an `Ok` result; if the
-child task fails, `try` will return an `Error` result.
+child task panics, `try` will return an `Error` result.
[`Result`]: std/result/index.html
-> *Note:* A failed task does not currently produce a useful error
+> *Note:* A panicked task does not currently produce a useful error
> value (`try` always returns `Err(())`). In the
> future, it may be possible for tasks to intercept the value passed to
-> `fail!()`.
+> `panic!()`.
-But not all failures are created equal. In some cases you might need to abort
+But not all panics are created equal. In some cases you might need to abort
the entire program (perhaps you're writing an assert which, if it trips,
indicates an unrecoverable logic error); in other cases you might want to
-contain the failure at a certain boundary (perhaps a small piece of input from
+contain the panic at a certain boundary (perhaps a small piece of input from
the outside world, which you happen to be processing in parallel, is malformed
such that the processing task cannot proceed).
`--test` flag: `rustc myprogram.rs --test -o myprogram-tests`. Running
the resulting executable will run all the tests in the crate. A test
is considered successful if its function returns; if the task running
-the test fails, through a call to `fail!`, a failed `assert`, or some
+the test fails, through a call to `panic!`, a failed `assert`, or some
other (`assert_eq`, ...) means, then the test fails.
When compiling a crate with the `--test` flag `--cfg test` is also
Tests that are intended to fail can be annotated with the
`should_fail` attribute. The test will be run, and if it causes its
-task to fail then the test will be counted as successful; otherwise it
+task to panic then the test will be counted as successful; otherwise it
will be counted as a failure. For example:
~~~test_harness
- implement the `Drop` for resource clean-up via a destructor, and use
RAII (Resource Acquisition Is Initialization). This reduces the need
for any manual memory management by users, and automatically ensures
- that clean-up is always run, even when the task fails.
+ that clean-up is always run, even when the task panics.
- ensure that any data stored behind a raw pointer is destroyed at the
appropriate time.
// provided by libstd.
#[lang = "stack_exhausted"] extern fn stack_exhausted() {}
#[lang = "eh_personality"] extern fn eh_personality() {}
-#[lang = "fail_fmt"] fn fail_fmt() -> ! { loop {} }
+#[lang = "panic_fmt"] fn panic_fmt() -> ! { loop {} }
# // fn main() {} tricked you, rustdoc!
```
#[lang = "stack_exhausted"] extern fn stack_exhausted() {}
#[lang = "eh_personality"] extern fn eh_personality() {}
-#[lang = "fail_fmt"] fn fail_fmt() -> ! { loop {} }
+#[lang = "panic_fmt"] fn panic_fmt() -> ! { loop {} }
# // fn main() {} tricked you, rustdoc!
```
failure mechanisms of the compiler. This is often mapped to GCC's
personality function (see the
[libstd implementation](std/rt/unwind/index.html) for more
-information), but crates which do not trigger failure can be assured
-that this function is never called. The final function, `fail_fmt`, is
+information), but crates which do not trigger a panic can be assured
+that this function is never called. The final function, `panic_fmt`, is
also used by the failure mechanisms of the compiler.
## Using libcore
return ret;
}
-#[lang = "fail_fmt"]
-extern fn fail_fmt(args: &core::fmt::Arguments,
+#[lang = "panic_fmt"]
+extern fn panic_fmt(args: &core::fmt::Arguments,
file: &str,
line: uint) -> ! {
loop {}
```
Note that there is one extra lang item here which differs from the examples
-above, `fail_fmt`. This must be defined by consumers of libcore because the
-core library declares failure, but it does not define it. The `fail_fmt`
-lang item is this crate's definition of failure, and it must be guaranteed to
+above, `panic_fmt`. This must be defined by consumers of libcore because the
+core library declares panics, but it does not define it. The `panic_fmt`
+lang item is this crate's definition of panic, and it must be guaranteed to
never return.
As can be seen in this example, the core library is intended to provide the
#[lang = "stack_exhausted"] extern fn stack_exhausted() {}
#[lang = "eh_personality"] extern fn eh_personality() {}
-#[lang = "fail_fmt"] fn fail_fmt() -> ! { loop {} }
+#[lang = "panic_fmt"] fn panic_fmt() -> ! { loop {} }
```
Note the use of `abort`: the `exchange_malloc` lang item is assumed to
let y = Missing;
match x {
- Value(n) => println!("x is {:d}", n),
+ Value(n) => println!("x is {}", n),
Missing => println!("x is missing!"),
}
match y {
- Value(n) => println!("y is {:d}", n),
+ Value(n) => println!("y is {}", n),
Missing => println!("y is missing!"),
}
}
```{rust}
for x in range(0i, 10i) {
- println!("{:d}", x);
+ println!("{}", x);
}
```
for x in range(0i, 10i) {
if x % 2 == 0 { continue; }
- println!("{:d}", x);
+ println!("{}", x);
}
```
let y = Missing;
match x {
- Value(n) => println!("x is {:d}", n),
+ Value(n) => println!("x is {}", n),
Missing => println!("x is missing!"),
}
match y {
- Value(n) => println!("y is {:d}", n),
+ Value(n) => println!("y is {}", n),
Missing => println!("y is missing!"),
}
}
```{rust}
fn main() {
- println!("Hello, world!");
+ println!("Hello, world!")
}
```
```
fn main() {
- println!("Hello, world!");
+ println!("Hello, world!")
}
mod hello {
fn print_hello() {
- println!("Hello, world!");
+ println!("Hello, world!")
}
}
```
mod hello {
fn print_hello() {
- println!("Hello, world!");
+ println!("Hello, world!")
}
}
```
mod hello {
pub fn print_hello() {
- println!("Hello, world!");
+ println!("Hello, world!")
}
}
```
```{notrust,ignore}
$ cargo test
Compiling testing v0.0.1 (file:///home/you/projects/testing)
-/home/you/projects/testing/src/main.rs:1:1: 3:2 warning: code is never used: `main`, #[warn(dead_code)] on by default
+/home/you/projects/testing/src/main.rs:1:1: 3:2 warning: function is never used: `main`, #[warn(dead_code)] on by default
/home/you/projects/testing/src/main.rs:1 fn main() {
-/home/you/projects/testing/src/main.rs:2 println!("Hello, world");
+/home/you/projects/testing/src/main.rs:2 println!("Hello, world!")
/home/you/projects/testing/src/main.rs:3 }
-
-running 0 tests
-
-test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured
-
+ Running target/lib-654ce120f310a3a5
running 1 test
test foo ... FAILED
test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured
-task '<main>' failed at 'Some tests failed', /home/you/src/rust/src/libtest/lib.rs:242
+task '<main>' failed at 'Some tests failed', /home/you/src/rust/src/libtest/lib.rs:243
```
Lots of output! Let's break this down:
`tests`, as well as the tests you put inside of your crate.
```{notrust,ignore}
-/home/you/projects/testing/src/main.rs:1:1: 3:2 warning: code is never used: `main`, #[warn(dead_code)] on by default
+/home/you/projects/testing/src/main.rs:1:1: 3:2 warning: function is never used: `main`, #[warn(dead_code)] on by default
/home/you/projects/testing/src/main.rs:1 fn main() {
-/home/you/projects/testing/src/main.rs:2 println!("Hello, world");
+/home/you/projects/testing/src/main.rs:2 println!("Hello, world!")
/home/you/projects/testing/src/main.rs:3 }
```
output.
```{notrust,ignore}
-running 0 tests
-
-test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured
-```
+ Running target/lib-654ce120f310a3a5
-Wait a minute, zero tests? Didn't we define one? Yup. This output is from
-attempting to run the tests in our crate, of which we don't have any.
-You'll note that Rust reports on several kinds of tests: passed, failed,
-ignored, and measured. The 'measured' tests refer to benchmark tests, which
-we'll cover soon enough!
-
-```{notrust,ignore}
running 1 test
test foo ... FAILED
```
test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured
-task '<main>' failed at 'Some tests failed', /home/you/src/rust/src/libtest/lib.rs:242
+task '<main>' failed at 'Some tests failed', /home/you/src/rust/src/libtest/lib.rs:243
```
After all the tests run, Rust will show us any output from our failed tests.
```{notrust,ignore}
$ cargo test
Compiling testing v0.0.1 (file:///home/you/projects/testing)
-/home/you/projects/testing/src/main.rs:1:1: 3:2 warning: code is never used: `main`, #[warn(dead_code)] on by default
-/home/you/projects/testing/src/main.rs:1 fn main() {
-/home/you/projects/testing/src/main.rs:2 println!("Hello, world");
-/home/you/projects/testing/src/main.rs:3 }
-
-running 0 tests
-
-test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured
-
+ Running target/lib-654ce120f310a3a5
running 1 test
test foo ... ok
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured
+
+ Running target/testing-6d7518593c7c3ee5
+
+running 0 tests
+
+test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured
```
-Nice! Our test passes, as we expected. Let's get rid of that warning for our `main`
-function. Change your `src/main.rs` to look like this:
+Nice! Our test passes, as we expected. Note how we didn't get the
+`main` warning this time? This is because `src/main.rs` didn't
+need recompiling, but we'll get that warning again if we
+change (and recompile) that file. Let's get rid of that
+warning; change your `src/main.rs` to look like this:
```{rust}
#[cfg(not(test))]
fn main() {
- println!("Hello, world");
+ println!("Hello, world!")
}
```
include `main` when it's _not_ true. So we use `not` to negate things:
`cfg(not(test))` will only compile our code when the `cfg(test)` is false.
-With this attribute, we won't get the warning:
+With this attribute we won't get the warning (even
+though `src/main.rs` gets recompiled this time):
```{notrust,ignore}
$ cargo test
Compiling testing v0.0.1 (file:///home/you/projects/testing)
-
-running 0 tests
-
-test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured
-
+ Running target/lib-654ce120f310a3a5
running 1 test
test foo ... ok
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured
+
+ Running target/testing-6d7518593c7c3ee5
+
+running 0 tests
+
+test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured
```
Nice. Okay, let's write a real test now. Change your `tests/lib.rs`
#[cfg(not(test))]
fn main() {
- println!("Hello, world");
+ println!("Hello, world!")
}
```
```{ignore,notrust}
$ cargo test
Compiling testing v0.0.1 (file:///home/you/projects/testing)
+ Running target/lib-654ce120f310a3a5
+
+running 1 test
+test math_checks_out ... ok
+
+test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured
+
+ Running target/testing-6d7518593c7c3ee5
running 0 tests
test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured
+ Running target/testing-8a94b31f7fd2e8fe
running 0 tests
test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured
+ Doc-tests testing
-running 1 test
-test math_checks_out ... ok
+running 0 tests
-test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured
+test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured
```
Great! One test passed. We've got an integration test showing that our public
```{ignore,notrust}
$ cargo test
Compiling testing v0.0.1 (file:///home/you/projects/testing)
+ Running target/lib-654ce120f310a3a5
+
+running 1 test
+test math_checks_out ... ok
+
+test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured
+
+ Running target/testing-6d7518593c7c3ee5
running 0 tests
test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured
+ Running target/testing-8a94b31f7fd2e8fe
running 0 tests
test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured
+ Doc-tests testing
-running 1 test
-test math_checks_out ... ok
+running 0 tests
-test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured
+test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured
```
If we tried to write a test for these two new functions, it wouldn't
```{ignore,notrust}
$ cargo test
Compiling testing v0.0.1 (file:///home/you/projects/testing)
+ Running target/lib-654ce120f310a3a5
+
+running 1 test
+test math_checks_out ... ok
+
+test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured
+
+ Running target/testing-6d7518593c7c3ee5
+
+running 0 tests
+
+test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured
+
+ Running target/testing-8a94b31f7fd2e8fe
running 2 tests
test test::test_times_four ... ok
test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured
+ Doc-tests testing
running 0 tests
test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured
-
-
-running 1 test
-test math_checks_out ... ok
-
-test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured
```
Cool! We now have two tests of our internal functions. You'll note that there
## Boxes
-All of our references so far have been to variables we've created on the stack.
-In Rust, the simplest way to allocate heap variables is using a *box*. To
-create a box, use the `box` keyword:
+Most of the types we've seen so far have a fixed size or number of components.
+The compiler needs this fact to lay out values in memory. However, some data
+structures, such as a linked list, do not have a fixed size. You might think to
+implement a linked list with an enum that's either a `Node` or the end of the
+list (`Nil`), like this:
+
+```{rust,ignore}
+enum List { // error: illegal recursive enum type
+ Node(u32, List),
+ Nil
+}
+```
+
+But the compiler complains that the type is recursive, that is, it could be
+arbitrarily large. To remedy this, Rust provides a fixed-size container called
+a **box** that can hold any type. You can box up any value with the `box`
+keyword. Our boxed List gets the type `Box<List>` (more on the notation when we
+get to generics):
```{rust}
-let x = box 5i;
+enum List {
+ Node(u32, Box<List>),
+ Nil
+}
+
+fn main() {
+ let list = Node(0, box Node(1, box Nil));
+}
```
-This allocates an integer `5` on the heap, and creates a binding `x` that
-refers to it. The great thing about boxed pointers is that we don't have to
-manually free this allocation! If we write
+A box dynamically allocates memory to hold its contents. The great thing about
+Rust is that that memory is *automatically*, *efficiently*, and *predictably*
+deallocated when you're done with the box.
+
+A box is a pointer type, and you access what's inside using the `*` operator,
+just like regular references. This (rather silly) example dynamically allocates
+an integer `5` and makes `x` a pointer to it:
```{rust}
{
let x = box 5i;
- // do stuff
+ println!("{}", *x); // Prints 5
}
```
-then Rust will automatically free `x` at the end of the block. This isn't
-because Rust has a garbage collector -- it doesn't. Instead, when `x` goes out
-of scope, Rust `free`s `x`. This Rust code will do the same thing as the
-following C code:
+The great thing about boxes is that we don't have to manually free this
+allocation! Instead, when `x` reaches the end of its lifetime -- in this case,
+when it goes out of scope at the end of the block -- Rust `free`s `x`. This
+isn't because Rust has a garbage collector (it doesn't). Instead, by tracking
+the ownership and lifetime of a variable (with a little help from you, the
+programmer), the compiler knows precisely when it is no longer used.
+
+The Rust code above will do the same thing as the following C code:
```{c,ignore}
{
int *x = (int *)malloc(sizeof(int));
- // do stuff
+ if (!x) abort();
+ *x = 5;
+ printf("%d\n", *x);
free(x);
}
```
-This means we get the benefits of manual memory management, but the compiler
-ensures that we don't do something wrong. We can't forget to `free` our memory.
+We get the benefits of manual memory management, while ensuring we don't
+introduce any bugs. We can't forget to `free` our memory.
Boxes are the sole owner of their contents, so you cannot take a mutable
reference to them and then use the original box:
*x;
```
-## Rc and Arc
-
-Sometimes, you need to allocate something on the heap, but give out multiple
-references to the memory. Rust's `Rc<T>` (pronounced 'arr cee tee') and
-`Arc<T>` types (again, the `T` is for generics, we'll learn more later) provide
-you with this ability. **Rc** stands for 'reference counted,' and **Arc** for
-'atomically reference counted.' This is how Rust keeps track of the multiple
-owners: every time we make a new reference to the `Rc<T>`, we add one to its
-internal 'reference count.' Every time a reference goes out of scope, we
-subtract one from the count. When the count is zero, the `Rc<T>` can be safely
-deallocated. `Arc<T>` is almost identical to `Rc<T>`, except for one thing: The
-'atomically' in 'Arc' means that increasing and decreasing the count uses a
-thread-safe mechanism to do so. Why two types? `Rc<T>` is faster, so if you're
-not in a multi-threaded scenario, you can have that advantage. Since we haven't
-talked about threading yet in Rust, we'll show you `Rc<T>` for the rest of this
-section.
+Boxes are simple and efficient pointers to dynamically allocated values with a
+single owner. They are useful for tree-like structures where the lifetime of a
+child depends solely on the lifetime of its (single) parent. If you need a
+value that must persist as long as any of several referrers, read on.
-To create an `Rc<T>`, use `Rc::new()`:
+## Rc and Arc
-```{rust}
-use std::rc::Rc;
+Sometimes, you need a variable that is referenced from multiple places
+(immutably!), lasting as long as any of those places, and disappearing when it
+is no longer referenced. For instance, in a graph-like data structure, a node
+might be referenced from all of its neighbors. In this case, it is not possible
+for the compiler to determine ahead of time when the value can be freed -- it
+needs a little run-time support.
-let x = Rc::new(5i);
-```
+Rust's **Rc** type provides shared ownership of a dynamically allocated value
+that is automatically freed at the end of its last owner's lifetime. (`Rc`
+stands for 'reference counted,' referring to the way these library types are
+implemented.) This provides more flexibility than single-owner boxes, but has
+some runtime overhead.
-To create a second reference, use the `.clone()` method:
+To create an `Rc` value, use `Rc::new()`. To create a second owner, use the
+`.clone()` method:
```{rust}
use std::rc::Rc;
let x = Rc::new(5i);
let y = x.clone();
+
+println!("{} {}", *x, *y); // Prints 5 5
```
-The `Rc<T>` will live as long as any of its references are alive. After they
-all go out of scope, the memory will be `free`d.
+The `Rc` will live as long as any of its owners are alive. After that, the
+memory will be `free`d.
+
+**Arc** is an 'atomically reference counted' value, identical to `Rc` except
+that ownership can be safely shared among multiple threads. Why two types?
+`Arc` has more overhead, so if you're not in a multi-threaded scenario, you
+don't have to pay the price.
-If you use `Rc<T>` or `Arc<T>`, you have to be careful about introducing
-cycles. If you have two `Rc<T>`s that point to each other, the reference counts
-will never drop to zero, and you'll have a memory leak. To learn more, check
-out [the section on `Rc<T>` and `Arc<T>` in the pointers
-guide](guide-pointers.html#rc-and-arc).
+If you use `Rc` or `Arc`, you have to be careful about introducing cycles. If
+you have two `Rc`s that point to each other, they will happily keep each other
+alive forever, creating a memory leak. To learn more, check out [the section on
+`Rc` and `Arc` in the pointers guide](guide-pointers.html#rc-and-arc).
# Patterns
# Closures
-So far, we've made lots of functions in Rust. But we've given them all names.
-Rust also allows us to create anonymous functions too. Rust's anonymous
+So far, we've made lots of functions in Rust, but we've given them all names.
+Rust also allows us to create anonymous functions. Rust's anonymous
functions are called **closure**s. By themselves, closures aren't all that
interesting, but when you combine them with functions that take closures as
arguments, really powerful things are possible.
default to returning unit (`()`).
There's one big difference between a closure and named functions, and it's in
-the name: a closure "closes over its environment." What's that mean? It means
+the name: a closure "closes over its environment." What does that mean? It means
this:
```{rust}
The `||` syntax means this is an anonymous closure that takes no arguments.
Without it, we'd just have a block of code in `{}`s.
-In other words, a closure has access to variables in the scope that it's
-defined. The closure borrows any variables that it uses. This will error:
+In other words, a closure has access to variables in the scope where it's
+defined. The closure borrows any variables it uses, so this will error:
```{rust,ignore}
fn main() {
println!("{}", p()); // prints 25
```
-Procs have a big difference from closures: they may only be called once. This
+There is a big difference between procs and closures: procs may only be called once. This
will error when we try to compile:
```{rust,ignore}
If you do the math, `(5 * 5) + (5 * 5) == 50`, so that's the output we get.
Play around with this concept until you're comfortable with it. Rust's standard
-library uses lots of closures, where appropriate, so you'll be using
+library uses lots of closures where appropriate, so you'll be using
this technique a lot.
-If we didn't want to give `square` a name, we could also just define it inline.
+If we didn't want to give `square` a name, we could just define it inline.
This example is the same as the previous one:
```{rust}
}
```
-Doing this is not particularly common, but every once in a while, it's useful.
+Doing this is not particularly common, but it's useful every once in a while.
That's all you need to get the hang of closures! Closures are a little bit
-strange at first, but once you're used to using them, you'll miss them in any
-language that doesn't have them. Passing functions to other functions is
-incredibly powerful. Next, let's look at one of those things: iterators.
+strange at first, but once you're used to them, you'll miss them
+in other languages. Passing functions to other functions is
+incredibly powerful, as you will see in the following chapter about iterators.
# Iterators
```{rust}
for x in range(0i, 10i) {
- println!("{:d}", x);
+ println!("{}", x);
}
```
```{rust}
let greater_than_forty_two = range(0i, 100i)
- .find(|x| *x >= 42);
+ .find(|x| *x > 42);
match greater_than_forty_two {
Some(_) => println!("We got some numbers!"),
`map` is called upon another iterator, and produces a new iterator where each
element reference has the closure it's been given as an argument called on it.
-So this would give us the numbers from `2-101`. Well, almost! If you
+So this would give us the numbers from `2-100`. Well, almost! If you
compile the example, you'll get a warning:
```{notrust,ignore}
If you are trying to execute a closure on an iterator for its side effects,
just use `for` instead.
-There are tons of interesting iterator adapters. `take(n)` will get the
-first `n` items out of an iterator, and return them as a list. Let's
-try it out with our infinite iterator from before, `count()`:
+There are tons of interesting iterator adapters. `take(n)` will return an
+iterator over the next `n` elements of the original iterator, note that this
+has no side effect on the original iterator. Let's try it out with our infinite
+iterator from before, `count()`:
```{rust}
for i in std::iter::count(1i, 5i).take(5) {
## Success and failure
-Tasks don't always succeed, they can also fail. A task that wishes to fail
-can call the `fail!` macro, passing a message:
+Tasks don't always succeed, they can also panic. A task that wishes to panic
+can call the `panic!` macro, passing a message:
```{rust}
spawn(proc() {
- fail!("Nope.");
+ panic!("Nope.");
});
```
-If a task fails, it is not possible for it to recover. However, it can
-notify other tasks that it has failed. We can do this with `task::try`:
+If a task panics, it is not possible for it to recover. However, it can
+notify other tasks that it has panicked. We can do this with `task::try`:
```{rust}
use std::task;
if rand::random() {
println!("OK");
} else {
- fail!("oops!");
+ panic!("oops!");
}
});
```
-This task will randomly fail or succeed. `task::try` returns a `Result`
+This task will randomly panic or succeed. `task::try` returns a `Result`
type, so we can handle the response like any other computation that may
-fail.
+panic.
# Macros
The first is when interfacing with C code, and the second is when building
certain kinds of abstractions.
-Rust has support for FFI (which you can read about in the [FFI
-Guide](guide-ffi.html)), but can't guarantee that the C code will be safe.
-Therefore, Rust marks such functions with the `unsafe`
+Rust has support for [FFI](http://en.wikipedia.org/wiki/Foreign_function_interface)
+(which you can read about in the [FFI Guide](guide-ffi.html)), but can't guarantee
+that the C code will be safe. Therefore, Rust marks such functions with the `unsafe`
keyword, which indicates that the function may not behave properly.
Second, if you'd like to create some sort of shared-memory data structure, Rust
* [Strings](guide-strings.html)
* [Pointers](guide-pointers.html)
* [References and Lifetimes](guide-lifetimes.html)
+* [Crates and modules](guide-crates.html)
* [Tasks and Communication](guide-tasks.html)
* [Foreign Function Interface](guide-ffi.html)
* [Writing Unsafe and Low-Level Code](guide-unsafe.html)
[type: text] src/doc/guide-tasks.md $lang:doc/l10n/$lang/guide-tasks.md
[type: text] src/doc/guide-testing.md $lang:doc/l10n/$lang/guide-testing.md
[type: text] src/doc/guide-unsafe.md $lang:doc/l10n/$lang/guide-unsafe.md
+[type: text] src/doc/guide-unsafe.md $lang:doc/l10n/$lang/guide-crates.md
[type: text] src/doc/guide.md $lang:doc/l10n/$lang/guide.md
[type: text] src/doc/index.md $lang:doc/l10n/$lang/index.md
[type: text] src/doc/intro.md $lang:doc/l10n/$lang/intro.md
### Keywords
-<p id="keyword-table-marker">The keywords are the following strings, organized by first letter:</p>
-
-| | | | |
-|----------|--------|--------|-------|
-| as | | | |
-| box | break | | |
-| continue | crate | | |
-| else | enum | extern | |
-| false | fn | for | |
-| if | impl | in | |
-| let | loop | | |
-| match | mod | mut | |
-| priv | proc | pub | |
-| ref | return | | |
-| self | static | struct | super |
-| trait | true | type | |
-| unsafe | use | | |
-| while | | | |
+<p id="keyword-table-marker"></p>
+
+| | | | | |
+|----------|----------|----------|----------|--------|
+| abstract | alignof | as | be | box |
+| break | const | continue | crate | do |
+| else | enum | extern | false | final |
+| fn | for | if | impl | in |
+| let | loop | match | mod | move |
+| mut | offsetof | once | override | priv |
+| proc | pub | pure | ref | return |
+| sizeof | static | self | struct | super |
+| true | trait | type | typeof | unsafe |
+| unsized | use | virtual | where | while |
+| yield | | | | |
+
Each of these keywords has special meaning in its grammar, and all of them are
excluded from the `ident` rule.
+Note that some of these keywords are reserved, and do not currently do
+anything.
+
### Literals
A literal is an expression consisting of a single token, rather than a sequence
type Complex = (f64, f64);
fn sin(f: f64) -> f64 {
/* ... */
-# fail!();
+# panic!();
}
fn cos(f: f64) -> f64 {
/* ... */
-# fail!();
+# panic!();
}
fn tan(f: f64) -> f64 {
/* ... */
-# fail!();
+# panic!();
}
}
```
```
fn my_err(s: &str) -> ! {
println!("{}", s);
- fail!();
+ panic!();
}
```
We call such functions "diverging" because they never return a value to the
-caller. Every control path in a diverging function must end with a `fail!()` or
+caller. Every control path in a diverging function must end with a `panic!()` or
a call to another diverging function on every control path. The `!` annotation
does *not* denote a type. Rather, the result type of a diverging function is a
special type called $\bot$ ("bottom") that unifies with any type. Rust has no
typecheck:
```
-# fn my_err(s: &str) -> ! { fail!() }
+# fn my_err(s: &str) -> ! { panic!() }
fn f(i: int) -> int {
if i == 42 {
: Allocate memory on the exchange heap.
* `closure_exchange_malloc`
: ___Needs filling in___
-* `fail_`
+* `panic`
: Abort the program with an error.
* `fail_bounds_check`
: Abort the program with a bounds check error.
Indices are zero-based, and may be of any integral type. Vector access is
bounds-checked at run-time. When the check fails, it will put the task in a
-_failing state_.
+_panicked state_.
```{should-fail}
([1, 2, 3, 4])[0];
-(["a", "b"])[10]; // fails
+(["a", "b"])[10]; // panics
```
### Unary operator expressions
let x: List<int> = Cons(10, box Cons(11, box Nil));
match x {
- Cons(_, box Nil) => fail!("singleton list"),
+ Cons(_, box Nil) => panic!("singleton list"),
Cons(..) => return,
- Nil => fail!("empty list")
+ Nil => panic!("empty list")
}
```
return;
}
_ => {
- fail!();
+ panic!();
}
}
```
Cons(x, ref r @ box Cons(_, _)) => {
match *r {
box Cons(y, _) => (x <= y) && is_sorted(&**r),
- _ => fail!()
+ _ => panic!()
}
}
}
let message = match maybe_digit {
Some(x) if x < 10 => process_digit(x),
Some(x) => process_other(x),
- None => fail!()
+ None => panic!()
};
```
* running
* blocked
-* failing
+* panicked
* dead
A task begins its lifecycle — once it has been spawned — in the
when a message arrives at a sender, or a buffer opens to receive a message
— then the blocked task will unblock and transition back to *running*.
-A task may transition to the *failing* state at any time, due being killed by
-some external event or internally, from the evaluation of a `fail!()` macro.
-Once *failing*, a task unwinds its stack and transitions to the *dead* state.
+A task may transition to the *panicked* state at any time, due being killed by
+some external event or internally, from the evaluation of a `panic!()` macro.
+Once *panicking*, a task unwinds its stack and transitions to the *dead* state.
Unwinding the stack of a task is done by the task itself, on its own control
stack. If a value with a destructor is freed during unwinding, the code for the
destructor is run, also on the task's control stack. Running the destructor
code causes a temporary transition to a *running* state, and allows the
destructor code to cause any subsequent state transitions. The original task
-of unwinding and failing thereby may suspend temporarily, and may involve
+of unwinding and panicking thereby may suspend temporarily, and may involve
(recursive) unwinding of the stack of a failed destructor. Nonetheless, the
outermost unwinding activity will continue until the stack is unwound and the
task transitions to the *dead* state. There is no way to "recover" from task
-failure. Once a task has temporarily suspended its unwinding in the *failing*
-state, failure occurring from within this destructor results in *hard* failure.
-A hard failure currently results in the process aborting.
+panics. Once a task has temporarily suspended its unwinding in the *panicking*
+state, a panic occurring from within this destructor results in *hard* panic.
+A hard panic currently results in the process aborting.
A task in the *dead* state cannot transition to other states; it exists only to
have its termination status inspected by other tasks, and/or to await
~~~md
```should_fail
-// This code block is expected to generate a failure when run
+// This code block is expected to generate a panic when run
```
~~~
```test_harness
#[test]
fn foo() {
- fail!("oops! (will run & register as failure)")
+ panic!("oops! (will run & register as a failed test)")
}
```
~~~
Running tests often requires some special configuration to filter tests, find
libraries, or try running ignored examples. The testing framework that rustdoc
-uses is build on crate `test`, which is also used when you compile crates with
+uses is built on crate `test`, which is also used when you compile crates with
rustc's `--test` flag. Extra arguments can be passed to rustdoc's test harness
with the `--test-args` flag.
-> int
{ }
-fn baz( a:int, // shoudl work with a comment here
+fn baz( a:int, // should work with a comment here
b:char)
-> int
{ }
--- /dev/null
+#!/bin/sh
+# Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+# file at the top-level directory of this distribution and at
+# http://rust-lang.org/COPYRIGHT.
+#
+# Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+# http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+# <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+# option. This file may not be copied, modified, or distributed
+# except according to those terms.
+
+
+msg() {
+ echo "rustup: $1"
+}
+
+step_msg() {
+ msg
+ msg "$1"
+ msg
+}
+
+warn() {
+ echo "rustup: WARNING: $1"
+}
+
+err() {
+ echo "rustup: error: $1"
+ exit 1
+}
+
+need_ok() {
+ if [ $? -ne 0 ]
+ then
+ err "$1"
+ fi
+}
+
+
+putvar() {
+ local T
+ eval T=\$$1
+ eval TLEN=\${#$1}
+ if [ $TLEN -gt 35 ]
+ then
+ printf "rustup: %-20s := %.35s ...\n" $1 "$T"
+ else
+ printf "rustup: %-20s := %s %s\n" $1 "$T" "$2"
+ fi
+}
+
+probe() {
+ local V=$1
+ shift
+ local P
+ local T
+ for P
+ do
+ T=$(which $P 2>&1)
+ if [ $? -eq 0 ]
+ then
+ VER0=$($P --version 2>/dev/null | head -1 \
+ | sed -e 's/[^0-9]*\([vV]\?[0-9.]\+[^ ]*\).*/\1/' )
+ if [ $? -eq 0 -a "x${VER0}" != "x" ]
+ then
+ VER="($VER0)"
+ else
+ VER=""
+ fi
+ break
+ else
+ VER=""
+ T=""
+ fi
+ done
+ eval $V=\$T
+ putvar $V "$VER"
+}
+
+probe_need() {
+ local V=$1
+ probe $*
+ eval VV=\$$V
+ if [ -z "$VV" ]
+ then
+ err "needed, but unable to find any of: $*"
+ fi
+}
+
+
+valopt() {
+ VAL_OPTIONS="$VAL_OPTIONS $1"
+
+ local OP=$1
+ local DEFAULT=$2
+ shift
+ shift
+ local DOC="$*"
+ if [ $HELP -eq 0 ]
+ then
+ local UOP=$(echo $OP | tr '[:lower:]' '[:upper:]' | tr '\-' '\_')
+ local V="CFG_${UOP}"
+ eval $V="$DEFAULT"
+ for arg in $CFG_ARGS
+ do
+ if echo "$arg" | grep -q -- "--$OP="
+ then
+ val=$(echo "$arg" | cut -f2 -d=)
+ eval $V=$val
+ fi
+ done
+ putvar $V
+ else
+ if [ -z "$DEFAULT" ]
+ then
+ DEFAULT="<none>"
+ fi
+ OP="${OP}=[${DEFAULT}]"
+ printf " --%-30s %s\n" "$OP" "$DOC"
+ fi
+}
+
+opt() {
+ BOOL_OPTIONS="$BOOL_OPTIONS $1"
+
+ local OP=$1
+ local DEFAULT=$2
+ shift
+ shift
+ local DOC="$*"
+ local FLAG=""
+
+ if [ $DEFAULT -eq 0 ]
+ then
+ FLAG="enable"
+ else
+ FLAG="disable"
+ DOC="don't $DOC"
+ fi
+
+ if [ $HELP -eq 0 ]
+ then
+ for arg in $CFG_ARGS
+ do
+ if [ "$arg" = "--${FLAG}-${OP}" ]
+ then
+ OP=$(echo $OP | tr 'a-z-' 'A-Z_')
+ FLAG=$(echo $FLAG | tr 'a-z' 'A-Z')
+ local V="CFG_${FLAG}_${OP}"
+ eval $V=1
+ putvar $V
+ fi
+ done
+ else
+ if [ ! -z "$META" ]
+ then
+ OP="$OP=<$META>"
+ fi
+ printf " --%-30s %s\n" "$FLAG-$OP" "$DOC"
+ fi
+}
+
+flag() {
+ BOOL_OPTIONS="$BOOL_OPTIONS $1"
+
+ local OP=$1
+ shift
+ local DOC="$*"
+
+ if [ $HELP -eq 0 ]
+ then
+ for arg in $CFG_ARGS
+ do
+ if [ "$arg" = "--${OP}" ]
+ then
+ OP=$(echo $OP | tr 'a-z-' 'A-Z_')
+ local V="CFG_${OP}"
+ eval $V=1
+ putvar $V
+ fi
+ done
+ else
+ if [ ! -z "$META" ]
+ then
+ OP="$OP=<$META>"
+ fi
+ printf " --%-30s %s\n" "$OP" "$DOC"
+ fi
+}
+
+validate_opt () {
+ for arg in $CFG_ARGS
+ do
+ isArgValid=0
+ for option in $BOOL_OPTIONS
+ do
+ if test --disable-$option = $arg
+ then
+ isArgValid=1
+ fi
+ if test --enable-$option = $arg
+ then
+ isArgValid=1
+ fi
+ if test --$option = $arg
+ then
+ isArgValid=1
+ fi
+ done
+ for option in $VAL_OPTIONS
+ do
+ if echo "$arg" | grep -q -- "--$option="
+ then
+ isArgValid=1
+ fi
+ done
+ if [ "$arg" = "--help" ]
+ then
+ echo
+ echo "No more help available for Configure options,"
+ echo "check the Wiki or join our IRC channel"
+ break
+ else
+ if test $isArgValid -eq 0
+ then
+ err "Option '$arg' is not recognized"
+ fi
+ fi
+ done
+}
+
+probe_need CFG_CURL curl
+
+CFG_SRC_DIR="$(cd $(dirname $0) && pwd)/"
+CFG_SELF="$0"
+CFG_ARGS="$@"
+
+HELP=0
+if [ "$1" = "--help" ]
+then
+ HELP=1
+ shift
+ echo
+ echo "Usage: $CFG_SELF [options]"
+ echo
+ echo "Options:"
+ echo
+else
+ step_msg "processing $CFG_SELF args"
+fi
+
+OPTIONS=""
+BOOL_OPTIONS=""
+VAL_OPTIONS=""
+
+flag uninstall "only uninstall from the installation prefix"
+valopt prefix "" "set installation prefix"
+opt cargo 1 "install cargo with rust"
+
+if [ $HELP -eq 1 ]
+then
+ echo
+ exit 0
+fi
+
+step_msg "validating $CFG_SELF args"
+validate_opt
+
+
+# Platform detection copied from `configure`
+
+CFG_OSTYPE=$(uname -s)
+CFG_CPUTYPE=$(uname -m)
+
+if [ $CFG_OSTYPE = Darwin -a $CFG_CPUTYPE = i386 ]
+then
+ # Darwin's `uname -s` lies and always returns i386. We have to use sysctl
+ # instead.
+ if sysctl hw.optional.x86_64 | grep -q ': 1'
+ then
+ CFG_CPUTYPE=x86_64
+ fi
+fi
+
+# The goal here is to come up with the same triple as LLVM would,
+# at least for the subset of platforms we're willing to target.
+
+case $CFG_OSTYPE in
+
+ Linux)
+ CFG_OSTYPE=unknown-linux-gnu
+ ;;
+
+ FreeBSD)
+ CFG_OSTYPE=unknown-freebsd
+ ;;
+
+ Darwin)
+ CFG_OSTYPE=apple-darwin
+ ;;
+
+ MINGW32*)
+ CFG_OSTYPE=pc-mingw32
+ ;;
+# Thad's Cygwin identifers below
+
+# Vista 32 bit
+ CYGWIN_NT-6.0)
+ CFG_OSTYPE=pc-mingw32
+ CFG_CPUTYPE=i686
+ ;;
+
+# Vista 64 bit
+ CYGWIN_NT-6.0-WOW64)
+ CFG_OSTYPE=w64-mingw32
+ CFG_CPUTYPE=x86_64
+ ;;
+
+# Win 7 32 bit
+ CYGWIN_NT-6.1)
+ CFG_OSTYPE=pc-mingw32
+ CFG_CPUTYPE=i686
+ ;;
+
+# Win 7 64 bit
+ CYGWIN_NT-6.1-WOW64)
+ CFG_OSTYPE=w64-mingw32
+ CFG_CPUTYPE=x86_64
+ ;;
+
+# We do not detect other OS such as XP/2003 using 64 bit using uname.
+# If we want to in the future, we will need to use Cygwin
+# Chuck's csih helper in /usr/lib/csih/winProductName.exe or alternative.
+ *)
+ err "unknown OS type: $CFG_OSTYPE"
+ ;;
+esac
+
+
+case $CFG_CPUTYPE in
+
+ i386 | i486 | i686 | i786 | x86)
+ CFG_CPUTYPE=i686
+ ;;
+
+ xscale | arm)
+ CFG_CPUTYPE=arm
+ ;;
+
+ x86_64 | x86-64 | x64 | amd64)
+ CFG_CPUTYPE=x86_64
+ ;;
+
+ *)
+ err "unknown CPU type: $CFG_CPUTYPE"
+esac
+
+# Detect 64 bit linux systems with 32 bit userland and force 32 bit compilation
+if [ $CFG_OSTYPE = unknown-linux-gnu -a $CFG_CPUTYPE = x86_64 ]
+then
+ file -L "$SHELL" | grep -q "x86[_-]64"
+ if [ $? != 0 ]; then
+ CFG_CPUTYPE=i686
+ fi
+fi
+
+HOST_TRIPLE="${CFG_CPUTYPE}-${CFG_OSTYPE}"
+
+# Is this a triple we have nightlies for?
+case $HOST_TRIPLE in
+
+ x86_64-unknown-linux-gnu)
+ ;;
+
+ i686-unknown-linux-gnu)
+ ;;
+
+ x86_64-apple-darwin)
+ ;;
+
+ i686-apple-darwin)
+ ;;
+
+ *)
+ err "rustup.sh doesn't work for host $HOST_TRIPLE"
+
+esac
+
+msg "host triple: ${HOST_TRIPLE}"
+
+PACKAGE_NAME=rust-nightly
+PACKAGE_NAME_AND_TRIPLE="${PACKAGE_NAME}-${HOST_TRIPLE}"
+TARBALL_NAME="${PACKAGE_NAME_AND_TRIPLE}.tar.gz"
+REMOTE_TARBALL="https://static.rust-lang.org/dist/${TARBALL_NAME}"
+TMP_DIR="./rustup-tmp-install"
+LOCAL_TARBALL="${TMP_DIR}/${TARBALL_NAME}"
+LOCAL_INSTALL_DIR="${TMP_DIR}/${PACKAGE_NAME_AND_TRIPLE}"
+LOCAL_INSTALL_SCRIPT="${LOCAL_INSTALL_DIR}/install.sh"
+
+CARGO_PACKAGE_NAME=cargo-nightly
+CARGO_PACKAGE_NAME_AND_TRIPLE="${CARGO_PACKAGE_NAME}-${HOST_TRIPLE}"
+CARGO_TARBALL_NAME="${CARGO_PACKAGE_NAME_AND_TRIPLE}.tar.gz"
+CARGO_REMOTE_TARBALL="https://static.rust-lang.org/cargo-dist/${CARGO_TARBALL_NAME}"
+CARGO_LOCAL_TARBALL="${TMP_DIR}/${CARGO_TARBALL_NAME}"
+CARGO_LOCAL_INSTALL_DIR="${TMP_DIR}/${CARGO_PACKAGE_NAME_AND_TRIPLE}"
+CARGO_LOCAL_INSTALL_SCRIPT="${CARGO_LOCAL_INSTALL_DIR}/install.sh"
+
+rm -Rf "${TMP_DIR}"
+need_ok "failed to remove temporary installation directory"
+
+mkdir -p "${TMP_DIR}"
+need_ok "failed to create create temporary installation directory"
+
+msg "downloading rust installer"
+"${CFG_CURL}" "${REMOTE_TARBALL}" > "${LOCAL_TARBALL}"
+if [ $? -ne 0 ]
+then
+ rm -Rf "${TMP_DIR}"
+ err "failed to download installer"
+fi
+
+if [ -z "${CFG_DISABLE_CARGO}" ]; then
+ msg "downloading cargo installer"
+ "${CFG_CURL}" "${CARGO_REMOTE_TARBALL}" > "${CARGO_LOCAL_TARBALL}"
+ if [ $? -ne 0 ]
+ then
+ rm -Rf "${TMP_DIR}"
+ err "failed to download cargo installer"
+ fi
+fi
+
+
+(cd "${TMP_DIR}" && tar xzf "${TARBALL_NAME}")
+if [ $? -ne 0 ]
+then
+ rm -Rf "${TMP_DIR}"
+ err "failed to unpack installer"
+fi
+
+MAYBE_UNINSTALL=
+if [ -n "${CFG_UNINSTALL}" ]
+then
+ MAYBE_UNINSTALL="--uninstall"
+fi
+
+MAYBE_PREFIX=
+if [ -n "${CFG_PREFIX}" ]
+then
+ MAYBE_PREFIX="--prefix=${CFG_PREFIX}"
+fi
+
+sh "${LOCAL_INSTALL_SCRIPT}" "${MAYBE_UNINSTALL}" "${MAYBE_PREFIX}"
+if [ $? -ne 0 ]
+then
+ rm -Rf "${TMP_DIR}"
+ err "failed to install Rust"
+fi
+
+if [ -z "${CFG_DISABLE_CARGO}" ]; then
+ (cd "${TMP_DIR}" && tar xzf "${CARGO_TARBALL_NAME}")
+ if [ $? -ne 0 ]
+ then
+ rm -Rf "${TMP_DIR}"
+ err "failed to unpack cargo installer"
+ fi
+
+ sh "${CARGO_LOCAL_INSTALL_SCRIPT}" "${MAYBE_UNINSTALL}" "${MAYBE_PREFIX}"
+ if [ $? -ne 0 ]
+ then
+ rm -Rf "${TMP_DIR}"
+ err "failed to install Cargo"
+ fi
+fi
+
+rm -Rf "${TMP_DIR}"
+need_ok "couldn't rm temporary installation directory"
use syntax::ast;
use syntax::ast::Name;
-use syntax::parse::token::*;
+use syntax::parse::token;
use syntax::parse::lexer::TokenAndSpan;
fn parse_token_list(file: &str) -> HashMap<String, Token> {
fn id() -> Token {
- IDENT(ast::Ident { name: Name(0), ctxt: 0, }, false)
+ token::Ident(ast::Ident { name: Name(0), ctxt: 0, }, token::Plain)
}
let mut res = HashMap::new();
let num = line.slice_from(eq + 1);
let tok = match val {
- "SHR" => BINOP(SHR),
- "DOLLAR" => DOLLAR,
- "LT" => LT,
- "STAR" => BINOP(STAR),
- "FLOAT_SUFFIX" => id(),
- "INT_SUFFIX" => id(),
- "SHL" => BINOP(SHL),
- "LBRACE" => LBRACE,
- "RARROW" => RARROW,
- "LIT_STR" => LIT_STR(Name(0)),
- "DOTDOT" => DOTDOT,
- "MOD_SEP" => MOD_SEP,
- "DOTDOTDOT" => DOTDOTDOT,
- "NOT" => NOT,
- "AND" => BINOP(AND),
- "LPAREN" => LPAREN,
- "ANDAND" => ANDAND,
- "AT" => AT,
- "LBRACKET" => LBRACKET,
- "LIT_STR_RAW" => LIT_STR_RAW(Name(0), 0),
- "RPAREN" => RPAREN,
- "SLASH" => BINOP(SLASH),
- "COMMA" => COMMA,
- "LIFETIME" => LIFETIME(ast::Ident { name: Name(0), ctxt: 0 }),
- "CARET" => BINOP(CARET),
- "TILDE" => TILDE,
- "IDENT" => id(),
- "PLUS" => BINOP(PLUS),
- "LIT_CHAR" => LIT_CHAR(Name(0)),
- "LIT_BYTE" => LIT_BYTE(Name(0)),
- "EQ" => EQ,
- "RBRACKET" => RBRACKET,
- "COMMENT" => COMMENT,
- "DOC_COMMENT" => DOC_COMMENT(Name(0)),
- "DOT" => DOT,
- "EQEQ" => EQEQ,
- "NE" => NE,
- "GE" => GE,
- "PERCENT" => BINOP(PERCENT),
- "RBRACE" => RBRACE,
- "BINOP" => BINOP(PLUS),
- "POUND" => POUND,
- "OROR" => OROR,
- "LIT_INTEGER" => LIT_INTEGER(Name(0)),
- "BINOPEQ" => BINOPEQ(PLUS),
- "LIT_FLOAT" => LIT_FLOAT(Name(0)),
- "WHITESPACE" => WS,
- "UNDERSCORE" => UNDERSCORE,
- "MINUS" => BINOP(MINUS),
- "SEMI" => SEMI,
- "COLON" => COLON,
- "FAT_ARROW" => FAT_ARROW,
- "OR" => BINOP(OR),
- "GT" => GT,
- "LE" => LE,
- "LIT_BINARY" => LIT_BINARY(Name(0)),
- "LIT_BINARY_RAW" => LIT_BINARY_RAW(Name(0), 0),
- _ => continue
+ "SHR" => token::BinOp(token::Shr),
+ "DOLLAR" => token::Dollar,
+ "LT" => token::Lt,
+ "STAR" => token::BinOp(token::Star),
+ "FLOAT_SUFFIX" => id(),
+ "INT_SUFFIX" => id(),
+ "SHL" => token::BinOp(token::Shl),
+ "LBRACE" => token::LBrace,
+ "RARROW" => token::Rarrow,
+ "LIT_STR" => token::LitStr(Name(0)),
+ "DOTDOT" => token::DotDot,
+ "MOD_SEP" => token::ModSep,
+ "DOTDOTDOT" => token::DotDotDot,
+ "NOT" => token::Not,
+ "AND" => token::BinOp(token::And),
+ "LPAREN" => token::LParen,
+ "ANDAND" => token::AndAnd,
+ "AT" => token::At,
+ "LBRACKET" => token::LBracket,
+ "LIT_STR_RAW" => token::LitStrRaw(Name(0), 0),
+ "RPAREN" => token::RParen,
+ "SLASH" => token::BinOp(token::Slash),
+ "COMMA" => token::Comma,
+ "LIFETIME" => token::Lifetime(ast::Ident { name: Name(0), ctxt: 0 }),
+ "CARET" => token::BinOp(token::Caret),
+ "TILDE" => token::Tilde,
+ "IDENT" => token::Id(),
+ "PLUS" => token::BinOp(token::Plus),
+ "LIT_CHAR" => token::LitChar(Name(0)),
+ "LIT_BYTE" => token::LitByte(Name(0)),
+ "EQ" => token::Eq,
+ "RBRACKET" => token::RBracket,
+ "COMMENT" => token::Comment,
+ "DOC_COMMENT" => token::DocComment(Name(0)),
+ "DOT" => token::Dot,
+ "EQEQ" => token::EqEq,
+ "NE" => token::Ne,
+ "GE" => token::Ge,
+ "PERCENT" => token::BinOp(token::Percent),
+ "RBRACE" => token::RBrace,
+ "BINOP" => token::BinOp(token::Plus),
+ "POUND" => token::Pound,
+ "OROR" => token::OrOr,
+ "LIT_INTEGER" => token::LitInteger(Name(0)),
+ "BINOPEQ" => token::BinOpEq(token::Plus),
+ "LIT_FLOAT" => token::LitFloat(Name(0)),
+ "WHITESPACE" => token::Whitespace,
+ "UNDERSCORE" => token::Underscore,
+ "MINUS" => token::BinOp(token::Minus),
+ "SEMI" => token::Semi,
+ "COLON" => token::Colon,
+ "FAT_ARROW" => token::FatArrow,
+ "OR" => token::BinOp(token::Or),
+ "GT" => token::Gt,
+ "LE" => token::Le,
+ "LIT_BINARY" => token::LitBinary(Name(0)),
+ "LIT_BINARY_RAW" => token::LitBinaryRaw(Name(0), 0),
+ _ => continue,
};
res.insert(num.to_string(), tok);
res
}
-fn str_to_binop(s: &str) -> BinOp {
+fn str_to_binop(s: &str) -> BinOpToken {
match s {
- "+" => PLUS,
- "/" => SLASH,
- "-" => MINUS,
- "*" => STAR,
- "%" => PERCENT,
- "^" => CARET,
- "&" => AND,
- "|" => OR,
- "<<" => SHL,
- ">>" => SHR,
- _ => fail!("Bad binop str `{}`", s)
+ "+" => token::Plus,
+ "/" => token::Slash,
+ "-" => token::Minus,
+ "*" => token::Star,
+ "%" => token::Percent,
+ "^" => token::Caret,
+ "&" => token::And,
+ "|" => token::Or,
+ "<<" => token::Shl,
+ ">>" => token::Shr,
+ _ => panic!("Bad binop str `{}`", s),
}
}
debug!("What we got: content (`{}`), proto: {}", content, proto_tok);
let real_tok = match *proto_tok {
- BINOP(..) => BINOP(str_to_binop(content)),
- BINOPEQ(..) => BINOPEQ(str_to_binop(content.slice_to(content.len() - 1))),
- LIT_STR(..) => LIT_STR(fix(content)),
- LIT_STR_RAW(..) => LIT_STR_RAW(fix(content), count(content)),
- LIT_CHAR(..) => LIT_CHAR(fixchar(content)),
- LIT_BYTE(..) => LIT_BYTE(fixchar(content)),
- DOC_COMMENT(..) => DOC_COMMENT(nm),
- LIT_INTEGER(..) => LIT_INTEGER(nm),
- LIT_FLOAT(..) => LIT_FLOAT(nm),
- LIT_BINARY(..) => LIT_BINARY(nm),
- LIT_BINARY_RAW(..) => LIT_BINARY_RAW(fix(content), count(content)),
- IDENT(..) => IDENT(ast::Ident { name: nm, ctxt: 0 }, true),
- LIFETIME(..) => LIFETIME(ast::Ident { name: nm, ctxt: 0 }),
+ token::BinOp(..) => token::BinOp(str_to_binop(content)),
+ token::BinOpEq(..) => token::BinOpEq(str_to_binop(content.slice_to(
+ content.len() - 1))),
+ token::LitStr(..) => token::LitStr(fix(content)),
+ token::LitStrRaw(..) => token::LitStrRaw(fix(content), count(content)),
+ token::LitChar(..) => token::LitChar(fixchar(content)),
+ token::LitByte(..) => token::LitByte(fixchar(content)),
+ token::DocComment(..) => token::DocComment(nm),
+ token::LitInteger(..) => token::LitInteger(nm),
+ token::LitFloat(..) => token::LitFloat(nm),
+ token::LitBinary(..) => token::LitBinary(nm),
+ token::LitBinaryRaw(..) => token::LitBinaryRaw(fix(content), count(content)),
+ token::Ident(..) => token::Ident(ast::Ident { name: nm, ctxt: 0 },
+ token::ModName),
+ token::Lifetime(..) => token::Lifetime(ast::Ident { name: nm, ctxt: 0 }),
ref t => t.clone()
};
fn tok_cmp(a: &Token, b: &Token) -> bool {
match a {
- &IDENT(id, _) => match b {
- &IDENT(id2, _) => id == id2,
+ &token::Ident(id, _) => match b {
+ &token::Ident(id2, _) => id == id2,
_ => false
},
_ => a == b
warn!("Different names for {} and {}", rustc_tok, antlr_tok);
}
}
- _ => fail!("{} is not {}", antlr_tok, rustc_tok)
+ _ => panic!("{} is not {}", antlr_tok, rustc_tok)
},)*
ref c => assert!(c == &antlr_tok.tok, "{} is not {}", rustc_tok, antlr_tok)
}
)
)
- matches!(LIT_BYTE(..),
- LIT_CHAR(..),
- LIT_INTEGER(..),
- LIT_FLOAT(..),
- LIT_STR(..),
- LIT_STR_RAW(..),
- LIT_BINARY(..),
- LIT_BINARY_RAW(..),
- IDENT(..),
- LIFETIME(..),
- INTERPOLATED(..),
- DOC_COMMENT(..),
- SHEBANG(..)
+ matches!(
+ LitByte(..),
+ LitChar(..),
+ LitInteger(..),
+ LitFloat(..),
+ LitStr(..),
+ LitStrRaw(..),
+ LitBinary(..),
+ LitBinaryRaw(..),
+ Ident(..),
+ Lifetime(..),
+ Interpolated(..),
+ DocComment(..),
+ Shebang(..)
);
}
}
use core::atomic;
use core::clone::Clone;
+use core::fmt::{mod, Show};
+use core::cmp::{Eq, Ord, PartialEq, PartialOrd, Ordering};
+use core::default::Default;
use core::kinds::{Sync, Send};
use core::mem::{min_align_of, size_of, drop};
use core::mem;
use core::ops::{Drop, Deref};
use core::option::{Some, None, Option};
-use core::ptr;
use core::ptr::RawPtr;
+use core::ptr;
use heap::deallocate;
/// An atomically reference counted wrapper for shared state.
Arc { _ptr: unsafe { mem::transmute(x) } }
}
- #[inline]
- fn inner(&self) -> &ArcInner<T> {
- // This unsafety is ok because while this arc is alive we're guaranteed
- // that the inner pointer is valid. Furthermore, we know that the
- // `ArcInner` structure itself is `Sync` because the inner data is
- // `Sync` as well, so we're ok loaning out an immutable pointer to
- // these contents.
- unsafe { &*self._ptr }
- }
-
/// Downgrades a strong pointer to a weak pointer.
///
/// Weak pointers will not keep the data alive. Once all strong references
}
}
+impl<T> Arc<T> {
+ #[inline]
+ fn inner(&self) -> &ArcInner<T> {
+ // This unsafety is ok because while this arc is alive we're guaranteed
+ // that the inner pointer is valid. Furthermore, we know that the
+ // `ArcInner` structure itself is `Sync` because the inner data is
+ // `Sync` as well, so we're ok loaning out an immutable pointer to
+ // these contents.
+ unsafe { &*self._ptr }
+ }
+}
+
#[unstable = "waiting on stability of Clone"]
-impl<T: Sync + Send> Clone for Arc<T> {
+impl<T> Clone for Arc<T> {
/// Duplicate an atomically reference counted wrapper.
///
/// The resulting two `Arc` objects will point to the same underlying data
}
#[experimental = "Deref is experimental."]
-impl<T: Send + Sync> Deref<T> for Arc<T> {
+impl<T> Deref<T> for Arc<T> {
#[inline]
fn deref(&self) -> &T {
&self.inner().data
impl<T: Sync + Send> Weak<T> {
/// Attempts to upgrade this weak reference to a strong reference.
///
- /// This method will fail to upgrade this reference if the strong reference
- /// count has already reached 0, but if there are still other active strong
- /// references this function will return a new strong reference to the data.
+ /// This method will not upgrade this reference if the strong reference count has already
+ /// reached 0, but if there are still other active strong references this function will return
+ /// a new strong reference to the data.
pub fn upgrade(&self) -> Option<Arc<T>> {
// We use a CAS loop to increment the strong count instead of a
// fetch_add because once the count hits 0 is must never be above 0.
}
}
+#[unstable = "waiting on PartialEq"]
+impl<T: PartialEq> PartialEq for Arc<T> {
+ fn eq(&self, other: &Arc<T>) -> bool { *(*self) == *(*other) }
+ fn ne(&self, other: &Arc<T>) -> bool { *(*self) != *(*other) }
+}
+#[unstable = "waiting on PartialOrd"]
+impl<T: PartialOrd> PartialOrd for Arc<T> {
+ fn partial_cmp(&self, other: &Arc<T>) -> Option<Ordering> {
+ (**self).partial_cmp(&**other)
+ }
+ fn lt(&self, other: &Arc<T>) -> bool { *(*self) < *(*other) }
+ fn le(&self, other: &Arc<T>) -> bool { *(*self) <= *(*other) }
+ fn ge(&self, other: &Arc<T>) -> bool { *(*self) >= *(*other) }
+ fn gt(&self, other: &Arc<T>) -> bool { *(*self) > *(*other) }
+}
+#[unstable = "waiting on Ord"]
+impl<T: Ord> Ord for Arc<T> {
+ fn cmp(&self, other: &Arc<T>) -> Ordering { (**self).cmp(&**other) }
+}
+#[unstable = "waiting on Eq"]
+impl<T: Eq> Eq for Arc<T> {}
+
+impl<T: fmt::Show> fmt::Show for Arc<T> {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ (**self).fmt(f)
+ }
+}
+
+impl<T: Default + Sync + Send> Default for Arc<T> {
+ fn default() -> Arc<T> { Arc::new(Default::default()) }
+}
+
#[cfg(test)]
#[allow(experimental)]
mod tests {
use std::mem::drop;
use std::ops::Drop;
use std::option::{Option, Some, None};
+ use std::str::Str;
use std::sync::atomic;
use std::task;
use std::vec::Vec;
assert!(canary.load(atomic::Acquire) == 1);
drop(arc_weak);
}
+
+ #[test]
+ fn show_arc() {
+ let a = Arc::new(5u32);
+ assert!(format!("{}", a).as_slice() == "5")
+ }
+
+ // Make sure deriving works with Arc<T>
+ #[deriving(Eq, Ord, PartialEq, PartialOrd, Clone, Show, Default)]
+ struct Foo { inner: Arc<int> }
}
match a.downcast::<uint>() {
Ok(a) => { assert!(a == box 8u); }
- Err(..) => fail!()
+ Err(..) => panic!()
}
match b.downcast::<Test>() {
Ok(a) => { assert!(a == box Test); }
- Err(..) => fail!()
+ Err(..) => panic!()
}
let a = box 8u as Box<Any>;
/// element). When the arena is destroyed, it iterates through all of its
/// chunks, and uses the tydesc information to trace through the objects,
/// calling the destructors on them. One subtle point that needs to be
-/// addressed is how to handle failures while running the user provided
+/// addressed is how to handle panics while running the user provided
/// initializer function. It is important to not run the destructor on
/// uninitialized objects, but how to detect them is somewhat subtle. Since
/// `alloc()` can be invoked recursively, it is not sufficient to simply exclude
// We encode whether the object a tydesc describes has been
// initialized in the arena in the low bit of the tydesc pointer. This
-// is necessary in order to properly do cleanup if a failure occurs
+// is necessary in order to properly do cleanup if a panic occurs
// during an initializer.
#[inline]
fn bitpack_tydesc_ptr(p: *const TyDesc, is_done: bool) -> uint {
// things interesting.
arena.alloc(|| { [0u8, 1u8, 2u8] });
}
- // Now, fail while allocating
+ // Now, panic while allocating
arena.alloc::<Rc<int>>(|| {
- // Now fail.
- fail!();
+ panic!();
});
}
/// the BST strategy.
///
/// A B-Tree instead makes each node contain B-1 to 2B-1 elements in a contiguous array. By doing
-/// this, we reduce the number of allocations by a factor of B, and improve cache effeciency in
+/// this, we reduce the number of allocations by a factor of B, and improve cache efficiency in
/// searches. However, this does mean that searches will have to do *more* comparisons on average.
/// The precise number of comparisons depends on the node search strategy used. For optimal cache
-/// effeciency, one could search the nodes linearly. For optimal comparisons, one could search
+/// efficiency, one could search the nodes linearly. For optimal comparisons, one could search
/// the node using binary search. As a compromise, one could also perform a linear search
/// that initially only checks every i<sup>th</sup> element for some choice of i.
///
// hard. For now, we accept this cost in the name of correctness and simplicity.
//
// As a compromise, keys and vals could be merged into one Vec<(K, V)>, which would shave
- // off 3 words, but possibly hurt our cache effeciency during search, which only cares about
+ // off 3 words, but possibly hurt our cache efficiency during search, which only cares about
// keys. This would also avoid the Zip we use in our iterator implementations. This is
// probably worth investigating.
//
impl<K: Ord, V> Node<K, V> {
/// Searches for the given key in the node. If it finds an exact match,
- /// `Found` will be yielded with the matching index. If it fails to find an exact match,
+ /// `Found` will be yielded with the matching index. If it doesn't find an exact match,
/// `GoDown` will be yielded with the index of the subtree the key must lie in.
pub fn search(&self, key: &K) -> SearchResult {
// FIXME(Gankro): Tune when to search linear or binary based on B (and maybe K/V).
- // For the B configured as of this writing (B = 6), binary search was *singnificantly*
+ // For the B configured as of this writing (B = 6), binary search was *significantly*
// worse for uints.
self.search_linear(key)
}
}
}
- /// Steal! Stealing is roughly analagous to a binary tree rotation.
+ /// Steal! Stealing is roughly analogous to a binary tree rotation.
/// In this case, we're "rotating" right.
unsafe fn steal_to_left(&mut self, underflowed_child_index: uint) {
// Take the biggest stuff off left
}
};
- // Swap the parent's seperating key-value pair with left's
+ // Swap the parent's separating key-value pair with left's
self.unsafe_swap(underflowed_child_index - 1, &mut key, &mut val);
// Put them at the start of right
}
}
- /// Steal! Stealing is roughly analagous to a binary tree rotation.
+ /// Steal! Stealing is roughly analogous to a binary tree rotation.
/// In this case, we're "rotating" left.
unsafe fn steal_to_right(&mut self, underflowed_child_index: uint) {
// Take the smallest stuff off right
}
};
- // Swap the parent's seperating key-value pair with right's
+ // Swap the parent's separating key-value pair with right's
self.unsafe_swap(underflowed_child_index, &mut key, &mut val);
// Put them at the end of left
}
/// Merge! Left and right will be smooshed into one node, along with the key-value
- /// pair that seperated them in their parent.
+ /// pair that separated them in their parent.
unsafe fn merge_children(&mut self, left_index: uint) {
- // Permanently remove right's index, and the key-value pair that seperates
+ // Permanently remove right's index, and the key-value pair that separates
// left and right
let (key, val, right) = {
match (self.keys.remove(left_index),
left.absorb(key, val, right);
}
- /// Take all the values from right, seperated by the given key and value
+ /// Take all the values from right, separated by the given key and value
fn absorb(&mut self, key: K, val: V, right: Node<K, V>) {
// Just as a sanity check, make sure we can fit this guy in
debug_assert!(self.len() + right.len() <= self.capacity())
loop {
match (last_ptr, node_ptr.prev.resolve_immut()) {
(None , None ) => {}
- (None , _ ) => fail!("prev link for list_head"),
+ (None , _ ) => panic!("prev link for list_head"),
(Some(p), Some(pptr)) => {
assert_eq!(p as *const Node<T>, pptr as *const Node<T>);
}
- _ => fail!("prev link is none, not good"),
+ _ => panic!("prev link is none, not good"),
}
match node_ptr.next {
Some(ref next) => {
#[cfg(not(test))]
mod std {
- pub use core::fmt; // necessary for fail!()
- pub use core::option; // necessary for fail!()
+ pub use core::fmt; // necessary for panic!()
+ pub use core::option; // necessary for panic!()
pub use core::clone; // deriving(Clone)
pub use core::cmp; // deriving(Eq, Ord, etc.)
pub use hash; // deriving(Hash)
pub fn get_mut<'a>(&'a mut self, i: uint) -> &'a mut T {
let idx = self.raw_index(i);
match *self.elts.get_mut(idx) {
- None => fail!(),
+ None => panic!(),
Some(ref mut v) => v
}
}
fn index<'a>(&'a self, i: &uint) -> &'a A {
let idx = self.raw_index(*i);
match self.elts[idx] {
- None => fail!(),
+ None => panic!(),
Some(ref v) => v,
}
}
use alloc::boxed::Box;
use core::cmp;
+use core::kinds::Sized;
use core::mem::size_of;
use core::mem;
use core::prelude::{Clone, Collection, Greater, Iterator, Less, None, Option};
// Functional utilities
#[allow(missing_doc)]
-pub trait VectorVector<T> {
+pub trait VectorVector<T> for Sized? {
// FIXME #5898: calling these .concat and .connect conflicts with
// StrVector::con{cat,nect}, since they have generic contents.
/// Flattens a vector of vectors of `T` into a single `Vec<T>`.
fn connect_vec(&self, sep: &T) -> Vec<T>;
}
-impl<'a, T: Clone, V: AsSlice<T>> VectorVector<T> for &'a [V] {
+impl<T: Clone, V: AsSlice<T>> VectorVector<T> for [V] {
fn concat_vec(&self) -> Vec<T> {
let size = self.iter().fold(0u, |acc, v| acc + v.as_slice().len());
let mut result = Vec::with_capacity(size);
}
/// Extension methods for vector slices with cloneable elements
-pub trait CloneableVector<T> {
+pub trait CloneableVector<T> for Sized? {
/// Copies `self` into a new `Vec`.
fn to_vec(&self) -> Vec<T>;
}
-impl<'a, T: Clone> CloneableVector<T> for &'a [T] {
+impl<T: Clone> CloneableVector<T> for [T] {
/// Returns a copy of `v`.
#[inline]
fn to_vec(&self) -> Vec<T> {
let mut vector = Vec::with_capacity(self.len());
- vector.push_all(*self);
+ vector.push_all(self);
vector
}
}
#[experimental]
fn into_vec(mut self) -> Vec<T> {
unsafe {
- let xs = Vec::from_raw_parts(self.len(), self.len(), self.as_mut_ptr());
+ let xs = Vec::from_raw_parts(self.as_mut_ptr(), self.len(), self.len());
mem::forget(self);
xs
}
}
/// Extension methods for vectors containing `Clone` elements.
-pub trait ImmutableCloneableVector<T> {
+pub trait ImmutableCloneableVector<T> for Sized? {
/// Partitions the vector into two vectors `(a, b)`, where all
/// elements of `a` satisfy `f` and all elements of `b` do not.
fn partitioned(&self, f: |&T| -> bool) -> (Vec<T>, Vec<T>);
/// assert_eq!(Some(vec![1i, 3, 2]), perms.next());
/// assert_eq!(Some(vec![3i, 1, 2]), perms.next());
/// ```
- fn permutations(self) -> Permutations<T>;
+ fn permutations(&self) -> Permutations<T>;
}
-impl<'a,T:Clone> ImmutableCloneableVector<T> for &'a [T] {
+impl<T: Clone> ImmutableCloneableVector<T> for [T] {
#[inline]
fn partitioned(&self, f: |&T| -> bool) -> (Vec<T>, Vec<T>) {
let mut lefts = Vec::new();
}
/// Returns an iterator over all permutations of a vector.
- fn permutations(self) -> Permutations<T> {
+ fn permutations(&self) -> Permutations<T> {
Permutations{
swaps: ElementSwaps::new(self.len()),
v: self.to_vec(),
/// Extension methods for vectors such that their elements are
/// mutable.
-pub trait MutableSliceAllocating<'a, T> {
+pub trait MutableSliceAllocating<T> for Sized? {
/// Sorts the slice, in place, using `compare` to compare
/// elements.
///
/// v.sort_by(|a, b| b.cmp(a));
/// assert!(v == [5, 4, 3, 2, 1]);
/// ```
- fn sort_by(self, compare: |&T, &T| -> Ordering);
+ fn sort_by(&mut self, compare: |&T, &T| -> Ordering);
/// Consumes `src` and moves as many elements as it can into `self`
/// from the range [start,end).
/// assert_eq!(num_moved, 3);
/// assert!(a == [6i, 7, 8, 4, 5]);
/// ```
- fn move_from(self, src: Vec<T>, start: uint, end: uint) -> uint;
+ fn move_from(&mut self, src: Vec<T>, start: uint, end: uint) -> uint;
}
-impl<'a,T> MutableSliceAllocating<'a, T> for &'a mut [T] {
+impl<T> MutableSliceAllocating<T> for [T] {
#[inline]
- fn sort_by(self, compare: |&T, &T| -> Ordering) {
+ fn sort_by(&mut self, compare: |&T, &T| -> Ordering) {
merge_sort(self, compare)
}
#[inline]
- fn move_from(self, mut src: Vec<T>, start: uint, end: uint) -> uint {
+ fn move_from(&mut self, mut src: Vec<T>, start: uint, end: uint) -> uint {
for (a, b) in self.iter_mut().zip(src[mut start..end].iter_mut()) {
mem::swap(a, b);
}
/// Methods for mutable vectors with orderable elements, such as
/// in-place sorting.
-pub trait MutableOrdSlice<T> {
+pub trait MutableOrdSlice<T> for Sized? {
/// Sorts the slice, in place.
///
/// This is equivalent to `self.sort_by(|a, b| a.cmp(b))`.
/// v.sort();
/// assert!(v == [-5i, -3, 1, 2, 4]);
/// ```
- fn sort(self);
+ fn sort(&mut self);
/// Mutates the slice to the next lexicographic permutation.
///
/// let b: &mut [_] = &mut [1i, 0, 2];
/// assert!(v == b);
/// ```
- fn next_permutation(self) -> bool;
+ fn next_permutation(&mut self) -> bool;
/// Mutates the slice to the previous lexicographic permutation.
///
/// let b: &mut [_] = &mut [0i, 1, 2];
/// assert!(v == b);
/// ```
- fn prev_permutation(self) -> bool;
+ fn prev_permutation(&mut self) -> bool;
}
-impl<'a, T: Ord> MutableOrdSlice<T> for &'a mut [T] {
+impl<T: Ord> MutableOrdSlice<T> for [T] {
#[inline]
- fn sort(self) {
- self.sort_by(|a,b| a.cmp(b))
+ fn sort(&mut self) {
+ self.sort_by(|a, b| a.cmp(b))
}
- fn next_permutation(self) -> bool {
+ fn next_permutation(&mut self) -> bool {
// These cases only have 1 permutation each, so we can't do anything.
if self.len() < 2 { return false; }
true
}
- fn prev_permutation(self) -> bool {
+ fn prev_permutation(&mut self) -> bool {
// These cases only have 1 permutation each, so we can't do anything.
if self.len() < 2 { return false; }
3 => assert!(v == [2, 3, 1]),
4 => assert!(v == [2, 1, 3]),
5 => assert!(v == [1, 2, 3]),
- _ => fail!(),
+ _ => panic!(),
}
}
}
}
}
- // shouldn't fail/crash
+ // shouldn't panic
let mut v: [uint, .. 0] = [];
v.sort();
#[should_fail]
fn test_from_fn_fail() {
Vec::from_fn(100, |v| {
- if v == 50 { fail!() }
+ if v == 50 { panic!() }
box 0i
});
}
impl Clone for S {
fn clone(&self) -> S {
self.f.set(self.f.get() + 1);
- if self.f.get() == 10 { fail!() }
+ if self.f.get() == 10 { panic!() }
S { f: self.f, boxes: self.boxes.clone() }
}
}
let mut v = vec![];
v.grow_fn(100, |i| {
if i == 50 {
- fail!()
+ panic!()
}
(box 0i, Rc::new(0i))
})
let mut i = 0u;
for _ in v.permutations() {
if i == 2 {
- fail!()
+ panic!()
}
i += 1;
}
sum += *x;
}
// sum == 11806, to stop dead code elimination.
- if sum == 0 {fail!()}
+ if sum == 0 {panic!()}
})
}
assert!(m.insert(5, 14));
let new = 100;
match m.find_mut(&5) {
- None => fail!(), Some(x) => *x = new
+ None => panic!(), Some(x) => *x = new
}
assert_eq!(m.find(&5), Some(&new));
}
use core::fmt;
use core::cmp;
use core::iter::AdditiveIterator;
+use core::kinds::Sized;
use core::prelude::{Char, Clone, Collection, Eq, Equiv, ImmutableSlice};
use core::prelude::{Iterator, MutableSlice, None, Option, Ord, Ordering};
use core::prelude::{PartialEq, PartialOrd, Result, AsSlice, Some, Tuple2};
*/
/// Methods for vectors of strings.
-pub trait StrVector {
+pub trait StrVector for Sized? {
/// Concatenates a vector of strings.
///
/// # Example
fn connect(&self, sep: &str) -> String;
}
-impl<'a, S: Str> StrVector for &'a [S] {
+impl<S: Str> StrVector for [S] {
fn concat(&self) -> String {
if self.is_empty() {
return String::new();
}
}
-impl<'a, S: Str> StrVector for Vec<S> {
+impl<S: Str> StrVector for Vec<S> {
#[inline]
fn concat(&self) -> String {
self.as_slice().concat()
// original problem code path anymore.)
let s = String::from_str("");
let _bytes = s.as_bytes();
- fail!();
+ panic!();
}
#[test]
let len = c.encode_utf8(bytes).unwrap_or(0);
let s = ::core::str::from_utf8(bytes[..len]).unwrap();
if Some(c) != s.chars().next() {
- fail!("character {:x}={} does not decode correctly", c as u32, c);
+ panic!("character {:x}={} does not decode correctly", c as u32, c);
}
}
}
let len = c.encode_utf8(bytes).unwrap_or(0);
let s = ::core::str::from_utf8(bytes[..len]).unwrap();
if Some(c) != s.chars().rev().next() {
- fail!("character {:x}={} does not decode correctly", c as u32, c);
+ panic!("character {:x}={} does not decode correctly", c as u32, c);
}
}
}
/// assert_eq!(s.as_slice(), "he");
/// ```
#[inline]
- #[unstable = "the failure conventions for strings are under development"]
+ #[unstable = "the panic conventions for strings are under development"]
pub fn truncate(&mut self, new_len: uint) {
assert!(self.as_slice().is_char_boundary(new_len));
self.vec.truncate(new_len)
/// This is a O(n) operation as it requires copying every element in the
/// buffer.
///
- /// # Failure
+ /// # Panics
///
/// If `idx` does not lie on a character boundary, then this function will
- /// fail.
+ /// panic.
///
/// # Example
///
/// assert_eq!(s.remove(0), Some('o'));
/// assert_eq!(s.remove(0), None);
/// ```
- #[unstable = "the failure semantics of this function and return type \
+ #[unstable = "the panic semantics of this function and return type \
may change"]
pub fn remove(&mut self, idx: uint) -> Option<char> {
let len = self.len();
/// This is a O(n) operation as it requires copying every element in the
/// buffer.
///
- /// # Failure
+ /// # Panics
///
/// If `idx` does not lie on a character boundary or is out of bounds, then
- /// this function will fail.
- #[unstable = "the failure semantics of this function are uncertain"]
+ /// this function will panic.
+ #[unstable = "the panic semantics of this function are uncertain"]
pub fn insert(&mut self, idx: uint, ch: char) {
let len = self.len();
assert!(idx <= len);
#[inline]
pub unsafe fn from_parts(buf: *mut u8, length: uint, capacity: uint) -> String {
String {
- vec: Vec::from_raw_parts(length, capacity, buf),
+ vec: Vec::from_raw_parts(buf, length, capacity),
}
}
/// let new_ua = "Safari/156.0";
/// match t.find_with_mut(|k| "User-Agent".cmp(k)) {
/// Some(x) => *x = new_ua,
- /// None => fail!(),
+ /// None => panic!(),
/// }
///
/// assert_eq!(t.find(&"User-Agent"), Some(&new_ua));
}
}
return match node.take() {
- Some(box TreeNode{value, ..}) => Some(value), None => fail!()
+ Some(box TreeNode{value, ..}) => Some(value), None => panic!()
};
}
assert!(m.insert(5, 14));
let new = 100;
match m.find_mut(&5) {
- None => fail!(), Some(x) => *x = new
+ None => panic!(), Some(x) => *x = new
}
assert_eq!(m.find(&5), Some(&new));
}
assert!(m.insert("t5", 14));
let new = 100;
match m.find_with_mut(|k| "t5".cmp(k)) {
- None => fail!(), Some(x) => *x = new
+ None => panic!(), Some(x) => *x = new
}
assert_eq!(m.find_with(|k| "t5".cmp(k)), Some(&new));
}
*child = Internal(new);
return ret;
}
- _ => fail!("unreachable code"),
+ _ => panic!("unreachable code"),
}
}
External(stored, _) if stored == key => {
match mem::replace(child, Nothing) {
External(_, value) => (Some(value), true),
- _ => fail!()
+ _ => panic!()
}
}
External(..) => (None, false),
assert!(m.insert(5u, 14i));
let new = 100;
match m.find_mut(&5) {
- None => fail!(), Some(x) => *x = new
+ None => panic!(), Some(x) => *x = new
}
assert_eq!(m.find(&5), Some(&new));
}
#[unsafe_no_drop_flag]
#[stable]
pub struct Vec<T> {
+ ptr: *mut T,
len: uint,
cap: uint,
- ptr: *mut T
}
impl<T> Vec<T> {
// 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.
- Vec { len: 0, cap: 0, ptr: EMPTY as *mut T }
+ Vec { ptr: EMPTY as *mut T, len: 0, cap: 0 }
}
/// Constructs a new, empty `Vec` with the specified capacity.
#[stable]
pub fn with_capacity(capacity: uint) -> Vec<T> {
if mem::size_of::<T>() == 0 {
- Vec { len: 0, cap: uint::MAX, ptr: EMPTY as *mut T }
+ Vec { ptr: EMPTY as *mut T, len: 0, cap: uint::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>()) };
- Vec { len: 0, cap: capacity, ptr: ptr as *mut T }
+ Vec { ptr: ptr as *mut T, len: 0, cap: capacity }
}
}
/// }
///
/// // Put everything back together into a Vec
- /// let rebuilt = Vec::from_raw_parts(len, cap, p);
+ /// let rebuilt = Vec::from_raw_parts(p, len, cap);
/// assert_eq!(rebuilt, vec![4i, 5i, 6i]);
/// }
/// }
/// ```
#[experimental]
- pub unsafe fn from_raw_parts(length: uint, capacity: uint,
- ptr: *mut T) -> Vec<T> {
- Vec { len: length, cap: capacity, ptr: ptr }
+ pub unsafe fn from_raw_parts(ptr: *mut T, length: uint,
+ capacity: uint) -> Vec<T> {
+ Vec { ptr: ptr, len: length, cap: capacity }
}
/// Consumes the `Vec`, partitioning it based on a predicate.
pub fn reserve_additional(&mut self, extra: uint) {
if self.cap - self.len < extra {
match self.len.checked_add(&extra) {
- None => fail!("Vec::reserve_additional: `uint` overflow"),
+ None => panic!("Vec::reserve_additional: `uint` overflow"),
Some(new_cap) => self.reserve(new_cap)
}
}
}
}
- /// Shrinks the capacity of the vector as much as possible.
+ /// Shrinks the capacity of the vector as much as possible. It will drop
+ /// down as close as possible to the length but the allocator may still
+ /// inform the vector that there is space for a few more elements.
///
/// # Example
///
/// ```
- /// let mut vec = vec![1i, 2, 3];
+ /// let mut vec: Vec<int> = Vec::with_capacity(10);
+ /// vec.push_all([1, 2, 3]);
+ /// assert_eq!(vec.capacity(), 10);
/// vec.shrink_to_fit();
+ /// assert!(vec.capacity() >= 3);
/// ```
#[stable]
pub fn shrink_to_fit(&mut self) {
/// vec.truncate(2);
/// assert_eq!(vec, vec![1, 2]);
/// ```
- #[unstable = "waiting on failure semantics"]
+ #[unstable = "waiting on panic semantics"]
pub fn truncate(&mut self, len: uint) {
unsafe {
// drop any extra elements
while len < self.len {
- // decrement len before the read(), so a failure on Drop doesn't
+ // decrement len before the read(), so a panic on Drop doesn't
// re-drop the just-failed value.
self.len -= 1;
ptr::read(self.as_slice().unsafe_get(self.len));
/// for num in vec.iter_mut() {
/// *num = 0;
/// }
+ /// assert_eq!(vec, vec![0i, 0, 0]);
/// ```
#[inline]
pub fn iter_mut<'a>(&'a mut self) -> MutItems<'a,T> {
/// Inserts an element at position `index` within the vector, shifting all
/// elements after position `i` one position to the right.
///
- /// # Failure
+ /// # Panics
///
- /// Fails if `index` is not between `0` and the vector's length (both
+ /// Panics if `index` is not between `0` and the vector's length (both
/// bounds inclusive).
///
/// # Example
/// vec.insert(4, 5);
/// assert_eq!(vec, vec![1, 4, 2, 3, 5]);
/// ```
- #[unstable = "failure semantics need settling"]
+ #[unstable = "panic semantics need settling"]
pub fn insert(&mut self, index: uint, element: T) {
let len = self.len();
assert!(index <= len);
/// // v is unchanged:
/// assert_eq!(v, vec![1, 3]);
/// ```
- #[unstable = "failure semantics need settling"]
+ #[unstable = "panic semantics need settling"]
pub fn remove(&mut self, index: uint) -> Option<T> {
let len = self.len();
if index < len {
pub fn dedup(&mut self) {
unsafe {
// Although we have a mutable reference to `self`, we cannot make
- // *arbitrary* changes. The `PartialEq` comparisons could fail, so we
+ // *arbitrary* changes. The `PartialEq` comparisons could panic, so we
// must ensure that the vector is in a valid state at all time.
//
// The way that we handle this is by using swaps; we iterate
if self.len == self.cap {
let old_size = self.cap * mem::size_of::<T>();
let size = max(old_size, 2 * mem::size_of::<T>()) * 2;
- if old_size > size { fail!("capacity overflow") }
+ if old_size > size { panic!("capacity overflow") }
unsafe {
self.ptr = alloc_or_realloc(self.ptr, old_size, size);
}
pub fn as_vec<'a, T>(x: &'a [T]) -> DerefVec<'a, T> {
unsafe {
DerefVec {
- x: Vec::from_raw_parts(x.len(), x.len(), x.as_ptr() as *mut T),
+ x: Vec::from_raw_parts(x.as_ptr() as *mut T, x.len(), x.len()),
l: ContravariantLifetime::<'a>
}
}
// +-+-+-+-+-+-+-+-+-+
// | |
// end_u end_t
- // We must not fail here, one cell is marked as `T`
+ // We must not panic here, one cell is marked as `T`
// although it is not `T`.
pv.start_t = pv.start_t.offset(1);
// +-+-+-+-+-+-+-+-+-+
// | |
// end_u end_t
- // We may fail again.
+ // We may panic again.
- // The function given by the user might fail.
+ // The function given by the user might panic.
let u = f(t);
ptr::write(pv.end_u, u);
// +-+-+-+-+-+-+-+-+-+
// | |
// end_u end_t
- // We should not fail here, because that would leak the `U`
+ // We should not panic here, because that would leak the `U`
// pointed to by `end_u`.
pv.end_u = pv.end_u.offset(1);
// +-+-+-+-+-+-+-+-+-+
// | |
// end_u end_t
- // We may fail again.
+ // We may panic again.
}
}
// end_u
// Extract `vec` and prevent the destructor of
// `PartialVecNonZeroSized` from running. Note that none of the
- // function calls can fail, thus no resources can be leaked (as the
+ // function calls can panic, thus no resources can be leaked (as the
// `vec` member of `PartialVec` is the only one which holds
// allocations -- and it is returned from this function. None of
- // this can fail.
+ // this can panic.
unsafe {
let vec_len = pv.vec.len();
let vec_cap = pv.vec.capacity();
let vec_ptr = pv.vec.as_mut_ptr() as *mut U;
mem::forget(pv);
- Vec::from_raw_parts(vec_len, vec_cap, vec_ptr)
+ Vec::from_raw_parts(vec_ptr, vec_len, vec_cap)
}
} else {
// Put the `Vec` into the `PartialVecZeroSized` structure and
while pv.num_t != 0 {
unsafe {
// Create a `T` out of thin air and decrement `num_t`. This
- // must not fail between these steps, as otherwise a
+ // must not panic between these steps, as otherwise a
// destructor of `T` which doesn't exist runs.
let t = mem::uninitialized();
pv.num_t -= 1;
- // The function given by the user might fail.
+ // The function given by the user might panic.
let u = f(t);
// Forget the `U` and increment `num_u`. This increment
// cannot overflow the `uint` as we only do this for a
// number of times that fits into a `uint` (and start with
- // `0`). Again, we should not fail between these steps.
+ // `0`). Again, we should not panic between these steps.
mem::forget(u);
pv.num_u += 1;
}
}
// Create a `Vec` from our `PartialVecZeroSized` and make sure the
- // destructor of the latter will not run. None of this can fail.
+ // destructor of the latter will not run. None of this can panic.
let mut result = Vec::new();
unsafe { result.set_len(pv.num_u); }
result
fn drop(&mut self) {
let BadElem(ref mut x) = *self;
if *x == 0xbadbeef {
- fail!("BadElem failure: 0xbadbeef")
+ panic!("BadElem panic: 0xbadbeef")
}
}
}
#[stable]
impl AtomicBool {
/// Create a new `AtomicBool`
+ #[inline]
pub fn new(v: bool) -> AtomicBool {
let val = if v { UINT_TRUE } else { 0 };
AtomicBool { v: UnsafeCell::new(val), nocopy: marker::NoCopy }
#[stable]
impl AtomicInt {
/// Create a new `AtomicInt`
+ #[inline]
pub fn new(v: int) -> AtomicInt {
AtomicInt {v: UnsafeCell::new(v), nocopy: marker::NoCopy}
}
#[stable]
impl AtomicUint {
/// Create a new `AtomicUint`
+ #[inline]
pub fn new(v: uint) -> AtomicUint {
AtomicUint { v: UnsafeCell::new(v), nocopy: marker::NoCopy }
}
#[stable]
impl<T> AtomicPtr<T> {
/// Create a new `AtomicPtr`
+ #[inline]
pub fn new(p: *mut T) -> AtomicPtr<T> {
AtomicPtr { p: UnsafeCell::new(p as uint), nocopy: marker::NoCopy }
}
Release => intrinsics::atomic_store_rel(dst, val),
Relaxed => intrinsics::atomic_store_relaxed(dst, val),
SeqCst => intrinsics::atomic_store(dst, val),
- Acquire => fail!("there is no such thing as an acquire store"),
- AcqRel => fail!("there is no such thing as an acquire/release store"),
+ Acquire => panic!("there is no such thing as an acquire store"),
+ AcqRel => panic!("there is no such thing as an acquire/release store"),
}
}
Acquire => intrinsics::atomic_load_acq(dst),
Relaxed => intrinsics::atomic_load_relaxed(dst),
SeqCst => intrinsics::atomic_load(dst),
- Release => fail!("there is no such thing as a release load"),
- AcqRel => fail!("there is no such thing as an acquire/release load"),
+ Release => panic!("there is no such thing as a release load"),
+ AcqRel => panic!("there is no such thing as an acquire/release load"),
}
}
Release => intrinsics::atomic_fence_rel(),
AcqRel => intrinsics::atomic_fence_acqrel(),
SeqCst => intrinsics::atomic_fence(),
- Relaxed => fail!("there is no such thing as a relaxed fence")
+ Relaxed => panic!("there is no such thing as a relaxed fence")
}
}
}
//! tracked statically, at compile time. Because `RefCell` borrows are
//! dynamic it is possible to attempt to borrow a value that is
//! already mutably borrowed; when this happens it results in task
-//! failure.
+//! panic.
//!
//! # When to choose interior mutability
//!
//! // Recursive call to return the just-cached value.
//! // Note that if we had not let the previous borrow
//! // of the cache fall out of scope then the subsequent
-//! // recursive borrow would cause a dynamic task failure.
+//! // recursive borrow would cause a dynamic task panic.
//! // This is the major hazard of using `RefCell`.
//! self.minimum_spanning_tree()
//! }
pub fn borrow<'a>(&'a self) -> Ref<'a, T> {
match self.try_borrow() {
Some(ptr) => ptr,
- None => fail!("RefCell<T> already mutably borrowed")
+ None => panic!("RefCell<T> already mutably borrowed")
}
}
pub fn borrow_mut<'a>(&'a self) -> RefMut<'a, T> {
match self.try_borrow_mut() {
Some(ptr) => ptr,
- None => fail!("RefCell<T> already borrowed")
+ None => panic!("RefCell<T> already borrowed")
}
}
#[inline]
pub fn to_digit(c: char, radix: uint) -> Option<uint> {
if radix > 36 {
- fail!("to_digit: radix is too high (maximum 36)");
+ panic!("to_digit: radix is too high (maximum 36)");
}
let val = match c {
'0' ... '9' => c as uint - ('0' as uint),
#[inline]
pub fn from_digit(num: uint, radix: uint) -> Option<char> {
if radix > 36 {
- fail!("from_digit: radix is too high (maximum 36)");
+ panic!("from_digit: radix is to high (maximum 36)");
}
if num < radix {
unsafe {
+++ /dev/null
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-//! Failure support for libcore
-//!
-//! The core library cannot define failure, but it does *declare* failure. This
-//! means that the functions inside of libcore are allowed to fail, but to be
-//! useful an upstream crate must define failure for libcore to use. The current
-//! interface for failure is:
-//!
-//! ```ignore
-//! fn fail_impl(fmt: &fmt::Arguments, &(&'static str, uint)) -> !;
-//! ```
-//!
-//! This definition allows for failing with any general message, but it does not
-//! allow for failing with a `~Any` value. The reason for this is that libcore
-//! is not allowed to allocate.
-//!
-//! This module contains a few other failure functions, but these are just the
-//! necessary lang items for the compiler. All failure is funneled through this
-//! one function. Currently, the actual symbol is declared in the standard
-//! library, but the location of this may change over time.
-
-#![allow(dead_code, missing_doc)]
-
-use fmt;
-use intrinsics;
-
-#[cold] #[inline(never)] // this is the slow path, always
-#[lang="fail"]
-pub fn fail(expr_file_line: &(&'static str, &'static str, uint)) -> ! {
- let (expr, file, line) = *expr_file_line;
- let ref file_line = (file, line);
- format_args!(|args| -> () {
- fail_fmt(args, file_line);
- }, "{}", expr);
-
- unsafe { intrinsics::abort() }
-}
-
-#[cold] #[inline(never)]
-#[lang="fail_bounds_check"]
-fn fail_bounds_check(file_line: &(&'static str, uint),
- index: uint, len: uint) -> ! {
- format_args!(|args| -> () {
- fail_fmt(args, file_line);
- }, "index out of bounds: the len is {} but the index is {}", len, index);
- unsafe { intrinsics::abort() }
-}
-
-#[cold] #[inline(never)]
-pub fn fail_fmt(fmt: &fmt::Arguments, file_line: &(&'static str, uint)) -> ! {
- #[allow(ctypes)]
- extern {
- #[lang = "fail_fmt"]
- fn fail_impl(fmt: &fmt::Arguments, file: &'static str,
- line: uint) -> !;
-
- }
- let (file, line) = *file_line;
- unsafe { fail_impl(fmt, file, line) }
-}
/**
* The most general form of the `finally` functions. The function
- * `try_fn` will be invoked first; whether or not it fails, the
+ * `try_fn` will be invoked first; whether or not it panics, the
* function `finally_fn` will be invoked next. The two parameters
* `mutate` and `drop` are used to thread state through the two
* closures. `mutate` is used for any shared, mutable state that both
*
* **WARNING:** While shared, mutable state between the try and finally
* function is often necessary, one must be very careful; the `try`
- * function could have failed at any point, so the values of the shared
+ * function could have panicked at any point, so the values of the shared
* state may be inconsistent.
*
* # Example
assert!(2 <= radix && radix <= 36);
match exp_format {
ExpDec if radix >= DIGIT_E_RADIX // decimal exponent 'e'
- => fail!("float_to_str_bytes_common: radix {} incompatible with \
+ => panic!("float_to_str_bytes_common: radix {} incompatible with \
use of 'e' as decimal exponent", radix),
_ => ()
}
ExpDec => {
let (exp, exp_base) = match exp_format {
ExpDec => (num.abs().log10().floor(), cast::<f64, T>(10.0f64).unwrap()),
- ExpNone => fail!("unreachable"),
+ ExpNone => panic!("unreachable"),
};
(num / exp_base.powf(exp), cast::<T, i32>(exp).unwrap())
buf[end] = match exp_format {
ExpDec if exp_upper => 'E',
ExpDec if !exp_upper => 'e',
- _ => fail!("unreachable"),
+ _ => panic!("unreachable"),
} as u8;
end += 1;
fn digit(&self, x: u8) -> u8 {
match x {
$($x => $conv,)+
- x => fail!("number not in the range 0..{}: {}", self.base() - 1, x),
+ x => panic!("number not in the range 0..{}: {}", self.base() - 1, x),
}
}
}
match x {
x @ 0 ... 9 => b'0' + x,
x if x < self.base() => b'a' + (x - 10),
- x => fail!("number not in the range 0..{}: {}", self.base() - 1, x),
+ x => panic!("number not in the range 0..{}: {}", self.base() - 1, x),
}
}
}
fn visit_fn_input(&mut self, i: uint, mode: uint,
inner: *const TyDesc) -> bool;
fn visit_fn_output(&mut self, retstyle: uint, variadic: bool,
- inner: *const TyDesc) -> bool;
+ converging: bool, inner: *const TyDesc) -> bool;
fn visit_leave_fn(&mut self, purity: uint, proto: uint,
n_inputs: uint, retstyle: uint) -> bool;
//!
//! * `rust_begin_unwind` - This function takes three arguments, a
//! `&fmt::Arguments`, a `&str`, and a `uint`. These three arguments dictate
-//! the failure message, the file at which failure was invoked, and the line.
-//! It is up to consumers of this core library to define this failure
+//! the panic message, the file at which panic was invoked, and the line.
+//! It is up to consumers of this core library to define this panic
//! function; it is only required to never return.
// Since libcore defines many fundamental lang items, all tests live in a
pub mod bool;
pub mod cell;
pub mod char;
-pub mod failure;
+pub mod panicking;
pub mod finally;
pub mod iter;
pub mod option;
#[doc(hidden)]
mod core {
- pub use failure;
+ pub use panicking;
}
#[doc(hidden)]
#![macro_escape]
-/// Entry point of failure, for details, see std::macros
+/// Entry point of task panic, for details, see std::macros
#[macro_export]
-macro_rules! fail(
+macro_rules! panic(
() => (
- fail!("{}", "explicit failure")
+ panic!("{}", "explicit panic")
);
($msg:expr) => ({
static _MSG_FILE_LINE: (&'static str, &'static str, uint) = ($msg, file!(), line!());
- ::core::failure::fail(&_MSG_FILE_LINE)
+ ::core::panicking::panic(&_MSG_FILE_LINE)
});
($fmt:expr, $($arg:tt)*) => ({
// a closure can't have return type !, so we need a full
// as returning !. We really do want this to be inlined, however,
// because it's just a tiny wrapper. Small wins (156K to 149K in size)
// were seen when forcing this to be inlined, and that number just goes
- // up with the number of calls to fail!()
+ // up with the number of calls to panic!()
//
// The leading _'s are to avoid dead code warnings if this is
// used inside a dead function. Just `#[allow(dead_code)]` is
#[inline(always)]
fn _run_fmt(fmt: &::std::fmt::Arguments) -> ! {
static _FILE_LINE: (&'static str, uint) = (file!(), line!());
- ::core::failure::fail_fmt(fmt, &_FILE_LINE)
+ ::core::panicking::panic_fmt(fmt, &_FILE_LINE)
}
format_args!(_run_fmt, $fmt, $($arg)*)
});
macro_rules! assert(
($cond:expr) => (
if !$cond {
- fail!(concat!("assertion failed: ", stringify!($cond)))
+ panic!(concat!("assertion failed: ", stringify!($cond)))
}
);
($cond:expr, $($arg:tt)*) => (
if !$cond {
- fail!($($arg)*)
+ panic!($($arg)*)
}
);
)
let c1 = $cond1;
let c2 = $cond2;
if c1 != c2 || c2 != c1 {
- fail!("expressions not equal, left: {}, right: {}", c1, c2);
+ panic!("expressions not equal, left: {}, right: {}", c1, c2);
}
})
)
)
#[macro_export]
-macro_rules! unreachable( () => (fail!("unreachable code")) )
+macro_rules! unreachable( () => (panic!("unreachable code")) )
checked_impl!(CheckedMul, checked_mul, i32, intrinsics::i32_mul_with_overflow)
checked_impl!(CheckedMul, checked_mul, i64, intrinsics::i64_mul_with_overflow)
-/// Performs division that returns `None` instead of failing on division by zero and instead of
+/// Performs division that returns `None` instead of panicking on division by zero and instead of
/// wrapping around on underflow and overflow.
pub trait CheckedDiv: Div<Self, Self> {
/// Divides two numbers, checking for underflow, overflow and division by zero. If any of that
/// Take the square root of a number.
///
- /// Returns NaN if `self` is not a non-negative number.
+ /// Returns NaN if `self` is a negative number.
fn sqrt(self) -> Self;
/// Take the reciprocal (inverse) square root of a number, `1/sqrt(x)`.
fn rsqrt(self) -> Self;
/// Unwraps an option, yielding the content of a `Some`
///
- /// # Failure
+ /// # Panics
///
- /// Fails if the value is a `None` with a custom failure message provided by
+ /// Fails if the value is a `None` with a custom panic message provided by
/// `msg`.
///
/// # Example
pub fn expect(self, msg: &str) -> T {
match self {
Some(val) => val,
- None => fail!("{}", msg),
+ None => panic!("{}", msg),
}
}
/// Returns the inner `T` of a `Some(T)`.
///
- /// # Failure
+ /// # Panics
///
- /// Fails if the self value equals `None`.
+ /// Panics if the self value equals `None`.
///
/// # Safety note
///
- /// In general, because this function may fail, its use is discouraged.
+ /// In general, because this function may panic, its use is discouraged.
/// Instead, prefer to use pattern matching and handle the `None`
/// case explicitly.
///
pub fn unwrap(self) -> T {
match self {
Some(val) => val,
- None => fail!("called `Option::unwrap()` on a `None` value"),
+ None => panic!("called `Option::unwrap()` on a `None` value"),
}
}
--- /dev/null
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! Panic support for libcore
+//!
+//! The core library cannot define panicking, but it does *declare* panicking. This
+//! means that the functions inside of libcore are allowed to panic, but to be
+//! useful an upstream crate must define panicking for libcore to use. The current
+//! interface for panicking is:
+//!
+//! ```ignore
+//! fn panic_impl(fmt: &fmt::Arguments, &(&'static str, uint)) -> !;
+//! ```
+//!
+//! This definition allows for panicking with any general message, but it does not
+//! allow for failing with a `Box<Any>` value. The reason for this is that libcore
+//! is not allowed to allocate.
+//!
+//! This module contains a few other panicking functions, but these are just the
+//! necessary lang items for the compiler. All panics are funneled through this
+//! one function. Currently, the actual symbol is declared in the standard
+//! library, but the location of this may change over time.
+
+#![allow(dead_code, missing_doc)]
+
+use fmt;
+use intrinsics;
+
+// NOTE(stage0): remove after a snapshot
+#[cfg(stage0)]
+#[cold] #[inline(never)] // this is the slow path, always
+#[lang="fail"]
+pub fn panic(expr_file_line: &(&'static str, &'static str, uint)) -> ! {
+ let (expr, file, line) = *expr_file_line;
+ let ref file_line = (file, line);
+ format_args!(|args| -> () {
+ panic_fmt(args, file_line);
+ }, "{}", expr);
+
+ unsafe { intrinsics::abort() }
+}
+
+// NOTE(stage0): remove after a snapshot
+#[cfg(stage0)]
+#[cold] #[inline(never)]
+#[lang="fail_bounds_check"]
+fn panic_bounds_check(file_line: &(&'static str, uint),
+ index: uint, len: uint) -> ! {
+ format_args!(|args| -> () {
+ panic_fmt(args, file_line);
+ }, "index out of bounds: the len is {} but the index is {}", len, index);
+ unsafe { intrinsics::abort() }
+}
+
+// NOTE(stage0): remove after a snapshot
+#[cfg(stage0)]
+#[cold] #[inline(never)]
+pub fn panic_fmt(fmt: &fmt::Arguments, file_line: &(&'static str, uint)) -> ! {
+ #[allow(ctypes)]
+ extern {
+ #[lang = "fail_fmt"]
+ fn panic_impl(fmt: &fmt::Arguments, file: &'static str,
+ line: uint) -> !;
+
+ }
+ let (file, line) = *file_line;
+ unsafe { panic_impl(fmt, file, line) }
+}
+
+// NOTE(stage0): remove cfg after a snapshot
+#[cfg(not(stage0))]
+#[cold] #[inline(never)] // this is the slow path, always
+#[lang="panic"]
+pub fn panic(expr_file_line: &(&'static str, &'static str, uint)) -> ! {
+ let (expr, file, line) = *expr_file_line;
+ let ref file_line = (file, line);
+ format_args!(|args| -> () {
+ panic_fmt(args, file_line);
+ }, "{}", expr);
+
+ unsafe { intrinsics::abort() }
+}
+
+// NOTE(stage0): remove cfg after a snapshot
+#[cfg(not(stage0))]
+#[cold] #[inline(never)]
+#[lang="panic_bounds_check"]
+fn panic_bounds_check(file_line: &(&'static str, uint),
+ index: uint, len: uint) -> ! {
+ format_args!(|args| -> () {
+ panic_fmt(args, file_line);
+ }, "index out of bounds: the len is {} but the index is {}", len, index);
+ unsafe { intrinsics::abort() }
+}
+
+// NOTE(stage0): remove cfg after a snapshot
+#[cfg(not(stage0))]
+#[cold] #[inline(never)]
+pub fn panic_fmt(fmt: &fmt::Arguments, file_line: &(&'static str, uint)) -> ! {
+ #[allow(ctypes)]
+ extern {
+ #[lang = "panic_fmt"]
+ fn panic_impl(fmt: &fmt::Arguments, file: &'static str,
+ line: uint) -> !;
+
+ }
+ let (file, line) = *file_line;
+ unsafe { panic_impl(fmt, file, line) }
+}
//! unsafe {
//! let my_num: *mut int = libc::malloc(mem::size_of::<int>() as libc::size_t) as *mut int;
//! if my_num.is_null() {
-//! fail!("failed to allocate memory");
+//! panic!("failed to allocate memory");
//! }
//! libc::free(my_num as *mut libc::c_void);
//! }
//! Their definition should always match the ABI defined in `rustc::back::abi`.
use mem;
+use kinds::Sized;
/// The representation of a Rust slice
+#[repr(C)]
pub struct Slice<T> {
pub data: *const T,
pub len: uint,
}
/// The representation of a Rust closure
+#[repr(C)]
pub struct Closure {
pub code: *mut (),
pub env: *mut (),
}
/// The representation of a Rust procedure (`proc()`)
+#[repr(C)]
pub struct Procedure {
pub code: *mut (),
pub env: *mut (),
///
/// This struct does not have a `Repr` implementation
/// because there is no way to refer to all trait objects generically.
+#[repr(C)]
pub struct TraitObject {
pub data: *mut (),
pub vtable: *mut (),
/// This trait is meant to map equivalences between raw structs and their
/// corresponding rust values.
-pub trait Repr<T> {
+pub trait Repr<T> for Sized? {
/// This function "unwraps" a rust value (without consuming it) into its raw
/// struct representation. This can be used to read/write different values
/// for the struct. This is a safe method because by default it does not
/// enable write-access to the fields of the return value in safe code.
#[inline]
- fn repr(&self) -> T { unsafe { mem::transmute_copy(self) } }
+ fn repr(&self) -> T { unsafe { mem::transmute_copy(&self) } }
}
-impl<'a, T> Repr<Slice<T>> for &'a [T] {}
-impl<'a> Repr<Slice<u8>> for &'a str {}
-
+impl<T> Repr<Slice<T>> for [T] {}
+impl Repr<Slice<u8>> for str {}
//! warning (by default, controlled by the `unused_must_use` lint).
//!
//! You might instead, if you don't want to handle the error, simply
-//! fail, by converting to an `Option` with `ok`, then asserting
-//! success with `expect`. This will fail if the write fails, proving
+//! panic, by converting to an `Option` with `ok`, then asserting
+//! success with `expect`. This will panic if the write fails, proving
//! a marginally useful message indicating why:
//!
//! ```{.no_run}
//! let mut t = Timer::new().ok().expect("failed to create timer!");
//! ```
//!
-//! # `Result` vs. `fail!`
+//! # `Result` vs. `panic!`
//!
-//! `Result` is for recoverable errors; `fail!` is for unrecoverable
-//! errors. Callers should always be able to avoid failure if they
+//! `Result` is for recoverable errors; `panic!` is for unrecoverable
+//! errors. Callers should always be able to avoid panics if they
//! take the proper precautions, for example, calling `is_some()`
//! on an `Option` type before calling `unwrap`.
//!
-//! The suitability of `fail!` as an error handling mechanism is
+//! The suitability of `panic!` as an error handling mechanism is
//! limited by Rust's lack of any way to "catch" and resume execution
-//! from a thrown exception. Therefore using failure for error
-//! handling requires encapsulating fallible code in a task. Calling
-//! the `fail!` macro, or invoking `fail!` indirectly should be
-//! avoided as an error reporting strategy. Failure is only for
-//! unrecoverable errors and a failing task is typically the sign of
+//! from a thrown exception. Therefore using panics for error
+//! handling requires encapsulating code that may panic in a task.
+//! Calling the `panic!` macro, or invoking `panic!` indirectly should be
+//! avoided as an error reporting strategy. Panics is only for
+//! unrecoverable errors and a panicking task is typically the sign of
//! a bug.
//!
//! A module that instead returns `Results` is alerting the caller
-//! that failure is possible, and providing precise control over how
+//! that panics are possible, and providing precise control over how
//! it is handled.
//!
-//! Furthermore, failure may not be recoverable at all, depending on
-//! the context. The caller of `fail!` should assume that execution
-//! will not resume after failure, that failure is catastrophic.
+//! Furthermore, panics may not be recoverable at all, depending on
+//! the context. The caller of `panic!` should assume that execution
+//! will not resume after the panic, that a panic is catastrophic.
#![stable]
impl<T, E: Show> Result<T, E> {
/// Unwraps a result, yielding the content of an `Ok`.
///
- /// # Failure
+ /// # Panics
///
- /// Fails if the value is an `Err`, with a custom failure message provided
+ /// Panics if the value is an `Err`, with a custom panic message provided
/// by the `Err`'s value.
///
/// # Example
///
/// ```{.should_fail}
/// let x: Result<uint, &str> = Err("emergency failure");
- /// x.unwrap(); // fails with `emergency failure`
+ /// x.unwrap(); // panics with `emergency failure`
/// ```
#[inline]
#[unstable = "waiting for conventions"]
match self {
Ok(t) => t,
Err(e) =>
- fail!("called `Result::unwrap()` on an `Err` value: {}", e)
+ panic!("called `Result::unwrap()` on an `Err` value: {}", e)
}
}
}
impl<T: Show, E> Result<T, E> {
/// Unwraps a result, yielding the content of an `Err`.
///
- /// # Failure
+ /// # Panics
///
- /// Fails if the value is an `Ok`, with a custom failure message provided
+ /// Panics if the value is an `Ok`, with a custom panic message provided
/// by the `Ok`'s value.
///
/// # Example
///
/// ```{.should_fail}
/// let x: Result<uint, &str> = Ok(2u);
- /// x.unwrap_err(); // fails with `2`
+ /// x.unwrap_err(); // panics with `2`
/// ```
///
/// ```
pub fn unwrap_err(self) -> E {
match self {
Ok(t) =>
- fail!("called `Result::unwrap_err()` on an `Ok` value: {}", t),
+ panic!("called `Result::unwrap_err()` on an `Ok` value: {}", t),
Err(e) => e
}
}
use ptr::RawPtr;
use mem;
use mem::size_of;
-use kinds::marker;
+use kinds::{Sized, marker};
use raw::Repr;
// Avoid conflicts with *both* the Slice trait (buggy) and the `slice::raw` module.
use raw::Slice as RawSlice;
/// Extension methods for immutable slices.
#[unstable = "may merge with other traits; region parameter may disappear"]
-pub trait ImmutableSlice<'a, T> {
+pub trait ImmutableSlice<T> for Sized? {
/// Returns a subslice spanning the interval [`start`, `end`).
///
/// Fails when the end of the new slice lies beyond the end of the
///
/// Slicing with `start` equal to `end` yields an empty slice.
#[unstable = "waiting on final error conventions/slicing syntax"]
- fn slice(&self, start: uint, end: uint) -> &'a [T];
+ fn slice<'a>(&'a self, start: uint, end: uint) -> &'a [T];
/// Returns a subslice from `start` to the end of the slice.
///
///
/// Slicing from `self.len()` yields an empty slice.
#[unstable = "waiting on final error conventions/slicing syntax"]
- fn slice_from(&self, start: uint) -> &'a [T];
+ fn slice_from<'a>(&'a self, start: uint) -> &'a [T];
/// Returns a subslice from the start of the slice to `end`.
///
///
/// Slicing to `0` yields an empty slice.
#[unstable = "waiting on final error conventions/slicing syntax"]
- fn slice_to(&self, end: uint) -> &'a [T];
+ fn slice_to<'a>(&'a self, end: uint) -> &'a [T];
/// Divides one slice into two at an index.
///
///
/// Fails if `mid > len`.
#[unstable = "waiting on final error conventions"]
- fn split_at(&self, mid: uint) -> (&'a [T], &'a [T]);
+ fn split_at<'a>(&'a self, mid: uint) -> (&'a [T], &'a [T]);
/// Returns an iterator over the slice
#[unstable = "iterator type may change"]
- fn iter(self) -> Items<'a, T>;
+ fn iter<'a>(&'a self) -> Items<'a, T>;
/// Returns an iterator over subslices separated by elements that match
/// `pred`. The matched element is not contained in the subslices.
#[unstable = "iterator type may change, waiting on unboxed closures"]
- fn split(self, pred: |&T|: 'a -> bool) -> Splits<'a, T>;
+ fn split<'a>(&'a self, pred: |&T|: 'a -> bool) -> Splits<'a, T>;
/// Returns an iterator over subslices separated by elements that match
/// `pred`, limited to splitting at most `n` times. The matched element is
/// not contained in the subslices.
#[unstable = "iterator type may change"]
- fn splitn(self, n: uint, pred: |&T|: 'a -> bool) -> SplitsN<Splits<'a, T>>;
+ fn splitn<'a>(&'a self, n: uint, pred: |&T|: 'a -> bool) -> SplitsN<Splits<'a, T>>;
/// Returns an iterator over subslices separated by elements that match
/// `pred` limited to splitting at most `n` times. This starts at the end of
/// the slice and works backwards. The matched element is not contained in
/// the subslices.
#[unstable = "iterator type may change"]
- fn rsplitn(self, n: uint, pred: |&T|: 'a -> bool) -> SplitsN<Splits<'a, T>>;
+ fn rsplitn<'a>(&'a self, n: uint, pred: |&T|: 'a -> bool) -> SplitsN<Splits<'a, T>>;
/// Returns an iterator over all contiguous windows of length
/// `size`. The windows overlap. If the slice is shorter than
/// }
/// ```
#[unstable = "iterator type may change"]
- fn windows(self, size: uint) -> Windows<'a, T>;
+ fn windows<'a>(&'a self, size: uint) -> Windows<'a, T>;
/// Returns an iterator over `size` elements of the slice at a
/// time. The chunks do not overlap. If `size` does not divide the
/// }
/// ```
#[unstable = "iterator type may change"]
- fn chunks(self, size: uint) -> Chunks<'a, T>;
+ fn chunks<'a>(&'a self, size: uint) -> Chunks<'a, T>;
/// Returns the element of a slice at the given index, or `None` if the
/// index is out of bounds.
#[unstable = "waiting on final collection conventions"]
- fn get(&self, index: uint) -> Option<&'a T>;
+ fn get<'a>(&'a self, index: uint) -> Option<&'a T>;
/// Returns the first element of a slice, or `None` if it is empty.
#[unstable = "name may change"]
- fn head(&self) -> Option<&'a T>;
+ fn head<'a>(&'a self) -> Option<&'a T>;
/// Returns all but the first element of a slice.
#[unstable = "name may change"]
- fn tail(&self) -> &'a [T];
+ fn tail<'a>(&'a self) -> &'a [T];
/// Returns all but the last element of a slice.
#[unstable = "name may change"]
- fn init(&self) -> &'a [T];
+ fn init<'a>(&'a self) -> &'a [T];
/// Returns the last element of a slice, or `None` if it is empty.
#[unstable = "name may change"]
- fn last(&self) -> Option<&'a T>;
+ fn last<'a>(&'a self) -> Option<&'a T>;
/// Returns a pointer to the element at the given index, without doing
/// bounds checking.
#[unstable]
- unsafe fn unsafe_get(self, index: uint) -> &'a T;
+ unsafe fn unsafe_get<'a>(&'a self, index: uint) -> &'a T;
/// Returns an unsafe pointer to the slice's buffer
///
}
#[unstable]
-impl<'a,T> ImmutableSlice<'a, T> for &'a [T] {
+impl<T> ImmutableSlice<T> for [T] {
#[inline]
- fn slice(&self, start: uint, end: uint) -> &'a [T] {
+ fn slice(&self, start: uint, end: uint) -> &[T] {
assert!(start <= end);
assert!(end <= self.len());
unsafe {
}
#[inline]
- fn slice_from(&self, start: uint) -> &'a [T] {
+ fn slice_from(&self, start: uint) -> &[T] {
self.slice(start, self.len())
}
#[inline]
- fn slice_to(&self, end: uint) -> &'a [T] {
+ fn slice_to(&self, end: uint) -> &[T] {
self.slice(0, end)
}
#[inline]
- fn split_at(&self, mid: uint) -> (&'a [T], &'a [T]) {
- ((*self)[..mid], (*self)[mid..])
+ fn split_at(&self, mid: uint) -> (&[T], &[T]) {
+ (self[..mid], self[mid..])
}
#[inline]
- fn iter(self) -> Items<'a, T> {
+ fn iter<'a>(&'a self) -> Items<'a, T> {
unsafe {
let p = self.as_ptr();
if mem::size_of::<T>() == 0 {
}
#[inline]
- fn split(self, pred: |&T|: 'a -> bool) -> Splits<'a, T> {
+ fn split<'a>(&'a self, pred: |&T|: 'a -> bool) -> Splits<'a, T> {
Splits {
v: self,
pred: pred,
}
#[inline]
- fn splitn(self, n: uint, pred: |&T|: 'a -> bool) -> SplitsN<Splits<'a, T>> {
+ fn splitn<'a>(&'a self, n: uint, pred: |&T|: 'a -> bool) -> SplitsN<Splits<'a, T>> {
SplitsN {
iter: self.split(pred),
count: n,
}
#[inline]
- fn rsplitn(self, n: uint, pred: |&T|: 'a -> bool) -> SplitsN<Splits<'a, T>> {
+ fn rsplitn<'a>(&'a self, n: uint, pred: |&T|: 'a -> bool) -> SplitsN<Splits<'a, T>> {
SplitsN {
iter: self.split(pred),
count: n,
}
#[inline]
- fn windows(self, size: uint) -> Windows<'a, T> {
+ fn windows(&self, size: uint) -> Windows<T> {
assert!(size != 0);
Windows { v: self, size: size }
}
#[inline]
- fn chunks(self, size: uint) -> Chunks<'a, T> {
+ fn chunks(&self, size: uint) -> Chunks<T> {
assert!(size != 0);
Chunks { v: self, size: size }
}
#[inline]
- fn get(&self, index: uint) -> Option<&'a T> {
+ fn get(&self, index: uint) -> Option<&T> {
if index < self.len() { Some(&self[index]) } else { None }
}
#[inline]
- fn head(&self) -> Option<&'a T> {
+ fn head(&self) -> Option<&T> {
if self.len() == 0 { None } else { Some(&self[0]) }
}
#[inline]
- fn tail(&self) -> &'a [T] { (*self)[1..] }
+ fn tail(&self) -> &[T] { self[1..] }
#[inline]
- fn init(&self) -> &'a [T] {
- (*self)[..self.len() - 1]
+ fn init(&self) -> &[T] {
+ self[..self.len() - 1]
}
#[inline]
- fn last(&self) -> Option<&'a T> {
+ fn last(&self) -> Option<&T> {
if self.len() == 0 { None } else { Some(&self[self.len() - 1]) }
}
#[inline]
- unsafe fn unsafe_get(self, index: uint) -> &'a T {
+ unsafe fn unsafe_get(&self, index: uint) -> &T {
transmute(self.repr().data.offset(index as int))
}
/// Extension methods for slices such that their elements are
/// mutable.
#[experimental = "may merge with other traits; may lose region param; needs review"]
-pub trait MutableSlice<'a, T> {
+pub trait MutableSlice<T> for Sized? {
/// Returns a mutable reference to the element at the given index,
/// or `None` if the index is out of bounds
#[unstable = "waiting on final error conventions"]
- fn get_mut(self, index: uint) -> Option<&'a mut T>;
+ fn get_mut<'a>(&'a mut self, index: uint) -> Option<&'a mut T>;
/// Work with `self` as a mut slice.
/// Primarily intended for getting a &mut [T] from a [T, ..N].
- fn as_mut_slice(self) -> &'a mut [T];
+ fn as_mut_slice<'a>(&'a mut self) -> &'a mut [T];
/// Returns a mutable subslice spanning the interval [`start`, `end`).
///
///
/// Slicing with `start` equal to `end` yields an empty slice.
#[unstable = "waiting on final error conventions"]
- fn slice_mut(self, start: uint, end: uint) -> &'a mut [T];
+ fn slice_mut<'a>(&'a mut self, start: uint, end: uint) -> &'a mut [T];
/// Returns a mutable subslice from `start` to the end of the slice.
///
///
/// Slicing from `self.len()` yields an empty slice.
#[unstable = "waiting on final error conventions"]
- fn slice_from_mut(self, start: uint) -> &'a mut [T];
+ fn slice_from_mut<'a>(&'a mut self, start: uint) -> &'a mut [T];
/// Returns a mutable subslice from the start of the slice to `end`.
///
///
/// Slicing to `0` yields an empty slice.
#[unstable = "waiting on final error conventions"]
- fn slice_to_mut(self, end: uint) -> &'a mut [T];
+ fn slice_to_mut<'a>(&'a mut self, end: uint) -> &'a mut [T];
/// Returns an iterator that allows modifying each value
#[unstable = "waiting on iterator type name conventions"]
- fn iter_mut(self) -> MutItems<'a, T>;
+ fn iter_mut<'a>(&'a mut self) -> MutItems<'a, T>;
/// Returns a mutable pointer to the first element of a slice, or `None` if it is empty
#[unstable = "name may change"]
- fn head_mut(self) -> Option<&'a mut T>;
+ fn head_mut<'a>(&'a mut self) -> Option<&'a mut T>;
/// Returns all but the first element of a mutable slice
#[unstable = "name may change"]
- fn tail_mut(self) -> &'a mut [T];
+ fn tail_mut<'a>(&'a mut self) -> &'a mut [T];
/// Returns all but the last element of a mutable slice
#[unstable = "name may change"]
- fn init_mut(self) -> &'a mut [T];
+ fn init_mut<'a>(&'a mut self) -> &'a mut [T];
/// Returns a mutable pointer to the last item in the slice.
#[unstable = "name may change"]
- fn last_mut(self) -> Option<&'a mut T>;
+ fn last_mut<'a>(&'a mut self) -> Option<&'a mut T>;
/// Returns an iterator over mutable subslices separated by elements that
/// match `pred`. The matched element is not contained in the subslices.
#[unstable = "waiting on unboxed closures, iterator type name conventions"]
- fn split_mut(self, pred: |&T|: 'a -> bool) -> MutSplits<'a, T>;
+ fn split_mut<'a>(&'a mut self, pred: |&T|: 'a -> bool) -> MutSplits<'a, T>;
/// Returns an iterator over subslices separated by elements that match
/// `pred`, limited to splitting at most `n` times. The matched element is
/// not contained in the subslices.
#[unstable = "waiting on unboxed closures, iterator type name conventions"]
- fn splitn_mut(self, n: uint, pred: |&T|: 'a -> bool) -> SplitsN<MutSplits<'a, T>>;
+ fn splitn_mut<'a>(&'a mut self, n: uint, pred: |&T|: 'a -> bool) -> SplitsN<MutSplits<'a, T>>;
/// Returns an iterator over subslices separated by elements that match
/// `pred` limited to splitting at most `n` times. This starts at the end of
/// the slice and works backwards. The matched element is not contained in
/// the subslices.
#[unstable = "waiting on unboxed closures, iterator type name conventions"]
- fn rsplitn_mut(self, n: uint, pred: |&T|: 'a -> bool) -> SplitsN<MutSplits<'a, T>>;
+ fn rsplitn_mut<'a>(&'a mut self, n: uint, pred: |&T|: 'a -> bool) -> SplitsN<MutSplits<'a, T>>;
/// Returns an iterator over `chunk_size` elements of the slice at a time.
/// The chunks are mutable and do not overlap. If `chunk_size` does
///
/// Fails if `chunk_size` is 0.
#[unstable = "waiting on iterator type name conventions"]
- fn chunks_mut(self, chunk_size: uint) -> MutChunks<'a, T>;
+ fn chunks_mut<'a>(&'a mut self, chunk_size: uint) -> MutChunks<'a, T>;
/// Swaps two elements in a slice.
///
/// assert!(v == ["a", "d", "c", "b"]);
/// ```
#[unstable = "waiting on final error conventions"]
- fn swap(self, a: uint, b: uint);
+ fn swap(&mut self, a: uint, b: uint);
/// Divides one `&mut` into two at an index.
///
/// }
/// ```
#[unstable = "waiting on final error conventions"]
- fn split_at_mut(self, mid: uint) -> (&'a mut [T], &'a mut [T]);
+ fn split_at_mut<'a>(&'a mut self, mid: uint) -> (&'a mut [T], &'a mut [T]);
/// Reverse the order of elements in a slice, in place.
///
/// assert!(v == [3i, 2, 1]);
/// ```
#[experimental = "may be moved to iterators instead"]
- fn reverse(self);
+ fn reverse(&mut self);
/// Returns an unsafe mutable pointer to the element in index
#[experimental = "waiting on unsafe conventions"]
- unsafe fn unsafe_mut(self, index: uint) -> &'a mut T;
+ unsafe fn unsafe_mut<'a>(&'a mut self, index: uint) -> &'a mut T;
/// Return an unsafe mutable pointer to the slice's buffer.
///
/// would also make any pointers to it invalid.
#[inline]
#[unstable]
- fn as_mut_ptr(self) -> *mut T;
+ fn as_mut_ptr(&mut self) -> *mut T;
}
#[experimental = "trait is experimental"]
-impl<'a,T> MutableSlice<'a, T> for &'a mut [T] {
+impl<T> MutableSlice<T> for [T] {
#[inline]
- fn get_mut(self, index: uint) -> Option<&'a mut T> {
+ fn get_mut(&mut self, index: uint) -> Option<&mut T> {
if index < self.len() { Some(&mut self[index]) } else { None }
}
#[inline]
- fn as_mut_slice(self) -> &'a mut [T] { self }
+ fn as_mut_slice(&mut self) -> &mut [T] { self }
- fn slice_mut(self, start: uint, end: uint) -> &'a mut [T] {
+ fn slice_mut(&mut self, start: uint, end: uint) -> &mut [T] {
self[mut start..end]
}
#[inline]
- fn slice_from_mut(self, start: uint) -> &'a mut [T] {
+ fn slice_from_mut(&mut self, start: uint) -> &mut [T] {
self[mut start..]
}
#[inline]
- fn slice_to_mut(self, end: uint) -> &'a mut [T] {
+ fn slice_to_mut(&mut self, end: uint) -> &mut [T] {
self[mut ..end]
}
#[inline]
- fn split_at_mut(self, mid: uint) -> (&'a mut [T], &'a mut [T]) {
+ fn split_at_mut(&mut self, mid: uint) -> (&mut [T], &mut [T]) {
unsafe {
- let self2: &'a mut [T] = mem::transmute_copy(&self);
+ let self2: &mut [T] = mem::transmute_copy(&self);
(self[mut ..mid], self2[mut mid..])
}
}
#[inline]
- fn iter_mut(self) -> MutItems<'a, T> {
+ fn iter_mut<'a>(&'a mut self) -> MutItems<'a, T> {
unsafe {
let p = self.as_mut_ptr();
if mem::size_of::<T>() == 0 {
}
#[inline]
- fn last_mut(self) -> Option<&'a mut T> {
+ fn last_mut(&mut self) -> Option<&mut T> {
let len = self.len();
if len == 0 { return None; }
Some(&mut self[len - 1])
}
#[inline]
- fn head_mut(self) -> Option<&'a mut T> {
+ fn head_mut(&mut self) -> Option<&mut T> {
if self.len() == 0 { None } else { Some(&mut self[0]) }
}
#[inline]
- fn tail_mut(self) -> &'a mut [T] {
+ fn tail_mut(&mut self) -> &mut [T] {
let len = self.len();
self[mut 1..len]
}
#[inline]
- fn init_mut(self) -> &'a mut [T] {
+ fn init_mut(&mut self) -> &mut [T] {
let len = self.len();
self[mut 0..len - 1]
}
#[inline]
- fn split_mut(self, pred: |&T|: 'a -> bool) -> MutSplits<'a, T> {
+ fn split_mut<'a>(&'a mut self, pred: |&T|: 'a -> bool) -> MutSplits<'a, T> {
MutSplits { v: self, pred: pred, finished: false }
}
#[inline]
- fn splitn_mut(self, n: uint, pred: |&T|: 'a -> bool) -> SplitsN<MutSplits<'a, T>> {
+ fn splitn_mut<'a>(&'a mut self, n: uint, pred: |&T|: 'a -> bool) -> SplitsN<MutSplits<'a, T>> {
SplitsN {
iter: self.split_mut(pred),
count: n,
}
#[inline]
- fn rsplitn_mut(self, n: uint, pred: |&T|: 'a -> bool) -> SplitsN<MutSplits<'a, T>> {
+ fn rsplitn_mut<'a>(&'a mut self, n: uint, pred: |&T|: 'a -> bool) -> SplitsN<MutSplits<'a, T>> {
SplitsN {
iter: self.split_mut(pred),
count: n,
}
#[inline]
- fn chunks_mut(self, chunk_size: uint) -> MutChunks<'a, T> {
+ fn chunks_mut(&mut self, chunk_size: uint) -> MutChunks<T> {
assert!(chunk_size > 0);
MutChunks { v: self, chunk_size: chunk_size }
}
- fn swap(self, a: uint, b: uint) {
+ fn swap(&mut self, a: uint, b: uint) {
unsafe {
// Can't take two mutable loans from one vector, so instead just cast
// them to their raw pointers to do the swap
}
}
- fn reverse(self) {
+ fn reverse(&mut self) {
let mut i: uint = 0;
let ln = self.len();
while i < ln / 2 {
}
#[inline]
- unsafe fn unsafe_mut(self, index: uint) -> &'a mut T {
+ unsafe fn unsafe_mut(&mut self, index: uint) -> &mut T {
transmute((self.repr().data as *mut T).offset(index as int))
}
#[inline]
- fn as_mut_ptr(self) -> *mut T {
+ fn as_mut_ptr(&mut self) -> *mut T {
self.repr().data as *mut T
}
}
/// Extension methods for slices containing `PartialEq` elements.
#[unstable = "may merge with other traits"]
-pub trait ImmutablePartialEqSlice<T:PartialEq> {
+pub trait ImmutablePartialEqSlice<T: PartialEq> for Sized? {
/// Find the first index containing a matching value.
fn position_elem(&self, t: &T) -> Option<uint>;
}
#[unstable = "trait is unstable"]
-impl<'a,T:PartialEq> ImmutablePartialEqSlice<T> for &'a [T] {
+impl<T: PartialEq> ImmutablePartialEqSlice<T> for [T] {
#[inline]
fn position_elem(&self, x: &T) -> Option<uint> {
self.iter().position(|y| *x == *y)
#[inline]
fn starts_with(&self, needle: &[T]) -> bool {
let n = needle.len();
- self.len() >= n && needle == (*self)[..n]
+ self.len() >= n && needle == self[..n]
}
#[inline]
fn ends_with(&self, needle: &[T]) -> bool {
let (m, n) = (self.len(), needle.len());
- m >= n && needle == (*self)[m-n..]
+ m >= n && needle == self[m-n..]
}
}
/// Extension methods for slices containing `Ord` elements.
#[unstable = "may merge with other traits"]
-pub trait ImmutableOrdSlice<T: Ord> {
+pub trait ImmutableOrdSlice<T: Ord> for Sized? {
/// Binary search a sorted slice for a given element.
///
/// If the value is found then `Found` is returned, containing the
}
#[unstable = "trait is unstable"]
-impl<'a, T: Ord> ImmutableOrdSlice<T> for &'a [T] {
+impl<T: Ord> ImmutableOrdSlice<T> for [T] {
#[unstable]
fn binary_search_elem(&self, x: &T) -> BinarySearchResult {
self.binary_search(|p| p.cmp(x))
/// Trait for &[T] where T is Cloneable
#[unstable = "may merge with other traits"]
-pub trait MutableCloneableSlice<T> {
+pub trait MutableCloneableSlice<T> for Sized? {
/// Copies as many elements from `src` as it can into `self` (the
/// shorter of `self.len()` and `src.len()`). Returns the number
/// of elements copied.
/// assert!(dst.clone_from_slice(src2) == 3);
/// assert!(dst == [3i, 4, 5]);
/// ```
- fn clone_from_slice(self, &[T]) -> uint;
+ fn clone_from_slice(&mut self, &[T]) -> uint;
}
#[unstable = "trait is unstable"]
-impl<'a, T: Clone> MutableCloneableSlice<T> for &'a mut [T] {
+impl<T: Clone> MutableCloneableSlice<T> for [T] {
#[inline]
- fn clone_from_slice(self, src: &[T]) -> uint {
+ fn clone_from_slice(&mut self, src: &[T]) -> uint {
let min = cmp::min(self.len(), src.len());
let dst = self.slice_to_mut(min);
let src = src.slice_to(min);
#[experimental = "needs review"]
pub mod bytes {
use collections::Collection;
+ use kinds::Sized;
use ptr;
use slice::{ImmutableSlice, MutableSlice};
/// A trait for operations on mutable `[u8]`s.
- pub trait MutableByteVector {
+ pub trait MutableByteVector for Sized? {
/// Sets all bytes of the receiver to the given value.
- fn set_memory(self, value: u8);
+ fn set_memory(&mut self, value: u8);
}
- impl<'a> MutableByteVector for &'a mut [u8] {
+ impl MutableByteVector for [u8] {
#[inline]
#[allow(experimental)]
- fn set_memory(self, value: u8) {
+ fn set_memory(&mut self, value: u8) {
unsafe { ptr::set_memory(self.as_mut_ptr(), value, self.len()) };
}
}
/// Extension methods for immutable slices containing integers.
#[experimental]
-pub trait ImmutableIntSlice<'a, U, S> {
+pub trait ImmutableIntSlice<U, S> for Sized? {
/// Converts the slice to an immutable slice of unsigned integers with the same width.
- fn as_unsigned(self) -> &'a [U];
+ fn as_unsigned<'a>(&'a self) -> &'a [U];
/// Converts the slice to an immutable slice of signed integers with the same width.
- fn as_signed(self) -> &'a [S];
+ fn as_signed<'a>(&'a self) -> &'a [S];
}
/// Extension methods for mutable slices containing integers.
#[experimental]
-pub trait MutableIntSlice<'a, U, S>: ImmutableIntSlice<'a, U, S> {
+pub trait MutableIntSlice<U, S> for Sized?: ImmutableIntSlice<U, S> {
/// Converts the slice to a mutable slice of unsigned integers with the same width.
- fn as_unsigned_mut(self) -> &'a mut [U];
+ fn as_unsigned_mut<'a>(&'a mut self) -> &'a mut [U];
/// Converts the slice to a mutable slice of signed integers with the same width.
- fn as_signed_mut(self) -> &'a mut [S];
+ fn as_signed_mut<'a>(&'a mut self) -> &'a mut [S];
}
macro_rules! impl_immut_int_slice {
($u:ty, $s:ty, $t:ty) => {
#[experimental]
- impl<'a> ImmutableIntSlice<'a, $u, $s> for $t {
+ impl ImmutableIntSlice<$u, $s> for [$t] {
#[inline]
- fn as_unsigned(self) -> &'a [$u] { unsafe { transmute(self) } }
+ fn as_unsigned(&self) -> &[$u] { unsafe { transmute(self) } }
#[inline]
- fn as_signed(self) -> &'a [$s] { unsafe { transmute(self) } }
+ fn as_signed(&self) -> &[$s] { unsafe { transmute(self) } }
}
}
}
macro_rules! impl_mut_int_slice {
($u:ty, $s:ty, $t:ty) => {
#[experimental]
- impl<'a> MutableIntSlice<'a, $u, $s> for $t {
+ impl MutableIntSlice<$u, $s> for [$t] {
#[inline]
- fn as_unsigned_mut(self) -> &'a mut [$u] { unsafe { transmute(self) } }
+ fn as_unsigned_mut(&mut self) -> &mut [$u] { unsafe { transmute(self) } }
#[inline]
- fn as_signed_mut(self) -> &'a mut [$s] { unsafe { transmute(self) } }
+ fn as_signed_mut(&mut self) -> &mut [$s] { unsafe { transmute(self) } }
}
}
}
macro_rules! impl_int_slice {
($u:ty, $s:ty) => {
- impl_immut_int_slice!($u, $s, &'a [$u])
- impl_immut_int_slice!($u, $s, &'a [$s])
- impl_immut_int_slice!($u, $s, &'a mut [$u])
- impl_immut_int_slice!($u, $s, &'a mut [$s])
- impl_mut_int_slice!($u, $s, &'a mut [$u])
- impl_mut_int_slice!($u, $s, &'a mut [$s])
+ impl_immut_int_slice!($u, $s, $u)
+ impl_immut_int_slice!($u, $s, $s)
+ impl_mut_int_slice!($u, $s, $u)
+ impl_mut_int_slice!($u, $s, $s)
}
}
use iter::{Map, Iterator};
use iter::{DoubleEndedIterator, ExactSize};
use iter::range;
+use kinds::Sized;
use num::{CheckedMul, Saturating};
use option::{Option, None, Some};
use raw::Repr;
}
/// Methods for string slices
-pub trait StrSlice<'a> {
+pub trait StrSlice for Sized? {
/// Returns true if one string contains another
///
/// # Arguments
/// ```rust
/// assert!("bananas".contains("nana"));
/// ```
- fn contains<'a>(&self, needle: &'a str) -> bool;
+ fn contains(&self, needle: &str) -> bool;
/// Returns true if a string contains a char.
///
/// let v: Vec<char> = "abc åäö".chars().collect();
/// assert_eq!(v, vec!['a', 'b', 'c', ' ', 'å', 'ä', 'ö']);
/// ```
- fn chars(&self) -> Chars<'a>;
+ fn chars<'a>(&'a self) -> Chars<'a>;
/// An iterator over the bytes of `self`
///
/// let v: Vec<u8> = "bors".bytes().collect();
/// assert_eq!(v, b"bors".to_vec());
/// ```
- fn bytes(&self) -> Bytes<'a>;
+ fn bytes<'a>(&'a self) -> Bytes<'a>;
/// An iterator over the characters of `self` and their byte offsets.
- fn char_indices(&self) -> CharOffsets<'a>;
+ fn char_indices<'a>(&'a self) -> CharOffsets<'a>;
/// An iterator over substrings of `self`, separated by characters
/// matched by `sep`.
/// let v: Vec<&str> = "".split('X').collect();
/// assert_eq!(v, vec![""]);
/// ```
- fn split<Sep: CharEq>(&self, sep: Sep) -> CharSplits<'a, Sep>;
+ fn split<'a, Sep: CharEq>(&'a self, sep: Sep) -> CharSplits<'a, Sep>;
/// An iterator over substrings of `self`, separated by characters
/// matched by `sep`, restricted to splitting at most `count`
/// let v: Vec<&str> = "".splitn(1, 'X').collect();
/// assert_eq!(v, vec![""]);
/// ```
- fn splitn<Sep: CharEq>(&self, count: uint, sep: Sep) -> CharSplitsN<'a, Sep>;
+ fn splitn<'a, Sep: CharEq>(&'a self, count: uint, sep: Sep) -> CharSplitsN<'a, Sep>;
/// An iterator over substrings of `self`, separated by characters
/// matched by `sep`.
/// let v: Vec<&str> = "lionXXtigerXleopard".split('X').rev().collect();
/// assert_eq!(v, vec!["leopard", "tiger", "", "lion"]);
/// ```
- fn split_terminator<Sep: CharEq>(&self, sep: Sep) -> CharSplits<'a, Sep>;
+ fn split_terminator<'a, Sep: CharEq>(&'a self, sep: Sep) -> CharSplits<'a, Sep>;
/// An iterator over substrings of `self`, separated by characters
/// matched by `sep`, starting from the end of the string.
/// let v: Vec<&str> = "lionXXtigerXleopard".rsplitn(2, 'X').collect();
/// assert_eq!(v, vec!["leopard", "tiger", "lionX"]);
/// ```
- fn rsplitn<Sep: CharEq>(&self, count: uint, sep: Sep) -> CharSplitsN<'a, Sep>;
+ fn rsplitn<'a, Sep: CharEq>(&'a self, count: uint, sep: Sep) -> CharSplitsN<'a, Sep>;
/// An iterator over the start and end indices of the disjoint
/// matches of `sep` within `self`.
/// let v: Vec<(uint, uint)> = "ababa".match_indices("aba").collect();
/// assert_eq!(v, vec![(0, 3)]); // only the first `aba`
/// ```
- fn match_indices(&self, sep: &'a str) -> MatchIndices<'a>;
+ fn match_indices<'a>(&'a self, sep: &'a str) -> MatchIndices<'a>;
/// An iterator over the substrings of `self` separated by `sep`.
///
/// let v: Vec<&str> = "1abcabc2".split_str("abc").collect();
/// assert_eq!(v, vec!["1", "", "2"]);
/// ```
- fn split_str(&self, &'a str) -> StrSplits<'a>;
+ fn split_str<'a>(&'a self, &'a str) -> StrSplits<'a>;
/// An iterator over the lines of a string (subsequences separated
/// by `\n`). This does not include the empty string after a
/// let v: Vec<&str> = four_lines.lines().collect();
/// assert_eq!(v, vec!["foo", "bar", "", "baz"]);
/// ```
- fn lines(&self) -> CharSplits<'a, char>;
+ fn lines<'a>(&'a self) -> CharSplits<'a, char>;
/// An iterator over the lines of a string, separated by either
/// `\n` or `\r\n`. As with `.lines()`, this does not include an
/// let v: Vec<&str> = four_lines.lines_any().collect();
/// assert_eq!(v, vec!["foo", "bar", "", "baz"]);
/// ```
- fn lines_any(&self) -> AnyLines<'a>;
+ fn lines_any<'a>(&'a self) -> AnyLines<'a>;
/// Returns the number of Unicode code points (`char`) that a
/// string holds.
///
/// assert_eq!(s.slice(1, 9), "öwe 老");
///
- /// // these will fail:
+ /// // these will panic:
/// // byte 2 lies within `ö`:
/// // s.slice(2, 3);
///
/// // byte 100 is outside the string
/// // s.slice(3, 100);
/// ```
- fn slice(&self, begin: uint, end: uint) -> &'a str;
+ fn slice<'a>(&'a self, begin: uint, end: uint) -> &'a str;
/// Returns a slice of the string from `begin` to its end.
///
/// out of bounds.
///
/// See also `slice`, `slice_to` and `slice_chars`.
- fn slice_from(&self, begin: uint) -> &'a str;
+ fn slice_from<'a>(&'a self, begin: uint) -> &'a str;
/// Returns a slice of the string from the beginning to byte
/// `end`.
/// out of bounds.
///
/// See also `slice`, `slice_from` and `slice_chars`.
- fn slice_to(&self, end: uint) -> &'a str;
+ fn slice_to<'a>(&'a self, end: uint) -> &'a str;
/// Returns a slice of the string from the character range
/// [`begin`..`end`).
/// assert_eq!(s.slice_chars(0, 4), "Löwe");
/// assert_eq!(s.slice_chars(5, 7), "老虎");
/// ```
- fn slice_chars(&self, begin: uint, end: uint) -> &'a str;
+ fn slice_chars<'a>(&'a self, begin: uint, end: uint) -> &'a str;
/// Returns true if `needle` is a prefix of the string.
///
/// assert_eq!("12foo1bar12".trim_chars(x), "foo1bar")
/// assert_eq!("123foo1bar123".trim_chars(|c: char| c.is_digit()), "foo1bar")
/// ```
- fn trim_chars<C: CharEq>(&self, to_trim: C) -> &'a str;
+ fn trim_chars<'a, C: CharEq>(&'a self, to_trim: C) -> &'a str;
/// Returns a string with leading `chars_to_trim` removed.
///
/// assert_eq!("12foo1bar12".trim_left_chars(x), "foo1bar12")
/// assert_eq!("123foo1bar123".trim_left_chars(|c: char| c.is_digit()), "foo1bar123")
/// ```
- fn trim_left_chars<C: CharEq>(&self, to_trim: C) -> &'a str;
+ fn trim_left_chars<'a, C: CharEq>(&'a self, to_trim: C) -> &'a str;
/// Returns a string with trailing `chars_to_trim` removed.
///
/// assert_eq!("12foo1bar12".trim_right_chars(x), "12foo1bar")
/// assert_eq!("123foo1bar123".trim_right_chars(|c: char| c.is_digit()), "123foo1bar")
/// ```
- fn trim_right_chars<C: CharEq>(&self, to_trim: C) -> &'a str;
+ fn trim_right_chars<'a, C: CharEq>(&'a self, to_trim: C) -> &'a str;
/// Check that `index`-th byte lies at the start and/or end of a
/// UTF-8 code point sequence.
/// ```rust
/// assert_eq!("bors".as_bytes(), b"bors");
/// ```
- fn as_bytes(&self) -> &'a [u8];
+ fn as_bytes<'a>(&'a self) -> &'a [u8];
/// Returns the byte index of the first character of `self` that
/// matches `search`.
/// assert_eq!(c, Some('ö'));
/// assert_eq!(s2, "we 老虎 Léopard");
/// ```
- fn slice_shift_char(&self) -> (Option<char>, &'a str);
+ fn slice_shift_char<'a>(&'a self) -> (Option<char>, &'a str);
/// Returns the byte offset of an inner slice relative to an enclosing outer slice.
///
fn as_ptr(&self) -> *const u8;
/// Return an iterator of `u16` over the string encoded as UTF-16.
- fn utf16_units(&self) -> Utf16CodeUnits<'a>;
+ fn utf16_units<'a>(&'a self) -> Utf16CodeUnits<'a>;
}
#[inline(never)]
fn slice_error_fail(s: &str, begin: uint, end: uint) -> ! {
assert!(begin <= end);
- fail!("index {} and/or {} in `{}` do not lie on character boundary",
+ panic!("index {} and/or {} in `{}` do not lie on character boundary",
begin, end, s);
}
-impl<'a> StrSlice<'a> for &'a str {
+impl StrSlice for str {
#[inline]
- fn contains<'a>(&self, needle: &'a str) -> bool {
+ fn contains(&self, needle: &str) -> bool {
self.find_str(needle).is_some()
}
}
#[inline]
- fn chars(&self) -> Chars<'a> {
+ fn chars(&self) -> Chars {
Chars{iter: self.as_bytes().iter()}
}
#[inline]
- fn bytes(&self) -> Bytes<'a> {
+ fn bytes(&self) -> Bytes {
self.as_bytes().iter().map(|&b| b)
}
#[inline]
- fn char_indices(&self) -> CharOffsets<'a> {
+ fn char_indices(&self) -> CharOffsets {
CharOffsets{front_offset: 0, iter: self.chars()}
}
#[inline]
- fn split<Sep: CharEq>(&self, sep: Sep) -> CharSplits<'a, Sep> {
+ fn split<Sep: CharEq>(&self, sep: Sep) -> CharSplits<Sep> {
CharSplits {
- string: *self,
+ string: self,
only_ascii: sep.only_ascii(),
sep: sep,
allow_trailing_empty: true,
#[inline]
fn splitn<Sep: CharEq>(&self, count: uint, sep: Sep)
- -> CharSplitsN<'a, Sep> {
+ -> CharSplitsN<Sep> {
CharSplitsN {
iter: self.split(sep),
count: count,
#[inline]
fn split_terminator<Sep: CharEq>(&self, sep: Sep)
- -> CharSplits<'a, Sep> {
+ -> CharSplits<Sep> {
CharSplits {
allow_trailing_empty: false,
..self.split(sep)
#[inline]
fn rsplitn<Sep: CharEq>(&self, count: uint, sep: Sep)
- -> CharSplitsN<'a, Sep> {
+ -> CharSplitsN<Sep> {
CharSplitsN {
iter: self.split(sep),
count: count,
}
#[inline]
- fn match_indices(&self, sep: &'a str) -> MatchIndices<'a> {
+ fn match_indices<'a>(&'a self, sep: &'a str) -> MatchIndices<'a> {
assert!(!sep.is_empty())
MatchIndices {
- haystack: *self,
+ haystack: self,
needle: sep,
searcher: Searcher::new(self.as_bytes(), sep.as_bytes())
}
}
#[inline]
- fn split_str(&self, sep: &'a str) -> StrSplits<'a> {
+ fn split_str<'a>(&'a self, sep: &'a str) -> StrSplits<'a> {
StrSplits {
it: self.match_indices(sep),
last_end: 0,
}
#[inline]
- fn lines(&self) -> CharSplits<'a, char> {
+ fn lines(&self) -> CharSplits<char> {
self.split_terminator('\n')
}
- fn lines_any(&self) -> AnyLines<'a> {
+ fn lines_any(&self) -> AnyLines {
self.lines().map(|line| {
let l = line.len();
if l > 0 && line.as_bytes()[l - 1] == b'\r' { line.slice(0, l - 1) }
fn char_len(&self) -> uint { self.chars().count() }
#[inline]
- fn slice(&self, begin: uint, end: uint) -> &'a str {
+ fn slice(&self, begin: uint, end: uint) -> &str {
// is_char_boundary checks that the index is in [0, .len()]
if begin <= end &&
self.is_char_boundary(begin) &&
self.is_char_boundary(end) {
- unsafe { raw::slice_unchecked(*self, begin, end) }
+ unsafe { raw::slice_unchecked(self, begin, end) }
} else {
- slice_error_fail(*self, begin, end)
+ slice_error_fail(self, begin, end)
}
}
#[inline]
- fn slice_from(&self, begin: uint) -> &'a str {
+ fn slice_from(&self, begin: uint) -> &str {
// is_char_boundary checks that the index is in [0, .len()]
if self.is_char_boundary(begin) {
- unsafe { raw::slice_unchecked(*self, begin, self.len()) }
+ unsafe { raw::slice_unchecked(self, begin, self.len()) }
} else {
- slice_error_fail(*self, begin, self.len())
+ slice_error_fail(self, begin, self.len())
}
}
#[inline]
- fn slice_to(&self, end: uint) -> &'a str {
+ fn slice_to(&self, end: uint) -> &str {
// is_char_boundary checks that the index is in [0, .len()]
if self.is_char_boundary(end) {
- unsafe { raw::slice_unchecked(*self, 0, end) }
+ unsafe { raw::slice_unchecked(self, 0, end) }
} else {
- slice_error_fail(*self, 0, end)
+ slice_error_fail(self, 0, end)
}
}
- fn slice_chars(&self, begin: uint, end: uint) -> &'a str {
+ fn slice_chars(&self, begin: uint, end: uint) -> &str {
assert!(begin <= end);
let mut count = 0;
let mut begin_byte = None;
if end_byte.is_none() && count == end { end_byte = Some(self.len()) }
match (begin_byte, end_byte) {
- (None, _) => fail!("slice_chars: `begin` is beyond end of string"),
- (_, None) => fail!("slice_chars: `end` is beyond end of string"),
- (Some(a), Some(b)) => unsafe { raw::slice_bytes(*self, a, b) }
+ (None, _) => panic!("slice_chars: `begin` is beyond end of string"),
+ (_, None) => panic!("slice_chars: `end` is beyond end of string"),
+ (Some(a), Some(b)) => unsafe { raw::slice_bytes(self, a, b) }
}
}
#[inline]
- fn starts_with<'a>(&self, needle: &'a str) -> bool {
+ fn starts_with(&self, needle: &str) -> bool {
let n = needle.len();
self.len() >= n && needle.as_bytes() == self.as_bytes()[..n]
}
}
#[inline]
- fn trim_chars<C: CharEq>(&self, mut to_trim: C) -> &'a str {
+ fn trim_chars<C: CharEq>(&self, mut to_trim: C) -> &str {
let cur = match self.find(|c: char| !to_trim.matches(c)) {
None => "",
- Some(i) => unsafe { raw::slice_bytes(*self, i, self.len()) }
+ Some(i) => unsafe { raw::slice_bytes(self, i, self.len()) }
};
match cur.rfind(|c: char| !to_trim.matches(c)) {
None => "",
}
#[inline]
- fn trim_left_chars<C: CharEq>(&self, mut to_trim: C) -> &'a str {
+ fn trim_left_chars<C: CharEq>(&self, mut to_trim: C) -> &str {
match self.find(|c: char| !to_trim.matches(c)) {
None => "",
- Some(first) => unsafe { raw::slice_bytes(*self, first, self.len()) }
+ Some(first) => unsafe { raw::slice_bytes(self, first, self.len()) }
}
}
#[inline]
- fn trim_right_chars<C: CharEq>(&self, mut to_trim: C) -> &'a str {
+ fn trim_right_chars<C: CharEq>(&self, mut to_trim: C) -> &str {
match self.rfind(|c: char| !to_trim.matches(c)) {
None => "",
Some(last) => {
let next = self.char_range_at(last).next;
- unsafe { raw::slice_bytes(*self, 0u, next) }
+ unsafe { raw::slice_bytes(self, 0u, next) }
}
}
}
return CharRange {ch: unsafe { mem::transmute(val) }, next: i + w};
}
- return multibyte_char_range_at(*self, i);
+ return multibyte_char_range_at(self, i);
}
#[inline]
return CharRange {ch: unsafe { mem::transmute(val) }, next: i};
}
- return multibyte_char_range_at_reverse(*self, prev);
+ return multibyte_char_range_at_reverse(self, prev);
}
#[inline]
}
#[inline]
- fn as_bytes(&self) -> &'a [u8] {
- unsafe { mem::transmute(*self) }
+ fn as_bytes(&self) -> &[u8] {
+ unsafe { mem::transmute(self) }
}
fn find<C: CharEq>(&self, mut search: C) -> Option<uint> {
}
#[inline]
- fn slice_shift_char(&self) -> (Option<char>, &'a str) {
+ fn slice_shift_char(&self) -> (Option<char>, &str) {
if self.is_empty() {
- return (None, *self);
+ return (None, self);
} else {
let CharRange {ch, next} = self.char_range_at(0u);
- let next_s = unsafe { raw::slice_bytes(*self, next, self.len()) };
+ let next_s = unsafe { raw::slice_bytes(self, next, self.len()) };
return (Some(ch), next_s);
}
}
}
#[inline]
- fn utf16_units(&self) -> Utf16CodeUnits<'a> {
+ fn utf16_units(&self) -> Utf16CodeUnits {
Utf16CodeUnits{ chars: self.chars(), extra: 0}
}
}
match a.downcast_ref::<uint>() {
Some(&5) => {}
- x => fail!("Unexpected value {}", x)
+ x => panic!("Unexpected value {}", x)
}
match a.downcast_ref::<Test>() {
None => {}
- x => fail!("Unexpected value {}", x)
+ x => panic!("Unexpected value {}", x)
}
}
assert_eq!(*x, 5u);
*x = 612;
}
- x => fail!("Unexpected value {}", x)
+ x => panic!("Unexpected value {}", x)
}
match b_r.downcast_mut::<uint>() {
assert_eq!(*x, 7u);
*x = 413;
}
- x => fail!("Unexpected value {}", x)
+ x => panic!("Unexpected value {}", x)
}
match a_r.downcast_mut::<Test>() {
None => (),
- x => fail!("Unexpected value {}", x)
+ x => panic!("Unexpected value {}", x)
}
match b_r.downcast_mut::<Test>() {
None => (),
- x => fail!("Unexpected value {}", x)
+ x => panic!("Unexpected value {}", x)
}
match a_r.downcast_mut::<uint>() {
Some(&612) => {}
- x => fail!("Unexpected value {}", x)
+ x => panic!("Unexpected value {}", x)
}
match b_r.downcast_mut::<uint>() {
Some(&413) => {}
- x => fail!("Unexpected value {}", x)
+ x => panic!("Unexpected value {}", x)
}
}
&mut i, (),
|i, ()| {
*i = 10;
- fail!();
+ panic!();
},
|i| {
assert!(failing());
assert!(v.iter().all(|&x| x < 10));
assert!(!v.iter().all(|&x| x % 2 == 0));
assert!(!v.iter().all(|&x| x > 100));
- assert!(v.slice_or_fail(&0, &0).iter().all(|_| fail!()));
+ assert!(v.slice_or_fail(&0, &0).iter().all(|_| panic!()));
}
#[test]
assert!(v.iter().any(|&x| x < 10));
assert!(v.iter().any(|&x| x % 2 == 0));
assert!(!v.iter().any(|&x| x > 100));
- assert!(!v.slice_or_fail(&0, &0).iter().any(|_| fail!()));
+ assert!(!v.slice_or_fail(&0, &0).iter().any(|_| panic!()));
}
#[test]
#[test]
#[should_fail]
-fn test_rposition_fail() {
+fn test_rposition_panic() {
let v = [(box 0i, box 0i), (box 0i, box 0i),
(box 0i, box 0i), (box 0i, box 0i)];
let mut i = 0i;
v.iter().rposition(|_elt| {
if i == 2 {
- fail!()
+ panic!()
}
i += 1;
false
fn test_double_ended_range() {
assert!(range(11i, 14).rev().collect::<Vec<int>>() == vec![13i, 12, 11]);
for _ in range(10i, 0).rev() {
- fail!("unreachable");
+ panic!("unreachable");
}
assert!(range(11u, 14).rev().collect::<Vec<uint>>() == vec![13u, 12, 11]);
for _ in range(10u, 0).rev() {
- fail!("unreachable");
+ panic!("unreachable");
}
}
#[test]
#[should_fail]
-fn test_unwrap_fail1() {
+fn test_unwrap_panic1() {
let x: Option<int> = None;
x.unwrap();
}
#[test]
#[should_fail]
-fn test_unwrap_fail2() {
+fn test_unwrap_panic2() {
let x: Option<String> = None;
x.unwrap();
}
assert!(v == None);
// test that it does not take more elements than it needs
- let mut functions = [|| Some(()), || None, || fail!()];
+ let mut functions = [|| Some(()), || None, || panic!()];
let v: Option<Vec<()>> = functions.iter_mut().map(|f| (*f)()).collect();
assert!(v == Err(2));
// test that it does not take more elements than it needs
- let mut functions = [|| Ok(()), || Err(1i), || fail!()];
+ let mut functions = [|| Ok(()), || Err(1i), || panic!()];
let v: Result<Vec<()>, int> = functions.iter_mut().map(|f| (*f)()).collect();
assert!(v == Err(1));
if msg == "I got this." {
50i
} else {
- fail!("BadBad")
+ panic!("BadBad")
}
}
#[test]
#[should_fail]
-pub fn test_unwrap_or_else_failure() {
+pub fn test_unwrap_or_else_panic() {
fn handler(msg: &'static str) -> int {
if msg == "I got this." {
50i
} else {
- fail!("BadBad")
+ panic!("BadBad")
}
}
//! ];
//! let matches = match getopts(args.tail(), opts) {
//! Ok(m) => { m }
-//! Err(f) => { fail!(f.to_string()) }
+//! Err(f) => { panic!(f.to_string()) }
//! };
//! if matches.opt_present("h") {
//! print_usage(program.as_slice(), opts);
} = (*self).clone();
match (short_name.len(), long_name.len()) {
- (0,0) => fail!("this long-format option was given no name"),
+ (0,0) => panic!("this long-format option was given no name"),
(0,_) => Opt {
name: Long((long_name)),
hasarg: hasarg,
}
)
},
- (_,_) => fail!("something is wrong with the long-form opt")
+ (_,_) => panic!("something is wrong with the long-form opt")
}
}
}
fn opt_vals(&self, nm: &str) -> Vec<Optval> {
match find_opt(self.opts.as_slice(), Name::from_str(nm)) {
Some(id) => self.vals[id].clone(),
- None => fail!("No option '{}' defined", nm)
+ None => panic!("No option '{}' defined", nm)
}
}
/// Parse command line arguments according to the provided options.
///
/// On success returns `Ok(Matches)`. Use methods such as `opt_present`
-/// `opt_str`, etc. to interrogate results. Returns `Err(Fail_)` on
-/// failure: use the `Show` implementation of `Fail_` to display
+/// `opt_str`, etc. to interrogate results.
+/// # Failure
+///
+/// Returns `Err(Fail_)` on failure: use the `Show` implementation of `Fail_` to display
/// information about it.
pub fn getopts(args: &[String], optgrps: &[OptGroup]) -> Result {
let opts: Vec<Opt> = optgrps.iter().map(|x| x.long_to_short()).collect();
row.push_str(short_name.as_slice());
row.push(' ');
}
- _ => fail!("the short name should only be 1 ascii char long"),
+ _ => panic!("the short name should only be 1 ascii char long"),
}
// long option
(B, Cr, UnderLim) => { B }
(B, Cr, OverLim) if (i - last_start + 1) > lim
- => fail!("word starting with {} longer than limit!",
+ => panic!("word starting with {} longer than limit!",
ss.slice(last_start, i + 1)),
(B, Cr, OverLim) => {
*cont = it(ss.slice(slice_start, last_end));
assert!(m.opt_present("t"));
assert_eq!(m.opt_str("t").unwrap(), "20".to_string());
}
- _ => { fail!("test_reqopt failed (long arg)"); }
+ _ => { panic!("test_reqopt failed (long arg)"); }
}
let short_args = vec!("-t".to_string(), "20".to_string());
match getopts(short_args.as_slice(), opts.as_slice()) {
assert!((m.opt_present("t")));
assert_eq!(m.opt_str("t").unwrap(), "20".to_string());
}
- _ => { fail!("test_reqopt failed (short arg)"); }
+ _ => { panic!("test_reqopt failed (short arg)"); }
}
}
let rs = getopts(args.as_slice(), opts.as_slice());
match rs {
Err(f) => check_fail_type(f, OptionMissing_),
- _ => fail!()
+ _ => panic!()
}
}
let rs = getopts(long_args.as_slice(), opts.as_slice());
match rs {
Err(f) => check_fail_type(f, ArgumentMissing_),
- _ => fail!()
+ _ => panic!()
}
let short_args = vec!("-t".to_string());
match getopts(short_args.as_slice(), opts.as_slice()) {
Err(f) => check_fail_type(f, ArgumentMissing_),
- _ => fail!()
+ _ => panic!()
}
}
let rs = getopts(args.as_slice(), opts.as_slice());
match rs {
Err(f) => check_fail_type(f, OptionDuplicated_),
- _ => fail!()
+ _ => panic!()
}
}
assert!((m.opt_present("t")));
assert_eq!(m.opt_str("t").unwrap(), "20".to_string());
}
- _ => fail!()
+ _ => panic!()
}
let short_args = vec!("-t".to_string(), "20".to_string());
match getopts(short_args.as_slice(), opts.as_slice()) {
assert!((m.opt_present("t")));
assert_eq!(m.opt_str("t").unwrap(), "20".to_string());
}
- _ => fail!()
+ _ => panic!()
}
}
assert!(!m.opt_present("test"));
assert!(!m.opt_present("t"));
}
- _ => fail!()
+ _ => panic!()
}
}
let rs = getopts(long_args.as_slice(), opts.as_slice());
match rs {
Err(f) => check_fail_type(f, ArgumentMissing_),
- _ => fail!()
+ _ => panic!()
}
let short_args = vec!("-t".to_string());
match getopts(short_args.as_slice(), opts.as_slice()) {
Err(f) => check_fail_type(f, ArgumentMissing_),
- _ => fail!()
+ _ => panic!()
}
}
let rs = getopts(args.as_slice(), opts.as_slice());
match rs {
Err(f) => check_fail_type(f, OptionDuplicated_),
- _ => fail!()
+ _ => panic!()
}
}
assert!(m.opt_present("test"));
assert!(m.opt_present("t"));
}
- _ => fail!()
+ _ => panic!()
}
let short_args = vec!("-t".to_string());
match getopts(short_args.as_slice(), opts.as_slice()) {
assert!(m.opt_present("test"));
assert!(m.opt_present("t"));
}
- _ => fail!()
+ _ => panic!()
}
}
assert!(!m.opt_present("test"));
assert!(!m.opt_present("t"));
}
- _ => fail!()
+ _ => panic!()
}
}
Err(f) => {
check_fail_type(f, UnexpectedArgument_);
}
- _ => fail!()
+ _ => panic!()
}
}
let rs = getopts(args.as_slice(), opts.as_slice());
match rs {
Err(f) => check_fail_type(f, OptionDuplicated_),
- _ => fail!()
+ _ => panic!()
}
}
assert!(m.free[0] == "20".to_string());
}
- _ => fail!()
+ _ => panic!()
}
}
Ok(ref m) => {
assert_eq!(m.opt_count("v"), 1);
}
- _ => fail!()
+ _ => panic!()
}
}
Ok(ref m) => {
assert_eq!(m.opt_count("v"), 2);
}
- _ => fail!()
+ _ => panic!()
}
}
Ok(ref m) => {
assert_eq!(m.opt_count("v"), 2);
}
- _ => fail!()
+ _ => panic!()
}
}
Ok(ref m) => {
assert_eq!(m.opt_count("verbose"), 1);
}
- _ => fail!()
+ _ => panic!()
}
}
Ok(ref m) => {
assert_eq!(m.opt_count("verbose"), 2);
}
- _ => fail!()
+ _ => panic!()
}
}
assert_eq!(m.opt_count("verbose"), 4);
assert_eq!(m.opt_count("v"), 4);
}
- _ => fail!()
+ _ => panic!()
}
}
assert!((m.opt_present("t")));
assert_eq!(m.opt_str("t").unwrap(), "20".to_string());
}
- _ => fail!()
+ _ => panic!()
}
let short_args = vec!("-t".to_string(), "20".to_string());
match getopts(short_args.as_slice(), opts.as_slice()) {
assert!((m.opt_present("t")));
assert_eq!(m.opt_str("t").unwrap(), "20".to_string());
}
- _ => fail!()
+ _ => panic!()
}
}
assert!(!m.opt_present("test"));
assert!(!m.opt_present("t"));
}
- _ => fail!()
+ _ => panic!()
}
}
let rs = getopts(long_args.as_slice(), opts.as_slice());
match rs {
Err(f) => check_fail_type(f, ArgumentMissing_),
- _ => fail!()
+ _ => panic!()
}
let short_args = vec!("-t".to_string());
match getopts(short_args.as_slice(), opts.as_slice()) {
Err(f) => check_fail_type(f, ArgumentMissing_),
- _ => fail!()
+ _ => panic!()
}
}
assert!(pair[0] == "20".to_string());
assert!(pair[1] == "30".to_string());
}
- _ => fail!()
+ _ => panic!()
}
}
let rs = getopts(long_args.as_slice(), opts.as_slice());
match rs {
Err(f) => check_fail_type(f, UnrecognizedOption_),
- _ => fail!()
+ _ => panic!()
}
let short_args = vec!("-u".to_string());
match getopts(short_args.as_slice(), opts.as_slice()) {
Err(f) => check_fail_type(f, UnrecognizedOption_),
- _ => fail!()
+ _ => panic!()
}
}
assert!(pair[1] == "-60 70".to_string());
assert!((!m.opt_present("notpresent")));
}
- _ => fail!()
+ _ => panic!()
}
}
let matches_single = &match getopts(args_single.as_slice(),
opts.as_slice()) {
result::Ok(m) => m,
- result::Err(_) => fail!()
+ result::Err(_) => panic!()
};
assert!(matches_single.opts_present(["e".to_string()]));
assert!(matches_single.opts_present(["encrypt".to_string(), "e".to_string()]));
let matches_both = &match getopts(args_both.as_slice(),
opts.as_slice()) {
result::Ok(m) => m,
- result::Err(_) => fail!()
+ result::Err(_) => panic!()
};
assert!(matches_both.opts_present(["e".to_string()]));
assert!(matches_both.opts_present(["encrypt".to_string()]));
optmulti("M", "", "something", "MMMM"));
let matches = &match getopts(args.as_slice(), opts.as_slice()) {
result::Ok(m) => m,
- result::Err(_) => fail!()
+ result::Err(_) => panic!()
};
assert!(matches.opts_present(["L".to_string()]));
assert_eq!(matches.opts_str(["L".to_string()]).unwrap(), "foo".to_string());
optflagmulti("v", "verbose", "Verbose"));
let matches = &match getopts(args.as_slice(), opts.as_slice()) {
result::Ok(m) => m,
- result::Err(e) => fail!( "{}", e )
+ result::Err(e) => panic!( "{}", e )
};
assert!(matches.opts_present(["L".to_string()]));
assert_eq!(matches.opts_str(["L".to_string()]).unwrap(), "verbose".to_string());
RunRemote(i) => {
match self.remotes.iter_mut().find(|& &(id, _)| id == i) {
Some(&(_, ref mut f)) => f.call(),
- None => fail!("bad remote: {}", i),
+ None => panic!("bad remote: {}", i),
}
}
RemoveRemote(i) => {
match self.remotes.iter().position(|&(id, _)| id == i) {
Some(i) => { self.remotes.remove(i).unwrap(); }
- None => fail!("bad remote: {}", i),
+ None => panic!("bad remote: {}", i),
}
}
}
// Right before we switch to the new context, set the new context's
// stack limit in the OS-specified TLS slot. This also means that
// we cannot call any more rust functions after record_stack_bounds
- // returns because they would all likely fail due to the limit being
+ // returns because they would all likely panic due to the limit being
// invalid for the current task. Lucky for us `rust_swap_registers`
// is a C function so we don't have to worry about that!
match in_context.stack_bounds {
Some((lo, hi)) => stack::record_rust_managed_stack_bounds(lo, hi),
// If we're going back to one of the original contexts or
// something that's possibly not a "normal task", then reset
- // the stack limit to 0 to make morestack never fail
+ // the stack limit to 0 to make morestack never panic
None => stack::record_rust_managed_stack_bounds(0, uint::MAX),
}
rust_swap_registers(out_regs, in_regs);
//! drop(handle);
//!
//! // Required to shut down this scheduler pool.
-//! // The task will fail if `shutdown` is not called.
+//! // The task will panic if `shutdown` is not called.
//! pool.shutdown();
//! # }
//! ```
impl Drop for SchedPool {
fn drop(&mut self) {
if self.threads.len() > 0 {
- fail!("dropping a M:N scheduler pool that wasn't shut down");
+ panic!("dropping a M:N scheduler pool that wasn't shut down");
}
}
}
// task-local lock around this block. The resumption of the task in
// context switching will bounce on the lock, thereby waiting for this
// block to finish, eliminating the race mentioned above.
- // fail!("should never return!");
+ // panic!("should never return!");
//
// To actually maintain a handle to the lock, we use an unsafe pointer
// to it, but we're guaranteed that the task won't exit until we've
coroutine.recycle(&mut sched.stack_pool);
sched.task_state.decrement();
});
- fail!("should never return!");
+ panic!("should never return!");
}
pub fn run_task(self: Box<Scheduler>,
task.put_runtime(green);
return ret;
}
- None => fail!()
+ None => panic!()
}
}
}))) => {
*id == sched_id
}
- TypeGreen(None) => { fail!("task without home"); }
- TypeSched => { fail!("expected green task"); }
+ TypeGreen(None) => { panic!("task without home"); }
+ TypeSched => { panic!("expected green task"); }
};
task.put();
ret
}
}
- // These functions are all unimplemented and fail as a result. This is on
+ // These functions are all unimplemented and panic as a result. This is on
// purpose. A "simple task" is just that, a very simple task that can't
// really do a whole lot. The only purpose of the task is to get us off our
// feet and running.
- fn yield_now(self: Box<SimpleTask>, _cur_task: Box<Task>) { fail!() }
- fn maybe_yield(self: Box<SimpleTask>, _cur_task: Box<Task>) { fail!() }
+ fn yield_now(self: Box<SimpleTask>, _cur_task: Box<Task>) { panic!() }
+ fn maybe_yield(self: Box<SimpleTask>, _cur_task: Box<Task>) { panic!() }
fn spawn_sibling(self: Box<SimpleTask>,
_cur_task: Box<Task>,
_opts: TaskOpts,
_f: proc():Send) {
- fail!()
+ panic!()
}
fn local_io<'a>(&'a mut self) -> Option<rtio::LocalIo<'a>> { None }
- fn stack_bounds(&self) -> (uint, uint) { fail!() }
- fn stack_guard(&self) -> Option<uint> { fail!() }
+ fn stack_bounds(&self) -> (uint, uint) { panic!() }
+ fn stack_guard(&self) -> Option<uint> { panic!() }
fn can_block(&self) -> bool { true }
- fn wrap(self: Box<SimpleTask>) -> Box<Any+'static> { fail!() }
+ fn wrap(self: Box<SimpleTask>) -> Box<Any+'static> { panic!() }
}
pub fn task() -> Box<Task> {
// Try to use MAP_STACK on platforms that support it (it's what we're doing
// anyway), but some platforms don't support it at all. For example, it appears
// that there's a bug in freebsd that MAP_STACK implies MAP_FIXED (so it always
-// fails): http://lists.freebsd.org/pipermail/freebsd-bugs/2011-July/044840.html
+// panics): http://lists.freebsd.org/pipermail/freebsd-bugs/2011-July/044840.html
//
// DragonFly BSD also seems to suffer from the same problem. When MAP_STACK is
// used, it returns the same `ptr` multiple times.
static STACK_FLAGS: libc::c_int = 0;
impl Stack {
- /// Allocate a new stack of `size`. If size = 0, this will fail. Use
+ /// Allocate a new stack of `size`. If size = 0, this will panic. Use
/// `dummy_stack` if you want a zero-sized stack.
pub fn new(size: uint) -> Stack {
// Map in a stack. Eventually we might be able to handle stack
let stack = match MemoryMap::new(size, [MapReadable, MapWritable,
MapNonStandardFlags(STACK_FLAGS)]) {
Ok(map) => map,
- Err(e) => fail!("mmap for stack of size {} failed: {}", size, e)
+ Err(e) => panic!("mmap for stack of size {} failed: {}", size, e)
};
// Change the last page to be inaccessible. This is to provide safety;
// page. It isn't guaranteed, but that's why FFI is unsafe. buf.data is
// guaranteed to be aligned properly.
if !protect_last_page(&stack) {
- fail!("Could not memory-protect guard page. stack={}, errno={}",
+ panic!("Could not memory-protect guard page. stack={}, errno={}",
stack.data(), errno());
}
self.put_task(cur_task);
// First, set up a bomb which when it goes off will restore the local
- // task unless its disarmed. This will allow us to gracefully fail from
+ // task unless its disarmed. This will allow us to gracefully panic from
// inside of `configure` which allocates a new task.
struct Bomb { inner: Option<Box<GreenTask>> }
impl Drop for Bomb {
}
#[test]
- fn smoke_fail() {
+ fn smoke_panic() {
let (tx, rx) = channel::<int>();
spawn_opts(TaskOpts::new(), proc() {
let _tx = tx;
- fail!()
+ panic!()
});
assert_eq!(rx.recv_opt(), Err(()));
}
}
#[test]
- fn smoke_opts_fail() {
+ fn smoke_opts_panic() {
let mut opts = TaskOpts::new();
let (tx, rx) = channel();
opts.on_exit = Some(proc(r) tx.send(r));
- spawn_opts(opts, proc() { fail!() });
+ spawn_opts(opts, proc() { panic!() });
assert!(rx.recv().is_err());
}
Some(ops) => {
task.put_runtime(ops);
}
- None => fail!(),
+ None => panic!(),
}
Local::put(task);
tx.send(());
record.level,
record.module_path,
record.args) {
- Err(e) => fail!("failed to log: {}", e),
+ Err(e) => panic!("failed to log: {}", e),
Ok(()) => {}
}
}
impl Drop for DefaultLogger {
fn drop(&mut self) {
- // FIXME(#12628): is failure the right thing to do?
+ // FIXME(#12628): is panicking the right thing to do?
match self.handle.flush() {
- Err(e) => fail!("failed to flush a logger: {}", e),
+ Err(e) => panic!("failed to flush a logger: {}", e),
Ok(()) => {}
}
}
assert_eq!(buf[2], 's' as u8);
assert_eq!(buf[3], 't' as u8);
}
- r => fail!("invalid read: {}", r)
+ r => panic!("invalid read: {}", r),
}
assert!(writer.inner_read(buf).is_err());
assert_eq!(buf[2], 's' as u8);
assert_eq!(buf[3], 't' as u8);
}
- r => fail!("invalid read: {}", r)
+ r => panic!("invalid read: {}", r)
}
}
}
if new_handle == libc::INVALID_HANDLE_VALUE {
let ret = Err(super::last_error());
// If our disconnection fails, then there's not really a whole lot
- // that we can do, so fail the task.
+ // that we can do, so panic
let err = unsafe { libc::DisconnectNamedPipe(handle) };
assert!(err != 0);
return ret;
handle: ptr::null_mut()
})
}
- Ok(..) => fail!("short read on the cloexec pipe"),
+ Ok(..) => panic!("short read on the cloexec pipe"),
};
}
// And at this point we've reached a special time in the life of the
let mut status = 0 as c_int;
if deadline == 0 {
return match retry(|| unsafe { c::waitpid(pid, &mut status, 0) }) {
- -1 => fail!("unknown waitpid error: {}", super::last_error().code),
+ -1 => panic!("unknown waitpid error: {}", super::last_error().code),
_ => Ok(translate_status(status)),
}
}
continue
}
- n => fail!("error in select {} ({})", os::errno(), n),
+ n => panic!("error in select {} ({})", os::errno(), n),
}
// Process any pending messages
n if n > 0 => { ret = true; }
0 => return true,
-1 if util::wouldblock() => return ret,
- n => fail!("bad read {} ({})", os::last_os_error(), n),
+ n => panic!("bad read {} ({})", os::last_os_error(), n),
}
}
}
} {
1 => {}
-1 if util::wouldblock() => {} // see above comments
- n => fail!("bad error on write fd: {} {}", n, os::errno()),
+ n => panic!("bad error on write fd: {} {}", n, os::errno()),
}
}
}
}) {
n if n == pid => Some(translate_status(status)),
0 => None,
- n => fail!("unknown waitpid error `{}`: {}", n,
+ n => panic!("unknown waitpid error `{}`: {}", n,
super::last_error().code),
}
}
}
-1 if os::errno() == libc::EINTR as int => {}
- n => fail!("helper thread failed in select() with error: {} ({})",
+ n => panic!("helper thread panicked in select() with error: {} ({})",
n, os::last_os_error())
}
}
};
while unsafe { libc::nanosleep(&to_sleep, &mut to_sleep) } != 0 {
if os::errno() as int != libc::EINTR as int {
- fail!("failed to sleep, but not because of EINTR?");
+ panic!("failed to sleep, but not because of EINTR?");
}
}
}
exit_code = Some(run(main.take().unwrap()));
}).destroy());
unsafe { rt::cleanup(); }
- // If the exit code wasn't set, then the task block must have failed.
+ // If the exit code wasn't set, then the task block must have panicked.
return exit_code.unwrap_or(rt::DEFAULT_ERROR_CODE);
}
}
#[test]
- fn smoke_fail() {
+ fn smoke_panic() {
let (tx, rx) = channel::<()>();
spawn(proc() {
let _tx = tx;
- fail!()
+ panic!()
});
assert_eq!(rx.recv_opt(), Err(()));
}
}
#[test]
- fn smoke_opts_fail() {
+ fn smoke_opts_panic() {
let mut opts = TaskOpts::new();
let (tx, rx) = channel();
opts.on_exit = Some(proc(r) tx.send(r));
- NativeSpawner.spawn(opts, proc() { fail!() });
+ NativeSpawner.spawn(opts, proc() { panic!() });
assert!(rx.recv().is_err());
}
Some(ops) => {
task.put_runtime(ops);
}
- None => fail!(),
+ None => panic!(),
}
Local::put(task);
tx.send(());
fn reseed(&mut self, seed: &'a [u32]) {
// reset state
self.init(&[0u32, ..KEY_WORDS]);
- // set key inplace
+ // set key in place
let key = self.state.slice_mut(4, 4+KEY_WORDS);
for (k, s) in key.iter_mut().zip(seed.iter()) {
*k = *s;
for item in items.iter_mut() {
running_total = match running_total.checked_add(&item.weight) {
Some(n) => n,
- None => fail!("WeightedChoice::new called with a total weight \
+ None => panic!("WeightedChoice::new called with a total weight \
larger than a uint can contain")
};
/// not be relied upon.
///
/// This method should guarantee that `dest` is entirely filled
- /// with new data, and may fail if this is impossible
+ /// with new data, and may panic if this is impossible
/// (e.g. reading past the end of a file that is being used as the
/// source of randomness).
///
}
impl SeedableRng<[u32, .. 4]> for XorShiftRng {
- /// Reseed an XorShiftRng. This will fail if `seed` is entirely 0.
+ /// Reseed an XorShiftRng. This will panic if `seed` is entirely 0.
fn reseed(&mut self, seed: [u32, .. 4]) {
assert!(!seed.iter().all(|&x| x == 0),
"XorShiftRng.reseed called with an all zero seed.");
self.w = seed[3];
}
- /// Create a new XorShiftRng. This will fail if `seed` is entirely 0.
+ /// Create a new XorShiftRng. This will panic if `seed` is entirely 0.
fn from_seed(seed: [u32, .. 4]) -> XorShiftRng {
assert!(!seed.iter().all(|&x| x == 0),
"XorShiftRng::from_seed called with an all zero seed.");
#[cfg(not(test))]
mod std {
- pub use core::{option, fmt}; // fail!()
+ pub use core::{option, fmt}; // panic!()
}
#[cfg(test)]
Some(d) => d,
None => {
error!("failed to find block with tag {}", tg);
- fail!();
+ panic!();
}
}
}
/// Sets the left and right locations of a `Split` instruction at index
/// `i` to `pc1` and `pc2`, respectively.
/// If the instruction at index `i` isn't a `Split` instruction, then
- /// `fail!` is called.
+ /// `panic!` is called.
#[inline]
fn set_split(&mut self, i: InstIdx, pc1: InstIdx, pc2: InstIdx) {
let split = self.insts.get_mut(i);
match *split {
Split(_, _) => *split = Split(pc1, pc2),
- _ => fail!("BUG: Invalid split index."),
+ _ => panic!("BUG: Invalid split index."),
}
}
/// Sets the location of a `Jump` instruction at index `i` to `pc`.
/// If the instruction at index `i` isn't a `Jump` instruction, then
- /// `fail!` is called.
+ /// `panic!` is called.
#[inline]
fn set_jump(&mut self, i: InstIdx, pc: InstIdx) {
let jmp = self.insts.get_mut(i);
match *jmp {
Jump(_) => *jmp = Jump(pc),
- _ => fail!("BUG: Invalid jump index."),
+ _ => panic!("BUG: Invalid jump index."),
}
}
}
//! use regex::Regex;
//! let re = match Regex::new(r"^\d{4}-\d{2}-\d{2}$") {
//! Ok(re) => re,
-//! Err(err) => fail!("{}", err),
+//! Err(err) => panic!("{}", err),
//! };
//! assert_eq!(re.is_match("2014-01-01"), true);
//! ```
fn flags(&self) -> Flags {
match *self {
Paren(flags, _, _) => flags,
- _ => fail!("Cannot get flags from {}", self),
+ _ => panic!("Cannot get flags from {}", self),
}
}
match *self {
Paren(_, 0, _) => None,
Paren(_, c, _) => Some(c),
- _ => fail!("Cannot get capture group from {}", self),
+ _ => panic!("Cannot get capture group from {}", self),
}
}
Some(name.clone())
}
}
- _ => fail!("Cannot get capture name from {}", self),
+ _ => panic!("Cannot get capture name from {}", self),
}
}
fn unwrap(self) -> Result<Ast, Error> {
match self {
Expr(x) => Ok(x),
- _ => fail!("Tried to unwrap non-AST item: {}", self),
+ _ => panic!("Tried to unwrap non-AST item: {}", self),
}
}
}
}
let rep: Repeater = match c {
'?' => ZeroOne, '*' => ZeroMore, '+' => OneMore,
- _ => fail!("Not a valid repeater operator."),
+ _ => panic!("Not a valid repeater operator."),
};
match self.peek(1) {
let mut ranges: Vec<(char, char)> = vec!();
let mut alts: Vec<Ast> = vec!();
- if self.peek_is(1, ']') {
- try!(self.expect(']'))
- ranges.push((']', ']'))
- }
while self.peek_is(1, '-') {
- try!(self.expect('-'))
+ try!(self.expect('-'));
ranges.push(('-', '-'))
}
loop {
- try!(self.noteof("a closing ']' or a non-empty character class)"))
+ try!(self.noteof("a closing ']' or a non-empty character class)"));
let mut c = self.cur();
match c {
'[' =>
continue
}
Some(ast) =>
- fail!("Expected Class AST but got '{}'", ast),
+ panic!("Expected Class AST but got '{}'", ast),
// Just drop down and try to add as a regular character.
None => {},
},
return self.err(
"\\A, \\z, \\b and \\B are not valid escape \
sequences inside a character class."),
- ast => fail!("Unexpected AST item '{}'", ast),
+ ast => panic!("Unexpected AST item '{}'", ast),
}
}
- _ => {},
- }
- match c {
- ']' => {
+ ']' if ranges.len() > 0 || alts.len() > 0 => {
if ranges.len() > 0 {
let flags = negated | (self.flags & FLAG_NOCASE);
let mut ast = AstClass(combine_ranges(ranges), flags);
}
return Ok(())
}
- c => {
- if self.peek_is(1, '-') && !self.peek_is(2, ']') {
- try!(self.expect('-'))
- try!(self.noteof("not a ']'"))
- let c2 = self.cur();
- if c2 < c {
- return self.err(format!("Invalid character class \
- range '{}-{}'",
- c,
- c2).as_slice())
- }
- ranges.push((c, self.cur()))
- } else {
- ranges.push((c, c))
+ _ => {}
+ }
+
+ if self.peek_is(1, '-') && !self.peek_is(2, ']') {
+ try!(self.expect('-'));
+ // The regex can't end here.
+ try!(self.noteof("not a ']'"));
+ // End the range with a single character or character escape.
+ let mut c2 = self.cur();
+ if c2 == '\\' {
+ match try!(self.parse_escape()) {
+ Literal(c3, _) => c2 = c3, // allow literal escapes below
+ ast =>
+ return self.err(format!("Expected a literal, but got {}.",
+ ast).as_slice()),
}
}
+ if c2 < c {
+ return self.err(format!("Invalid character class \
+ range '{}-{}'",
+ c,
+ c2).as_slice())
+ }
+ ranges.push((c, self.cur()))
+ } else {
+ ranges.push((c, c))
}
}
}
/// # use regex::Regex;
/// let re = match Regex::new("[0-9]{3}-[0-9]{3}-[0-9]{4}") {
/// Ok(re) => re,
-/// Err(err) => fail!("{}", err),
+/// Err(err) => panic!("{}", err),
/// };
/// assert_eq!(re.find("phone: 111-222-3333"), Some((7, 19)));
/// ```
use regex::{Regex, NoExpand};
fn bench_assert_match(b: &mut Bencher, re: Regex, text: &str) {
- b.iter(|| if !re.is_match(text) { fail!("no match") });
+ b.iter(|| if !re.is_match(text) { panic!("no match") });
}
#[bench]
fn $name(b: &mut Bencher) {
let text = gen_text($size);
b.bytes = $size;
- b.iter(|| if $regex.is_match(text.as_slice()) { fail!("match") });
+ b.iter(|| if $regex.is_match(text.as_slice()) { panic!("match") });
}
);
)
($re:expr) => (
match ::regex::Regex::new($re) {
Ok(re) => re,
- Err(err) => fail!("{}", err),
+ Err(err) => panic!("{}", err),
}
);
)
assert_eq!(ms, vec![(0, 0), (1, 1), (2, 2), (3, 3)]);
}
+#[test]
+fn quoted_bracket_set() {
+ let re = regex!(r"([\x{5b}\x{5d}])");
+ let ms = re.find_iter("[]").collect::<Vec<(uint, uint)>>();
+ assert_eq!(ms, vec![(0, 1), (1, 2)]);
+ let re = regex!(r"([\[\]])");
+ let ms = re.find_iter("[]").collect::<Vec<(uint, uint)>>();
+ assert_eq!(ms, vec![(0, 1), (1, 2)]);
+}
+
+#[test]
+fn first_range_starts_with_left_bracket() {
+ let re = regex!(r"([[-z])");
+ let ms = re.find_iter("[]").collect::<Vec<(uint, uint)>>();
+ assert_eq!(ms, vec![(0, 1), (1, 2)]);
+}
+
+#[test]
+fn range_ends_with_escape() {
+ let re = regex!(r"([\[-\x{5d}])");
+ let ms = re.find_iter("[]").collect::<Vec<(uint, uint)>>();
+ assert_eq!(ms, vec![(0, 1), (1, 2)]);
+}
+
macro_rules! replace(
($name:ident, $which:ident, $re:expr,
$search:expr, $replace:expr, $result:expr) => (
let re = $re;
match Regex::new(re) {
Err(_) => {},
- Ok(_) => fail!("Regex '{}' should cause a parse error.", re),
+ Ok(_) => panic!("Regex '{}' should cause a parse error.", re),
}
}
);
noparse!(fail_neg_empty, "(?i-)")
noparse!(fail_empty_group, "()")
noparse!(fail_dupe_named, "(?P<a>.)(?P<a>.)")
+noparse!(fail_range_end_no_class, "[a-[:lower:]]")
+noparse!(fail_range_end_no_begin, r"[a-\A]")
+noparse!(fail_range_end_no_end, r"[a-\z]")
+noparse!(fail_range_end_no_boundary, r"[a-\b]")
macro_rules! mat(
($name:ident, $re:expr, $text:expr, $($loc:tt)+) => (
sgot = sgot[0..sexpect.len()]
}
if sexpect != sgot {
- fail!("For RE '{}' against '{}', expected '{}' but got '{}'",
+ panic!("For RE '{}' against '{}', expected '{}' but got '{}'",
$re, text, sexpect, sgot);
}
}
return None
}
};
- if !parser.eat(&token::EOF) {
+ if !parser.eat(&token::Eof) {
cx.span_err(parser.span, "only one string literal allowed");
return None;
}
// We use an Arc instead of just returning a list of diagnostics from the
// child task because we need to make sure that the messages are seen even
-// if the child task fails (for example, when `fatal` is called).
+// if the child task panics (for example, when `fatal` is called).
#[deriving(Clone)]
struct SharedEmitter {
buffer: Arc<Mutex<Vec<Diagnostic>>>,
fn custom_emit(&mut self, _cm: &codemap::CodeMap,
_sp: diagnostic::RenderSpan, _msg: &str, _lvl: Level) {
- fail!("SharedEmitter doesn't support custom_emit");
+ panic!("SharedEmitter doesn't support custom_emit");
}
}
.stdout(::std::io::process::InheritFd(1))
.stderr(::std::io::process::InheritFd(2));
match cmd.status() {
- Ok(_) => {},
+ Ok(status) => {
+ if !status.success() {
+ sess.err(format!("linking of {} with `{}` failed",
+ output_path.display(), cmd).as_slice());
+ sess.abort_if_errors();
+ }
+ },
Err(e) => {
sess.err(format!("could not exec the linker `{}`: {}",
pname,
futures.push(future);
}
- let mut failed = false;
+ let mut panicked = false;
for future in futures.into_iter() {
match future.unwrap() {
Ok(()) => {},
Err(_) => {
- failed = true;
+ panicked = true;
},
}
// Display any new diagnostics.
diag_emitter.dump(sess.diagnostic().handler());
}
- if failed {
- sess.fatal("aborting due to worker thread failure");
+ if panicked {
+ sess.fatal("aborting due to worker thread panic");
}
}
E0015,
E0016,
E0017,
+ E0018,
E0019,
E0020,
E0022,
E0035,
E0036,
E0038,
- E0039,
E0040,
E0044,
E0045,
E0162,
E0163,
E0164,
- E0165
+ E0165,
+ E0166
)
early_warn("the --crate-file-name argument has been renamed to \
--print-file-name");
}
-
- let mut cg = build_codegen_options(matches);
-
- if cg.codegen_units == 0 {
- match opt_level {
- // `-C lto` doesn't work with multiple codegen units.
- _ if cg.lto => cg.codegen_units = 1,
-
- No | Less => cg.codegen_units = 2,
- Default | Aggressive => cg.codegen_units = 1,
- }
- }
- let cg = cg;
-
+ let cg = build_codegen_options(matches);
if !cg.remark.is_empty() && debuginfo == NoDebugInfo {
early_warn("-C remark will not show source locations without --debuginfo");
let matches =
&match getopts(["--test".to_string()], optgroups().as_slice()) {
Ok(m) => m,
- Err(f) => fail!("test_switch_implies_cfg_test: {}", f)
+ Err(f) => panic!("test_switch_implies_cfg_test: {}", f)
};
let registry = diagnostics::registry::Registry::new([]);
let sessopts = build_session_options(matches);
optgroups().as_slice()) {
Ok(m) => m,
Err(f) => {
- fail!("test_switch_implies_cfg_test_unless_cfg_test: {}", f)
+ panic!("test_switch_implies_cfg_test_unless_cfg_test: {}", f)
}
};
let registry = diagnostics::registry::Registry::new([]);
println!("Compiler plugins can provide additional lints and lint groups. To see a \
listing of these, re-run `rustc -W help` with a crate filename.");
}
- (false, _, _) => fail!("didn't load lint plugins but got them anyway!"),
+ (false, _, _) => panic!("didn't load lint plugins but got them anyway!"),
(true, 0, 0) => println!("This crate does not load any lint plugins or lint groups."),
(true, l, g) => {
if l > 0 {
pub fn early_error(msg: &str) -> ! {
let mut emitter = diagnostic::EmitterWriter::stderr(diagnostic::Auto, None);
emitter.emit(None, msg, None, diagnostic::Fatal);
- fail!(diagnostic::FatalError);
+ panic!(diagnostic::FatalError);
}
pub fn early_warn(msg: &str) {
match task.try(f) {
Ok(()) => { /* fallthrough */ }
Err(value) => {
- // Task failed without emitting a fatal diagnostic
+ // Task panicked without emitting a fatal diagnostic
if !value.is::<diagnostic::FatalError>() {
let mut emitter = diagnostic::EmitterWriter::stderr(diagnostic::Auto, None);
if !value.is::<diagnostic::ExplicitBug>() {
emitter.emit(
None,
- "unexpected failure",
+ "unexpected panic",
None,
diagnostic::Bug);
}
let xs = [
- "the compiler hit an unexpected failure path. this is a bug.".to_string(),
+ "the compiler unexpectedly panicked. this is a bug.".to_string(),
format!("we would appreciate a bug report: {}",
BUG_REPORT_URL),
"run with `RUST_BACKTRACE=1` for a backtrace".to_string(),
}
}
- // Fail so the process returns a failure code, but don't pollute the
+ // Panic so the process returns a failure code, but don't pollute the
// output with some unnecessary failure messages, we've already
// printed everything that we needed to.
io::stdio::set_stderr(box io::util::NullWriter);
- fail!();
+ panic!();
}
}
}
let r = io::File::create(&p);
match r {
Ok(w) => box w as Box<Writer+'static>,
- Err(e) => fail!("print-print failed to open {} due to {}",
+ Err(e) => panic!("print-print failed to open {} due to {}",
p.display(), e),
}
}
return;
}
}
- _ => fail!()
+ _ => panic!()
};
},
ty::ty_uint(t) => {
let lit_val: u64 = match lit.node {
ast::LitByte(_v) => return, // _v is u8, within range by definition
ast::LitInt(v, _) => v,
- _ => fail!()
+ _ => panic!()
};
if lit_val < min || lit_val > max {
cx.span_lint(OVERFLOWING_LITERALS, e.span,
Some(f) => f,
None => return
},
- _ => fail!()
+ _ => panic!()
};
if lit_val < min || lit_val > max {
cx.span_lint(OVERFLOWING_LITERALS, e.span,
ast::BiGt => v >= min && v < max,
ast::BiGe => v > min && v <= max,
ast::BiEq | ast::BiNe => v >= min && v <= max,
- _ => fail!()
+ _ => panic!()
}
}
ast::LitInt(v, ast::UnsuffixedIntLit(ast::Minus)) => -(v as i64),
_ => return true
},
- _ => fail!()
+ _ => panic!()
};
is_valid(norm_binop, lit_val, min, max)
}
ast::LitInt(v, _) => v,
_ => return true
},
- _ => fail!()
+ _ => panic!()
};
is_valid(norm_binop, lit_val, min, max)
}
def::DefTy(..) => {
let tty = match self.cx.tcx.ast_ty_to_ty_cache.borrow().find(&ty_id) {
Some(&ty::atttce_resolved(t)) => t,
- _ => fail!("ast_ty_to_ty_cache was incomplete after typeck!")
+ _ => panic!("ast_ty_to_ty_cache was incomplete after typeck!")
};
if !ty::is_ffi_safe(self.cx.tcx, tty) {
let t = ty::expr_ty(cx.tcx, expr);
let mut warned = false;
match ty::get(t).sty {
- ty::ty_nil | ty::ty_bot | ty::ty_bool => return,
+ ty::ty_nil | ty::ty_bool => return,
ty::ty_struct(did, _) |
ty::ty_enum(did, _) => {
if ast_util::is_local(did) {
fn register_renamed(&mut self, old_name: &str, new_name: &str) {
let target = match self.by_name.find_equiv(&new_name) {
Some(&Id(lint_id)) => lint_id.clone(),
- _ => fail!("invalid lint renaming of {} to {}", old_name, new_name)
+ _ => panic!("invalid lint renaming of {} to {}", old_name, new_name)
};
self.by_name.insert(old_name.to_string(), Renamed(new_name.to_string(), target));
}
format!("{} [-{} {}]", msg,
match level {
Warn => 'W', Deny => 'D', Forbid => 'F',
- Allow => fail!()
+ Allow => panic!()
}, name.replace("_", "-"))
},
Node(src) => {
pub fn validate_crate_name(sess: Option<&Session>, s: &str, sp: Option<Span>) {
let err = |s: &str| {
match (sp, sess) {
- (_, None) => fail!("{}", s),
+ (_, None) => panic!("{}", s),
(Some(sp), Some(sess)) => sess.span_err(sp, s),
(None, Some(sess)) => sess.err(s),
}
fn find_item<'a>(item_id: ast::NodeId, items: rbml::Doc<'a>) -> rbml::Doc<'a> {
match maybe_find_item(item_id, items) {
- None => fail!("lookup_item: id not found: {}", item_id),
+ None => panic!("lookup_item: id not found: {}", item_id),
Some(d) => d
}
}
'S' => Struct,
'g' => PublicField,
'N' => InheritedField,
- c => fail!("unexpected family char: {}", c)
+ c => panic!("unexpected family char: {}", c)
}
}
match reader::doc_as_u8(visibility_doc) as char {
'y' => ast::Public,
'i' => ast::Inherited,
- _ => fail!("unknown visibility character")
+ _ => panic!("unknown visibility character")
}
}
}
match ch as char {
'i' => ast::MutImmutable,
'm' => ast::MutMutable,
- _ => fail!("unknown mutability character: `{}`", ch as char),
+ _ => panic!("unknown mutability character: `{}`", ch as char),
}
}
ty::ReEmpty,
get_mutability(string.as_bytes()[1]))
}
- _ => fail!("unknown self type code: `{}`", explicit_self_kind as char)
+ _ => panic!("unknown self type code: `{}`", explicit_self_kind as char)
}
}
match item_sort(doc) {
'r' | 'p' => impl_items.push(ty::MethodTraitItemId(def_id)),
't' => impl_items.push(ty::TypeTraitItemId(def_id)),
- _ => fail!("unknown impl item sort"),
+ _ => panic!("unknown impl item sort"),
}
true
});
}
't' => (name, TypeTraitItemKind),
c => {
- fail!("get_trait_item_name_and_kind(): unknown trait item kind \
+ panic!("get_trait_item_name_and_kind(): unknown trait item kind \
in metadata: `{}`", c)
}
}
container: container,
}))
}
- _ => fail!("unknown impl/trait item sort"),
+ _ => panic!("unknown impl/trait item sort"),
}
}
match item_sort(mth) {
'r' | 'p' => result.push(ty::MethodTraitItemId(def_id)),
't' => result.push(ty::TypeTraitItemId(def_id)),
- _ => fail!("unknown trait item sort"),
+ _ => panic!("unknown trait item sort"),
}
true
});
match item_family(impl_method_doc) {
StaticMethod => fn_style = ast::NormalFn,
UnsafeStaticMethod => fn_style = ast::UnsafeFn,
- _ => fail!()
+ _ => panic!()
}
static_impl_methods.push(StaticMethodInfo {
match family {
PublicField => ast::Public,
InheritedField => ast::Inherited,
- _ => fail!()
+ _ => panic!()
}
}
node: did.node,
}
}
- None => fail!("didn't find a crate in the cnum_map")
+ None => panic!("didn't find a crate in the cnum_map")
}
}
let cnum = from_str(cnum).unwrap();
let cnum = match cdata.cnum_map.find(&cnum) {
Some(&n) => n,
- None => fail!("didn't find a crate in the cnum_map")
+ None => panic!("didn't find a crate in the cnum_map")
};
result.push((cnum, if link == "d" {
cstore::RequireDynamic
path.and_then(|path|
match myfs::realpath(&path) {
Ok(canon) => Some(canon),
- Err(e) => fail!("failed to get realpath: {}", e),
+ Err(e) => panic!("failed to get realpath: {}", e),
})
}
match canonicalize(os::self_exe_name()) {
Some(mut p) => { p.pop(); p.pop(); p }
- None => fail!("can't determine value for sysroot")
+ None => panic!("can't determine value for sysroot")
}
}
parse_vec_per_param_space(
st, |st| parse_region(st, |x,y| conv(x,y))))
}
- _ => fail!("parse_bound_region: bad input")
+ _ => panic!("parse_bound_region: bad input")
}
}
ty::BrFresh(id)
}
'e' => ty::BrEnv,
- _ => fail!("parse_bound_region: bad input")
+ _ => panic!("parse_bound_region: bad input")
}
}
'e' => {
ty::ReStatic
}
- _ => fail!("parse_region: bad input")
+ _ => panic!("parse_region: bad input")
}
}
match next(st) {
'n' => None,
's' => Some(f(st)),
- _ => fail!("parse_opt: bad input")
+ _ => panic!("parse_opt: bad input")
}
}
fn parse_ty(st: &mut PState, conv: conv_did) -> ty::t {
match next(st) {
'n' => return ty::mk_nil(),
- 'z' => return ty::mk_bot(),
'b' => return ty::mk_bool(),
'i' => return ty::mk_int(),
'u' => return ty::mk_uint(),
'D' => return ty::mk_mach_int(ast::TyI64),
'f' => return ty::mk_mach_float(ast::TyF32),
'F' => return ty::mk_mach_float(ast::TyF64),
- _ => fail!("parse_ty: bad numeric type")
+ _ => panic!("parse_ty: bad numeric type")
}
}
'c' => return ty::mk_char(),
return ty::mk_struct(st.tcx, did, substs);
}
'k' => {
+ assert_eq!(next(st), '[');
let did = parse_def(st, NominalType, |x,y| conv(x,y));
- let region = parse_region(st, conv);
- return ty::mk_unboxed_closure(st.tcx, did, region);
+ let region = parse_region(st, |x,y| conv(x,y));
+ let substs = parse_substs(st, |x,y| conv(x,y));
+ assert_eq!(next(st), ']');
+ return ty::mk_unboxed_closure(st.tcx, did, region, substs);
}
'e' => {
return ty::mk_err();
}
- c => { fail!("unexpected char in type string: {}", c);}
+ c => { panic!("unexpected char in type string: {}", c);}
}
}
match c {
'u' => UnsafeFn,
'n' => NormalFn,
- _ => fail!("parse_fn_style: bad fn_style {}", c)
+ _ => panic!("parse_fn_style: bad fn_style {}", c)
}
}
match c {
'o' => ast::Once,
'm' => ast::Many,
- _ => fail!("parse_onceness: bad onceness")
+ _ => panic!("parse_onceness: bad onceness")
}
}
let variadic = match next(st) {
'V' => true,
'N' => false,
- r => fail!(format!("bad variadic: {}", r)),
+ r => panic!(format!("bad variadic: {}", r)),
+ };
+ let output = match peek(st) {
+ 'z' => {
+ st.pos += 1u;
+ ty::FnDiverging
+ }
+ _ => ty::FnConverging(parse_ty(st, |x,y| conv(x,y)))
};
- let ret_ty = parse_ty(st, |x,y| conv(x,y));
ty::FnSig {binder_id: id,
inputs: inputs,
- output: ret_ty,
+ output: output,
variadic: variadic}
}
while colon_idx < len && buf[colon_idx] != ':' as u8 { colon_idx += 1u; }
if colon_idx == len {
error!("didn't find ':' when parsing def id");
- fail!();
+ panic!();
}
let crate_part = buf[0u..colon_idx];
let crate_num = match uint::parse_bytes(crate_part, 10u) {
Some(cn) => cn as ast::CrateNum,
- None => fail!("internal error: parse_def_id: crate number expected, found {}",
+ None => panic!("internal error: parse_def_id: crate number expected, found {}",
crate_part)
};
let def_num = match uint::parse_bytes(def_part, 10u) {
Some(dn) => dn as ast::NodeId,
- None => fail!("internal error: parse_def_id: id expected, found {}",
+ None => panic!("internal error: parse_def_id: id expected, found {}",
def_part)
};
ast::DefId { krate: crate_num, node: def_num }
return builtin_bounds;
}
c => {
- fail!("parse_bounds: bad builtin bounds ('{}')", c)
+ panic!("parse_bounds: bad builtin bounds ('{}')", c)
}
}
}
return param_bounds;
}
c => {
- fail!("parse_bounds: bad bounds ('{}')", c)
+ panic!("parse_bounds: bad bounds ('{}')", c)
}
}
}
fn enc_sty(w: &mut SeekableMemWriter, cx: &ctxt, st: &ty::sty) {
match *st {
ty::ty_nil => mywrite!(w, "n"),
- ty::ty_bot => mywrite!(w, "z"),
ty::ty_bool => mywrite!(w, "b"),
ty::ty_char => mywrite!(w, "c"),
ty::ty_int(t) => {
enc_substs(w, cx, substs);
mywrite!(w, "]");
}
- ty::ty_unboxed_closure(def, region) => {
- mywrite!(w, "k{}", (cx.ds)(def));
+ ty::ty_unboxed_closure(def, region, ref substs) => {
+ mywrite!(w, "k[{}|", (cx.ds)(def));
enc_region(w, cx, region);
+ enc_substs(w, cx, substs);
+ mywrite!(w, "]");
}
ty::ty_err => {
mywrite!(w, "e");
} else {
mywrite!(w, "N");
}
- enc_ty(w, cx, fsig.output);
+ match fsig.output {
+ ty::FnConverging(result_type) => {
+ enc_ty(w, cx, result_type);
+ }
+ ty::FnDiverging => {
+ mywrite!(w, "z");
+ }
+ }
}
pub fn enc_builtin_bounds(w: &mut SeekableMemWriter, _cx: &ctxt, bs: &ty::BuiltinBounds) {
ast::DeclItem(_) => false,
}
}
- ast::StmtMac(..) => fail!("unexpanded macro in astencode")
+ ast::StmtMac(..) => panic!("unexpanded macro in astencode")
};
if use_stmt {
Some(stmt)
3 => {
typeck::vtable_error
}
- _ => fail!("bad enum variant")
+ _ => panic!("bad enum variant")
})
})
}).unwrap()
}).unwrap()
}
- _ => fail!("..")
+ _ => panic!("..")
})
})
}).unwrap()
ty::AdjustDerefRef(auto_deref_ref)
}
- _ => fail!("bad enum variant for ty::AutoAdjustment")
+ _ => panic!("bad enum variant for ty::AutoAdjustment")
})
})
}).unwrap()
ty::AutoUnsafe(m, a)
}
- _ => fail!("bad enum variant for ty::AutoRef")
+ _ => panic!("bad enum variant for ty::AutoRef")
})
})
}).unwrap()
substs: substs };
ty::UnsizeVtable(ty_trait, self_ty)
}
- _ => fail!("bad enum variant for ty::UnsizeKind")
+ _ => panic!("bad enum variant for ty::UnsizeKind")
})
})
}).unwrap()
0 => ty::FnUnboxedClosureKind,
1 => ty::FnMutUnboxedClosureKind,
2 => ty::FnOnceUnboxedClosureKind,
- _ => fail!("bad enum variant for ty::UnboxedClosureKind"),
+ _ => panic!("bad enum variant for ty::UnboxedClosureKind"),
})
}).unwrap();
ty::UnboxedClosure {
assert!(pprust::item_to_string(&*item_out) ==
pprust::item_to_string(&*item_exp));
}
- _ => fail!()
+ _ => panic!()
}
}
// Otherwise, just a plain error.
match assignee_cmt.note {
mc::NoteClosureEnv(upvar_id) => {
- self.bccx.span_err(
- assignment_span,
- format!("cannot assign to {}",
- self.bccx.cmt_to_string(&*assignee_cmt)).as_slice());
- self.bccx.span_note(
- self.tcx().map.span(upvar_id.closure_expr_id),
- "consider changing this closure to take self by mutable reference");
+ // If this is an `Fn` closure, it simply can't mutate upvars.
+ // If it's an `FnMut` closure, the original variable was declared immutable.
+ // We need to determine which is the case here.
+ let kind = match assignee_cmt.upvar().unwrap().cat {
+ mc::cat_upvar(mc::Upvar { kind, .. }) => kind,
+ _ => unreachable!()
+ };
+ if kind == ty::FnUnboxedClosureKind {
+ self.bccx.span_err(
+ assignment_span,
+ format!("cannot assign to {}",
+ self.bccx.cmt_to_string(&*assignee_cmt)).as_slice());
+ self.bccx.span_note(
+ self.tcx().map.span(upvar_id.closure_expr_id),
+ "consider changing this closure to take self by mutable reference");
+ } else {
+ self.bccx.span_err(
+ assignment_span,
+ format!("cannot assign to {} {}",
+ assignee_cmt.mutbl.to_user_str(),
+ self.bccx.cmt_to_string(&*assignee_cmt)).as_slice());
+ }
}
_ => match opt_loan_path(&assignee_cmt) {
Some(lp) => {
mc::cat_rvalue(..) |
mc::cat_static_item |
mc::cat_deref(_, _, mc::UnsafePtr(..)) |
- mc::cat_deref(_, _, mc::BorrowedPtr(..)) |
mc::cat_deref(_, _, mc::Implicit(..)) => {
assert_eq!(cmt.mutbl, mc::McDeclared);
return;
}
+ mc::cat_deref(_, _, mc::BorrowedPtr(..)) => {
+ assert_eq!(cmt.mutbl, mc::McDeclared);
+ // We need to drill down to upvar if applicable
+ match cmt.upvar() {
+ Some(b) => cmt = b,
+ None => return
+ }
+ }
+
mc::cat_deref(b, _, mc::OwnedPtr) => {
assert_eq!(cmt.mutbl, mc::McInherited);
cmt = b;
which defines the `Drop` trait",
b.ty.user_string(bccx.tcx)).as_slice());
},
- _ => fail!("this path should not cause illegal move")
+ _ => panic!("this path should not cause illegal move")
}
}
- _ => fail!("this path should not cause illegal move")
+ _ => panic!("this path should not cause illegal move")
}
}
ast::ExprProc(_, ref block) |
ast::ExprFnBlock(_, _, ref block) |
ast::ExprUnboxedFn(_, _, _, ref block) => { block.id }
- _ => fail!("encountered non-closure id: {}", closure_id)
+ _ => panic!("encountered non-closure id: {}", closure_id)
},
- _ => fail!("encountered non-expr id: {}", closure_id)
+ _ => panic!("encountered non-expr id: {}", closure_id)
}
}
match err.code {
err_mutbl => {
let descr = match err.cmt.note {
- mc::NoteClosureEnv(_) => {
+ mc::NoteClosureEnv(_) | mc::NoteUpvarRef(_) => {
self.cmt_to_string(&*err.cmt)
}
_ => match opt_loan_path(&err.cmt) {
match code {
err_mutbl(..) => {
match err.cmt.note {
- mc::NoteClosureEnv(upvar_id) => {
- self.tcx.sess.span_note(
- self.tcx.map.span(upvar_id.closure_expr_id),
- "consider changing this closure to take \
- self by mutable reference");
+ mc::NoteClosureEnv(upvar_id) | mc::NoteUpvarRef(upvar_id) => {
+ // If this is an `Fn` closure, it simply can't mutate upvars.
+ // If it's an `FnMut` closure, the original variable was declared immutable.
+ // We need to determine which is the case here.
+ let kind = match err.cmt.upvar().unwrap().cat {
+ mc::cat_upvar(mc::Upvar { kind, .. }) => kind,
+ _ => unreachable!()
+ };
+ if kind == ty::FnUnboxedClosureKind {
+ self.tcx.sess.span_note(
+ self.tcx.map.span(upvar_id.closure_expr_id),
+ "consider changing this closure to take \
+ self by mutable reference");
+ }
}
_ => {}
}
pred: CFGIndex,
func_or_rcvr: &ast::Expr,
args: I) -> CFGIndex {
+ let method_call = typeck::MethodCall::expr(call_expr.id);
+ let return_ty = ty::ty_fn_ret(match self.tcx.method_map.borrow().find(&method_call) {
+ Some(method) => method.ty,
+ None => ty::expr_ty(self.tcx, func_or_rcvr)
+ });
+
let func_or_rcvr_exit = self.expr(func_or_rcvr, pred);
let ret = self.straightline(call_expr, func_or_rcvr_exit, args);
-
- let return_ty = ty::node_id_to_type(self.tcx, call_expr.id);
- let fails = ty::type_is_bot(return_ty);
- if fails {
+ if return_ty == ty::FnDiverging {
self.add_node(ast::DUMMY_NODE_ID, [])
} else {
ret
}
}
ExprLit(_) => (),
- ExprCast(_, _) => {
- let ety = ty::expr_ty(v.tcx, e);
- if !ty::type_is_numeric(ety) && !ty::type_is_unsafe_ptr(ety) {
+ ExprCast(ref from, _) => {
+ let toty = ty::expr_ty(v.tcx, e);
+ let fromty = ty::expr_ty(v.tcx, &**from);
+ if !ty::type_is_numeric(toty) && !ty::type_is_unsafe_ptr(toty) {
span_err!(v.tcx.sess, e.span, E0012,
"can not cast to `{}` in a constant expression",
- ppaux::ty_to_string(v.tcx, ety));
+ ppaux::ty_to_string(v.tcx, toty));
+ }
+ if ty::type_is_unsafe_ptr(fromty) && ty::type_is_numeric(toty) {
+ span_err!(v.tcx.sess, e.span, E0018,
+ "can not cast a pointer to an integer in a constant \
+ expression");
}
}
ExprPath(ref pth) => {
node: FieldPat {
ident: Ident::new(field.name),
pat: pat,
- is_shorthand: true,
+ is_shorthand: false,
}
}).collect();
let has_more_fields = field_pats.len() < pats_len;
Some(&DefStatic(def_id, _)) |
Some(&DefConst(def_id)) if
ast_util::is_local(def_id) => {
- self.visit_item(&*self.ast_map.expect_item(def_id.node));
+ match self.ast_map.get(def_id.node) {
+ ast_map::NodeItem(item) =>
+ self.visit_item(item),
+ ast_map::NodeForeignItem(_) => {},
+ _ => {
+ self.sess.span_err(e.span,
+ format!("expected item, found {}",
+ self.ast_map.node_to_string(def_id.node)).as_slice());
+ return;
+ },
+ }
}
_ => ()
}
node: FieldPat {
ident: field.ident.node,
pat: const_expr_to_pat(tcx, &*field.expr),
- is_shorthand: true,
+ is_shorthand: false,
},
}).collect();
PatStruct(path.clone(), field_pats, false)
fn to_cfgidx_or_die(id: ast::NodeId, index: &NodeMap<CFGIndex>) -> CFGIndex {
let opt_cfgindex = index.find(&id).map(|&i|i);
opt_cfgindex.unwrap_or_else(|| {
- fail!("nodeid_to_index does not have entry for NodeId {}", id);
+ panic!("nodeid_to_index does not have entry for NodeId {}", id);
})
}
local_def(id)
}
- DefPrimTy(_) => fail!()
+ DefPrimTy(_) => panic!()
}
}
// make sure that the thing we are pointing out stays valid
// for the lifetime `scope_r` of the resulting ptr:
let expr_ty = ty::expr_ty(self.tcx(), expr);
- if !ty::type_is_bot(expr_ty) {
- let r = ty::ty_region(self.tcx(), expr.span, expr_ty);
- let bk = ty::BorrowKind::from_mutbl(m);
- self.borrow_expr(&**base, r, bk, AddrOf);
- } else {
- self.walk_expr(&**base);
- }
+ let r = ty::ty_region(self.tcx(), expr.span, expr_ty);
+ let bk = ty::BorrowKind::from_mutbl(m);
+ self.borrow_expr(&**base, r, bk, AddrOf);
}
ast::ExprInlineAsm(ref ia) => {
match ty::get(typ).sty {
ty_bare_fn(ref bare_fn_ty)
if bare_fn_ty.abi == RustIntrinsic => {
- let from = bare_fn_ty.sig.inputs[0];
- let to = bare_fn_ty.sig.output;
- self.check_transmute(expr.span, from, to, expr.id);
+ if let ty::FnConverging(to) = bare_fn_ty.sig.output {
+ let from = bare_fn_ty.sig.inputs[0];
+ self.check_transmute(expr.span, from, to, expr.id);
+ }
}
_ => {
self.tcx
StrEqFnLangItem, "str_eq", str_eq_fn;
- // A number of failure-related lang items. The `fail` item corresponds to
- // divide-by-zero and various failure cases with `match`. The
- // `fail_bounds_check` item is for indexing arrays.
+ // A number of panic-related lang items. The `panic` item corresponds to
+ // divide-by-zero and various panic cases with `match`. The
+ // `panic_bounds_check` item is for indexing arrays.
//
// The `begin_unwind` lang item has a predefined symbol name and is sort of
// a "weak lang item" in the sense that a crate is not required to have it
// defined to use it, but a final product is required to define it
// somewhere. Additionally, there are restrictions on crates that use a weak
// lang item, but do not have it defined.
- FailFnLangItem, "fail", fail_fn;
- FailBoundsCheckFnLangItem, "fail_bounds_check", fail_bounds_check_fn;
- FailFmtLangItem, "fail_fmt", fail_fmt;
+ PanicFnLangItem, "panic", panic_fn;
+ PanicBoundsCheckFnLangItem, "panic_bounds_check", panic_bounds_check_fn;
+ PanicFmtLangItem, "panic_fmt", panic_fmt;
ExchangeMallocFnLangItem, "exchange_malloc", exchange_malloc_fn;
ExchangeFreeFnLangItem, "exchange_free", exchange_free_fn;
* These are described in the `specials` struct:
*
* - `exit_ln`: a live node that is generated to represent every 'exit' from
- * the function, whether it be by explicit return, fail, or other means.
+ * the function, whether it be by explicit return, panic, or other means.
*
* - `fallthrough_ln`: a live node that represents a fallthrough
*
* - `no_ret_var`: a synthetic variable that is only 'read' from, the
* fallthrough node. This allows us to detect functions where we fail
* to return explicitly.
+ * - `clean_exit_var`: a synthetic variable that is only 'read' from the
+ * fallthrough node. It is only live if the function could converge
+ * via means other than an explicit `return` expression. That is, it is
+ * only dead if the end of the function's block can never be reached.
+ * It is the responsibility of typeck to ensure that there are no
+ * `return` expressions in a function declared as diverging.
*/
use middle::def::*;
use middle::mem_categorization::Typer;
use middle::pat_util;
+use middle::typeck;
use middle::ty;
use lint;
use util::nodemap::NodeMap;
enum VarKind {
Arg(NodeId, Ident),
Local(LocalInfo),
- ImplicitRet
+ ImplicitRet,
+ CleanExit
}
struct IrMaps<'a, 'tcx: 'a> {
Local(LocalInfo { id: node_id, .. }) | Arg(node_id, _) => {
self.variable_map.insert(node_id, v);
},
- ImplicitRet => {}
+ ImplicitRet | CleanExit => {}
}
debug!("{} is {}", v.to_string(), vk);
Local(LocalInfo { ident: nm, .. }) | Arg(_, nm) => {
token::get_ident(nm).get().to_string()
},
- ImplicitRet => "<implicit-ret>".to_string()
+ ImplicitRet => "<implicit-ret>".to_string(),
+ CleanExit => "<clean-exit>".to_string()
}
}
visit::walk_fn(&mut fn_maps, fk, decl, body, sp);
// Special nodes and variables:
- // - exit_ln represents the end of the fn, either by return or fail
+ // - exit_ln represents the end of the fn, either by return or panic
// - implicit_ret_var is a pseudo-variable that represents
// an implicit return
let specials = Specials {
exit_ln: fn_maps.add_live_node(ExitNode),
fallthrough_ln: fn_maps.add_live_node(ExitNode),
- no_ret_var: fn_maps.add_variable(ImplicitRet)
+ no_ret_var: fn_maps.add_variable(ImplicitRet),
+ clean_exit_var: fn_maps.add_variable(CleanExit)
};
// compute liveness
struct Specials {
exit_ln: LiveNode,
fallthrough_ln: LiveNode,
- no_ret_var: Variable
+ no_ret_var: Variable,
+ clean_exit_var: Variable
}
static ACC_READ: uint = 1u;
if blk.expr.is_none() {
self.acc(s.fallthrough_ln, s.no_ret_var, ACC_READ)
}
+ self.acc(s.fallthrough_ln, s.clean_exit_var, ACC_READ);
self.propagate_through_block(blk, s.fallthrough_ln)
}
opt_expr: Option<&Expr>,
succ: LiveNode)
-> LiveNode {
- opt_expr.iter().fold(succ, |succ, expr| {
- self.propagate_through_expr(&**expr, succ)
- })
+ opt_expr.map_or(succ, |expr| self.propagate_through_expr(expr, succ))
}
fn propagate_through_expr(&mut self, expr: &Expr, succ: LiveNode)
}
ExprCall(ref f, ref args) => {
- // calling a fn with bot return type means that the fn
- // will fail, and hence the successors can be ignored
- let is_bot = !self.ir.tcx.is_method_call(expr.id) && {
+ let diverges = !self.ir.tcx.is_method_call(expr.id) && {
let t_ret = ty::ty_fn_ret(ty::expr_ty(self.ir.tcx, &**f));
- ty::type_is_bot(t_ret)
+ t_ret == ty::FnDiverging
};
- let succ = if is_bot {
+ let succ = if diverges {
self.s.exit_ln
} else {
succ
}
ExprMethodCall(_, _, ref args) => {
- // calling a method with bot return type means that the method
- // will fail, and hence the successors can be ignored
- let t_ret = ty::node_id_to_type(self.ir.tcx, expr.id);
- let succ = if ty::type_is_bot(t_ret) {self.s.exit_ln}
- else {succ};
+ let method_call = typeck::MethodCall::expr(expr.id);
+ let method_ty = self.ir.tcx.method_map.borrow().find(&method_call).unwrap().ty;
+ let diverges = ty::ty_fn_ret(method_ty) == ty::FnDiverging;
+ let succ = if diverges {
+ self.s.exit_ln
+ } else {
+ succ
+ };
self.propagate_through_exprs(args.as_slice(), succ)
}
}
impl<'a, 'tcx> Liveness<'a, 'tcx> {
+ fn fn_ret(&self, id: NodeId) -> ty::FnOutput {
+ let fn_ty = ty::node_id_to_type(self.ir.tcx, id);
+ match ty::get(fn_ty).sty {
+ ty::ty_unboxed_closure(closure_def_id, _, _) =>
+ self.ir.tcx.unboxed_closures()
+ .borrow()
+ .find(&closure_def_id)
+ .unwrap()
+ .closure_type
+ .sig
+ .output,
+ _ => ty::ty_fn_ret(fn_ty)
+ }
+ }
+
fn check_ret(&self,
id: NodeId,
sp: Span,
_fk: FnKind,
entry_ln: LiveNode,
body: &Block) {
- if self.live_on_entry(entry_ln, self.s.no_ret_var).is_some() {
- // if no_ret_var is live, then we fall off the end of the
- // function without any kind of return expression:
-
- let t_ret = ty::ty_fn_ret(ty::node_id_to_type(self.ir.tcx, id));
- if ty::type_is_nil(t_ret) {
- // for nil return types, it is ok to not return a value expl.
- } else if ty::type_is_bot(t_ret) {
- // for bot return types, not ok. Function should fail.
- self.ir.tcx.sess.span_err(
- sp, "some control paths may return");
- } else {
- let ends_with_stmt = match body.expr {
- None if body.stmts.len() > 0 =>
- match body.stmts.last().unwrap().node {
- StmtSemi(ref e, _) => {
- let t_stmt = ty::expr_ty(self.ir.tcx, &**e);
- ty::get(t_stmt).sty == ty::get(t_ret).sty
+ match self.fn_ret(id) {
+ ty::FnConverging(t_ret)
+ if self.live_on_entry(entry_ln, self.s.no_ret_var).is_some() => {
+
+ if ty::type_is_nil(t_ret) {
+ // for nil return types, it is ok to not return a value expl.
+ } else {
+ let ends_with_stmt = match body.expr {
+ None if body.stmts.len() > 0 =>
+ match body.stmts.last().unwrap().node {
+ StmtSemi(ref e, _) => {
+ let t_stmt = ty::expr_ty(self.ir.tcx, &**e);
+ ty::get(t_stmt).sty == ty::get(t_ret).sty
+ },
+ _ => false
},
- _ => false
- },
- _ => false
- };
- self.ir.tcx.sess.span_err(
- sp, "not all control paths return a value");
- if ends_with_stmt {
- let last_stmt = body.stmts.last().unwrap();
- let original_span = original_sp(self.ir.tcx.sess.codemap(),
- last_stmt.span, sp);
- let span_semicolon = Span {
- lo: original_span.hi - BytePos(1),
- hi: original_span.hi,
- expn_id: original_span.expn_id
+ _ => false
};
- self.ir.tcx.sess.span_note(
- span_semicolon, "consider removing this semicolon:");
+ self.ir.tcx.sess.span_err(
+ sp, "not all control paths return a value");
+ if ends_with_stmt {
+ let last_stmt = body.stmts.last().unwrap();
+ let original_span = original_sp(self.ir.tcx.sess.codemap(),
+ last_stmt.span, sp);
+ let span_semicolon = Span {
+ lo: original_span.hi - BytePos(1),
+ hi: original_span.hi,
+ expn_id: original_span.expn_id
+ };
+ self.ir.tcx.sess.span_note(
+ span_semicolon, "consider removing this semicolon:");
+ }
}
- }
+ }
+ ty::FnDiverging
+ if self.live_on_entry(entry_ln, self.s.clean_exit_var).is_some() => {
+ self.ir.tcx.sess.span_err(sp,
+ "computation may converge in a function marked as diverging");
+ }
+
+ _ => {}
}
}
Some(method_ty) => {
// If this is an index implemented by a method call, then it will
// include an implicit deref of the result.
- let ret_ty = ty::ty_fn_ret(method_ty);
+ let ret_ty = ty::ty_fn_ret(method_ty).unwrap();
Ok(self.cat_deref(expr,
self.cat_rvalue_node(expr.id(),
expr.span(),
};
self.cat_upvar(id, span, var_id, fn_node_id, kind, mode, false)
}
- ty::ty_unboxed_closure(closure_id, _) => {
+ ty::ty_unboxed_closure(closure_id, _, _) => {
let unboxed_closures = self.typer.unboxed_closures().borrow();
let kind = (*unboxed_closures)[closure_id].kind;
let mode = self.typer.capture_mode(fn_node_id);
// FnOnce | copied | upvar -> &'up bk
// old stack | N/A | upvar -> &'env mut -> &'up bk
// old proc/once | copied | N/A
+ let var_ty = if_ok!(self.node_ty(var_id));
+
let upvar_id = ty::UpvarId { var_id: var_id,
closure_expr_id: fn_node_id };
- // Do we need to deref through an env reference?
- let has_env_deref = kind != ty::FnOnceUnboxedClosureKind;
-
// Mutability of original variable itself
let var_mutbl = MutabilityCategory::from_local(self.tcx(), var_id);
- // Mutability of environment dereference
- let env_mutbl = match kind {
- ty::FnOnceUnboxedClosureKind => var_mutbl,
- ty::FnMutUnboxedClosureKind => McInherited,
- ty::FnUnboxedClosureKind => McImmutable
+ // Construct information about env pointer dereference, if any
+ let mutbl = match kind {
+ ty::FnOnceUnboxedClosureKind => None, // None, env is by-value
+ ty::FnMutUnboxedClosureKind => match mode { // Depends on capture type
+ ast::CaptureByValue => Some(var_mutbl), // Mutable if the original var is
+ ast::CaptureByRef => Some(McDeclared) // Mutable regardless
+ },
+ ty::FnUnboxedClosureKind => Some(McImmutable) // Never mutable
};
+ let env_info = mutbl.map(|env_mutbl| {
+ // Look up the node ID of the closure body so we can construct
+ // a free region within it
+ let fn_body_id = {
+ let fn_expr = match self.tcx().map.find(fn_node_id) {
+ Some(ast_map::NodeExpr(e)) => e,
+ _ => unreachable!()
+ };
- // Look up the node ID of the closure body so we can construct
- // a free region within it
- let fn_body_id = {
- let fn_expr = match self.tcx().map.find(fn_node_id) {
- Some(ast_map::NodeExpr(e)) => e,
- _ => unreachable!()
+ match fn_expr.node {
+ ast::ExprFnBlock(_, _, ref body) |
+ ast::ExprProc(_, ref body) |
+ ast::ExprUnboxedFn(_, _, _, ref body) => body.id,
+ _ => unreachable!()
+ }
};
- match fn_expr.node {
- ast::ExprFnBlock(_, _, ref body) |
- ast::ExprProc(_, ref body) |
- ast::ExprUnboxedFn(_, _, _, ref body) => body.id,
- _ => unreachable!()
- }
- };
+ // Region of environment pointer
+ let env_region = ty::ReFree(ty::FreeRegion {
+ scope_id: fn_body_id,
+ bound_region: ty::BrEnv
+ });
- // Region of environment pointer
- let env_region = ty::ReFree(ty::FreeRegion {
- scope_id: fn_body_id,
- bound_region: ty::BrEnv
- });
-
- let env_ptr = BorrowedPtr(if env_mutbl.is_mutable() {
- ty::MutBorrow
- } else {
- ty::ImmBorrow
- }, env_region);
+ let env_ptr = BorrowedPtr(if env_mutbl.is_mutable() {
+ ty::MutBorrow
+ } else {
+ ty::ImmBorrow
+ }, env_region);
- let var_ty = if_ok!(self.node_ty(var_id));
+ (env_mutbl, env_ptr)
+ });
// First, switch by capture mode
Ok(match mode {
note: NoteNone
};
- if has_env_deref {
- // We need to add the env deref. This means that
- // the above is actually immutable and has a ref
- // type. However, nothing should actually look at
- // the type, so we can get away with stuffing a
- // `ty_err` in there instead of bothering to
- // construct a proper one.
- base.mutbl = McImmutable;
- base.ty = ty::mk_err();
- Rc::new(cmt_ {
- id: id,
- span: span,
- cat: cat_deref(Rc::new(base), 0, env_ptr),
- mutbl: env_mutbl,
- ty: var_ty,
- note: NoteClosureEnv(upvar_id)
- })
- } else {
- Rc::new(base)
+ match env_info {
+ Some((env_mutbl, env_ptr)) => {
+ // We need to add the env deref. This means
+ // that the above is actually immutable and
+ // has a ref type. However, nothing should
+ // actually look at the type, so we can get
+ // away with stuffing a `ty_err` in there
+ // instead of bothering to construct a proper
+ // one.
+ base.mutbl = McImmutable;
+ base.ty = ty::mk_err();
+ Rc::new(cmt_ {
+ id: id,
+ span: span,
+ cat: cat_deref(Rc::new(base), 0, env_ptr),
+ mutbl: env_mutbl,
+ ty: var_ty,
+ note: NoteClosureEnv(upvar_id)
+ })
+ }
+ None => Rc::new(base)
}
},
ast::CaptureByRef => {
note: NoteNone
};
- // As in the by-value case, add env deref if needed
- if has_env_deref {
- base = cmt_ {
- id: id,
- span: span,
- cat: cat_deref(Rc::new(base), 0, env_ptr),
- mutbl: env_mutbl,
- ty: ty::mk_err(),
- note: NoteClosureEnv(upvar_id)
- };
+ match env_info {
+ Some((env_mutbl, env_ptr)) => {
+ base = cmt_ {
+ id: id,
+ span: span,
+ cat: cat_deref(Rc::new(base), 0, env_ptr),
+ mutbl: env_mutbl,
+ ty: ty::mk_err(),
+ note: NoteClosureEnv(upvar_id)
+ };
+ }
+ None => {}
}
// Look up upvar borrow so we can get its region
let base_cmt = match method_ty {
Some(method_ty) => {
- let ref_ty = ty::ty_fn_ret(method_ty);
+ let ref_ty = ty::ty_fn_ret(method_ty).unwrap();
self.cat_rvalue_node(node.id(), node.span(), ref_ty)
}
None => base_cmt
let element_ty = match method_ty {
Some(method_ty) => {
- let ref_ty = ty::ty_fn_ret(method_ty);
+ let ref_ty = ty::ty_fn_ret(method_ty).unwrap();
base_cmt = self.cat_rvalue_node(elt.id(), elt.span(), ref_ty);
ty::ty_fn_args(method_ty)[0]
}
//! Returns the narrowest scope that encloses `id`, if any.
match self.scope_map.borrow().find(&id) {
Some(&r) => r,
- None => { fail!("no enclosing scope for id {}", id); }
+ None => { panic!("no enclosing scope for id {}", id); }
}
}
*/
match self.var_map.borrow().find(&var_id) {
Some(&r) => r,
- None => { fail!("no enclosing scope for id {}", var_id); }
+ None => { panic!("no enclosing scope for id {}", var_id); }
}
}
fn get_module(&self) -> Rc<Module> {
match self.get_module_if_available() {
None => {
- fail!("get_module called on a node with no module \
+ panic!("get_module called on a node with no module \
definition!")
}
Some(module_def) => module_def
DefLocal(..) | DefPrimTy(..) | DefTyParam(..) |
DefUse(..) | DefUpvar(..) | DefRegion(..) |
DefTyParamBinder(..) | DefLabel(..) | DefSelfTy(..) => {
- fail!("didn't expect `{}`", def);
+ panic!("didn't expect `{}`", def);
}
}
}
}
UnboundResult => { /* Continue. */ }
UnknownResult => {
- fail!("value result should be known at this point");
+ panic!("value result should be known at this point");
}
}
match type_result {
}
UnboundResult => { /* Continue. */ }
UnknownResult => {
- fail!("type result should be known at this point");
+ panic!("type result should be known at this point");
}
}
target.bindings.value_def.borrow());
match *target.bindings.value_def.borrow() {
None => {
- fail!("resolved name in the value namespace to a \
+ panic!("resolved name in the value namespace to a \
set of name bindings with no def?!");
}
Some(def) => {
}
Indeterminate => {
- fail!("unexpected indeterminate result");
+ panic!("unexpected indeterminate result");
}
Failed(err) => {
match err {
msg.as_slice()));
return None;
}
- Indeterminate => fail!("indeterminate unexpected"),
+ Indeterminate => panic!("indeterminate unexpected"),
Success((resulting_module, resulting_last_private)) => {
containing_module = resulting_module;
last_private = resulting_last_private;
}
Indeterminate => {
- fail!("indeterminate unexpected");
+ panic!("indeterminate unexpected");
}
Success((resulting_module, resulting_last_private)) => {
}
}
Indeterminate => {
- fail!("unexpected indeterminate result");
+ panic!("unexpected indeterminate result");
}
Failed(err) => {
match err {
type_used: _
}) => (v, t),
Some(_) => {
- fail!("we should only have LastImport for `use` directives")
+ panic!("we should only have LastImport for `use` directives")
}
_ => return,
};
let qualname = format!("{}::{}", qualname, name);
let typ = ppaux::ty_to_string(&self.analysis.ty_cx,
(*self.analysis.ty_cx.node_types.borrow())[field.node.id as uint]);
- match self.span.sub_span_before_token(field.span, token::COLON) {
+ match self.span.sub_span_before_token(field.span, token::Colon) {
Some(sub_span) => self.fmt.field_str(field.span,
Some(sub_span),
field.node.id,
// 'use' always introduces an alias, if there is not an explicit
// one, there is an implicit one.
let sub_span =
- match self.span.sub_span_before_token(path.span, token::EQ) {
+ match self.span.sub_span_before_token(path.span, token::Eq) {
Some(sub_span) => Some(sub_span),
None => sub_span,
};
use syntax::parse::lexer;
use syntax::parse::lexer::{Reader,StringReader};
use syntax::parse::token;
-use syntax::parse::token::{is_keyword,keywords,is_ident,Token};
+use syntax::parse::token::{keywords, Token};
pub struct SpanUtils<'a> {
pub sess: &'a Session,
let mut bracket_count = 0u;
loop {
let ts = toks.next_token();
- if ts.tok == token::EOF {
+ if ts.tok == token::Eof {
return self.make_sub_span(span, result)
}
if bracket_count == 0 &&
- (is_ident(&ts.tok) || is_keyword(keywords::Self, &ts.tok)) {
+ (ts.tok.is_ident() || ts.tok.is_keyword(keywords::Self)) {
result = Some(ts.sp);
}
bracket_count += match ts.tok {
- token::LT => 1,
- token::GT => -1,
- token::BINOP(token::SHR) => -2,
+ token::Lt => 1,
+ token::Gt => -1,
+ token::BinOp(token::Shr) => -2,
_ => 0
}
}
let mut bracket_count = 0u;
loop {
let ts = toks.next_token();
- if ts.tok == token::EOF {
+ if ts.tok == token::Eof {
return None;
}
if bracket_count == 0 &&
- (is_ident(&ts.tok) || is_keyword(keywords::Self, &ts.tok)) {
+ (ts.tok.is_ident() || ts.tok.is_keyword(keywords::Self)) {
return self.make_sub_span(span, Some(ts.sp));
}
bracket_count += match ts.tok {
- token::LT => 1,
- token::GT => -1,
- token::BINOP(token::SHR) => -2,
+ token::Lt => 1,
+ token::Gt => -1,
+ token::BinOp(token::Shr) => -2,
_ => 0
}
}
let mut result = None;
let mut bracket_count = 0u;
let mut last_span = None;
- while prev.tok != token::EOF {
+ while prev.tok != token::Eof {
last_span = None;
let mut next = toks.next_token();
- if (next.tok == token::LPAREN ||
- next.tok == token::LT) &&
+ if (next.tok == token::LParen ||
+ next.tok == token::Lt) &&
bracket_count == 0 &&
- is_ident(&prev.tok) {
+ prev.tok.is_ident() {
result = Some(prev.sp);
}
if bracket_count == 0 &&
- next.tok == token::MOD_SEP {
+ next.tok == token::ModSep {
let old = prev;
prev = next;
next = toks.next_token();
- if next.tok == token::LT &&
- is_ident(&old.tok) {
+ if next.tok == token::Lt &&
+ old.tok.is_ident() {
result = Some(old.sp);
}
}
bracket_count += match prev.tok {
- token::LPAREN | token::LT => 1,
- token::RPAREN | token::GT => -1,
- token::BINOP(token::SHR) => -2,
+ token::LParen | token::Lt => 1,
+ token::RParen | token::Gt => -1,
+ token::BinOp(token::Shr) => -2,
_ => 0
};
- if is_ident(&prev.tok) && bracket_count == 0 {
+ if prev.tok.is_ident() && bracket_count == 0 {
last_span = Some(prev.sp);
}
prev = next;
loop {
let next = toks.next_token();
- if (next.tok == token::LT ||
- next.tok == token::COLON) &&
+ if (next.tok == token::Lt ||
+ next.tok == token::Colon) &&
bracket_count == 0 &&
- is_ident(&prev.tok) {
+ prev.tok.is_ident() {
result = Some(prev.sp);
}
bracket_count += match prev.tok {
- token::LT => 1,
- token::GT => -1,
- token::BINOP(token::SHR) => -2,
+ token::Lt => 1,
+ token::Gt => -1,
+ token::BinOp(token::Shr) => -2,
_ => 0
};
- if next.tok == token::EOF {
+ if next.tok == token::Eof {
break;
}
prev = next;
format!("Mis-counted brackets when breaking path? Parsing '{}' in {}, line {}",
self.snippet(span), loc.file.name, loc.line).as_slice());
}
- if result.is_none() && is_ident(&prev.tok) && bracket_count == 0 {
+ if result.is_none() && prev.tok.is_ident() && bracket_count == 0 {
return self.make_sub_span(span, Some(prev.sp));
}
self.make_sub_span(span, result)
let mut bracket_count = 0i;
loop {
let ts = toks.next_token();
- if ts.tok == token::EOF {
+ if ts.tok == token::Eof {
if bracket_count != 0 {
let loc = self.sess.codemap().lookup_char_pos(span.lo);
self.sess.span_bug(span, format!(
return result;
}
bracket_count += match ts.tok {
- token::LT => 1,
- token::GT => -1,
- token::BINOP(token::SHL) => 2,
- token::BINOP(token::SHR) => -2,
+ token::Lt => 1,
+ token::Gt => -1,
+ token::BinOp(token::Shl) => 2,
+ token::BinOp(token::Shr) => -2,
_ => 0
};
- if is_ident(&ts.tok) &&
+ if ts.tok.is_ident() &&
bracket_count == nesting {
result.push(self.make_sub_span(span, Some(ts.sp)).unwrap());
}
let mut toks = self.retokenise_span(span);
let mut prev = toks.next_token();
loop {
- if prev.tok == token::EOF {
+ if prev.tok == token::Eof {
return None;
}
let next = toks.next_token();
let mut toks = self.retokenise_span(span);
loop {
let ts = toks.next_token();
- if ts.tok == token::EOF {
+ if ts.tok == token::Eof {
return None;
}
- if is_keyword(keyword, &ts.tok) {
+ if ts.tok.is_keyword(keyword) {
let ts = toks.next_token();
- if ts.tok == token::EOF {
+ if ts.tok == token::Eof {
return None
} else {
return self.make_sub_span(span, Some(ts.sp));
*/
match self.regions {
- ErasedRegions => fail!("Erased regions only expected in trans"),
+ ErasedRegions => panic!("Erased regions only expected in trans"),
NonerasedRegions(ref r) => r
}
}
*/
match self.regions {
- ErasedRegions => fail!("Erased regions only expected in trans"),
+ ErasedRegions => panic!("Erased regions only expected in trans"),
NonerasedRegions(ref mut r) => r
}
}
0 => TypeSpace,
1 => SelfSpace,
2 => FnSpace,
- _ => fail!("Invalid ParamSpace: {}", u)
+ _ => panic!("Invalid ParamSpace: {}", u)
}
}
}
match ty::get(ty).sty {
ty::ty_nil |
- ty::ty_bot |
ty::ty_bool |
ty::ty_char |
ty::ty_int(..) |
type of the receiver and various other complications. The procedure is
described in `select.rs` in the "METHOD MATCHING" section.
+# Caching and subtle considerations therewith
+
+In general we attempt to cache the results of trait selection. This
+is a somewhat complex process. Part of the reason for this is that we
+want to be able to cache results even when all the types in the trait
+reference are not fully known. In that case, it may happen that the
+trait selection process is also influencing type variables, so we have
+to be able to not only cache the *result* of the selection process,
+but *replay* its effects on the type variables.
+
+## An example
+
+The high-level idea of how the cache works is that we first replace
+all unbound inference variables with skolemized versions. Therefore,
+if we had a trait reference `uint : Foo<$1>`, where `$n` is an unbound
+inference variable, we might replace it with `uint : Foo<%0>`, where
+`%n` is a skolemized type. We would then look this up in the cache.
+If we found a hit, the hit would tell us the immediate next step to
+take in the selection process: i.e., apply impl #22, or apply where
+clause `X : Foo<Y>`. Let's say in this case there is no hit.
+Therefore, we search through impls and where clauses and so forth, and
+we come to the conclusion that the only possible impl is this one,
+with def-id 22:
+
+ impl Foo<int> for uint { ... } // Impl #22
+
+We would then record in the cache `uint : Foo<%0> ==>
+ImplCandidate(22)`. Next we would confirm `ImplCandidate(22)`, which
+would (as a side-effect) unify `$1` with `int`.
+
+Now, at some later time, we might come along and see a `uint :
+Foo<$3>`. When skolemized, this would yield `uint : Foo<%0>`, just as
+before, and hence the cache lookup would succeed, yielding
+`ImplCandidate(22)`. We would confirm `ImplCandidate(22)` which would
+(as a side-effect) unify `$3` with `int`.
+
+## Where clauses and the local vs global cache
+
+One subtle interaction is that the results of trait lookup will vary
+depending on what where clauses are in scope. Therefore, we actually
+have *two* caches, a local and a global cache. The local cache is
+attached to the `ParameterEnvironment` and the global cache attached
+to the `tcx`. We use the local cache whenever the result might depend
+on the where clauses that are in scope. The determination of which
+cache to use is done by the method `pick_candidate_cache` in
+`select.rs`.
+
+There are two cases where we currently use the local cache. The
+current rules are probably more conservative than necessary.
+
+### Trait references that involve parameter types
+
+The most obvious case where you need the local environment is
+when the trait reference includes parameter types. For example,
+consider the following function:
+
+ impl<T> Vec<T> {
+ fn foo(x: T)
+ where T : Foo
+ { ... }
+
+ fn bar(x: T)
+ { ... }
+ }
+
+If there is an obligation `T : Foo`, or `int : Bar<T>`, or whatever,
+clearly the results from `foo` and `bar` are potentially different,
+since the set of where clauses in scope are different.
+
+### Trait references with unbound variables when where clauses are in scope
+
+There is another less obvious interaction which involves unbound variables
+where *only* where clauses are in scope (no impls). This manifested as
+issue #18209 (`run-pass/trait-cache-issue-18209.rs`). Consider
+this snippet:
+
+```
+pub trait Foo {
+ fn load_from() -> Box<Self>;
+ fn load() -> Box<Self> {
+ Foo::load_from()
+ }
+}
+```
+
+The default method will incur an obligation `$0 : Foo` from the call
+to `load_from`. If there are no impls, this can be eagerly resolved to
+`VtableParam(Self : Foo)` and cached. Because the trait reference
+doesn't involve any parameters types (only the resolution does), this
+result was stored in the global cache, causing later calls to
+`Foo::load_from()` to get nonsense.
+
+To fix this, we always use the local cache if there are unbound
+variables and where clauses in scope. This is more conservative than
+necessary as far as I can tell. However, it still seems to be a simple
+rule and I observe ~99% hit rate on rustc, so it doesn't seem to hurt
+us in particular.
+
+Here is an example of the kind of subtle case that I would be worried
+about with a more complex rule (although this particular case works
+out ok). Imagine the trait reference doesn't directly reference a
+where clause, but the where clause plays a role in the winnowing
+phase. Something like this:
+
+```
+pub trait Foo<T> { ... }
+pub trait Bar { ... }
+impl<U,T:Bar> Foo<U> for T { ... } // Impl A
+impl Foo<char> for uint { ... } // Impl B
+```
+
+Now, in some function, we have no where clauses in scope, and we have
+an obligation `$1 : Foo<$0>`. We might then conclude that `$0=char`
+and `$1=uint`: this is because for impl A to apply, `uint:Bar` would
+have to hold, and we know it does not or else the coherence check
+would have failed. So we might enter into our global cache: `$1 :
+Foo<$0> => Impl B`. Then we come along in a different scope, where a
+generic type `A` is around with the bound `A:Bar`. Now suddenly the
+impl is viable.
+
+The flaw in this imaginary DOOMSDAY SCENARIO is that we would not
+currently conclude that `$1 : Foo<$0>` implies that `$0 == uint` and
+`$1 == char`, even though it is true that (absent type parameters)
+there is no other type the user could enter. However, it is not
+*completely* implausible that we *could* draw this conclusion in the
+future; we wouldn't have to guess types, in particular, we could be
+led by the impls.
+
*/
// A list of all obligations that have been registered with this
// fulfillment context.
trait_obligations: Vec<Obligation>,
+
+ // Remembers the count of trait obligations that we have already
+ // attempted to select. This is used to avoid repeating work
+ // when `select_new_obligations` is called.
+ attempted_mark: uint,
}
impl FulfillmentContext {
pub fn new() -> FulfillmentContext {
FulfillmentContext {
trait_obligations: Vec::new(),
+ attempted_mark: 0,
}
}
}
}
+ pub fn select_new_obligations<'a,'tcx>(&mut self,
+ infcx: &InferCtxt<'a,'tcx>,
+ param_env: &ty::ParameterEnvironment,
+ typer: &Typer<'tcx>)
+ -> Result<(),Vec<FulfillmentError>>
+ {
+ /*!
+ * Attempts to select obligations that were registered since
+ * the call to a selection routine. This is used by the type checker
+ * to eagerly attempt to resolve obligations in hopes of gaining
+ * type information. It'd be equally valid to use `select_where_possible`
+ * but it results in `O(n^2)` performance (#18208).
+ */
+
+ let mut selcx = SelectionContext::new(infcx, param_env, typer);
+ self.select(&mut selcx, true)
+ }
+
pub fn select_where_possible<'a,'tcx>(&mut self,
infcx: &InferCtxt<'a,'tcx>,
param_env: &ty::ParameterEnvironment,
typer: &Typer<'tcx>)
-> Result<(),Vec<FulfillmentError>>
{
- let tcx = infcx.tcx;
let mut selcx = SelectionContext::new(infcx, param_env, typer);
+ self.select(&mut selcx, false)
+ }
- debug!("select_where_possible({} obligations) start",
- self.trait_obligations.len());
+ fn select(&mut self,
+ selcx: &mut SelectionContext,
+ only_new_obligations: bool)
+ -> Result<(),Vec<FulfillmentError>>
+ {
+ /*!
+ * Attempts to select obligations using `selcx`. If
+ * `only_new_obligations` is true, then it only attempts to
+ * select obligations that haven't been seen before.
+ */
+ debug!("select({} obligations, only_new_obligations={}) start",
+ self.trait_obligations.len(),
+ only_new_obligations);
+ let tcx = selcx.tcx();
let mut errors = Vec::new();
loop {
let mut selections = Vec::new();
+ // If we are only attempting obligations we haven't seen yet,
+ // then set `skip` to the number of obligations we've already
+ // seen.
+ let mut skip = if only_new_obligations {
+ self.attempted_mark
+ } else {
+ 0
+ };
+
// First pass: walk each obligation, retaining
// only those that we cannot yet process.
self.trait_obligations.retain(|obligation| {
- match selcx.select(obligation) {
- Ok(None) => {
- true
- }
- Ok(Some(s)) => {
- selections.push(s);
- false
- }
- Err(selection_err) => {
- debug!("obligation: {} error: {}",
- obligation.repr(tcx),
- selection_err.repr(tcx));
-
- errors.push(FulfillmentError::new(
- (*obligation).clone(),
- CodeSelectionError(selection_err)));
- false
+ // Hack: Retain does not pass in the index, but we want
+ // to avoid processing the first `start_count` entries.
+ if skip > 0 {
+ skip -= 1;
+ true
+ } else {
+ match selcx.select(obligation) {
+ Ok(None) => {
+ true
+ }
+ Ok(Some(s)) => {
+ selections.push(s);
+ false
+ }
+ Err(selection_err) => {
+ debug!("obligation: {} error: {}",
+ obligation.repr(tcx),
+ selection_err.repr(tcx));
+ errors.push(FulfillmentError::new(
+ (*obligation).clone(),
+ CodeSelectionError(selection_err)));
+ false
+ }
}
}
});
+ self.attempted_mark = self.trait_obligations.len();
+
if self.trait_obligations.len() == count {
// Nothing changed.
break;
}
}
- debug!("select_where_possible({} obligations, {} errors) done",
+ debug!("select({} obligations, {} errors) done",
self.trait_obligations.len(),
errors.len());
BuiltinCandidate(ty::BuiltinBound),
ParamCandidate(VtableParamData),
ImplCandidate(ast::DefId),
- UnboxedClosureCandidate(/* closure */ ast::DefId),
+ UnboxedClosureCandidate(/* closure */ ast::DefId, Substs),
ErrorCandidate,
}
// can be applied to particular types. It skips the "confirmation"
// step and hence completely ignores output type parameters.
//
- // The result is "true" if the obliation *may* hold and "false" if
+ // The result is "true" if the obligation *may* hold and "false" if
// we can be sure it does not.
pub fn evaluate_obligation_intercrate(&mut self,
cache_skol_trait_ref: &Rc<ty::TraitRef>)
-> &SelectionCache
{
+ // High-level idea: we have to decide whether to consult the
+ // cache that is specific to this scope, or to consult the
+ // global cache. We want the cache that is specific to this
+ // scope whenever where clauses might affect the result.
+
// If the trait refers to any parameters in scope, then use
- // the cache of the param-environment. This is because the
- // result will depend on the where clauses that are in
- // scope. Otherwise, use the generic tcx cache, since the
- // result holds across all environments.
+ // the cache of the param-environment.
if
cache_skol_trait_ref.input_types().iter().any(
|&t| ty::type_has_self(t) || ty::type_has_params(t))
{
- &self.param_env.selection_cache
- } else {
- &self.tcx().selection_cache
+ return &self.param_env.selection_cache;
+ }
+
+ // If the trait refers to unbound type variables, and there
+ // are where clauses in scope, then use the local environment.
+ // If there are no where clauses in scope, which is a very
+ // common case, then we can use the global environment.
+ // See the discussion in doc.rs for more details.
+ if
+ !self.param_env.caller_obligations.is_empty()
+ &&
+ cache_skol_trait_ref.input_types().iter().any(
+ |&t| ty::type_has_ty_infer(t))
+ {
+ return &self.param_env.selection_cache;
}
+
+ // Otherwise, we can use the global cache.
+ &self.tcx().selection_cache
}
fn check_candidate_cache(&mut self,
};
let self_ty = self.infcx.shallow_resolve(obligation.self_ty());
- let closure_def_id = match ty::get(self_ty).sty {
- ty::ty_unboxed_closure(id, _) => id,
+ let (closure_def_id, substs) = match ty::get(self_ty).sty {
+ ty::ty_unboxed_closure(id, _, ref substs) => (id, substs.clone()),
ty::ty_infer(ty::TyVar(_)) => {
candidates.ambiguous = true;
return Ok(());
};
if closure_kind == kind {
- candidates.vec.push(UnboxedClosureCandidate(closure_def_id));
+ candidates.vec.push(UnboxedClosureCandidate(closure_def_id, substs.clone()));
}
Ok(())
ty::ty_uint(_) |
ty::ty_int(_) |
ty::ty_nil |
- ty::ty_bot |
ty::ty_bool |
ty::ty_float(_) |
ty::ty_bare_fn(_) |
Ok(If(tys.clone()))
}
- ty::ty_unboxed_closure(def_id, _) => {
+ ty::ty_unboxed_closure(def_id, _, ref substs) => {
// FIXME -- This case is tricky. In the case of by-ref
// closures particularly, we need the results of
// inference to decide how to reflect the type of each
.map(|freevar| {
let freevar_def_id = freevar.def.def_id();
self.typer.node_ty(freevar_def_id.node)
- .unwrap_or(ty::mk_err())
+ .unwrap_or(ty::mk_err()).subst(self.tcx(), substs)
})
.collect();
Ok(If(tys))
Ok(VtableImpl(vtable_impl))
}
- UnboxedClosureCandidate(closure_def_id) => {
- try!(self.confirm_unboxed_closure_candidate(obligation, closure_def_id));
+ UnboxedClosureCandidate(closure_def_id, ref substs) => {
+ try!(self.confirm_unboxed_closure_candidate(obligation, closure_def_id, substs));
Ok(VtableUnboxedClosure(closure_def_id))
}
}
fn confirm_unboxed_closure_candidate(&mut self,
obligation: &Obligation,
- closure_def_id: ast::DefId)
+ closure_def_id: ast::DefId,
+ substs: &Substs)
-> Result<(),SelectionError>
{
- debug!("confirm_unboxed_closure_candidate({},{})",
+ debug!("confirm_unboxed_closure_candidate({},{},{})",
obligation.repr(self.tcx()),
- closure_def_id.repr(self.tcx()));
+ closure_def_id.repr(self.tcx()),
+ substs.repr(self.tcx()));
let closure_type = match self.typer.unboxed_closures().borrow().find(&closure_def_id) {
Some(closure) => closure.closure_type.clone(),
let trait_ref = Rc::new(ty::TraitRef {
def_id: obligation.trait_ref.def_id,
substs: Substs::new_trait(
- vec![arguments_tuple, new_signature.output],
+ vec![arguments_tuple.subst(self.tcx(), substs),
+ new_signature.output.unwrap().subst(self.tcx(), substs)],
vec![],
obligation.self_ty())
});
util::obligations_for_generics(self.tcx(), cause, recursion_depth,
&impl_generics, impl_substs)
}
-
- fn contains_skolemized_types(&self,
- ty: ty::t)
- -> bool
- {
- /*!
- * True if the type contains skolemized variables.
- */
-
- let mut found_skol = false;
-
- ty::walk_ty(ty, |t| {
- match ty::get(t).sty {
- ty::ty_infer(ty::SkolemizedTy(_)) => { found_skol = true; }
- _ => { }
- }
- });
-
- found_skol
- }
}
impl Repr for Candidate {
match *self {
ErrorCandidate => format!("ErrorCandidate"),
BuiltinCandidate(b) => format!("BuiltinCandidate({})", b),
- UnboxedClosureCandidate(c) => format!("MatchedUnboxedClosureCandidate({})", c),
+ UnboxedClosureCandidate(c, ref s) => {
+ format!("MatchedUnboxedClosureCandidate({},{})", c, s.repr(tcx))
+ }
ParamCandidate(ref a) => format!("ParamCandidate({})", a.repr(tcx)),
ImplCandidate(a) => format!("ImplCandidate({})", a.repr(tcx)),
}
let ConstantExpr(other_expr) = other;
match const_eval::compare_lit_exprs(tcx, expr, other_expr) {
Some(val1) => val1 == 0,
- None => fail!("compare_list_exprs: type mismatch"),
+ None => panic!("compare_list_exprs: type mismatch"),
}
}
}
fn handle_fail(&self, bcx: Block) {
match *self {
Infallible =>
- fail!("attempted to fail in an infallible failure handler!"),
+ panic!("attempted to panic in a non-panicking panic handler!"),
JumpToBasicBlock(basic_block) =>
Br(bcx, basic_block),
Unreachable =>
// General path.
let init_datum =
unpack_datum!(bcx, expr::trans_to_lvalue(bcx, &**init_expr, "let"));
- if ty::type_is_bot(expr_ty(bcx, &**init_expr)) {
- create_dummy_locals(bcx, pat)
- } else {
- if bcx.sess().asm_comments() {
- add_comment(bcx, "creating zeroable ref llval");
- }
- let var_scope = cleanup::var_scope(tcx, local.id);
- bind_irrefutable_pat(bcx, pat, init_datum.val, var_scope)
+ if bcx.sess().asm_comments() {
+ add_comment(bcx, "creating zeroable ref llval");
}
+ let var_scope = cleanup::var_scope(tcx, local.id);
+ bind_irrefutable_pat(bcx, pat, init_datum.val, var_scope)
}
None => {
create_dummy_locals(bcx, pat)
return Univariant(mk_struct(cx, ftys.as_slice(), packed, t), dtor)
}
- ty::ty_unboxed_closure(def_id, _) => {
- let upvars = ty::unboxed_closure_upvars(cx.tcx(), def_id);
+ ty::ty_unboxed_closure(def_id, _, ref substs) => {
+ let upvars = ty::unboxed_closure_upvars(cx.tcx(), def_id, substs);
let upvar_types = upvars.iter().map(|u| u.ty).collect::<Vec<_>>();
return Univariant(mk_struct(cx, upvar_types.as_slice(), false, t),
false)
Type::array(&Type::i64(cx), align_units),
a if a.count_ones() == 1 => Type::array(&Type::vector(&Type::i32(cx), a / 4),
align_units),
- _ => fail!("unsupported enum alignment: {}", align)
+ _ => panic!("unsupported enum alignment: {}", align)
};
assert_eq!(machine::llalign_of_min(cx, pad_ty), align);
assert_eq!(align_s % discr_size, 0);
// only use this for foreign function ABIs and glue, use `decl_rust_fn` for Rust functions
pub fn decl_fn(ccx: &CrateContext, name: &str, cc: llvm::CallConv,
- ty: Type, output: ty::t) -> ValueRef {
+ ty: Type, output: ty::FnOutput) -> ValueRef {
let llfn: ValueRef = name.with_c_str(|buf| {
unsafe {
}
});
- match ty::get(output).sty {
- // functions returning bottom may unwind, but can never return normally
- ty::ty_bot => {
- llvm::SetFunctionAttribute(llfn, llvm::NoReturnAttribute)
- }
- _ => {}
+ // diverging functions may unwind, but can never return normally
+ if output == ty::FnDiverging {
+ llvm::SetFunctionAttribute(llfn, llvm::NoReturnAttribute);
}
if ccx.tcx().sess.opts.cg.no_redzone {
name: &str,
ty: Type,
output: ty::t) -> ValueRef {
- decl_fn(ccx, name, llvm::CCallConv, ty, output)
+ decl_fn(ccx, name, llvm::CCallConv, ty, ty::FnConverging(output))
}
// only use this for foreign function ABIs and glue, use `get_extern_rust_fn` for Rust functions
Some(n) => return *n,
None => {}
}
- let f = decl_fn(ccx, name, cc, ty, output);
+ let f = decl_fn(ccx, name, cc, ty, ty::FnConverging(output));
externs.insert(name.to_string(), f);
f
}
}
pub fn self_type_for_unboxed_closure(ccx: &CrateContext,
- closure_id: ast::DefId)
+ closure_id: ast::DefId,
+ fn_ty: ty::t)
-> ty::t {
- let unboxed_closure_type = ty::mk_unboxed_closure(ccx.tcx(),
- closure_id,
- ty::ReStatic);
let unboxed_closures = ccx.tcx().unboxed_closures.borrow();
let unboxed_closure = &(*unboxed_closures)[closure_id];
match unboxed_closure.kind {
ty::FnUnboxedClosureKind => {
- ty::mk_imm_rptr(ccx.tcx(), ty::ReStatic, unboxed_closure_type)
+ ty::mk_imm_rptr(ccx.tcx(), ty::ReStatic, fn_ty)
}
ty::FnMutUnboxedClosureKind => {
- ty::mk_mut_rptr(ccx.tcx(), ty::ReStatic, unboxed_closure_type)
+ ty::mk_mut_rptr(ccx.tcx(), ty::ReStatic, fn_ty)
}
- ty::FnOnceUnboxedClosureKind => unboxed_closure_type,
+ ty::FnOnceUnboxedClosureKind => fn_ty
}
}
ty::ty_closure(ref f) => {
(f.sig.inputs.clone(), f.sig.output, f.abi, Some(Type::i8p(ccx)))
}
- ty::ty_unboxed_closure(closure_did, _) => {
+ ty::ty_unboxed_closure(closure_did, _, ref substs) => {
let unboxed_closures = ccx.tcx().unboxed_closures.borrow();
let unboxed_closure = &(*unboxed_closures)[closure_did];
let function_type = unboxed_closure.closure_type.clone();
- let self_type = self_type_for_unboxed_closure(ccx, closure_did);
+ let self_type = self_type_for_unboxed_closure(ccx, closure_did, fn_ty);
let llenvironment_type = type_of_explicit_arg(ccx, self_type);
- (function_type.sig.inputs.clone(),
- function_type.sig.output,
+ (function_type.sig.inputs.iter().map(|t| t.subst(ccx.tcx(), substs)).collect(),
+ function_type.sig.output.subst(ccx.tcx(), substs),
RustCall,
Some(llenvironment_type))
}
- _ => fail!("expected closure or fn")
+ _ => panic!("expected closure or fn")
};
let llfty = type_of_rust_fn(ccx, env, inputs.as_slice(), output, abi);
}
})
}
- ty::ty_unboxed_closure(def_id, _) => {
+ ty::ty_unboxed_closure(def_id, _, ref substs) => {
let repr = adt::represent_type(cx.ccx(), t);
- let upvars = ty::unboxed_closure_upvars(cx.tcx(), def_id);
+ let upvars = ty::unboxed_closure_upvars(cx.tcx(), def_id, substs);
for (i, upvar) in upvars.iter().enumerate() {
let llupvar = adt::trans_field_ptr(cx, &*repr, data_ptr, 0, i);
cx = f(cx, llupvar, upvar.ty);
llfndecl: ValueRef,
id: ast::NodeId,
has_env: bool,
- output_type: ty::t,
+ output_type: ty::FnOutput,
param_substs: &'a param_substs,
sp: Option<Span>,
block_arena: &'a TypedArena<common::BlockS<'a, 'tcx>>)
},
id, param_substs.repr(ccx.tcx()));
- let substd_output_type = output_type.substp(ccx.tcx(), param_substs);
- let uses_outptr = type_of::return_uses_outptr(ccx, substd_output_type);
+ let uses_outptr = match output_type {
+ ty::FnConverging(output_type) => {
+ let substd_output_type = output_type.substp(ccx.tcx(), param_substs);
+ type_of::return_uses_outptr(ccx, substd_output_type)
+ }
+ ty::FnDiverging => false
+ };
let debug_context = debuginfo::create_function_debug_context(ccx, id, param_substs, llfndecl);
let nested_returns = has_nested_returns(ccx.tcx(), id);
/// and allocating space for the return pointer.
pub fn init_function<'a, 'tcx>(fcx: &'a FunctionContext<'a, 'tcx>,
skip_retptr: bool,
- output_type: ty::t) -> Block<'a, 'tcx> {
+ output: ty::FnOutput) -> Block<'a, 'tcx> {
let entry_bcx = fcx.new_temp_block("entry-block");
// Use a dummy instruction as the insertion point for all allocas.
llvm::LLVMGetFirstInstruction(entry_bcx.llbb)
}));
- // This shouldn't need to recompute the return type,
- // as new_fn_ctxt did it already.
- let substd_output_type = output_type.substp(fcx.ccx.tcx(), fcx.param_substs);
-
- if !return_type_is_void(fcx.ccx, substd_output_type) {
- // If the function returns nil/bot, there is no real return
- // value, so do not set `llretslotptr`.
- if !skip_retptr || fcx.caller_expects_out_pointer {
- // Otherwise, we normally allocate the llretslotptr, unless we
- // have been instructed to skip it for immediate return
- // values.
- fcx.llretslotptr.set(Some(make_return_slot_pointer(fcx, substd_output_type)));
+ if let ty::FnConverging(output_type) = output {
+ // This shouldn't need to recompute the return type,
+ // as new_fn_ctxt did it already.
+ let substd_output_type = output_type.substp(fcx.ccx.tcx(), fcx.param_substs);
+ if !return_type_is_void(fcx.ccx, substd_output_type) {
+ // If the function returns nil/bot, there is no real return
+ // value, so do not set `llretslotptr`.
+ if !skip_retptr || fcx.caller_expects_out_pointer {
+ // Otherwise, we normally allocate the llretslotptr, unless we
+ // have been instructed to skip it for immediate return
+ // values.
+ fcx.llretslotptr.set(Some(make_return_slot_pointer(fcx, substd_output_type)));
+ }
}
}
// and builds the return block.
pub fn finish_fn<'blk, 'tcx>(fcx: &'blk FunctionContext<'blk, 'tcx>,
last_bcx: Block<'blk, 'tcx>,
- retty: ty::t) {
+ retty: ty::FnOutput) {
let _icx = push_ctxt("finish_fn");
- // This shouldn't need to recompute the return type,
- // as new_fn_ctxt did it already.
- let substd_retty = retty.substp(fcx.ccx.tcx(), fcx.param_substs);
-
let ret_cx = match fcx.llreturn.get() {
Some(llreturn) => {
if !last_bcx.terminated.get() {
}
None => last_bcx
};
+
+ // This shouldn't need to recompute the return type,
+ // as new_fn_ctxt did it already.
+ let substd_retty = retty.substp(fcx.ccx.tcx(), fcx.param_substs);
build_return_block(fcx, ret_cx, substd_retty);
+
debuginfo::clear_source_location(fcx);
fcx.cleanup();
}
// Builds the return block for a function.
-pub fn build_return_block(fcx: &FunctionContext, ret_cx: Block, retty: ty::t) {
+pub fn build_return_block(fcx: &FunctionContext, ret_cx: Block, retty: ty::FnOutput) {
if fcx.llretslotptr.get().is_none() ||
(!fcx.needs_ret_allocas && fcx.caller_expects_out_pointer) {
return RetVoid(ret_cx);
retptr.erase_from_parent();
}
- let retval = if ty::type_is_bool(retty) {
+ let retval = if retty == ty::FnConverging(ty::mk_bool()) {
Trunc(ret_cx, retval, Type::i1(fcx.ccx))
} else {
retval
};
if fcx.caller_expects_out_pointer {
- store_ty(ret_cx, retval, get_param(fcx.llfn, 0), retty);
- return RetVoid(ret_cx);
+ if let ty::FnConverging(retty) = retty {
+ store_ty(ret_cx, retval, get_param(fcx.llfn, 0), retty);
+ }
+ RetVoid(ret_cx)
} else {
- return Ret(ret_cx, retval);
+ Ret(ret_cx, retval)
}
}
// Otherwise, copy the return value to the ret slot
- None => {
- if fcx.caller_expects_out_pointer {
- memcpy_ty(ret_cx, get_param(fcx.llfn, 0), retslot, retty);
- return RetVoid(ret_cx);
- } else {
- return Ret(ret_cx, load_ty(ret_cx, retslot, retty));
+ None => match retty {
+ ty::FnConverging(retty) => {
+ if fcx.caller_expects_out_pointer {
+ memcpy_ty(ret_cx, get_param(fcx.llfn, 0), retslot, retty);
+ RetVoid(ret_cx)
+ } else {
+ Ret(ret_cx, load_ty(ret_cx, retslot, retty))
+ }
+ }
+ ty::FnDiverging => {
+ if fcx.caller_expects_out_pointer {
+ RetVoid(ret_cx)
+ } else {
+ Ret(ret_cx, C_undef(Type::nil(fcx.ccx)))
+ }
}
}
}
fn_ast_id: ast::NodeId,
_attributes: &[ast::Attribute],
arg_types: Vec<ty::t>,
- output_type: ty::t,
+ output_type: ty::FnOutput,
abi: Abi,
has_env: bool,
is_unboxed_closure: IsUnboxedClosureFlag,
debuginfo::start_emitting_source_locations(&fcx);
let dest = match fcx.llretslotptr.get() {
- Some(_) => expr::SaveIn(fcx.get_ret_slot(bcx, block_ty, "iret_slot")),
+ Some(_) => expr::SaveIn(fcx.get_ret_slot(bcx, ty::FnConverging(block_ty), "iret_slot")),
None => {
assert!(type_is_zero_size(bcx.ccx(), block_ty));
expr::Ignore
let tcx = ccx.tcx();
let result_ty = match ty::get(ctor_ty).sty {
- ty::ty_bare_fn(ref bft) => bft.sig.output,
+ ty::ty_bare_fn(ref bft) => bft.sig.output.unwrap(),
_ => ccx.sess().bug(
format!("trans_enum_variant_constructor: \
unexpected ctor return type {}",
let arg_datums = create_datums_for_fn_args(&fcx, arg_tys.as_slice());
- if !type_is_zero_size(fcx.ccx, result_ty) {
+ if !type_is_zero_size(fcx.ccx, result_ty.unwrap()) {
let dest = fcx.get_ret_slot(bcx, result_ty, "eret_slot");
- let repr = adt::represent_type(ccx, result_ty);
+ let repr = adt::represent_type(ccx, result_ty.unwrap());
for (i, arg_datum) in arg_datums.into_iter().enumerate() {
let lldestptr = adt::trans_field_ptr(bcx,
&*repr,
ty::ty_bare_fn(ref f) => {
assert!(f.abi == Rust || f.abi == RustCall);
}
- _ => fail!("expected bare rust fn")
+ _ => panic!("expected bare rust fn")
};
let llfn = decl_rust_fn(ccx, node_type, sym.as_slice());
let (fn_sig, abi, has_env) = match ty::get(fn_ty).sty {
ty::ty_closure(ref f) => (f.sig.clone(), f.abi, true),
ty::ty_bare_fn(ref f) => (f.sig.clone(), f.abi, false),
- ty::ty_unboxed_closure(closure_did, _) => {
+ ty::ty_unboxed_closure(closure_did, _, ref substs) => {
let unboxed_closures = ccx.tcx().unboxed_closures.borrow();
let ref function_type = (*unboxed_closures)[closure_did]
.closure_type;
- (function_type.sig.clone(), RustCall, true)
+ (function_type.sig.subst(ccx.tcx(), substs), RustCall, true)
}
_ => ccx.sess().bug("expected closure or function.")
};
// These have an odd calling convention, so we need to manually
// unpack the input ty's
let input_tys = match ty::get(fn_ty).sty {
- ty::ty_unboxed_closure(_, _) => {
+ ty::ty_unboxed_closure(_, _, _) => {
assert!(abi == RustCall);
match ty::get(fn_sig.inputs[0]).sty {
_ => fn_sig.inputs.clone()
};
- // A function pointer is called without the declaration
- // available, so we have to apply any attributes with ABI
- // implications directly to the call instruction. Right now,
- // the only attribute we need to worry about is `sret`.
- if type_of::return_uses_outptr(ccx, ret_ty) {
- let llret_sz = llsize_of_real(ccx, type_of::type_of(ccx, ret_ty));
-
- // The outptr can be noalias and nocapture because it's entirely
- // invisible to the program. We also know it's nonnull as well
- // as how many bytes we can dereference
- attrs.arg(1, llvm::StructRetAttribute)
- .arg(1, llvm::NoAliasAttribute)
- .arg(1, llvm::NoCaptureAttribute)
- .arg(1, llvm::DereferenceableAttribute(llret_sz));
-
- // Add one more since there's an outptr
- first_arg_offset += 1;
- } else {
- // The `noalias` attribute on the return value is useful to a
- // function ptr caller.
- match ty::get(ret_ty).sty {
- // `~` pointer return values never alias because ownership
- // is transferred
- ty::ty_uniq(it) if !ty::type_is_sized(ccx.tcx(), it) => {}
- ty::ty_uniq(_) => {
- attrs.ret(llvm::NoAliasAttribute);
+ if let ty::FnConverging(ret_ty) = ret_ty {
+ // A function pointer is called without the declaration
+ // available, so we have to apply any attributes with ABI
+ // implications directly to the call instruction. Right now,
+ // the only attribute we need to worry about is `sret`.
+ if type_of::return_uses_outptr(ccx, ret_ty) {
+ let llret_sz = llsize_of_real(ccx, type_of::type_of(ccx, ret_ty));
+
+ // The outptr can be noalias and nocapture because it's entirely
+ // invisible to the program. We also know it's nonnull as well
+ // as how many bytes we can dereference
+ attrs.arg(1, llvm::StructRetAttribute)
+ .arg(1, llvm::NoAliasAttribute)
+ .arg(1, llvm::NoCaptureAttribute)
+ .arg(1, llvm::DereferenceableAttribute(llret_sz));
+
+ // Add one more since there's an outptr
+ first_arg_offset += 1;
+ } else {
+ // The `noalias` attribute on the return value is useful to a
+ // function ptr caller.
+ match ty::get(ret_ty).sty {
+ // `~` pointer return values never alias because ownership
+ // is transferred
+ ty::ty_uniq(it) if !ty::type_is_sized(ccx.tcx(), it) => {}
+ ty::ty_uniq(_) => {
+ attrs.ret(llvm::NoAliasAttribute);
+ }
+ _ => {}
}
- _ => {}
- }
- // We can also mark the return value as `dereferenceable` in certain cases
- match ty::get(ret_ty).sty {
- // These are not really pointers but pairs, (pointer, len)
- ty::ty_uniq(it) |
- ty::ty_rptr(_, ty::mt { ty: it, .. }) if !ty::type_is_sized(ccx.tcx(), it) => {}
- ty::ty_uniq(inner) | ty::ty_rptr(_, ty::mt { ty: inner, .. }) => {
- let llret_sz = llsize_of_real(ccx, type_of::type_of(ccx, inner));
- attrs.ret(llvm::DereferenceableAttribute(llret_sz));
+ // We can also mark the return value as `dereferenceable` in certain cases
+ match ty::get(ret_ty).sty {
+ // These are not really pointers but pairs, (pointer, len)
+ ty::ty_uniq(it) |
+ ty::ty_rptr(_, ty::mt { ty: it, .. }) if !ty::type_is_sized(ccx.tcx(), it) => {}
+ ty::ty_uniq(inner) | ty::ty_rptr(_, ty::mt { ty: inner, .. }) => {
+ let llret_sz = llsize_of_real(ccx, type_of::type_of(ccx, inner));
+ attrs.ret(llvm::DereferenceableAttribute(llret_sz));
+ }
+ _ => {}
}
- _ => {}
- }
- match ty::get(ret_ty).sty {
- ty::ty_bool => {
- attrs.ret(llvm::ZExtAttribute);
+ match ty::get(ret_ty).sty {
+ ty::ty_bool => {
+ attrs.ret(llvm::ZExtAttribute);
+ }
+ _ => {}
}
- _ => {}
}
}
llfty: Type) -> ValueRef {
debug!("register_fn_llvmty id={} sym={}", node_id, sym);
- let llfn = decl_fn(ccx, sym.as_slice(), cc, llfty, ty::mk_nil());
+ let llfn = decl_fn(ccx, sym.as_slice(), cc, llfty, ty::FnConverging(ty::mk_nil()));
finish_register_fn(ccx, sp, sym, node_id, llfn);
llfn
}
llfn
}
- _ => fail!("get_item_val: weird result in table")
+ _ => panic!("get_item_val: weird result in table")
};
match attr::first_attr_value_str_by_name(i.attrs.as_slice(),
let args = match v.node.kind {
ast::TupleVariantKind(ref args) => args,
ast::StructVariantKind(_) => {
- fail!("struct variant kind unexpected in get_item_val")
+ panic!("struct variant kind unexpected in get_item_val")
}
};
assert!(args.len() != 0u);
ast::ItemEnum(_, _) => {
register_fn(ccx, (*v).span, sym, id, ty)
}
- _ => fail!("NodeVariant, shouldn't happen")
+ _ => panic!("NodeVariant, shouldn't happen")
};
set_inline_hint(llfn);
llfn
pub fn check_not_terminated(cx: Block) {
if cx.terminated.get() {
- fail!("already terminated!");
+ panic!("already terminated!");
}
}
// terminated, we're saying that trying to add any further statements in the
// block is an error. On the other hand, if something is unreachable, that
// means that the block was terminated in some way that we don't want to check
-// for (fail/break/return statements, call to diverging functions, etc), and
+// for (panic/break/return statements, call to diverging functions, etc), and
// further instructions to the block should simply be ignored.
pub fn RetVoid(cx: Block) {
let elt = ty.element_type();
ty_align(elt)
}
- _ => fail!("ty_align: unhandled type")
+ _ => panic!("ty_align: unhandled type")
}
}
let eltsz = ty_size(elt);
len * eltsz
}
- _ => fail!("ty_size: unhandled type")
+ _ => panic!("ty_size: unhandled type")
}
}
let elt = ty.element_type();
ty_align(elt)
}
- _ => fail!("ty_size: unhandled type")
+ _ => panic!("ty_size: unhandled type")
}
}
let eltsz = ty_size(elt);
len * eltsz
}
- _ => fail!("ty_size: unhandled type")
+ _ => panic!("ty_size: unhandled type")
}
}
let elt = ty.element_type();
ty_align(elt)
}
- _ => fail!("ty_size: unhandled type")
+ _ => panic!("ty_size: unhandled type")
}
}
let eltsz = ty_size(elt);
len * eltsz
}
- _ => fail!("ty_size: unhandled type")
+ _ => panic!("ty_size: unhandled type")
}
}
i += 1u;
}
}
- _ => fail!("classify: unhandled type")
+ _ => panic!("classify: unhandled type")
}
}
SSEDs => {
tys.push(Type::f64(ccx));
}
- _ => fail!("llregtype: unhandled class")
+ _ => panic!("llregtype: unhandled class")
}
i += 1u;
}
llshimmedargs.push(get_param(fcx.llfn, fcx.arg_pos(i) as u32));
}
assert!(!fcx.needs_ret_allocas);
- let dest = match fcx.llretslotptr.get() {
- Some(_) => Some(expr::SaveIn(fcx.get_ret_slot(bcx, return_type, "ret_slot"))),
- None => None
- };
+ let dest = fcx.llretslotptr.get().map(|_|
+ expr::SaveIn(fcx.get_ret_slot(bcx, return_type, "ret_slot"))
+ );
bcx = trans_call_inner(bcx,
None,
function_type,
};
// If this is an unboxed closure, redirect to it.
- match closure::get_or_create_declaration_if_unboxed_closure(ccx, def_id) {
+ match closure::get_or_create_declaration_if_unboxed_closure(bcx, def_id) {
None => {}
Some(llfn) => return llfn,
}
// Introduce a temporary cleanup scope that will contain cleanups
// for the arguments while they are being evaluated. The purpose
- // this cleanup is to ensure that, should a failure occur while
+ // this cleanup is to ensure that, should a panic occur while
// evaluating argument N, the values for arguments 0...N-1 are all
- // cleaned up. If no failure occurs, the values are handed off to
+ // cleaned up. If no panic occurs, the values are handed off to
// the callee, and hence none of the cleanups in this temporary
// scope will ever execute.
let fcx = bcx.fcx;
let (abi, ret_ty) = match ty::get(callee_ty).sty {
ty::ty_bare_fn(ref f) => (f.abi, f.sig.output),
ty::ty_closure(ref f) => (f.abi, f.sig.output),
- _ => fail!("expected bare rust fn or closure in trans_call_inner")
+ _ => panic!("expected bare rust fn or closure in trans_call_inner")
};
let (llfn, llenv, llself) = match callee.data {
// Generate a location to store the result. If the user does
// not care about the result, just make a stack slot.
- let opt_llretslot = match dest {
- None => {
- assert!(!type_of::return_uses_outptr(ccx, ret_ty));
- None
- }
- Some(expr::SaveIn(dst)) => Some(dst),
- Some(expr::Ignore) if !is_rust_fn ||
- type_of::return_uses_outptr(ccx, ret_ty) ||
- ty::type_needs_drop(bcx.tcx(), ret_ty) => {
- if !type_is_zero_size(ccx, ret_ty) {
- Some(alloc_ty(bcx, ret_ty, "__llret"))
+ let opt_llretslot = dest.and_then(|dest| match dest {
+ expr::SaveIn(dst) => Some(dst),
+ expr::Ignore => {
+ let ret_ty = match ret_ty {
+ ty::FnConverging(ret_ty) => ret_ty,
+ ty::FnDiverging => ty::mk_nil()
+ };
+ if !is_rust_fn ||
+ type_of::return_uses_outptr(ccx, ret_ty) ||
+ ty::type_needs_drop(bcx.tcx(), ret_ty) {
+ // Push the out-pointer if we use an out-pointer for this
+ // return type, otherwise push "undef".
+ if type_is_zero_size(ccx, ret_ty) {
+ let llty = type_of::type_of(ccx, ret_ty);
+ Some(C_undef(llty.ptr_to()))
+ } else {
+ Some(alloc_ty(bcx, ret_ty, "__llret"))
+ }
} else {
- let llty = type_of::type_of(ccx, ret_ty);
- Some(C_undef(llty.ptr_to()))
+ None
}
}
- Some(expr::Ignore) => None
- };
+ });
let mut llresult = unsafe {
llvm::LLVMGetUndef(Type::nil(ccx).ptr_to().to_ref())
if is_rust_fn {
let mut llargs = Vec::new();
- // Push the out-pointer if we use an out-pointer for this
- // return type, otherwise push "undef".
- if type_of::return_uses_outptr(ccx, ret_ty) {
- llargs.push(opt_llretslot.unwrap());
+ if let (ty::FnConverging(ret_ty), Some(llretslot)) = (ret_ty, opt_llretslot) {
+ if type_of::return_uses_outptr(ccx, ret_ty) {
+ llargs.push(llretslot);
+ }
}
// Push the environment (or a trait object's self).
match (llenv, llself) {
- (Some(llenv), None) => {
- llargs.push(llenv)
- },
+ (Some(llenv), None) => llargs.push(llenv),
(None, Some(llself)) => llargs.push(llself),
_ => {}
}
// If the Rust convention for this type is return via
// the return value, copy it into llretslot.
- match opt_llretslot {
- Some(llretslot) => {
+ match (opt_llretslot, ret_ty) {
+ (Some(llretslot), ty::FnConverging(ret_ty)) => {
if !type_of::return_uses_outptr(bcx.ccx(), ret_ty) &&
!type_is_zero_size(bcx.ccx(), ret_ty)
{
store_ty(bcx, llret, llretslot, ret_ty)
}
}
- None => {}
+ (_, _) => {}
}
} else {
// Lang items are the only case where dest is None, and
let mut llargs = Vec::new();
let arg_tys = match args {
ArgExprs(a) => a.iter().map(|x| expr_ty(bcx, &**x)).collect(),
- _ => fail!("expected arg exprs.")
+ _ => panic!("expected arg exprs.")
};
bcx = trans_args(bcx,
args,
// If the caller doesn't care about the result of this fn call,
// drop the temporary slot we made.
- match (dest, opt_llretslot) {
- (Some(expr::Ignore), Some(llretslot)) => {
+ match (dest, opt_llretslot, ret_ty) {
+ (Some(expr::Ignore), Some(llretslot), ty::FnConverging(ret_ty)) => {
// drop the value if it is not being saved.
bcx = glue::drop_ty(bcx, llretslot, ret_ty, call_info);
call_lifetime_end(bcx, llretslot);
_ => {}
}
- if ty::type_is_bot(ret_ty) {
+ if ret_ty == ty::FnDiverging {
Unreachable(bcx);
}
debug!(" arg datum: {}", arg_datum.to_string(bcx.ccx()));
let mut val;
- if ty::type_is_bot(arg_datum_ty) {
- // For values of type _|_, we generate an
- // "undef" value, as such a value should never
- // be inspected. It's important for the value
- // to have type lldestty (the callee's expected type).
- let llformal_arg_ty = type_of::type_of_explicit_arg(ccx, formal_arg_ty);
- unsafe {
- val = llvm::LLVMGetUndef(llformal_arg_ty.to_ref());
+ // FIXME(#3548) use the adjustments table
+ match autoref_arg {
+ DoAutorefArg(arg_id) => {
+ // We will pass argument by reference
+ // We want an lvalue, so that we can pass by reference and
+ let arg_datum = unpack_datum!(
+ bcx, arg_datum.to_lvalue_datum(bcx, "arg", arg_id));
+ val = arg_datum.val;
}
- } else {
- // FIXME(#3548) use the adjustments table
- match autoref_arg {
- DoAutorefArg(arg_id) => {
- // We will pass argument by reference
- // We want an lvalue, so that we can pass by reference and
- let arg_datum = unpack_datum!(
- bcx, arg_datum.to_lvalue_datum(bcx, "arg", arg_id));
- val = arg_datum.val;
- }
- DontAutorefArg => {
- // Make this an rvalue, since we are going to be
- // passing ownership.
- let arg_datum = unpack_datum!(
- bcx, arg_datum.to_rvalue_datum(bcx, "arg"));
-
- // Now that arg_datum is owned, get it into the appropriate
- // mode (ref vs value).
- let arg_datum = unpack_datum!(
- bcx, arg_datum.to_appropriate_datum(bcx));
-
- // Technically, ownership of val passes to the callee.
- // However, we must cleanup should we fail before the
- // callee is actually invoked.
- val = arg_datum.add_clean(bcx.fcx, arg_cleanup_scope);
- }
+ DontAutorefArg => {
+ // Make this an rvalue, since we are going to be
+ // passing ownership.
+ let arg_datum = unpack_datum!(
+ bcx, arg_datum.to_rvalue_datum(bcx, "arg"));
+
+ // Now that arg_datum is owned, get it into the appropriate
+ // mode (ref vs value).
+ let arg_datum = unpack_datum!(
+ bcx, arg_datum.to_appropriate_datum(bcx));
+
+ // Technically, ownership of val passes to the callee.
+ // However, we must cleanup should we panic before the
+ // callee is actually invoked.
+ val = arg_datum.add_clean(bcx.fcx, arg_cleanup_scope);
}
+ }
- if formal_arg_ty != arg_datum_ty {
- // this could happen due to e.g. subtyping
- let llformal_arg_ty = type_of::type_of_explicit_arg(ccx, formal_arg_ty);
- debug!("casting actual type ({}) to match formal ({})",
- bcx.val_to_string(val), bcx.llty_str(llformal_arg_ty));
- debug!("Rust types: {}; {}", ty_to_string(bcx.tcx(), arg_datum_ty),
- ty_to_string(bcx.tcx(), formal_arg_ty));
- val = PointerCast(bcx, val, llformal_arg_ty);
- }
+ if formal_arg_ty != arg_datum_ty {
+ // this could happen due to e.g. subtyping
+ let llformal_arg_ty = type_of::type_of_explicit_arg(ccx, formal_arg_ty);
+ debug!("casting actual type ({}) to match formal ({})",
+ bcx.val_to_string(val), bcx.llty_str(llformal_arg_ty));
+ debug!("Rust types: {}; {}", ty_to_string(bcx.tcx(), arg_datum_ty),
+ ty_to_string(bcx.tcx(), formal_arg_ty));
+ val = PointerCast(bcx, val, llformal_arg_ty);
}
debug!("--- trans_arg_datum passing {}", bcx.val_to_string(val));
fn needs_invoke(&self) -> bool {
/*!
* Returns true if there are pending cleanups that should
- * execute on failure.
+ * execute on panic.
*/
self.scopes.borrow().iter().rev().any(|s| s.needs_invoke())
fn get_landing_pad(&'blk self) -> BasicBlockRef {
/*!
- * Returns a basic block to branch to in the event of a failure.
- * This block will run the failure cleanups and eventually
+ * Returns a basic block to branch to in the event of a panic.
+ * This block will run the panic cleanups and eventually
* invoke the LLVM `Resume` instruction.
*/
let orig_scopes_len = self.scopes_len();
assert!(orig_scopes_len > 0);
- // Remove any scopes that do not have cleanups on failure:
+ // Remove any scopes that do not have cleanups on panic:
let mut popped_scopes = vec!();
while !self.top_scope(|s| s.needs_invoke()) {
debug!("top scope does not need invoke");
use middle::trans::datum::{Datum, DatumBlock, Expr, Lvalue, rvalue_scratch_datum};
use middle::trans::debuginfo;
use middle::trans::expr;
+use middle::trans::monomorphize::MonoId;
use middle::trans::type_of::*;
use middle::trans::type_::Type;
use middle::ty;
}
// Special case for small by-value selfs.
- let self_type = self_type_for_unboxed_closure(bcx.ccx(), closure_id);
+ let self_type = self_type_for_unboxed_closure(bcx.ccx(), closure_id,
+ node_id_type(bcx, closure_id.node));
let kind = kind_for_unboxed_closure(bcx.ccx(), closure_id);
let llenv = if kind == ty::FnOnceUnboxedClosureKind &&
!arg_is_indirect(bcx.ccx(), self_type) {
/// Returns the LLVM function declaration for an unboxed closure, creating it
/// if necessary. If the ID does not correspond to a closure ID, returns None.
-pub fn get_or_create_declaration_if_unboxed_closure(ccx: &CrateContext,
- closure_id: ast::DefId)
- -> Option<ValueRef> {
+pub fn get_or_create_declaration_if_unboxed_closure<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
+ closure_id: ast::DefId)
+ -> Option<ValueRef> {
+ let ccx = bcx.ccx();
if !ccx.tcx().unboxed_closures.borrow().contains_key(&closure_id) {
// Not an unboxed closure.
return None
}
- match ccx.unboxed_closure_vals().borrow().find(&closure_id) {
+ let function_type = node_id_type(bcx, closure_id.node);
+ let params = match ty::get(function_type).sty {
+ ty::ty_unboxed_closure(_, _, ref substs) => substs.types.clone(),
+ _ => unreachable!()
+ };
+ let mono_id = MonoId {
+ def: closure_id,
+ params: params
+ };
+
+ match ccx.unboxed_closure_vals().borrow().find(&mono_id) {
Some(llfn) => {
debug!("get_or_create_declaration_if_unboxed_closure(): found \
closure");
None => {}
}
- let function_type = ty::mk_unboxed_closure(ccx.tcx(),
- closure_id,
- ty::ReStatic);
+ let function_type = node_id_type(bcx, closure_id.node);
let symbol = ccx.tcx().map.with_path(closure_id.node, |path| {
mangle_internal_name_by_path_and_seq(path, "unboxed_closure")
});
debug!("get_or_create_declaration_if_unboxed_closure(): inserting new \
closure {} (type {})",
- closure_id,
+ mono_id,
ccx.tn().type_to_string(val_ty(llfn)));
- ccx.unboxed_closure_vals().borrow_mut().insert(closure_id, llfn);
+ ccx.unboxed_closure_vals().borrow_mut().insert(mono_id, llfn);
Some(llfn)
}
let closure_id = ast_util::local_def(id);
let llfn = get_or_create_declaration_if_unboxed_closure(
- bcx.ccx(),
+ bcx,
closure_id).unwrap();
let unboxed_closures = bcx.tcx().unboxed_closures.borrow();
llargs.extend(args.iter().map(|arg| arg.val));
let retval = Call(bcx, fn_ptr, llargs.as_slice(), None);
- if type_is_zero_size(ccx, f.sig.output) || fcx.llretslotptr.get().is_some() {
- RetVoid(bcx);
- } else {
- Ret(bcx, retval);
+ match f.sig.output {
+ ty::FnConverging(output_type) => {
+ if type_is_zero_size(ccx, output_type) || fcx.llretslotptr.get().is_some() {
+ RetVoid(bcx);
+ } else {
+ Ret(bcx, retval);
+ }
+ }
+ ty::FnDiverging => {
+ RetVoid(bcx);
+ }
}
// HACK(eddyb) finish_fn cannot be used here, we returned directly.
let tcx = ccx.tcx();
let simple = ty::type_is_scalar(ty) ||
ty::type_is_unique(ty) || ty::type_is_region_ptr(ty) ||
- type_is_newtype_immediate(ccx, ty) || ty::type_is_bot(ty) ||
+ type_is_newtype_immediate(ccx, ty) ||
ty::type_is_simd(tcx, ty);
if simple && !ty::type_is_fat_ptr(tcx, ty) {
return true;
return false;
}
match ty::get(ty).sty {
- ty::ty_bot => true,
ty::ty_struct(..) | ty::ty_enum(..) | ty::ty_tup(..) |
ty::ty_unboxed_closure(..) => {
let llty = sizing_type_of(ccx, ty);
* return type (in order to aid with C ABI compatibility).
*/
- ty::type_is_nil(ty) || ty::type_is_bot(ty) || ty::type_is_empty(ccx.tcx(), ty)
+ ty::type_is_nil(ty) || ty::type_is_empty(ccx.tcx(), ty)
}
/// Generates a unique symbol based off the name given. This is used to create
-> Self;
}
-impl<T:Subst+Clone> SubstP for T {
+impl<T: Subst + Clone> SubstP for T {
fn substp(&self, tcx: &ty::ctxt, substs: ¶m_substs) -> T {
self.subst(tcx, &substs.substs)
}
self.llreturn.get().unwrap()
}
- pub fn get_ret_slot(&self, bcx: Block, ty: ty::t, name: &str) -> ValueRef {
+ pub fn get_ret_slot(&self, bcx: Block, output: ty::FnOutput, name: &str) -> ValueRef {
if self.needs_ret_allocas {
- base::alloca_no_lifetime(bcx, type_of::type_of(bcx.ccx(), ty), name)
+ base::alloca_no_lifetime(bcx, match output {
+ ty::FnConverging(output_type) => type_of::type_of(bcx.ccx(), output_type),
+ ty::FnDiverging => Type::void(bcx.ccx())
+ }, name)
} else {
self.llretslotptr.get().unwrap()
}
match machine::llbitsize_of_real(ccx, ccx.int_type()) {
32 => assert!(v < (1<<31) && v >= -(1<<31)),
64 => {},
- n => fail!("unsupported target size: {}", n)
+ n => panic!("unsupported target size: {}", n)
}
C_integral(ccx.int_type(), v as u64, true)
match machine::llbitsize_of_real(ccx, ccx.int_type()) {
32 => assert!(v < (1<<32)),
64 => {},
- n => fail!("unsupported target size: {}", n)
+ n => panic!("unsupported target size: {}", n)
}
C_integral(ccx.int_type(), v, false)
builder: BuilderRef_res,
/// Holds the LLVM values for closure IDs.
- unboxed_closure_vals: RefCell<DefIdMap<ValueRef>>,
+ unboxed_closure_vals: RefCell<HashMap<MonoId, ValueRef>>,
dbg_cx: Option<debuginfo::CrateDebugContext>,
int_type: Type::from_ref(ptr::null_mut()),
opaque_vec_type: Type::from_ref(ptr::null_mut()),
builder: BuilderRef_res(llvm::LLVMCreateBuilderInContext(llcx)),
- unboxed_closure_vals: RefCell::new(DefIdMap::new()),
+ unboxed_closure_vals: RefCell::new(HashMap::new()),
dbg_cx: dbg_cx,
eh_personality: RefCell::new(None),
intrinsics: RefCell::new(HashMap::new()),
/// Create a dummy `CrateContext` from `self` and the provided
/// `SharedCrateContext`. This is somewhat dangerous because `self` may
/// not actually be an element of `shared.local_ccxs`, which can cause some
- /// operations to `fail` unexpectedly.
+ /// operations to panic unexpectedly.
///
/// This is used in the `LocalCrateContext` constructor to allow calling
/// functions that expect a complete `CrateContext`, even before the local
}
match declare_intrinsic(self, key) {
Some(v) => return v,
- None => fail!()
+ None => panic!()
}
}
self.local.opaque_vec_type
}
- pub fn unboxed_closure_vals<'a>(&'a self) -> &'a RefCell<DefIdMap<ValueRef>> {
+ pub fn unboxed_closure_vals<'a>(&'a self) -> &'a RefCell<HashMap<MonoId,ValueRef>> {
&self.local.unboxed_closure_vals
}
use llvm::*;
use driver::config::FullDebugInfo;
use middle::def;
-use middle::lang_items::{FailFnLangItem, FailBoundsCheckFnLangItem};
+use middle::lang_items::{PanicFnLangItem, PanicBoundsCheckFnLangItem};
use middle::trans::_match;
use middle::trans::adt;
use middle::trans::base::*;
.borrow())[method_call]
.ty;
let method_type = monomorphize_type(loopback_bcx_in, method_type);
- let method_result_type = ty::ty_fn_ret(method_type);
+ let method_result_type = ty::ty_fn_ret(method_type).unwrap();
let option_cleanup_scope = body_bcx_in.fcx.push_custom_cleanup_scope();
let option_cleanup_scope_id = cleanup::CustomScope(option_cleanup_scope);
fcx.pop_loop_cleanup_scope(loop_id);
- if ty::type_is_bot(node_id_type(bcx, loop_id)) {
- Unreachable(next_bcx_in);
- }
-
return next_bcx_in;
}
let dest = match (fcx.llretslotptr.get(), e) {
(Some(_), Some(e)) => {
let ret_ty = expr_ty(bcx, &*e);
- expr::SaveIn(fcx.get_ret_slot(bcx, ret_ty, "ret_slot"))
+ expr::SaveIn(fcx.get_ret_slot(bcx, ty::FnConverging(ret_ty), "ret_slot"))
}
_ => expr::Ignore,
};
let expr_file_line_const = C_struct(ccx, &[v_str, filename, line], false);
let expr_file_line = consts::const_addr_of(ccx, expr_file_line_const, ast::MutImmutable);
let args = vec!(expr_file_line);
- let did = langcall(bcx, Some(sp), "", FailFnLangItem);
+ let did = langcall(bcx, Some(sp), "", PanicFnLangItem);
let bcx = callee::trans_lang_call(bcx,
did,
args.as_slice(),
let file_line_const = C_struct(ccx, &[filename, line], false);
let file_line = consts::const_addr_of(ccx, file_line_const, ast::MutImmutable);
let args = vec!(file_line, index, len);
- let did = langcall(bcx, Some(sp), "", FailBoundsCheckFnLangItem);
+ let did = langcall(bcx, Some(sp), "", PanicBoundsCheckFnLangItem);
let bcx = callee::trans_lang_call(bcx,
did,
args.as_slice(),
}
pub fn to_llbool(self, bcx: Block) -> ValueRef {
- assert!(ty::type_is_bool(self.ty) || ty::type_is_bot(self.ty))
+ assert!(ty::type_is_bool(self.ty))
self.to_llscalarish(bcx)
}
}
use llvm::{ModuleRef, ContextRef, ValueRef};
use llvm::debuginfo::*;
use metadata::csearch;
-use middle::subst;
+use middle::subst::{mod, Subst};
use middle::trans::adt;
use middle::trans::common::*;
use middle::trans::machine;
match ty::get(type_).sty {
ty::ty_nil |
- ty::ty_bot |
ty::ty_bool |
ty::ty_char |
ty::ty_str |
}
unique_type_id.push_str(")->");
- let return_type_id = self.get_unique_type_id_of_type(cx, sig.output);
- let return_type_id = self.get_unique_type_id_as_string(return_type_id);
- unique_type_id.push_str(return_type_id.as_slice());
+ match sig.output {
+ ty::FnConverging(ret_ty) => {
+ let return_type_id = self.get_unique_type_id_of_type(cx, ret_ty);
+ let return_type_id = self.get_unique_type_id_as_string(return_type_id);
+ unique_type_id.push_str(return_type_id.as_slice());
+ }
+ ty::FnDiverging => {
+ unique_type_id.push_str("!");
+ }
+ }
},
ty::ty_closure(box ref closure_ty) => {
self.get_unique_type_id_of_closure_type(cx,
closure_ty.clone(),
&mut unique_type_id);
},
- ty::ty_unboxed_closure(ref def_id, _) => {
+ ty::ty_unboxed_closure(ref def_id, _, ref substs) => {
let closure_ty = cx.tcx().unboxed_closures.borrow()
- .find(def_id).unwrap().closure_type.clone();
+ .find(def_id).unwrap().closure_type.subst(cx.tcx(), substs);
self.get_unique_type_id_of_closure_type(cx,
closure_ty,
&mut unique_type_id);
unique_type_id.push_str("|->");
- let return_type_id = self.get_unique_type_id_of_type(cx, sig.output);
- let return_type_id = self.get_unique_type_id_as_string(return_type_id);
- unique_type_id.push_str(return_type_id.as_slice());
+ match sig.output {
+ ty::FnConverging(ret_ty) => {
+ let return_type_id = self.get_unique_type_id_of_type(cx, ret_ty);
+ let return_type_id = self.get_unique_type_id_as_string(return_type_id);
+ unique_type_id.push_str(return_type_id.as_slice());
+ }
+ ty::FnDiverging => {
+ unique_type_id.push_str("!");
+ }
+ }
unique_type_id.push(':');
}
}
+fn diverging_type_metadata(cx: &CrateContext) -> DIType {
+ "!".with_c_str(|name| {
+ unsafe {
+ llvm::LLVMDIBuilderCreateBasicType(
+ DIB(cx),
+ name,
+ bytes_to_bits(0),
+ bytes_to_bits(0),
+ DW_ATE_unsigned)
+ }
+ })
+}
+
fn basic_type_metadata(cx: &CrateContext, t: ty::t) -> DIType {
debug!("basic_type_metadata: {}", ty::get(t));
let (name, encoding) = match ty::get(t).sty {
ty::ty_nil => ("()".to_string(), DW_ATE_unsigned),
- ty::ty_bot => ("!".to_string(), DW_ATE_unsigned),
ty::ty_bool => ("bool".to_string(), DW_ATE_boolean),
ty::ty_char => ("char".to_string(), DW_ATE_unsigned_char),
ty::ty_int(int_ty) => match int_ty {
let mut signature_metadata: Vec<DIType> = Vec::with_capacity(signature.inputs.len() + 1);
// return type
- signature_metadata.push(match ty::get(signature.output).sty {
- ty::ty_nil => ptr::null_mut(),
- _ => type_metadata(cx, signature.output, span)
+ signature_metadata.push(match signature.output {
+ ty::FnConverging(ret_ty) => match ty::get(ret_ty).sty {
+ ty::ty_nil => ptr::null_mut(),
+ _ => type_metadata(cx, ret_ty, span)
+ },
+ ty::FnDiverging => diverging_type_metadata(cx)
});
// regular arguments
let sty = &ty::get(t).sty;
let MetadataCreationResult { metadata, already_stored_in_typemap } = match *sty {
ty::ty_nil |
- ty::ty_bot |
ty::ty_bool |
ty::ty_char |
ty::ty_int(_) |
ty::ty_closure(ref closurety) => {
subroutine_type_metadata(cx, unique_type_id, &closurety.sig, usage_site_span)
}
- ty::ty_unboxed_closure(ref def_id, _) => {
+ ty::ty_unboxed_closure(ref def_id, _, ref substs) => {
let sig = cx.tcx().unboxed_closures.borrow()
- .find(def_id).unwrap().closure_type.sig.clone();
+ .find(def_id).unwrap().closure_type.sig.subst(cx.tcx(), substs);
subroutine_type_metadata(cx, unique_type_id, &sig, usage_site_span)
}
ty::ty_struct(def_id, ref substs) => {
output:&mut String) {
match ty::get(t).sty {
ty::ty_nil => output.push_str("()"),
- ty::ty_bot => output.push_str("!"),
ty::ty_bool => output.push_str("bool"),
ty::ty_char => output.push_str("char"),
ty::ty_str => output.push_str("str"),
output.push(')');
- if !ty::type_is_nil(sig.output) {
- output.push_str(" -> ");
- push_debuginfo_type_name(cx, sig.output, true, output);
+ match sig.output {
+ ty::FnConverging(result_type) if ty::type_is_nil(result_type) => {}
+ ty::FnConverging(result_type) => {
+ output.push_str(" -> ");
+ push_debuginfo_type_name(cx, result_type, true, output);
+ }
+ ty::FnDiverging => {
+ output.push_str(" -> !");
+ }
}
},
ty::ty_closure(box ty::ClosureTy { fn_style,
output.push(param_list_closing_char);
- if !ty::type_is_nil(sig.output) {
- output.push_str(" -> ");
- push_debuginfo_type_name(cx, sig.output, true, output);
+ match sig.output {
+ ty::FnConverging(result_type) if ty::type_is_nil(result_type) => {}
+ ty::FnConverging(result_type) => {
+ output.push_str(" -> ");
+ push_debuginfo_type_name(cx, result_type, true, output);
+ }
+ ty::FnDiverging => {
+ output.push_str(" -> !");
+ }
}
},
ty::ty_unboxed_closure(..) => {
## The Cleanup module
The cleanup module tracks what values need to be cleaned up as scopes
-are exited, either via failure or just normal control flow. The basic
+are exited, either via panic or just normal control flow. The basic
idea is that the function context maintains a stack of cleanup scopes
that are pushed/popped as we traverse the AST tree. There is typically
at least one cleanup scope per AST node; some AST nodes may introduce
Typically, when a scope is popped, we will also generate the code for
each of its cleanups at that time. This corresponds to a normal exit
from a block (for example, an expression completing evaluation
-successfully without failure). However, it is also possible to pop a
+successfully without panic). However, it is also possible to pop a
block *without* executing its cleanups; this is typically used to
-guard intermediate values that must be cleaned up on failure, but not
+guard intermediate values that must be cleaned up on panic, but not
if everything goes right. See the section on custom scopes below for
more details.
byproducts that need to be freed, then you should use temporary custom
scopes to ensure that those byproducts will get freed on unwind. For
example, an expression like `box foo()` will first allocate a box in the
-heap and then call `foo()` -- if `foo()` should fail, this box needs
+heap and then call `foo()` -- if `foo()` should panic, this box needs
to be *shallowly* freed.
### Long-distance jumps
In addition to popping a scope, which corresponds to normal control
flow exiting the scope, we may also *jump out* of a scope into some
earlier scope on the stack. This can occur in response to a `return`,
-`break`, or `continue` statement, but also in response to failure. In
+`break`, or `continue` statement, but also in response to panic. In
any of these cases, we will generate a series of cleanup blocks for
each of the scopes that is exited. So, if the stack contains scopes A
... Z, and we break out of a loop whose corresponding cleanup scope is
X, we would generate cleanup blocks for the cleanups in X, Y, and Z.
After cleanup is done we would branch to the exit point for scope X.
-But if failure should occur, we would generate cleanups for all the
+But if panic should occur, we would generate cleanups for all the
scopes from A to Z and then resume the unwind process afterwards.
To avoid generating tons of code, we cache the cleanup blocks that we
Custom cleanup scopes are used for a variety of purposes. The most
common though is to handle temporary byproducts, where cleanup only
-needs to occur on failure. The general strategy is to push a custom
+needs to occur on panic. The general strategy is to push a custom
cleanup scope, schedule *shallow* cleanups into the custom scope, and
then pop the custom scope (without transing the cleanups) when
execution succeeds normally. This way the cleanups are only trans'd on
5. Pop the scope C.
6. Return the box as an rvalue.
-This way, if a failure occurs while transing `expr`, the custom
+This way, if a panic occurs while transing `expr`, the custom
cleanup scope C is pushed and hence the box will be freed. The trans
code for `expr` itself is responsible for freeing any other byproducts
that may be in play.
start.as_ref().map(|e| args.push((unpack_datum!(bcx, trans(bcx, &**e)), e.id)));
end.as_ref().map(|e| args.push((unpack_datum!(bcx, trans(bcx, &**e)), e.id)));
- let result_ty = ty::ty_fn_ret(monomorphize_type(bcx, method_ty.unwrap()));
+ let result_ty = ty::ty_fn_ret(monomorphize_type(bcx, method_ty.unwrap())).unwrap();
let scratch = rvalue_scratch_datum(bcx, result_ty, "trans_slice");
unpack_result!(bcx,
base_datum,
vec![(ix_datum, idx.id)],
None));
- let ref_ty = ty::ty_fn_ret(monomorphize_type(bcx, method_ty));
+ let ref_ty = ty::ty_fn_ret(monomorphize_type(bcx, method_ty)).unwrap();
let elt_ty = match ty::deref(ref_ty, true) {
None => {
bcx.tcx().sess.span_bug(index_expr.span,
controlflow::trans_loop(bcx, expr.id, &**body)
}
ast::ExprAssign(ref dst, ref src) => {
+ let src_datum = unpack_datum!(bcx, trans(bcx, &**src));
let dst_datum = unpack_datum!(bcx, trans_to_lvalue(bcx, &**dst, "assign"));
if ty::type_needs_drop(bcx.tcx(), dst_datum.ty) {
// We could avoid this intermediary with some analysis
// to determine whether `dst` may possibly own `src`.
debuginfo::set_source_location(bcx.fcx, expr.id, expr.span);
- let src_datum = unpack_datum!(bcx, trans(bcx, &**src));
let src_datum = unpack_datum!(
bcx, src_datum.to_rvalue_datum(bcx, "ExprAssign"));
bcx = glue::drop_ty(bcx,
Some(NodeInfo { id: expr.id, span: expr.span }));
src_datum.store_to(bcx, dst_datum.val)
} else {
- trans_into(bcx, &**src, SaveIn(dst_datum.to_llref()))
+ src_datum.store_to(bcx, dst_datum.val)
}
}
ast::ExprAssignOp(op, ref dst, ref src) => {
* Helper for enumerating the field types of structs, enums, or records.
* The optional node ID here is the node ID of the path identifying the enum
* variant in use. If none, this cannot possibly an enum variant (so, if it
- * is and `node_id_opt` is none, this function fails).
+ * is and `node_id_opt` is none, this function panics).
*/
match ty::get(ty).sty {
};
// This scope holds intermediates that must be cleaned should
- // failure occur before the ADT as a whole is ready.
+ // panic occur before the ADT as a whole is ready.
let custom_cleanup_scope = fcx.push_custom_cleanup_scope();
// First we trans the base, if we have one, to the dest
let tcx = bcx.tcx();
let is_simd = ty::type_is_simd(tcx, lhs_t);
let intype = {
- if ty::type_is_bot(lhs_t) { rhs_t }
- else if is_simd { ty::simd_type(tcx, lhs_t) }
+ if is_simd { ty::simd_type(tcx, lhs_t) }
else { lhs_t }
};
let is_float = ty::type_is_fp(intype);
} else { LShr(bcx, lhs, rhs) }
}
ast::BiEq | ast::BiNe | ast::BiLt | ast::BiGe | ast::BiLe | ast::BiGt => {
- if ty::type_is_bot(rhs_t) {
- C_bool(bcx.ccx(), false)
- } else if ty::type_is_scalar(rhs_t) {
+ if ty::type_is_scalar(rhs_t) {
unpack_result!(bcx, base::compare_scalar_types(bcx, lhs, rhs, rhs_t, op))
} else if is_simd {
base::compare_simd_types(bcx, lhs, rhs, intype, ty::simd_size(tcx, lhs_t), op)
_ => datum
};
- let ref_ty = ty::ty_fn_ret(monomorphize_type(bcx, method_ty));
+ let ref_ty = ty::ty_fn_ret(monomorphize_type(bcx, method_ty)).unwrap();
let scratch = rvalue_scratch_datum(bcx, ref_ty, "overloaded_deref");
unpack_result!(bcx, trans_overloaded_op(bcx, expr, method_call,
deref_owned_pointer(bcx, expr, datum, content_ty)
} else {
// A fat pointer and an opened DST value have the same
- // represenation just different types. Since there is no
+ // representation just different types. Since there is no
// temporary for `*e` here (because it is unsized), we cannot
// emulate the sized object code path for running drop glue and
// free. Instead, we schedule cleanup for `e`, turning it into
// owner (or, in the case of *T, by the user).
DatumBlock::new(bcx, Datum::new(ptr, content_ty, LvalueExpr))
} else {
- // A fat pointer and an opened DST value have the same represenation
+ // A fat pointer and an opened DST value have the same representation
// just different types.
DatumBlock::new(bcx, Datum::new(datum.val,
ty::mk_open(bcx.tcx(), content_ty),
/// LLVM types that will appear on the foreign function
llsig: LlvmSignature,
-
- /// True if there is a return value (not bottom, not unit)
- ret_def: bool,
}
struct LlvmSignature {
// function, because the foreign function may opt to return via an
// out pointer.
llret_ty: Type,
+
+ /// True if there is a return value (not bottom, not unit)
+ ret_def: bool,
}
_ => ccx.sess().bug("trans_native_call called on non-function type")
};
let llsig = foreign_signature(ccx, &fn_sig, passed_arg_tys.as_slice());
- let ret_def = !return_type_is_void(bcx.ccx(), fn_sig.output);
let fn_type = cabi::compute_abi_info(ccx,
llsig.llarg_tys.as_slice(),
llsig.llret_ty,
- ret_def);
+ llsig.ret_def);
let arg_tys: &[cabi::ArgType] = fn_type.arg_tys.as_slice();
// type to match because some ABIs will use a different type than
// the Rust type. e.g., a {u32,u32} struct could be returned as
// u64.
- if ret_def && !fn_type.ret_ty.is_indirect() {
+ if llsig.ret_def && !fn_type.ret_ty.is_indirect() {
let llrust_ret_ty = llsig.llret_ty;
let llforeign_ret_ty = match fn_type.ret_ty.cast {
Some(ty) => ty,
debug!("llforeign_ret_ty={}", ccx.tn().type_to_string(llforeign_ret_ty));
if llrust_ret_ty == llforeign_ret_ty {
- base::store_ty(bcx, llforeign_retval, llretptr, fn_sig.output)
+ match fn_sig.output {
+ ty::FnConverging(result_ty) => {
+ base::store_ty(bcx, llforeign_retval, llretptr, result_ty)
+ }
+ ty::FnDiverging => {}
+ }
} else {
// The actual return type is a struct, but the ABI
// adaptation code has cast it into some scalar type. The
let c = llvm_calling_convention(ccx, fn_ty.abi);
c.unwrap_or(llvm::CCallConv)
}
- _ => fail!("expected bare fn in decl_rust_fn_with_foreign_abi")
+ _ => panic!("expected bare fn in decl_rust_fn_with_foreign_abi")
};
- let llfn = base::decl_fn(ccx, name, cconv, llfn_ty, ty::mk_nil());
+ let llfn = base::decl_fn(ccx, name, cconv, llfn_ty, ty::FnConverging(ty::mk_nil()));
add_argument_attributes(&tys, llfn);
debug!("decl_rust_fn_with_foreign_abi(llfn_ty={}, llfn={})",
ccx.tn().type_to_string(llfn_ty), ccx.tn().val_to_string(llfn));
let c = llvm_calling_convention(ccx, fn_ty.abi);
c.unwrap_or(llvm::CCallConv)
}
- _ => fail!("expected bare fn in register_rust_fn_with_foreign_abi")
+ _ => panic!("expected bare fn in register_rust_fn_with_foreign_abi")
};
let llfn = base::register_fn_llvmty(ccx, sp, sym, node_id, cconv, llfn_ty);
add_argument_attributes(&tys, llfn);
};
// Push Rust return pointer, using null if it will be unused.
- let rust_uses_outptr =
- type_of::return_uses_outptr(ccx, tys.fn_sig.output);
+ let rust_uses_outptr = match tys.fn_sig.output {
+ ty::FnConverging(ret_ty) => type_of::return_uses_outptr(ccx, ret_ty),
+ ty::FnDiverging => false
+ };
let return_alloca: Option<ValueRef>;
let llrust_ret_ty = tys.llsig.llret_ty;
let llrust_retptr_ty = llrust_ret_ty.ptr_to();
debug!("out pointer, foreign={}",
ccx.tn().val_to_string(llforeign_outptr));
let llrust_retptr =
- builder.bitcast(llforeign_outptr, llrust_ret_ty.ptr_to());
+ builder.bitcast(llforeign_outptr, llrust_retptr_ty);
debug!("out pointer, foreign={} (casted)",
ccx.tn().val_to_string(llrust_retptr));
llrust_args.push(llrust_retptr);
None => tys.fn_ty.ret_ty.ty
};
match foreign_outptr {
- None if !tys.ret_def => {
+ None if !tys.llsig.ret_def => {
// Function returns `()` or `bot`, which in Rust is the LLVM
// type "{}" but in foreign ABIs is "Void".
builder.ret_void();
*/
let llarg_tys = arg_tys.iter().map(|&arg| arg_type_of(ccx, arg)).collect();
- let llret_ty = type_of::arg_type_of(ccx, fn_sig.output);
+ let (llret_ty, ret_def) = match fn_sig.output {
+ ty::FnConverging(ret_ty) =>
+ (type_of::arg_type_of(ccx, ret_ty), !return_type_is_void(ccx, ret_ty)),
+ ty::FnDiverging =>
+ (Type::nil(ccx), false)
+ };
LlvmSignature {
llarg_tys: llarg_tys,
- llret_ty: llret_ty
+ llret_ty: llret_ty,
+ ret_def: ret_def
}
}
_ => ccx.sess().bug("foreign_types_for_fn_ty called on non-function type")
};
let llsig = foreign_signature(ccx, &fn_sig, fn_sig.inputs.as_slice());
- let ret_def = !return_type_is_void(ccx, fn_sig.output);
let fn_ty = cabi::compute_abi_info(ccx,
llsig.llarg_tys.as_slice(),
llsig.llret_ty,
- ret_def);
+ llsig.ret_def);
debug!("foreign_types_for_fn_ty(\
ty={}, \
llsig={} -> {}, \
ccx.tn().type_to_string(llsig.llret_ty),
ccx.tn().types_to_str(fn_ty.arg_tys.iter().map(|t| t.ty).collect::<Vec<_>>().as_slice()),
ccx.tn().type_to_string(fn_ty.ret_ty.ty),
- ret_def);
+ llsig.ret_def);
ForeignTypes {
fn_sig: fn_sig,
llsig: llsig,
- ret_def: ret_def,
fn_ty: fn_ty
}
}
adt::fold_variants(bcx, &*repr, struct_data, |variant_cx, st, value| {
// Be sure to put all of the fields into a scope so we can use an invoke
// instruction to call the user destructor but still call the field
- // destructors if the user destructor fails.
+ // destructors if the user destructor panics.
let field_scope = variant_cx.fcx.push_custom_cleanup_scope();
// Class dtors have no explicit args, so the params should
let arena = TypedArena::new();
let empty_param_substs = param_substs::empty();
- let fcx = new_fn_ctxt(ccx, llfn, ast::DUMMY_NODE_ID, false, ty::mk_nil(),
+ let fcx = new_fn_ctxt(ccx, llfn, ast::DUMMY_NODE_ID, false, ty::FnConverging(ty::mk_nil()),
&empty_param_substs, None, &arena);
- let bcx = init_function(&fcx, false, ty::mk_nil());
+ let bcx = init_function(&fcx, false, ty::FnConverging(ty::mk_nil()));
update_linkage(ccx, llfn, None, OriginalTranslation);
let llrawptr0 = get_param(llfn, fcx.arg_pos(0) as c_uint);
let bcx = helper(bcx, llrawptr0, t);
- finish_fn(&fcx, bcx, ty::mk_nil());
+ finish_fn(&fcx, bcx, ty::FnConverging(ty::mk_nil()));
llfn
}
let ret_ty = match ty::get(callee_ty).sty {
ty::ty_bare_fn(ref f) => f.sig.output,
- _ => fail!("expected bare_fn in trans_intrinsic_call")
+ _ => panic!("expected bare_fn in trans_intrinsic_call")
};
- let llret_ty = type_of::type_of(ccx, ret_ty);
let foreign_item = tcx.map.expect_foreign_item(node);
let name = token::get_ident(foreign_item.ident);
// For `transmute` we can just trans the input expr directly into dest
if name.get() == "transmute" {
+ let llret_ty = type_of::type_of(ccx, ret_ty.unwrap());
match args {
callee::ArgExprs(arg_exprs) => {
assert_eq!(arg_exprs.len(), 1);
}
}
+ // Push the arguments.
+ let mut llargs = Vec::new();
+ bcx = callee::trans_args(bcx,
+ args,
+ callee_ty,
+ &mut llargs,
+ cleanup::CustomScope(cleanup_scope),
+ false,
+ RustIntrinsic);
+
+ fcx.pop_custom_cleanup_scope(cleanup_scope);
+
+ // These are the only intrinsic functions that diverge.
+ if name.get() == "abort" {
+ let llfn = ccx.get_intrinsic(&("llvm.trap"));
+ Call(bcx, llfn, [], None);
+ Unreachable(bcx);
+ return Result::new(bcx, C_undef(Type::nil(ccx).ptr_to()));
+ } else if name.get() == "unreachable" {
+ Unreachable(bcx);
+ return Result::new(bcx, C_nil(ccx));
+ }
+
+ let ret_ty = match ret_ty {
+ ty::FnConverging(ret_ty) => ret_ty,
+ ty::FnDiverging => unreachable!()
+ };
+
+ let llret_ty = type_of::type_of(ccx, ret_ty);
+
// Get location to store the result. If the user does
// not care about the result, just make a stack slot
let llresult = match dest {
}
};
- // Push the arguments.
- let mut llargs = Vec::new();
- bcx = callee::trans_args(bcx,
- args,
- callee_ty,
- &mut llargs,
- cleanup::CustomScope(cleanup_scope),
- false,
- RustIntrinsic);
-
- fcx.pop_custom_cleanup_scope(cleanup_scope);
-
let simple = get_simple_intrinsic(ccx, &*foreign_item);
-
let llval = match (simple, name.get()) {
(Some(llfn), _) => {
Call(bcx, llfn, llargs.as_slice(), None)
}
- (_, "abort") => {
- let llfn = ccx.get_intrinsic(&("llvm.trap"));
- let v = Call(bcx, llfn, [], None);
- Unreachable(bcx);
- v
- }
- (_, "unreachable") => {
- Unreachable(bcx);
- C_nil(ccx)
- }
(_, "breakpoint") => {
let llfn = ccx.get_intrinsic(&("llvm.debugtrap"));
Call(bcx, llfn, [], None)
};
ident.name
}
- _ => fail!("callee is not a trait method")
+ _ => panic!("callee is not a trait method")
}
} else {
csearch::get_item_path(bcx.tcx(), method_id).last().unwrap().name()
Callee { bcx: bcx, data: Fn(llfn) }
}
traits::VtableUnboxedClosure(closure_def_id) => {
- // The static region and type parameters are lies, but we're in
- // trans so it doesn't matter.
- //
- // FIXME(pcwalton): Is this true in the case of type parameters?
- let callee_substs = get_callee_substitutions_for_unboxed_closure(
+ let self_ty = node_id_type(bcx, closure_def_id.node);
+ let callee_substs = get_callee_substitutions_for_unboxed_closure(
bcx,
- closure_def_id);
+ self_ty);
let llfn = trans_fn_ref_with_substs(bcx,
closure_def_id,
};
}
-/// Creates the self type and (fake) callee substitutions for an unboxed
-/// closure with the given def ID. The static region and type parameters are
-/// lies, but we're in trans so it doesn't matter.
+/// Looks up the substitutions for an unboxed closure and adds the
+/// self type
fn get_callee_substitutions_for_unboxed_closure(bcx: Block,
- def_id: ast::DefId)
+ self_ty: ty::t)
-> subst::Substs {
- let self_ty = ty::mk_unboxed_closure(bcx.tcx(), def_id, ty::ReStatic);
- subst::Substs::erased(
- VecPerParamSpace::new(Vec::new(),
- vec![
- ty::mk_rptr(bcx.tcx(),
- ty::ReStatic,
- ty::mt {
+ match ty::get(self_ty).sty {
+ ty::ty_unboxed_closure(_, _, ref substs) => {
+ substs.with_self_ty(ty::mk_rptr(bcx.tcx(),
+ ty::ReStatic,
+ ty::mt {
ty: self_ty,
mutbl: ast::MutMutable,
- })
- ],
- Vec::new()))
+ }))
+ },
+ _ => unreachable!()
+ }
}
/// Creates a returns a dynamic vtable for the given type and vtable origin.
emit_vtable_methods(bcx, id, substs).into_iter()
}
traits::VtableUnboxedClosure(closure_def_id) => {
+ let self_ty = node_id_type(bcx, closure_def_id.node);
+
let callee_substs =
get_callee_substitutions_for_unboxed_closure(
bcx,
- closure_def_id);
+ self_ty.clone());
let mut llfn = trans_fn_ref_with_substs(
bcx,
unboxed closure");
if closure_info.kind == ty::FnOnceUnboxedClosureKind {
// Untuple the arguments and create an unboxing shim.
- let mut new_inputs = vec![
- ty::mk_unboxed_closure(bcx.tcx(),
- closure_def_id,
- ty::ReStatic)
- ];
- match ty::get(closure_info.closure_type
- .sig
- .inputs[0]).sty {
- ty::ty_tup(ref elements) => {
- for element in elements.iter() {
- new_inputs.push(*element)
+ let (new_inputs, new_output) = match ty::get(self_ty).sty {
+ ty::ty_unboxed_closure(_, _, ref substs) => {
+ let mut new_inputs = vec![self_ty.clone()];
+ match ty::get(closure_info.closure_type
+ .sig
+ .inputs[0]).sty {
+ ty::ty_tup(ref elements) => {
+ for element in elements.iter() {
+ new_inputs.push(element.subst(bcx.tcx(), substs));
+ }
+ }
+ ty::ty_nil => {}
+ _ => {
+ bcx.tcx().sess.bug("get_vtable(): closure \
+ type wasn't a tuple")
+ }
}
- }
- ty::ty_nil => {}
- _ => {
- bcx.tcx().sess.bug("get_vtable(): closure \
- type wasn't a tuple")
- }
- }
+ (new_inputs,
+ closure_info.closure_type.sig.output.subst(bcx.tcx(), substs))
+ },
+ _ => bcx.tcx().sess.bug("get_vtable(): def wasn't an unboxed closure")
+ };
let closure_type = ty::BareFnTy {
fn_style: closure_info.closure_type.fn_style,
.sig
.binder_id,
inputs: new_inputs,
- output: closure_info.closure_type.sig.output,
+ output: new_output,
variadic: false,
},
};
return bcx;
}
- // Some cleanup would be required in the case in which failure happens
+ // Some cleanup would be required in the case in which panic happens
// during a copy. But given that copy constructors are not overridable,
// this can only happen as a result of OOM. So we just skip out on the
// cleanup since things would *probably* be broken at that point anyways.
Double => 64,
X86_FP80 => 80,
FP128 | PPC_FP128 => 128,
- _ => fail!("llvm_float_width called on a non-float type")
+ _ => panic!("llvm_float_width called on a non-float type")
}
}
}
pub fn type_of_rust_fn(cx: &CrateContext,
llenvironment_type: Option<Type>,
inputs: &[ty::t],
- output: ty::t,
+ output: ty::FnOutput,
abi: abi::Abi)
-> Type {
let mut atys: Vec<Type> = Vec::new();
// Arg 0: Output pointer.
// (if the output type is non-immediate)
- let use_out_pointer = return_uses_outptr(cx, output);
- let lloutputtype = arg_type_of(cx, output);
- if use_out_pointer {
- atys.push(lloutputtype.ptr_to());
- }
+ let lloutputtype = match output {
+ ty::FnConverging(output) => {
+ let use_out_pointer = return_uses_outptr(cx, output);
+ let lloutputtype = arg_type_of(cx, output);
+ // Use the output as the actual return value if it's immediate.
+ if use_out_pointer {
+ atys.push(lloutputtype.ptr_to());
+ Type::void(cx)
+ } else if return_type_is_void(cx, output) {
+ Type::void(cx)
+ } else {
+ lloutputtype
+ }
+ }
+ ty::FnDiverging => Type::void(cx)
+ };
// Arg 1: Environment
match llenvironment_type {
let input_tys = inputs.iter().map(|&arg_ty| type_of_explicit_arg(cx, arg_ty));
atys.extend(input_tys);
- // Use the output as the actual return value if it's immediate.
- if use_out_pointer || return_type_is_void(cx, output) {
- Type::func(atys.as_slice(), &Type::void(cx))
- } else {
- Type::func(atys.as_slice(), &lloutputtype)
- }
+ Type::func(atys.as_slice(), &lloutputtype)
}
// Given a function type and a count of ty params, construct an llvm type
ppaux::ty_to_string(cx.tcx(), t)).as_slice())
}
- ty::ty_nil | ty::ty_bot => Type::nil(cx),
+ ty::ty_nil => Type::nil(cx),
ty::ty_bool => Type::bool(cx),
ty::ty_char => Type::char(cx),
ty::ty_int(t) => Type::int_from_ty(cx, t),
cx.sess().bug(format!("fictitious type {} in sizing_type_of()",
ppaux::ty_to_string(cx.tcx(), t)).as_slice())
}
- ty::ty_vec(_, None) | ty::ty_trait(..) | ty::ty_str => fail!("unreachable")
+ ty::ty_vec(_, None) | ty::ty_trait(..) | ty::ty_str => panic!("unreachable")
};
cx.llsizingtypes().borrow_mut().insert(t, llsizingty);
match ty::get(ty::unsized_part_of_type(cx.tcx(), t)).sty {
ty::ty_str | ty::ty_vec(..) => Type::uint_from_ty(cx, ast::TyU),
ty::ty_trait(_) => Type::vtable_ptr(cx),
- _ => fail!("Unexpected type returned from unsized_part_of_type : {}",
+ _ => panic!("Unexpected type returned from unsized_part_of_type : {}",
t.repr(cx.tcx()))
}
}
}
let mut llty = match ty::get(t).sty {
- ty::ty_nil | ty::ty_bot => Type::nil(cx),
+ ty::ty_nil => Type::nil(cx),
ty::ty_bool => Type::bool(cx),
ty::ty_char => Type::char(cx),
ty::ty_int(t) => Type::int_from_ty(cx, t),
let name = llvm_type_name(cx, an_enum, did, tps);
adt::incomplete_type_of(cx, &*repr, name.as_slice())
}
- ty::ty_unboxed_closure(did, _) => {
+ ty::ty_unboxed_closure(did, _, ref substs) => {
// Only create the named struct, but don't fill it in. We
// fill it in *after* placing it into the type cache.
let repr = adt::represent_type(cx, t);
- let name = llvm_type_name(cx, an_unboxed_closure, did, []);
+ // Unboxed closures can have substitutions in all spaces
+ // inherited from their environment, so we use entire
+ // contents of the VecPerParamSpace to to construct the llvm
+ // name
+ let name = llvm_type_name(cx, an_unboxed_closure, did, substs.types.as_slice());
adt::incomplete_type_of(cx, &*repr, name.as_slice())
}
pub repr_hint_cache: RefCell<DefIdMap<Rc<Vec<attr::ReprAttr>>>>,
}
-pub enum tbox_flag {
- has_params = 1,
- has_self = 2,
- needs_infer = 4,
- has_regions = 8,
- has_ty_err = 16,
- has_ty_bot = 32,
-
- // a meta-pub flag: subst may be required if the type has parameters, a self
- // type, or references bound regions
- needs_subst = 1 | 2 | 8
+// Flags that we track on types. These flags are propagated upwards
+// through the type during type construction, so that we can quickly
+// check whether the type has various kinds of types in it without
+// recursing over the type itself.
+bitflags! {
+ flags TypeFlags: u32 {
+ const NO_TYPE_FLAGS = 0b0,
+ const HAS_PARAMS = 0b1,
+ const HAS_SELF = 0b10,
+ const HAS_TY_INFER = 0b100,
+ const HAS_RE_INFER = 0b1000,
+ const HAS_REGIONS = 0b10000,
+ const HAS_TY_ERR = 0b100000,
+ const NEEDS_SUBST = HAS_PARAMS.bits | HAS_SELF.bits | HAS_REGIONS.bits,
+ }
}
pub type t_box = &'static t_box_;
pub struct t_box_ {
pub sty: sty,
pub id: uint,
- pub flags: uint,
+ pub flags: TypeFlags,
+}
+
+impl fmt::Show for TypeFlags {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(f, "{}", self.bits)
+ }
}
// To reduce refcounting cost, we're representing types as unsafe pointers
}
}
-pub fn tbox_has_flag(tb: t_box, flag: tbox_flag) -> bool {
- (tb.flags & (flag as uint)) != 0u
+fn tbox_has_flag(tb: t_box, flag: TypeFlags) -> bool {
+ tb.flags.intersects(flag)
}
pub fn type_has_params(t: t) -> bool {
- tbox_has_flag(get(t), has_params)
+ tbox_has_flag(get(t), HAS_PARAMS)
}
-pub fn type_has_self(t: t) -> bool { tbox_has_flag(get(t), has_self) }
+pub fn type_has_self(t: t) -> bool { tbox_has_flag(get(t), HAS_SELF) }
+pub fn type_has_ty_infer(t: t) -> bool { tbox_has_flag(get(t), HAS_TY_INFER) }
pub fn type_needs_infer(t: t) -> bool {
- tbox_has_flag(get(t), needs_infer)
+ tbox_has_flag(get(t), HAS_TY_INFER | HAS_RE_INFER)
}
pub fn type_id(t: t) -> uint { get(t).id }
pub abi: abi::Abi,
}
+#[deriving(Clone, PartialEq, Eq, Hash)]
+pub enum FnOutput {
+ FnConverging(ty::t),
+ FnDiverging
+}
+
+impl FnOutput {
+ pub fn unwrap(&self) -> ty::t {
+ match *self {
+ ty::FnConverging(ref t) => *t,
+ ty::FnDiverging => unreachable!()
+ }
+ }
+}
+
/**
* Signature of a function type, which I have arbitrarily
* decided to use to refer to the input/output types.
pub struct FnSig {
pub binder_id: ast::NodeId,
pub inputs: Vec<t>,
- pub output: t,
+ pub output: FnOutput,
pub variadic: bool
}
pub static $name: t_box_ = t_box_ {
sty: $sty,
id: $id,
- flags: 0,
+ flags: super::NO_TYPE_FLAGS,
};
)
)
def_prim_ty!(TY_F32, super::ty_float(ast::TyF32), 14)
def_prim_ty!(TY_F64, super::ty_float(ast::TyF64), 15)
- pub static TY_BOT: t_box_ = t_box_ {
- sty: super::ty_bot,
- id: 16,
- flags: super::has_ty_bot as uint,
- };
-
pub static TY_ERR: t_box_ = t_box_ {
sty: super::ty_err,
id: 17,
- flags: super::has_ty_err as uint,
+ flags: super::HAS_TY_ERR,
};
pub const LAST_PRIMITIVE_ID: uint = 18;
#[deriving(Clone, PartialEq, Eq, Hash, Show)]
pub enum sty {
ty_nil,
- ty_bot,
ty_bool,
ty_char,
ty_int(ast::IntTy),
ty_closure(Box<ClosureTy>),
ty_trait(Box<TyTrait>),
ty_struct(DefId, Substs),
- ty_unboxed_closure(DefId, Region),
+ ty_unboxed_closure(DefId, Region, Substs),
ty_tup(Vec<t>),
ty_param(ParamTy), // type parameter
terr_builtin_bounds(expected_found<BuiltinBounds>),
terr_variadic_mismatch(expected_found<bool>),
terr_cyclic_ty,
+ terr_convergence_mismatch(expected_found<bool>)
}
/// Bounds suitable for a named type parameter like `A` in `fn foo<A>`
ty_uint(u) => return mk_mach_uint(u),
ty_float(f) => return mk_mach_float(f),
ty_char => return mk_char(),
- ty_bot => return mk_bot(),
_ => {}
};
_ => ()
}
- let mut flags = 0u;
- fn rflags(r: Region) -> uint {
- (has_regions as uint) | {
+ let mut flags = NO_TYPE_FLAGS;
+ fn rflags(r: Region) -> TypeFlags {
+ HAS_REGIONS | {
match r {
- ty::ReInfer(_) => needs_infer as uint,
- _ => 0u
+ ty::ReInfer(_) => HAS_RE_INFER,
+ _ => NO_TYPE_FLAGS,
}
}
}
- fn sflags(substs: &Substs) -> uint {
- let mut f = 0u;
+ fn sflags(substs: &Substs) -> TypeFlags {
+ let mut f = NO_TYPE_FLAGS;
let mut i = substs.types.iter();
for tt in i {
- f |= get(*tt).flags;
+ f = f | get(*tt).flags;
}
match substs.regions {
subst::ErasedRegions => {}
subst::NonerasedRegions(ref regions) => {
for r in regions.iter() {
- f |= rflags(*r)
+ f = f | rflags(*r)
}
}
}
return f;
}
- fn flags_for_bounds(bounds: &ExistentialBounds) -> uint {
+ fn flags_for_bounds(bounds: &ExistentialBounds) -> TypeFlags {
rflags(bounds.region_bound)
}
match &st {
&ty_str => {}
// You might think that we could just return ty_err for
// any type containing ty_err as a component, and get
- // rid of the has_ty_err flag -- likewise for ty_bot (with
+ // rid of the HAS_TY_ERR flag -- likewise for ty_bot (with
// the exception of function types that return bot).
// But doing so caused sporadic memory corruption, and
// neither I (tjc) nor nmatsakis could figure out why,
// so we're doing it this way.
- &ty_bot => flags |= has_ty_bot as uint,
- &ty_err => flags |= has_ty_err as uint,
+ &ty_err => flags = flags | HAS_TY_ERR,
&ty_param(ref p) => {
if p.space == subst::SelfSpace {
- flags |= has_self as uint;
+ flags = flags | HAS_SELF;
} else {
- flags |= has_params as uint;
+ flags = flags | HAS_PARAMS;
}
}
- &ty_unboxed_closure(_, ref region) => flags |= rflags(*region),
- &ty_infer(_) => flags |= needs_infer as uint,
+ &ty_unboxed_closure(_, ref region, ref substs) => {
+ flags = flags | rflags(*region);
+ flags = flags | sflags(substs);
+ }
+ &ty_infer(_) => flags = flags | HAS_TY_INFER,
&ty_enum(_, ref substs) | &ty_struct(_, ref substs) => {
- flags |= sflags(substs);
+ flags = flags | sflags(substs);
}
&ty_trait(box TyTrait { ref substs, ref bounds, .. }) => {
- flags |= sflags(substs);
- flags |= flags_for_bounds(bounds);
+ flags = flags | sflags(substs);
+ flags = flags | flags_for_bounds(bounds);
}
&ty_uniq(tt) | &ty_vec(tt, _) | &ty_open(tt) => {
- flags |= get(tt).flags
+ flags = flags | get(tt).flags
}
&ty_ptr(ref m) => {
- flags |= get(m.ty).flags;
+ flags = flags | get(m.ty).flags;
}
&ty_rptr(r, ref m) => {
- flags |= rflags(r);
- flags |= get(m.ty).flags;
+ flags = flags | rflags(r);
+ flags = flags | get(m.ty).flags;
}
- &ty_tup(ref ts) => for tt in ts.iter() { flags |= get(*tt).flags; },
+ &ty_tup(ref ts) => for tt in ts.iter() { flags = flags | get(*tt).flags; },
&ty_bare_fn(ref f) => {
- for a in f.sig.inputs.iter() { flags |= get(*a).flags; }
- flags |= get(f.sig.output).flags;
- // T -> _|_ is *not* _|_ !
- flags &= !(has_ty_bot as uint);
+ for a in f.sig.inputs.iter() { flags = flags | get(*a).flags; }
+ if let ty::FnConverging(output) = f.sig.output {
+ flags = flags | get(output).flags;
+ }
}
&ty_closure(ref f) => {
match f.store {
RegionTraitStore(r, _) => {
- flags |= rflags(r);
+ flags = flags | rflags(r);
}
_ => {}
}
- for a in f.sig.inputs.iter() { flags |= get(*a).flags; }
- flags |= get(f.sig.output).flags;
- // T -> _|_ is *not* _|_ !
- flags &= !(has_ty_bot as uint);
- flags |= flags_for_bounds(&f.bounds);
+ for a in f.sig.inputs.iter() { flags = flags | get(*a).flags; }
+ if let ty::FnConverging(output) = f.sig.output {
+ flags = flags | get(output).flags;
+ }
+ flags = flags | flags_for_bounds(&f.bounds);
}
}
#[inline]
pub fn mk_err() -> t { mk_prim_t(&primitives::TY_ERR) }
-#[inline]
-pub fn mk_bot() -> t { mk_prim_t(&primitives::TY_BOT) }
-
#[inline]
pub fn mk_bool() -> t { mk_prim_t(&primitives::TY_BOOL) }
sig: FnSig {
binder_id: binder_id,
inputs: input_args,
- output: output,
+ output: ty::FnConverging(output),
variadic: false
}
})
mk_t(cx, ty_struct(struct_id, substs))
}
-pub fn mk_unboxed_closure(cx: &ctxt, closure_id: ast::DefId, region: Region)
+pub fn mk_unboxed_closure(cx: &ctxt, closure_id: ast::DefId, region: Region, substs: Substs)
-> t {
- mk_t(cx, ty_unboxed_closure(closure_id, region))
+ mk_t(cx, ty_unboxed_closure(closure_id, region, substs))
}
pub fn mk_var(cx: &ctxt, v: TyVid) -> t { mk_infer(cx, TyVar(v)) }
return;
}
match get(ty).sty {
- ty_nil | ty_bot | ty_bool | ty_char | ty_int(_) | ty_uint(_) | ty_float(_) |
- ty_str | ty_infer(_) | ty_param(_) | ty_unboxed_closure(_, _) | ty_err => {}
+ ty_nil | ty_bool | ty_char | ty_int(_) | ty_uint(_) | ty_float(_) |
+ ty_str | ty_infer(_) | ty_param(_) | ty_err => {}
ty_uniq(ty) | ty_vec(ty, _) | ty_open(ty) => maybe_walk_ty(ty, f),
ty_ptr(ref tm) | ty_rptr(_, ref tm) => {
maybe_walk_ty(tm.ty, f);
}
- ty_enum(_, ref substs) | ty_struct(_, ref substs) |
+ ty_enum(_, ref substs) | ty_struct(_, ref substs) | ty_unboxed_closure(_, _, ref substs) |
ty_trait(box TyTrait { ref substs, .. }) => {
for subty in (*substs).types.iter() {
maybe_walk_ty(*subty, |x| f(x));
ty_tup(ref ts) => { for tt in ts.iter() { maybe_walk_ty(*tt, |x| f(x)); } }
ty_bare_fn(ref ft) => {
for a in ft.sig.inputs.iter() { maybe_walk_ty(*a, |x| f(x)); }
- maybe_walk_ty(ft.sig.output, f);
+ if let ty::FnConverging(output) = ft.sig.output {
+ maybe_walk_ty(output, f);
+ }
}
ty_closure(ref ft) => {
for a in ft.sig.inputs.iter() { maybe_walk_ty(*a, |x| f(x)); }
- maybe_walk_ty(ft.sig.output, f);
+ if let ty::FnConverging(output) = ft.sig.output {
+ maybe_walk_ty(output, f);
+ }
}
}
}
// Type utilities
-pub fn type_is_nil(ty: t) -> bool { get(ty).sty == ty_nil }
-
-pub fn type_is_bot(ty: t) -> bool {
- (get(ty).flags & (has_ty_bot as uint)) != 0
+pub fn type_is_nil(ty: t) -> bool {
+ get(ty).sty == ty_nil
}
pub fn type_is_error(ty: t) -> bool {
- (get(ty).flags & (has_ty_err as uint)) != 0
+ get(ty).flags.intersects(HAS_TY_ERR)
}
pub fn type_needs_subst(ty: t) -> bool {
- tbox_has_flag(get(ty), needs_subst)
+ tbox_has_flag(get(ty), NEEDS_SUBST)
}
pub fn trait_ref_contains_error(tref: &ty::TraitRef) -> bool {
pub fn type_is_ty_var(ty: t) -> bool {
match get(ty).sty {
- ty_infer(TyVar(_)) => true,
- _ => false
+ ty_infer(TyVar(_)) => true,
+ _ => false
}
}
let fields = lookup_struct_fields(cx, did);
lookup_field_type(cx, did, fields[0].id, substs)
}
- _ => fail!("simd_type called on invalid type")
+ _ => panic!("simd_type called on invalid type")
}
}
let fields = lookup_struct_fields(cx, did);
fields.len()
}
- _ => fail!("simd_size called on invalid type")
+ _ => panic!("simd_size called on invalid type")
}
}
let mut needs_unwind_cleanup = false;
maybe_walk_ty(ty, |ty| {
needs_unwind_cleanup |= match get(ty).sty {
- ty_nil | ty_bot | ty_bool | ty_int(_) | ty_uint(_) |
+ ty_nil | ty_bool | ty_int(_) | ty_uint(_) |
ty_float(_) | ty_tup(_) | ty_ptr(_) => false,
ty_enum(did, ref substs) =>
// Scalar and unique types are sendable, and durable
ty_infer(ty::SkolemizedIntTy(_)) |
- ty_nil | ty_bot | ty_bool | ty_int(_) | ty_uint(_) | ty_float(_) |
+ ty_nil | ty_bool | ty_int(_) | ty_uint(_) | ty_float(_) |
ty_bare_fn(_) | ty::ty_char => {
TC::None
}
apply_lang_items(cx, did, res)
}
- ty_unboxed_closure(did, r) => {
+ ty_unboxed_closure(did, r, ref substs) => {
// FIXME(#14449): `borrowed_contents` below assumes `&mut`
// unboxed closure.
- let upvars = unboxed_closure_upvars(cx, did);
+ let upvars = unboxed_closure_upvars(cx, did, substs);
TypeContents::union(upvars.as_slice(),
|f| tc_ty(cx, f.ty, cache)) |
borrowed_contents(r, MutMutable)
// We only ever ask for the kind of types that are defined in
// the current crate; therefore, the only type parameters that
// could be in scope are those defined in the current crate.
- // If this assertion failures, it is likely because of a
- // failure in the cross-crate inlining code to translate a
+ // If this assertion fails, it is likely because of a
+ // failure of the cross-crate inlining code to translate a
// def-id.
assert_eq!(p.def_id.krate, ast::LOCAL_CRATE);
ty_vec(ty, Some(_)) => type_requires(cx, seen, r_ty, ty),
ty_nil |
- ty_bot |
ty_bool |
ty_char |
ty_int(_) |
r
}
- ty_unboxed_closure(did, _) => {
- let upvars = unboxed_closure_upvars(cx, did);
+ ty_unboxed_closure(did, _, ref substs) => {
+ let upvars = unboxed_closure_upvars(cx, did, substs);
upvars.iter().any(|f| type_requires(cx, seen, r_ty, f.ty))
}
find_nonrepresentable(cx, sp, seen, iter)
}
- ty_unboxed_closure(did, _) => {
- let upvars = unboxed_closure_upvars(cx, did);
+ ty_unboxed_closure(did, _, ref substs) => {
+ let upvars = unboxed_closure_upvars(cx, did, substs);
find_nonrepresentable(cx, sp, seen, upvars.iter().map(|f| f.ty))
}
_ => Representable,
_ => {
assert!(type_is_sized(cx, ty),
"unsized_part_of_type failed even though ty is unsized");
- fail!("called unsized_part_of_type with sized ty");
+ panic!("called unsized_part_of_type with sized ty");
}
}
}
ty_bare_fn(ref f) => f.sig.variadic,
ty_closure(ref f) => f.sig.variadic,
ref s => {
- fail!("fn_is_variadic() called on non-fn type: {}", s)
+ panic!("fn_is_variadic() called on non-fn type: {}", s)
}
}
}
ty_bare_fn(ref f) => f.sig.clone(),
ty_closure(ref f) => f.sig.clone(),
ref s => {
- fail!("ty_fn_sig() called on non-fn type: {}", s)
+ panic!("ty_fn_sig() called on non-fn type: {}", s)
}
}
}
match get(fty).sty {
ty_bare_fn(ref f) => f.abi,
ty_closure(ref f) => f.abi,
- _ => fail!("ty_fn_abi() called on non-fn type"),
+ _ => panic!("ty_fn_abi() called on non-fn type"),
}
}
ty_bare_fn(ref f) => f.sig.inputs.clone(),
ty_closure(ref f) => f.sig.inputs.clone(),
ref s => {
- fail!("ty_fn_args() called on non-fn type: {}", s)
+ panic!("ty_fn_args() called on non-fn type: {}", s)
}
}
}
UniqTraitStore
}
ref s => {
- fail!("ty_closure_store() called on non-closure type: {}", s)
+ panic!("ty_closure_store() called on non-closure type: {}", s)
}
}
}
-pub fn ty_fn_ret(fty: t) -> t {
+pub fn ty_fn_ret(fty: t) -> FnOutput {
match get(fty).sty {
ty_bare_fn(ref f) => f.sig.output,
ty_closure(ref f) => f.sig.output,
ref s => {
- fail!("ty_fn_ret() called on non-fn type: {}", s)
+ panic!("ty_fn_ret() called on non-fn type: {}", s)
}
}
}
let method_call = typeck::MethodCall::autoderef(expr_id, i);
match method_type(method_call) {
Some(method_ty) => {
- adjusted_ty = ty_fn_ret(method_ty);
+ if let ty::FnConverging(result_type) = ty_fn_ret(method_ty) {
+ adjusted_ty = result_type;
+ }
}
None => {}
}
// Special case: A unit like struct's constructor must be called without () at the
// end (like `UnitStruct`) which means this is an ExprPath to a DefFn. But in case
- // of unit structs this is should not be interpretet as function pointer but as
+ // of unit structs this is should not be interpreted as function pointer but as
// call to the constructor.
def::DefFn(_, _, true) => RvalueDpsExpr,
// Special case `Box<T>` for now:
let definition = match tcx.def_map.borrow().find(&place.id) {
Some(&def) => def,
- None => fail!("no def for place"),
+ None => panic!("no def for place"),
};
let def_id = definition.def_id();
if tcx.lang_items.exchange_heap() == Some(def_id) {
ast::StmtDecl(_, id) | StmtExpr(_, id) | StmtSemi(_, id) => {
return id;
}
- ast::StmtMac(..) => fail!("unexpanded macro in trans")
+ ast::StmtMac(..) => panic!("unexpanded macro in trans")
}
}
pub fn ty_sort_string(cx: &ctxt, t: t) -> String {
match get(t).sty {
- ty_nil | ty_bot | ty_bool | ty_char | ty_int(_) |
+ ty_nil | ty_bool | ty_char | ty_int(_) |
ty_uint(_) | ty_float(_) | ty_str => {
::util::ppaux::ty_to_string(cx, t)
}
if values.expected { "variadic" } else { "non-variadic" },
if values.found { "variadic" } else { "non-variadic" })
}
+ terr_convergence_mismatch(ref values) => {
+ format!("expected {} fn, found {} function",
+ if values.expected { "converging" } else { "diverging" },
+ if values.found { "converging" } else { "diverging" })
+ }
}
}
}
if def_id.krate == ast::LOCAL_CRATE {
- fail!("No def'n found for {} in tcx.{}", def_id, descr);
+ panic!("No def'n found for {} in tcx.{}", def_id, descr);
}
let v = load_external();
map.insert(def_id, v.clone());
ty_trait(box TyTrait { def_id: id, .. }) |
ty_struct(id, _) |
ty_enum(id, _) |
- ty_unboxed_closure(id, _) => Some(id),
+ ty_unboxed_closure(id, _, _) => Some(id),
_ => None
}
}
}
// Returns a list of `UnboxedClosureUpvar`s for each upvar.
-pub fn unboxed_closure_upvars(tcx: &ctxt, closure_id: ast::DefId)
+pub fn unboxed_closure_upvars(tcx: &ctxt, closure_id: ast::DefId, substs: &Substs)
-> Vec<UnboxedClosureUpvar> {
if closure_id.krate == ast::LOCAL_CRATE {
let capture_mode = tcx.capture_modes.borrow().get_copy(&closure_id.node);
Some(ref freevars) => {
freevars.iter().map(|freevar| {
let freevar_def_id = freevar.def.def_id();
- let mut freevar_ty = node_id_to_type(tcx, freevar_def_id.node);
+ let freevar_ty = node_id_to_type(tcx, freevar_def_id.node);
+ let mut freevar_ty = freevar_ty.subst(tcx, substs);
if capture_mode == ast::CaptureByRef {
let borrow = tcx.upvar_borrow_map.borrow().get_copy(&ty::UpvarId {
var_id: freevar_def_id.node,
static tycat_char: int = 2;
static tycat_int: int = 3;
static tycat_float: int = 4;
- static tycat_bot: int = 5;
static tycat_raw_ptr: int = 6;
static opcat_add: int = 0;
ty_bool => tycat_bool,
ty_int(_) | ty_uint(_) | ty_infer(IntVar(_)) => tycat_int,
ty_float(_) | ty_infer(FloatVar(_)) => tycat_float,
- ty_bot => tycat_bot,
ty_ptr(_) => tycat_raw_ptr,
_ => tycat_other
}
ty::walk_ty(t, |t| {
match ty::get(t).sty {
ty_nil => byte!(0),
- ty_bot => byte!(1),
ty_bool => byte!(2),
ty_char => byte!(3),
ty_int(i) => {
ty_open(_) => byte!(22),
ty_infer(_) => unreachable!(),
ty_err => byte!(23),
- ty_unboxed_closure(d, r) => {
+ ty_unboxed_closure(d, r, _) => {
byte!(24);
did(&mut state, d);
region(&mut state, r);
MutBorrow => ast::MutMutable,
ImmBorrow => ast::MutImmutable,
- // We have no type correponding to a unique imm borrow, so
+ // We have no type corresponding to a unique imm borrow, so
// use `&mut`. It gives all the capabilities of an `&uniq`
// and hence is a safe "over approximation".
UniqueImmBorrow => ast::MutMutable,
..
}) |
ty_struct(_, ref substs) => {
- match substs.regions {
- subst::ErasedRegions => {}
- subst::NonerasedRegions(ref regions) => {
- for region in regions.iter() {
- accumulator.push(*region)
- }
- }
- }
+ accum_substs(accumulator, substs);
}
ty_closure(ref closure_ty) => {
match closure_ty.store {
UniqTraitStore => {}
}
}
- ty_unboxed_closure(_, ref region) => accumulator.push(*region),
+ ty_unboxed_closure(_, ref region, ref substs) => {
+ accumulator.push(*region);
+ accum_substs(accumulator, substs);
+ }
ty_nil |
- ty_bot |
ty_bool |
ty_char |
ty_int(_) |
ty_open(_) |
ty_err => {}
}
- })
+ });
+
+ fn accum_substs(accumulator: &mut Vec<Region>, substs: &Substs) {
+ match substs.regions {
+ subst::ErasedRegions => {}
+ subst::NonerasedRegions(ref regions) => {
+ for region in regions.iter() {
+ accumulator.push(*region)
+ }
+ }
+ }
+ }
}
/// A free variable referred to in a function.
super_fold_sig(self, sig)
}
+ fn fold_output(&mut self,
+ output: &ty::FnOutput)
+ -> ty::FnOutput {
+ super_fold_output(self, output)
+ }
+
fn fold_bare_fn_ty(&mut self,
fty: &ty::BareFnTy)
-> ty::BareFnTy
}
}
+impl TypeFoldable for ty::FnOutput {
+ fn fold_with<'tcx, F: TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::FnOutput {
+ folder.fold_output(self)
+ }
+}
+
impl TypeFoldable for ty::FnSig {
fn fold_with<'tcx, F: TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::FnSig {
folder.fold_sig(self)
variadic: sig.variadic }
}
+pub fn super_fold_output<'tcx, T: TypeFolder<'tcx>>(this: &mut T,
+ output: &ty::FnOutput)
+ -> ty::FnOutput {
+ match *output {
+ ty::FnConverging(ref ty) => ty::FnConverging(ty.fold_with(this)),
+ ty::FnDiverging => ty::FnDiverging
+ }
+}
+
pub fn super_fold_bare_fn_ty<'tcx, T: TypeFolder<'tcx>>(this: &mut T,
fty: &ty::BareFnTy)
-> ty::BareFnTy
ty::ty_struct(did, ref substs) => {
ty::ty_struct(did, substs.fold_with(this))
}
- ty::ty_unboxed_closure(did, ref region) => {
- ty::ty_unboxed_closure(did, region.fold_with(this))
+ ty::ty_unboxed_closure(did, ref region, ref substs) => {
+ ty::ty_unboxed_closure(did, region.fold_with(this), substs.fold_with(this))
}
- ty::ty_nil | ty::ty_bot | ty::ty_bool | ty::ty_char | ty::ty_str |
+ ty::ty_nil | ty::ty_bool | ty::ty_char | ty::ty_str |
ty::ty_int(_) | ty::ty_uint(_) | ty::ty_float(_) |
ty::ty_err | ty::ty_infer(_) |
ty::ty_param(..) => {
return constr(ty::mk_str(tcx));
}
RPtr(r) => {
- return ty::mk_str_slice(tcx, r, ast::MutImmutable);
+ return ty::mk_str_slice(tcx, r, a_seq_mutbl);
}
}
}
let typ = ast_ty_to_builtin_ty(this, rscope, ast_ty).unwrap_or_else(|| {
match ast_ty.node {
ast::TyNil => ty::mk_nil(),
- ast::TyBot => ty::mk_bot(),
+ ast::TyBot => unreachable!(),
ast::TyUniq(ref ty) => {
mk_pointer(this, rscope, ast::MutImmutable, &**ty, Uniq,
|ty| ty::mk_uniq(tcx, ty))
tcx.map.node_to_string(id.node)).as_slice());
}
def::DefPrimTy(_) => {
- fail!("DefPrimTy arm missed in previous ast_ty_to_prim_ty call");
+ panic!("DefPrimTy arm missed in previous ast_ty_to_prim_ty call");
}
def::DefAssociatedTy(trait_type_id) => {
let path_str = tcx.map.path_to_string(
.collect();
let output_ty = match decl.output.node {
- ast::TyInfer => this.ty_infer(decl.output.span),
- _ => {
- match implied_output_region {
- Some(implied_output_region) => {
- let rb = SpecificRscope::new(implied_output_region);
- ast_ty_to_ty(this, &rb, &*decl.output)
- }
- None => {
- // All regions must be explicitly specified in the output
- // if the lifetime elision rules do not apply. This saves
- // the user from potentially-confusing errors.
- let rb = UnelidableRscope::new(param_lifetimes);
- ast_ty_to_ty(this, &rb, &*decl.output)
- }
+ ast::TyBot => ty::FnDiverging,
+ ast::TyInfer => ty::FnConverging(this.ty_infer(decl.output.span)),
+ _ => ty::FnConverging(match implied_output_region {
+ Some(implied_output_region) => {
+ let rb = SpecificRscope::new(implied_output_region);
+ ast_ty_to_ty(this, &rb, &*decl.output)
}
- }
+ None => {
+ // All regions must be explicitly specified in the output
+ // if the lifetime elision rules do not apply. This saves
+ // the user from potentially-confusing errors.
+ let rb = UnelidableRscope::new(param_lifetimes);
+ ast_ty_to_ty(this, &rb, &*decl.output)
+ }
+ })
};
(ty::BareFnTy {
}).collect();
let expected_ret_ty = expected_sig.map(|e| e.output);
+
let output_ty = match decl.output.node {
+ ast::TyBot => ty::FnDiverging,
ast::TyInfer if expected_ret_ty.is_some() => expected_ret_ty.unwrap(),
- ast::TyInfer => this.ty_infer(decl.output.span),
- _ => ast_ty_to_ty(this, &rb, &*decl.output)
+ ast::TyInfer => ty::FnConverging(this.ty_infer(decl.output.span)),
+ _ => ty::FnConverging(ast_ty_to_ty(this, &rb, &*decl.output))
};
ty::ClosureTy {
let const_did = tcx.def_map.borrow().get_copy(&pat.id).def_id();
let const_pty = ty::lookup_item_type(tcx, const_did);
fcx.write_ty(pat.id, const_pty.ty);
- demand::eqtype(fcx, pat.span, expected, const_pty.ty);
+ demand::suptype(fcx, pat.span, expected, const_pty.ty);
}
ast::PatIdent(bm, ref path, ref sub) if pat_is_binding(&tcx.def_map, pat) => {
let typ = fcx.local_ty(pat.span, pat.id);
// bottom the type lattice, and we'll be moving up the lattice as
// we process each arm. (Note that any match with 0 arms is matching
// on any empty type and is therefore unreachable; should the flow
- // of execution reach it, we will fail, so bottom is an appropriate
+ // of execution reach it, we will panic, so bottom is an appropriate
// type in that case)
- let result_ty = arms.iter().fold(ty::mk_bot(), |result_ty, arm| {
+ let result_ty = arms.iter().fold(fcx.infcx().next_diverging_ty_var(), |result_ty, arm| {
check_expr(fcx, &*arm.body);
let bty = fcx.node_ty(arm.body.id);
let ctor_pty = ty::lookup_item_type(tcx, enum_def);
let path_ty = if ty::is_fn_ty(ctor_pty.ty) {
- ty::Polytype { ty: ty::ty_fn_ret(ctor_pty.ty), ..ctor_pty }
+ ty::Polytype {
+ ty: ty::ty_fn_ret(ctor_pty.ty).unwrap(),
+ ..ctor_pty
+ }
} else {
ctor_pty
};
use middle::typeck::astconv::AstConv;
use middle::typeck::check::{FnCtxt, NoPreference, PreferMutLvalue};
use middle::typeck::check::{impl_self_ty};
-use middle::typeck::check::vtable2::select_fcx_obligations_where_possible;
+use middle::typeck::check::vtable::select_new_fcx_obligations;
use middle::typeck::check;
use middle::typeck::infer;
use middle::typeck::{MethodCall, MethodCallee};
{
match error {
NoMatch(static_sources) => {
+ let cx = fcx.tcx();
+ let method_ustring = method_name.user_string(cx);
+
+ // True if the type is a struct and contains a field with
+ // the same name as the not-found method
+ let is_field = match ty::get(rcvr_ty).sty {
+ ty_struct(did, _) =>
+ ty::lookup_struct_fields(cx, did)
+ .iter()
+ .any(|f| f.name.user_string(cx) == method_ustring),
+ _ => false
+ };
+
fcx.type_error_message(
span,
|actual| {
format!("type `{}` does not implement any \
method in scope named `{}`",
actual,
- method_name.user_string(fcx.tcx()))
+ method_ustring)
},
rcvr_ty,
None);
+ // If the method has the name of a field, give a help note
+ if is_field {
+ cx.sess.span_note(span,
+ format!("use `(s.{0})(...)` if you meant to call the \
+ function stored in the `{0}` field", method_ustring).as_slice());
+ }
+
if static_sources.len() > 0 {
fcx.tcx().sess.fileline_note(
span,
}
ty_enum(did, _) |
ty_struct(did, _) |
- ty_unboxed_closure(did, _) => {
+ ty_unboxed_closure(did, _, _) => {
if self.check_traits == CheckTraitsAndInherentMethods {
self.push_inherent_impl_candidates_for_type(did);
}
let tcx = self.tcx();
- // It is illegal to invoke a method on a trait instance that
- // refers to the `Self` type. An error will be reported by
- // `enforce_object_limitations()` if the method refers to the
- // `Self` type anywhere other than the receiver. Here, we use
- // a substitution that replaces `Self` with the object type
- // itself. Hence, a `&self` method will wind up with an
- // argument type like `&Trait`.
+ // It is illegal to invoke a method on a trait instance that refers to
+ // the `Self` type. Here, we use a substitution that replaces `Self`
+ // with the object type itself. Hence, a `&self` method will wind up
+ // with an argument type like `&Trait`.
let rcvr_substs = substs.with_self_ty(self_ty);
+
let trait_ref = Rc::new(TraitRef {
def_id: did,
substs: rcvr_substs.clone()
// FIXME(#6129). Default methods can't deal with autoref.
//
// I am a horrible monster and I pray for death. Currently
- // the default method code fails when you try to reborrow
+ // the default method code panics when you try to reborrow
// because it is not handling types correctly. In lieu of
// fixing that, I am introducing this horrible hack. - ndm
self_mt.mutbl == MutImmutable && ty::type_is_self(self_mt.ty)
ty::mk_rptr(tcx, r, ty::mt{ ty: tr, mutbl: m })
})
}
- _ => fail!("Expected ty_trait in auto_slice_trait")
+ _ => panic!("Expected ty_trait in auto_slice_trait")
}
}
ty_bare_fn(..) | ty_uniq(..) | ty_rptr(..) |
ty_infer(IntVar(_)) |
ty_infer(FloatVar(_)) |
- ty_param(..) | ty_nil | ty_bot | ty_bool |
+ ty_param(..) | ty_nil | ty_bool |
ty_char | ty_int(..) | ty_uint(..) |
ty_float(..) | ty_enum(..) | ty_ptr(..) | ty_struct(..) |
ty_unboxed_closure(..) | ty_tup(..) | ty_open(..) |
// the `Self` trait).
let callee = self.confirm_candidate(rcvr_ty, &candidate);
- select_fcx_obligations_where_possible(self.fcx);
+ select_new_fcx_obligations(self.fcx);
Some(Ok(callee))
}
self.ty_to_string(rcvr_ty),
candidate.repr(self.tcx()));
- let mut rcvr_substs = candidate.rcvr_substs.clone();
-
- if !self.enforce_object_limitations(candidate) {
- // Here we change `Self` from `Trait` to `err` in the case that
- // this is an illegal object method. This is necessary to prevent
- // the user from getting strange, derivative errors when the method
- // takes an argument/return-type of type `Self` etc.
- rcvr_substs.types.get_mut_slice(SelfSpace)[0] = ty::mk_err();
- }
-
+ let rcvr_substs = candidate.rcvr_substs.clone();
self.enforce_drop_trait_limitations(candidate);
// Determine the values for the generic parameters of the method.
}
}
- fn enforce_object_limitations(&self, candidate: &Candidate) -> bool {
- /*!
- * There are some limitations to calling functions through an
- * object, because (a) the self type is not known
- * (that's the whole point of a trait instance, after all, to
- * obscure the self type) and (b) the call must go through a
- * vtable and hence cannot be monomorphized.
- */
-
- match candidate.origin {
- MethodStatic(..) |
- MethodTypeParam(..) |
- MethodStaticUnboxedClosure(..) => {
- return true; // not a call to a trait instance
- }
- MethodTraitObject(..) => {}
- }
-
- match candidate.method_ty.explicit_self {
- ty::StaticExplicitSelfCategory => { // reason (a) above
- self.tcx().sess.span_err(
- self.span,
- "cannot call a method without a receiver \
- through an object");
- return false;
- }
-
- ty::ByValueExplicitSelfCategory |
- ty::ByReferenceExplicitSelfCategory(..) |
- ty::ByBoxExplicitSelfCategory => {}
- }
-
- // reason (a) above
- let check_for_self_ty = |ty| -> bool {
- if ty::type_has_self(ty) {
- span_err!(self.tcx().sess, self.span, E0038,
- "cannot call a method whose type contains a \
- self-type through an object");
- false
- } else {
- true
- }
- };
- let ref sig = candidate.method_ty.fty.sig;
- for &input_ty in sig.inputs[1..].iter() {
- if !check_for_self_ty(input_ty) {
- return false;
- }
- }
- if !check_for_self_ty(sig.output) {
- return false;
- }
-
- if candidate.method_ty.generics.has_type_params(subst::FnSpace) {
- // reason (b) above
- span_err!(self.tcx().sess, self.span, E0039,
- "cannot call a generic method through an object");
- return false;
- }
-
- true
- }
-
fn enforce_drop_trait_limitations(&self, candidate: &Candidate) {
// No code can call the finalize method explicitly.
let bad = match candidate.origin {
ImplSource(def_id)
}
MethodStaticUnboxedClosure(..) => {
- fail!("MethodStaticUnboxedClosure only used in trans")
+ panic!("MethodStaticUnboxedClosure only used in trans")
}
MethodTypeParam(ref param) => {
TraitSource(param.trait_ref.def_id)
use middle::typeck::check::method::{CheckTraitsAndInherentMethods};
use middle::typeck::check::regionmanip::replace_late_bound_regions;
use middle::typeck::CrateCtxt;
-use middle::typeck::infer::{resolve_type, force_tvar};
use middle::typeck::infer;
use middle::typeck::rscope::RegionScope;
use middle::typeck::{lookup_def_ccx};
use syntax;
pub mod _match;
-pub mod vtable2; // New trait code
+pub mod vtable;
pub mod writeback;
pub mod regionmanip;
pub mod regionck;
// expects the types within the function to be consistent.
err_count_on_creation: uint,
- ret_ty: ty::t,
+ ret_ty: ty::FnOutput,
ps: RefCell<FnStyleState>,
// Used by check_const and check_enum_variants
pub fn blank_fn_ctxt<'a, 'tcx>(ccx: &'a CrateCtxt<'a, 'tcx>,
inh: &'a Inherited<'a, 'tcx>,
- rty: ty::t,
+ rty: ty::FnOutput,
body_id: ast::NodeId)
-> FnCtxt<'a, 'tcx> {
FnCtxt {
let fcx = check_fn(ccx, fn_ty.fn_style, id, &fn_ty.sig,
decl, id, body, &inh);
- vtable2::select_all_fcx_obligations_or_error(&fcx);
+ vtable::select_all_fcx_obligations_or_error(&fcx);
regionck::regionck_fn(&fcx, id, body);
+ fcx.default_diverging_type_variables_to_nil();
writeback::resolve_type_vars_in_fn(&fcx, decl, body);
}
_ => ccx.tcx.sess.impossible_case(body.span,
match ty_opt {
None => {
// infer the variable's type
- let var_id = self.fcx.infcx().next_ty_var_id();
- let var_ty = ty::mk_var(self.fcx.tcx(), var_id);
+ let var_ty = self.fcx.infcx().next_ty_var();
self.fcx.inh.locals.borrow_mut().insert(nid, var_ty);
var_ty
}
};
// Remember return type so that regionck can access it later.
- let fn_sig_tys: Vec<ty::t> =
- arg_tys.iter().chain([ret_ty].iter()).map(|&ty| ty).collect();
+ let mut fn_sig_tys: Vec<ty::t> =
+ arg_tys.iter()
+ .map(|&ty| ty)
+ .collect();
+
+ if let ty::FnConverging(ret_ty) = ret_ty {
+ fcx.require_type_is_sized(ret_ty, decl.output.span, traits::ReturnType);
+ fn_sig_tys.push(ret_ty);
+ }
+
debug!("fn-sig-map: fn_id={} fn_sig_tys={}",
fn_id,
fn_sig_tys.repr(tcx));
visit.visit_block(body);
}
- fcx.require_type_is_sized(ret_ty, decl.output.span, traits::ReturnType);
- check_block_with_expected(&fcx, body, ExpectHasType(ret_ty));
+ check_block_with_expected(&fcx, body, match ret_ty {
+ ty::FnConverging(result_type) => ExpectHasType(result_type),
+ ty::FnDiverging => NoExpectation
+ });
for (input, arg) in decl.inputs.iter().zip(arg_tys.iter()) {
fcx.write_ty(input.id, *arg);
return
}
- if ty::type_is_bot(t_e) {
- fcx.write_bot(id);
- return
- }
-
if !ty::type_is_sized(fcx.tcx(), t_1) {
let tstr = fcx.infcx().ty_to_string(t_1);
fcx.type_error_message(span, |actual| {
if ty::type_is_trait(t_1) {
// This will be looked up later on.
- vtable2::check_object_cast(fcx, cast_expr, e, t_1);
+ vtable::check_object_cast(fcx, cast_expr, e, t_1);
fcx.write_ty(id, t_1);
return
}
}
// casts from C-like enums are allowed
} else if t_1_is_char {
- let t_e = fcx.infcx().resolve_type_vars_if_possible(t_e);
+ let t_e = fcx.infcx().shallow_resolve(t_e);
if ty::get(t_e).sty != ty::ty_uint(ast::TyU8) {
fcx.type_error_message(span, |actual| {
format!("only `u8` can be cast as \
}
}
+ pub fn default_diverging_type_variables_to_nil(&self) {
+ for (_, &ref ty) in self.inh.node_types.borrow_mut().iter_mut() {
+ if self.infcx().type_var_diverges(self.infcx().resolve_type_vars_if_possible(*ty)) {
+ demand::eqtype(self, codemap::DUMMY_SP, *ty, ty::mk_nil());
+ }
+ }
+ }
+
#[inline]
pub fn write_ty(&self, node_id: ast::NodeId, ty: ty::t) {
debug!("write_ty({}, {}) in fcx {}",
self.register_unsize_obligations(span, &**u)
}
ty::UnsizeVtable(ref ty_trait, self_ty) => {
+ vtable::check_object_safety(self.tcx(), ty_trait, span);
// If the type is `Foo+'a`, ensures that the type
// being cast to `Foo+'a` implements `Foo`:
- vtable2::register_object_cast_obligations(self,
+ vtable::register_object_cast_obligations(self,
span,
ty_trait,
self_ty);
pub fn write_nil(&self, node_id: ast::NodeId) {
self.write_ty(node_id, ty::mk_nil());
}
- pub fn write_bot(&self, node_id: ast::NodeId) {
- self.write_ty(node_id, ty::mk_bot());
- }
pub fn write_error(&self, node_id: ast::NodeId) {
self.write_ty(node_id, ty::mk_err());
}
for autoderefs in range(0, fcx.tcx().sess.recursion_limit.get()) {
let resolved_t = structurally_resolved_type(fcx, sp, t);
- if ty::type_is_bot(resolved_t) {
- return (resolved_t, autoderefs, None);
- }
-
match should_stop(resolved_t, autoderefs) {
Some(x) => return (resolved_t, autoderefs, Some(x)),
None => {}
}
None => {}
}
- ty::deref(ref_ty, true)
+ match ref_ty {
+ ty::FnConverging(ref_ty) =>
+ ty::deref(ref_ty, true),
+ ty::FnDiverging =>
+ None
+ }
}
None => None,
}
}
None => {}
}
- Some(ty::mt { ty: result_ty, mutbl: ast::MutImmutable })
+ match result_ty {
+ ty::FnConverging(result_ty) =>
+ Some(ty::mt { ty: result_ty, mutbl: ast::MutImmutable }),
+ ty::FnDiverging =>
+ None
+ }
}
None => None,
}
// We expect the return type to be `Option` or something like it.
// Grab the first parameter of its type substitution.
- let return_type = structurally_resolved_type(fcx,
- iterator_expr.span,
- return_type);
+ let return_type = match return_type {
+ ty::FnConverging(return_type) =>
+ structurally_resolved_type(fcx, iterator_expr.span, return_type),
+ ty::FnDiverging => ty::mk_err()
+ };
match ty::get(return_type).sty {
ty::ty_enum(_, ref substs)
if !substs.types.is_empty_in(subst::TypeSpace) => {
args_no_rcvr: &[&'a P<ast::Expr>],
deref_args: DerefArgs,
tuple_arguments: TupleArgumentsFlag)
- -> ty::t {
+ -> ty::FnOutput {
if ty::type_is_error(method_fn_ty) {
let err_inputs = err_args(args_no_rcvr.len());
check_argument_types(fcx,
deref_args,
false,
tuple_arguments);
- method_fn_ty
+ ty::FnConverging(method_fn_ty)
} else {
match ty::get(method_fn_ty).sty {
ty::ty_bare_fn(ref fty) => {
// an "opportunistic" vtable resolution of any trait
// bounds on the call.
if check_blocks {
- vtable2::select_fcx_obligations_where_possible(fcx);
+ vtable::select_new_fcx_obligations(fcx);
}
// For variadic functions, we don't have a declared type for all of
Vec::from_fn(len, |_| ty::mk_err())
}
-fn write_call(fcx: &FnCtxt, call_expr: &ast::Expr, output: ty::t) {
- fcx.write_ty(call_expr.id, output);
+fn write_call(fcx: &FnCtxt, call_expr: &ast::Expr, output: ty::FnOutput) {
+ fcx.write_ty(call_expr.id, match output {
+ ty::FnConverging(output_ty) => output_ty,
+ ty::FnDiverging => fcx.infcx().next_diverging_ty_var()
+ });
}
// AST fragment checking
/// strict, _|_ can appear in the type of an expression that does not,
/// itself, diverge: for example, fn() -> _|_.)
/// Note that inspecting a type's structure *directly* may expose the fact
-/// that there are actually multiple representations for both `ty_err` and
-/// `ty_bot`, so avoid that when err and bot need to be handled differently.
+/// that there are actually multiple representations for `ty_err`, so avoid
+/// that when err needs to be handled differently.
fn check_expr_with_unifier(fcx: &FnCtxt,
expr: &ast::Expr,
expected: Expectation,
let error_fn_sig = FnSig {
binder_id: ast::CRATE_NODE_ID,
inputs: err_args(args.len()),
- output: ty::mk_err(),
+ output: ty::FnConverging(ty::mk_err()),
variadic: false
};
// 'else' branch.
let expected = match expected.only_has_type() {
ExpectHasType(ety) => {
- match infer::resolve_type(fcx.infcx(), Some(sp), ety, force_tvar) {
- Ok(rty) if !ty::type_is_ty_var(rty) => ExpectHasType(rty),
- _ => NoExpectation
+ let ety = fcx.infcx().shallow_resolve(ety);
+ if !ty::type_is_ty_var(ety) {
+ ExpectHasType(ety)
+ } else {
+ NoExpectation
}
}
_ => NoExpectation
let cond_ty = fcx.expr_ty(cond_expr);
let if_ty = if ty::type_is_error(cond_ty) {
ty::mk_err()
- } else if ty::type_is_bot(cond_ty) {
- ty::mk_bot()
} else {
branches_ty
};
// HACK(eddyb) Fully qualified path to work around a resolve bug.
let method_call = ::middle::typeck::MethodCall::expr(op_ex.id);
fcx.inh.method_map.borrow_mut().insert(method_call, method);
- check_method_argument_types(fcx,
+ match check_method_argument_types(fcx,
op_ex.span,
method_ty,
op_ex,
args.as_slice(),
DoDerefArgs,
- DontTupleArguments)
+ DontTupleArguments) {
+ ty::FnConverging(result_type) => result_type,
+ ty::FnDiverging => ty::mk_err()
+ }
}
None => {
unbound_method();
};
let closure_type = ty::mk_unboxed_closure(fcx.ccx.tcx,
local_def(expr.id),
- region);
+ region,
+ fcx.inh.param_env.free_substs.clone());
fcx.write_ty(expr.id, closure_type);
check_fn(fcx.ccx,
None => {}
Some(base_expr) => {
check_expr_has_type(fcx, &*base_expr, struct_type);
- if ty::type_is_bot(fcx.node_ty(base_expr.id)) {
- struct_type = ty::mk_bot();
- }
}
}
ty::type_is_error(rhs_ty) {
fcx.write_error(id);
}
- else if ty::type_is_bot(lhs_ty) ||
- (ty::type_is_bot(rhs_ty) && !ast_util::lazy_binop(op)) {
- fcx.write_bot(id);
- }
}
ast::ExprAssignOp(op, ref lhs, ref rhs) => {
check_binop(fcx, expr, op, &**lhs, rhs, BinopAssignment);
// Overwrite result of check_binop...this preserves existing behavior
// but seems quite dubious with regard to user-defined methods
// and so forth. - Niko
- if !ty::type_is_error(result_t)
- && !ty::type_is_bot(result_t) {
+ if !ty::type_is_error(result_t) {
fcx.write_nil(expr.id);
}
}
if !ty::type_is_error(oprnd_t) {
match unop {
ast::UnUniq => {
- if !ty::type_is_bot(oprnd_t) {
- oprnd_t = ty::mk_uniq(tcx, oprnd_t);
- }
+ oprnd_t = ty::mk_uniq(tcx, oprnd_t);
}
ast::UnDeref => {
oprnd_t = structurally_resolved_type(fcx, expr.span, oprnd_t);
};
}
ast::UnNot => {
- if !ty::type_is_bot(oprnd_t) {
- oprnd_t = structurally_resolved_type(fcx, oprnd.span,
- oprnd_t);
- if !(ty::type_is_integral(oprnd_t) ||
- ty::get(oprnd_t).sty == ty::ty_bool) {
- oprnd_t = check_user_unop(fcx, "!", "not",
- tcx.lang_items.not_trait(),
- expr, &**oprnd, oprnd_t);
- }
+ oprnd_t = structurally_resolved_type(fcx, oprnd.span,
+ oprnd_t);
+ if !(ty::type_is_integral(oprnd_t) ||
+ ty::get(oprnd_t).sty == ty::ty_bool) {
+ oprnd_t = check_user_unop(fcx, "!", "not",
+ tcx.lang_items.not_trait(),
+ expr, &**oprnd, oprnd_t);
}
}
ast::UnNeg => {
- if !ty::type_is_bot(oprnd_t) {
- oprnd_t = structurally_resolved_type(fcx, oprnd.span,
- oprnd_t);
- if !(ty::type_is_integral(oprnd_t) ||
- ty::type_is_fp(oprnd_t)) {
- oprnd_t = check_user_unop(fcx, "-", "neg",
- tcx.lang_items.neg_trait(),
- expr, &**oprnd, oprnd_t);
- }
+ oprnd_t = structurally_resolved_type(fcx, oprnd.span,
+ oprnd_t);
+ if !(ty::type_is_integral(oprnd_t) ||
+ ty::type_is_fp(oprnd_t)) {
+ oprnd_t = check_user_unop(fcx, "-", "neg",
+ tcx.lang_items.neg_trait(),
+ expr, &**oprnd, oprnd_t);
}
}
}
let tm = ty::mt { ty: fcx.expr_ty(&**oprnd), mutbl: mutbl };
let oprnd_t = if ty::type_is_error(tm.ty) {
ty::mk_err()
- } else if ty::type_is_bot(tm.ty) {
- ty::mk_bot()
- }
- else {
+ } else {
// Note: at this point, we cannot say what the best lifetime
// is to use for resulting pointer. We want to use the
// shortest lifetime possible so as to avoid spurious borrowck
fcx.write_nil(id);
}
ast::ExprMac(_) => tcx.sess.bug("unexpanded macro"),
- ast::ExprBreak(_) => { fcx.write_bot(id); }
- ast::ExprAgain(_) => { fcx.write_bot(id); }
+ ast::ExprBreak(_) => { fcx.write_ty(id, fcx.infcx().next_diverging_ty_var()); }
+ ast::ExprAgain(_) => { fcx.write_ty(id, fcx.infcx().next_diverging_ty_var()); }
ast::ExprRet(ref expr_opt) => {
- let ret_ty = fcx.ret_ty;
- match *expr_opt {
- None => match fcx.mk_eqty(false, infer::Misc(expr.span),
- ret_ty, ty::mk_nil()) {
- Ok(_) => { /* fall through */ }
- Err(_) => {
- span_err!(tcx.sess, expr.span, E0069,
- "`return;` in function returning non-nil");
+ match fcx.ret_ty {
+ ty::FnConverging(result_type) => {
+ match *expr_opt {
+ None =>
+ if let Err(_) = fcx.mk_eqty(false, infer::Misc(expr.span),
+ result_type, ty::mk_nil()) {
+ span_err!(tcx.sess, expr.span, E0069,
+ "`return;` in function returning non-nil");
+ },
+ Some(ref e) => {
+ check_expr_coercable_to_type(fcx, &**e, result_type);
+ }
+ }
+ }
+ ty::FnDiverging => {
+ if let Some(ref e) = *expr_opt {
+ check_expr(fcx, &**e);
+ }
+ span_err!(tcx.sess, expr.span, E0166,
+ "`return` in a function declared as diverging");
}
- },
- Some(ref e) => {
- check_expr_coercable_to_type(fcx, &**e, ret_ty);
- }
}
- fcx.write_bot(id);
+ fcx.write_ty(id, fcx.infcx().next_diverging_ty_var());
}
ast::ExprParen(ref a) => {
check_expr_with_expectation_and_lvalue_pref(fcx,
if ty::type_is_error(lhs_ty) || ty::type_is_error(rhs_ty) {
fcx.write_error(id);
- } else if ty::type_is_bot(lhs_ty) || ty::type_is_bot(rhs_ty) {
- fcx.write_bot(id);
} else {
fcx.write_nil(id);
}
if ty::type_is_error(cond_ty) || ty::type_is_error(body_ty) {
fcx.write_error(id);
}
- else if ty::type_is_bot(cond_ty) {
- fcx.write_bot(id);
- }
else {
fcx.write_nil(id);
}
ast::ExprForLoop(ref pat, ref head, ref block, _) => {
check_expr(fcx, &**head);
let typ = lookup_method_for_for_loop(fcx, &**head, expr.id);
- vtable2::select_fcx_obligations_where_possible(fcx);
+ vtable::select_new_fcx_obligations(fcx);
let pcx = pat_ctxt {
fcx: fcx,
ast::ExprLoop(ref body, _) => {
check_block_no_value(fcx, &**body);
if !may_break(tcx, expr.id, &**body) {
- fcx.write_bot(id);
+ fcx.write_ty(id, fcx.infcx().next_diverging_ty_var());
} else {
fcx.write_nil(id);
}
let args: Vec<_> = args.iter().map(|x| x).collect();
if !try_overloaded_call(fcx, expr, &**f, f_ty, args.as_slice()) {
check_call(fcx, expr, &**f, args.as_slice());
- let (args_bot, args_err) = args.iter().fold((false, false),
- |(rest_bot, rest_err), a| {
+ let args_err = args.iter().fold(false,
+ |rest_err, a| {
// is this not working?
let a_ty = fcx.expr_ty(&***a);
- (rest_bot || ty::type_is_bot(a_ty),
- rest_err || ty::type_is_error(a_ty))});
+ rest_err || ty::type_is_error(a_ty)});
if ty::type_is_error(f_ty) || args_err {
fcx.write_error(id);
}
- else if ty::type_is_bot(f_ty) || args_bot {
- fcx.write_bot(id);
- }
}
}
ast::ExprMethodCall(ident, ref tps, ref args) => {
check_method_call(fcx, expr, ident, args.as_slice(), tps.as_slice(), lvalue_pref);
let mut arg_tys = args.iter().map(|a| fcx.expr_ty(&**a));
- let (args_bot, args_err) = arg_tys.fold((false, false),
- |(rest_bot, rest_err), a| {
- (rest_bot || ty::type_is_bot(a),
- rest_err || ty::type_is_error(a))});
+ let args_err = arg_tys.fold(false,
+ |rest_err, a| {
+ rest_err || ty::type_is_error(a)});
if args_err {
fcx.write_error(id);
- } else if args_bot {
- fcx.write_bot(id);
}
}
ast::ExprCast(ref e, ref t) => {
if ty::type_is_error(element_ty) {
fcx.write_error(id);
- } else if ty::type_is_bot(element_ty) {
- fcx.write_bot(id);
} else {
let t = ty::mk_vec(tcx, t, Some(count));
fcx.write_ty(id, t);
_ => None
}
});
- let mut bot_field = false;
let mut err_field = false;
let elt_ts = elts.iter().enumerate().map(|(i, e)| {
}
};
err_field = err_field || ty::type_is_error(t);
- bot_field = bot_field || ty::type_is_bot(t);
t
}).collect();
- if bot_field {
- fcx.write_bot(id);
- } else if err_field {
+ if err_field {
fcx.write_error(id);
} else {
let typ = ty::mk_tup(tcx, elt_ts);
autoderef(fcx, expr.span, raw_base_t, Some(base.id),
lvalue_pref, |base_t, _| ty::index(base_t));
match field_ty {
- Some(ty) if !ty::type_is_bot(ty) => {
+ Some(ty) => {
check_expr_has_type(fcx, &**idx, ty::mk_uint());
fcx.write_ty(id, ty);
fcx.write_autoderef_adjustment(base.id, base.span, autoderefs);
let raw_base_t = fcx.expr_ty(&**base);
let mut some_err = false;
- if ty::type_is_error(raw_base_t) || ty::type_is_bot(raw_base_t) {
+ if ty::type_is_error(raw_base_t) {
fcx.write_ty(id, raw_base_t);
some_err = true;
}
let check_slice_idx = |e: &ast::Expr| {
check_expr(fcx, e);
let e_t = fcx.expr_ty(e);
- if ty::type_is_error(e_t) || ty::type_is_bot(e_t) {
+ if ty::type_is_error(e_t) {
fcx.write_ty(id, e_t);
some_err = true;
}
Some(ref init) => {
check_decl_initializer(fcx, local.id, &**init);
let init_ty = fcx.expr_ty(&**init);
- if ty::type_is_error(init_ty) || ty::type_is_bot(init_ty) {
+ if ty::type_is_error(init_ty) {
fcx.write_ty(local.id, init_ty);
}
}
};
_match::check_pat(&pcx, &*local.pat, t);
let pat_ty = fcx.node_ty(local.pat.id);
- if ty::type_is_error(pat_ty) || ty::type_is_bot(pat_ty) {
+ if ty::type_is_error(pat_ty) {
fcx.write_ty(local.id, pat_ty);
}
}
ast::DeclLocal(ref l) => {
check_decl_local(fcx, &**l);
let l_t = fcx.node_ty(l.id);
- saw_bot = saw_bot || ty::type_is_bot(l_t);
+ saw_bot = saw_bot || fcx.infcx().type_var_diverges(l_t);
saw_err = saw_err || ty::type_is_error(l_t);
}
ast::DeclItem(_) => {/* ignore for now */ }
// Check with expected type of ()
check_expr_has_type(fcx, &**expr, ty::mk_nil());
let expr_ty = fcx.expr_ty(&**expr);
- saw_bot = saw_bot || ty::type_is_bot(expr_ty);
+ saw_bot = saw_bot || fcx.infcx().type_var_diverges(expr_ty);
saw_err = saw_err || ty::type_is_error(expr_ty);
}
ast::StmtSemi(ref expr, id) => {
node_id = id;
check_expr(fcx, &**expr);
let expr_ty = fcx.expr_ty(&**expr);
- saw_bot |= ty::type_is_bot(expr_ty);
+ saw_bot |= fcx.infcx().type_var_diverges(expr_ty);
saw_err |= ty::type_is_error(expr_ty);
}
ast::StmtMac(..) => fcx.ccx.tcx.sess.bug("unexpanded macro")
}
if saw_bot {
- fcx.write_bot(node_id);
+ fcx.write_ty(node_id, fcx.infcx().next_diverging_ty_var());
}
else if saw_err {
fcx.write_error(node_id);
let blkty = fcx.node_ty(blk.id);
if ty::type_is_error(blkty) {
fcx.write_error(blk.id);
- }
- else if ty::type_is_bot(blkty) {
- fcx.write_bot(blk.id);
- }
- else {
+ } else {
let nilty = ty::mk_nil();
demand::suptype(fcx, blk.span, nilty, blkty);
}
};
let mut warned = false;
- let mut last_was_bot = false;
- let mut any_bot = false;
+ let mut any_diverges = false;
let mut any_err = false;
for s in blk.stmts.iter() {
check_stmt(fcx, &**s);
let s_id = ast_util::stmt_id(&**s);
let s_ty = fcx.node_ty(s_id);
- if last_was_bot && !warned && match s.node {
+ if any_diverges && !warned && match s.node {
ast::StmtDecl(ref decl, _) => {
match decl.node {
ast::DeclLocal(_) => true,
"unreachable statement".to_string());
warned = true;
}
- if ty::type_is_bot(s_ty) {
- last_was_bot = true;
- }
- any_bot = any_bot || ty::type_is_bot(s_ty);
+ any_diverges = any_diverges || fcx.infcx().type_var_diverges(s_ty);
any_err = any_err || ty::type_is_error(s_ty);
}
match blk.expr {
None => if any_err {
fcx.write_error(blk.id);
- } else if any_bot {
- fcx.write_bot(blk.id);
+ } else if any_diverges {
+ fcx.write_ty(blk.id, fcx.infcx().next_diverging_ty_var());
} else {
fcx.write_nil(blk.id);
},
Some(ref e) => {
- if any_bot && !warned {
+ if any_diverges && !warned {
fcx.ccx
.tcx
.sess
}
};
- fcx.write_ty(blk.id, ety);
if any_err {
fcx.write_error(blk.id);
- } else if any_bot {
- fcx.write_bot(blk.id);
+ } else if any_diverges {
+ fcx.write_ty(blk.id, fcx.infcx().next_diverging_ty_var());
+ } else {
+ fcx.write_ty(blk.id, ety);
}
}
};
tcx: tcx,
};
let inh = static_inherited_fields(&ccx);
- let fcx = blank_fn_ctxt(&ccx, &inh, expected_type, expr.id);
+ let fcx = blank_fn_ctxt(&ccx, &inh, ty::FnConverging(expected_type), expr.id);
check_const_with_ty(&fcx, expr.span, expr, expected_type);
}
id: ast::NodeId) {
let inh = static_inherited_fields(ccx);
let rty = ty::node_id_to_type(ccx.tcx, id);
- let fcx = blank_fn_ctxt(ccx, &inh, rty, e.id);
+ let fcx = blank_fn_ctxt(ccx, &inh, ty::FnConverging(rty), e.id);
let declty = (*fcx.ccx.tcx.tcache.borrow())[local_def(id)].ty;
check_const_with_ty(&fcx, sp, e, declty);
}
check_expr_with_hint(fcx, e, declty);
demand::coerce(fcx, e.span, declty, e);
- vtable2::select_all_fcx_obligations_or_error(fcx);
+ vtable::select_all_fcx_obligations_or_error(fcx);
regionck::regionck_expr(fcx, e);
writeback::resolve_type_vars_in_expr(fcx, e);
}
debug!("disr expr, checking {}", pprust::expr_to_string(&**e));
let inh = static_inherited_fields(ccx);
- let fcx = blank_fn_ctxt(ccx, &inh, rty, e.id);
+ let fcx = blank_fn_ctxt(ccx, &inh, ty::FnConverging(rty), e.id);
let declty = match hint {
attr::ReprAny | attr::ReprPacked | attr::ReprExtern => ty::mk_int(),
attr::ReprInt(_, attr::SignedInt(ity)) => {
// Resolves `typ` by a single level if `typ` is a type variable. If no
// resolution is possible, then an error is reported.
-pub fn structurally_resolved_type(fcx: &FnCtxt, sp: Span, tp: ty::t) -> ty::t {
- match infer::resolve_type(fcx.infcx(), Some(sp), tp, force_tvar) {
- Ok(t_s) if !ty::type_is_ty_var(t_s) => t_s,
- _ => {
- fcx.type_error_message(sp, |_actual| {
- "the type of this value must be known in this \
- context".to_string()
- }, tp, None);
- demand::suptype(fcx, sp, ty::mk_err(), tp);
- tp
- }
- }
+pub fn structurally_resolved_type(fcx: &FnCtxt, sp: Span, mut ty: ty::t) -> ty::t {
+ // If `ty` is a type variable, see whether we already know what it is.
+ ty = fcx.infcx().shallow_resolve(ty);
+
+ // If not, try resolve pending fcx obligations. Those can shed light.
+ //
+ // FIXME(#18391) -- This current strategy can lead to bad performance in
+ // extreme cases. We probably ought to smarter in general about
+ // only resolving when we need help and only resolving obligations
+ // will actually help.
+ if ty::type_is_ty_var(ty) {
+ vtable::select_fcx_obligations_where_possible(fcx);
+ ty = fcx.infcx().shallow_resolve(ty);
+ }
+
+ // If not, error.
+ if ty::type_is_ty_var(ty) {
+ fcx.type_error_message(sp, |_actual| {
+ "the type of this value must be known in this \
+ context".to_string()
+ }, ty, None);
+ demand::suptype(fcx, sp, ty::mk_err(), ty);
+ ty = ty::mk_err();
+ }
+
+ ty
}
// Returns the one-level-deep structure of the given type.
assert!(split.len() >= 2, "Atomic intrinsic not correct format");
//We only care about the operation here
- match split[1] {
+ let (n_tps, inputs, output) = match split[1] {
"cxchg" => (1, vec!(ty::mk_mut_ptr(tcx, param(ccx, 0)),
param(ccx, 0),
param(ccx, 0)),
"unrecognized atomic operation function: `{}`", op);
return;
}
- }
-
+ };
+ (n_tps, inputs, ty::FnConverging(output))
+ } else if name.get() == "abort" || name.get() == "unreachable" {
+ (0, Vec::new(), ty::FnDiverging)
} else {
- match name.get() {
- "abort" => (0, Vec::new(), ty::mk_bot()),
- "unreachable" => (0, Vec::new(), ty::mk_bot()),
+ let (n_tps, inputs, output) = match name.get() {
"breakpoint" => (0, Vec::new(), ty::mk_nil()),
"size_of" |
"pref_align_of" | "min_align_of" => (1u, Vec::new(), ty::mk_uint()),
"unrecognized intrinsic function: `{}`", *other);
return;
}
- }
+ };
+ (n_tps, inputs, ty::FnConverging(output))
};
let fty = ty::mk_bare_fn(tcx, ty::BareFnTy {
fn_style: ast::UnsafeFn,
use middle::typeck::astconv::AstConv;
use middle::typeck::check::FnCtxt;
use middle::typeck::check::regionmanip;
-use middle::typeck::check::vtable2;
+use middle::typeck::check::vtable;
use middle::typeck::infer::resolve_and_force_all_but_regions;
use middle::typeck::infer::resolve_type;
use middle::typeck::infer;
// Region checking a fn can introduce new trait obligations,
// particularly around closure bounds.
- vtable2::select_all_fcx_obligations_or_error(fcx);
+ vtable::select_all_fcx_obligations_or_error(fcx);
fcx.infcx().resolve_regions_and_report_errors();
}
/// Try to resolve the type for the given node.
pub fn resolve_expr_type_adjusted(&mut self, expr: &ast::Expr) -> ty::t {
let ty_unadjusted = self.resolve_node_type(expr.id);
- if ty::type_is_error(ty_unadjusted) || ty::type_is_bot(ty_unadjusted) {
+ if ty::type_is_error(ty_unadjusted) {
ty_unadjusted
} else {
let tcx = self.fcx.tcx();
Some(method) => {
constrain_call(rcx, expr, Some(&**base),
None::<ast::Expr>.iter(), true);
- ty::ty_fn_ret(method.ty)
+ ty::ty_fn_ret(method.ty).unwrap()
}
None => rcx.resolve_node_type(base.id)
};
}
});
}
- ty::ty_unboxed_closure(_, region) => {
+ ty::ty_unboxed_closure(_, region, _) => {
if tcx.capture_modes.borrow().get_copy(&expr.id) == ast::CaptureByRef {
ty::with_freevars(tcx, expr.id, |freevars| {
if !freevars.is_empty() {
ensure_free_variable_types_outlive_closure_bound(rcx, bounds, expr, freevars);
})
}
- ty::ty_unboxed_closure(_, region) => {
+ ty::ty_unboxed_closure(_, region, _) => {
ty::with_freevars(tcx, expr.id, |freevars| {
let bounds = ty::region_existential_bound(region);
ensure_free_variable_types_outlive_closure_bound(rcx, bounds, expr, freevars);
// Specialized version of constrain_call.
type_must_outlive(rcx, infer::CallRcvr(deref_expr.span),
self_ty, r_deref_expr);
- type_must_outlive(rcx, infer::CallReturn(deref_expr.span),
- fn_sig.output, r_deref_expr);
- fn_sig.output
+ match fn_sig.output {
+ ty::FnConverging(return_type) => {
+ type_must_outlive(rcx, infer::CallReturn(deref_expr.span),
+ return_type, r_deref_expr);
+ return_type
+ }
+ ty::FnDiverging => unreachable!()
+ }
}
None => derefd_ty
};
*/
let rptr_ty = rcx.resolve_node_type(id);
- if !ty::type_is_bot(rptr_ty) && !ty::type_is_error(rptr_ty) {
+ if !ty::type_is_error(rptr_ty) {
let tcx = rcx.fcx.ccx.tcx;
debug!("rptr_ty={}", ty_to_string(tcx, rptr_ty));
let r = ty::ty_region(tcx, span, rptr_ty);
//
// If mutability was inferred from an upvar, we may be
// forced to revisit this decision later if processing
- // another borrow or nested closure ends up coverting the
+ // another borrow or nested closure ends up converting the
// upvar borrow kind to mutable/unique. Record the
// information needed to perform the recursive link in the
// maybe link map.
match ty::get(ty).sty {
ty::ty_nil |
- ty::ty_bot |
ty::ty_bool |
ty::ty_char |
ty::ty_int(..) |
self.accumulate_from_closure_ty(ty, c);
}
- ty::ty_unboxed_closure(_, region) => {
+ ty::ty_unboxed_closure(_, region, _) => {
// An "unboxed closure type" is basically
// modeled here as equivalent to a struct like
//
//
// where the `'b` is the lifetime bound of the
// contents (i.e., all contents must outlive 'b).
+ //
+ // Even though unboxed closures are glorified structs
+ // of upvars, we do not need to consider them as they
+ // can't generate any new constraints. The
+ // substitutions on the closure are equal to the free
+ // substitutions of the enclosing parameter
+ // environment. An upvar captured by value has the
+ // same type as the original local variable which is
+ // already checked for consistency. If the upvar is
+ // captured by reference it must also outlive the
+ // region bound on the closure, but this is explicitly
+ // handled by logic in regionck.
self.push_region_constraint_from_top(region);
}
--- /dev/null
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use middle::subst::{SelfSpace, FnSpace};
+use middle::traits;
+use middle::traits::{SelectionError, OutputTypeParameterMismatch, Overflow, Unimplemented};
+use middle::traits::{Obligation, obligation_for_builtin_bound};
+use middle::traits::{FulfillmentError, CodeSelectionError, CodeAmbiguity};
+use middle::traits::{ObligationCause};
+use middle::ty;
+use middle::typeck::check::{FnCtxt,
+ structurally_resolved_type};
+use middle::typeck::infer;
+use std::rc::Rc;
+use syntax::ast;
+use syntax::codemap::Span;
+use util::ppaux::{UserString, Repr, ty_to_string};
+
+pub fn check_object_cast(fcx: &FnCtxt,
+ cast_expr: &ast::Expr,
+ source_expr: &ast::Expr,
+ target_object_ty: ty::t)
+{
+ debug!("check_object_cast(cast_expr={}, target_object_ty={})",
+ cast_expr.repr(fcx.tcx()),
+ target_object_ty.repr(fcx.tcx()));
+
+ // Look up vtables for the type we're casting to,
+ // passing in the source and target type. The source
+ // must be a pointer type suitable to the object sigil,
+ // e.g.: `&x as &Trait` or `box x as Box<Trait>`
+ let source_ty = fcx.expr_ty(source_expr);
+ let source_ty = structurally_resolved_type(fcx, source_expr.span, source_ty);
+ debug!("source_ty={}", source_ty.repr(fcx.tcx()));
+ match (&ty::get(source_ty).sty, &ty::get(target_object_ty).sty) {
+ (&ty::ty_uniq(referent_ty), &ty::ty_uniq(object_trait_ty)) => {
+ let object_trait = object_trait(&object_trait_ty);
+
+ // Ensure that if ~T is cast to ~Trait, then T : Trait
+ push_cast_obligation(fcx, cast_expr, object_trait, referent_ty);
+ check_object_safety(fcx.tcx(), object_trait, source_expr.span);
+ }
+
+ (&ty::ty_rptr(referent_region, ty::mt { ty: referent_ty,
+ mutbl: referent_mutbl }),
+ &ty::ty_rptr(target_region, ty::mt { ty: object_trait_ty,
+ mutbl: target_mutbl })) =>
+ {
+ let object_trait = object_trait(&object_trait_ty);
+ if !mutability_allowed(referent_mutbl, target_mutbl) {
+ fcx.tcx().sess.span_err(source_expr.span,
+ "types differ in mutability");
+ } else {
+ // Ensure that if &'a T is cast to &'b Trait, then T : Trait
+ push_cast_obligation(fcx, cast_expr,
+ object_trait,
+ referent_ty);
+
+ // Ensure that if &'a T is cast to &'b Trait, then 'b <= 'a
+ infer::mk_subr(fcx.infcx(),
+ infer::RelateObjectBound(source_expr.span),
+ target_region,
+ referent_region);
+
+ check_object_safety(fcx.tcx(), object_trait, source_expr.span);
+ }
+ }
+
+ (_, &ty::ty_uniq(..)) => {
+ fcx.ccx.tcx.sess.span_err(
+ source_expr.span,
+ format!("can only cast an boxed pointer \
+ to a boxed object, not a {}",
+ ty::ty_sort_string(fcx.tcx(), source_ty)).as_slice());
+ }
+
+ (_, &ty::ty_rptr(..)) => {
+ fcx.ccx.tcx.sess.span_err(
+ source_expr.span,
+ format!("can only cast a &-pointer \
+ to an &-object, not a {}",
+ ty::ty_sort_string(fcx.tcx(), source_ty)).as_slice());
+ }
+
+ _ => {
+ fcx.tcx().sess.span_bug(
+ source_expr.span,
+ "expected object type");
+ }
+ }
+
+ // Because we currently give unsound lifetimes to the "t_box", I
+ // could have written &'static ty::TyTrait here, but it seems
+ // gratuitously unsafe.
+ fn object_trait<'a>(t: &'a ty::t) -> &'a ty::TyTrait {
+ match ty::get(*t).sty {
+ ty::ty_trait(ref ty_trait) => &**ty_trait,
+ _ => panic!("expected ty_trait")
+ }
+ }
+
+ fn mutability_allowed(a_mutbl: ast::Mutability,
+ b_mutbl: ast::Mutability)
+ -> bool {
+ a_mutbl == b_mutbl ||
+ (a_mutbl == ast::MutMutable && b_mutbl == ast::MutImmutable)
+ }
+
+ fn push_cast_obligation(fcx: &FnCtxt,
+ cast_expr: &ast::Expr,
+ object_trait: &ty::TyTrait,
+ referent_ty: ty::t) {
+ let object_trait_ref =
+ register_object_cast_obligations(fcx,
+ cast_expr.span,
+ object_trait,
+ referent_ty);
+
+ // Finally record the object_trait_ref for use during trans
+ // (it would prob be better not to do this, but it's just kind
+ // of a pain to have to reconstruct it).
+ fcx.write_object_cast(cast_expr.id, object_trait_ref);
+ }
+}
+
+// Check that a trait is 'object-safe'. This should be checked whenever a trait object
+// is created (by casting or coercion, etc.). A trait is object-safe if all its
+// methods are object-safe. A trait method is object-safe if it does not take
+// self by value, has no type parameters and does not use the `Self` type, except
+// in self position.
+pub fn check_object_safety(tcx: &ty::ctxt, object_trait: &ty::TyTrait, span: Span) {
+ // Skip the fn_once lang item trait since only the compiler should call
+ // `call_once` which is the method which takes self by value. What could go
+ // wrong?
+ match tcx.lang_items.fn_once_trait() {
+ Some(def_id) if def_id == object_trait.def_id => return,
+ _ => {}
+ }
+
+ let trait_items = ty::trait_items(tcx, object_trait.def_id);
+
+ let mut errors = Vec::new();
+ for item in trait_items.iter() {
+ match *item {
+ ty::MethodTraitItem(ref m) => {
+ errors.push(check_object_safety_of_method(tcx, &**m))
+ }
+ ty::TypeTraitItem(_) => {}
+ }
+ }
+
+ let mut errors = errors.iter().flat_map(|x| x.iter()).peekable();
+ if errors.peek().is_some() {
+ let trait_name = ty::item_path_str(tcx, object_trait.def_id);
+ span_err!(tcx.sess, span, E0038,
+ "cannot convert to a trait object because trait `{}` is not object-safe",
+ trait_name);
+
+ for msg in errors {
+ tcx.sess.note(msg.as_slice());
+ }
+ }
+
+ // Returns a vec of error messages. If hte vec is empty - no errors!
+ fn check_object_safety_of_method(tcx: &ty::ctxt, method: &ty::Method) -> Vec<String> {
+ /*!
+ * There are some limitations to calling functions through an
+ * object, because (a) the self type is not known
+ * (that's the whole point of a trait instance, after all, to
+ * obscure the self type) and (b) the call must go through a
+ * vtable and hence cannot be monomorphized.
+ */
+ let mut msgs = Vec::new();
+
+ let method_name = method.name.repr(tcx);
+
+ match method.explicit_self {
+ ty::ByValueExplicitSelfCategory => { // reason (a) above
+ msgs.push(format!("cannot call a method (`{}`) with a by-value \
+ receiver through a trait object", method_name))
+ }
+
+ ty::StaticExplicitSelfCategory |
+ ty::ByReferenceExplicitSelfCategory(..) |
+ ty::ByBoxExplicitSelfCategory => {}
+ }
+
+ // reason (a) above
+ let check_for_self_ty = |ty| {
+ if ty::type_has_self(ty) {
+ Some(format!(
+ "cannot call a method (`{}`) whose type contains \
+ a self-type (`{}`) through a trait object",
+ method_name, ty_to_string(tcx, ty)))
+ } else {
+ None
+ }
+ };
+ let ref sig = method.fty.sig;
+ for &input_ty in sig.inputs[1..].iter() {
+ match check_for_self_ty(input_ty) {
+ Some(msg) => msgs.push(msg),
+ _ => {}
+ }
+ }
+ if let ty::FnConverging(result_type) = sig.output {
+ match check_for_self_ty(result_type) {
+ Some(msg) => msgs.push(msg),
+ _ => {}
+ }
+ }
+
+ if method.generics.has_type_params(FnSpace) {
+ // reason (b) above
+ msgs.push(format!("cannot call a generic method (`{}`) through a trait object",
+ method_name));
+ }
+
+ msgs
+ }
+}
+
+pub fn register_object_cast_obligations(fcx: &FnCtxt,
+ span: Span,
+ object_trait: &ty::TyTrait,
+ referent_ty: ty::t)
+ -> Rc<ty::TraitRef>
+{
+ // This is just for better error reporting. Kinda goofy. The object type stuff
+ // needs some refactoring so there is a more convenient type to pass around.
+ let object_trait_ty =
+ ty::mk_trait(fcx.tcx(),
+ object_trait.def_id,
+ object_trait.substs.clone(),
+ object_trait.bounds);
+
+ debug!("register_object_cast_obligations: referent_ty={} object_trait_ty={}",
+ referent_ty.repr(fcx.tcx()),
+ object_trait_ty.repr(fcx.tcx()));
+
+ // Take the type parameters from the object type, but set
+ // the Self type (which is unknown, for the object type)
+ // to be the type we are casting from.
+ let mut object_substs = object_trait.substs.clone();
+ assert!(object_substs.self_ty().is_none());
+ object_substs.types.push(SelfSpace, referent_ty);
+
+ // Create the obligation for casting from T to Trait.
+ let object_trait_ref =
+ Rc::new(ty::TraitRef { def_id: object_trait.def_id,
+ substs: object_substs });
+ let object_obligation =
+ Obligation::new(
+ ObligationCause::new(span,
+ traits::ObjectCastObligation(object_trait_ty)),
+ object_trait_ref.clone());
+ fcx.register_obligation(object_obligation);
+
+ // Create additional obligations for all the various builtin
+ // bounds attached to the object cast. (In other words, if the
+ // object type is Foo+Send, this would create an obligation
+ // for the Send check.)
+ for builtin_bound in object_trait.bounds.builtin_bounds.iter() {
+ let obligation = obligation_for_builtin_bound(
+ fcx.tcx(),
+ ObligationCause::new(span,
+ traits::ObjectCastObligation(object_trait_ty)),
+ referent_ty,
+ builtin_bound);
+ match obligation {
+ Ok(obligation) => fcx.register_obligation(obligation),
+ _ => {}
+ }
+ }
+
+ object_trait_ref
+}
+
+pub fn select_all_fcx_obligations_or_error(fcx: &FnCtxt) {
+ debug!("select_all_fcx_obligations_or_error");
+
+ let mut fulfillment_cx = fcx.inh.fulfillment_cx.borrow_mut();
+ let r = fulfillment_cx.select_all_or_error(fcx.infcx(),
+ &fcx.inh.param_env,
+ fcx);
+ match r {
+ Ok(()) => { }
+ Err(errors) => { report_fulfillment_errors(fcx, &errors); }
+ }
+}
+
+fn resolve_trait_ref(fcx: &FnCtxt, obligation: &Obligation)
+ -> (ty::TraitRef, ty::t)
+{
+ let trait_ref =
+ fcx.infcx().resolve_type_vars_in_trait_ref_if_possible(
+ &*obligation.trait_ref);
+ let self_ty =
+ trait_ref.substs.self_ty().unwrap();
+ (trait_ref, self_ty)
+}
+
+pub fn report_fulfillment_errors(fcx: &FnCtxt,
+ errors: &Vec<FulfillmentError>) {
+ for error in errors.iter() {
+ report_fulfillment_error(fcx, error);
+ }
+}
+
+pub fn report_fulfillment_error(fcx: &FnCtxt,
+ error: &FulfillmentError) {
+ match error.code {
+ CodeSelectionError(ref e) => {
+ report_selection_error(fcx, &error.obligation, e);
+ }
+ CodeAmbiguity => {
+ maybe_report_ambiguity(fcx, &error.obligation);
+ }
+ }
+}
+
+pub fn report_selection_error(fcx: &FnCtxt,
+ obligation: &Obligation,
+ error: &SelectionError)
+{
+ match *error {
+ Overflow => {
+ let (trait_ref, self_ty) = resolve_trait_ref(fcx, obligation);
+ fcx.tcx().sess.span_err(
+ obligation.cause.span,
+ format!(
+ "overflow evaluating the trait `{}` for the type `{}`",
+ trait_ref.user_string(fcx.tcx()),
+ self_ty.user_string(fcx.tcx())).as_slice());
+ note_obligation_cause(fcx, obligation);
+ }
+ Unimplemented => {
+ let (trait_ref, self_ty) = resolve_trait_ref(fcx, obligation);
+ if !ty::type_is_error(self_ty) {
+ fcx.tcx().sess.span_err(
+ obligation.cause.span,
+ format!(
+ "the trait `{}` is not implemented for the type `{}`",
+ trait_ref.user_string(fcx.tcx()),
+ self_ty.user_string(fcx.tcx())).as_slice());
+ note_obligation_cause(fcx, obligation);
+ }
+ }
+ OutputTypeParameterMismatch(ref expected_trait_ref, ref e) => {
+ let expected_trait_ref =
+ fcx.infcx().resolve_type_vars_in_trait_ref_if_possible(
+ &**expected_trait_ref);
+ let (trait_ref, self_ty) = resolve_trait_ref(fcx, obligation);
+ if !ty::type_is_error(self_ty) {
+ fcx.tcx().sess.span_err(
+ obligation.cause.span,
+ format!(
+ "type mismatch: the type `{}` implements the trait `{}`, \
+ but the trait `{}` is required ({})",
+ self_ty.user_string(fcx.tcx()),
+ expected_trait_ref.user_string(fcx.tcx()),
+ trait_ref.user_string(fcx.tcx()),
+ ty::type_err_to_str(fcx.tcx(), e)).as_slice());
+ note_obligation_cause(fcx, obligation);
+ }
+ }
+ }
+}
+
+pub fn maybe_report_ambiguity(fcx: &FnCtxt, obligation: &Obligation) {
+ // Unable to successfully determine, probably means
+ // insufficient type information, but could mean
+ // ambiguous impls. The latter *ought* to be a
+ // coherence violation, so we don't report it here.
+ let (trait_ref, self_ty) = resolve_trait_ref(fcx, obligation);
+ debug!("maybe_report_ambiguity(trait_ref={}, self_ty={}, obligation={})",
+ trait_ref.repr(fcx.tcx()),
+ self_ty.repr(fcx.tcx()),
+ obligation.repr(fcx.tcx()));
+ let all_types = &trait_ref.substs.types;
+ if all_types.iter().any(|&t| ty::type_is_error(t)) {
+ } else if all_types.iter().any(|&t| ty::type_needs_infer(t)) {
+ // This is kind of a hack: it frequently happens that some earlier
+ // error prevents types from being fully inferred, and then we get
+ // a bunch of uninteresting errors saying something like "<generic
+ // #0> doesn't implement Sized". It may even be true that we
+ // could just skip over all checks where the self-ty is an
+ // inference variable, but I was afraid that there might be an
+ // inference variable created, registered as an obligation, and
+ // then never forced by writeback, and hence by skipping here we'd
+ // be ignoring the fact that we don't KNOW the type works
+ // out. Though even that would probably be harmless, given that
+ // we're only talking about builtin traits, which are known to be
+ // inhabited. But in any case I just threw in this check for
+ // has_errors() to be sure that compilation isn't happening
+ // anyway. In that case, why inundate the user.
+ if !fcx.tcx().sess.has_errors() {
+ fcx.tcx().sess.span_err(
+ obligation.cause.span,
+ format!(
+ "unable to infer enough type information to \
+ locate the impl of the trait `{}` for \
+ the type `{}`; type annotations required",
+ trait_ref.user_string(fcx.tcx()),
+ self_ty.user_string(fcx.tcx())).as_slice());
+ note_obligation_cause(fcx, obligation);
+ }
+ } else if !fcx.tcx().sess.has_errors() {
+ // Ambiguity. Coherence should have reported an error.
+ fcx.tcx().sess.span_bug(
+ obligation.cause.span,
+ format!(
+ "coherence failed to report ambiguity: \
+ cannot locate the impl of the trait `{}` for \
+ the type `{}`",
+ trait_ref.user_string(fcx.tcx()),
+ self_ty.user_string(fcx.tcx())).as_slice());
+ }
+}
+
+pub fn select_fcx_obligations_where_possible(fcx: &FnCtxt) {
+ /*! Select as many obligations as we can at present. */
+
+ match
+ fcx.inh.fulfillment_cx
+ .borrow_mut()
+ .select_where_possible(fcx.infcx(), &fcx.inh.param_env, fcx)
+ {
+ Ok(()) => { }
+ Err(errors) => { report_fulfillment_errors(fcx, &errors); }
+ }
+}
+
+pub fn select_new_fcx_obligations(fcx: &FnCtxt) {
+ /*!
+ * Try to select any fcx obligation that we haven't tried yet,
+ * in an effort to improve inference. You could just call
+ * `select_fcx_obligations_where_possible` except that it leads
+ * to repeated work.
+ */
+
+ match
+ fcx.inh.fulfillment_cx
+ .borrow_mut()
+ .select_new_obligations(fcx.infcx(), &fcx.inh.param_env, fcx)
+ {
+ Ok(()) => { }
+ Err(errors) => { report_fulfillment_errors(fcx, &errors); }
+ }
+}
+
+fn note_obligation_cause(fcx: &FnCtxt,
+ obligation: &Obligation) {
+ let tcx = fcx.tcx();
+ let trait_name = ty::item_path_str(tcx, obligation.trait_ref.def_id);
+ match obligation.cause.code {
+ traits::MiscObligation => { }
+ traits::ItemObligation(item_def_id) => {
+ let item_name = ty::item_path_str(tcx, item_def_id);
+ tcx.sess.span_note(
+ obligation.cause.span,
+ format!(
+ "the trait `{}` must be implemented because it is required by `{}`",
+ trait_name,
+ item_name).as_slice());
+ }
+ traits::ObjectCastObligation(object_ty) => {
+ tcx.sess.span_note(
+ obligation.cause.span,
+ format!(
+ "the trait `{}` must be implemented for the cast \
+ to the object type `{}`",
+ trait_name,
+ fcx.infcx().ty_to_string(object_ty)).as_slice());
+ }
+ traits::RepeatVec => {
+ tcx.sess.span_note(
+ obligation.cause.span,
+ "the `Copy` trait is required because the \
+ repeated element will be copied");
+ }
+ traits::VariableType(_) => {
+ tcx.sess.span_note(
+ obligation.cause.span,
+ "all local variables must have a statically known size");
+ }
+ traits::ReturnType => {
+ tcx.sess.span_note(
+ obligation.cause.span,
+ "the return type of a function must have a \
+ statically known size");
+ }
+ traits::AssignmentLhsSized => {
+ tcx.sess.span_note(
+ obligation.cause.span,
+ "the left-hand-side of an assignment must have a statically known size");
+ }
+ traits::StructInitializerSized => {
+ tcx.sess.span_note(
+ obligation.cause.span,
+ "structs must have a statically known size to be initialized");
+ }
+ traits::DropTrait => {
+ span_note!(tcx.sess, obligation.cause.span,
+ "cannot implement a destructor on a \
+ structure or enumeration that does not satisfy Send");
+ span_note!(tcx.sess, obligation.cause.span,
+ "use \"#[unsafe_destructor]\" on the implementation \
+ to force the compiler to allow this");
+ }
+ traits::ClosureCapture(var_id, closure_span) => {
+ let name = ty::local_var_name_str(tcx, var_id);
+ span_note!(tcx.sess, closure_span,
+ "the closure that captures `{}` requires that all captured variables \"
+ implement the trait `{}`",
+ name,
+ trait_name);
+ }
+ traits::FieldSized => {
+ span_note!(tcx.sess, obligation.cause.span,
+ "only the last field of a struct or enum variant \
+ may have a dynamically sized type")
+ }
+ }
+}
+++ /dev/null
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-use middle::subst::{SelfSpace};
-use middle::traits;
-use middle::traits::{SelectionError, OutputTypeParameterMismatch, Overflow, Unimplemented};
-use middle::traits::{Obligation, obligation_for_builtin_bound};
-use middle::traits::{FulfillmentError, CodeSelectionError, CodeAmbiguity};
-use middle::traits::{ObligationCause};
-use middle::ty;
-use middle::typeck::check::{FnCtxt,
- structurally_resolved_type};
-use middle::typeck::infer;
-use std::rc::Rc;
-use syntax::ast;
-use syntax::codemap::Span;
-use util::ppaux::UserString;
-use util::ppaux::Repr;
-
-pub fn check_object_cast(fcx: &FnCtxt,
- cast_expr: &ast::Expr,
- source_expr: &ast::Expr,
- target_object_ty: ty::t)
-{
- debug!("check_object_cast(cast_expr={}, target_object_ty={})",
- cast_expr.repr(fcx.tcx()),
- target_object_ty.repr(fcx.tcx()));
-
- // Look up vtables for the type we're casting to,
- // passing in the source and target type. The source
- // must be a pointer type suitable to the object sigil,
- // e.g.: `&x as &Trait` or `box x as Box<Trait>`
- let source_ty = fcx.expr_ty(source_expr);
- let source_ty = structurally_resolved_type(fcx, source_expr.span, source_ty);
- debug!("source_ty={}", source_ty.repr(fcx.tcx()));
- match (&ty::get(source_ty).sty, &ty::get(target_object_ty).sty) {
- (&ty::ty_uniq(referent_ty), &ty::ty_uniq(object_trait_ty)) => {
- let object_trait = object_trait(&object_trait_ty);
-
- // Ensure that if ~T is cast to ~Trait, then T : Trait
- push_cast_obligation(fcx, cast_expr, object_trait, referent_ty);
- }
-
- (&ty::ty_rptr(referent_region, ty::mt { ty: referent_ty,
- mutbl: referent_mutbl }),
- &ty::ty_rptr(target_region, ty::mt { ty: object_trait_ty,
- mutbl: target_mutbl })) =>
- {
- let object_trait = object_trait(&object_trait_ty);
- if !mutability_allowed(referent_mutbl, target_mutbl) {
- fcx.tcx().sess.span_err(source_expr.span,
- "types differ in mutability");
- } else {
- // Ensure that if &'a T is cast to &'b Trait, then T : Trait
- push_cast_obligation(fcx, cast_expr,
- object_trait,
- referent_ty);
-
- // Ensure that if &'a T is cast to &'b Trait, then 'b <= 'a
- infer::mk_subr(fcx.infcx(),
- infer::RelateObjectBound(source_expr.span),
- target_region,
- referent_region);
- }
- }
-
- (_, &ty::ty_uniq(..)) => {
- fcx.ccx.tcx.sess.span_err(
- source_expr.span,
- format!("can only cast an boxed pointer \
- to a boxed object, not a {}",
- ty::ty_sort_string(fcx.tcx(), source_ty)).as_slice());
- }
-
- (_, &ty::ty_rptr(..)) => {
- fcx.ccx.tcx.sess.span_err(
- source_expr.span,
- format!("can only cast a &-pointer \
- to an &-object, not a {}",
- ty::ty_sort_string(fcx.tcx(), source_ty)).as_slice());
- }
-
- _ => {
- fcx.tcx().sess.span_bug(
- source_expr.span,
- "expected object type");
- }
- }
-
- // Because we currently give unsound lifetimes to the "t_box", I
- // could have written &'static ty::TyTrait here, but it seems
- // gratuitously unsafe.
- fn object_trait<'a>(t: &'a ty::t) -> &'a ty::TyTrait {
- match ty::get(*t).sty {
- ty::ty_trait(ref ty_trait) => &**ty_trait,
- _ => fail!("expected ty_trait")
- }
- }
-
- fn mutability_allowed(a_mutbl: ast::Mutability,
- b_mutbl: ast::Mutability)
- -> bool {
- a_mutbl == b_mutbl ||
- (a_mutbl == ast::MutMutable && b_mutbl == ast::MutImmutable)
- }
-
- fn push_cast_obligation(fcx: &FnCtxt,
- cast_expr: &ast::Expr,
- object_trait: &ty::TyTrait,
- referent_ty: ty::t) {
- let object_trait_ref =
- register_object_cast_obligations(fcx,
- cast_expr.span,
- object_trait,
- referent_ty);
-
- // Finally record the object_trait_ref for use during trans
- // (it would prob be better not to do this, but it's just kind
- // of a pain to have to reconstruct it).
- fcx.write_object_cast(cast_expr.id, object_trait_ref);
- }
-}
-
-pub fn register_object_cast_obligations(fcx: &FnCtxt,
- span: Span,
- object_trait: &ty::TyTrait,
- referent_ty: ty::t)
- -> Rc<ty::TraitRef>
-{
- // This is just for better error reporting. Kinda goofy. The object type stuff
- // needs some refactoring so there is a more convenient type to pass around.
- let object_trait_ty =
- ty::mk_trait(fcx.tcx(),
- object_trait.def_id,
- object_trait.substs.clone(),
- object_trait.bounds);
-
- debug!("register_object_cast_obligations: referent_ty={} object_trait_ty={}",
- referent_ty.repr(fcx.tcx()),
- object_trait_ty.repr(fcx.tcx()));
-
- // Take the type parameters from the object type, but set
- // the Self type (which is unknown, for the object type)
- // to be the type we are casting from.
- let mut object_substs = object_trait.substs.clone();
- assert!(object_substs.self_ty().is_none());
- object_substs.types.push(SelfSpace, referent_ty);
-
- // Create the obligation for casting from T to Trait.
- let object_trait_ref =
- Rc::new(ty::TraitRef { def_id: object_trait.def_id,
- substs: object_substs });
- let object_obligation =
- Obligation::new(
- ObligationCause::new(span,
- traits::ObjectCastObligation(object_trait_ty)),
- object_trait_ref.clone());
- fcx.register_obligation(object_obligation);
-
- // Create additional obligations for all the various builtin
- // bounds attached to the object cast. (In other words, if the
- // object type is Foo+Send, this would create an obligation
- // for the Send check.)
- for builtin_bound in object_trait.bounds.builtin_bounds.iter() {
- let obligation = obligation_for_builtin_bound(
- fcx.tcx(),
- ObligationCause::new(span,
- traits::ObjectCastObligation(object_trait_ty)),
- referent_ty,
- builtin_bound);
- match obligation {
- Ok(obligation) => fcx.register_obligation(obligation),
- _ => {}
- }
- }
-
- object_trait_ref
-}
-
-pub fn select_all_fcx_obligations_or_error(fcx: &FnCtxt) {
- debug!("select_all_fcx_obligations_or_error");
-
- let mut fulfillment_cx = fcx.inh.fulfillment_cx.borrow_mut();
- let r = fulfillment_cx.select_all_or_error(fcx.infcx(),
- &fcx.inh.param_env,
- fcx);
- match r {
- Ok(()) => { }
- Err(errors) => { report_fulfillment_errors(fcx, &errors); }
- }
-}
-
-fn resolve_trait_ref(fcx: &FnCtxt, obligation: &Obligation)
- -> (ty::TraitRef, ty::t)
-{
- let trait_ref =
- fcx.infcx().resolve_type_vars_in_trait_ref_if_possible(
- &*obligation.trait_ref);
- let self_ty =
- trait_ref.substs.self_ty().unwrap();
- (trait_ref, self_ty)
-}
-
-pub fn report_fulfillment_errors(fcx: &FnCtxt,
- errors: &Vec<FulfillmentError>) {
- for error in errors.iter() {
- report_fulfillment_error(fcx, error);
- }
-}
-
-pub fn report_fulfillment_error(fcx: &FnCtxt,
- error: &FulfillmentError) {
- match error.code {
- CodeSelectionError(ref e) => {
- report_selection_error(fcx, &error.obligation, e);
- }
- CodeAmbiguity => {
- maybe_report_ambiguity(fcx, &error.obligation);
- }
- }
-}
-
-pub fn report_selection_error(fcx: &FnCtxt,
- obligation: &Obligation,
- error: &SelectionError)
-{
- match *error {
- Overflow => {
- let (trait_ref, self_ty) = resolve_trait_ref(fcx, obligation);
- fcx.tcx().sess.span_err(
- obligation.cause.span,
- format!(
- "overflow evaluating the trait `{}` for the type `{}`",
- trait_ref.user_string(fcx.tcx()),
- self_ty.user_string(fcx.tcx())).as_slice());
- note_obligation_cause(fcx, obligation);
- }
- Unimplemented => {
- let (trait_ref, self_ty) = resolve_trait_ref(fcx, obligation);
- if !ty::type_is_error(self_ty) {
- fcx.tcx().sess.span_err(
- obligation.cause.span,
- format!(
- "the trait `{}` is not implemented for the type `{}`",
- trait_ref.user_string(fcx.tcx()),
- self_ty.user_string(fcx.tcx())).as_slice());
- note_obligation_cause(fcx, obligation);
- }
- }
- OutputTypeParameterMismatch(ref expected_trait_ref, ref e) => {
- let expected_trait_ref =
- fcx.infcx().resolve_type_vars_in_trait_ref_if_possible(
- &**expected_trait_ref);
- let (trait_ref, self_ty) = resolve_trait_ref(fcx, obligation);
- if !ty::type_is_error(self_ty) {
- fcx.tcx().sess.span_err(
- obligation.cause.span,
- format!(
- "type mismatch: the type `{}` implements the trait `{}`, \
- but the trait `{}` is required ({})",
- self_ty.user_string(fcx.tcx()),
- expected_trait_ref.user_string(fcx.tcx()),
- trait_ref.user_string(fcx.tcx()),
- ty::type_err_to_str(fcx.tcx(), e)).as_slice());
- note_obligation_cause(fcx, obligation);
- }
- }
- }
-}
-
-pub fn maybe_report_ambiguity(fcx: &FnCtxt, obligation: &Obligation) {
- // Unable to successfully determine, probably means
- // insufficient type information, but could mean
- // ambiguous impls. The latter *ought* to be a
- // coherence violation, so we don't report it here.
- let (trait_ref, self_ty) = resolve_trait_ref(fcx, obligation);
- debug!("maybe_report_ambiguity(trait_ref={}, self_ty={}, obligation={})",
- trait_ref.repr(fcx.tcx()),
- self_ty.repr(fcx.tcx()),
- obligation.repr(fcx.tcx()));
- let all_types = &trait_ref.substs.types;
- if all_types.iter().any(|&t| ty::type_is_error(t)) {
- } else if all_types.iter().any(|&t| ty::type_needs_infer(t)) {
- // This is kind of a hack: it frequently happens that some earlier
- // error prevents types from being fully inferred, and then we get
- // a bunch of uninteresting errors saying something like "<generic
- // #0> doesn't implement Sized". It may even be true that we
- // could just skip over all checks where the self-ty is an
- // inference variable, but I was afraid that there might be an
- // inference variable created, registered as an obligation, and
- // then never forced by writeback, and hence by skipping here we'd
- // be ignoring the fact that we don't KNOW the type works
- // out. Though even that would probably be harmless, given that
- // we're only talking about builtin traits, which are known to be
- // inhabited. But in any case I just threw in this check for
- // has_errors() to be sure that compilation isn't happening
- // anyway. In that case, why inundate the user.
- if !fcx.tcx().sess.has_errors() {
- fcx.tcx().sess.span_err(
- obligation.cause.span,
- format!(
- "unable to infer enough type information to \
- locate the impl of the trait `{}` for \
- the type `{}`; type annotations required",
- trait_ref.user_string(fcx.tcx()),
- self_ty.user_string(fcx.tcx())).as_slice());
- note_obligation_cause(fcx, obligation);
- }
- } else if !fcx.tcx().sess.has_errors() {
- // Ambiguity. Coherence should have reported an error.
- fcx.tcx().sess.span_bug(
- obligation.cause.span,
- format!(
- "coherence failed to report ambiguity: \
- cannot locate the impl of the trait `{}` for \
- the type `{}`",
- trait_ref.user_string(fcx.tcx()),
- self_ty.user_string(fcx.tcx())).as_slice());
- }
-}
-
-pub fn select_fcx_obligations_where_possible(fcx: &FnCtxt) {
- /*! Select as many obligations as we can at present. */
-
- match
- fcx.inh.fulfillment_cx
- .borrow_mut()
- .select_where_possible(fcx.infcx(), &fcx.inh.param_env, fcx)
- {
- Ok(()) => { }
- Err(errors) => { report_fulfillment_errors(fcx, &errors); }
- }
-}
-
-fn note_obligation_cause(fcx: &FnCtxt,
- obligation: &Obligation) {
- let tcx = fcx.tcx();
- let trait_name = ty::item_path_str(tcx, obligation.trait_ref.def_id);
- match obligation.cause.code {
- traits::MiscObligation => { }
- traits::ItemObligation(item_def_id) => {
- let item_name = ty::item_path_str(tcx, item_def_id);
- tcx.sess.span_note(
- obligation.cause.span,
- format!(
- "the trait `{}` must be implemented because it is required by `{}`",
- trait_name,
- item_name).as_slice());
- }
- traits::ObjectCastObligation(object_ty) => {
- tcx.sess.span_note(
- obligation.cause.span,
- format!(
- "the trait `{}` must be implemented for the cast \
- to the object type `{}`",
- trait_name,
- fcx.infcx().ty_to_string(object_ty)).as_slice());
- }
- traits::RepeatVec => {
- tcx.sess.span_note(
- obligation.cause.span,
- "the `Copy` trait is required because the \
- repeated element will be copied");
- }
- traits::VariableType(_) => {
- tcx.sess.span_note(
- obligation.cause.span,
- "all local variables must have a statically known size");
- }
- traits::ReturnType => {
- tcx.sess.span_note(
- obligation.cause.span,
- "the return type of a function must have a \
- statically known size");
- }
- traits::AssignmentLhsSized => {
- tcx.sess.span_note(
- obligation.cause.span,
- "the left-hand-side of an assignment must have a statically known size");
- }
- traits::StructInitializerSized => {
- tcx.sess.span_note(
- obligation.cause.span,
- "structs must have a statically known size to be initialized");
- }
- traits::DropTrait => {
- span_note!(tcx.sess, obligation.cause.span,
- "cannot implement a destructor on a \
- structure or enumeration that does not satisfy Send");
- span_note!(tcx.sess, obligation.cause.span,
- "use \"#[unsafe_destructor]\" on the implementation \
- to force the compiler to allow this");
- }
- traits::ClosureCapture(var_id, closure_span) => {
- let name = ty::local_var_name_str(tcx, var_id);
- span_note!(tcx.sess, closure_span,
- "the closure that captures `{}` requires that all captured variables \"
- implement the trait `{}`",
- name,
- trait_name);
- }
- traits::FieldSized => {
- span_note!(tcx.sess, obligation.cause.span,
- "only the last field of a struct or enum variant \
- may have a dynamically sized type")
- }
- }
-}
use middle::ty;
use middle::ty_fold::{TypeFolder, TypeFoldable};
use middle::typeck::astconv::AstConv;
-use middle::typeck::check::{FnCtxt, Inherited, blank_fn_ctxt, vtable2, regionck};
+use middle::typeck::check::{FnCtxt, Inherited, blank_fn_ctxt, vtable, regionck};
use middle::typeck::check::regionmanip::replace_late_bound_regions;
use middle::typeck::CrateCtxt;
use util::ppaux::Repr;
&polytype.generics,
item.id);
let inh = Inherited::new(ccx.tcx, param_env);
- let fcx = blank_fn_ctxt(ccx, &inh, polytype.ty, item.id);
+ let fcx = blank_fn_ctxt(ccx, &inh, ty::FnConverging(polytype.ty), item.id);
f(self, &fcx);
- vtable2::select_all_fcx_obligations_or_error(&fcx);
+ vtable::select_all_fcx_obligations_or_error(&fcx);
regionck::regionck_item(&fcx, item);
}
use middle::ty::get;
use middle::ty::{ImplContainer, ImplOrTraitItemId, MethodTraitItemId};
use middle::ty::{TypeTraitItemId, lookup_item_type};
-use middle::ty::{t, ty_bool, ty_char, ty_bot, ty_enum, ty_err};
+use middle::ty::{t, ty_bool, ty_char, ty_enum, ty_err};
use middle::ty::{ty_str, ty_vec, ty_float, ty_infer, ty_int, ty_nil, ty_open};
use middle::ty::{ty_param, Polytype, ty_ptr};
use middle::ty::{ty_rptr, ty_struct, ty_trait, ty_tup};
Some(resolved_type)
}
- ty_nil | ty_bot | ty_bool | ty_char | ty_int(..) | ty_uint(..) | ty_float(..) |
+ ty_nil | ty_bool | ty_char | ty_int(..) | ty_uint(..) | ty_float(..) |
ty_str(..) | ty_vec(..) | ty_bare_fn(..) | ty_closure(..) | ty_tup(..) |
ty_infer(..) | ty_param(..) | ty_err | ty_open(..) | ty_uniq(_) |
ty_ptr(_) | ty_rptr(_, _) => {
get(original_type).sty);
None
}
- ty_trait(..) => fail!("should have been caught")
+ ty_trait(..) => panic!("should have been caught")
}
}
match get(base_type).sty {
ty_enum(def_id, _) |
ty_struct(def_id, _) |
- ty_unboxed_closure(def_id, _) => {
+ ty_unboxed_closure(def_id, _, _) => {
Some(def_id)
}
ty_ptr(ty::mt {ty, ..}) |
Some(def_id)
}
_ => {
- fail!("get_base_type() returned a type that wasn't an \
+ panic!("get_base_type() returned a type that wasn't an \
enum, struct, or trait");
}
}
Some(def_id)
}
_ => {
- fail!("get_base_type() returned a type that wasn't an \
+ panic!("get_base_type() returned a type that wasn't an \
enum, struct, or trait");
}
}
match ty::get(self_type.ty).sty {
ty::ty_enum(type_def_id, _) |
ty::ty_struct(type_def_id, _) |
- ty::ty_unboxed_closure(type_def_id, _) => {
+ ty::ty_unboxed_closure(type_def_id, _, _) => {
tcx.destructor_for_type
.borrow_mut()
.insert(type_def_id, method_def_id.def_id());
return pty;
}
ast::ItemImpl(..) | ast::ItemMod(_) |
- ast::ItemForeignMod(_) | ast::ItemMac(_) => fail!(),
+ ast::ItemForeignMod(_) | ast::ItemMac(_) => panic!(),
}
}
.map(|a| ty_of_arg(ccx, &rb, a, None))
.collect();
- let output_ty = ast_ty_to_ty(ccx, &rb, &*decl.output);
+ let output = match decl.output.node {
+ ast::TyBot => ty::FnDiverging,
+ _ => ty::FnConverging(ast_ty_to_ty(ccx, &rb, &*decl.output))
+ };
let t_fn = ty::mk_bare_fn(
ccx.tcx,
fn_style: ast::UnsafeFn,
sig: ty::FnSig {binder_id: def_id.node,
inputs: input_tys,
- output: output_ty,
+ output: output,
variadic: decl.variadic}
});
let pty = Polytype {
} else {
None
};
+ self.substs_variances(variances.as_ref().map(|v| &**v), a_subst, b_subst)
+ }
+
+ fn substs_variances(&self,
+ variances: Option<&ty::ItemVariances>,
+ a_subst: &subst::Substs,
+ b_subst: &subst::Substs)
+ -> cres<subst::Substs>
+ {
let mut substs = subst::Substs::empty();
for &space in subst::ParamSpace::all().iter() {
let mut invariance = Vec::new();
let r_variances = match variances {
- Some(ref variances) => {
+ Some(variances) => {
variances.regions.get_slice(space)
}
None => {
};
let regions = try!(relate_region_params(self,
- item_def_id,
r_variances,
a_regions,
b_regions));
return Ok(substs);
fn relate_region_params<'tcx, C: Combine<'tcx>>(this: &C,
- item_def_id: ast::DefId,
variances: &[ty::Variance],
a_rs: &[ty::Region],
b_rs: &[ty::Region])
let num_region_params = variances.len();
debug!("relate_region_params(\
- item_def_id={}, \
a_rs={}, \
b_rs={},
variances={})",
- item_def_id.repr(tcx),
a_rs.repr(tcx),
b_rs.repr(tcx),
variances.repr(tcx));
let inputs = try!(argvecs(this,
a.inputs.as_slice(),
b.inputs.as_slice()));
- let output = try!(this.tys(a.output, b.output));
+
+ let output = try!(match (a.output, b.output) {
+ (ty::FnConverging(a_ty), ty::FnConverging(b_ty)) =>
+ Ok(ty::FnConverging(try!(this.tys(a_ty, b_ty)))),
+ (ty::FnDiverging, ty::FnDiverging) =>
+ Ok(ty::FnDiverging),
+ (a, b) =>
+ Err(ty::terr_convergence_mismatch(
+ expected_found(this, a != ty::FnDiverging, b != ty::FnDiverging)
+ )),
+ });
+
Ok(FnSig {binder_id: a.binder_id,
inputs: inputs,
output: output,
let b_sty = &ty::get(b).sty;
debug!("super_tys: a_sty={} b_sty={}", a_sty, b_sty);
return match (a_sty, b_sty) {
- // The "subtype" ought to be handling cases involving bot or var:
- (&ty::ty_bot, _) |
- (_, &ty::ty_bot) |
+ // The "subtype" ought to be handling cases involving var:
(&ty::ty_infer(TyVar(_)), _) |
(_, &ty::ty_infer(TyVar(_))) => {
tcx.sess.bug(
Ok(ty::mk_struct(tcx, a_id, substs))
}
- (&ty::ty_unboxed_closure(a_id, a_region),
- &ty::ty_unboxed_closure(b_id, b_region))
+ (&ty::ty_unboxed_closure(a_id, a_region, ref a_substs),
+ &ty::ty_unboxed_closure(b_id, b_region, ref b_substs))
if a_id == b_id => {
// All ty_unboxed_closure types with the same id represent
// the (anonymous) type of the same closure expression. So
// all of their regions should be equated.
let region = try!(this.equate().regions(a_region, b_region));
- Ok(ty::mk_unboxed_closure(tcx, a_id, region))
+ let substs = try!(this.substs_variances(None, a_substs, b_substs));
+ Ok(ty::mk_unboxed_closure(tcx, a_id, region, substs))
}
(&ty::ty_uniq(a_inner), &ty::ty_uniq(b_inner)) => {
let a = infcx.type_variables.borrow().replace_if_possible(a);
let b = infcx.type_variables.borrow().replace_if_possible(b);
match (&ty::get(a).sty, &ty::get(b).sty) {
- (&ty::ty_bot, &ty::ty_bot) => {
- Ok(a)
- }
-
- (&ty::ty_bot, _) |
- (_, &ty::ty_bot) => {
- Err(ty::terr_sorts(expected_found(self, a, b)))
- }
-
(&ty::ty_infer(TyVar(a_id)), &ty::ty_infer(TyVar(b_id))) => {
infcx.type_variables.borrow_mut().relate_vars(a_id, EqTo, b_id);
Ok(a)
// NB---I do not believe this algorithm computes
// (necessarily) the GLB. As written it can
- // spuriously fail. In particular, if there is a case
+ // spuriously fail. In particular, if there is a case
// like: |fn(&a)| and fn(fn(&b)), where a and b are
// free, it will return fn(&c) where c = GLB(a,b). If
// however this GLB is not defined, then the result is
use std::collections::HashMap;
pub trait LatticeDir {
- // Relates the bottom type to `t` and returns LUB(t, _|_) or
- // GLB(t, _|_) as appropriate.
- fn ty_bot(&self, t: ty::t) -> cres<ty::t>;
-
// Relates the type `v` to `a` and `b` such that `v` represents
// the LUB/GLB of `a` and `b` as appropriate.
fn relate_bound<'a>(&'a self, v: ty::t, a: ty::t, b: ty::t) -> cres<()>;
}
impl<'a, 'tcx> LatticeDir for Lub<'a, 'tcx> {
- fn ty_bot(&self, t: ty::t) -> cres<ty::t> {
- Ok(t)
- }
-
fn relate_bound<'a>(&'a self, v: ty::t, a: ty::t, b: ty::t) -> cres<()> {
let sub = self.sub();
try!(sub.tys(a, v));
}
impl<'a, 'tcx> LatticeDir for Glb<'a, 'tcx> {
- fn ty_bot(&self, _: ty::t) -> cres<ty::t> {
- Ok(ty::mk_bot())
- }
-
fn relate_bound<'a>(&'a self, v: ty::t, a: ty::t, b: ty::t) -> cres<()> {
let sub = self.sub();
try!(sub.tys(v, a));
let a = infcx.type_variables.borrow().replace_if_possible(a);
let b = infcx.type_variables.borrow().replace_if_possible(b);
match (&ty::get(a).sty, &ty::get(b).sty) {
- (&ty::ty_bot, _) => { this.ty_bot(b) }
- (_, &ty::ty_bot) => { this.ty_bot(a) }
+ (&ty::ty_infer(TyVar(..)), &ty::ty_infer(TyVar(..)))
+ if infcx.type_var_diverges(a) && infcx.type_var_diverges(b) => {
+ let v = infcx.next_diverging_ty_var();
+ try!(this.relate_bound(v, a, b));
+ Ok(v)
+ }
(&ty::ty_infer(TyVar(..)), _) |
(_, &ty::ty_infer(TyVar(..))) => {
t.fold_with(&mut self.skolemizer())
}
+ pub fn type_var_diverges(&'a self, ty: ty::t) -> bool {
+ match ty::get(ty).sty {
+ ty::ty_infer(ty::TyVar(vid)) => self.type_variables.borrow().var_diverges(vid),
+ _ => false
+ }
+ }
+
pub fn skolemizer<'a>(&'a self) -> TypeSkolemizer<'a, 'tcx> {
skolemize::TypeSkolemizer::new(self)
}
self.commit_unconditionally(|| self.try(|| f()))
}
- /// Execute `f`, unroll bindings on failure
+ /// Execute `f`, unroll bindings on panic
pub fn try<T,E>(&self, f: || -> Result<T,E>) -> Result<T,E> {
debug!("try()");
let snapshot = self.start_snapshot();
}
impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
- pub fn next_ty_var_id(&self) -> TyVid {
+ pub fn next_ty_var_id(&self, diverging: bool) -> TyVid {
self.type_variables
.borrow_mut()
- .new_var()
+ .new_var(diverging)
}
pub fn next_ty_var(&self) -> ty::t {
- ty::mk_var(self.tcx, self.next_ty_var_id())
+ ty::mk_var(self.tcx, self.next_ty_var_id(false))
+ }
+
+ pub fn next_diverging_ty_var(&self) -> ty::t {
+ ty::mk_var(self.tcx, self.next_ty_var_id(true))
}
pub fn next_ty_vars(&self, n: uint) -> Vec<ty::t> {
while undo_log.len() > snapshot.length + 1 {
match undo_log.pop().unwrap() {
OpenSnapshot => {
- fail!("Failure to observe stack discipline");
+ panic!("Failure to observe stack discipline");
}
Mark | CommitedSnapshot => { }
AddVar(vid) => {
// We want to generate the intersection of two
// scopes or two free regions. So, if one of
// these scopes is a subscope of the other, return
- // it. Otherwise fail.
+ // it. Otherwise fail.
debug!("intersect_scopes(scope_a={}, scope_b={}, region_a={}, region_b={})",
scope_a, scope_b, region_a, region_b);
match self.tcx.region_maps.nearest_common_ancestor(scope_a, scope_b) {
pub fn resolve_ty_var(&mut self, vid: TyVid) -> ty::t {
let tcx = self.infcx.tcx;
- let t1 = match self.infcx.type_variables.borrow().probe(vid) {
+ let tv = self.infcx.type_variables.borrow();
+ match tv.probe(vid) {
Some(t) => {
self.resolve_type(t)
}
}
ty::mk_var(tcx, vid)
}
- };
- return t1;
+ }
}
pub fn resolve_int_var(&mut self, vid: IntVid) -> ty::t {
}
ty::ty_nil |
- ty::ty_bot |
ty::ty_bool |
ty::ty_char |
ty::ty_int(..) |
let a = infcx.type_variables.borrow().replace_if_possible(a);
let b = infcx.type_variables.borrow().replace_if_possible(b);
match (&ty::get(a).sty, &ty::get(b).sty) {
- (&ty::ty_bot, _) => {
- Ok(a)
- }
-
(&ty::ty_infer(TyVar(a_id)), &ty::ty_infer(TyVar(b_id))) => {
infcx.type_variables
.borrow_mut()
Ok(ty::mk_err())
}
- (_, &ty::ty_bot) => {
- Err(ty::terr_sorts(expected_found(self, a, b)))
- }
-
_ => {
super_tys(self, a, b)
}
e.messages.remove(i);
}
None => {
- fail!("Unexpected error: {} Expected: {}",
+ panic!("Unexpected error: {} Expected: {}",
msg, e.messages);
}
}
return match search_mod(self, &self.infcx.tcx.map.krate().module, 0, names) {
Some(id) => id,
None => {
- fail!("no item found: `{}`", names.connect("::"));
+ panic!("no item found: `{}`", names.connect("::"));
}
};
pub fn make_subtype(&self, a: ty::t, b: ty::t) -> bool {
match infer::mk_subty(self.infcx, true, infer::Misc(DUMMY_SP), a, b) {
Ok(_) => true,
- Err(ref e) => fail!("Encountered error: {}",
+ Err(ref e) => panic!("Encountered error: {}",
ty::type_err_to_str(self.infcx.tcx, e))
}
}
pub fn assert_subtype(&self, a: ty::t, b: ty::t) {
if !self.is_subtype(a, b) {
- fail!("{} is not a subtype of {}, but it should be",
+ panic!("{} is not a subtype of {}, but it should be",
self.ty_to_string(a),
self.ty_to_string(b));
}
pub fn assert_not_subtype(&self, a: ty::t, b: ty::t) {
if self.is_subtype(a, b) {
- fail!("{} is a subtype of {}, but it shouldn't be",
+ panic!("{} is a subtype of {}, but it shouldn't be",
self.ty_to_string(a),
self.ty_to_string(b));
}
pub fn make_lub_ty(&self, t1: ty::t, t2: ty::t) -> ty::t {
match self.lub().tys(t1, t2) {
Ok(t) => t,
- Err(ref e) => fail!("unexpected error computing LUB: {}",
+ Err(ref e) => panic!("unexpected error computing LUB: {}",
ty::type_err_to_str(self.infcx.tcx, e))
}
}
self.assert_eq(t, t_lub);
}
Err(ref e) => {
- fail!("unexpected error in LUB: {}",
+ panic!("unexpected error in LUB: {}",
ty::type_err_to_str(self.infcx.tcx, e))
}
}
self.ty_to_string(t_glb));
match self.glb().tys(t1, t2) {
Err(e) => {
- fail!("unexpected error computing LUB: {}", e)
+ panic!("unexpected error computing LUB: {}", e)
}
Ok(t) => {
self.assert_eq(t, t_glb);
match self.lub().tys(t1, t2) {
Err(_) => {}
Ok(t) => {
- fail!("unexpected success computing LUB: {}", self.ty_to_string(t))
+ panic!("unexpected success computing LUB: {}", self.ty_to_string(t))
}
}
}
match self.glb().tys(t1, t2) {
Err(_) => {}
Ok(t) => {
- fail!("unexpected success computing GLB: {}", self.ty_to_string(t))
+ panic!("unexpected success computing GLB: {}", self.ty_to_string(t))
}
}
}
}
struct TypeVariableData {
- value: TypeVariableValue
+ value: TypeVariableValue,
+ diverging: bool
}
enum TypeVariableValue {
relations(self.values.get_mut(a.index))
}
+ pub fn var_diverges<'a>(&'a self, vid: ty::TyVid) -> bool {
+ self.values.get(vid.index).diverging
+ }
+
pub fn relate_vars(&mut self, a: ty::TyVid, dir: RelationDir, b: ty::TyVid) {
/*!
* Records that `a <: b`, `a :> b`, or `a == b`, depending on `dir`.
let relations = match old_value {
Bounded(b) => b,
- Known(_) => fail!("Asked to instantiate variable that is \
+ Known(_) => panic!("Asked to instantiate variable that is \
already instantiated")
};
self.values.record(SpecifyVar(vid, relations));
}
- pub fn new_var(&mut self) -> ty::TyVid {
- let index =
- self.values.push(
- TypeVariableData { value: Bounded(Vec::new()) });
+ pub fn new_var(&mut self, diverging: bool) -> ty::TyVid {
+ let index = self.values.push(TypeVariableData {
+ value: Bounded(vec![]),
+ diverging: diverging
+ });
ty::TyVid { index: index }
}
fn relations<'a>(v: &'a mut TypeVariableData) -> &'a mut Vec<Relation> {
match v.value {
- Known(_) => fail!("var_sub_var: variable is known"),
+ Known(_) => panic!("var_sub_var: variable is known"),
Bounded(ref mut relations) => relations
}
}
impl<K,V> sv::SnapshotVecDelegate<VarValue<K,V>,()> for Delegate {
fn reverse(&mut self, _: &mut Vec<VarValue<K,V>>, _: ()) {
- fail!("Nothing to reverse");
+ panic!("Nothing to reverse");
}
}
sig: ty::FnSig {
binder_id: main_id,
inputs: Vec::new(),
- output: ty::mk_nil(),
+ output: ty::FnConverging(ty::mk_nil()),
variadic: false
}
});
ty::mk_int(),
ty::mk_imm_ptr(tcx, ty::mk_imm_ptr(tcx, ty::mk_u8()))
),
- output: ty::mk_int(),
+ output: ty::FnConverging(ty::mk_int()),
variadic: false
}
});
match tcx.named_region_map.find(¶m_id) {
Some(&rl::DefEarlyBoundRegion(_, _, lifetime_decl_id))
=> lifetime_decl_id,
- Some(_) => fail!("should not encounter non early-bound cases"),
+ Some(_) => panic!("should not encounter non early-bound cases"),
// The lookup should only fail when `param_id` is
// itself a lifetime binding: use it as the decl_id.
assert!(is_lifetime(&tcx.map, param_id));
let parent_id = tcx.map.get_parent(decl_id);
let parent = tcx.map.find(parent_id).unwrap_or_else(
- || fail!("tcx.map missing entry for id: {}", parent_id));
+ || panic!("tcx.map missing entry for id: {}", parent_id));
let is_inferred;
macro_rules! cannot_happen { () => { {
- fail!("invalid parent: {:s} for {:s}",
+ panic!("invalid parent: {:s} for {:s}",
tcx.map.node_to_string(parent_id),
tcx.map.node_to_string(param_id));
} } }
debug!("add_constraints_from_ty(ty={})", ty.repr(self.tcx()));
match ty::get(ty).sty {
- ty::ty_nil | ty::ty_bot | ty::ty_bool |
+ ty::ty_nil | ty::ty_bool |
ty::ty_char | ty::ty_int(_) | ty::ty_uint(_) |
ty::ty_float(_) | ty::ty_str => {
/* leaf type -- noop */
}
- ty::ty_unboxed_closure(_, region) => {
- let contra = self.contravariant(variance);
- self.add_constraints_from_region(region, contra);
+ ty::ty_unboxed_closure(..) => {
+ self.tcx().sess.bug("Unexpected unboxed closure type in variance computation");
}
ty::ty_rptr(region, ref mt) => {
for &input in sig.inputs.iter() {
self.add_constraints_from_ty(input, contra);
}
- self.add_constraints_from_ty(sig.output, variance);
+ if let ty::FnConverging(result_type) = sig.output {
+ self.add_constraints_from_ty(result_type, variance);
+ }
}
/// Adds constraints appropriate for a region appearing in a
) )
weak_lang_items!(
- fail_fmt, FailFmtLangItem, rust_begin_unwind;
+ panic_fmt, PanicFmtLangItem, rust_begin_unwind;
stack_exhausted, StackExhaustedLangItem, rust_stack_exhausted;
eh_personality, EhPersonalityLangItem, rust_eh_personality;
)
Decorator(ext) => Decorator(ext),
Modifier(ext) => Modifier(ext),
// there's probably a nicer way to signal this:
- LetSyntaxTT(_, _) => fail!("can't register a new LetSyntax!"),
+ LetSyntaxTT(_, _) => panic!("can't register a new LetSyntax!"),
}));
}
use middle::ty::{ReFree, ReScope, ReInfer, ReStatic, Region, ReEmpty};
use middle::ty::{ReSkolemized, ReVar, BrEnv};
use middle::ty::{mt, t, ParamTy};
-use middle::ty::{ty_bool, ty_char, ty_bot, ty_struct, ty_enum};
+use middle::ty::{ty_bool, ty_char, ty_struct, ty_enum};
use middle::ty::{ty_err, ty_str, ty_vec, ty_float, ty_bare_fn, ty_closure};
use middle::ty::{ty_nil, ty_param, ty_ptr, ty_rptr, ty_tup, ty_open};
use middle::ty::{ty_unboxed_closure};
s.push_str(bounds);
}
- if ty::get(sig.output).sty != ty_nil {
- s.push_str(" -> ");
- if ty::type_is_bot(sig.output) {
- s.push('!');
- } else {
- s.push_str(ty_to_string(cx, sig.output).as_slice());
+ match sig.output {
+ ty::FnConverging(t) => {
+ if !ty::type_is_nil(t) {
+ s.push_str(" -> ");
+ s.push_str(ty_to_string(cx, t).as_slice());
+ }
+ }
+ ty::FnDiverging => {
+ s.push_str(" -> !");
}
}
}
// pretty print the structural type representation:
return match ty::get(typ).sty {
ty_nil => "()".to_string(),
- ty_bot => "!".to_string(),
ty_bool => "bool".to_string(),
ty_char => "char".to_string(),
ty_int(t) => ast_util::int_ty_to_string(t, None).to_string(),
bound_str)
}
ty_str => "str".to_string(),
- ty_unboxed_closure(..) => "closure".to_string(),
+ ty_unboxed_closure(ref did, _, ref substs) => {
+ let unboxed_closures = cx.unboxed_closures.borrow();
+ unboxed_closures.find(did).map(|cl| {
+ closure_to_string(cx, &cl.closure_type.subst(cx, substs))
+ }).unwrap_or_else(|| "closure".to_string())
+ }
ty_vec(t, sz) => {
match sz {
Some(n) => {
}
}
+impl Repr for ty::FnOutput {
+ fn repr(&self, tcx: &ctxt) -> String {
+ match *self {
+ ty::FnConverging(ty) =>
+ format!("FnConverging({0})", ty.repr(tcx)),
+ ty::FnDiverging =>
+ "FnDiverging".to_string()
+ }
+ }
+}
+
impl Repr for typeck::MethodCallee {
fn repr(&self, tcx: &ctxt) -> String {
format!("MethodCallee {{origin: {}, ty: {}, {}}}",
match self.undo_log.pop().unwrap() {
OpenSnapshot => {
// This indicates a failure to obey the stack discipline.
- fail!("Cannot rollback an uncommitted snapshot");
+ panic!("Cannot rollback an uncommitted snapshot");
}
CommittedSnapshot => {
handler.err(format!("could not exec `{}`: {}", ar.as_slice(),
e).as_slice());
handler.abort_if_errors();
- fail!("rustc::back::archive::run_ar() should not reach this point");
+ panic!("rustc::back::archive::run_ar() should not reach this point");
}
}
}
os: abi::OsLinux,
used_crates: Vec::new(),
out_filename: Path::new("bin/rustc"),
- get_install_prefix_lib_path: || fail!(),
+ get_install_prefix_lib_path: || panic!(),
realpath: |p| Ok(p.clone())
};
let res = get_rpath_relative_to_output(config, &Path::new("lib/libstd.so"));
os: abi::OsFreebsd,
used_crates: Vec::new(),
out_filename: Path::new("bin/rustc"),
- get_install_prefix_lib_path: || fail!(),
+ get_install_prefix_lib_path: || panic!(),
realpath: |p| Ok(p.clone())
};
let res = get_rpath_relative_to_output(config, &Path::new("lib/libstd.so"));
os: abi::OsDragonfly,
used_crates: Vec::new(),
out_filename: Path::new("bin/rustc"),
- get_install_prefix_lib_path: || fail!(),
+ get_install_prefix_lib_path: || panic!(),
realpath: |p| Ok(p.clone())
};
let res = get_rpath_relative_to_output(config, &Path::new("lib/libstd.so"));
os: abi::OsMacos,
used_crates: Vec::new(),
out_filename: Path::new("bin/rustc"),
- get_install_prefix_lib_path: || fail!(),
+ get_install_prefix_lib_path: || panic!(),
realpath: |p| Ok(p.clone())
};
let res = get_rpath_relative_to_output(config, &Path::new("lib/libstd.so"));
}
}
-/// Adds the specified number of bytes to the bit count. fail!() if this would cause numeric
+/// Adds the specified number of bytes to the bit count. panic!() if this would cause numeric
/// overflow.
fn add_bytes_to_bits<T: Int + CheckedAdd + ToBits>(bits: T, bytes: T) -> T {
let (new_high_bits, new_low_bits) = bytes.to_bits();
if new_high_bits > Zero::zero() {
- fail!("numeric overflow occurred.")
+ panic!("numeric overflow occurred.")
}
match bits.checked_add(&new_low_bits) {
Some(x) => return x,
- None => fail!("numeric overflow occurred.")
+ None => panic!("numeric overflow occurred.")
}
}
} else {
// It is not possible to observe any kind of macro
// invocation at this stage except `macro_rules!`.
- fail!("reached macro somehow: {}",
+ panic!("reached macro somehow: {}",
pprust::to_string(|pp_state| pp_state.print_mac(macro)));
}
clean::Function {
decl: match ty::get(t.ty).sty {
ty::ty_bare_fn(ref f) => (did, &f.sig).clean(cx),
- _ => fail!("bad function"),
+ _ => panic!("bad function"),
},
generics: (&t.generics, subst::FnSpace).clean(cx),
fn_style: style,
generics: generics,
})
}
- _ => fail!("not a tymethod"),
+ _ => panic!("not a tymethod"),
};
Some(item)
}
decoder::DlDef(..) => {}
// All impls were inlined above
decoder::DlImpl(..) => {}
- decoder::DlField => fail!("unimplemented field"),
+ decoder::DlField => panic!("unimplemented field"),
}
});
}
}
}
+impl<'a> Clean<Type> for ty::FnOutput {
+ fn clean(&self, cx: &DocContext) -> Type {
+ match *self {
+ ty::FnConverging(ty) => ty.clean(cx),
+ ty::FnDiverging => Bottom
+ }
+ }
+}
+
impl<'a> Clean<FnDecl> for (ast::DefId, &'a ty::FnSig) {
fn clean(&self, cx: &DocContext) -> FnDecl {
let (did, sig) = *self;
TyBareFn(ref barefn) => BareFunction(box barefn.clean(cx)),
TyParen(ref ty) => ty.clean(cx),
TyBot => Bottom,
- ref x => fail!("Unimplemented type {}", x),
+ ref x => panic!("Unimplemented type {}", x),
}
}
}
impl Clean<Type> for ty::t {
fn clean(&self, cx: &DocContext) -> Type {
match ty::get(*self).sty {
- ty::ty_bot => Bottom,
ty::ty_nil => Primitive(Unit),
ty::ty_bool => Primitive(Bool),
ty::ty_char => Primitive(Char),
ty::ty_unboxed_closure(..) => Primitive(Unit), // FIXME(pcwalton)
- ty::ty_infer(..) => fail!("ty_infer"),
- ty::ty_open(..) => fail!("ty_open"),
- ty::ty_err => fail!("ty_err"),
+ ty::ty_infer(..) => panic!("ty_infer"),
+ ty::ty_open(..) => panic!("ty_open"),
+ ty::ty_err => panic!("ty_err"),
}
}
}
which is silly in function arguments");
"()".to_string()
},
- PatRange(..) => fail!("tried to get argument name from PatRange, \
+ PatRange(..) => panic!("tried to get argument name from PatRange, \
which is not allowed in function arguments"),
- PatVec(..) => fail!("tried to get argument name from pat_vec, \
+ PatVec(..) => panic!("tried to get argument name from pat_vec, \
which is not allowed in function arguments"),
PatMac(..) => {
warn!("can't document the name of a function argument \
debug!("searching for {} in defmap", id);
let def = match tcx.def_map.borrow().find(&id) {
Some(&k) => k,
- None => fail!("unresolved id not in defmap")
+ None => panic!("unresolved id not in defmap")
};
match def {
};
if ret == -1 {
unsafe { libc::close(fd); }
- fail!("could not lock `{}`", p.display())
+ panic!("could not lock `{}`", p.display())
}
Lock { fd: fd }
}
ptr::null_mut())
};
if handle == libc::INVALID_HANDLE_VALUE {
- fail!("create file error: {}", os::last_os_error());
+ panic!("create file error: {}", os::last_os_error());
}
let mut overlapped: libc::OVERLAPPED = unsafe { mem::zeroed() };
let ret = unsafe {
};
if ret == 0 {
unsafe { libc::CloseHandle(handle); }
- fail!("could not lock `{}`: {}", p.display(),
+ panic!("could not lock `{}`: {}", p.display(),
os::last_os_error())
}
Lock { handle: handle }
}
}
clean::Unique(..) => {
- fail!("should have been cleaned")
+ panic!("should have been cleaned")
}
}
}
use std::io;
use syntax::parse::lexer;
-use syntax::parse::token as t;
+use syntax::parse::token;
use syntax::parse;
/// Highlights some source code, returning the HTML output.
let snip = |sp| sess.span_diagnostic.cm.span_to_snippet(sp).unwrap();
- if next.tok == t::EOF { break }
+ if next.tok == token::Eof { break }
let klass = match next.tok {
- t::WS => {
+ token::Whitespace => {
try!(write!(out, "{}", Escape(snip(next.sp).as_slice())));
continue
},
- t::COMMENT => {
+ token::Comment => {
try!(write!(out, "<span class='comment'>{}</span>",
Escape(snip(next.sp).as_slice())));
continue
},
- t::SHEBANG(s) => {
+ token::Shebang(s) => {
try!(write!(out, "{}", Escape(s.as_str())));
continue
},
// that it's the address-of operator instead of the and-operator.
// This allows us to give all pointers their own class (`Box` and
// `@` are below).
- t::BINOP(t::AND) if lexer.peek().sp.lo == next.sp.hi => "kw-2",
- t::AT | t::TILDE => "kw-2",
+ token::BinOp(token::And) if lexer.peek().sp.lo == next.sp.hi => "kw-2",
+ token::At | token::Tilde => "kw-2",
// consider this as part of a macro invocation if there was a
// leading identifier
- t::NOT if is_macro => { is_macro = false; "macro" }
+ token::Not if is_macro => { is_macro = false; "macro" }
// operators
- t::EQ | t::LT | t::LE | t::EQEQ | t::NE | t::GE | t::GT |
- t::ANDAND | t::OROR | t::NOT | t::BINOP(..) | t::RARROW |
- t::BINOPEQ(..) | t::FAT_ARROW => "op",
+ token::Eq | token::Lt | token::Le | token::EqEq | token::Ne | token::Ge | token::Gt |
+ token::AndAnd | token::OrOr | token::Not | token::BinOp(..) | token::RArrow |
+ token::BinOpEq(..) | token::FatArrow => "op",
// miscellaneous, no highlighting
- t::DOT | t::DOTDOT | t::DOTDOTDOT | t::COMMA | t::SEMI |
- t::COLON | t::MOD_SEP | t::LARROW | t::LPAREN |
- t::RPAREN | t::LBRACKET | t::LBRACE | t::RBRACE | t::QUESTION => "",
- t::DOLLAR => {
- if t::is_ident(&lexer.peek().tok) {
+ token::Dot | token::DotDot | token::DotDotDot | token::Comma | token::Semi |
+ token::Colon | token::ModSep | token::LArrow | token::LParen |
+ token::RParen | token::LBracket | token::LBrace | token::RBrace |
+ token::Question => "",
+ token::Dollar => {
+ if lexer.peek().tok.is_ident() {
is_macro_nonterminal = true;
"macro-nonterminal"
} else {
// continue highlighting it as an attribute until the ending ']' is
// seen, so skip out early. Down below we terminate the attribute
// span when we see the ']'.
- t::POUND => {
+ token::Pound => {
is_attribute = true;
try!(write!(out, r"<span class='attribute'>#"));
continue
}
- t::RBRACKET => {
+ token::RBracket => {
if is_attribute {
is_attribute = false;
try!(write!(out, "]</span>"));
}
// text literals
- t::LIT_BYTE(..) | t::LIT_BINARY(..) | t::LIT_BINARY_RAW(..) |
- t::LIT_CHAR(..) | t::LIT_STR(..) | t::LIT_STR_RAW(..) => "string",
+ token::LitByte(..) | token::LitBinary(..) | token::LitBinaryRaw(..) |
+ token::LitChar(..) | token::LitStr(..) | token::LitStrRaw(..) => "string",
// number literals
- t::LIT_INTEGER(..) | t::LIT_FLOAT(..) => "number",
+ token::LitInteger(..) | token::LitFloat(..) => "number",
// keywords are also included in the identifier set
- t::IDENT(ident, _is_mod_sep) => {
- match t::get_ident(ident).get() {
+ token::Ident(ident, _is_mod_sep) => {
+ match token::get_ident(ident).get() {
"ref" | "mut" => "kw-2",
"self" => "self",
"Option" | "Result" => "prelude-ty",
"Some" | "None" | "Ok" | "Err" => "prelude-val",
- _ if t::is_any_keyword(&next.tok) => "kw",
+ _ if next.tok.is_any_keyword() => "kw",
_ => {
if is_macro_nonterminal {
is_macro_nonterminal = false;
"macro-nonterminal"
- } else if lexer.peek().tok == t::NOT {
+ } else if lexer.peek().tok == token::Not {
is_macro = true;
"macro"
} else {
}
}
- t::LIFETIME(..) => "lifetime",
- t::DOC_COMMENT(..) => "doccomment",
- t::UNDERSCORE | t::EOF | t::INTERPOLATED(..) => "",
+ token::Lifetime(..) => "lifetime",
+ token::DocComment(..) => "doccomment",
+ token::Underscore | token::Eof | token::Interpolated(..) => "",
};
// as mentioned above, use the original source code instead of
/// sure it always points to the top (relatively)
fn recurse<T>(&mut self, s: String, f: |&mut Context| -> T) -> T {
if s.len() == 0 {
- fail!("Unexpected empty destination: {}", self.current);
+ panic!("Unexpected empty destination: {}", self.current);
}
let prev = self.dst.clone();
self.dst.push(s.as_slice());
Some("html") | None => {
match html::render::run(krate, &external_html, output.unwrap_or(Path::new("doc"))) {
Ok(()) => {}
- Err(e) => fail!("failed to generate documentation: {}", e),
+ Err(e) => panic!("failed to generate documentation: {}", e),
}
}
Some("json") => {
match json_output(krate, res, output.unwrap_or(Path::new("doc.json"))) {
Ok(()) => {}
- Err(e) => fail!("failed to write json: {}", e),
+ Err(e) => panic!("failed to write json: {}", e),
}
}
Some(s) => {
};
let crate_json = match json::from_str(crate_json_str.as_slice()) {
Ok(j) => j,
- Err(e) => fail!("Rust generated JSON is invalid: {}", e)
+ Err(e) => panic!("Rust generated JSON is invalid: {}", e)
};
json.insert("crate".to_string(), crate_json);
cmd.env(DynamicLibrary::envvar(), newpath.as_slice());
match cmd.output() {
- Err(e) => fail!("couldn't run the test: {}{}", e,
+ Err(e) => panic!("couldn't run the test: {}{}", e,
if e.kind == io::PermissionDenied {
" - maybe your tempdir is mounted with noexec?"
} else { "" }),
Ok(out) => {
if should_fail && out.status.success() {
- fail!("test executable succeeded when it should have failed");
+ panic!("test executable succeeded when it should have failed");
} else if !should_fail && !out.status.success() {
- fail!("test executable failed:\n{}",
+ panic!("test executable failed:\n{}",
str::from_utf8(out.error.as_slice()));
}
}
self.visit_item(&**i, None, om);
}
}
- _ => { fail!("glob not mapped to a module"); }
+ _ => { panic!("glob not mapped to a module"); }
}
} else {
self.visit_item(it, renamed, om);
om.foreigns.push(fm.clone());
}
ast::ItemMac(_) => {
- fail!("rustdoc: macros should be gone, after expansion");
+ panic!("rustdoc: macros should be gone, after expansion");
}
}
}
}
pub fn take() -> Option<Vec<Vec<u8>>> {
- fail!()
+ panic!()
}
pub fn put(_args: Vec<Vec<u8>>) {
- fail!()
+ panic!()
}
pub fn clone() -> Option<Vec<Vec<u8>>> {
- fail!()
+ panic!()
}
}
fn clone(&self) -> CString {
let len = self.len() + 1;
let buf = unsafe { libc::malloc(len as libc::size_t) } as *mut libc::c_char;
- if buf.is_null() { fail!("out of memory") }
+ if buf.is_null() { panic!("out of memory") }
unsafe { ptr::copy_nonoverlapping_memory(buf, self.buf, len); }
CString { buf: buf as *const libc::c_char, owns_buffer_: true }
}
unsafe fn to_c_str_unchecked(&self) -> CString {
let self_len = self.len();
let buf = libc::malloc(self_len as libc::size_t + 1) as *mut u8;
- if buf.is_null() { fail!("out of memory") }
+ if buf.is_null() { panic!("out of memory") }
ptr::copy_memory(buf, self.as_ptr(), self_len);
*buf.offset(self_len as int) = 0;
fn wrap(self: Box<Self>) -> Box<Any+'static>;
}
-/// The default error code of the rust runtime if the main task fails instead
+/// The default error code of the rust runtime if the main task panics instead
/// of exiting cleanly.
pub const DEFAULT_ERROR_CODE: int = 101;
*slot = Some(TreeMap::new());
match *slot {
Some(ref mut map_ptr) => { return Some(map_ptr) }
- None => fail!("unreachable code"),
+ None => panic!("unreachable code"),
}
}
}
/// If this key is already present in TLD, then the previous value is
/// replaced with the provided data, and then returned.
///
- /// # Failure
+ /// # Panics
///
- /// This function will fail if the key is present in TLD and currently on
+ /// This function will panic if the key is present in TLD and currently on
/// loan with the `get` method.
///
- /// It will also fail if there is no local task (because the current thread
+ /// It will also panic if there is no local task (because the current thread
/// is not owned by the runtime).
///
/// # Example
pub fn replace(&'static self, data: Option<T>) -> Option<T> {
let map = match unsafe { get_local_map() } {
Some(map) => map,
- None => fail!("must have a local task to insert into TLD"),
+ None => panic!("must have a local task to insert into TLD"),
};
let keyval = key_to_key_value(self);
}
_ => {
// Refcount is 2+, which means we have a live borrow.
- fail!("TLD value cannot be replaced because it is already borrowed");
+ panic!("TLD value cannot be replaced because it is already borrowed");
}
}
}
unsafe fn d<T>(p: *mut ()) {
let value_box = p as *mut TLDValueBox<T>;
debug_assert!(*(*value_box).refcount.get() < 2, "TLDValue destructed while borrowed");
- // use a RAII type here to ensure we always deallocate even if we fail while
+ // use a RAII type here to ensure we always deallocate even if we panic while
// running the destructor for the value.
struct Guard<T> {
p: *mut TLDValueBox<T>
#[test]
#[should_fail]
- fn test_tls_cleanup_on_failure() {
+ fn test_tls_cleanup_on_panic() {
static STR_KEY: Key<String> = &KeyValueKey;
static BOX_KEY: Key<Box<int>> = &KeyValueKey;
static INT_KEY: Key<int> = &KeyValueKey;
STR_KEY.replace(Some("string data".to_string()));
BOX_KEY.replace(Some(box 2));
INT_KEY.replace(Some(42));
- fail!();
+ panic!();
});
// Not quite nondeterministic.
INT_KEY.replace(Some(31337));
- fail!();
+ panic!();
}
#[test]
/// destruction.
///
/// Using this makes lock-based code resilient to unwinding/task
-/// failure, because the lock will be automatically unlocked even
+/// panic, because the lock will be automatically unlocked even
/// then.
#[must_use]
pub struct LockGuard<'a> {
PAGE_SIZE = info.dwPageSize as uint;
if AddVectoredExceptionHandler(0, vectored_handler) == ptr::null_mut() {
- fail!("failed to install exception handler");
+ panic!("failed to install exception handler");
}
mem::forget(make_handler());
pub unsafe fn make_handler() -> Handler {
if SetThreadStackGuarantee(&mut 0x5000) == 0 {
- fail!("failed to reserve stack space for exception handling");
+ panic!("failed to reserve stack space for exception handling");
}
super::Handler { _data: 0i as *mut libc::c_void }
pub unsafe fn init() {
let psize = libc::sysconf(libc::consts::os::sysconf::_SC_PAGESIZE);
if psize == -1 {
- fail!("failed to get page size");
+ panic!("failed to get page size");
}
PAGE_SIZE = psize as uint;
-1,
0);
if alt_stack == MAP_FAILED {
- fail!("failed to allocate an alternative stack");
+ panic!("failed to allocate an alternative stack");
}
let mut stack: sigaltstack = mem::zeroed();
///
/// * `run` - This function will execute a closure inside the context of a task.
/// Failure is caught and handled via the task's on_exit callback. If
-/// this fails, the task is still returned, but it can no longer be
+/// this panics, the task is still returned, but it can no longer be
/// used, it is poisoned.
///
/// * `destroy` - This is a required function to call to destroy a task. If a
/// // Create a task using a native runtime
/// let task = native::task::new((0, uint::MAX), 0);
///
-/// // Run some code, catching any possible failures
+/// // Run some code, catching any possible panic
/// let task = task.run(|| {
/// // Run some code inside this task
/// println!("Hello with a native runtime!");
/// });
///
-/// // Run some code again, catching the failure
+/// // Run some code again, catching the panic
/// let task = task.run(|| {
-/// fail!("oh no, what to do!");
+/// panic!("oh no, what to do!");
/// });
///
-/// // Now that the task is failed, it can never be used again
+/// // Now that the task has panicked, it can never be used again
/// assert!(task.is_destroyed());
///
/// // Deallocate the resources associated with this task
pub struct TaskOpts {
/// Invoke this procedure with the result of the task when it finishes.
pub on_exit: Option<proc(Result): Send>,
- /// A name for the task-to-be, for identification in failure messages
+ /// A name for the task-to-be, for identification in panic messages
pub name: Option<SendStr>,
/// The size of the stack for the spawned task
pub stack_size: Option<uint>,
/// Indicates the manner in which a task exited.
///
-/// A task that completes without failing is considered to exit successfully.
+/// A task that completes without panicking is considered to exit successfully.
///
/// If you wish for this result's delivery to block until all
/// children tasks complete, recommend using a result future.
Shared(Arc<AtomicUint>),
}
-/// Per-task state related to task death, killing, failure, etc.
+/// Per-task state related to task death, killing, panic, etc.
pub struct Death {
pub on_exit: Option<proc(Result):Send>,
marker: marker::NoCopy,
/// try/catch). Invoking this function is quite cheap.
///
/// If the closure `f` succeeds, then the returned task can be used again
- /// for another invocation of `run`. If the closure `f` fails then `self`
+ /// for another invocation of `run`. If the closure `f` panics then `self`
/// will be internally destroyed along with all of the other associated
/// resources of this task. The `on_exit` callback is invoked with the
- /// cause of failure (not returned here). This can be discovered by querying
+ /// cause of panic (not returned here). This can be discovered by querying
/// `is_destroyed()`.
///
/// Note that it is possible to view partial execution of the closure `f`
/// because it is not guaranteed to run to completion, but this function is
- /// guaranteed to return if it fails. Care should be taken to ensure that
+ /// guaranteed to return if it panicks. Care should be taken to ensure that
/// stack references made by `f` are handled appropriately.
///
/// It is invalid to call this function with a task that has been previously
// recursive invocations of run(). If there's no one else, then
// relinquish ownership of ourselves back into TLS.
if Local::exists(None::<Task>) {
- fail!("cannot run a task recursively inside another");
+ panic!("cannot run a task recursively inside another");
}
self.state = Armed;
Local::put(self);
let result = unsafe { unwind::try(f) };
// After running the closure given return the task back out if it ran
- // successfully, or clean up the task if it failed.
+ // successfully, or clean up the task if it panicked.
let task: Box<Task> = Local::take();
match result {
Ok(()) => task,
// There is a test for this at fail-during-tld-destroy.rs.
//
// 2. One failure in destruction is tolerable, so long as the task
- // didn't originally fail while it was running.
+ // didn't originally panic while it was running.
//
// And with all that in mind, we attempt to clean things up!
let mut task = self.run(|| {
drop(tld);
});
- // If the above `run` block failed, then it must be the case that the
+ // If the above `run` block panicked, then it must be the case that the
// task had previously succeeded. This also means that the code below
// was recursively run via the `run` method invoking this method. In
// this case, we just make sure the world is as we thought, and return.
// FIXME: this is running in a seriously constrained context. If this
// allocates TLD then it will likely abort the runtime. Similarly,
- // if this fails, this will also likely abort the runtime.
+ // if this panics, this will also likely abort the runtime.
//
// This closure is currently limited to a channel send via the
// standard library's task interface, but this needs
}
// This assertion has two flavours because the wake involves an atomic op.
- // In the faster version, destructors will fail dramatically instead.
+ // In the faster version, destructors will panic dramatically instead.
#[cfg(not(test))] pub fn trash(self) { }
#[cfg(test)] pub fn trash(self) { assert!(self.wake().is_none()); }
let result = task::try(proc()());
rtdebug!("trying first assert");
assert!(result.is_ok());
- let result = task::try::<()>(proc() fail!());
+ let result = task::try::<()>(proc() panic!());
rtdebug!("trying second assert");
assert!(result.is_err());
}
if ret as uint == 0 {
// be sure to not leak the closure
let _p: Box<proc():Send> = mem::transmute(arg);
- fail!("failed to spawn native thread: {}", ret);
+ panic!("failed to spawn native thread: {}", ret);
}
return ret;
}
unsafe fn get_stack_start() -> *mut libc::c_void {
let mut attr: libc::pthread_attr_t = mem::zeroed();
if pthread_getattr_np(pthread_self(), &mut attr) != 0 {
- fail!("failed to get thread attributes");
+ panic!("failed to get thread attributes");
}
let mut stackaddr = ptr::null_mut();
let mut stacksize = 0;
if pthread_attr_getstack(&attr, &mut stackaddr, &mut stacksize) != 0 {
- fail!("failed to get stack information");
+ panic!("failed to get stack information");
}
if pthread_attr_destroy(&mut attr) != 0 {
- fail!("failed to destroy thread attributes");
+ panic!("failed to destroy thread attributes");
}
stackaddr
}
pub unsafe fn init() {
let psize = libc::sysconf(libc::consts::os::sysconf::_SC_PAGESIZE);
if psize == -1 {
- fail!("failed to get page size");
+ panic!("failed to get page size");
}
PAGE_SIZE = psize as uint;
0);
if result != stackaddr || result == MAP_FAILED {
- fail!("failed to allocate a guard page");
+ panic!("failed to allocate a guard page");
}
let offset = if cfg!(target_os = "linux") {
pub unsafe fn current() -> uint {
let mut attr: libc::pthread_attr_t = mem::zeroed();
if pthread_getattr_np(pthread_self(), &mut attr) != 0 {
- fail!("failed to get thread attributes");
+ panic!("failed to get thread attributes");
}
let mut guardsize = 0;
if pthread_attr_getguardsize(&attr, &mut guardsize) != 0 {
- fail!("failed to get stack guard page");
+ panic!("failed to get stack guard page");
}
if guardsize == 0 {
- fail!("there is no guard page");
+ panic!("there is no guard page");
}
let mut stackaddr = ptr::null_mut();
let mut stacksize = 0;
if pthread_attr_getstack(&attr, &mut stackaddr, &mut stacksize) != 0 {
- fail!("failed to get stack information");
+ panic!("failed to get stack information");
}
if pthread_attr_destroy(&mut attr) != 0 {
- fail!("failed to destroy thread attributes");
+ panic!("failed to destroy thread attributes");
}
stackaddr as uint + guardsize as uint
},
errno => {
// This cannot really happen.
- fail!("pthread_attr_setstacksize() error: {}", errno);
+ panic!("pthread_attr_setstacksize() error: {}", errno);
},
};
if ret != 0 {
// be sure to not leak the closure
let _p: Box<proc():Send> = mem::transmute(arg);
- fail!("failed to spawn native thread: {}", ret);
+ panic!("failed to spawn native thread: {}", ret);
}
native
}
}
}
-/// Invoke a closure, capturing the cause of failure if one occurs.
+/// Invoke a closure, capturing the cause of panic if one occurs.
///
-/// This function will return `None` if the closure did not fail, and will
-/// return `Some(cause)` if the closure fails. The `cause` returned is the
-/// object with which failure was originally invoked.
+/// This function will return `None` if the closure did not panic, and will
+/// return `Some(cause)` if the closure panics. The `cause` returned is the
+/// object with which panic was originally invoked.
///
/// This function also is unsafe for a variety of reasons:
///
}
}
-// Entry point of failure from the libcore crate
+// Entry point of panic from the libcore crate
#[cfg(not(test))]
-#[lang = "fail_fmt"]
+#[lang = "panic_fmt"]
pub extern fn rust_begin_unwind(msg: &fmt::Arguments,
file: &'static str, line: uint) -> ! {
begin_unwind_fmt(msg, &(file, line))
}
+// NOTE(stage0): remove after a snapshot
+#[cfg(not(test))]
+#[lang = "fail_fmt"]
+pub extern fn rust_fail_begin_unwind(msg: &fmt::Arguments,
+ file: &'static str, line: uint) -> ! {
+ rust_begin_unwind(msg, file, line)
+}
+
/// The entry point for unwinding with a formatted message.
///
/// This is designed to reduce the amount of code required at the call
-/// site as much as possible (so that `fail!()` has as low an impact
+/// site as much as possible (so that `panic!()` has as low an impact
/// on (e.g.) the inlining of other functions as possible), by moving
/// the actual formatting into this shared place.
#[inline(never)] #[cold]
// We do two allocations here, unfortunately. But (a) they're
// required with the current scheme, and (b) we don't handle
- // failure + OOM properly anyway (see comment in begin_unwind
+ // panic + OOM properly anyway (see comment in begin_unwind
// below).
struct VecWriter<'a> { v: &'a mut Vec<u8> }
begin_unwind_inner(msg, file_line)
}
-/// This is the entry point of unwinding for fail!() and assert!().
+/// This is the entry point of unwinding for panic!() and assert!().
#[inline(never)] #[cold] // avoid code bloat at the call sites as much as possible
pub fn begin_unwind<M: Any + Send>(msg: M, file_line: &(&'static str, uint)) -> ! {
// Note that this should be the only allocation performed in this code path.
- // Currently this means that fail!() on OOM will invoke this code path,
- // but then again we're not really ready for failing on OOM anyway. If
+ // Currently this means that panic!() on OOM will invoke this code path,
+ // but then again we're not really ready for panic on OOM anyway. If
// we do start doing this, then we should propagate this allocation to
// be performed in the parent of this task instead of the task that's
- // failing.
+ // panicking.
// see below for why we do the `Any` coercion here.
begin_unwind_inner(box msg, file_line)
/// we need the `Any` object anyway, we're not just creating it to
/// avoid being generic.)
///
-/// Do this split took the LLVM IR line counts of `fn main() { fail!()
+/// Do this split took the LLVM IR line counts of `fn main() { panic!()
/// }` from ~1900/3700 (-O/no opts) to 180/590.
#[inline(never)] #[cold] // this is the slow path, please never inline this
fn begin_unwind_inner(msg: Box<Any + Send>, file_line: &(&'static str, uint)) -> ! {
- // First, invoke call the user-defined callbacks triggered on task failure.
+ // First, invoke call the user-defined callbacks triggered on task panic.
//
// By the time that we see a callback has been registered (by reading
// MAX_CALLBACKS), the actual callback itself may have not been stored yet,
};
if task.unwinder.unwinding {
- // If a task fails while it's already unwinding then we
+ // If a task panics while it's already unwinding then we
// have limited options. Currently our preference is to
// just abort. In the future we may consider resuming
// unwinding or otherwise exiting the task cleanly.
/// Register a callback to be invoked when a task unwinds.
///
/// This is an unsafe and experimental API which allows for an arbitrary
-/// callback to be invoked when a task fails. This callback is invoked on both
+/// callback to be invoked when a task panics. This callback is invoked on both
/// the initial unwinding and a double unwinding if one occurs. Additionally,
/// the local `Task` will be in place for the duration of the callback, and
/// the callback must ensure that it remains in place once the callback returns.
v.push(b'=');
}
}
- _ => fail!("Algebra is broken, please alert the math police")
+ _ => panic!("Algebra is broken, please alert the math police")
}
unsafe {
let len = self.stack.len();
let idx = match *self.stack.last().unwrap() {
InternalIndex(i) => { i + 1 }
- _ => { fail!(); }
+ _ => { panic!(); }
};
*self.stack.get_mut(len - 1) = InternalIndex(idx);
}
match self.token {
None => {}
Some(Error(e)) => { return Err(e); }
- ref tok => { fail!("unexpected token {}", tok.clone()); }
+ ref tok => { panic!("unexpected token {}", tok.clone()); }
}
result
}
}
let key = match self.parser.stack().top() {
Some(Key(k)) => { k.to_string() }
- _ => { fail!("invalid state"); }
+ _ => { panic!("invalid state"); }
};
match self.build_value() {
Ok(value) => { values.insert(key, value); }
Ok(json) => Decodable::decode(&mut Decoder::new(json))
};
match res {
- Ok(_) => fail!("`{}` parsed & decoded ok, expecting error `{}`",
+ Ok(_) => panic!("`{}` parsed & decoded ok, expecting error `{}`",
to_parse, expected),
- Err(ParseError(e)) => fail!("`{}` is not valid json: {}",
+ Err(ParseError(e)) => panic!("`{}` is not valid json: {}",
to_parse, e),
Err(e) => {
assert_eq!(e, expected);
let bytes = mem_buf.unwrap();
let json_str = from_utf8(bytes.as_slice()).unwrap();
match from_str(json_str) {
- Err(_) => fail!("Unable to parse json_str: {}", json_str),
+ Err(_) => panic!("Unable to parse json_str: {}", json_str),
_ => {} // it parsed and we are good to go
}
}
let bytes = mem_buf.unwrap();
let json_str = from_utf8(bytes.as_slice()).unwrap();
match from_str(json_str) {
- Err(_) => fail!("Unable to parse json_str: {}", json_str),
+ Err(_) => panic!("Unable to parse json_str: {}", json_str),
_ => {} // it parsed and we are good to go
}
}
use Decodable;
let json_str = "{\"1\":true}";
let json_obj = match from_str(json_str) {
- Err(_) => fail!("Unable to parse json_str: {}", json_str),
+ Err(_) => panic!("Unable to parse json_str: {}", json_str),
Ok(o) => o
};
let mut decoder = Decoder::new(json_obj);
use Decodable;
let json_str = "{\"a\":true}";
let json_obj = match from_str(json_str) {
- Err(_) => fail!("Unable to parse json_str: {}", json_str),
+ Err(_) => panic!("Unable to parse json_str: {}", json_str),
Ok(o) => o
};
let mut decoder = Decoder::new(json_obj);
};
let (ref expected_evt, ref expected_stack) = expected[i];
if !parser.stack().is_equal_to(expected_stack.as_slice()) {
- fail!("Parser stack is not equal to {}", expected_stack);
+ panic!("Parser stack is not equal to {}", expected_stack);
}
assert_eq!(&evt, expected_evt);
i+=1;
use std::path;
use std::rc::Rc;
use std::cell::{Cell, RefCell};
+use std::sync::Arc;
pub trait Encoder<E> {
// Primitive types:
}
}
+impl<E, S:Encoder<E>, T:Encodable<S, E>> Encodable<S, E> for Arc<T> {
+ fn encode(&self, s: &mut S) -> Result<(), E> {
+ (**self).encode(s)
+ }
+}
+
+impl<E, D:Decoder<E>,T:Decodable<D, E>+Send+Sync> Decodable<D, E> for Arc<T> {
+ fn decode(d: &mut D) -> Result<Arc<T>, E> {
+ Ok(Arc::new(try!(Decodable::decode(d))))
+ }
+}
+
// ___________________________________________________________________________
// Helper routines
#![experimental]
use collections::Collection;
+use core::kinds::Sized;
use fmt;
use iter::Iterator;
use mem;
/// Trait for converting into an ascii type.
pub trait AsciiCast<T> {
- /// Convert to an ascii type, fail on non-ASCII input.
+ /// Convert to an ascii type, panic on non-ASCII input.
#[inline]
fn to_ascii(&self) -> T {
assert!(self.is_ascii());
#[inline]
unsafe fn into_ascii_nocheck(self) -> Vec<Ascii> {
- let v: Vec<u8> = mem::transmute(self);
- v.into_ascii_nocheck()
+ self.into_bytes().into_ascii_nocheck()
}
}
#[inline]
unsafe fn into_ascii_nocheck(self) -> Vec<Ascii> {
- mem::transmute(self)
+ let v = Vec::from_raw_parts(self.as_ptr() as *mut Ascii,
+ self.len(),
+ self.capacity());
+
+ // We forget `self` to avoid freeing it at the end of the scope
+ // Otherwise, the returned `Vec` would point to freed memory
+ mem::forget(self);
+ v
}
}
/// Trait for converting an ascii type to a string. Needed to convert
/// `&[Ascii]` to `&str`.
-pub trait AsciiStr {
+pub trait AsciiStr for Sized? {
/// Convert to a string.
fn as_str_ascii<'a>(&'a self) -> &'a str;
fn to_uppercase(&self) -> Vec<Ascii>;
/// Compares two Ascii strings ignoring case.
- fn eq_ignore_case(self, other: &[Ascii]) -> bool;
+ fn eq_ignore_case(&self, other: &[Ascii]) -> bool;
}
-impl<'a> AsciiStr for &'a [Ascii] {
+impl AsciiStr for [Ascii] {
#[inline]
fn as_str_ascii<'a>(&'a self) -> &'a str {
- unsafe { mem::transmute(*self) }
+ unsafe { mem::transmute(self) }
}
#[inline]
}
#[inline]
- fn eq_ignore_case(self, other: &[Ascii]) -> bool {
+ fn eq_ignore_case(&self, other: &[Ascii]) -> bool {
self.iter().zip(other.iter()).all(|(&a, &b)| a.eq_ignore_case(b))
}
}
#[inline]
fn into_string(self) -> String {
unsafe {
- let s: &str = mem::transmute(self.as_slice());
- String::from_str(s)
+ string::raw::from_utf8(self.into_bytes())
}
}
}
impl IntoBytes for Vec<Ascii> {
fn into_bytes(self) -> Vec<u8> {
- unsafe { mem::transmute(self) }
+ unsafe {
+ let v = Vec::from_raw_parts(self.as_ptr() as *mut u8,
+ self.len(),
+ self.capacity());
+
+ // We forget `self` to avoid freeing it at the end of the scope
+ // Otherwise, the returned `Vec` would point to freed memory
+ mem::forget(self);
+ v
+ }
}
}
}
/// Extension methods for ASCII-subset only operations on string slices
-pub trait AsciiExt<T> {
+pub trait AsciiExt<T> for Sized? {
/// Makes a copy of the string in ASCII upper case:
/// ASCII letters 'a' to 'z' are mapped to 'A' to 'Z',
/// but non-ASCII letters are unchanged.
/// Check that two strings are an ASCII case-insensitive match.
/// Same as `to_ascii_lower(a) == to_ascii_lower(b)`,
/// but without allocating and copying temporary strings.
- fn eq_ignore_ascii_case(&self, other: Self) -> bool;
+ fn eq_ignore_ascii_case(&self, other: &Self) -> bool;
}
-impl<'a> AsciiExt<String> for &'a str {
+impl AsciiExt<String> for str {
#[inline]
fn to_ascii_upper(&self) -> String {
// Vec<u8>::to_ascii_upper() preserves the UTF-8 invariant.
}
}
-impl<'a> AsciiExt<Vec<u8>> for &'a [u8] {
+impl AsciiExt<Vec<u8>> for [u8] {
#[inline]
fn to_ascii_upper(&self) -> Vec<u8> {
self.iter().map(|&byte| ASCII_UPPER_MAP[byte as uint]).collect()
}
#[test] #[should_fail]
- fn test_ascii_vec_fail_u8_slice() { (&[127u8, 128u8, 255u8]).to_ascii(); }
+ fn test_ascii_vec_panic_u8_slice() { (&[127u8, 128u8, 255u8]).to_ascii(); }
#[test] #[should_fail]
- fn test_ascii_vec_fail_str_slice() { "zoä华".to_ascii(); }
+ fn test_ascii_vec_panic_str_slice() { "zoä华".to_ascii(); }
#[test] #[should_fail]
- fn test_ascii_fail_u8_slice() { 255u8.to_ascii(); }
+ fn test_ascii_panic_u8_slice() { 255u8.to_ascii(); }
#[test] #[should_fail]
- fn test_ascii_fail_char_slice() { 'λ'.to_ascii(); }
+ fn test_ascii_panic_char_slice() { 'λ'.to_ascii(); }
#[test]
fn test_opt() {
fn malloc(n: uint) -> CVec<u8> {
unsafe {
let mem = libc::malloc(n as libc::size_t);
- if mem.is_null() { fail!("out of memory") }
+ if mem.is_null() { panic!("out of memory") }
CVec::new_with_dtor(mem as *mut u8, n,
proc() { libc::free(mem as *mut libc::c_void); })
#[test]
#[should_fail]
- fn test_fail_at_null() {
+ fn test_panic_at_null() {
unsafe {
CVec::new(ptr::null_mut::<u8>(), 9);
}
fn test_unwrap() {
unsafe {
let cv = CVec::new_with_dtor(1 as *mut int, 0,
- proc() { fail!("Don't run this destructor!") });
+ proc() { panic!("Don't run this destructor!") });
let p = cv.unwrap();
assert_eq!(p, 1 as *mut int);
}
// is also memory and cache pressure that this would entail that would be very
// difficult to properly see in a microbenchmark.
//
-// Future Improvements (FIXME!)
-// ============================
+// ## Future Improvements (FIXME!)
//
// Allow the load factor to be changed dynamically and/or at initialization.
//
// underlying table? This is exactly the use case for 'realloc', and may
// be worth exploring.
//
-// Future Optimizations (FIXME!)
-// =============================
+// ## Future Optimizations (FIXME!)
//
// Another possible design choice that I made without any real reason is
// parameterizing the raw table over keys and values. Technically, all we need
};
buckets.next();
}
- fail!("Internal HashMap error: Out of space.");
+ panic!("Internal HashMap error: Out of space.");
}
}
}
/// Retrieves a mutable value for the given key.
- /// See [`find_mut`](../trait.MutableMap.html#tymethod.find_mut) for a non-failing alternative.
+ /// See [`find_mut`](../trait.MutableMap.html#tymethod.find_mut) for a non-panicking
+ /// alternative.
///
/// # Failure
///
pub fn get_mut<'a>(&'a mut self, k: &K) -> &'a mut V {
match self.find_mut(k) {
Some(v) => v,
- None => fail!("no entry found for key")
+ None => panic!("no entry found for key")
}
}
assert!(m.insert(5i, 14i));
let new = 100;
match m.find_mut(&5) {
- None => fail!(), Some(x) => *x = new
+ None => panic!(), Some(x) => *x = new
}
assert_eq!(m.find(&5), Some(&new));
}
assert!(m.find(&1i).is_none());
m.insert(1i, 2i);
match m.find(&1) {
- None => fail!(),
+ None => panic!(),
Some(v) => assert_eq!(*v, 2)
}
}
for i in range(1i, 10000) {
m.insert(i, i + 7);
match m.find_copy(&i) {
- None => fail!(),
+ None => panic!(),
Some(v) => assert_eq!(v, i + 7)
}
for j in range(1i, i/100) {
match m.find_copy(&j) {
- None => fail!(),
+ None => panic!(),
Some(v) => assert_eq!(v, j + 7)
}
}
/// # Example
///
/// This is a slightly silly example where we define the number's
- /// parity as the equivilance class. It is important that the
+ /// parity as the equivalance class. It is important that the
/// values hash the same, which is why we implement `Hash`.
///
/// ```
pub fn expect_full(self) -> FullBucket<K, V, M> {
match self {
Full(full) => full,
- Empty(..) => fail!("Expected full bucket")
+ Empty(..) => panic!("Expected full bucket")
}
}
}
}
}) {
Ok(()) => {},
- Err(str) => fail!("{}", str)
+ Err(str) => panic!("{}", str)
}
}
}
// statically linked in
let none: Option<Path> = None; // appease the typechecker
let libm = match DynamicLibrary::open(none) {
- Err(error) => fail!("Could not load self as module: {}", error),
+ Err(error) => panic!("Could not load self as module: {}", error),
Ok(libm) => libm
};
let cosine: extern fn(libc::c_double) -> libc::c_double = unsafe {
match libm.symbol("cos") {
- Err(error) => fail!("Could not load function cos: {}", error),
+ Err(error) => panic!("Could not load function cos: {}", error),
Ok(cosine) => mem::transmute::<*mut u8, _>(cosine)
}
};
let expected_result = 1.0;
let result = cosine(argument);
if result != expected_result {
- fail!("cos({}) != {} but equaled {} instead", argument,
+ panic!("cos({}) != {} but equaled {} instead", argument,
expected_result, result)
}
}
let path = Path::new("/dev/null");
match DynamicLibrary::open(Some(&path)) {
Err(_) => {}
- Ok(_) => fail!("Successfully opened the empty library.")
+ Ok(_) => panic!("Successfully opened the empty library.")
}
}
}
// all times. This means that this `exists` will return true almost all of
// the time. There are border cases, however, when the runtime has
// *almost* set up the local task, but hasn't quite gotten there yet. In
- // order to get some better diagnostics, we print on failure and
+ // order to get some better diagnostics, we print on panic and
// immediately abort the whole process if there is no local task
// available.
if !Local::exists(None::<Task>) {
- let _ = writeln!(&mut err, "failed at '{}', {}:{}", msg, file, line);
+ let _ = writeln!(&mut err, "panicked at '{}', {}:{}", msg, file, line);
if backtrace::log_enabled() {
let _ = backtrace::write(&mut err);
} else {
match local_stderr.replace(None) {
Some(mut stderr) => {
- // FIXME: what to do when the task printing fails?
+ // FIXME: what to do when the task printing panics?
let _ = writeln!(stderr,
- "task '{}' failed at '{}', {}:{}\n",
+ "task '{}' panicked at '{}', {}:{}\n",
n, msg, file, line);
if backtrace::log_enabled() {
let _ = backtrace::write(&mut *stderr);
local_stderr.replace(Some(stderr));
}
None => {
- let _ = writeln!(&mut err, "task '{}' failed at '{}', {}:{}",
+ let _ = writeln!(&mut err, "task '{}' panicked at '{}', {}:{}",
n, msg, file, line);
if backtrace::log_enabled() {
let _ = backtrace::write(&mut err);
}
}
- // If this is a double failure, make sure that we printed a backtrace
- // for this failure.
+ // If this is a double panic, make sure that we printed a backtrace
+ // for this panic.
if unwinding && !backtrace::log_enabled() {
let _ = backtrace::write(&mut err);
}
/// # Example
///
/// ```rust
-/// # #![allow(unused_must_use)]
/// use std::io::{BufferedWriter, File};
///
-/// let file = File::open(&Path::new("message.txt"));
+/// let file = File::create(&Path::new("message.txt")).unwrap();
/// let mut writer = BufferedWriter::new(file);
///
-/// writer.write_str("hello, world");
-/// writer.flush();
+/// writer.write_str("hello, world").unwrap();
+/// writer.flush().unwrap();
/// ```
pub struct BufferedWriter<W> {
inner: Option<W>,
///
/// The buffer is flushed before returning the writer.
pub fn unwrap(mut self) -> W {
- // FIXME(#12628): is failing the right thing to do if flushing fails?
+ // FIXME(#12628): is panicking the right thing to do if flushing panicks?
self.flush_buf().unwrap();
self.inner.take().unwrap()
}
impl<W: Writer> Drop for BufferedWriter<W> {
fn drop(&mut self) {
if self.inner.is_some() {
- // dtors should not fail, so we ignore a failed flush
+ // dtors should not panic, so we ignore a panicked flush
let _ = self.flush_buf();
}
}
#[test]
#[should_fail]
- fn dont_fail_in_drop_on_failed_flush() {
+ fn dont_panic_in_drop_on_panicked_flush() {
struct FailFlushWriter;
impl Writer for FailFlushWriter {
let writer = FailFlushWriter;
let _writer = BufferedWriter::new(writer);
- // Trigger failure. If writer fails *again* due to the flush
- // error then the process will abort.
- fail!();
+ // If writer panics *again* due to the flush error then the process will abort.
+ panic!();
}
#[bench]
assert_eq!(a, buf.as_slice());
match reader.read(buf.as_mut_slice()) {
- Ok(..) => fail!(),
+ Ok(..) => panic!(),
Err(e) => assert_eq!(e.kind, io::EndOfFile),
}
assert_eq!(a, buf.as_slice());
- // Ensure it continues to fail in the same way.
+ // Ensure it continues to panic in the same way.
match reader.read(buf.as_mut_slice()) {
- Ok(..) => fail!(),
+ Ok(..) => panic!(),
Err(e) => assert_eq!(e.kind, io::EndOfFile),
}
assert_eq!(a, buf.as_slice());
assert_eq!(Ok("hello world\n".to_string()), reader.read_line());
assert_eq!(Ok("how are you?".to_string()), reader.read_line());
match reader.read_line() {
- Ok(..) => fail!(),
+ Ok(..) => panic!(),
Err(e) => assert_eq!(e.kind, io::EndOfFile),
}
}
let wanted = vec![0u8, 0u8, 0u8, 42u8];
let got = match task::try(proc() { rx.recv() }) {
Ok(got) => got,
- Err(_) => fail!(),
+ Err(_) => panic!(),
};
assert_eq!(wanted, got);
match writer.write_u8(1) {
- Ok(..) => fail!(),
+ Ok(..) => panic!(),
Err(e) => assert_eq!(e.kind, io::BrokenPipe),
}
}
///
/// * `n`: The value to convert.
/// * `size`: The size of the value, in bytes. This must be 8 or less, or task
-/// failure occurs. If this is less than 8, then a value of that
+/// panic occurs. If this is less than 8, then a value of that
/// many bytes is produced. For example, if `size` is 4, then a
/// 32-bit byte representation is produced.
/// * `f`: A callback that receives the value.
///
/// * `n`: The value to convert.
/// * `size`: The size of the value, in bytes. This must be 8 or less, or task
-/// failure occurs. If this is less than 8, then a value of that
+/// panic occurs. If this is less than 8, then a value of that
/// many bytes is produced. For example, if `size` is 4, then a
/// 32-bit byte representation is produced.
/// * `f`: A callback that receives the value.
/// * `data`: The buffer in which to extract the value.
/// * `start`: The offset at which to extract the value.
/// * `size`: The size of the value in bytes to extract. This must be 8 or
-/// less, or task failure occurs. If this is less than 8, then only
+/// less, or task panic occurs. If this is less than 8, then only
/// that many bytes are parsed. For example, if `size` is 4, then a
/// 32-bit value is parsed.
pub fn u64_from_be_bytes(data: &[u8], start: uint, size: uint) -> u64 {
assert!(size <= 8u);
if data.len() - start < size {
- fail!("index out of bounds");
+ panic!("index out of bounds");
}
let mut buf = [0u8, ..8];
mod test {
use prelude::*;
use io;
- use io::{MemReader, MemWriter};
+ use io::{MemReader, MemWriter, BytesReader};
struct InitialZeroByteReader {
count: int,
///
/// let file = match File::open_mode(&p, Open, ReadWrite) {
/// Ok(f) => f,
- /// Err(e) => fail!("file error: {}", e),
+ /// Err(e) => panic!("file error: {}", e),
/// };
/// // do some stuff with that file
///
macro_rules! check( ($e:expr) => (
match $e {
Ok(t) => t,
- Err(e) => fail!("{} failed with: {}", stringify!($e), e),
+ Err(e) => panic!("{} failed with: {}", stringify!($e), e),
}
) )
macro_rules! error( ($e:expr, $s:expr) => (
match $e {
- Ok(val) => fail!("Unexpected success. Should've been: {}", $s),
+ Ok(val) => panic!("Unexpected success. Should've been: {}", $s),
Err(ref err) => assert!(err.to_string().as_slice().contains($s.as_slice()),
format!("`{}` did not contain `{}`", err, $s))
}
let mut read_stream = File::open_mode(filename, Open, Read);
let mut read_buf = [0, .. 1028];
let read_str = match check!(read_stream.read(read_buf)) {
- -1|0 => fail!("shouldn't happen"),
+ -1|0 => panic!("shouldn't happen"),
n => str::from_utf8(read_buf[..n]).unwrap().to_string()
};
assert_eq!(read_str.as_slice(), message);
check!(File::open(f).read(mem));
let read_str = str::from_utf8(mem).unwrap();
let expected = match n {
- None|Some("") => fail!("really shouldn't happen.."),
+ None|Some("") => panic!("really shouldn't happen.."),
Some(n) => format!("{}{}", prefix, n),
};
assert_eq!(expected.as_slice(), read_str);
from.display(), to.display()));
match copy(&from, &to) {
- Ok(..) => fail!(),
+ Ok(..) => panic!(),
Err(..) => {
assert!(!from.exists());
assert!(!to.exists());
check!(File::create(&out));
match copy(&out, tmpdir.path()) {
- Ok(..) => fail!(), Err(..) => {}
+ Ok(..) => panic!(), Err(..) => {}
}
}
let out = tmpdir.join("out");
match copy(tmpdir.path(), &out) {
- Ok(..) => fail!(), Err(..) => {}
+ Ok(..) => panic!(), Err(..) => {}
}
assert!(!out.exists());
}
fn readlink_not_symlink() {
let tmpdir = tmpdir();
match readlink(tmpdir.path()) {
- Ok(..) => fail!("wanted a failure"),
+ Ok(..) => panic!("wanted a failure"),
Err(..) => {}
}
}
// can't link to yourself
match link(&input, &input) {
- Ok(..) => fail!("wanted a failure"),
+ Ok(..) => panic!("wanted a failure"),
Err(..) => {}
}
// can't link to something that doesn't exist
match link(&tmpdir.join("foo"), &tmpdir.join("bar")) {
- Ok(..) => fail!("wanted a failure"),
+ Ok(..) => panic!("wanted a failure"),
Err(..) => {}
}
}
assert!(!check!(stat(&file)).perm.contains(io::USER_WRITE));
match chmod(&tmpdir.join("foo"), io::USER_RWX) {
- Ok(..) => fail!("wanted a failure"),
+ Ok(..) => panic!("wanted a panic"),
Err(..) => {}
}
let tmpdir = tmpdir();
match File::open_mode(&tmpdir.join("a"), io::Open, io::Read) {
- Ok(..) => fail!(), Err(..) => {}
+ Ok(..) => panic!(), Err(..) => {}
}
// Perform each one twice to make sure that it succeeds the second time
let mut f = check!(File::open_mode(&tmpdir.join("h"), io::Open,
io::Read));
match f.write("wut".as_bytes()) {
- Ok(..) => fail!(), Err(..) => {}
+ Ok(..) => panic!(), Err(..) => {}
}
}
assert!(check!(stat(&tmpdir.join("h"))).size == 3,
let tmpdir = tmpdir();
match change_file_times(&tmpdir.join("a"), 100, 200) {
- Ok(..) => fail!(),
+ Ok(..) => panic!(),
Err(..) => {}
}
}
use slice::AsSlice;
use vec::Vec;
-static BUF_CAPACITY: uint = 128;
+const BUF_CAPACITY: uint = 128;
fn combine(seek: SeekStyle, cur: uint, end: uint, offset: i64) -> IoResult<u64> {
// compute offset as signed and clamp to prevent overflow
/// the internal buffer.
#[inline]
pub fn with_capacity(n: uint) -> MemWriter {
- MemWriter { buf: Vec::with_capacity(n) }
+ MemWriter::from_vec(Vec::with_capacity(n))
+ }
+ /// Create a new `MemWriter` that will append to an existing `Vec`.
+ #[inline]
+ pub fn from_vec(buf: Vec<u8>) -> MemWriter {
+ MemWriter { buf: buf }
}
/// Acquires an immutable reference to the underlying buffer of this
writer.write([0]).unwrap();
match writer.write([0, 0]) {
- Ok(..) => fail!(),
+ Ok(..) => panic!(),
Err(e) => assert_eq!(e.kind, io::OtherIoError),
}
}
let buf = [0xff];
let mut r = BufReader::new(buf);
match r.read_to_string() {
- Ok(..) => fail!(),
+ Ok(..) => panic!(),
Err(..) => {}
}
}
})
}
- /// Create an iterator that reads a single byte on
- /// each iteration, until EOF.
- ///
- /// # Error
- ///
- /// Any error other than `EndOfFile` that is produced by the underlying Reader
- /// is returned by the iterator and should be handled by the caller.
- fn bytes<'r>(&'r mut self) -> extensions::Bytes<'r, Self> {
- extensions::Bytes::new(self)
- }
-
// Byte conversion helpers
/// Reads `n` little-endian unsigned integer bytes.
fn read_i8(&mut self) -> IoResult<i8> {
self.read_byte().map(|i| i as i8)
}
+}
+/// A reader which can be converted to a RefReader.
+pub trait AsRefReader {
/// Creates a wrapper around a mutable reference to the reader.
///
/// This is useful to allow applying adaptors while still
/// retaining ownership of the original value.
- fn by_ref<'a>(&'a mut self) -> RefReader<'a, Self> {
+ fn by_ref<'a>(&'a mut self) -> RefReader<'a, Self>;
+}
+
+impl<T: Reader> AsRefReader for T {
+ fn by_ref<'a>(&'a mut self) -> RefReader<'a, T> {
RefReader { inner: self }
}
}
+/// A reader which can be converted to bytes.
+pub trait BytesReader {
+ /// Create an iterator that reads a single byte on
+ /// each iteration, until EOF.
+ ///
+ /// # Error
+ ///
+ /// Any error other than `EndOfFile` that is produced by the underlying Reader
+ /// is returned by the iterator and should be handled by the caller.
+ fn bytes<'r>(&'r mut self) -> extensions::Bytes<'r, Self>;
+}
+
+impl<T: Reader> BytesReader for T {
+ fn bytes<'r>(&'r mut self) -> extensions::Bytes<'r, T> {
+ extensions::Bytes::new(self)
+ }
+}
+
impl<'a> Reader for Box<Reader+'a> {
fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> {
let reader: &mut Reader = &mut **self;
/// # fn process_input<R: Reader>(r: R) {}
/// # fn foo() {
/// use std::io;
+/// use std::io::AsRefReader;
/// use std::io::util::LimitReader;
///
/// let mut stream = io::stdin();
fn write_i8(&mut self, n: i8) -> IoResult<()> {
self.write([n as u8])
}
+}
+/// A writer which can be converted to a RefWriter.
+pub trait AsRefWriter {
/// Creates a wrapper around a mutable reference to the writer.
///
/// This is useful to allow applying wrappers while still
/// retaining ownership of the original value.
#[inline]
- fn by_ref<'a>(&'a mut self) -> RefWriter<'a, Self> {
+ fn by_ref<'a>(&'a mut self) -> RefWriter<'a, Self>;
+}
+
+impl<T: Writer> AsRefWriter for T {
+ fn by_ref<'a>(&'a mut self) -> RefWriter<'a, T> {
RefWriter { inner: self }
}
}
/// # fn process_input<R: Reader>(r: R) {}
/// # fn foo () {
/// use std::io::util::TeeReader;
-/// use std::io::{stdin, MemWriter};
+/// use std::io::{stdin, MemWriter, AsRefWriter};
///
/// let mut output = MemWriter::new();
///
/// # fn foo() {
/// let info = match Path::new("foo.txt").stat() {
/// Ok(stat) => stat,
-/// Err(e) => fail!("couldn't read foo.txt: {}", e),
+/// Err(e) => panic!("couldn't read foo.txt: {}", e),
/// };
///
/// println!("byte size: {}", info.size);
spawn(proc() {
match UnixStream::connect(&path2) {
Ok(c) => client(c),
- Err(e) => fail!("failed connect: {}", e),
+ Err(e) => panic!("failed connect: {}", e),
}
});
match acceptor.accept() {
Ok(c) => server(c),
- Err(e) => fail!("failed accept: {}", e),
+ Err(e) => panic!("failed accept: {}", e),
}
}
fn bind_error() {
let path = "path/to/nowhere";
match UnixListener::bind(&path) {
- Ok(..) => fail!(),
+ Ok(..) => panic!(),
Err(e) => {
assert!(e.kind == PermissionDenied || e.kind == FileNotFound ||
e.kind == InvalidInput);
"path/to/nowhere"
};
match UnixStream::connect(&path) {
- Ok(..) => fail!(),
+ Ok(..) => panic!(),
Err(e) => {
assert!(e.kind == FileNotFound || e.kind == OtherIoError);
}
let mut acceptor = match UnixListener::bind(&path1).listen() {
Ok(a) => a,
- Err(e) => fail!("failed listen: {}", e),
+ Err(e) => panic!("failed listen: {}", e),
};
spawn(proc() {
let mut stream = UnixStream::connect(&path2);
match stream.write([100]) {
Ok(..) => {}
- Err(e) => fail!("failed write: {}", e)
+ Err(e) => panic!("failed write: {}", e)
}
}
});
let mut buf = [0];
match client.read(buf) {
Ok(..) => {}
- Err(e) => fail!("failed read/accept: {}", e),
+ Err(e) => panic!("failed read/accept: {}", e),
}
assert_eq!(buf[0], 100);
}
match a.accept() {
Ok(..) => break,
Err(ref e) if e.kind == TimedOut => {}
- Err(e) => fail!("error: {}", e),
+ Err(e) => panic!("error: {}", e),
}
::task::deschedule();
- if i == 1000 { fail!("should have a pending connection") }
+ if i == 1000 { panic!("should have a pending connection") }
}
drop(l);
match s.write([0, .. 128 * 1024]) {
Ok(()) | Err(IoError { kind: ShortWrite(..), .. }) => {},
Err(IoError { kind: TimedOut, .. }) => break,
- Err(e) => fail!("{}", e),
+ Err(e) => panic!("{}", e),
}
- if i == 1000 { fail!("should have filled up?!"); }
+ if i == 1000 { panic!("should have filled up?!"); }
}
// I'm not sure as to why, but apparently the write on windows always
while amt < 100 * 128 * 1024 {
match s.read([0, ..128 * 1024]) {
Ok(n) => { amt += n; }
- Err(e) => fail!("{}", e),
+ Err(e) => panic!("{}", e),
}
}
let _ = rx.recv_opt();
match s.write([0, .. 128 * 1024]) {
Ok(()) | Err(IoError { kind: ShortWrite(..), .. }) => {},
Err(IoError { kind: TimedOut, .. }) => break,
- Err(e) => fail!("{}", e),
+ Err(e) => panic!("{}", e),
}
- if i == 1000 { fail!("should have filled up?!"); }
+ if i == 1000 { panic!("should have filled up?!"); }
}
tx.send(());
/// match socket {
/// Ok(s) => { /* handle s */ }
/// Err(ref e) if e.kind == EndOfFile => break, // closed
- /// Err(e) => fail!("unexpected error: {}", e),
+ /// Err(e) => panic!("unexpected error: {}", e),
/// }
/// }
/// });
#[test]
fn bind_error() {
match TcpListener::bind("0.0.0.0", 1) {
- Ok(..) => fail!(),
+ Ok(..) => panic!(),
Err(e) => assert_eq!(e.kind, PermissionDenied),
}
}
#[test]
fn connect_error() {
match TcpStream::connect("0.0.0.0", 1) {
- Ok(..) => fail!(),
+ Ok(..) => panic!(),
Err(e) => assert_eq!(e.kind, ConnectionRefused),
}
}
assert!(nread.is_err());
match stream.read(buf) {
- Ok(..) => fail!(),
+ Ok(..) => panic!(),
Err(ref e) => {
assert!(e.kind == NotConnected || e.kind == EndOfFile,
"unknown kind: {}", e.kind);
assert!(nread.is_err());
match stream.read(buf) {
- Ok(..) => fail!(),
+ Ok(..) => panic!(),
Err(ref e) => {
assert!(e.kind == NotConnected || e.kind == EndOfFile,
"unknown kind: {}", e.kind);
let listener = TcpListener::bind(ip_str.as_slice(), port).unwrap().listen();
assert!(listener.is_ok());
match TcpListener::bind(ip_str.as_slice(), port).listen() {
- Ok(..) => fail!(),
+ Ok(..) => panic!(),
Err(e) => {
assert!(e.kind == ConnectionRefused || e.kind == OtherIoError,
"unknown error: {} {}", e, e.kind);
match a.accept() {
Ok(..) => break,
Err(ref e) if e.kind == TimedOut => {}
- Err(e) => fail!("error: {}", e),
+ Err(e) => panic!("error: {}", e),
}
::task::deschedule();
- if i == 1000 { fail!("should have a pending connection") }
+ if i == 1000 { panic!("should have a pending connection") }
}
}
match s.write([0, .. 128 * 1024]) {
Ok(()) | Err(IoError { kind: ShortWrite(..), .. }) => {},
Err(IoError { kind: TimedOut, .. }) => break,
- Err(e) => fail!("{}", e),
+ Err(e) => panic!("{}", e),
}
- if i == 1000 { fail!("should have filled up?!"); }
+ if i == 1000 { panic!("should have filled up?!"); }
}
assert_eq!(s.write([0]).err().unwrap().kind, TimedOut);
while amt < 100 * 128 * 1024 {
match s.read([0, ..128 * 1024]) {
Ok(n) => { amt += n; }
- Err(e) => fail!("{}", e),
+ Err(e) => panic!("{}", e),
}
}
let _ = rx.recv_opt();
match s.write([0, .. 128 * 1024]) {
Ok(()) | Err(IoError { kind: ShortWrite(..), .. }) => {},
Err(IoError { kind: TimedOut, .. }) => break,
- Err(e) => fail!("{}", e),
+ Err(e) => panic!("{}", e),
}
- if i == 1000 { fail!("should have filled up?!"); }
+ if i == 1000 { panic!("should have filled up?!"); }
}
assert_eq!(s.write([0]).err().unwrap().kind, TimedOut);
/// let addr = SocketAddr { ip: Ipv4Addr(127, 0, 0, 1), port: 34254 };
/// let mut socket = match UdpSocket::bind(addr) {
/// Ok(s) => s,
-/// Err(e) => fail!("couldn't bind socket: {}", e),
+/// Err(e) => panic!("couldn't bind socket: {}", e),
/// };
///
/// let mut buf = [0, ..10];
fn bind_error() {
let addr = SocketAddr { ip: Ipv4Addr(0, 0, 0, 0), port: 1 };
match UdpSocket::bind(addr) {
- Ok(..) => fail!(),
+ Ok(..) => panic!(),
Err(e) => assert_eq!(e.kind, PermissionDenied),
}
}
rx1.recv();
client.send_to([99], server_ip).unwrap()
}
- Err(..) => fail!()
+ Err(..) => panic!()
}
tx2.send(());
});
assert_eq!(buf[0], 99);
assert_eq!(src, client_ip);
}
- Err(..) => fail!()
+ Err(..) => panic!()
}
}
- Err(..) => fail!()
+ Err(..) => panic!()
}
rx2.recv();
}
rx.recv();
client.send_to([99], server_ip).unwrap()
}
- Err(..) => fail!()
+ Err(..) => panic!()
}
});
assert_eq!(buf[0], 99);
assert_eq!(src, client_ip);
}
- Err(..) => fail!()
+ Err(..) => panic!()
}
}
- Err(..) => fail!()
+ Err(..) => panic!()
}
}
let mut stream = client.connect(server_ip);
stream.write(val).unwrap();
}
- Err(..) => fail!()
+ Err(..) => panic!()
}
};
rx1.recv();
assert_eq!(nread, 1);
assert_eq!(buf[0], 99);
}
- Err(..) => fail!(),
+ Err(..) => panic!(),
}
}
- Err(..) => fail!()
+ Err(..) => panic!()
}
rx2.recv();
}
rx1.recv();
stream.write([99]).unwrap();
}
- Err(..) => fail!()
+ Err(..) => panic!()
}
tx2.send(());
});
assert_eq!(nread, 1);
assert_eq!(buf[0], 99);
}
- Err(..) => fail!()
+ Err(..) => panic!()
}
}
- Err(..) => fail!()
+ Err(..) => panic!()
}
rx2.recv();
}
rx.recv();
match sock2.recv_from(buf) {
Ok(..) => {}
- Err(e) => fail!("failed receive: {}", e),
+ Err(e) => panic!("failed receive: {}", e),
}
serv_tx.send(());
});
match a.send_to([0, ..4*1024], addr2) {
Ok(()) | Err(IoError { kind: ShortWrite(..), .. }) => {},
Err(IoError { kind: TimedOut, .. }) => break,
- Err(e) => fail!("other error: {}", e),
+ Err(e) => panic!("other error: {}", e),
}
}
}
///
/// let mut child = match Command::new("/bin/cat").arg("file.txt").spawn() {
/// Ok(child) => child,
-/// Err(e) => fail!("failed to execute child: {}", e),
+/// Err(e) => panic!("failed to execute child: {}", e),
/// };
///
/// let contents = child.stdout.as_mut().unwrap().read_to_end();
///
/// let mut process = match Command::new("sh").arg("-c").arg("echo hello").spawn() {
/// Ok(p) => p,
-/// Err(e) => fail!("failed to execute process: {}", e),
+/// Err(e) => panic!("failed to execute process: {}", e),
/// };
///
/// let output = process.stdout.as_mut().unwrap().read_to_end();
///
/// let output = match Command::new("cat").arg("foot.txt").output() {
/// Ok(output) => output,
- /// Err(e) => fail!("failed to execute process: {}", e),
+ /// Err(e) => panic!("failed to execute process: {}", e),
/// };
///
/// println!("status: {}", output.status);
///
/// let status = match Command::new("ls").status() {
/// Ok(status) => status,
- /// Err(e) => fail!("failed to execute process: {}", e),
+ /// Err(e) => panic!("failed to execute process: {}", e),
/// };
///
/// println!("process exited with: {}", status);
#[test]
fn smoke_failure() {
match Command::new("if-this-is-a-binary-then-the-world-has-ended").spawn() {
- Ok(..) => fail!(),
+ Ok(..) => panic!(),
Err(..) => {}
}
}
let mut p = p.unwrap();
match p.wait().unwrap() {
process::ExitSignal(1) => {},
- result => fail!("not terminated by signal 1 (instead, {})", result),
+ result => panic!("not terminated by signal 1 (instead, {})", result),
}
}
fn test_process_output_fail_to_start() {
match Command::new("/no-binary-by-this-name-should-exist").output() {
Err(e) => assert_eq!(e.kind, FileNotFound),
- Ok(..) => fail!()
+ Ok(..) => panic!()
}
}
}
timer::sleep(Duration::milliseconds(100));
}
- fail!("never saw the child go away");
+ panic!("never saw the child go away");
}
#[test]
let mut fdes = match file::open(&path.to_c_str(), Truncate, Write) {
Ok(f) => f,
- Err(_) => fail!("failed to open file descriptor"),
+ Err(_) => panic!("failed to open file descriptor"),
};
let mut cmd = pwd_cmd();
Err(io::standard_error(io::EndOfFile));
match writer.write([0, 0, 0]) {
- Ok(..) => fail!(),
+ Ok(..) => panic!(),
Err(e) => assert_eq!(e.kind, io::EndOfFile),
}
match writer.flush() {
- Ok(..) => fail!(),
+ Ok(..) => panic!(),
Err(e) => assert_eq!(e.kind, io::EndOfFile),
}
}
let mut buf = [];
match reader.read(buf) {
- Ok(..) => fail!(),
+ Ok(..) => panic!(),
Err(e) => assert_eq!(e.kind, io::EndOfFile),
}
}
/// Resets the task-local stderr handle to the specified writer
///
/// This will replace the current task's stderr handle, returning the old
-/// handle. Currently, the stderr handle is used for printing failure messages
-/// during task failure.
+/// handle. Currently, the stderr handle is used for printing panic messages
+/// during task panic.
///
/// Note that this does not need to be called for all new tasks; the default
/// output handle is to the process's stderr stream.
};
match result {
Ok(()) => {}
- Err(e) => fail!("failed printing to stdout: {}", e),
+ Err(e) => panic!("failed printing to stdout: {}", e),
}
}
let (mut r, w) = (ChanReader::new(rx), ChanWriter::new(tx));
spawn(proc() {
::realstd::io::stdio::set_stderr(box w);
- fail!("my special message");
+ panic!("my special message");
});
let s = r.read_to_string().unwrap();
assert!(s.as_slice().contains("my special message"));
if sysctl(&mut mib[0], 2, &mut maxfiles as *mut libc::c_int as *mut libc::c_void, &mut size,
null_mut(), 0) != 0 {
let err = last_os_error();
- fail!("raise_fd_limit: error calling sysctl: {}", err);
+ panic!("raise_fd_limit: error calling sysctl: {}", err);
}
// Fetch the current resource limits
let mut rlim = rlimit{rlim_cur: 0, rlim_max: 0};
if getrlimit(RLIMIT_NOFILE, &mut rlim) != 0 {
let err = last_os_error();
- fail!("raise_fd_limit: error calling getrlimit: {}", err);
+ panic!("raise_fd_limit: error calling getrlimit: {}", err);
}
// Bump the soft limit to the smaller of kern.maxfilesperproc and the hard limit
// Set our newly-increased resource limit
if setrlimit(RLIMIT_NOFILE, &rlim) != 0 {
let err = last_os_error();
- fail!("raise_fd_limit: error calling setrlimit: {}", err);
+ panic!("raise_fd_limit: error calling setrlimit: {}", err);
}
}
}
fn oneshot_fail() {
let mut timer = Timer::new().unwrap();
let _rx = timer.oneshot(Duration::milliseconds(1));
- fail!();
+ panic!();
}
#[test]
fn period_fail() {
let mut timer = Timer::new().unwrap();
let _rx = timer.periodic(Duration::milliseconds(1));
- fail!();
+ panic!();
}
#[test]
#[should_fail]
fn normal_fail() {
let _timer = Timer::new().unwrap();
- fail!();
+ panic!();
}
#[test]
#[cfg(test)]
mod test {
- use io::{MemReader, MemWriter, BufReader};
+ use io::{MemReader, MemWriter, BufReader, AsRefReader};
use io;
use boxed::Box;
use super::*;
//! Finally, the [`prelude`](prelude/index.html) defines a
//! common set of traits, types, and functions that are made available
//! to all code by default. [`macros`](macros/index.html) contains
-//! all the standard macros, such as `assert!`, `fail!`, `println!`,
+//! all the standard macros, such as `assert!`, `panic!`, `println!`,
//! and `format!`, also available to all Rust code.
#![crate_name = "std"]
pub use io; // used for println!()
pub use local_data; // used for local_data_key!()
pub use option; // used for bitflags!{}
- pub use rt; // used for fail!()
+ pub use rt; // used for panic!()
pub use vec; // used for vec![]
// The test runner calls ::std::os::args() but really wants realstd
#![experimental]
#![macro_escape]
-/// The entry point for failure of rust tasks.
+/// The entry point for panic of Rust tasks.
///
-/// This macro is used to inject failure into a rust task, causing the task to
-/// unwind and fail entirely. Each task's failure can be reaped as the
-/// `Box<Any>` type, and the single-argument form of the `fail!` macro will be
+/// This macro is used to inject panic into a Rust task, causing the task to
+/// unwind and panic entirely. Each task's panic can be reaped as the
+/// `Box<Any>` type, and the single-argument form of the `panic!` macro will be
/// the value which is transmitted.
///
-/// The multi-argument form of this macro fails with a string and has the
+/// The multi-argument form of this macro panics with a string and has the
/// `format!` syntax for building a string.
///
/// # Example
///
/// ```should_fail
/// # #![allow(unreachable_code)]
-/// fail!();
-/// fail!("this is a terrible mistake!");
-/// fail!(4i); // fail with the value of 4 to be collected elsewhere
-/// fail!("this is a {} {message}", "fancy", message = "message");
+/// panic!();
+/// panic!("this is a terrible mistake!");
+/// panic!(4i); // panic with the value of 4 to be collected elsewhere
+/// panic!("this is a {} {message}", "fancy", message = "message");
/// ```
#[macro_export]
-macro_rules! fail(
+macro_rules! panic(
() => ({
- fail!("explicit failure")
+ panic!("explicit panic")
});
($msg:expr) => ({
// static requires less code at runtime, more constant data
// as returning !. We really do want this to be inlined, however,
// because it's just a tiny wrapper. Small wins (156K to 149K in size)
// were seen when forcing this to be inlined, and that number just goes
- // up with the number of calls to fail!()
+ // up with the number of calls to panic!()
//
// The leading _'s are to avoid dead code warnings if this is
// used inside a dead function. Just `#[allow(dead_code)]` is
/// Ensure that a boolean expression is `true` at runtime.
///
-/// This will invoke the `fail!` macro if the provided expression cannot be
+/// This will invoke the `panic!` macro if the provided expression cannot be
/// evaluated to `true` at runtime.
///
/// # Example
///
/// ```
-/// // the failure message for these assertions is the stringified value of the
+/// // the panic message for these assertions is the stringified value of the
/// // expression given.
/// assert!(true);
/// # fn some_computation() -> bool { true }
macro_rules! assert(
($cond:expr) => (
if !$cond {
- fail!(concat!("assertion failed: ", stringify!($cond)))
+ panic!(concat!("assertion failed: ", stringify!($cond)))
}
);
($cond:expr, $($arg:expr),+) => (
if !$cond {
- fail!($($arg),+)
+ panic!($($arg),+)
}
);
)
/// Asserts that two expressions are equal to each other, testing equality in
/// both directions.
///
-/// On failure, this macro will print the values of the expressions.
+/// On panic, this macro will print the values of the expressions.
///
/// # Example
///
// check both directions of equality....
if !((*given_val == *expected_val) &&
(*expected_val == *given_val)) {
- fail!("assertion failed: `(left == right) && (right == left)` \
+ panic!("assertion failed: `(left == right) && (right == left)` \
(left: `{}`, right: `{}`)", *given_val, *expected_val)
}
}
/// Ensure that a boolean expression is `true` at runtime.
///
-/// This will invoke the `fail!` macro if the provided expression cannot be
+/// This will invoke the `panic!` macro if the provided expression cannot be
/// evaluated to `true` at runtime.
///
/// Unlike `assert!`, `debug_assert!` statements can be disabled by passing
/// # Example
///
/// ```
-/// // the failure message for these assertions is the stringified value of the
+/// // the panic message for these assertions is the stringified value of the
/// // expression given.
/// debug_assert!(true);
/// # fn some_expensive_computation() -> bool { true }
/// Asserts that two expressions are equal to each other, testing equality in
/// both directions.
///
-/// On failure, this macro will print the values of the expressions.
+/// On panic, this macro will print the values of the expressions.
///
/// Unlike `assert_eq!`, `debug_assert_eq!` statements can be disabled by
/// passing `--cfg ndebug` to the compiler. This makes `debug_assert_eq!`
($($arg:tt)*) => (if cfg!(not(ndebug)) { assert_eq!($($arg)*); })
)
-/// A utility macro for indicating unreachable code. It will fail if
+/// A utility macro for indicating unreachable code. It will panic if
/// executed. This is occasionally useful to put after loops that never
/// terminate normally, but instead directly return from a function.
///
/// ```
#[macro_export]
macro_rules! unreachable(
- () => (fail!("internal error: entered unreachable code"))
+ () => (panic!("internal error: entered unreachable code"))
)
-/// A standardised placeholder for marking unfinished code. It fails with the
+/// A standardised placeholder for marking unfinished code. It panics with the
/// message `"not yet implemented"` when executed.
#[macro_export]
macro_rules! unimplemented(
- () => (fail!("not yet implemented"))
+ () => (panic!("not yet implemented"))
)
/// Use the syntax described in `std::fmt` to create a value of type `String`.
assert!(2 <= radix && radix <= 36);
match exp_format {
ExpDec if radix >= DIGIT_E_RADIX // decimal exponent 'e'
- => fail!("float_to_str_bytes_common: radix {} incompatible with \
+ => panic!("float_to_str_bytes_common: radix {} incompatible with \
use of 'e' as decimal exponent", radix),
ExpBin if radix >= DIGIT_P_RADIX // binary exponent 'p'
- => fail!("float_to_str_bytes_common: radix {} incompatible with \
+ => panic!("float_to_str_bytes_common: radix {} incompatible with \
use of 'p' as binary exponent", radix),
_ => ()
}
) -> Option<T> {
match exponent {
ExpDec if radix >= DIGIT_E_RADIX // decimal exponent 'e'
- => fail!("from_str_bytes_common: radix {} incompatible with \
+ => panic!("from_str_bytes_common: radix {} incompatible with \
use of 'e' as decimal exponent", radix),
ExpBin if radix >= DIGIT_P_RADIX // binary exponent 'p'
- => fail!("from_str_bytes_common: radix {} incompatible with \
+ => panic!("from_str_bytes_common: radix {} incompatible with \
use of 'p' as binary exponent", radix),
_ if special && radix >= DIGIT_I_RADIX // first digit of 'inf'
- => fail!("from_str_bytes_common: radix {} incompatible with \
+ => panic!("from_str_bytes_common: radix {} incompatible with \
special values 'inf' and 'NaN'", radix),
_ if (radix as int) < 2
- => fail!("from_str_bytes_common: radix {} to low, \
+ => panic!("from_str_bytes_common: radix {} to low, \
must lie in the range [2, 36]", radix),
_ if (radix as int) > 36
- => fail!("from_str_bytes_common: radix {} to high, \
+ => panic!("from_str_bytes_common: radix {} to high, \
must lie in the range [2, 36]", radix),
_ => ()
}
let mut buf = [0 as c_char, ..BUF_BYTES];
unsafe {
if libc::getcwd(buf.as_mut_ptr(), buf.len() as libc::size_t).is_null() {
- fail!()
+ panic!()
}
Path::new(CString::new(buf.as_ptr(), false))
}
let mut buf = [0 as u16, ..BUF_BYTES];
unsafe {
if libc::GetCurrentDirectoryW(buf.len() as DWORD, buf.as_mut_ptr()) == 0 as DWORD {
- fail!();
+ panic!();
}
}
Path::new(String::from_utf16(::str::truncate_utf16_at_nul(buf))
};
let ch = GetEnvironmentStringsW();
if ch as uint == 0 {
- fail!("os::env() failure getting env string from OS: {}",
+ panic!("os::env() failure getting env string from OS: {}",
os::last_os_error());
}
// Here, we lossily decode the string as UTF16.
}
let mut environ = rust_env_pairs();
if environ as uint == 0 {
- fail!("os::env() failure getting env string from OS: {}",
+ panic!("os::env() failure getting env string from OS: {}",
os::last_os_error());
}
let mut result = Vec::new();
let p = buf.as_mut_ptr();
unsafe {
if strerror_r(errnum as c_int, p, buf.len() as libc::size_t) < 0 {
- fail!("strerror_r failure");
+ panic!("strerror_r failure");
}
::string::raw::from_buf(p as *const u8)
* Sets the process exit code
*
* Sets the exit code returned by the process if all supervised tasks
- * terminate successfully (without failing). If the current root task fails
+ * terminate successfully (without panicking). If the current root task panics
* and is supervised by the scheduler then any user-specified exit status is
- * ignored and the process exits with the default failure status.
+ * ignored and the process exits with the default panic status.
*
* Note that this is not synchronized against modifications of other threads.
*/
match rt::args::clone() {
Some(args) => args,
- None => fail!("process arguments not initialized")
+ None => panic!("process arguments not initialized")
}
}
#[cfg(unix)]
impl Drop for MemoryMap {
- /// Unmap the mapping. Fails the task if `munmap` fails.
+ /// Unmap the mapping. Panics the task if `munmap` panics.
fn drop(&mut self) {
if self.len == 0 { /* workaround for dummy_stack */ return; }
unsafe {
- // `munmap` only fails due to logic errors
+ // `munmap` only panics due to logic errors
libc::munmap(self.data as *mut c_void, self.len as libc::size_t);
}
}
os::MapWritable
]) {
Ok(chunk) => chunk,
- Err(msg) => fail!("{}", msg)
+ Err(msg) => panic!("{}", msg)
};
assert!(chunk.len >= 16);
MapOffset(size / 2)
]) {
Ok(chunk) => chunk,
- Err(msg) => fail!("{}", msg)
+ Err(msg) => panic!("{}", msg)
};
assert!(chunk.len > 0);
/// Returns a normalized byte vector representation of a path, by removing all empty
/// components, and unnecessary . and .. components.
- fn normalize<V: AsSlice<u8>+CloneableVector<u8>>(v: V) -> Vec<u8> {
+ fn normalize<V: AsSlice<u8>>(v: V) -> Vec<u8> {
// borrowck is being very picky
let val = {
let is_abs = !v.as_slice().is_empty() && v.as_slice()[0] == SEP_BYTE;
#[test]
#[should_fail]
- fn test_not_utf8_fail() {
+ fn test_not_utf8_panics() {
Path::new(b"hello\x80.txt");
}
#[doc(no_inline)] pub use num::{FloatMath, ToPrimitive, FromPrimitive};
#[doc(no_inline)] pub use boxed::Box;
#[doc(no_inline)] pub use path::{GenericPath, Path, PosixPath, WindowsPath};
-#[doc(no_inline)] pub use ptr::RawPtr;
+#[doc(no_inline)] pub use ptr::{RawPtr, RawMutPtr};
#[doc(no_inline)] pub use io::{Buffer, Writer, Reader, Seek};
#[doc(no_inline)] pub use str::{Str, StrVector, StrSlice};
#[doc(no_inline)] pub use str::{IntoMaybeOwned, StrAllocating, UnicodeStrSlice};
pub fn weak_rng() -> XorShiftRng {
match OsRng::new() {
Ok(mut r) => r.gen(),
- Err(e) => fail!("weak_rng: failed to create seeded RNG: {}", e)
+ Err(e) => panic!("weak_rng: failed to create seeded RNG: {}", e)
}
}
fn reseed(&mut self, rng: &mut StdRng) {
*rng = match StdRng::new() {
Ok(r) => r,
- Err(e) => fail!("could not reseed task_rng: {}", e)
+ Err(e) => panic!("could not reseed task_rng: {}", e)
}
}
}
None => {
let r = match StdRng::new() {
Ok(r) => r,
- Err(e) => fail!("could not initialize task_rng: {}", e)
+ Err(e) => panic!("could not initialize task_rng: {}", e)
};
let rng = reseeding::ReseedingRng::new(r,
TASK_RNG_RESEED_THRESHOLD,
// use this to get nicer error messages.
for (i, &byte) in v.iter().enumerate() {
if byte == 0 {
- fail!("byte {} of {} is zero", i, n)
+ panic!("byte {} of {} is zero", i, n)
}
}
}
#[test]
#[should_fail]
- fn test_gen_range_fail_int() {
+ fn test_gen_range_panic_int() {
let mut r = task_rng();
r.gen_range(5i, -2);
}
#[test]
#[should_fail]
- fn test_gen_range_fail_uint() {
+ fn test_gen_range_panic_uint() {
let mut r = task_rng();
r.gen_range(5u, 2u);
}
SecRandomCopyBytes(kSecRandomDefault, v.len() as size_t, v.as_mut_ptr())
};
if ret == -1 {
- fail!("couldn't generate random bytes: {}", os::last_os_error());
+ panic!("couldn't generate random bytes: {}", os::last_os_error());
}
}
}
v.as_mut_ptr())
};
if ret == 0 {
- fail!("couldn't generate random bytes: {}", os::last_os_error());
+ panic!("couldn't generate random bytes: {}", os::last_os_error());
}
}
}
CryptReleaseContext(self.hcryptprov, 0)
};
if ret == 0 {
- fail!("couldn't release context: {}", os::last_os_error());
+ panic!("couldn't release context: {}", os::last_os_error());
}
}
}
/// An RNG that reads random bytes straight from a `Reader`. This will
/// work best with an infinite reader, but this is not required.
///
-/// It will fail if it there is insufficient data to fulfill a request.
+/// # Panics
+///
+/// It will panic if it there is insufficient data to fulfill a request.
///
/// # Example
///
if v.len() == 0 { return }
match self.reader.read_at_least(v.len(), v) {
Ok(_) => {}
- Err(e) => fail!("ReaderRng.fill_bytes error: {}", e)
+ Err(e) => panic!("ReaderRng.fill_bytes error: {}", e)
}
}
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-//! Simple backtrace functionality (to print on failure)
+//! Simple backtrace functionality (to print on panic)
#![allow(non_camel_case_types)]
// while it doesn't requires lock for work as everything is
// local, it still displays much nicer backtraces when a
- // couple of tasks fail simultaneously
+ // couple of tasks panic simultaneously
static LOCK: StaticNativeMutex = NATIVE_MUTEX_INIT;
let _g = unsafe { LOCK.lock() };
// FindEnclosingFunction on non-osx platforms. In doing so, we get a
// slightly more accurate stack trace in the process.
//
- // This is often because failure involves the last instruction of a
+ // This is often because panic involves the last instruction of a
// function being "call std::rt::begin_unwind", with no ret
// instructions after it. This means that the return instruction
// pointer points *outside* of the calling function, and by
pub use rustrt::{Stdio, Stdout, Stderr, begin_unwind, begin_unwind_fmt};
pub use rustrt::{bookkeeping, at_exit, unwind, DEFAULT_ERROR_CODE, Runtime};
-// Simple backtrace functionality (to print on failure)
+// Simple backtrace functionality (to print on panic)
pub mod backtrace;
// Just stuff
let opt_n: Option<uint> = FromStr::from_str(nstr.as_slice());
match opt_n {
Some(n) if n > 0 => n,
- _ => fail!("`RUST_THREADS` is `{}`, should be a positive integer", nstr)
+ _ => panic!("`RUST_THREADS` is `{}`, should be a positive integer", nstr)
}
}
None => {
let state = replace(&mut self.state, Evaluating);
match state {
Forced(v) => v,
- _ => fail!( "Logic error." ),
+ _ => panic!( "Logic error." ),
}
}
*/
match self.state {
Forced(ref v) => return v,
- Evaluating => fail!("Recursive forcing of future!"),
+ Evaluating => panic!("Recursive forcing of future!"),
Pending(_) => {
match replace(&mut self.state, Evaluating) {
- Forced(_) | Evaluating => fail!("Logic error."),
+ Forced(_) | Evaluating => panic!("Logic error."),
Pending(f) => {
self.state = Forced(f());
self.get_ref()
let (tx, rx) = channel();
spawn(proc() {
- // Don't fail if the other end has hung up
+ // Don't panic if the other end has hung up
let _ = tx.send_opt(blk());
});
#[test]
#[should_fail]
- fn test_futurefail() {
- let mut f = Future::spawn(proc() fail!());
+ fn test_future_panic() {
+ let mut f = Future::spawn(proc() panic!());
let _x: String = f.get();
}
}
#[test]
- fn test_dropped_future_doesnt_fail() {
+ fn test_dropped_future_doesnt_panic() {
struct Bomb(Sender<bool>);
local_data_key!(LOCAL: Bomb)
}
// Spawn a future, but drop it immediately. When we receive the result
- // later on, we should never view the task as having failed.
+ // later on, we should never view the task as having panicked.
let (tx, rx) = channel();
drop(Future::spawn(proc() {
LOCAL.replace(Some(Bomb(tx)));
}));
- // Make sure the future didn't fail the task.
+ // Make sure the future didn't panic the task.
assert!(!rx.recv());
}
}
/// `init_fn_factory` returns a function which, given the index of the
/// task, should return local data to be kept around in that task.
///
- /// # Failure
+ /// # Panics
///
- /// This function will fail if `n_tasks` is less than 1.
+ /// This function will panic if `n_tasks` is less than 1.
pub fn new(n_tasks: uint,
init_fn_factory: || -> proc(uint):Send -> T)
-> TaskPool<T> {
#[test]
#[should_fail]
-fn test_zero_tasks_failure() {
+fn test_zero_tasks_panic() {
let f: || -> proc(uint):Send -> uint = || { proc(i) i };
TaskPool::new(0, f);
}
//! using the atomically-reference-counted container,
//! [`Arc`](../../std/sync/struct.Arc.html).
//!
-//! Fatal logic errors in Rust cause *task failure*, during which
+//! Fatal logic errors in Rust cause *task panic*, during which
//! a task will unwind the stack, running destructors and freeing
-//! owned resources. Task failure is unrecoverable from within
-//! the failing task (i.e. there is no 'try/catch' in Rust), but
-//! failure may optionally be detected from a different task. If
-//! the main task fails the application will exit with a non-zero
+//! owned resources. Task panic is unrecoverable from within
+//! the panicking task (i.e. there is no 'try/catch' in Rust), but
+//! panic may optionally be detected from a different task. If
+//! the main task panics the application will exit with a non-zero
//! exit code.
//!
//! # Basic task scheduling
let tb: Option<Box<Task>> = Local::try_take();
match tb {
Some(t) => t.spawn_sibling(opts, f),
- None => fail!("need a local task to spawn a sibling task"),
+ None => panic!("need a local task to spawn a sibling task"),
};
}
}
// sidestep that whole issue by making builders uncopyable and making
// the run function move them in.
pub struct TaskBuilder<S = SiblingSpawner> {
- // A name for the task-to-be, for identification in failure messages
+ // A name for the task-to-be, for identification in panic messages
name: Option<SendStr>,
// The size of the stack for the spawned task
stack_size: Option<uint>,
impl<S: Spawner> TaskBuilder<S> {
/// Name the task-to-be. Currently the name is used for identification
- /// only in failure messages.
+ /// only in panic messages.
#[unstable = "IntoMaybeOwned will probably change."]
pub fn named<T: IntoMaybeOwned<'static>>(mut self, name: T) -> TaskBuilder<S> {
self.name = Some(name.into_maybe_owned());
///
/// # Return value
///
- /// If the child task executes successfully (without failing) then the
+ /// If the child task executes successfully (without panicking) then the
/// future returns `result::Ok` containing the value returned by the
- /// function. If the child task fails then the future returns `result::Err`
- /// containing the argument to `fail!(...)` as an `Any` trait object.
+ /// function. If the child task panics then the future returns `result::Err`
+ /// containing the argument to `panic!(...)` as an `Any` trait object.
#[experimental = "Futures are experimental."]
pub fn try_future<T:Send>(self, f: proc():Send -> T)
-> Future<Result<T, Box<Any + Send>>> {
}
/// Execute a function in a newly-spawnedtask and block until the task
- /// completes or fails. Equivalent to `.try_future(f).unwrap()`.
+ /// completes or panics. Equivalent to `.try_future(f).unwrap()`.
#[unstable = "Error type may change."]
pub fn try<T:Send>(self, f: proc():Send -> T) -> Result<T, Box<Any + Send>> {
self.try_future(f).unwrap()
}
/// Execute a function in a newly-spawned task and return either the return
-/// value of the function or an error if the task failed.
+/// value of the function or an error if the task panicked.
///
/// This is equivalent to `TaskBuilder::new().try`.
#[unstable = "Error type may change."]
task.yield_now();
}
-/// True if the running task is currently failing (e.g. will return `true` inside a
-/// destructor that is run while unwinding the stack after a call to `fail!()`).
+/// True if the running task is currently panicking (e.g. will return `true` inside a
+/// destructor that is run while unwinding the stack after a call to `panic!()`).
#[unstable = "May move to a different module."]
pub fn failing() -> bool {
use rt::task::Task;
assert!(result.unwrap().is_ok());
let result = TaskBuilder::new().try_future(proc() -> () {
- fail!();
+ panic!();
});
assert!(result.unwrap().is_err());
}
"Success!".to_string()
}).as_ref().map(|s| s.as_slice()) {
result::Ok("Success!") => (),
- _ => fail!()
+ _ => panic!()
}
}
#[test]
- fn test_try_fail() {
+ fn test_try_panic() {
match try(proc() {
- fail!()
+ panic!()
}) {
result::Err(_) => (),
- result::Ok(()) => fail!()
+ result::Ok(()) => panic!()
}
}
}
#[test]
- fn test_try_fail_message_static_str() {
+ fn test_try_panic_message_static_str() {
match try(proc() {
- fail!("static string");
+ panic!("static string");
}) {
Err(e) => {
type T = &'static str;
assert!(e.is::<T>());
assert_eq!(*e.downcast::<T>().unwrap(), "static string");
}
- Ok(()) => fail!()
+ Ok(()) => panic!()
}
}
#[test]
- fn test_try_fail_message_owned_str() {
+ fn test_try_panic_message_owned_str() {
match try(proc() {
- fail!("owned string".to_string());
+ panic!("owned string".to_string());
}) {
Err(e) => {
type T = String;
assert!(e.is::<T>());
assert_eq!(*e.downcast::<T>().unwrap(), "owned string".to_string());
}
- Ok(()) => fail!()
+ Ok(()) => panic!()
}
}
#[test]
- fn test_try_fail_message_any() {
+ fn test_try_panic_message_any() {
match try(proc() {
- fail!(box 413u16 as Box<Any + Send>);
+ panic!(box 413u16 as Box<Any + Send>);
}) {
Err(e) => {
type T = Box<Any + Send>;
assert!(any.is::<u16>());
assert_eq!(*any.downcast::<u16>().unwrap(), 413u16);
}
- Ok(()) => fail!()
+ Ok(()) => panic!()
}
}
#[test]
- fn test_try_fail_message_unit_struct() {
+ fn test_try_panic_message_unit_struct() {
struct Juju;
match try(proc() {
- fail!(Juju)
+ panic!(Juju)
}) {
Err(ref e) if e.is::<Juju>() => {}
- Err(_) | Ok(()) => fail!()
+ Err(_) | Ok(()) => panic!()
}
}
pub fn seconds(seconds: i64) -> Duration {
let d = Duration { secs: seconds, nanos: 0 };
if d < MIN || d > MAX {
- fail!("Duration::seconds out of bounds");
+ panic!("Duration::seconds out of bounds");
}
d
}
impl fmt::Show for Duration {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- let days = self.num_days();
- let secs = self.secs - days * SECS_PER_DAY;
+ // technically speaking, negative duration is not valid ISO 8601,
+ // but we need to print it anyway.
+ let (abs, sign) = if self.secs < 0 { (-self, "-") } else { (*self, "") };
+
+ let days = abs.secs / SECS_PER_DAY;
+ let secs = abs.secs - days * SECS_PER_DAY;
let hasdate = days != 0;
- let hastime = (secs != 0 || self.nanos != 0) || !hasdate;
+ let hastime = (secs != 0 || abs.nanos != 0) || !hasdate;
+
+ try!(write!(f, "{}P", sign));
- try!(write!(f, "P"));
if hasdate {
- // technically speaking the negative part is not the valid ISO 8601,
- // but we need to print it anyway.
try!(write!(f, "{}D", days));
}
if hastime {
- if self.nanos == 0 {
+ if abs.nanos == 0 {
try!(write!(f, "T{}S", secs));
- } else if self.nanos % NANOS_PER_MILLI == 0 {
- try!(write!(f, "T{}.{:03}S", secs, self.nanos / NANOS_PER_MILLI));
- } else if self.nanos % NANOS_PER_MICRO == 0 {
- try!(write!(f, "T{}.{:06}S", secs, self.nanos / NANOS_PER_MICRO));
+ } else if abs.nanos % NANOS_PER_MILLI == 0 {
+ try!(write!(f, "T{}.{:03}S", secs, abs.nanos / NANOS_PER_MILLI));
+ } else if abs.nanos % NANOS_PER_MICRO == 0 {
+ try!(write!(f, "T{}.{:06}S", secs, abs.nanos / NANOS_PER_MICRO));
} else {
- try!(write!(f, "T{}.{:09}S", secs, self.nanos));
+ try!(write!(f, "T{}.{:09}S", secs, abs.nanos));
}
}
Ok(())
let d: Duration = Zero::zero();
assert_eq!(d.to_string(), "PT0S".to_string());
assert_eq!(Duration::days(42).to_string(), "P42D".to_string());
- assert_eq!(Duration::days(-42).to_string(), "P-42D".to_string());
+ assert_eq!(Duration::days(-42).to_string(), "-P42D".to_string());
assert_eq!(Duration::seconds(42).to_string(), "PT42S".to_string());
assert_eq!(Duration::milliseconds(42).to_string(), "PT0.042S".to_string());
assert_eq!(Duration::microseconds(42).to_string(), "PT0.000042S".to_string());
assert_eq!(Duration::nanoseconds(42).to_string(), "PT0.000000042S".to_string());
assert_eq!((Duration::days(7) + Duration::milliseconds(6543)).to_string(),
"P7DT6.543S".to_string());
+ assert_eq!(Duration::seconds(-86401).to_string(), "-P1DT1S".to_string());
+ assert_eq!(Duration::nanoseconds(-1).to_string(), "-PT0.000000001S".to_string());
// the format specifier should have no effect on `Duration`
assert_eq!(format!("{:30}", Duration::days(1) + Duration::milliseconds(2345)),
//! ## Failure Propagation
//!
//! In addition to being a core primitive for communicating in rust, channels
-//! are the points at which failure is propagated among tasks. Whenever the one
+//! are the points at which panics are propagated among tasks. Whenever the one
//! half of channel is closed, the other half will have its next operation
-//! `fail!`. The purpose of this is to allow propagation of failure among tasks
+//! `panic!`. The purpose of this is to allow propagation of panics among tasks
//! that are linked to one another via channels.
//!
//! There are methods on both of senders and receivers to perform their
-//! respective operations without failing, however.
+//! respective operations without panicking, however.
//!
//! ## Runtime Requirements
//!
//! }
//! ```
//!
-//! Propagating failure:
+//! Propagating panics:
//!
//! ```should_fail
-//! // The call to recv() will fail!() because the channel has already hung
+//! // The call to recv() will panic!() because the channel has already hung
//! // up (or been deallocated)
//! let (tx, rx) = channel::<int>();
//! drop(tx);
/// becomes "rendezvous channel" where each send will not return until a recv
/// is paired with it.
///
-/// As with asynchronous channels, all senders will fail in `send` if the
+/// As with asynchronous channels, all senders will panic in `send` if the
/// `Receiver` has been destroyed.
///
/// # Example
///
/// Rust channels are infinitely buffered so this method will never block.
///
- /// # Failure
+ /// # Panics
///
- /// This function will fail if the other end of the channel has hung up.
+ /// This function will panic if the other end of the channel has hung up.
/// This means that if the corresponding receiver has fallen out of scope,
- /// this function will trigger a fail message saying that a message is
+ /// this function will trigger a panic message saying that a message is
/// being sent on a closed channel.
///
- /// Note that if this function does *not* fail, it does not mean that the
+ /// Note that if this function does *not* panic, it does not mean that the
/// data will be successfully received. All sends are placed into a queue,
/// so it is possible for a send to succeed (the other end is alive), but
/// then the other end could immediately disconnect.
///
- /// The purpose of this functionality is to propagate failure among tasks.
- /// If failure is not desired, then consider using the `send_opt` method
+ /// The purpose of this functionality is to propagate panicks among tasks.
+ /// If a panic is not desired, then consider using the `send_opt` method
#[experimental = "this function is being considered candidate for removal \
to adhere to the general guidelines of rust"]
pub fn send(&self, t: T) {
if self.send_opt(t).is_err() {
- fail!("sending on a closed channel");
+ panic!("sending on a closed channel");
}
}
///
/// Like `send`, this method will never block.
///
- /// # Failure
+ /// # Panics
///
- /// This method will never fail, it will return the message back to the
+ /// This method will never panic, it will return the message back to the
/// caller if the other end is disconnected
///
/// # Example
}
oneshot::UpDisconnected => (a, Err(t)),
oneshot::UpWoke(task) => {
- // This send cannot fail because the task is
+ // This send cannot panic because the task is
// asleep (we're looking at it), so the receiver
// can't go away.
(*a.get()).send(t).ok().unwrap();
/// time. If the buffer size is 0, however, it can be guaranteed that the
/// receiver has indeed received the data if this function returns success.
///
- /// # Failure
+ /// # Panics
///
- /// Similarly to `Sender::send`, this function will fail if the
+ /// Similarly to `Sender::send`, this function will panic if the
/// corresponding `Receiver` for this channel has disconnected. This
- /// behavior is used to propagate failure among tasks.
+ /// behavior is used to propagate panics among tasks.
///
- /// If failure is not desired, you can achieve the same semantics with the
- /// `SyncSender::send_opt` method which will not fail if the receiver
+ /// If a panic is not desired, you can achieve the same semantics with the
+ /// `SyncSender::send_opt` method which will not panic if the receiver
/// disconnects.
#[experimental = "this function is being considered candidate for removal \
to adhere to the general guidelines of rust"]
pub fn send(&self, t: T) {
if self.send_opt(t).is_err() {
- fail!("sending on a closed channel");
+ panic!("sending on a closed channel");
}
}
/// is returned back to the callee. This function is similar to `try_send`,
/// except that it will block if the channel is currently full.
///
- /// # Failure
+ /// # Panics
///
- /// This function cannot fail.
+ /// This function cannot panic.
#[unstable = "this function may be renamed to send() in the future"]
pub fn send_opt(&self, t: T) -> Result<(), T> {
unsafe { (*self.inner.get()).send(t) }
/// See `SyncSender::send` for notes about guarantees of whether the
/// receiver has received the data or not if this function is successful.
///
- /// # Failure
+ /// # Panics
///
- /// This function cannot fail
+ /// This function cannot panic
#[unstable = "the return type of this function is candidate for \
modification"]
pub fn try_send(&self, t: T) -> Result<(), TrySendError<T>> {
/// on the channel from its paired `Sender` structure. This receiver will
/// be woken up when data is ready, and the data will be returned.
///
- /// # Failure
+ /// # Panics
///
- /// Similar to channels, this method will trigger a task failure if the
+ /// Similar to channels, this method will trigger a task panic if the
/// other end of the channel has hung up (been deallocated). The purpose of
- /// this is to propagate failure among tasks.
+ /// this is to propagate panicks among tasks.
///
- /// If failure is not desired, then there are two options:
+ /// If a panic is not desired, then there are two options:
///
/// * If blocking is still desired, the `recv_opt` method will return `None`
/// when the other end hangs up
pub fn recv(&self) -> T {
match self.recv_opt() {
Ok(t) => t,
- Err(()) => fail!("receiving on a closed channel"),
+ Err(()) => panic!("receiving on a closed channel"),
}
}
/// This is useful for a flavor of "optimistic check" before deciding to
/// block on a receiver.
///
- /// This function cannot fail.
+ /// # Panics
+ ///
+ /// This function cannot panic.
#[unstable = "the return type of this function may be altered"]
pub fn try_recv(&self) -> Result<T, TryRecvError> {
// If a thread is spinning in try_recv, we should take the opportunity
}
}
- /// Attempt to wait for a value on this receiver, but does not fail if the
+ /// Attempt to wait for a value on this receiver, but does not panic if the
/// corresponding channel has hung up.
///
/// This implementation of iterators for ports will always block if there is
- /// not data available on the receiver, but it will not fail in the case
+ /// not data available on the receiver, but it will not panic in the case
/// that the channel has been deallocated.
///
/// In other words, this function has the same semantics as the `recv`
- /// method except for the failure aspect.
+ /// method except for the panic aspect.
///
/// If the channel has hung up, then `Err` is returned. Otherwise `Ok` of
/// the value found on the receiver is returned.
}
/// Returns an iterator which will block waiting for messages, but never
- /// `fail!`. It will return `None` when the channel has hung up.
+ /// `panic!`. It will return `None` when the channel has hung up.
#[unstable]
pub fn iter<'a>(&'a self) -> Messages<'a, T> {
Messages { rx: self }
assert_eq!(rx.recv(), 1);
}
match rx.try_recv() {
- Ok(..) => fail!(),
+ Ok(..) => panic!(),
_ => {}
}
dtx.send(());
} #[should_fail])
test!(fn oneshot_single_thread_recv_chan_close() {
- // Receiving on a closed chan will fail
+ // Receiving on a closed chan will panic
let res = task::try(proc() {
let (tx, rx) = channel::<int>();
drop(tx);
assert_eq!(rx.recv(), 1);
}
match rx.try_recv() {
- Ok(..) => fail!(),
+ Ok(..) => panic!(),
_ => {}
}
dtx.send(());
} #[should_fail])
test!(fn oneshot_single_thread_recv_chan_close() {
- // Receiving on a closed chan will fail
+ // Receiving on a closed chan will panic
let res = task::try(proc() {
let (tx, rx) = sync_channel::<int>(0);
drop(tx);
// Sanity check
match self.upgrade {
NothingSent => {}
- _ => fail!("sending on a oneshot that's already sent on "),
+ _ => panic!("sending on a oneshot that's already sent on "),
}
assert!(self.data.is_none());
self.data = Some(t);
let prev = match self.upgrade {
NothingSent => NothingSent,
SendUsed => SendUsed,
- _ => fail!("upgrading again"),
+ _ => panic!("upgrading again"),
};
self.upgrade = GoUp(up);
impl Select {
/// Creates a new selection structure. This set is initially empty and
- /// `wait` will fail!() if called.
+ /// `wait` will panic!() if called.
///
/// Usage of this struct directly can sometimes be burdensome, and usage is
/// rather much easier through the `select!` macro.
tx1.send(1);
select! (
foo = rx1.recv() => { assert_eq!(foo, 1); },
- _bar = rx2.recv() => { fail!() }
+ _bar = rx2.recv() => { panic!() }
)
tx2.send(2);
select! (
- _foo = rx1.recv() => { fail!() },
+ _foo = rx1.recv() => { panic!() },
bar = rx2.recv() => { assert_eq!(bar, 2) }
)
drop(tx1);
select! (
foo = rx1.recv_opt() => { assert_eq!(foo, Err(())); },
- _bar = rx2.recv() => { fail!() }
+ _bar = rx2.recv() => { panic!() }
)
drop(tx2);
select! (
let (tx5, rx5) = channel::<int>();
tx5.send(4);
select! (
- _foo = rx1.recv() => { fail!("1") },
- _foo = rx2.recv() => { fail!("2") },
- _foo = rx3.recv() => { fail!("3") },
- _foo = rx4.recv() => { fail!("4") },
+ _foo = rx1.recv() => { panic!("1") },
+ _foo = rx2.recv() => { panic!("2") },
+ _foo = rx3.recv() => { panic!("3") },
+ _foo = rx4.recv() => { panic!("4") },
foo = rx5.recv() => { assert_eq!(foo, 4); }
)
})
drop(tx2);
select! (
- _a1 = rx1.recv_opt() => { fail!() },
+ _a1 = rx1.recv_opt() => { panic!() },
a2 = rx2.recv_opt() => { assert_eq!(a2, Err(())); }
)
})
select! (
a = rx1.recv() => { assert_eq!(a, 1); },
- _b = rx2.recv() => { fail!() }
+ _b = rx2.recv() => { panic!() }
)
tx3.send(1);
select! (
a = rx1.recv_opt() => { assert_eq!(a, Err(())); },
- _b = rx2.recv() => { fail!() }
+ _b = rx2.recv() => { panic!() }
)
})
tx3.send(());
select!(
_i1 = rx1.recv() => {},
- _i2 = rx2.recv() => fail!()
+ _i2 = rx2.recv() => panic!()
)
tx3.send(());
})
tx3.send(());
select!(
_i1 = rx1.recv() => {},
- _i2 = rx2.recv() => fail!()
+ _i2 = rx2.recv() => panic!()
)
tx3.send(());
})
Thread::yield_now();
match self.queue.pop() {
mpsc::Data(t) => { data = t; break }
- mpsc::Empty => fail!("inconsistent => empty"),
+ mpsc::Empty => panic!("inconsistent => empty"),
mpsc::Inconsistent => {}
}
}
match self.channels.fetch_sub(1, atomic::SeqCst) {
1 => {}
n if n > 1 => return,
- n => fail!("bad number of channels left {}", n),
+ n => panic!("bad number of channels left {}", n),
}
match self.cnt.swap(DISCONNECTED, atomic::SeqCst) {
/// which means that every successful send is paired with a successful recv.
///
/// This flavor of channels defines a new `send_opt` method for channels which
-/// is the method by which a message is sent but the task does not fail if it
+/// is the method by which a message is sent but the task does not panic if it
/// cannot be delivered.
///
/// Another major difference is that send() will *always* return back the data
// success, someone's about to receive our buffered data.
BlockedReceiver(task) => { wakeup(task, guard); Ok(()) }
- BlockedSender(..) => fail!("lolwut"),
+ BlockedSender(..) => panic!("lolwut"),
}
}
while left > 0 {
match s.steal() {
Data((1, 10)) => { left -= 1; }
- Data(..) => fail!(),
+ Data(..) => panic!(),
Abort | Empty => {}
}
}
Data(box 20) => {
(*unsafe_remaining).fetch_sub(1, SeqCst);
}
- Data(..) => fail!(),
+ Data(..) => panic!(),
Abort | Empty => {}
}
}
while remaining.load(SeqCst) > 0 {
match w.pop() {
Some(box 20) => { remaining.fetch_sub(1, SeqCst); }
- Some(..) => fail!(),
+ Some(..) => panic!(),
None => {}
}
}
loop {
match s.steal() {
Data(2) => { HITS.fetch_add(1, SeqCst); }
- Data(..) => fail!(),
+ Data(..) => panic!(),
_ if DONE.load(SeqCst) => break,
_ => {}
}
match w.pop() {
None => {}
Some(2) => { HITS.fetch_add(1, SeqCst); },
- Some(_) => fail!(),
+ Some(_) => panic!(),
}
} else {
expected += 1;
match w.pop() {
None => {}
Some(2) => { HITS.fetch_add(1, SeqCst); },
- Some(_) => fail!(),
+ Some(_) => panic!(),
}
}
DONE.store(true, SeqCst);
Data((1, 2)) => {
(*thread_box).fetch_add(1, SeqCst);
}
- Data(..) => fail!(),
+ Data(..) => panic!(),
_ if DONE.load(SeqCst) => break,
_ => {}
}
match w.pop() {
None => {}
Some((1, 2)) => myhit = true,
- Some(_) => fail!(),
+ Some(_) => panic!(),
}
} else {
w.push((1, 2));
//!
//! The wrappers in this module build on the primitives from `sync::raw` to
//! provide safe interfaces around using the primitive locks. These primitives
-//! implement a technique called "poisoning" where when a task failed with a
-//! held lock, all future attempts to use the lock will fail.
+//! implement a technique called "poisoning" where when a task panicked with a
+//! held lock, all future attempts to use the lock will panic.
//!
-//! For example, if two tasks are contending on a mutex and one of them fails
-//! after grabbing the lock, the second task will immediately fail because the
+//! For example, if two tasks are contending on a mutex and one of them panics
+//! after grabbing the lock, the second task will immediately panic because the
//! lock is now poisoned.
use core::prelude::*;
impl<'a> PoisonOnFail<'a> {
fn check(flag: bool, name: &str) {
if flag {
- fail!("Poisoned {} - another task failed inside!", name);
+ panic!("Poisoned {} - another task failed inside!", name);
}
}
///
/// wait() is equivalent to wait_on(0).
///
- /// # Failure
+ /// # Panics
///
/// A task which is killed while waiting on a condition variable will wake
- /// up, fail, and unlock the associated lock as it unwinds.
+ /// up, panic, and unlock the associated lock as it unwinds.
#[inline]
pub fn wait(&self) { self.wait_on(0) }
/// when dropped. All concurrent tasks attempting to lock the mutex will
/// block while the returned value is still alive.
///
- /// # Failure
+ /// # Panics
///
- /// Failing while inside the Mutex will unlock the Mutex while unwinding, so
+ /// Panicking while inside the Mutex will unlock the Mutex while unwinding, so
/// that other tasks won't block forever. It will also poison the Mutex:
/// any tasks that subsequently try to access it (including those already
- /// blocked on the mutex) will also fail immediately.
+ /// blocked on the mutex) will also panic immediately.
#[inline]
pub fn lock<'a>(&'a self) -> MutexGuard<'a, T> {
let guard = self.lock.lock();
/// Access the underlying data mutably. Locks the rwlock in write mode;
/// other readers and writers will block.
///
- /// # Failure
+ /// # Panics
///
- /// Failing while inside the lock will unlock the lock while unwinding, so
+ /// Panicking while inside the lock will unlock the lock while unwinding, so
/// that other tasks won't block forever. As Mutex.lock, it will also poison
- /// the lock, so subsequent readers and writers will both also fail.
+ /// the lock, so subsequent readers and writers will both also panic.
#[inline]
pub fn write<'a>(&'a self) -> RWLockWriteGuard<'a, T> {
let guard = self.lock.write();
let lock = arc2.lock();
lock.cond.signal();
// Parent should fail when it wakes up.
- fail!();
+ panic!();
});
let lock = arc.lock();
}
}
let _u = Unwinder { i: arc2 };
- fail!();
+ panic!();
});
let lock = arc.lock();
assert_eq!(*lock, 2);
}
}
let _u = Unwinder { i: arc2 };
- fail!();
+ panic!();
});
let lock = arc.read();
assert_eq!(*lock, 2);
let q = Queue::new();
match q.pop() {
Empty => {}
- Inconsistent | Data(..) => fail!()
+ Inconsistent | Data(..) => panic!()
}
let (tx, rx) = channel();
let q = Arc::new(q);
impl<'a> Condvar<'a> {
/// Atomically drop the associated lock, and block until a signal is sent.
///
- /// # Failure
+ /// # Panics
///
/// A task which is killed while waiting on a condition variable will wake
- /// up, fail, and unlock the associated lock as it unwinds.
+ /// up, panic, and unlock the associated lock as it unwinds.
pub fn wait(&self) { self.wait_on(0) }
/// As wait(), but can specify which of multiple condition variables to
///
/// The associated lock must have been initialised with an appropriate
/// number of condvars. The condvar_id must be between 0 and num_condvars-1
- /// or else this call will fail.
+ /// or else this call will panic.
///
/// wait() is equivalent to wait_on(0).
pub fn wait_on(&self, condvar_id: uint) {
}
}
-// Checks whether a condvar ID was out of bounds, and fails if so, or does
+// Checks whether a condvar ID was out of bounds, and panics if so, or does
// something else next on success.
#[inline]
fn check_cvar_bounds<U>(
-> U {
match out_of_bounds {
Some(0) =>
- fail!("{} with illegal ID {} - this lock has no condvars!", act, id),
+ panic!("{} with illegal ID {} - this lock has no condvars!", act, id),
Some(length) =>
- fail!("{} with illegal ID {} - ID must be less than {}", act, id, length),
+ panic!("{} with illegal ID {} - ID must be less than {}", act, id, length),
None => blk()
}
}
impl Semaphore {
/// Create a new semaphore with the specified count.
///
- /// # Failure
+ /// # Panics
///
- /// This function will fail if `count` is negative.
+ /// This function will panic if `count` is negative.
pub fn new(count: int) -> Semaphore {
Semaphore { sem: Sem::new(count, ()) }
}
/// A blocking, bounded-waiting, mutual exclusion lock with an associated
/// FIFO condition variable.
///
-/// # Failure
-/// A task which fails while holding a mutex will unlock the mutex as it
+/// # Panics
+///
+/// A task which panicks while holding a mutex will unlock the mutex as it
/// unwinds.
pub struct Mutex {
sem: Sem<Vec<WaitQueue>>,
/// Create a new mutex, with a specified number of associated condvars. This
/// will allow calling wait_on/signal_on/broadcast_on with condvar IDs
/// between 0 and num_condvars-1. (If num_condvars is 0, lock_cond will be
- /// allowed but any operations on the condvar will fail.)
+ /// allowed but any operations on the condvar will panic.)
pub fn new_with_condvars(num_condvars: uint) -> Mutex {
Mutex { sem: Sem::new_and_signal(1, num_condvars) }
}
/// A blocking, no-starvation, reader-writer lock with an associated condvar.
///
-/// # Failure
+/// # Panics
///
-/// A task which fails while holding an rwlock will unlock the rwlock as it
+/// A task which panics while holding an rwlock will unlock the rwlock as it
/// unwinds.
pub struct RWLock {
order_lock: Semaphore,
fn test_mutex_killed_simple() {
use std::any::Any;
- // Mutex must get automatically unlocked if failed/killed within.
+ // Mutex must get automatically unlocked if panicked/killed within.
let m = Arc::new(Mutex::new());
let m2 = m.clone();
let result: result::Result<(), Box<Any + Send>> = task::try(proc() {
let _lock = m2.lock();
- fail!();
+ panic!();
});
assert!(result.is_err());
// child task must have finished by the time try returns
fn rwlock_kill_helper(mode1: RWLockMode, mode2: RWLockMode) {
use std::any::Any;
- // Mutex must get automatically unlocked if failed/killed within.
+ // Mutex must get automatically unlocked if panicked/killed within.
let x = Arc::new(RWLock::new());
let x2 = x.clone();
let result: result::Result<(), Box<Any + Send>> = task::try(proc() {
lock_rwlock_in_mode(&x2, mode1, || {
- fail!();
+ panic!();
})
});
assert!(result.is_err());
loop {
match consumer.pop() {
Some(1i) => break,
- Some(_) => fail!(),
+ Some(_) => panic!(),
None => {}
}
}
use std::rc::Rc;
use serialize::{Encodable, Decodable, Encoder, Decoder};
+#[cfg(stage0)]
+pub use self::TtToken as TTTok;
+
// FIXME #6993: in librustc, uses of "ident" should be replaced
// by just "Name".
//
// On the other hand, if the comparison does need to be hygienic,
// one example and its non-hygienic counterpart would be:
- // syntax::parse::token::mtwt_token_eq
+ // syntax::parse::token::Token::mtwt_eq
// syntax::ext::tt::macro_parser::token_name_eq
- fail!("not allowed to compare these idents: {}, {}. \
+ panic!("not allowed to compare these idents: {}, {}. \
Probably related to issue \\#6993", self, other);
}
}
/// Expr with trailing semi-colon (may have any type):
StmtSemi(P<Expr>, NodeId),
- /// bool: is there a trailing sem-colon?
+ /// bool: is there a trailing semi-colon?
StmtMac(Mac, bool),
}
CaptureByRef,
}
+/// A token that delimits a sequence of token trees
+#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
+pub struct Delimiter {
+ pub span: Span,
+ pub token: ::parse::token::Token,
+}
+
+impl Delimiter {
+ /// Convert the delimiter to a `TtToken`
+ pub fn to_tt(&self) -> TokenTree {
+ TtToken(self.span, self.token.clone())
+ }
+}
+
+/// A Kleene-style [repetition operator](http://en.wikipedia.org/wiki/Kleene_star)
+/// for token sequences.
+#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
+pub enum KleeneOp {
+ ZeroOrMore,
+ OneOrMore,
+}
+
/// When the main rust parser encounters a syntax-extension invocation, it
/// parses the arguments to the invocation as a token-tree. This is a very
/// loose structure, such that all sorts of different AST-fragments can
/// If the syntax extension is an MBE macro, it will attempt to match its
/// LHS "matchers" against the provided token tree, and if it finds a
/// match, will transcribe the RHS token tree, splicing in any captured
-/// macro_parser::matched_nonterminals into the TTNonterminals it finds.
+/// `macro_parser::matched_nonterminals` into the `TtNonterminal`s it finds.
///
-/// The RHS of an MBE macro is the only place a TTNonterminal or TTSeq
+/// The RHS of an MBE macro is the only place a `TtNonterminal` or `TtSequence`
/// makes any real sense. You could write them elsewhere but nothing
/// else knows what to do with them, so you'll probably get a syntax
/// error.
#[doc="For macro invocations; parsing is delegated to the macro"]
pub enum TokenTree {
/// A single token
- TTTok(Span, ::parse::token::Token),
- /// A delimited sequence (the delimiters appear as the first
- /// and last elements of the vector)
- // FIXME(eddyb) #6308 Use Rc<[TokenTree]> after DST.
- TTDelim(Rc<Vec<TokenTree>>),
+ TtToken(Span, ::parse::token::Token),
+ /// A delimited sequence of token trees
+ TtDelimited(Span, Rc<(Delimiter, Vec<TokenTree>, Delimiter)>),
// These only make sense for right-hand-sides of MBE macros:
- /// A kleene-style repetition sequence with a span, a TTForest,
- /// an optional separator, and a boolean where true indicates
- /// zero or more (..), and false indicates one or more (+).
+ /// A Kleene-style repetition sequence with an optional separator.
// FIXME(eddyb) #6308 Use Rc<[TokenTree]> after DST.
- TTSeq(Span, Rc<Vec<TokenTree>>, Option<::parse::token::Token>, bool),
-
+ TtSequence(Span, Rc<Vec<TokenTree>>, Option<::parse::token::Token>, KleeneOp),
/// A syntactic variable that will be filled in by macro expansion.
- TTNonterminal(Span, Ident)
+ TtNonterminal(Span, Ident)
+}
+
+impl TokenTree {
+ /// Returns the `Span` corresponding to this token tree.
+ pub fn get_span(&self) -> Span {
+ match *self {
+ TtToken(span, _) => span,
+ TtDelimited(span, _) => span,
+ TtSequence(span, _, _, _) => span,
+ TtNonterminal(span, _) => span,
+ }
+ }
}
// Matchers are nodes defined-by and recognized-by the main rust parser and
pub enum Matcher_ {
/// Match one token
MatchTok(::parse::token::Token),
- /// Match repetitions of a sequence: body, separator, zero ok?,
+ /// Match repetitions of a sequence: body, separator, Kleene operator,
/// lo, hi position-in-match-array used:
- MatchSeq(Vec<Matcher> , Option<::parse::token::Token>, bool, uint, uint),
+ MatchSeq(Vec<Matcher> , Option<::parse::token::Token>, KleeneOp, uint, uint),
/// Parse a Rust NT: name to bind, name of NT, position in match array:
MatchNonterminal(Ident, Ident, uint)
}
ident: i.ident, decl: &**decl, style: style, body: &**block,
generics: generics, abi: abi, id: i.id, span: i.span
}),
- _ => fail!("item FnLikeNode that is not fn-like"),
+ _ => panic!("item FnLikeNode that is not fn-like"),
},
ast_map::NodeTraitItem(t) => match *t {
ast::ProvidedMethod(ref m) => method(&**m),
- _ => fail!("trait method FnLikeNode that is not fn-like"),
+ _ => panic!("trait method FnLikeNode that is not fn-like"),
},
ast_map::NodeImplItem(ii) => {
match *ii {
ast::MethodImplItem(ref m) => method(&**m),
ast::TypeImplItem(_) => {
- fail!("impl method FnLikeNode that is not fn-like")
+ panic!("impl method FnLikeNode that is not fn-like")
}
}
}
closure(ClosureParts::new(&**decl, &**block, e.id, e.span)),
ast::ExprProc(ref decl, ref block) =>
closure(ClosureParts::new(&**decl, &**block, e.id, e.span)),
- _ => fail!("expr FnLikeNode that is not fn-like"),
+ _ => panic!("expr FnLikeNode that is not fn-like"),
},
- _ => fail!("other FnLikeNode that is not fn-like"),
+ _ => panic!("other FnLikeNode that is not fn-like"),
}
}
}
&self.forest.krate
}
- /// Retrieve the Node corresponding to `id`, failing if it cannot
+ /// Retrieve the Node corresponding to `id`, panicking if it cannot
/// be found.
pub fn get(&self, id: NodeId) -> Node<'ast> {
match self.find(id) {
Some(node) => node,
- None => fail!("couldn't find node id {} in the AST map", id)
+ None => panic!("couldn't find node id {} in the AST map", id)
}
}
};
match abi {
Some(abi) => abi,
- None => fail!("expected foreign mod or inlined parent, found {}",
+ None => panic!("expected foreign mod or inlined parent, found {}",
self.node_to_string(parent))
}
}
pub fn expect_item(&self, id: NodeId) -> &'ast Item {
match self.find(id) {
Some(NodeItem(item)) => item,
- _ => fail!("expected item, found {}", self.node_to_string(id))
+ _ => panic!("expected item, found {}", self.node_to_string(id))
}
}
Some(NodeItem(i)) => {
match i.node {
ItemStruct(ref struct_def, _) => &**struct_def,
- _ => fail!("struct ID bound to non-struct")
+ _ => panic!("struct ID bound to non-struct")
}
}
Some(NodeVariant(variant)) => {
match variant.node.kind {
StructVariantKind(ref struct_def) => &**struct_def,
- _ => fail!("struct ID bound to enum variant that isn't struct-like"),
+ _ => panic!("struct ID bound to enum variant that isn't struct-like"),
}
}
- _ => fail!(format!("expected struct, found {}", self.node_to_string(id))),
+ _ => panic!(format!("expected struct, found {}", self.node_to_string(id))),
}
}
pub fn expect_variant(&self, id: NodeId) -> &'ast Variant {
match self.find(id) {
Some(NodeVariant(variant)) => variant,
- _ => fail!(format!("expected variant, found {}", self.node_to_string(id))),
+ _ => panic!(format!("expected variant, found {}", self.node_to_string(id))),
}
}
pub fn expect_foreign_item(&self, id: NodeId) -> &'ast ForeignItem {
match self.find(id) {
Some(NodeForeignItem(item)) => item,
- _ => fail!("expected foreign item, found {}", self.node_to_string(id))
+ _ => panic!("expected foreign item, found {}", self.node_to_string(id))
}
}
pub fn expect_expr(&self, id: NodeId) -> &'ast Expr {
match self.find(id) {
Some(NodeExpr(expr)) => expr,
- _ => fail!("expected expr, found {}", self.node_to_string(id))
+ _ => panic!("expected expr, found {}", self.node_to_string(id))
}
}
PathName(ident.name)
}
MethMac(_) => {
- fail!("no path elem for {}", node)
+ panic!("no path elem for {}", node)
}
}
}
MethDecl(ident, _, _, _, _, _, _, _) => {
PathName(ident.name)
}
- MethMac(_) => fail!("no path elem for {}", node),
+ MethMac(_) => panic!("no path elem for {}", node),
}
}
TypeTraitItem(ref m) => PathName(m.ident.name),
},
NodeVariant(v) => PathName(v.node.name.name),
- _ => fail!("no path elem for {}", node)
+ _ => panic!("no path elem for {}", node)
}
}
pub fn span(&self, id: NodeId) -> Span {
self.opt_span(id)
- .unwrap_or_else(|| fail!("AstMap.span: could not find span for id {}", id))
+ .unwrap_or_else(|| panic!("AstMap.span: could not find span for id {}", id))
}
pub fn def_id_span(&self, def_id: DefId, fallback: Span) -> Span {
fn name(&self) -> Name {
match self.node {
MethDecl(i, _, _, _, _, _, _, _) => i.name,
- MethMac(_) => fail!("encountered unexpanded method macro."),
+ MethMac(_) => panic!("encountered unexpanded method macro."),
}
}
}
// these cases do not carry enough information in the
// ast_map to reconstruct their full structure for pretty
// printing.
- NodeLocal(_) => fail!("cannot print isolated Local"),
- NodeArg(_) => fail!("cannot print isolated Arg"),
- NodeStructCtor(_) => fail!("cannot print isolated StructCtor"),
+ NodeLocal(_) => panic!("cannot print isolated Local"),
+ NodeArg(_) => panic!("cannot print isolated Arg"),
+ NodeStructCtor(_) => panic!("cannot print isolated StructCtor"),
}
}
}
StmtDecl(_, id) => id,
StmtExpr(_, id) => id,
StmtSemi(_, id) => id,
- StmtMac(..) => fail!("attempted to analyze unexpanded stmt")
+ StmtMac(..) => panic!("attempted to analyze unexpanded stmt")
}
}
abi: abi,
}
},
- MethMac(_) => fail!("expected non-macro method declaration")
+ MethMac(_) => panic!("expected non-macro method declaration")
}
}
RequiredMethod(ref m) => (*m).clone(),
ProvidedMethod(ref m) => trait_method_to_ty_method(&**m),
TypeTraitItem(_) => {
- fail!("trait_method_to_ty_method(): expected method but found \
+ panic!("trait_method_to_ty_method(): expected method but found \
typedef")
}
}
slice.iter().all(|p| walk_pat(&**p, |p| it(p))) &&
after.iter().all(|p| walk_pat(&**p, |p| it(p)))
}
- PatMac(_) => fail!("attempted to analyze unexpanded pattern"),
+ PatMac(_) => panic!("attempted to analyze unexpanded pattern"),
PatWild(_) | PatLit(_) | PatRange(_, _) | PatIdent(_, _, _) |
PatEnum(_, _) => {
true
match self.node {
$field_pat => $result,
MethMac(_) => {
- fail!("expected an AST without macro invocations");
+ panic!("expected an AST without macro invocations");
}
}
}
// FIXME #8256: this used to be an assert but whatever precondition
// it's testing isn't true for all spans in the AST, so to allow the
- // caller to not have to fail (and it can't catch it since the CodeMap
+ // caller to not have to panic (and it can't catch it since the CodeMap
// isn't sendable), return None
if begin.fm.start_pos != end.fm.start_pos {
None
return fm.clone();
}
}
- fail!("asking for {} which we don't know about", filename);
+ panic!("asking for {} which we don't know about", filename);
}
pub fn lookup_byte_offset(&self, bpos: BytePos) -> FileMapAndBytePos {
break;
}
if a == 0 {
- fail!("position {} does not resolve to a source location",
+ panic!("position {} does not resolve to a source location",
pos.to_uint());
}
a -= 1;
}
if a >= len {
- fail!("position {} does not resolve to a source location",
+ panic!("position {} does not resolve to a source location",
pos.to_uint())
}
// Determine if an item should be translated in the current crate
// configuration based on the item's attributes
fn in_cfg(diagnostic: &SpanHandler, cfg: &[P<ast::MetaItem>], attrs: &[ast::Attribute]) -> bool {
- let mut in_cfg = false;
- let mut seen_cfg = false;
- for attr in attrs.iter() {
+ attrs.iter().all(|attr| {
let mis = match attr.node.value.node {
ast::MetaList(_, ref mis) if attr.check_name("cfg") => mis,
- _ => continue
+ _ => return true
};
if mis.len() != 1 {
diagnostic.span_err(attr.span, "expected 1 cfg-pattern");
- return false;
+ return true;
}
- if seen_cfg {
- diagnostic.span_err(attr.span, "The semantics of multiple `#[cfg(..)]` attributes on \
- same item are changing from the union of the cfgs to \
- the intersection of the cfgs. Change `#[cfg(a)] \
- #[cfg(b)]` to `#[cfg(any(a, b))]`.");
- return false;
- }
-
- seen_cfg = true;
- in_cfg |= attr::cfg_matches(diagnostic, cfg, &*mis[0]);
- }
- in_cfg | !seen_cfg
+ attr::cfg_matches(diagnostic, cfg, &*mis[0])
+ })
}
sp: RenderSpan, msg: &str, lvl: Level);
}
-/// This structure is used to signify that a task has failed with a fatal error
+/// This structure is used to signify that a task has panicked with a fatal error
/// from the diagnostics. You can use this with the `Any` trait to figure out
/// how a rustc task died (if so desired).
pub struct FatalError;
impl SpanHandler {
pub fn span_fatal(&self, sp: Span, msg: &str) -> ! {
self.handler.emit(Some((&self.cm, sp)), msg, Fatal);
- fail!(FatalError);
+ panic!(FatalError);
}
pub fn span_err(&self, sp: Span, msg: &str) {
self.handler.emit(Some((&self.cm, sp)), msg, Error);
}
pub fn span_bug(&self, sp: Span, msg: &str) -> ! {
self.handler.emit(Some((&self.cm, sp)), msg, Bug);
- fail!(ExplicitBug);
+ panic!(ExplicitBug);
}
pub fn span_unimpl(&self, sp: Span, msg: &str) -> ! {
self.span_bug(sp, format!("unimplemented {}", msg).as_slice());
impl Handler {
pub fn fatal(&self, msg: &str) -> ! {
self.emit.borrow_mut().emit(None, msg, None, Fatal);
- fail!(FatalError);
+ panic!(FatalError);
}
pub fn err(&self, msg: &str) {
self.emit.borrow_mut().emit(None, msg, None, Error);
}
pub fn bug(&self, msg: &str) -> ! {
self.emit.borrow_mut().emit(None, msg, None, Bug);
- fail!(ExplicitBug);
+ panic!(ExplicitBug);
}
pub fn unimpl(&self, msg: &str) -> ! {
self.bug(format!("unimplemented {}", msg).as_slice());
match error {
Ok(()) => {}
- Err(e) => fail!("failed to print diagnostics: {}", e),
+ Err(e) => panic!("failed to print diagnostics: {}", e),
}
}
sp: RenderSpan, msg: &str, lvl: Level) {
match emit(self, cm, sp, msg, None, lvl, true) {
Ok(()) => {}
- Err(e) => fail!("failed to print diagnostics: {}", e),
+ Err(e) => panic!("failed to print diagnostics: {}", e),
}
}
}
token_tree: &[TokenTree])
-> Box<MacResult+'cx> {
let code = match token_tree {
- [ast::TTTok(_, token::IDENT(code, _))] => code,
+ [ast::TtToken(_, token::Ident(code, _))] => code,
_ => unreachable!()
};
with_registered_diagnostics(|diagnostics| {
token_tree: &[TokenTree])
-> Box<MacResult+'cx> {
let (code, description) = match token_tree {
- [ast::TTTok(_, token::IDENT(ref code, _))] => {
+ [ast::TtToken(_, token::Ident(ref code, _))] => {
(code, None)
},
- [ast::TTTok(_, token::IDENT(ref code, _)),
- ast::TTTok(_, token::COMMA),
- ast::TTTok(_, token::LIT_STR_RAW(description, _))] => {
+ [ast::TtToken(_, token::Ident(ref code, _)),
+ ast::TtToken(_, token::Comma),
+ ast::TtToken(_, token::LitStrRaw(description, _))] => {
(code, Some(description))
}
_ => unreachable!()
token_tree: &[TokenTree])
-> Box<MacResult+'cx> {
let name = match token_tree {
- [ast::TTTok(_, token::IDENT(ref name, _))] => name,
+ [ast::TtToken(_, token::Ident(ref name, _))] => name,
_ => unreachable!()
};
asm_str_style = Some(style);
}
Outputs => {
- while p.token != token::EOF &&
- p.token != token::COLON &&
- p.token != token::MOD_SEP {
+ while p.token != token::Eof &&
+ p.token != token::Colon &&
+ p.token != token::ModSep {
if outputs.len() != 0 {
- p.eat(&token::COMMA);
+ p.eat(&token::Comma);
}
let (constraint, _str_style) = p.parse_str();
let span = p.last_span;
- p.expect(&token::LPAREN);
+ p.expect(&token::LParen);
let out = p.parse_expr();
- p.expect(&token::RPAREN);
+ p.expect(&token::RParen);
// Expands a read+write operand into two operands.
//
}
}
Inputs => {
- while p.token != token::EOF &&
- p.token != token::COLON &&
- p.token != token::MOD_SEP {
+ while p.token != token::Eof &&
+ p.token != token::Colon &&
+ p.token != token::ModSep {
if inputs.len() != 0 {
- p.eat(&token::COMMA);
+ p.eat(&token::Comma);
}
let (constraint, _str_style) = p.parse_str();
cx.span_err(p.last_span, "input operand constraint contains '+'");
}
- p.expect(&token::LPAREN);
+ p.expect(&token::LParen);
let input = p.parse_expr();
- p.expect(&token::RPAREN);
+ p.expect(&token::RParen);
inputs.push((constraint, input));
}
}
Clobbers => {
let mut clobs = Vec::new();
- while p.token != token::EOF &&
- p.token != token::COLON &&
- p.token != token::MOD_SEP {
+ while p.token != token::Eof &&
+ p.token != token::Colon &&
+ p.token != token::ModSep {
if clobs.len() != 0 {
- p.eat(&token::COMMA);
+ p.eat(&token::Comma);
}
let (s, _str_style) = p.parse_str();
cx.span_warn(p.last_span, "unrecognized option");
}
- if p.token == token::COMMA {
- p.eat(&token::COMMA);
+ if p.token == token::Comma {
+ p.eat(&token::Comma);
}
}
StateNone => ()
// MOD_SEP is a double colon '::' without space in between.
// When encountered, the state must be advanced twice.
match (&p.token, state.next(), state.next().next()) {
- (&token::COLON, StateNone, _) |
- (&token::MOD_SEP, _, StateNone) => {
+ (&token::Colon, StateNone, _) |
+ (&token::ModSep, _, StateNone) => {
p.bump();
break 'statement;
}
- (&token::COLON, st, _) |
- (&token::MOD_SEP, _, st) => {
+ (&token::Colon, st, _) |
+ (&token::ModSep, _, st) => {
p.bump();
state = st;
}
- (&token::EOF, _, _) => break 'statement,
+ (&token::Eof, _, _) => break 'statement,
_ => break
}
}
cx.span_err(sp, format!("{} takes 1 argument.", name).as_slice());
} else {
match tts[0] {
- ast::TTTok(_, token::LIT_STR(ident)) => return Some(parse::str_lit(ident.as_str())),
- ast::TTTok(_, token::LIT_STR_RAW(ident, _)) => {
+ ast::TtToken(_, token::LitStr(ident)) => return Some(parse::str_lit(ident.as_str())),
+ ast::TtToken(_, token::LitStrRaw(ident, _)) => {
return Some(parse::raw_str_lit(ident.as_str()))
}
_ => {
tts: &[ast::TokenTree]) -> Option<Vec<P<ast::Expr>>> {
let mut p = cx.new_parser_from_tts(tts);
let mut es = Vec::new();
- while p.token != token::EOF {
+ while p.token != token::Eof {
es.push(cx.expander().fold_expr(p.parse_expr()));
- if p.eat(&token::COMMA) {
+ if p.eat(&token::Comma) {
continue;
}
- if p.token != token::EOF {
+ if p.token != token::Eof {
cx.span_err(sp, "expected token: `,`");
return None;
}
let mut p = cx.new_parser_from_tts(tts);
let cfg = p.parse_meta_item();
- if !p.eat(&token::EOF) {
+ if !p.eat(&token::Eof) {
cx.span_err(sp, "expected 1 cfg-pattern");
return DummyResult::expr(sp);
}
for (i, e) in tts.iter().enumerate() {
if i & 1 == 1 {
match *e {
- ast::TTTok(_, token::COMMA) => (),
+ ast::TtToken(_, token::Comma) => {},
_ => {
cx.span_err(sp, "concat_idents! expecting comma.");
return DummyResult::expr(sp);
- }
+ },
}
} else {
match *e {
- ast::TTTok(_, token::IDENT(ident,_)) => {
+ ast::TtToken(_, token::Ident(ident, _)) => {
res_str.push_str(token::get_ident(ident).get())
- }
+ },
_ => {
cx.span_err(sp, "concat_idents! requires ident args.");
return DummyResult::expr(sp);
- }
+ },
}
}
}
// id is guaranteed to be Some
codemap::Spanned {
span: pat.span,
- node: ast::FieldPat { ident: id.unwrap(), pat: pat, is_shorthand: true },
+ node: ast::FieldPat { ident: id.unwrap(), pat: pat, is_shorthand: false },
}
}).collect();
cx.pat_struct(self.span, matching_path, field_pats)
// expand pats... they might contain macro uses:
let expanded_pats = arm.pats.move_map(|pat| fld.fold_pat(pat));
if expanded_pats.len() == 0 {
- fail!("encountered match arm with 0 patterns");
+ panic!("encountered match arm with 0 patterns");
}
// all of the pats must have the same set of bindings, so use the
// first one to extract them and generate new names:
// good lord, you can't make a path with 0 segments, can you?
let final_varref_ident = match varref.segments.last() {
Some(pathsegment) => pathsegment.identifier,
- None => fail!("varref with 0 path segments?")
+ None => panic!("varref with 0 path segments?")
};
let varref_name = mtwt::resolve(final_varref_ident);
let varref_idents : Vec<ast::Ident>
let cxbinds: &[&ast::Ident] = cxbinds.as_slice();
let cxbind = match cxbinds {
[b] => b,
- _ => fail!("expected just one binding for ext_cx")
+ _ => panic!("expected just one binding for ext_cx")
};
let resolved_binding = mtwt::resolve(*cxbind);
let varrefs = crate_varrefs(&cr);
// Parse the leading function expression (maybe a block, maybe a path)
let invocation = if allow_method {
let e = p.parse_expr();
- if !p.eat(&token::COMMA) {
+ if !p.eat(&token::Comma) {
ecx.span_err(sp, "expected token: `,`");
return (Call(e), None);
}
} else {
Call(p.parse_expr())
};
- if !p.eat(&token::COMMA) {
+ if !p.eat(&token::Comma) {
ecx.span_err(sp, "expected token: `,`");
return (invocation, None);
}
- if p.token == token::EOF {
+ if p.token == token::Eof {
ecx.span_err(sp, "requires at least a format string argument");
return (invocation, None);
}
let fmtstr = p.parse_expr();
let mut named = false;
- while p.token != token::EOF {
- if !p.eat(&token::COMMA) {
+ while p.token != token::Eof {
+ if !p.eat(&token::Comma) {
ecx.span_err(sp, "expected token: `,`");
return (invocation, None);
}
- if p.token == token::EOF { break } // accept trailing commas
- if named || (token::is_ident(&p.token) &&
- p.look_ahead(1, |t| *t == token::EQ)) {
+ if p.token == token::Eof { break } // accept trailing commas
+ if named || (p.token.is_ident() && p.look_ahead(1, |t| *t == token::Eq)) {
named = true;
let ident = match p.token {
- token::IDENT(i, _) => {
+ token::Ident(i, _) => {
p.bump();
i
}
};
let interned_name = token::get_ident(ident);
let name = interned_name.get();
- p.expect(&token::EQ);
+ p.expect(&token::Eq);
let e = p.parse_expr();
match names.find_equiv(&name) {
None => {}
use ext::base;
use print;
-use std::rc::Rc;
-
pub fn expand_syntax_ext<'cx>(cx: &'cx mut base::ExtCtxt,
sp: codemap::Span,
- tt: &[ast::TokenTree])
+ tts: &[ast::TokenTree])
-> Box<base::MacResult+'cx> {
cx.print_backtrace();
- println!("{}", print::pprust::tt_to_string(&ast::TTDelim(
- Rc::new(tt.iter().map(|x| (*x).clone()).collect()))));
+
+ println!("{}", print::pprust::tts_to_string(tts));
// any so that `log_syntax` can be invoked as an expression and item.
base::DummyResult::any(sp)
resolvedthis
}
}
- IllegalCtxt => fail!("expected resolvable context, got IllegalCtxt")
+ IllegalCtxt => panic!("expected resolvable context, got IllegalCtxt")
}
};
resolve_table.insert(key, resolved);
loopvar = tl;
}
}
- IllegalCtxt => fail!("expected resolvable context, got IllegalCtxt")
+ IllegalCtxt => panic!("expected resolvable context, got IllegalCtxt")
}
}
}
with_sctable(|sctable| {
match (*sctable.table.borrow())[ctxt as uint] {
Mark(mrk, _) => mrk,
- _ => fail!("can't retrieve outer mark when outside is not a mark")
+ _ => panic!("can't retrieve outer mark when outside is not a mark")
}
})
}
sc = tail;
continue;
}
- IllegalCtxt => fail!("expected resolvable context, got IllegalCtxt")
+ IllegalCtxt => panic!("expected resolvable context, got IllegalCtxt")
}
}
}
*
* This is registered as a set of expression syntax extension called quote!
* that lifts its argument token-tree to an AST representing the
-* construction of the same token tree, with ast::TTNonterminal nodes
+* construction of the same token tree, with ast::TtNonterminal nodes
* interpreted as antiquotes (splices).
*
*/
Some(ast) => ast,
None => {
error!("parse error");
- fail!()
+ panic!()
}
}
}
cx.expr_path(cx.path_global(sp, idents))
}
-fn mk_binop(cx: &ExtCtxt, sp: Span, bop: token::BinOp) -> P<ast::Expr> {
+fn mk_binop(cx: &ExtCtxt, sp: Span, bop: token::BinOpToken) -> P<ast::Expr> {
let name = match bop {
- PLUS => "PLUS",
- MINUS => "MINUS",
- STAR => "STAR",
- SLASH => "SLASH",
- PERCENT => "PERCENT",
- CARET => "CARET",
- AND => "AND",
- OR => "OR",
- SHL => "SHL",
- SHR => "SHR"
+ token::Plus => "Plus",
+ token::Minus => "Minus",
+ token::Star => "Star",
+ token::Slash => "Slash",
+ token::Percent => "Percent",
+ token::Caret => "Caret",
+ token::And => "And",
+ token::Or => "Or",
+ token::Shl => "Shl",
+ token::Shr => "Shr"
};
mk_token_path(cx, sp, name)
}
+#[allow(non_uppercase_statics)] // NOTE(stage0): remove this attribute after the next snapshot
fn mk_token(cx: &ExtCtxt, sp: Span, tok: &token::Token) -> P<ast::Expr> {
-
match *tok {
- BINOP(binop) => {
- return cx.expr_call(sp, mk_token_path(cx, sp, "BINOP"), vec!(mk_binop(cx, sp, binop)));
+ token::BinOp(binop) => {
+ return cx.expr_call(sp, mk_token_path(cx, sp, "BinOp"), vec!(mk_binop(cx, sp, binop)));
}
- BINOPEQ(binop) => {
- return cx.expr_call(sp, mk_token_path(cx, sp, "BINOPEQ"),
+ token::BinOpEq(binop) => {
+ return cx.expr_call(sp, mk_token_path(cx, sp, "BinOpEq"),
vec!(mk_binop(cx, sp, binop)));
}
- LIT_BYTE(i) => {
+ token::LitByte(i) => {
let e_byte = mk_name(cx, sp, i.ident());
- return cx.expr_call(sp, mk_token_path(cx, sp, "LIT_BYTE"), vec!(e_byte));
+ return cx.expr_call(sp, mk_token_path(cx, sp, "LitByte"), vec!(e_byte));
}
- LIT_CHAR(i) => {
+ token::LitChar(i) => {
let e_char = mk_name(cx, sp, i.ident());
- return cx.expr_call(sp, mk_token_path(cx, sp, "LIT_CHAR"), vec!(e_char));
+ return cx.expr_call(sp, mk_token_path(cx, sp, "LitChar"), vec!(e_char));
}
- LIT_INTEGER(i) => {
+ token::LitInteger(i) => {
let e_int = mk_name(cx, sp, i.ident());
- return cx.expr_call(sp, mk_token_path(cx, sp, "LIT_INTEGER"), vec!(e_int));
+ return cx.expr_call(sp, mk_token_path(cx, sp, "LitInteger"), vec!(e_int));
}
- LIT_FLOAT(fident) => {
+ token::LitFloat(fident) => {
let e_fident = mk_name(cx, sp, fident.ident());
- return cx.expr_call(sp, mk_token_path(cx, sp, "LIT_FLOAT"), vec!(e_fident));
+ return cx.expr_call(sp, mk_token_path(cx, sp, "LitFloat"), vec!(e_fident));
}
- LIT_STR(ident) => {
+ token::LitStr(ident) => {
return cx.expr_call(sp,
- mk_token_path(cx, sp, "LIT_STR"),
+ mk_token_path(cx, sp, "LitStr"),
vec!(mk_name(cx, sp, ident.ident())));
}
- LIT_STR_RAW(ident, n) => {
+ token::LitStrRaw(ident, n) => {
return cx.expr_call(sp,
- mk_token_path(cx, sp, "LIT_STR_RAW"),
+ mk_token_path(cx, sp, "LitStrRaw"),
vec!(mk_name(cx, sp, ident.ident()), cx.expr_uint(sp, n)));
}
- IDENT(ident, b) => {
+ token::Ident(ident, style) => {
return cx.expr_call(sp,
- mk_token_path(cx, sp, "IDENT"),
- vec!(mk_ident(cx, sp, ident), cx.expr_bool(sp, b)));
+ mk_token_path(cx, sp, "Ident"),
+ vec![mk_ident(cx, sp, ident),
+ match style {
+ ModName => mk_token_path(cx, sp, "ModName"),
+ Plain => mk_token_path(cx, sp, "Plain"),
+ }]);
}
- LIFETIME(ident) => {
+ token::Lifetime(ident) => {
return cx.expr_call(sp,
- mk_token_path(cx, sp, "LIFETIME"),
+ mk_token_path(cx, sp, "Lifetime"),
vec!(mk_ident(cx, sp, ident)));
}
- DOC_COMMENT(ident) => {
+ token::DocComment(ident) => {
return cx.expr_call(sp,
- mk_token_path(cx, sp, "DOC_COMMENT"),
+ mk_token_path(cx, sp, "DocComment"),
vec!(mk_name(cx, sp, ident.ident())));
}
- INTERPOLATED(_) => fail!("quote! with interpolated token"),
+ token::Interpolated(_) => panic!("quote! with interpolated token"),
_ => ()
}
let name = match *tok {
- EQ => "EQ",
- LT => "LT",
- LE => "LE",
- EQEQ => "EQEQ",
- NE => "NE",
- GE => "GE",
- GT => "GT",
- ANDAND => "ANDAND",
- OROR => "OROR",
- NOT => "NOT",
- TILDE => "TILDE",
- AT => "AT",
- DOT => "DOT",
- DOTDOT => "DOTDOT",
- COMMA => "COMMA",
- SEMI => "SEMI",
- COLON => "COLON",
- MOD_SEP => "MOD_SEP",
- RARROW => "RARROW",
- LARROW => "LARROW",
- FAT_ARROW => "FAT_ARROW",
- LPAREN => "LPAREN",
- RPAREN => "RPAREN",
- LBRACKET => "LBRACKET",
- RBRACKET => "RBRACKET",
- LBRACE => "LBRACE",
- RBRACE => "RBRACE",
- POUND => "POUND",
- DOLLAR => "DOLLAR",
- UNDERSCORE => "UNDERSCORE",
- EOF => "EOF",
- _ => fail!()
+ token::Eq => "Eq",
+ token::Lt => "Lt",
+ token::Le => "Le",
+ token::EqEq => "EqEq",
+ token::Ne => "Ne",
+ token::Ge => "Ge",
+ token::Gt => "Gt",
+ token::AndAnd => "AndAnd",
+ token::OrOr => "OrOr",
+ token::Not => "Not",
+ token::Tilde => "Tilde",
+ token::At => "At",
+ token::Dot => "Dot",
+ token::DotDot => "DotDot",
+ token::Comma => "Comma",
+ token::Semi => "Semi",
+ token::Colon => "Colon",
+ token::ModSep => "ModSep",
+ token::RArrow => "RArrow",
+ token::LArrow => "LArrow",
+ token::FatArrow => "FatArrow",
+ token::LParen => "LParen",
+ token::RParen => "RParen",
+ token::LBracket => "LBracket",
+ token::RBracket => "RBracket",
+ token::LBrace => "LBrace",
+ token::RBrace => "RBrace",
+ token::Pound => "Pound",
+ token::Dollar => "Dollar",
+ token::Underscore => "Underscore",
+ token::Eof => "Eof",
+ _ => panic!(),
};
mk_token_path(cx, sp, name)
}
-fn mk_tt(cx: &ExtCtxt, sp: Span, tt: &ast::TokenTree) -> Vec<P<ast::Stmt>> {
+fn mk_tt(cx: &ExtCtxt, _: Span, tt: &ast::TokenTree) -> Vec<P<ast::Stmt>> {
match *tt {
- ast::TTTok(sp, ref tok) => {
+ ast::TtToken(sp, ref tok) => {
let e_sp = cx.expr_ident(sp, id_ext("_sp"));
let e_tok = cx.expr_call(sp,
- mk_ast_path(cx, sp, "TTTok"),
+ mk_ast_path(cx, sp, "TtToken"),
vec!(e_sp, mk_token(cx, sp, tok)));
let e_push =
cx.expr_method_call(sp,
id_ext("push"),
vec!(e_tok));
vec!(cx.stmt_expr(e_push))
- }
-
- ast::TTDelim(ref tts) => mk_tts(cx, sp, tts.as_slice()),
- ast::TTSeq(..) => fail!("TTSeq in quote!"),
-
- ast::TTNonterminal(sp, ident) => {
-
+ },
+ ast::TtDelimited(sp, ref delimed) => {
+ let (ref open, ref tts, ref close) = **delimed;
+ mk_tt(cx, sp, &open.to_tt()).into_iter()
+ .chain(tts.iter().flat_map(|tt| mk_tt(cx, sp, tt).into_iter()))
+ .chain(mk_tt(cx, sp, &close.to_tt()).into_iter())
+ .collect()
+ },
+ ast::TtSequence(..) => panic!("TtSequence in quote!"),
+ ast::TtNonterminal(sp, ident) => {
// tt.extend($ident.to_tokens(ext_cx).into_iter())
let e_to_toks =
vec!(e_to_toks));
vec!(cx.stmt_expr(e_push))
- }
+ },
}
}
fn expand_tts(cx: &ExtCtxt, sp: Span, tts: &[ast::TokenTree])
-> (P<ast::Expr>, P<ast::Expr>) {
// NB: It appears that the main parser loses its mind if we consider
- // $foo as a TTNonterminal during the main parse, so we have to re-parse
+ // $foo as a TtNonterminal during the main parse, so we have to re-parse
// under quote_depth > 0. This is silly and should go away; the _guess_ is
// it has to do with transition away from supporting old-style macros, so
// try removing it when enough of them are gone.
p.quote_depth += 1u;
let cx_expr = p.parse_expr();
- if !p.eat(&token::COMMA) {
+ if !p.eat(&token::Comma) {
p.fatal("expected token `,`");
}
use codemap::Span;
use ext::base::ExtCtxt;
use ext::base;
-use parse::token::{keywords, is_keyword};
+use parse::token::keywords;
pub fn expand_trace_macros(cx: &mut ExtCtxt,
tt: &[ast::TokenTree])
-> Box<base::MacResult+'static> {
match tt {
- [ast::TTTok(_, ref tok)] if is_keyword(keywords::True, tok) => {
+ [ast::TtToken(_, ref tok)] if tok.is_keyword(keywords::True) => {
cx.set_trace_macros(true);
}
- [ast::TTTok(_, ref tok)] if is_keyword(keywords::False, tok) => {
+ [ast::TtToken(_, ref tok)] if tok.is_keyword(keywords::False) => {
cx.set_trace_macros(false);
}
_ => cx.span_err(sp, "trace_macros! accepts only `true` or `false`"),
use parse::ParseSess;
use parse::attr::ParserAttr;
use parse::parser::{LifetimeAndTypesWithoutColons, Parser};
-use parse::token::{Token, EOF, Nonterminal};
+use parse::token::{Token, Nonterminal};
use parse::token;
+use print::pprust;
use ptr::P;
use std::rc::Rc;
/// unhygienic comparison)
pub fn token_name_eq(t1 : &Token, t2 : &Token) -> bool {
match (t1,t2) {
- (&token::IDENT(id1,_),&token::IDENT(id2,_))
- | (&token::LIFETIME(id1),&token::LIFETIME(id2)) =>
+ (&token::Ident(id1,_),&token::Ident(id2,_))
+ | (&token::Lifetime(id1),&token::Lifetime(id2)) =>
id1.name == id2.name,
_ => *t1 == *t2
}
} else {
match ei.elts[idx].node.clone() {
/* need to descend into sequence */
- MatchSeq(ref matchers, ref sep, zero_ok,
+ MatchSeq(ref matchers, ref sep, kleene_op,
match_idx_lo, match_idx_hi) => {
- if zero_ok {
+ if kleene_op == ast::ZeroOrMore {
let mut new_ei = ei.clone();
new_ei.idx += 1u;
//we specifically matched zero repeats.
// Built-in nonterminals never start with these tokens,
// so we can eliminate them from consideration.
match tok {
- token::RPAREN |
- token::RBRACE |
- token::RBRACKET => {},
+ token::RParen |
+ token::RBrace |
+ token::RBracket => {},
_ => bb_eis.push(ei)
}
}
}
/* error messages here could be improved with links to orig. rules */
- if token_name_eq(&tok, &EOF) {
+ if token_name_eq(&tok, &token::Eof) {
if eof_eis.len() == 1u {
let mut v = Vec::new();
for dv in eof_eis.get_mut(0).matches.iter_mut() {
token::get_ident(name),
token::get_ident(bind))).to_string()
}
- _ => fail!()
+ _ => panic!()
} }).collect::<Vec<String>>().connect(" or ");
return Error(sp, format!(
"local ambiguity: multiple parsing options: \
nts, next_eis.len()).to_string());
} else if bb_eis.len() == 0u && next_eis.len() == 0u {
return Failure(sp, format!("no rules expected the token `{}`",
- token::to_string(&tok)).to_string());
+ pprust::token_to_string(&tok)).to_string());
} else if next_eis.len() > 0u {
/* Now process the next token */
while next_eis.len() > 0u {
parse_nt(&mut rust_parser, name_string.get()))));
ei.idx += 1u;
}
- _ => fail!()
+ _ => panic!()
}
cur_eis.push(ei);
"ty" => token::NtTy(p.parse_ty(false /* no need to disambiguate*/)),
// this could be handled like a token, since it is one
"ident" => match p.token {
- token::IDENT(sn,b) => { p.bump(); token::NtIdent(box sn,b) }
+ token::Ident(sn,b) => { p.bump(); token::NtIdent(box sn,b) }
_ => {
- let token_str = token::to_string(&p.token);
+ let token_str = pprust::token_to_string(&p.token);
p.fatal((format!("expected ident, found {}",
token_str.as_slice())).as_slice())
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use ast::{Ident, Matcher_, Matcher, MatchTok, MatchNonterminal, MatchSeq, TTDelim};
+use ast::{Ident, Matcher_, Matcher, MatchTok, MatchNonterminal, MatchSeq, TtDelimited};
use ast;
use codemap::{Span, Spanned, DUMMY_SP};
use ext::base::{ExtCtxt, MacResult, MacroDef};
use parse::parser::Parser;
use parse::attr::ParserAttr;
use parse::token::{special_idents, gensym_ident};
-use parse::token::{FAT_ARROW, SEMI, NtMatchers, NtTT, EOF};
+use parse::token::{NtMatchers, NtTT};
use parse::token;
use print;
use ptr::P;
/// silently drop anything. `allow_semi` is so that "optional"
/// semicolons at the end of normal expressions aren't complained
/// about e.g. the semicolon in `macro_rules! kapow( () => {
- /// fail!(); } )` doesn't get picked up by .parse_expr(), but it's
+ /// panic!(); } )` doesn't get picked up by .parse_expr(), but it's
/// allowed to be there.
fn ensure_complete_parse(&self, allow_semi: bool) {
let mut parser = self.parser.borrow_mut();
- if allow_semi && parser.token == SEMI {
+ if allow_semi && parser.token == token::Semi {
parser.bump()
}
- if parser.token != EOF {
+ if parser.token != token::Eof {
let token_str = parser.this_token_to_string();
let msg = format!("macro expansion ignores token `{}` and any \
following",
loop {
let mut parser = self.parser.borrow_mut();
match parser.token {
- EOF => break,
+ token::Eof => break,
_ => {
let attrs = parser.parse_outer_attributes();
ret.push(parser.parse_method(attrs, ast::Inherited))
rhses: &[Rc<NamedMatch>])
-> Box<MacResult+'cx> {
if cx.trace_macros() {
- println!("{}! {} {} {}",
+ println!("{}! {{ {} }}",
token::get_ident(name),
- "{",
- print::pprust::tt_to_string(&TTDelim(Rc::new(arg.iter()
- .map(|x| (*x).clone())
- .collect()))),
- "}");
+ print::pprust::tts_to_string(arg));
}
// Which arm's failure should we report? (the one furthest along)
// okay, what's your transcriber?
MatchedNonterminal(NtTT(ref tt)) => {
match **tt {
- // cut off delimiters; don't parse 'em
- TTDelim(ref tts) => {
- (*tts).slice(1u,(*tts).len()-1u)
- .iter()
- .map(|x| (*x).clone())
- .collect()
- }
- _ => cx.span_fatal(
- sp, "macro rhs must be delimited")
+ // ignore delimiters
+ TtDelimited(_, ref delimed) => {
+ let (_, ref tts, _) = **delimed;
+ tts.clone()
+ },
+ _ => cx.span_fatal(sp, "macro rhs must be delimited"),
}
},
_ => cx.span_bug(sp, "bad thing in rhs")
let argument_gram = vec!(
ms(MatchSeq(vec!(
ms(MatchNonterminal(lhs_nm, special_idents::matchers, 0u)),
- ms(MatchTok(FAT_ARROW)),
- ms(MatchNonterminal(rhs_nm, special_idents::tt, 1u))), Some(SEMI), false, 0u, 2u)),
+ ms(MatchTok(token::FatArrow)),
+ ms(MatchNonterminal(rhs_nm, special_idents::tt, 1u))),
+ Some(token::Semi), ast::OneOrMore, 0u, 2u)),
//to phase into semicolon-termination instead of
//semicolon-separation
- ms(MatchSeq(vec!(ms(MatchTok(SEMI))), None, true, 2u, 2u)));
+ ms(MatchSeq(vec!(ms(MatchTok(token::Semi))), None,
+ ast::ZeroOrMore, 2u, 2u)));
// Parse the macro_rules! invocation (`none` is for no interpolations):
// except according to those terms.
use ast;
-use ast::{TokenTree, TTDelim, TTTok, TTSeq, TTNonterminal, Ident};
+use ast::{TokenTree, TtDelimited, TtToken, TtSequence, TtNonterminal, Ident};
use codemap::{Span, DUMMY_SP};
use diagnostic::SpanHandler;
use ext::tt::macro_parser::{NamedMatch, MatchedSeq, MatchedNonterminal};
-use parse::token::{EOF, INTERPOLATED, IDENT, Token, NtIdent};
+use parse::token::{Token, NtIdent};
use parse::token;
use parse::lexer::TokenAndSpan;
use std::rc::Rc;
+use std::ops::Add;
use std::collections::HashMap;
///an unzipping of `TokenTree`s
}
/// This can do Macro-By-Example transcription. On the other hand, if
-/// `src` contains no `TTSeq`s and `TTNonterminal`s, `interp` can (and
+/// `src` contains no `TtSequence`s and `TtNonterminal`s, `interp` can (and
/// should) be none.
pub fn new_tt_reader<'a>(sp_diag: &'a SpanHandler,
interp: Option<HashMap<Ident, Rc<NamedMatch>>>,
repeat_idx: Vec::new(),
repeat_len: Vec::new(),
/* dummy values, never read: */
- cur_tok: EOF,
+ cur_tok: token::Eof,
cur_span: DUMMY_SP,
};
tt_next_token(&mut r); /* get cur_tok and cur_span set up */
LisContradiction(String),
}
-fn lis_merge(lhs: LockstepIterSize, rhs: LockstepIterSize) -> LockstepIterSize {
- match lhs {
- LisUnconstrained => rhs.clone(),
- LisContradiction(_) => lhs.clone(),
- LisConstraint(l_len, l_id) => match rhs {
- LisUnconstrained => lhs.clone(),
- LisContradiction(_) => rhs.clone(),
- LisConstraint(r_len, _) if l_len == r_len => lhs.clone(),
- LisConstraint(r_len, r_id) => {
- let l_n = token::get_ident(l_id);
- let r_n = token::get_ident(r_id);
- LisContradiction(format!("inconsistent lockstep iteration: \
- '{}' has {} items, but '{}' has {}",
- l_n, l_len, r_n, r_len).to_string())
- }
+impl Add<LockstepIterSize, LockstepIterSize> for LockstepIterSize {
+ fn add(&self, other: &LockstepIterSize) -> LockstepIterSize {
+ match *self {
+ LisUnconstrained => other.clone(),
+ LisContradiction(_) => self.clone(),
+ LisConstraint(l_len, l_id) => match *other {
+ LisUnconstrained => self.clone(),
+ LisContradiction(_) => other.clone(),
+ LisConstraint(r_len, _) if l_len == r_len => self.clone(),
+ LisConstraint(r_len, r_id) => {
+ let l_n = token::get_ident(l_id);
+ let r_n = token::get_ident(r_id);
+ LisContradiction(format!("inconsistent lockstep iteration: \
+ '{}' has {} items, but '{}' has {}",
+ l_n, l_len, r_n, r_len).to_string())
+ }
+ },
}
}
}
fn lockstep_iter_size(t: &TokenTree, r: &TtReader) -> LockstepIterSize {
match *t {
- TTDelim(ref tts) | TTSeq(_, ref tts, _, _) => {
- tts.iter().fold(LisUnconstrained, |lis, tt| {
- lis_merge(lis, lockstep_iter_size(tt, r))
+ TtDelimited(_, ref delimed) => {
+ let (_, ref tts, _) = **delimed;
+ tts.iter().fold(LisUnconstrained, |size, tt| {
+ size + lockstep_iter_size(tt, r)
})
- }
- TTTok(..) => LisUnconstrained,
- TTNonterminal(_, name) => match *lookup_cur_matched(r, name) {
+ },
+ TtSequence(_, ref tts, _, _) => {
+ tts.iter().fold(LisUnconstrained, |size, tt| {
+ size + lockstep_iter_size(tt, r)
+ })
+ },
+ TtToken(..) => LisUnconstrained,
+ TtNonterminal(_, name) => match *lookup_cur_matched(r, name) {
MatchedNonterminal(_) => LisUnconstrained,
MatchedSeq(ref ads, _) => LisConstraint(ads.len(), name)
- }
+ },
}
}
loop {
let should_pop = match r.stack.last() {
None => {
- assert_eq!(ret_val.tok, EOF);
+ assert_eq!(ret_val.tok, token::Eof);
return ret_val;
}
Some(frame) => {
let prev = r.stack.pop().unwrap();
match r.stack.last_mut() {
None => {
- r.cur_tok = EOF;
+ r.cur_tok = token::Eof;
return ret_val;
}
Some(frame) => {
}
}
}
- loop { /* because it's easiest, this handles `TTDelim` not starting
- with a `TTTok`, even though it won't happen */
+ loop { /* because it's easiest, this handles `TtDelimited` not starting
+ with a `TtToken`, even though it won't happen */
let t = {
let frame = r.stack.last().unwrap();
// FIXME(pcwalton): Bad copy.
(*frame.forest)[frame.idx].clone()
};
match t {
- TTDelim(tts) => {
+ TtDelimited(_, ref delimed) => {
+ let (ref open, ref tts, ref close) = **delimed;
+ let mut forest = Vec::with_capacity(1 + tts.len() + 1);
+ forest.push(open.to_tt());
+ forest.extend(tts.iter().map(|x| (*x).clone()));
+ forest.push(close.to_tt());
+
r.stack.push(TtFrame {
- forest: tts,
+ forest: Rc::new(forest),
idx: 0,
dotdotdoted: false,
sep: None
});
// if this could be 0-length, we'd need to potentially recur here
}
- TTTok(sp, tok) => {
+ TtToken(sp, tok) => {
r.cur_span = sp;
r.cur_tok = tok;
r.stack.last_mut().unwrap().idx += 1;
return ret_val;
}
- TTSeq(sp, tts, sep, zerok) => {
+ TtSequence(sp, tts, sep, kleene_op) => {
// FIXME(pcwalton): Bad copy.
- match lockstep_iter_size(&TTSeq(sp, tts.clone(), sep.clone(), zerok), r) {
+ match lockstep_iter_size(&TtSequence(sp, tts.clone(), sep.clone(), kleene_op), r) {
LisUnconstrained => {
r.sp_diag.span_fatal(
sp.clone(), /* blame macro writer */
}
LisConstraint(len, _) => {
if len == 0 {
- if !zerok {
+ if kleene_op == ast::OneOrMore {
// FIXME #2887 blame invoker
r.sp_diag.span_fatal(sp.clone(),
"this must repeat at least once");
}
}
// FIXME #2887: think about span stuff here
- TTNonterminal(sp, ident) => {
+ TtNonterminal(sp, ident) => {
r.stack.last_mut().unwrap().idx += 1;
match *lookup_cur_matched(r, ident) {
/* sidestep the interpolation tricks for ident because
(b) we actually can, since it's a token. */
MatchedNonterminal(NtIdent(box sn, b)) => {
r.cur_span = sp;
- r.cur_tok = IDENT(sn,b);
+ r.cur_tok = token::Ident(sn,b);
return ret_val;
}
MatchedNonterminal(ref other_whole_nt) => {
// FIXME(pcwalton): Bad copy.
r.cur_span = sp;
- r.cur_tok = INTERPOLATED((*other_whole_nt).clone());
+ r.cur_tok = token::Interpolated((*other_whole_nt).clone());
return ret_val;
}
MatchedSeq(..) => {
}
fn fold_mac(&mut self, _macro: Mac) -> Mac {
- fail!("fold_mac disabled by default");
+ panic!("fold_mac disabled by default");
// NB: see note about macros above.
// if you really want a folder that
// works on macros, use this
pub fn noop_fold_tt<T: Folder>(tt: &TokenTree, fld: &mut T) -> TokenTree {
match *tt {
- TTTok(span, ref tok) =>
- TTTok(span, fld.fold_token(tok.clone())),
- TTDelim(ref tts) => TTDelim(Rc::new(fld.fold_tts(tts.as_slice()))),
- TTSeq(span, ref pattern, ref sep, is_optional) =>
- TTSeq(span,
- Rc::new(fld.fold_tts(pattern.as_slice())),
- sep.clone().map(|tok| fld.fold_token(tok)),
- is_optional),
- TTNonterminal(sp,ref ident) =>
- TTNonterminal(sp,fld.fold_ident(*ident))
+ TtToken(span, ref tok) =>
+ TtToken(span, fld.fold_token(tok.clone())),
+ TtDelimited(span, ref delimed) => {
+ let (ref open, ref tts, ref close) = **delimed;
+ TtDelimited(span, Rc::new((
+ Delimiter {
+ span: open.span,
+ token: fld.fold_token(open.token.clone())
+ },
+ fld.fold_tts(tts.as_slice()),
+ Delimiter {
+ span: close.span,
+ token: fld.fold_token(close.token.clone())
+ },
+ )))
+ },
+ TtSequence(span, ref pattern, ref sep, is_optional) =>
+ TtSequence(span,
+ Rc::new(fld.fold_tts(pattern.as_slice())),
+ sep.clone().map(|tok| fld.fold_token(tok)),
+ is_optional),
+ TtNonterminal(sp,ref ident) =>
+ TtNonterminal(sp,fld.fold_ident(*ident))
}
}
// apply ident folder if it's an ident, apply other folds to interpolated nodes
pub fn noop_fold_token<T: Folder>(t: token::Token, fld: &mut T) -> token::Token {
match t {
- token::IDENT(id, followed_by_colons) => {
- token::IDENT(fld.fold_ident(id), followed_by_colons)
+ token::Ident(id, followed_by_colons) => {
+ token::Ident(fld.fold_ident(id), followed_by_colons)
}
- token::LIFETIME(id) => token::LIFETIME(fld.fold_ident(id)),
- token::INTERPOLATED(nt) => token::INTERPOLATED(fld.fold_interpolated(nt)),
+ token::Lifetime(id) => token::Lifetime(fld.fold_ident(id)),
+ token::Interpolated(nt) => token::Interpolated(fld.fold_interpolated(nt)),
_ => t
}
}
let a_val = $a;
let b_val = $b;
if !(pred_val(a_val.as_slice(),b_val.as_slice())) {
- fail!("expected args satisfying {}, got {} and {}",
+ panic!("expected args satisfying {}, got {} and {}",
$predname, a_val, b_val);
}
}
pub fn into_vec(self) -> Vec<T> {
// null is ok, because len == 0 in that case, as required by Vec.
unsafe {
- let ret = Vec::from_raw_parts(self.len, self.len, self.data);
+ let ret = Vec::from_raw_parts(self.data, self.len, self.len);
// the vector owns the allocation now
mem::forget(self);
ret
use parse::common::*; //resolve bug?
use parse::token;
use parse::parser::Parser;
-use parse::token::INTERPOLATED;
use ptr::P;
/// A parser that can parse attributes.
debug!("parse_outer_attributes: self.token={}",
self.token);
match self.token {
- token::POUND => {
+ token::Pound => {
attrs.push(self.parse_attribute(false));
}
- token::DOC_COMMENT(s) => {
+ token::DocComment(s) => {
let attr = ::attr::mk_sugared_doc_attr(
attr::mk_attr_id(),
self.id_to_interned_str(s.ident()),
debug!("parse_attributes: permit_inner={} self.token={}",
permit_inner, self.token);
let (span, value, mut style) = match self.token {
- token::POUND => {
+ token::Pound => {
let lo = self.span.lo;
self.bump();
- let style = if self.eat(&token::NOT) {
+ let style = if self.eat(&token::Not) {
if !permit_inner {
let span = self.span;
self.span_err(span,
ast::AttrOuter
};
- self.expect(&token::LBRACKET);
+ self.expect(&token::LBracket);
let meta_item = self.parse_meta_item();
let hi = self.span.hi;
- self.expect(&token::RBRACKET);
+ self.expect(&token::RBracket);
(mk_sp(lo, hi), meta_item, style)
}
}
};
- if permit_inner && self.eat(&token::SEMI) {
+ if permit_inner && self.eat(&token::Semi) {
self.span_warn(span, "this inner attribute syntax is deprecated. \
The new syntax is `#![foo]`, with a bang and no semicolon.");
style = ast::AttrInner;
let mut next_outer_attrs: Vec<ast::Attribute> = Vec::new();
loop {
let attr = match self.token {
- token::POUND => {
+ token::Pound => {
self.parse_attribute(true)
}
- token::DOC_COMMENT(s) => {
+ token::DocComment(s) => {
// we need to get the position of this token before we bump.
let Span { lo, hi, .. } = self.span;
self.bump();
/// | IDENT meta_seq
fn parse_meta_item(&mut self) -> P<ast::MetaItem> {
let nt_meta = match self.token {
- token::INTERPOLATED(token::NtMeta(ref e)) => {
+ token::Interpolated(token::NtMeta(ref e)) => {
Some(e.clone())
}
_ => None
let ident = self.parse_ident();
let name = self.id_to_interned_str(ident);
match self.token {
- token::EQ => {
+ token::Eq => {
self.bump();
let lit = self.parse_lit();
// FIXME #623 Non-string meta items are not serialized correctly;
let hi = self.span.hi;
P(spanned(lo, hi, ast::MetaNameValue(name, lit)))
}
- token::LPAREN => {
+ token::LParen => {
let inner_items = self.parse_meta_seq();
let hi = self.span.hi;
P(spanned(lo, hi, ast::MetaList(name, inner_items)))
/// matches meta_seq = ( COMMASEP(meta_item) )
fn parse_meta_seq(&mut self) -> Vec<P<ast::MetaItem>> {
- self.parse_seq(&token::LPAREN,
- &token::RPAREN,
- seq_sep_trailing_disallowed(token::COMMA),
+ self.parse_seq(&token::LParen,
+ &token::RParen,
+ seq_sep_trailing_disallowed(token::Comma),
|p| p.parse_meta_item()).node
}
fn parse_optional_meta(&mut self) -> Vec<P<ast::MetaItem>> {
match self.token {
- token::LPAREN => self.parse_meta_seq(),
+ token::LParen => self.parse_meta_seq(),
_ => Vec::new()
}
}
use parse::lexer::{StringReader, TokenAndSpan};
use parse::lexer::is_block_doc_comment;
use parse::lexer;
-use parse::token;
+use print::pprust;
use std::io;
use std::str;
return lines.connect("\n");
}
- fail!("not a doc-comment: {}", comment);
+ panic!("not a doc-comment: {}", comment);
}
fn push_blank_line_comment(rdr: &StringReader, comments: &mut Vec<Comment>) {
read_block_comment(rdr, code_to_the_left, comments);
} else if rdr.curr_is('#') && rdr.nextch_is('!') {
read_shebang_comment(rdr, code_to_the_left, comments);
- } else { fail!(); }
+ } else { panic!(); }
debug!("<<< consume comment");
}
rdr.next_token();
//discard, and look ahead; we're working with internal state
let TokenAndSpan { tok, sp } = rdr.peek();
- if token::is_lit(&tok) {
+ if tok.is_lit() {
rdr.with_str_from(bstart, |s| {
debug!("tok lit: {}", s);
literals.push(Literal {lit: s.to_string(), pos: sp.lo});
})
} else {
- debug!("tok: {}", token::to_string(&tok));
+ debug!("tok: {}", pprust::token_to_string(&tok));
}
first_read = false;
}
/// Return the next token. EFFECT: advances the string_reader.
fn next_token(&mut self) -> TokenAndSpan {
let ret_val = TokenAndSpan {
- tok: replace(&mut self.peek_tok, token::UNDERSCORE),
+ tok: replace(&mut self.peek_tok, token::Underscore),
sp: self.peek_span,
};
self.advance_token();
impl<'a> Reader for TtReader<'a> {
fn is_eof(&self) -> bool {
- self.cur_tok == token::EOF
+ self.cur_tok == token::Eof
}
fn next_token(&mut self) -> TokenAndSpan {
let r = tt_next_token(self);
curr: Some('\n'),
filemap: filemap,
/* dummy values; not read */
- peek_tok: token::EOF,
+ peek_tok: token::Eof,
peek_span: codemap::DUMMY_SP,
read_embedded_ident: false,
};
},
None => {
if self.is_eof() {
- self.peek_tok = token::EOF;
+ self.peek_tok = token::Eof;
} else {
let start_bytepos = self.last_pos;
self.peek_tok = self.next_token_inner();
return self.with_str_from(start_bpos, |string| {
// but comments with only more "/"s are not
let tok = if is_doc_comment(string) {
- token::DOC_COMMENT(token::intern(string))
+ token::DocComment(token::intern(string))
} else {
- token::COMMENT
+ token::Comment
};
return Some(TokenAndSpan{
let start_bpos = self.last_pos - BytePos(2);
while !self.curr_is('\n') && !self.is_eof() { self.bump(); }
return Some(TokenAndSpan {
- tok: token::COMMENT,
+ tok: token::Comment,
sp: codemap::mk_sp(start_bpos, self.last_pos)
});
}
let start = self.last_pos;
while !self.curr_is('\n') && !self.is_eof() { self.bump(); }
return Some(TokenAndSpan {
- tok: token::SHEBANG(self.name_from(start)),
+ tok: token::Shebang(self.name_from(start)),
sp: codemap::mk_sp(start, self.last_pos)
});
}
let start_bpos = self.last_pos;
while is_whitespace(self.curr) { self.bump(); }
let c = Some(TokenAndSpan {
- tok: token::WS,
+ tok: token::Whitespace,
sp: codemap::mk_sp(start_bpos, self.last_pos)
});
debug!("scanning whitespace: {}", c);
self.translate_crlf(start_bpos, string,
"bare CR not allowed in block doc-comment")
} else { string.into_maybe_owned() };
- token::DOC_COMMENT(token::intern(string.as_slice()))
+ token::DocComment(token::intern(string.as_slice()))
} else {
- token::COMMENT
+ token::Comment
};
Some(TokenAndSpan{
whence: &str) {
match r.curr {
Some(r_c) if r_c == c => r.bump(),
- Some(r_c) => fail!("expected {}, hit {}, {}", described_c, r_c, whence),
- None => fail!("expected {}, hit EOF, {}", described_c, whence),
+ Some(r_c) => panic!("expected {}, hit {}, {}", described_c, r_c, whence),
+ None => panic!("expected {}, hit EOF, {}", described_c, whence),
}
}
self.scan_digits(base);
let encoded_name : u32 = self.with_str_from(start_bpos, |s| {
num::from_str_radix(s, 10).unwrap_or_else(|| {
- fail!("expected digits representing a name, got `{}`, {}, range [{},{}]",
+ panic!("expected digits representing a name, got `{}`, {}, range [{},{}]",
s, whence, start_bpos, self.last_pos);
})
});
self.scan_digits(base);
let encoded_ctxt : ast::SyntaxContext = self.with_str_from(start_bpos, |s| {
num::from_str_radix(s, 10).unwrap_or_else(|| {
- fail!("expected digits representing a ctxt, got `{}`, {}", s, whence);
+ panic!("expected digits representing a ctxt, got `{}`, {}", s, whence);
})
});
}
'u' | 'i' => {
self.scan_int_suffix();
- return token::LIT_INTEGER(self.name_from(start_bpos));
+ return token::LitInteger(self.name_from(start_bpos));
},
'f' => {
let last_pos = self.last_pos;
self.scan_float_suffix();
self.check_float_base(start_bpos, last_pos, base);
- return token::LIT_FLOAT(self.name_from(start_bpos));
+ return token::LitFloat(self.name_from(start_bpos));
}
_ => {
// just a 0
- return token::LIT_INTEGER(self.name_from(start_bpos));
+ return token::LitInteger(self.name_from(start_bpos));
}
}
} else if c.is_digit_radix(10) {
self.err_span_(start_bpos, self.last_pos, "no valid digits found for number");
// eat any suffix
self.scan_int_suffix();
- return token::LIT_INTEGER(token::intern("0"));
+ return token::LitInteger(token::intern("0"));
}
// might be a float, but don't be greedy if this is actually an
}
let last_pos = self.last_pos;
self.check_float_base(start_bpos, last_pos, base);
- return token::LIT_FLOAT(self.name_from(start_bpos));
+ return token::LitFloat(self.name_from(start_bpos));
} else if self.curr_is('f') {
// or it might be an integer literal suffixed as a float
self.scan_float_suffix();
let last_pos = self.last_pos;
self.check_float_base(start_bpos, last_pos, base);
- return token::LIT_FLOAT(self.name_from(start_bpos));
+ return token::LitFloat(self.name_from(start_bpos));
} else {
// it might be a float if it has an exponent
if self.curr_is('e') || self.curr_is('E') {
self.scan_float_suffix();
let last_pos = self.last_pos;
self.check_float_base(start_bpos, last_pos, base);
- return token::LIT_FLOAT(self.name_from(start_bpos));
+ return token::LitFloat(self.name_from(start_bpos));
}
// but we certainly have an integer!
self.scan_int_suffix();
- return token::LIT_INTEGER(self.name_from(start_bpos));
+ return token::LitInteger(self.name_from(start_bpos));
}
}
}
}
- fn binop(&mut self, op: token::BinOp) -> token::Token {
+ fn binop(&mut self, op: token::BinOpToken) -> token::Token {
self.bump();
if self.curr_is('=') {
self.bump();
- return token::BINOPEQ(op);
+ return token::BinOpEq(op);
} else {
- return token::BINOP(op);
+ return token::BinOp(op);
}
}
return self.with_str_from(start, |string| {
if string == "_" {
- token::UNDERSCORE
+ token::Underscore
} else {
- let is_mod_name = self.curr_is(':') && self.nextch_is(':');
-
// FIXME: perform NFKC normalization here. (Issue #2253)
- token::IDENT(str_to_ident(string), is_mod_name)
+ if self.curr_is(':') && self.nextch_is(':') {
+ token::Ident(str_to_ident(string), token::ModName)
+ } else {
+ token::Ident(str_to_ident(string), token::Plain)
+ }
}
- })
+ });
}
if is_dec_digit(c) {
match (c.unwrap(), self.nextch(), self.nextnextch()) {
('\x00', Some('n'), Some('a')) => {
let ast_ident = self.scan_embedded_hygienic_ident();
- let is_mod_name = self.curr_is(':') && self.nextch_is(':');
- return token::IDENT(ast_ident, is_mod_name);
+ return if self.curr_is(':') && self.nextch_is(':') {
+ token::Ident(ast_ident, token::ModName)
+ } else {
+ token::Ident(ast_ident, token::Plain)
+ };
}
_ => {}
}
match c.expect("next_token_inner called at EOF") {
// One-byte tokens.
- ';' => { self.bump(); return token::SEMI; }
- ',' => { self.bump(); return token::COMMA; }
+ ';' => { self.bump(); return token::Semi; }
+ ',' => { self.bump(); return token::Comma; }
'.' => {
self.bump();
return if self.curr_is('.') {
self.bump();
if self.curr_is('.') {
self.bump();
- token::DOTDOTDOT
+ token::DotDotDot
} else {
- token::DOTDOT
+ token::DotDot
}
} else {
- token::DOT
+ token::Dot
};
}
- '(' => { self.bump(); return token::LPAREN; }
- ')' => { self.bump(); return token::RPAREN; }
- '{' => { self.bump(); return token::LBRACE; }
- '}' => { self.bump(); return token::RBRACE; }
- '[' => { self.bump(); return token::LBRACKET; }
- ']' => { self.bump(); return token::RBRACKET; }
- '@' => { self.bump(); return token::AT; }
- '#' => { self.bump(); return token::POUND; }
- '~' => { self.bump(); return token::TILDE; }
- '?' => { self.bump(); return token::QUESTION; }
+ '(' => { self.bump(); return token::LParen; }
+ ')' => { self.bump(); return token::RParen; }
+ '{' => { self.bump(); return token::LBrace; }
+ '}' => { self.bump(); return token::RBrace; }
+ '[' => { self.bump(); return token::LBracket; }
+ ']' => { self.bump(); return token::RBracket; }
+ '@' => { self.bump(); return token::At; }
+ '#' => { self.bump(); return token::Pound; }
+ '~' => { self.bump(); return token::Tilde; }
+ '?' => { self.bump(); return token::Question; }
':' => {
self.bump();
if self.curr_is(':') {
self.bump();
- return token::MOD_SEP;
+ return token::ModSep;
} else {
- return token::COLON;
+ return token::Colon;
}
}
- '$' => { self.bump(); return token::DOLLAR; }
+ '$' => { self.bump(); return token::Dollar; }
// Multi-byte tokens.
'=' => {
self.bump();
if self.curr_is('=') {
self.bump();
- return token::EQEQ;
+ return token::EqEq;
} else if self.curr_is('>') {
self.bump();
- return token::FAT_ARROW;
+ return token::FatArrow;
} else {
- return token::EQ;
+ return token::Eq;
}
}
'!' => {
self.bump();
if self.curr_is('=') {
self.bump();
- return token::NE;
- } else { return token::NOT; }
+ return token::Ne;
+ } else { return token::Not; }
}
'<' => {
self.bump();
match self.curr.unwrap_or('\x00') {
- '=' => { self.bump(); return token::LE; }
- '<' => { return self.binop(token::SHL); }
+ '=' => { self.bump(); return token::Le; }
+ '<' => { return self.binop(token::Shl); }
'-' => {
self.bump();
match self.curr.unwrap_or('\x00') {
- _ => { return token::LARROW; }
+ _ => { return token::LArrow; }
}
}
- _ => { return token::LT; }
+ _ => { return token::Lt; }
}
}
'>' => {
self.bump();
match self.curr.unwrap_or('\x00') {
- '=' => { self.bump(); return token::GE; }
- '>' => { return self.binop(token::SHR); }
- _ => { return token::GT; }
+ '=' => { self.bump(); return token::Ge; }
+ '>' => { return self.binop(token::Shr); }
+ _ => { return token::Gt; }
}
}
'\'' => {
str_to_ident(lifetime_name)
});
let keyword_checking_token =
- &token::IDENT(keyword_checking_ident, false);
+ &token::Ident(keyword_checking_ident, token::Plain);
let last_bpos = self.last_pos;
- if token::is_keyword(token::keywords::Self,
- keyword_checking_token) {
+ if keyword_checking_token.is_keyword(token::keywords::Self) {
self.err_span_(start,
last_bpos,
"invalid lifetime name: 'self \
is no longer a special lifetime");
- } else if token::is_any_keyword(keyword_checking_token) &&
- !token::is_keyword(token::keywords::Static,
- keyword_checking_token) {
+ } else if keyword_checking_token.is_any_keyword() &&
+ !keyword_checking_token.is_keyword(token::keywords::Static)
+ {
self.err_span_(start,
last_bpos,
"invalid lifetime name");
}
- return token::LIFETIME(ident);
+ return token::Lifetime(ident);
}
// Otherwise it is a character constant:
}
let id = if valid { self.name_from(start) } else { token::intern("0") };
self.bump(); // advance curr past token
- return token::LIT_CHAR(id);
+ return token::LitChar(id);
}
'b' => {
self.bump();
Some('\'') => self.scan_byte(),
Some('"') => self.scan_byte_string(),
Some('r') => self.scan_raw_byte_string(),
- _ => unreachable!() // Should have been a token::IDENT above.
+ _ => unreachable!() // Should have been a token::Ident above.
};
}
let id = if valid { self.name_from(start_bpos + BytePos(1)) }
else { token::intern("??") };
self.bump();
- return token::LIT_STR(id);
+ return token::LitStr(id);
}
'r' => {
let start_bpos = self.last_pos;
} else {
token::intern("??")
};
- return token::LIT_STR_RAW(id, hash_count);
+ return token::LitStrRaw(id, hash_count);
}
'-' => {
if self.nextch_is('>') {
self.bump();
self.bump();
- return token::RARROW;
- } else { return self.binop(token::MINUS); }
+ return token::RArrow;
+ } else { return self.binop(token::Minus); }
}
'&' => {
if self.nextch_is('&') {
self.bump();
self.bump();
- return token::ANDAND;
- } else { return self.binop(token::AND); }
+ return token::AndAnd;
+ } else { return self.binop(token::And); }
}
'|' => {
match self.nextch() {
- Some('|') => { self.bump(); self.bump(); return token::OROR; }
- _ => { return self.binop(token::OR); }
+ Some('|') => { self.bump(); self.bump(); return token::OrOr; }
+ _ => { return self.binop(token::Or); }
}
}
- '+' => { return self.binop(token::PLUS); }
- '*' => { return self.binop(token::STAR); }
- '/' => { return self.binop(token::SLASH); }
- '^' => { return self.binop(token::CARET); }
- '%' => { return self.binop(token::PERCENT); }
+ '+' => { return self.binop(token::Plus); }
+ '*' => { return self.binop(token::Star); }
+ '/' => { return self.binop(token::Slash); }
+ '^' => { return self.binop(token::Caret); }
+ '%' => { return self.binop(token::Percent); }
c => {
let last_bpos = self.last_pos;
let bpos = self.pos;
let id = if valid { self.name_from(start) } else { token::intern("??") };
self.bump(); // advance curr past token
- return token::LIT_BYTE(id);
+ return token::LitByte(id);
}
fn scan_byte_string(&mut self) -> token::Token {
}
let id = if valid { self.name_from(start) } else { token::intern("??") };
self.bump();
- return token::LIT_BINARY(id);
+ return token::LitBinary(id);
}
fn scan_raw_byte_string(&mut self) -> token::Token {
self.bump();
}
self.bump();
- return token::LIT_BINARY_RAW(self.name_from_to(content_start_bpos, content_end_bpos),
+ return token::LitBinaryRaw(self.name_from_to(content_start_bpos, content_end_bpos),
hash_count);
}
}
"/* my source file */ \
fn main() { println!(\"zebra\"); }\n".to_string());
let id = str_to_ident("fn");
- assert_eq!(string_reader.next_token().tok, token::COMMENT);
- assert_eq!(string_reader.next_token().tok, token::WS);
+ assert_eq!(string_reader.next_token().tok, token::Comment);
+ assert_eq!(string_reader.next_token().tok, token::Whitespace);
let tok1 = string_reader.next_token();
let tok2 = TokenAndSpan{
- tok:token::IDENT(id, false),
+ tok:token::Ident(id, token::Plain),
sp:Span {lo:BytePos(21),hi:BytePos(23),expn_id: NO_EXPANSION}};
assert_eq!(tok1,tok2);
- assert_eq!(string_reader.next_token().tok, token::WS);
+ assert_eq!(string_reader.next_token().tok, token::Whitespace);
// the 'main' id is already read:
assert_eq!(string_reader.last_pos.clone(), BytePos(28));
// read another token:
let tok3 = string_reader.next_token();
let tok4 = TokenAndSpan{
- tok:token::IDENT(str_to_ident("main"), false),
+ tok:token::Ident(str_to_ident("main"), token::Plain),
sp:Span {lo:BytePos(24),hi:BytePos(28),expn_id: NO_EXPANSION}};
assert_eq!(tok3,tok4);
// the lparen is already read:
}
}
- // make the identifier by looking up the string in the interner
+ #[cfg(stage0)]
fn mk_ident (id: &str, is_mod_name: bool) -> token::Token {
- token::IDENT (str_to_ident(id),is_mod_name)
+ token::Ident(str_to_ident(id), is_mod_name)
+ }
+
+ // make the identifier by looking up the string in the interner
+ #[cfg(not(stage0))]
+ fn mk_ident(id: &str, style: token::IdentStyle) -> token::Token {
+ token::Ident(str_to_ident(id), style)
}
#[test] fn doublecolonparsing () {
check_tokenization(setup(&mk_sh(), "a b".to_string()),
- vec!(mk_ident("a",false),
- token::WS,
- mk_ident("b",false)));
+ vec![mk_ident("a", token::Plain),
+ token::Whitespace,
+ mk_ident("b", token::Plain)]);
}
#[test] fn dcparsing_2 () {
check_tokenization(setup(&mk_sh(), "a::b".to_string()),
- vec!(mk_ident("a",true),
- token::MOD_SEP,
- mk_ident("b",false)));
+ vec![mk_ident("a",token::ModName),
+ token::ModSep,
+ mk_ident("b", token::Plain)]);
}
#[test] fn dcparsing_3 () {
check_tokenization(setup(&mk_sh(), "a ::b".to_string()),
- vec!(mk_ident("a",false),
- token::WS,
- token::MOD_SEP,
- mk_ident("b",false)));
+ vec![mk_ident("a", token::Plain),
+ token::Whitespace,
+ token::ModSep,
+ mk_ident("b", token::Plain)]);
}
#[test] fn dcparsing_4 () {
check_tokenization(setup(&mk_sh(), "a:: b".to_string()),
- vec!(mk_ident("a",true),
- token::MOD_SEP,
- token::WS,
- mk_ident("b",false)));
+ vec![mk_ident("a",token::ModName),
+ token::ModSep,
+ token::Whitespace,
+ mk_ident("b", token::Plain)]);
}
#[test] fn character_a() {
assert_eq!(setup(&mk_sh(), "'a'".to_string()).next_token().tok,
- token::LIT_CHAR(token::intern("a")));
+ token::LitChar(token::intern("a")));
}
#[test] fn character_space() {
assert_eq!(setup(&mk_sh(), "' '".to_string()).next_token().tok,
- token::LIT_CHAR(token::intern(" ")));
+ token::LitChar(token::intern(" ")));
}
#[test] fn character_escaped() {
assert_eq!(setup(&mk_sh(), "'\\n'".to_string()).next_token().tok,
- token::LIT_CHAR(token::intern("\\n")));
+ token::LitChar(token::intern("\\n")));
}
#[test] fn lifetime_name() {
assert_eq!(setup(&mk_sh(), "'abc".to_string()).next_token().tok,
- token::LIFETIME(token::str_to_ident("'abc")));
+ token::Lifetime(token::str_to_ident("'abc")));
}
#[test] fn raw_string() {
assert_eq!(setup(&mk_sh(),
"r###\"\"#a\\b\x00c\"\"###".to_string()).next_token()
.tok,
- token::LIT_STR_RAW(token::intern("\"#a\\b\x00c\""), 3));
+ token::LitStrRaw(token::intern("\"#a\\b\x00c\""), 3));
}
#[test] fn line_doc_comments() {
let sh = mk_sh();
let mut lexer = setup(&sh, "/* /* */ */'a'".to_string());
match lexer.next_token().tok {
- token::COMMENT => { },
- _ => fail!("expected a comment!")
+ token::Comment => { },
+ _ => panic!("expected a comment!")
}
- assert_eq!(lexer.next_token().tok, token::LIT_CHAR(token::intern("a")));
+ assert_eq!(lexer.next_token().tok, token::LitChar(token::intern("a")));
}
}
match v.checked_add(&count) {
Some(next) => { self.node_id.set(next); }
- None => fail!("Input too large, ran out of node ids!")
+ None => panic!("Input too large, ran out of node ids!")
}
v
'0' => Some('\0'),
_ => { None }
},
- _ => fail!("lexer accepted invalid char escape `{}`", lit)
+ _ => panic!("lexer accepted invalid char escape `{}`", lit)
};
match c {
match c {
'\\' => {
let ch = chars.peek().unwrap_or_else(|| {
- fail!("{}", error(i).as_slice())
+ panic!("{}", error(i).as_slice())
}).val1();
if ch == '\n' {
} else if ch == '\r' {
chars.next();
let ch = chars.peek().unwrap_or_else(|| {
- fail!("{}", error(i).as_slice())
+ panic!("{}", error(i).as_slice())
}).val1();
if ch != '\n' {
- fail!("lexer accepted bare CR");
+ panic!("lexer accepted bare CR");
}
eat(&mut chars);
} else {
},
'\r' => {
let ch = chars.peek().unwrap_or_else(|| {
- fail!("{}", error(i).as_slice())
+ panic!("{}", error(i).as_slice())
}).val1();
if ch != '\n' {
- fail!("lexer accepted bare CR");
+ panic!("lexer accepted bare CR");
}
chars.next();
res.push('\n');
Some(c) => {
if c == '\r' {
if *chars.peek().unwrap() != '\n' {
- fail!("lexer accepted bare CR");
+ panic!("lexer accepted bare CR");
}
chars.next();
res.push('\n');
match ::std::num::from_str_radix::<u64>(lit.slice(2, 4), 16) {
Some(c) =>
if c > 0xFF {
- fail!(err(2))
+ panic!(err(2))
} else {
return (c as u8, 4)
},
- None => fail!(err(3))
+ None => panic!(err(3))
}
}
};
b'\r' => {
chars.next();
if chars.peek().expect(em.as_slice()).val1() != b'\n' {
- fail!("lexer accepted bare CR");
+ panic!("lexer accepted bare CR");
}
eat(&mut chars);
}
Some((i, b'\r')) => {
let em = error(i);
if chars.peek().expect(em.as_slice()).val1() != b'\n' {
- fail!("lexer accepted bare CR");
+ panic!("lexer accepted bare CR");
}
chars.next();
res.push(b'\n');
}
// check the token-tree-ization of macros
- #[test] fn string_to_tts_macro () {
+ #[test]
+ fn string_to_tts_macro () {
let tts = string_to_tts("macro_rules! zip (($a)=>($a))".to_string());
let tts: &[ast::TokenTree] = tts.as_slice();
match tts {
- [ast::TTTok(_,_),
- ast::TTTok(_,token::NOT),
- ast::TTTok(_,_),
- ast::TTDelim(ref delim_elts)] => {
- let delim_elts: &[ast::TokenTree] = delim_elts.as_slice();
- match delim_elts {
- [ast::TTTok(_,token::LPAREN),
- ast::TTDelim(ref first_set),
- ast::TTTok(_,token::FAT_ARROW),
- ast::TTDelim(ref second_set),
- ast::TTTok(_,token::RPAREN)] => {
- let first_set: &[ast::TokenTree] =
- first_set.as_slice();
- match first_set {
- [ast::TTTok(_,token::LPAREN),
- ast::TTTok(_,token::DOLLAR),
- ast::TTTok(_,_),
- ast::TTTok(_,token::RPAREN)] => {
- let second_set: &[ast::TokenTree] =
- second_set.as_slice();
- match second_set {
- [ast::TTTok(_,token::LPAREN),
- ast::TTTok(_,token::DOLLAR),
- ast::TTTok(_,_),
- ast::TTTok(_,token::RPAREN)] => {
- assert_eq!("correct","correct")
- }
- _ => assert_eq!("wrong 4","correct")
- }
- },
- _ => {
- error!("failing value 3: {}",first_set);
- assert_eq!("wrong 3","correct")
- }
+ [ast::TtToken(_, token::Ident(name_macro_rules, token::Plain)),
+ ast::TtToken(_, token::Not),
+ ast::TtToken(_, token::Ident(name_zip, token::Plain)),
+ ast::TtDelimited(_, ref macro_delimed)]
+ if name_macro_rules.as_str() == "macro_rules"
+ && name_zip.as_str() == "zip" => {
+ let (ref macro_open, ref macro_tts, ref macro_close) = **macro_delimed;
+ match (macro_open, macro_tts.as_slice(), macro_close) {
+ (&ast::Delimiter { token: token::LParen, .. },
+ [ast::TtDelimited(_, ref first_delimed),
+ ast::TtToken(_, token::FatArrow),
+ ast::TtDelimited(_, ref second_delimed)],
+ &ast::Delimiter { token: token::RParen, .. }) => {
+ let (ref first_open, ref first_tts, ref first_close) = **first_delimed;
+ match (first_open, first_tts.as_slice(), first_close) {
+ (&ast::Delimiter { token: token::LParen, .. },
+ [ast::TtToken(_, token::Dollar),
+ ast::TtToken(_, token::Ident(name, token::Plain))],
+ &ast::Delimiter { token: token::RParen, .. })
+ if name.as_str() == "a" => {},
+ _ => panic!("value 3: {}", **first_delimed),
+ }
+ let (ref second_open, ref second_tts, ref second_close) = **second_delimed;
+ match (second_open, second_tts.as_slice(), second_close) {
+ (&ast::Delimiter { token: token::LParen, .. },
+ [ast::TtToken(_, token::Dollar),
+ ast::TtToken(_, token::Ident(name, token::Plain))],
+ &ast::Delimiter { token: token::RParen, .. })
+ if name.as_str() == "a" => {},
+ _ => panic!("value 4: {}", **second_delimed),
}
},
- _ => {
- error!("failing value 2: {}",delim_elts);
- assert_eq!("wrong","correct");
- }
+ _ => panic!("value 2: {}", **macro_delimed),
}
},
- _ => {
- error!("failing value: {}",tts);
- assert_eq!("wrong 1","correct");
- }
+ _ => panic!("value: {}",tts),
}
}
- #[test] fn string_to_tts_1 () {
+ #[test]
+ fn string_to_tts_1 () {
let tts = string_to_tts("fn a (b : int) { b; }".to_string());
assert_eq!(json::encode(&tts),
"[\
{\
- \"variant\":\"TTTok\",\
+ \"variant\":\"TtToken\",\
\"fields\":[\
null,\
{\
- \"variant\":\"IDENT\",\
+ \"variant\":\"Ident\",\
\"fields\":[\
\"fn\",\
- false\
+ \"Plain\"\
]\
}\
]\
},\
{\
- \"variant\":\"TTTok\",\
+ \"variant\":\"TtToken\",\
\"fields\":[\
null,\
{\
- \"variant\":\"IDENT\",\
+ \"variant\":\"Ident\",\
\"fields\":[\
\"a\",\
- false\
+ \"Plain\"\
]\
}\
]\
},\
{\
- \"variant\":\"TTDelim\",\
+ \"variant\":\"TtDelimited\",\
\"fields\":[\
+ null,\
[\
{\
- \"variant\":\"TTTok\",\
- \"fields\":[\
- null,\
- \"LPAREN\"\
- ]\
- },\
- {\
- \"variant\":\"TTTok\",\
- \"fields\":[\
- null,\
- {\
- \"variant\":\"IDENT\",\
- \"fields\":[\
- \"b\",\
- false\
- ]\
- }\
- ]\
+ \"span\":null,\
+ \"token\":\"LParen\"\
},\
+ [\
+ {\
+ \"variant\":\"TtToken\",\
+ \"fields\":[\
+ null,\
+ {\
+ \"variant\":\"Ident\",\
+ \"fields\":[\
+ \"b\",\
+ \"Plain\"\
+ ]\
+ }\
+ ]\
+ },\
+ {\
+ \"variant\":\"TtToken\",\
+ \"fields\":[\
+ null,\
+ \"Colon\"\
+ ]\
+ },\
+ {\
+ \"variant\":\"TtToken\",\
+ \"fields\":[\
+ null,\
+ {\
+ \"variant\":\"Ident\",\
+ \"fields\":[\
+ \"int\",\
+ \"Plain\"\
+ ]\
+ }\
+ ]\
+ }\
+ ],\
{\
- \"variant\":\"TTTok\",\
- \"fields\":[\
- null,\
- \"COLON\"\
- ]\
- },\
- {\
- \"variant\":\"TTTok\",\
- \"fields\":[\
- null,\
- {\
- \"variant\":\"IDENT\",\
- \"fields\":[\
- \"int\",\
- false\
- ]\
- }\
- ]\
- },\
- {\
- \"variant\":\"TTTok\",\
- \"fields\":[\
- null,\
- \"RPAREN\"\
- ]\
+ \"span\":null,\
+ \"token\":\"RParen\"\
}\
]\
]\
},\
{\
- \"variant\":\"TTDelim\",\
+ \"variant\":\"TtDelimited\",\
\"fields\":[\
+ null,\
[\
{\
- \"variant\":\"TTTok\",\
- \"fields\":[\
- null,\
- \"LBRACE\"\
- ]\
- },\
- {\
- \"variant\":\"TTTok\",\
- \"fields\":[\
- null,\
- {\
- \"variant\":\"IDENT\",\
- \"fields\":[\
- \"b\",\
- false\
- ]\
- }\
- ]\
- },\
- {\
- \"variant\":\"TTTok\",\
- \"fields\":[\
- null,\
- \"SEMI\"\
- ]\
+ \"span\":null,\
+ \"token\":\"LBrace\"\
},\
+ [\
+ {\
+ \"variant\":\"TtToken\",\
+ \"fields\":[\
+ null,\
+ {\
+ \"variant\":\"Ident\",\
+ \"fields\":[\
+ \"b\",\
+ \"Plain\"\
+ ]\
+ }\
+ ]\
+ },\
+ {\
+ \"variant\":\"TtToken\",\
+ \"fields\":[\
+ null,\
+ \"Semi\"\
+ ]\
+ }\
+ ],\
{\
- \"variant\":\"TTTok\",\
- \"fields\":[\
- null,\
- \"RBRACE\"\
- ]\
+ \"span\":null,\
+ \"token\":\"RBrace\"\
}\
]\
]\
}
fn parser_done(p: Parser){
- assert_eq!(p.token.clone(), token::EOF);
+ assert_eq!(p.token.clone(), token::Eof);
}
#[test] fn parse_ident_pat () {
fn is_obsolete_ident(&mut self, ident: &str) -> bool {
match self.token {
- token::IDENT(sid, _) => {
+ token::Ident(sid, _) => {
token::get_ident(sid).equiv(&ident)
}
_ => false
use ast::{StructVariantKind, BiSub};
use ast::StrStyle;
use ast::{SelfExplicit, SelfRegion, SelfStatic, SelfValue};
-use ast::{TokenTree, TraitItem, TraitRef, TTDelim, TTSeq, TTTok};
-use ast::{TTNonterminal, TupleVariantKind, Ty, Ty_, TyBot};
+use ast::{Delimiter, TokenTree, TraitItem, TraitRef, TtDelimited, TtSequence, TtToken};
+use ast::{TtNonterminal, TupleVariantKind, Ty, Ty_, TyBot};
use ast::{TypeField, TyFixedLengthVec, TyClosure, TyProc, TyBareFn};
use ast::{TyTypeof, TyInfer, TypeMethod};
use ast::{TyNil, TyParam, TyParamBound, TyParen, TyPath, TyPtr, TyQPath};
use parse::lexer::Reader;
use parse::lexer::TokenAndSpan;
use parse::obsolete::*;
-use parse::token::{INTERPOLATED, InternedString, can_begin_expr};
-use parse::token::{is_ident, is_ident_or_path, is_plain_ident};
-use parse::token::{keywords, special_idents, token_to_binop};
+use parse::token::InternedString;
+use parse::token::{keywords, special_idents};
use parse::token;
use parse::{new_sub_parser_from_file, ParseSess};
+use print::pprust;
use ptr::P;
use owned_slice::OwnedSlice;
}
-/// Possibly accept an `INTERPOLATED` expression (a pre-parsed expression
-/// dropped into the token stream, which happens while parsing the
-/// result of macro expansion)
-/// Placement of these is not as complex as I feared it would be.
-/// The important thing is to make sure that lookahead doesn't balk
-/// at INTERPOLATED tokens
+/// Possibly accept an `token::Interpolated` expression (a pre-parsed expression
+/// dropped into the token stream, which happens while parsing the result of
+/// macro expansion). Placement of these is not as complex as I feared it would
+/// be. The important thing is to make sure that lookahead doesn't balk at
+/// `token::Interpolated` tokens.
macro_rules! maybe_whole_expr (
($p:expr) => (
{
let found = match $p.token {
- INTERPOLATED(token::NtExpr(ref e)) => {
+ token::Interpolated(token::NtExpr(ref e)) => {
Some((*e).clone())
}
- INTERPOLATED(token::NtPath(_)) => {
+ token::Interpolated(token::NtPath(_)) => {
// FIXME: The following avoids an issue with lexical borrowck scopes,
// but the clone is unfortunate.
let pt = match $p.token {
- INTERPOLATED(token::NtPath(ref pt)) => (**pt).clone(),
+ token::Interpolated(token::NtPath(ref pt)) => (**pt).clone(),
_ => unreachable!()
};
let span = $p.span;
Some($p.mk_expr(span.lo, span.hi, ExprPath(pt)))
}
- INTERPOLATED(token::NtBlock(_)) => {
+ token::Interpolated(token::NtBlock(_)) => {
// FIXME: The following avoids an issue with lexical borrowck scopes,
// but the clone is unfortunate.
let b = match $p.token {
- INTERPOLATED(token::NtBlock(ref b)) => (*b).clone(),
+ token::Interpolated(token::NtBlock(ref b)) => (*b).clone(),
_ => unreachable!()
};
let span = $p.span;
($p:expr, $constructor:ident) => (
{
let found = match ($p).token {
- INTERPOLATED(token::$constructor(_)) => {
+ token::Interpolated(token::$constructor(_)) => {
Some(($p).bump_and_get())
}
_ => None
};
match found {
- Some(INTERPOLATED(token::$constructor(x))) => {
+ Some(token::Interpolated(token::$constructor(x))) => {
return x.clone()
}
_ => {}
(no_clone $p:expr, $constructor:ident) => (
{
let found = match ($p).token {
- INTERPOLATED(token::$constructor(_)) => {
+ token::Interpolated(token::$constructor(_)) => {
Some(($p).bump_and_get())
}
_ => None
};
match found {
- Some(INTERPOLATED(token::$constructor(x))) => {
+ Some(token::Interpolated(token::$constructor(x))) => {
return x
}
_ => {}
(deref $p:expr, $constructor:ident) => (
{
let found = match ($p).token {
- INTERPOLATED(token::$constructor(_)) => {
+ token::Interpolated(token::$constructor(_)) => {
Some(($p).bump_and_get())
}
_ => None
};
match found {
- Some(INTERPOLATED(token::$constructor(x))) => {
+ Some(token::Interpolated(token::$constructor(x))) => {
return (*x).clone()
}
_ => {}
(Some $p:expr, $constructor:ident) => (
{
let found = match ($p).token {
- INTERPOLATED(token::$constructor(_)) => {
+ token::Interpolated(token::$constructor(_)) => {
Some(($p).bump_and_get())
}
_ => None
};
match found {
- Some(INTERPOLATED(token::$constructor(x))) => {
+ Some(token::Interpolated(token::$constructor(x))) => {
return Some(x.clone()),
}
_ => {}
(iovi $p:expr, $constructor:ident) => (
{
let found = match ($p).token {
- INTERPOLATED(token::$constructor(_)) => {
+ token::Interpolated(token::$constructor(_)) => {
Some(($p).bump_and_get())
}
_ => None
};
match found {
- Some(INTERPOLATED(token::$constructor(x))) => {
+ Some(token::Interpolated(token::$constructor(x))) => {
return IoviItem(x.clone())
}
_ => {}
(pair_empty $p:expr, $constructor:ident) => (
{
let found = match ($p).token {
- INTERPOLATED(token::$constructor(_)) => {
+ token::Interpolated(token::$constructor(_)) => {
Some(($p).bump_and_get())
}
_ => None
};
match found {
- Some(INTERPOLATED(token::$constructor(x))) => {
+ Some(token::Interpolated(token::$constructor(x))) => {
return (Vec::new(), x)
}
_ => {}
}
fn is_plain_ident_or_underscore(t: &token::Token) -> bool {
- is_plain_ident(t) || *t == token::UNDERSCORE
+ t.is_plain_ident() || *t == token::Underscore
}
/// Get a token the parser cares about
let mut t = rdr.next_token();
loop {
match t.tok {
- token::WS | token::COMMENT | token::SHEBANG(_) => {
+ token::Whitespace | token::Comment | token::Shebang(_) => {
t = rdr.next_token();
},
_ => break
let tok0 = real_token(&mut *rdr);
let span = tok0.sp;
let placeholder = TokenAndSpan {
- tok: token::UNDERSCORE,
+ tok: token::Underscore,
sp: span,
};
/// Convert a token to a string using self's reader
pub fn token_to_string(token: &token::Token) -> String {
- token::to_string(token)
+ pprust::token_to_string(token)
}
/// Convert the current token to a string using self's reader
/// recover (without consuming any expected input token). Returns
/// true if and only if input was consumed for recovery.
pub fn check_for_erroneous_unit_struct_expecting(&mut self, expected: &[token::Token]) -> bool {
- if self.token == token::LBRACE
- && expected.iter().all(|t| *t != token::LBRACE)
- && self.look_ahead(1, |t| *t == token::RBRACE) {
+ if self.token == token::LBrace
+ && expected.iter().all(|t| *t != token::LBrace)
+ && self.look_ahead(1, |t| *t == token::RBrace) {
// matched; signal non-fatal error and recover.
let span = self.span;
self.span_err(span,
"unit-like struct construction is written with no trailing `{ }`");
- self.eat(&token::LBRACE);
- self.eat(&token::RBRACE);
+ self.eat(&token::LBrace);
+ self.eat(&token::RBrace);
true
} else {
false
pub fn commit_stmt(&mut self, edible: &[token::Token], inedible: &[token::Token]) {
if self.last_token
.as_ref()
- .map_or(false, |t| is_ident_or_path(&**t)) {
+ .map_or(false, |t| t.is_ident() || t.is_path()) {
let mut expected = edible.iter().map(|x| x.clone()).collect::<Vec<_>>();
expected.push_all(inedible.as_slice());
self.check_for_erroneous_unit_struct_expecting(
self.check_strict_keywords();
self.check_reserved_keywords();
match self.token {
- token::IDENT(i, _) => {
+ token::Ident(i, _) => {
self.bump();
i
}
- token::INTERPOLATED(token::NtIdent(..)) => {
+ token::Interpolated(token::NtIdent(..)) => {
self.bug("ident interpolation not converted to real token");
}
_ => {
is_present
}
- pub fn is_keyword(&mut self, kw: keywords::Keyword) -> bool {
- token::is_keyword(kw, &self.token)
- }
-
/// If the next token is the given keyword, eat it and return
/// true. Otherwise, return false.
pub fn eat_keyword(&mut self, kw: keywords::Keyword) -> bool {
- if self.is_keyword(kw) {
+ if self.token.is_keyword(kw) {
self.bump();
true
} else {
/// Signal an error if the given string is a strict keyword
pub fn check_strict_keywords(&mut self) {
- if token::is_strict_keyword(&self.token) {
+ if self.token.is_strict_keyword() {
let token_str = self.this_token_to_string();
let span = self.span;
self.span_err(span,
/// Signal an error if the current token is a reserved keyword
pub fn check_reserved_keywords(&mut self) {
- if token::is_reserved_keyword(&self.token) {
+ if self.token.is_reserved_keyword() {
let token_str = self.this_token_to_string();
self.fatal(format!("`{}` is a reserved keyword",
token_str).as_slice())
/// `&` and continue. If an `&` is not seen, signal an error.
fn expect_and(&mut self) {
match self.token {
- token::BINOP(token::AND) => self.bump(),
- token::ANDAND => {
+ token::BinOp(token::And) => self.bump(),
+ token::AndAnd => {
let span = self.span;
let lo = span.lo + BytePos(1);
- self.replace_token(token::BINOP(token::AND), lo, span.hi)
+ self.replace_token(token::BinOp(token::And), lo, span.hi)
}
_ => {
let token_str = self.this_token_to_string();
let found_token =
- Parser::token_to_string(&token::BINOP(token::AND));
+ Parser::token_to_string(&token::BinOp(token::And));
self.fatal(format!("expected `{}`, found `{}`",
found_token,
token_str).as_slice())
/// `|` and continue. If a `|` is not seen, signal an error.
fn expect_or(&mut self) {
match self.token {
- token::BINOP(token::OR) => self.bump(),
- token::OROR => {
+ token::BinOp(token::Or) => self.bump(),
+ token::OrOr => {
let span = self.span;
let lo = span.lo + BytePos(1);
- self.replace_token(token::BINOP(token::OR), lo, span.hi)
+ self.replace_token(token::BinOp(token::Or), lo, span.hi)
}
_ => {
let found_token = self.this_token_to_string();
let token_str =
- Parser::token_to_string(&token::BINOP(token::OR));
+ Parser::token_to_string(&token::BinOp(token::Or));
self.fatal(format!("expected `{}`, found `{}`",
token_str,
found_token).as_slice())
/// impl Foo<<'a> ||>() { ... }
fn eat_lt(&mut self, force: bool) -> bool {
match self.token {
- token::LT => { self.bump(); true }
- token::BINOP(token::SHL) => {
+ token::Lt => { self.bump(); true }
+ token::BinOp(token::Shl) => {
let next_lifetime = self.look_ahead(1, |t| match *t {
- token::LIFETIME(..) => true,
+ token::Lifetime(..) => true,
_ => false,
});
if force || next_lifetime {
let span = self.span;
let lo = span.lo + BytePos(1);
- self.replace_token(token::LT, lo, span.hi);
+ self.replace_token(token::Lt, lo, span.hi);
true
} else {
false
fn expect_lt(&mut self) {
if !self.eat_lt(true) {
let found_token = self.this_token_to_string();
- let token_str = Parser::token_to_string(&token::LT);
+ let token_str = Parser::token_to_string(&token::Lt);
self.fatal(format!("expected `{}`, found `{}`",
token_str,
found_token).as_slice())
-> Vec<T> {
let mut first = true;
let mut vector = Vec::new();
- while self.token != token::BINOP(token::OR) &&
- self.token != token::OROR {
+ while self.token != token::BinOp(token::Or) &&
+ self.token != token::OrOr {
if first {
first = false
} else {
/// signal an error.
pub fn expect_gt(&mut self) {
match self.token {
- token::GT => self.bump(),
- token::BINOP(token::SHR) => {
+ token::Gt => self.bump(),
+ token::BinOp(token::Shr) => {
let span = self.span;
let lo = span.lo + BytePos(1);
- self.replace_token(token::GT, lo, span.hi)
+ self.replace_token(token::Gt, lo, span.hi)
}
- token::BINOPEQ(token::SHR) => {
+ token::BinOpEq(token::Shr) => {
let span = self.span;
let lo = span.lo + BytePos(1);
- self.replace_token(token::GE, lo, span.hi)
+ self.replace_token(token::Ge, lo, span.hi)
}
- token::GE => {
+ token::Ge => {
let span = self.span;
let lo = span.lo + BytePos(1);
- self.replace_token(token::EQ, lo, span.hi)
+ self.replace_token(token::Eq, lo, span.hi)
}
_ => {
- let gt_str = Parser::token_to_string(&token::GT);
+ let gt_str = Parser::token_to_string(&token::Gt);
let this_token_str = self.this_token_to_string();
self.fatal(format!("expected `{}`, found `{}`",
gt_str,
// commas in generic parameters, because it can stop either after
// parsing a type or after parsing a comma.
for i in iter::count(0u, 1) {
- if self.token == token::GT
- || self.token == token::BINOP(token::SHR)
- || self.token == token::GE
- || self.token == token::BINOPEQ(token::SHR) {
+ if self.token == token::Gt
+ || self.token == token::BinOp(token::Shr)
+ || self.token == token::Ge
+ || self.token == token::BinOpEq(token::Shr) {
break;
}
pub fn bump(&mut self) {
self.last_span = self.span;
// Stash token for error recovery (sometimes; clone is not necessarily cheap).
- self.last_token = if is_ident_or_path(&self.token) {
+ self.last_token = if self.token.is_ident() || self.token.is_path() {
Some(box self.token.clone())
} else {
None
self.buffer_start = next_index as int;
let placeholder = TokenAndSpan {
- tok: token::UNDERSCORE,
+ tok: token::Underscore,
sp: self.span,
};
replace(&mut self.buffer[buffer_start], placeholder)
/// Advance the parser by one token and return the bumped token.
pub fn bump_and_get(&mut self) -> token::Token {
- let old_token = replace(&mut self.token, token::UNDERSCORE);
+ let old_token = replace(&mut self.token, token::Underscore);
self.bump();
old_token
}
/// Is the current token one of the keywords that signals a bare function
/// type?
pub fn token_is_bare_fn_keyword(&mut self) -> bool {
- if token::is_keyword(keywords::Fn, &self.token) {
+ if self.token.is_keyword(keywords::Fn) {
return true
}
- if token::is_keyword(keywords::Unsafe, &self.token) ||
- token::is_keyword(keywords::Once, &self.token) {
- return self.look_ahead(1, |t| token::is_keyword(keywords::Fn, t))
+ if self.token.is_keyword(keywords::Unsafe) ||
+ self.token.is_keyword(keywords::Once) {
+ return self.look_ahead(1, |t| t.is_keyword(keywords::Fn))
}
false
/// Is the current token one of the keywords that signals a closure type?
pub fn token_is_closure_keyword(&mut self) -> bool {
- token::is_keyword(keywords::Unsafe, &self.token) ||
- token::is_keyword(keywords::Once, &self.token)
+ self.token.is_keyword(keywords::Unsafe) ||
+ self.token.is_keyword(keywords::Once)
}
/// Is the current token one of the keywords that signals an old-style
/// closure type (with explicit sigil)?
pub fn token_is_old_style_closure_keyword(&mut self) -> bool {
- token::is_keyword(keywords::Unsafe, &self.token) ||
- token::is_keyword(keywords::Once, &self.token) ||
- token::is_keyword(keywords::Fn, &self.token)
- }
-
- pub fn token_is_lifetime(tok: &token::Token) -> bool {
- match *tok {
- token::LIFETIME(..) => true,
- _ => false,
- }
+ self.token.is_keyword(keywords::Unsafe) ||
+ self.token.is_keyword(keywords::Once) ||
+ self.token.is_keyword(keywords::Fn)
}
pub fn get_lifetime(&mut self) -> ast::Ident {
match self.token {
- token::LIFETIME(ref ident) => *ident,
+ token::Lifetime(ref ident) => *ident,
_ => self.bug("not a lifetime"),
}
}
*/
- let lifetime_defs = if self.eat(&token::LT) {
+ let lifetime_defs = if self.eat(&token::Lt) {
let lifetime_defs = self.parse_lifetime_defs();
self.expect_gt();
lifetime_defs
/// Parses an optional unboxed closure kind (`&:`, `&mut:`, or `:`).
pub fn parse_optional_unboxed_closure_kind(&mut self)
-> Option<UnboxedClosureKind> {
- if self.token == token::BINOP(token::AND) &&
- self.look_ahead(1, |t| {
- token::is_keyword(keywords::Mut, t)
- }) &&
- self.look_ahead(2, |t| *t == token::COLON) {
+ if self.token == token::BinOp(token::And) &&
+ self.look_ahead(1, |t| t.is_keyword(keywords::Mut)) &&
+ self.look_ahead(2, |t| *t == token::Colon) {
self.bump();
self.bump();
self.bump();
return Some(FnMutUnboxedClosureKind)
}
- if self.token == token::BINOP(token::AND) &&
- self.look_ahead(1, |t| *t == token::COLON) {
+ if self.token == token::BinOp(token::And) &&
+ self.look_ahead(1, |t| *t == token::Colon) {
self.bump();
self.bump();
return Some(FnUnboxedClosureKind)
}
- if self.eat(&token::COLON) {
+ if self.eat(&token::Colon) {
return Some(FnOnceUnboxedClosureKind)
}
let fn_style = self.parse_unsafety();
let onceness = if self.eat_keyword(keywords::Once) {Once} else {Many};
- let lifetime_defs = if self.eat(&token::LT) {
+ let lifetime_defs = if self.eat(&token::Lt) {
let lifetime_defs = self.parse_lifetime_defs();
self.expect_gt();
Vec::new()
};
- let (optional_unboxed_closure_kind, inputs) = if self.eat(&token::OROR) {
+ let (optional_unboxed_closure_kind, inputs) = if self.eat(&token::OrOr) {
(None, Vec::new())
} else {
self.expect_or();
self.parse_optional_unboxed_closure_kind();
let inputs = self.parse_seq_to_before_or(
- &token::COMMA,
+ &token::Comma,
|p| p.parse_arg_general(false));
self.expect_or();
(optional_unboxed_closure_kind, inputs)
Lifetime_defs
*/
- let lifetime_defs = if self.eat(&token::LT) {
+ let lifetime_defs = if self.eat(&token::Lt) {
let lifetime_defs = self.parse_lifetime_defs();
self.expect_gt();
lifetime_defs
let lo = self.span.lo;
let ident = self.parse_ident();
let hi = self.span.hi;
- self.expect(&token::SEMI);
+ self.expect(&token::Semi);
AssociatedType {
id: ast::DUMMY_NODE_ID,
span: mk_sp(lo, hi),
-> Typedef {
let lo = self.span.lo;
let ident = self.parse_ident();
- self.expect(&token::EQ);
+ self.expect(&token::Eq);
let typ = self.parse_ty(true);
let hi = self.span.hi;
- self.expect(&token::SEMI);
+ self.expect(&token::Semi);
Typedef {
id: ast::DUMMY_NODE_ID,
span: mk_sp(lo, hi),
/// Parse the items in a trait declaration
pub fn parse_trait_items(&mut self) -> Vec<TraitItem> {
self.parse_unspanned_seq(
- &token::LBRACE,
- &token::RBRACE,
+ &token::LBrace,
+ &token::RBrace,
seq_sep_none(),
|p| {
let attrs = p.parse_outer_attributes();
let hi = p.last_span.hi;
match p.token {
- token::SEMI => {
+ token::Semi => {
p.bump();
debug!("parse_trait_methods(): parsing required method");
RequiredMethod(TypeMethod {
vis: vis,
})
}
- token::LBRACE => {
+ token::LBrace => {
debug!("parse_trait_methods(): parsing provided method");
let (inner_attrs, body) =
p.parse_inner_attrs_and_block();
let lo = self.span.lo;
let mutbl = self.parse_mutability();
let id = self.parse_ident();
- self.expect(&token::COLON);
+ self.expect(&token::Colon);
let ty = self.parse_ty(true);
let hi = ty.span.hi;
ast::TypeField {
/// Parse optional return type [ -> TY ] in function decl
pub fn parse_ret_ty(&mut self) -> (RetStyle, P<Ty>) {
- return if self.eat(&token::RARROW) {
+ return if self.eat(&token::RArrow) {
let lo = self.span.lo;
- if self.eat(&token::NOT) {
+ if self.eat(&token::Not) {
(
NoReturn,
P(Ty {
let lo = self.span.lo;
- let t = if self.token == token::LPAREN {
+ let t = if self.token == token::LParen {
self.bump();
- if self.token == token::RPAREN {
+ if self.token == token::RParen {
self.bump();
TyNil
} else {
// of type t
let mut ts = vec!(self.parse_ty(true));
let mut one_tuple = false;
- while self.token == token::COMMA {
+ while self.token == token::Comma {
self.bump();
- if self.token != token::RPAREN {
+ if self.token != token::RParen {
ts.push(self.parse_ty(true));
}
else {
}
if ts.len() == 1 && !one_tuple {
- self.expect(&token::RPAREN);
+ self.expect(&token::RParen);
TyParen(ts.into_iter().nth(0).unwrap())
} else {
let t = TyTup(ts);
- self.expect(&token::RPAREN);
+ self.expect(&token::RParen);
t
}
}
- } else if self.token == token::TILDE {
+ } else if self.token == token::Tilde {
// OWNED POINTER
self.bump();
let last_span = self.last_span;
match self.token {
- token::LBRACKET => self.obsolete(last_span, ObsoleteOwnedVector),
+ token::LBracket => self.obsolete(last_span, ObsoleteOwnedVector),
_ => self.obsolete(last_span, ObsoleteOwnedType)
}
TyUniq(self.parse_ty(false))
- } else if self.token == token::BINOP(token::STAR) {
+ } else if self.token == token::BinOp(token::Star) {
// STAR POINTER (bare pointer?)
self.bump();
TyPtr(self.parse_ptr())
- } else if self.token == token::LBRACKET {
+ } else if self.token == token::LBracket {
// VECTOR
- self.expect(&token::LBRACKET);
+ self.expect(&token::LBracket);
let t = self.parse_ty(true);
// Parse the `, ..e` in `[ int, ..e ]`
None => TyVec(t),
Some(suffix) => TyFixedLengthVec(t, suffix)
};
- self.expect(&token::RBRACKET);
+ self.expect(&token::RBracket);
t
- } else if self.token == token::BINOP(token::AND) ||
- self.token == token::ANDAND {
+ } else if self.token == token::BinOp(token::And) ||
+ self.token == token::AndAnd {
// BORROWED POINTER
self.expect_and();
self.parse_borrowed_pointee()
- } else if self.is_keyword(keywords::Extern) ||
- self.is_keyword(keywords::Unsafe) ||
+ } else if self.token.is_keyword(keywords::Extern) ||
+ self.token.is_keyword(keywords::Unsafe) ||
self.token_is_bare_fn_keyword() {
// BARE FUNCTION
self.parse_ty_bare_fn()
} else if self.token_is_closure_keyword() ||
- self.token == token::BINOP(token::OR) ||
- self.token == token::OROR ||
- (self.token == token::LT &&
+ self.token == token::BinOp(token::Or) ||
+ self.token == token::OrOr ||
+ (self.token == token::Lt &&
self.look_ahead(1, |t| {
- *t == token::GT || Parser::token_is_lifetime(t)
+ *t == token::Gt || t.is_lifetime()
})) {
// CLOSURE
} else if self.eat_keyword(keywords::Typeof) {
// TYPEOF
// In order to not be ambiguous, the type must be surrounded by parens.
- self.expect(&token::LPAREN);
+ self.expect(&token::LParen);
let e = self.parse_expr();
- self.expect(&token::RPAREN);
+ self.expect(&token::RParen);
TyTypeof(e)
} else if self.eat_keyword(keywords::Proc) {
self.parse_proc_type()
- } else if self.token == token::LT {
+ } else if self.token == token::Lt {
// QUALIFIED PATH
self.bump();
let for_type = self.parse_ty(true);
self.expect_keyword(keywords::As);
let trait_name = self.parse_path(LifetimeAndTypesWithoutColons);
- self.expect(&token::GT);
- self.expect(&token::MOD_SEP);
+ self.expect(&token::Gt);
+ self.expect(&token::ModSep);
let item_name = self.parse_ident();
TyQPath(P(QPath {
for_type: for_type,
trait_name: trait_name.path,
item_name: item_name,
}))
- } else if self.token == token::MOD_SEP
- || is_ident_or_path(&self.token) {
+ } else if self.token == token::ModSep
+ || self.token.is_ident()
+ || self.token.is_path() {
// NAMED TYPE
let mode = if plus_allowed {
LifetimeAndTypesAndBounds
bounds
} = self.parse_path(mode);
TyPath(path, bounds, ast::DUMMY_NODE_ID)
- } else if self.eat(&token::UNDERSCORE) {
+ } else if self.eat(&token::Underscore) {
// TYPE TO BE INFERRED
TyInfer
} else {
pub fn is_named_argument(&mut self) -> bool {
let offset = match self.token {
- token::BINOP(token::AND) => 1,
- token::ANDAND => 1,
- _ if token::is_keyword(keywords::Mut, &self.token) => 1,
+ token::BinOp(token::And) => 1,
+ token::AndAnd => 1,
+ _ if self.token.is_keyword(keywords::Mut) => 1,
_ => 0
};
if offset == 0 {
is_plain_ident_or_underscore(&self.token)
- && self.look_ahead(1, |t| *t == token::COLON)
+ && self.look_ahead(1, |t| *t == token::Colon)
} else {
self.look_ahead(offset, |t| is_plain_ident_or_underscore(t))
- && self.look_ahead(offset + 1, |t| *t == token::COLON)
+ && self.look_ahead(offset + 1, |t| *t == token::Colon)
}
}
require_name);
let pat = self.parse_pat();
- self.expect(&token::COLON);
+ self.expect(&token::Colon);
pat
} else {
debug!("parse_arg_general ident_to_pat");
/// Parse an argument in a lambda header e.g. |arg, arg|
pub fn parse_fn_block_arg(&mut self) -> Arg {
let pat = self.parse_pat();
- let t = if self.eat(&token::COLON) {
+ let t = if self.eat(&token::Colon) {
self.parse_ty(true)
} else {
P(Ty {
}
pub fn maybe_parse_fixed_vstore(&mut self) -> Option<P<ast::Expr>> {
- if self.token == token::COMMA &&
- self.look_ahead(1, |t| *t == token::DOTDOT) {
+ if self.token == token::Comma &&
+ self.look_ahead(1, |t| *t == token::DotDot) {
self.bump();
self.bump();
Some(self.parse_expr())
/// Matches token_lit = LIT_INTEGER | ...
pub fn lit_from_token(&mut self, tok: &token::Token) -> Lit_ {
match *tok {
- token::LIT_BYTE(i) => LitByte(parse::byte_lit(i.as_str()).val0()),
- token::LIT_CHAR(i) => LitChar(parse::char_lit(i.as_str()).val0()),
- token::LIT_INTEGER(s) => parse::integer_lit(s.as_str(),
+ token::LitByte(i) => LitByte(parse::byte_lit(i.as_str()).val0()),
+ token::LitChar(i) => LitChar(parse::char_lit(i.as_str()).val0()),
+ token::LitInteger(s) => parse::integer_lit(s.as_str(),
&self.sess.span_diagnostic, self.span),
- token::LIT_FLOAT(s) => parse::float_lit(s.as_str()),
- token::LIT_STR(s) => {
+ token::LitFloat(s) => parse::float_lit(s.as_str()),
+ token::LitStr(s) => {
LitStr(token::intern_and_get_ident(parse::str_lit(s.as_str()).as_slice()),
ast::CookedStr)
}
- token::LIT_STR_RAW(s, n) => {
+ token::LitStrRaw(s, n) => {
LitStr(token::intern_and_get_ident(parse::raw_str_lit(s.as_str()).as_slice()),
ast::RawStr(n))
}
- token::LIT_BINARY(i) =>
+ token::LitBinary(i) =>
LitBinary(parse::binary_lit(i.as_str())),
- token::LIT_BINARY_RAW(i, _) =>
+ token::LitBinaryRaw(i, _) =>
LitBinary(Rc::new(i.as_str().as_bytes().iter().map(|&x| x).collect())),
- token::LPAREN => { self.expect(&token::RPAREN); LitNil },
+ token::LParen => { self.expect(&token::RParen); LitNil },
_ => { self.unexpected_last(tok); }
}
}
/// matches '-' lit | lit
pub fn parse_literal_maybe_minus(&mut self) -> P<Expr> {
let minus_lo = self.span.lo;
- let minus_present = self.eat(&token::BINOP(token::MINUS));
+ let minus_present = self.eat(&token::BinOp(token::Minus));
let lo = self.span.lo;
let literal = P(self.parse_lit());
pub fn parse_path(&mut self, mode: PathParsingMode) -> PathAndBounds {
// Check for a whole path...
let found = match self.token {
- INTERPOLATED(token::NtPath(_)) => Some(self.bump_and_get()),
+ token::Interpolated(token::NtPath(_)) => Some(self.bump_and_get()),
_ => None,
};
match found {
- Some(INTERPOLATED(token::NtPath(box path))) => {
+ Some(token::Interpolated(token::NtPath(box path))) => {
return PathAndBounds {
path: path,
bounds: None
}
let lo = self.span.lo;
- let is_global = self.eat(&token::MOD_SEP);
+ let is_global = self.eat(&token::ModSep);
// Parse any number of segments and bound sets. A segment is an
// identifier followed by an optional lifetime and a set of types.
// Parse the '::' before type parameters if it's required. If
// it is required and wasn't present, then we're done.
if mode == LifetimeAndTypesWithColons &&
- !self.eat(&token::MOD_SEP) {
+ !self.eat(&token::ModSep) {
segments.push(ast::PathSegment {
identifier: identifier,
lifetimes: Vec::new(),
// a double colon to get here in the first place.
if !(mode == LifetimeAndTypesWithColons &&
!any_lifetime_or_types) {
- if !self.eat(&token::MOD_SEP) {
+ if !self.eat(&token::ModSep) {
break
}
}
// error.
let opt_bounds = {
if mode == LifetimeAndTypesAndBounds &&
- self.eat(&token::BINOP(token::PLUS))
+ self.eat(&token::BinOp(token::Plus))
{
let bounds = self.parse_ty_param_bounds();
/// parses 0 or 1 lifetime
pub fn parse_opt_lifetime(&mut self) -> Option<ast::Lifetime> {
match self.token {
- token::LIFETIME(..) => {
+ token::Lifetime(..) => {
Some(self.parse_lifetime())
}
_ => {
/// Matches lifetime = LIFETIME
pub fn parse_lifetime(&mut self) -> ast::Lifetime {
match self.token {
- token::LIFETIME(i) => {
+ token::Lifetime(i) => {
let span = self.span;
self.bump();
return ast::Lifetime {
let mut res = Vec::new();
loop {
match self.token {
- token::LIFETIME(_) => {
+ token::Lifetime(_) => {
let lifetime = self.parse_lifetime();
let bounds =
- if self.eat(&token::COLON) {
- self.parse_lifetimes(token::BINOP(token::PLUS))
+ if self.eat(&token::Colon) {
+ self.parse_lifetimes(token::BinOp(token::Plus))
} else {
Vec::new()
};
}
match self.token {
- token::COMMA => { self.bump(); }
- token::GT => { return res; }
- token::BINOP(token::SHR) => { return res; }
+ token::Comma => { self.bump(); }
+ token::Gt => { return res; }
+ token::BinOp(token::Shr) => { return res; }
_ => {
let msg = format!("expected `,` or `>` after lifetime \
name, got: {}",
let mut res = Vec::new();
loop {
match self.token {
- token::LIFETIME(_) => {
+ token::Lifetime(_) => {
res.push(self.parse_lifetime());
}
_ => {
}
}
- pub fn token_is_mutability(tok: &token::Token) -> bool {
- token::is_keyword(keywords::Mut, tok) ||
- token::is_keyword(keywords::Const, tok)
- }
-
/// Parse mutability declaration (mut/const/imm)
pub fn parse_mutability(&mut self) -> Mutability {
if self.eat_keyword(keywords::Mut) {
let lo = self.span.lo;
let i = self.parse_ident();
let hi = self.last_span.hi;
- self.expect(&token::COLON);
+ self.expect(&token::Colon);
let e = self.parse_expr();
ast::Field {
ident: spanned(lo, hi, i),
let ex: Expr_;
match self.token {
- token::LPAREN => {
+ token::LParen => {
self.bump();
// (e) is parenthesized e
// (e,) is a tuple with only one field, e
let mut trailing_comma = false;
- if self.token == token::RPAREN {
+ if self.token == token::RParen {
hi = self.span.hi;
self.bump();
let lit = P(spanned(lo, hi, LitNil));
return self.mk_expr(lo, hi, ExprLit(lit));
}
let mut es = vec!(self.parse_expr());
- self.commit_expr(&**es.last().unwrap(), &[], &[token::COMMA, token::RPAREN]);
- while self.token == token::COMMA {
+ self.commit_expr(&**es.last().unwrap(), &[], &[token::Comma, token::RParen]);
+ while self.token == token::Comma {
self.bump();
- if self.token != token::RPAREN {
+ if self.token != token::RParen {
es.push(self.parse_expr());
self.commit_expr(&**es.last().unwrap(), &[],
- &[token::COMMA, token::RPAREN]);
+ &[token::Comma, token::RParen]);
} else {
trailing_comma = true;
}
}
hi = self.span.hi;
- self.commit_expr_expecting(&**es.last().unwrap(), token::RPAREN);
+ self.commit_expr_expecting(&**es.last().unwrap(), token::RParen);
return if es.len() == 1 && !trailing_comma {
self.mk_expr(lo, hi, ExprParen(es.into_iter().nth(0).unwrap()))
self.mk_expr(lo, hi, ExprTup(es))
}
},
- token::LBRACE => {
+ token::LBrace => {
self.bump();
let blk = self.parse_block_tail(lo, DefaultBlock);
return self.mk_expr(blk.span.lo, blk.span.hi,
ExprBlock(blk));
},
- token::BINOP(token::OR) | token::OROR => {
+ token::BinOp(token::Or) | token::OrOr => {
return self.parse_lambda_expr(CaptureByRef);
},
// FIXME #13626: Should be able to stick in
// token::SELF_KEYWORD_NAME
- token::IDENT(id @ ast::Ident{
- name: ast::Name(token::SELF_KEYWORD_NAME_NUM),
- ctxt: _
- } ,false) => {
+ token::Ident(id @ ast::Ident {
+ name: ast::Name(token::SELF_KEYWORD_NAME_NUM),
+ ctxt: _
+ }, token::Plain) => {
self.bump();
let path = ast_util::ident_to_path(mk_sp(lo, hi), id);
ex = ExprPath(path);
hi = self.last_span.hi;
}
- token::LBRACKET => {
+ token::LBracket => {
self.bump();
- if self.token == token::RBRACKET {
+ if self.token == token::RBracket {
// Empty vector.
self.bump();
ex = ExprVec(Vec::new());
} else {
// Nonempty vector.
let first_expr = self.parse_expr();
- if self.token == token::COMMA &&
- self.look_ahead(1, |t| *t == token::DOTDOT) {
+ if self.token == token::Comma &&
+ self.look_ahead(1, |t| *t == token::DotDot) {
// Repeating vector syntax: [ 0, ..512 ]
self.bump();
self.bump();
let count = self.parse_expr();
- self.expect(&token::RBRACKET);
+ self.expect(&token::RBracket);
ex = ExprRepeat(first_expr, count);
- } else if self.token == token::COMMA {
+ } else if self.token == token::Comma {
// Vector with two or more elements.
self.bump();
let remaining_exprs = self.parse_seq_to_end(
- &token::RBRACKET,
- seq_sep_trailing_allowed(token::COMMA),
+ &token::RBracket,
+ seq_sep_trailing_allowed(token::Comma),
|p| p.parse_expr()
);
let mut exprs = vec!(first_expr);
ex = ExprVec(exprs);
} else {
// Vector with one element.
- self.expect(&token::RBRACKET);
+ self.expect(&token::RBracket);
ex = ExprVec(vec!(first_expr));
}
}
if self.eat_keyword(keywords::While) {
return self.parse_while_expr(None);
}
- if Parser::token_is_lifetime(&self.token) {
+ if self.token.is_lifetime() {
let lifetime = self.get_lifetime();
self.bump();
- self.expect(&token::COLON);
+ self.expect(&token::Colon);
if self.eat_keyword(keywords::While) {
return self.parse_while_expr(Some(lifetime))
}
}
if self.eat_keyword(keywords::Continue) {
let lo = self.span.lo;
- let ex = if Parser::token_is_lifetime(&self.token) {
+ let ex = if self.token.is_lifetime() {
let lifetime = self.get_lifetime();
self.bump();
ExprAgain(Some(lifetime))
}
if self.eat_keyword(keywords::Return) {
// RETURN expression
- if can_begin_expr(&self.token) {
+ if self.token.can_begin_expr() {
let e = self.parse_expr();
hi = e.span.hi;
ex = ExprRet(Some(e));
}
} else if self.eat_keyword(keywords::Break) {
// BREAK expression
- if Parser::token_is_lifetime(&self.token) {
+ if self.token.is_lifetime() {
let lifetime = self.get_lifetime();
self.bump();
ex = ExprBreak(Some(lifetime));
ex = ExprBreak(None);
}
hi = self.span.hi;
- } else if self.token == token::MOD_SEP ||
- is_ident(&self.token) &&
- !self.is_keyword(keywords::True) &&
- !self.is_keyword(keywords::False) {
+ } else if self.token == token::ModSep ||
+ self.token.is_ident() &&
+ !self.token.is_keyword(keywords::True) &&
+ !self.token.is_keyword(keywords::False) {
let pth =
self.parse_path(LifetimeAndTypesWithColons).path;
// `!`, as an operator, is prefix, so we know this isn't that
- if self.token == token::NOT {
+ if self.token == token::Not {
// MACRO INVOCATION expression
self.bump();
- let ket = token::close_delimiter_for(&self.token)
+ let ket = self.token.get_close_delimiter()
.unwrap_or_else(|| {
self.fatal("expected open delimiter")
});
tts,
EMPTY_CTXT));
}
- if self.token == token::LBRACE {
+ if self.token == token::LBrace {
// This is a struct literal, unless we're prohibited
// from parsing struct literals here.
if !self.restrictions.contains(RESTRICTION_NO_STRUCT_LITERAL) {
let mut fields = Vec::new();
let mut base = None;
- while self.token != token::RBRACE {
- if self.eat(&token::DOTDOT) {
+ while self.token != token::RBrace {
+ if self.eat(&token::DotDot) {
base = Some(self.parse_expr());
break;
}
fields.push(self.parse_field());
self.commit_expr(&*fields.last().unwrap().expr,
- &[token::COMMA],
- &[token::RBRACE]);
+ &[token::Comma],
+ &[token::RBrace]);
}
if fields.len() == 0 && base.is_none() {
}
hi = self.span.hi;
- self.expect(&token::RBRACE);
+ self.expect(&token::RBrace);
ex = ExprStruct(pth, fields, base);
return self.mk_expr(lo, hi, ex);
}
/// Parse a block or unsafe block
pub fn parse_block_expr(&mut self, lo: BytePos, blk_mode: BlockCheckMode)
-> P<Expr> {
- self.expect(&token::LBRACE);
+ self.expect(&token::LBrace);
let blk = self.parse_block_tail(lo, blk_mode);
return self.mk_expr(blk.span.lo, blk.span.hi, ExprBlock(blk));
}
let mut hi;
loop {
// expr.f
- if self.eat(&token::DOT) {
+ if self.eat(&token::Dot) {
match self.token {
- token::IDENT(i, _) => {
+ token::Ident(i, _) => {
let dot = self.last_span.hi;
hi = self.span.hi;
self.bump();
- let (_, tys) = if self.eat(&token::MOD_SEP) {
+ let (_, tys) = if self.eat(&token::ModSep) {
self.expect_lt();
self.parse_generic_values_after_lt()
} else {
// expr.f() method call
match self.token {
- token::LPAREN => {
+ token::LParen => {
let mut es = self.parse_unspanned_seq(
- &token::LPAREN,
- &token::RPAREN,
- seq_sep_trailing_allowed(token::COMMA),
+ &token::LParen,
+ &token::RParen,
+ seq_sep_trailing_allowed(token::Comma),
|p| p.parse_expr()
);
hi = self.last_span.hi;
}
}
}
- token::LIT_INTEGER(n) => {
+ token::LitInteger(n) => {
let index = n.as_str();
let dot = self.last_span.hi;
hi = self.span.hi;
self.bump();
- let (_, tys) = if self.eat(&token::MOD_SEP) {
+ let (_, tys) = if self.eat(&token::ModSep) {
self.expect_lt();
self.parse_generic_values_after_lt()
} else {
}
}
}
- token::LIT_FLOAT(n) => {
+ token::LitFloat(n) => {
self.bump();
let last_span = self.last_span;
self.span_err(last_span,
if self.expr_is_complete(&*e) { break; }
match self.token {
// expr(...)
- token::LPAREN => {
+ token::LParen => {
let es = self.parse_unspanned_seq(
- &token::LPAREN,
- &token::RPAREN,
- seq_sep_trailing_allowed(token::COMMA),
+ &token::LParen,
+ &token::RParen,
+ seq_sep_trailing_allowed(token::Comma),
|p| p.parse_expr()
);
hi = self.last_span.hi;
// Could be either an index expression or a slicing expression.
// Any slicing non-terminal can have a mutable version with `mut`
// after the opening square bracket.
- token::LBRACKET => {
+ token::LBracket => {
self.bump();
let mutbl = if self.eat_keyword(keywords::Mut) {
MutMutable
};
match self.token {
// e[]
- token::RBRACKET => {
+ token::RBracket => {
self.bump();
hi = self.span.hi;
let slice = self.mk_slice(e, None, None, mutbl);
e = self.mk_expr(lo, hi, slice)
}
// e[..e]
- token::DOTDOT => {
+ token::DotDot => {
self.bump();
match self.token {
// e[..]
- token::RBRACKET => {
+ token::RBracket => {
self.bump();
hi = self.span.hi;
let slice = self.mk_slice(e, None, None, mutbl);
_ => {
hi = self.span.hi;
let e2 = self.parse_expr();
- self.commit_expr_expecting(&*e2, token::RBRACKET);
+ self.commit_expr_expecting(&*e2, token::RBracket);
let slice = self.mk_slice(e, None, Some(e2), mutbl);
e = self.mk_expr(lo, hi, slice)
}
let ix = self.parse_expr();
match self.token {
// e[e..] | e[e..e]
- token::DOTDOT => {
+ token::DotDot => {
self.bump();
let e2 = match self.token {
// e[e..]
- token::RBRACKET => {
+ token::RBracket => {
self.bump();
None
}
// e[e..e]
_ => {
let e2 = self.parse_expr();
- self.commit_expr_expecting(&*e2, token::RBRACKET);
+ self.commit_expr_expecting(&*e2, token::RBracket);
Some(e2)
}
};
"`mut` keyword is invalid in index expressions");
}
hi = self.span.hi;
- self.commit_expr_expecting(&*ix, token::RBRACKET);
+ self.commit_expr_expecting(&*ix, token::RBracket);
let index = self.mk_index(e, ix);
e = self.mk_expr(lo, hi, index)
}
return e;
}
- /// Parse an optional separator followed by a kleene-style
+ /// Parse an optional separator followed by a Kleene-style
/// repetition token (+ or *).
- pub fn parse_sep_and_zerok(&mut self) -> (Option<token::Token>, bool) {
- fn parse_zerok(parser: &mut Parser) -> Option<bool> {
+ pub fn parse_sep_and_kleene_op(&mut self) -> (Option<token::Token>, ast::KleeneOp) {
+ fn parse_kleene_op(parser: &mut Parser) -> Option<ast::KleeneOp> {
match parser.token {
- token::BINOP(token::STAR) | token::BINOP(token::PLUS) => {
- let zerok = parser.token == token::BINOP(token::STAR);
+ token::BinOp(token::Star) => {
parser.bump();
- Some(zerok)
+ Some(ast::ZeroOrMore)
+ },
+ token::BinOp(token::Plus) => {
+ parser.bump();
+ Some(ast::OneOrMore)
},
_ => None
}
};
- match parse_zerok(self) {
- Some(zerok) => return (None, zerok),
+ match parse_kleene_op(self) {
+ Some(kleene_op) => return (None, kleene_op),
None => {}
}
let separator = self.bump_and_get();
- match parse_zerok(self) {
+ match parse_kleene_op(self) {
Some(zerok) => (Some(separator), zerok),
None => self.fatal("expected `*` or `+`")
}
/// parse a single token tree from the input.
pub fn parse_token_tree(&mut self) -> TokenTree {
// FIXME #6994: currently, this is too eager. It
- // parses token trees but also identifies TTSeq's
- // and TTNonterminal's; it's too early to know yet
+ // parses token trees but also identifies TtSequence's
+ // and TtNonterminal's; it's too early to know yet
// whether something will be a nonterminal or a seq
// yet.
maybe_whole!(deref self, NtTT);
fn parse_non_delim_tt_tok(p: &mut Parser) -> TokenTree {
maybe_whole!(deref p, NtTT);
match p.token {
- token::RPAREN | token::RBRACE | token::RBRACKET => {
+ token::RParen | token::RBrace | token::RBracket => {
// This is a conservative error: only report the last unclosed delimiter. The
// previous unclosed delimiters could actually be closed! The parser just hasn't
// gotten to them yet.
token_str).as_slice())
},
/* we ought to allow different depths of unquotation */
- token::DOLLAR if p.quote_depth > 0u => {
+ token::Dollar if p.quote_depth > 0u => {
p.bump();
let sp = p.span;
- if p.token == token::LPAREN {
+ if p.token == token::LParen {
let seq = p.parse_seq(
- &token::LPAREN,
- &token::RPAREN,
+ &token::LParen,
+ &token::RParen,
seq_sep_none(),
|p| p.parse_token_tree()
);
- let (s, z) = p.parse_sep_and_zerok();
+ let (sep, repeat) = p.parse_sep_and_kleene_op();
let seq = match seq {
Spanned { node, .. } => node,
};
- TTSeq(mk_sp(sp.lo, p.span.hi), Rc::new(seq), s, z)
+ TtSequence(mk_sp(sp.lo, p.span.hi), Rc::new(seq), sep, repeat)
} else {
- TTNonterminal(sp, p.parse_ident())
+ TtNonterminal(sp, p.parse_ident())
}
}
_ => {
- parse_any_tt_tok(p)
+ TtToken(p.span, p.bump_and_get())
}
}
}
- // turn the next token into a TTTok:
- fn parse_any_tt_tok(p: &mut Parser) -> TokenTree {
- TTTok(p.span, p.bump_and_get())
- }
-
- match (&self.token, token::close_delimiter_for(&self.token)) {
- (&token::EOF, _) => {
+ match (&self.token, self.token.get_close_delimiter()) {
+ (&token::Eof, _) => {
let open_braces = self.open_braces.clone();
for sp in open_braces.iter() {
self.span_note(*sp, "Did you mean to close this delimiter?");
self.fatal("this file contains an un-closed delimiter ");
}
(_, Some(close_delim)) => {
+ // The span for beginning of the delimited section
+ let pre_span = self.span;
+
// Parse the open delimiter.
self.open_braces.push(self.span);
- let mut result = vec!(parse_any_tt_tok(self));
+ let open = Delimiter {
+ span: self.span,
+ token: self.bump_and_get(),
+ };
- let trees =
- self.parse_seq_to_before_end(&close_delim,
- seq_sep_none(),
- |p| p.parse_token_tree());
- result.extend(trees.into_iter());
+ // Parse the token trees within the delimeters
+ let tts = self.parse_seq_to_before_end(
+ &close_delim, seq_sep_none(), |p| p.parse_token_tree()
+ );
// Parse the close delimiter.
- result.push(parse_any_tt_tok(self));
+ let close = Delimiter {
+ span: self.span,
+ token: self.bump_and_get(),
+ };
self.open_braces.pop().unwrap();
- TTDelim(Rc::new(result))
+ // Expand to cover the entire delimited token tree
+ let span = Span { hi: self.span.hi, ..pre_span };
+
+ TtDelimited(span, Rc::new((open, tts, close)))
}
_ => parse_non_delim_tt_tok(self)
}
// up to EOF.
pub fn parse_all_token_trees(&mut self) -> Vec<TokenTree> {
let mut tts = Vec::new();
- while self.token != token::EOF {
+ while self.token != token::Eof {
tts.push(self.parse_token_tree());
}
tts
// the interpolation of Matcher's
maybe_whole!(self, NtMatchers);
let mut name_idx = 0u;
- match token::close_delimiter_for(&self.token) {
+ match self.token.get_close_delimiter() {
Some(other_delimiter) => {
self.bump();
self.parse_matcher_subseq_upto(&mut name_idx, &other_delimiter)
let mut lparens = 0u;
while self.token != *ket || lparens > 0u {
- if self.token == token::LPAREN { lparens += 1u; }
- if self.token == token::RPAREN { lparens -= 1u; }
+ if self.token == token::LParen { lparens += 1u; }
+ if self.token == token::RParen { lparens -= 1u; }
ret_val.push(self.parse_matcher(name_idx));
}
pub fn parse_matcher(&mut self, name_idx: &mut uint) -> Matcher {
let lo = self.span.lo;
- let m = if self.token == token::DOLLAR {
+ let m = if self.token == token::Dollar {
self.bump();
- if self.token == token::LPAREN {
+ if self.token == token::LParen {
let name_idx_lo = *name_idx;
self.bump();
let ms = self.parse_matcher_subseq_upto(name_idx,
- &token::RPAREN);
+ &token::RParen);
if ms.len() == 0u {
self.fatal("repetition body must be nonempty");
}
- let (sep, zerok) = self.parse_sep_and_zerok();
- MatchSeq(ms, sep, zerok, name_idx_lo, *name_idx)
+ let (sep, kleene_op) = self.parse_sep_and_kleene_op();
+ MatchSeq(ms, sep, kleene_op, name_idx_lo, *name_idx)
} else {
let bound_to = self.parse_ident();
- self.expect(&token::COLON);
+ self.expect(&token::Colon);
let nt_name = self.parse_ident();
let m = MatchNonterminal(bound_to, nt_name, *name_idx);
*name_idx += 1;
let ex;
match self.token {
- token::NOT => {
+ token::Not => {
self.bump();
let e = self.parse_prefix_expr();
hi = e.span.hi;
ex = self.mk_unary(UnNot, e);
}
- token::BINOP(token::MINUS) => {
+ token::BinOp(token::Minus) => {
self.bump();
let e = self.parse_prefix_expr();
hi = e.span.hi;
ex = self.mk_unary(UnNeg, e);
}
- token::BINOP(token::STAR) => {
+ token::BinOp(token::Star) => {
self.bump();
let e = self.parse_prefix_expr();
hi = e.span.hi;
ex = self.mk_unary(UnDeref, e);
}
- token::BINOP(token::AND) | token::ANDAND => {
+ token::BinOp(token::And) | token::AndAnd => {
self.expect_and();
let m = self.parse_mutability();
let e = self.parse_prefix_expr();
hi = e.span.hi;
ex = ExprAddrOf(m, e);
}
- token::TILDE => {
+ token::Tilde => {
self.bump();
let last_span = self.last_span;
match self.token {
- token::LBRACKET => self.obsolete(last_span, ObsoleteOwnedVector),
+ token::LBracket => self.obsolete(last_span, ObsoleteOwnedVector),
_ => self.obsolete(last_span, ObsoleteOwnedExpr)
}
hi = e.span.hi;
ex = self.mk_unary(UnUniq, e);
}
- token::IDENT(_, _) => {
- if !self.is_keyword(keywords::Box) {
+ token::Ident(_, _) => {
+ if !self.token.is_keyword(keywords::Box) {
return self.parse_dot_or_call_expr();
}
self.bump();
// Check for a place: `box(PLACE) EXPR`.
- if self.eat(&token::LPAREN) {
+ if self.eat(&token::LParen) {
// Support `box() EXPR` as the default.
- if !self.eat(&token::RPAREN) {
+ if !self.eat(&token::RParen) {
let place = self.parse_expr();
- self.expect(&token::RPAREN);
+ self.expect(&token::RParen);
let subexpression = self.parse_prefix_expr();
hi = subexpression.span.hi;
ex = ExprBox(place, subexpression);
// Prevent dynamic borrow errors later on by limiting the
// scope of the borrows.
- if self.token == token::BINOP(token::OR) &&
+ if self.token == token::BinOp(token::Or) &&
self.restrictions.contains(RESTRICTION_NO_BAR_OP) {
return lhs;
}
- let cur_opt = token_to_binop(&self.token);
+ let cur_opt = self.token.to_binop();
match cur_opt {
Some(cur_op) => {
let cur_prec = operator_prec(cur_op);
let lhs = self.parse_binops();
let restrictions = self.restrictions & RESTRICTION_NO_STRUCT_LITERAL;
match self.token {
- token::EQ => {
+ token::Eq => {
self.bump();
let rhs = self.parse_expr_res(restrictions);
self.mk_expr(lo, rhs.span.hi, ExprAssign(lhs, rhs))
}
- token::BINOPEQ(op) => {
+ token::BinOpEq(op) => {
self.bump();
let rhs = self.parse_expr_res(restrictions);
let aop = match op {
- token::PLUS => BiAdd,
- token::MINUS => BiSub,
- token::STAR => BiMul,
- token::SLASH => BiDiv,
- token::PERCENT => BiRem,
- token::CARET => BiBitXor,
- token::AND => BiBitAnd,
- token::OR => BiBitOr,
- token::SHL => BiShl,
- token::SHR => BiShr
+ token::Plus => BiAdd,
+ token::Minus => BiSub,
+ token::Star => BiMul,
+ token::Slash => BiDiv,
+ token::Percent => BiRem,
+ token::Caret => BiBitXor,
+ token::And => BiBitAnd,
+ token::Or => BiBitOr,
+ token::Shl => BiShl,
+ token::Shr => BiShr
};
let rhs_span = rhs.span;
let assign_op = self.mk_assign_op(aop, lhs, rhs);
/// Parse an 'if' or 'if let' expression ('if' token already eaten)
pub fn parse_if_expr(&mut self) -> P<Expr> {
- if self.is_keyword(keywords::Let) {
+ if self.token.is_keyword(keywords::Let) {
return self.parse_if_let_expr();
}
let lo = self.last_span.lo;
let lo = self.last_span.lo;
self.expect_keyword(keywords::Let);
let pat = self.parse_pat();
- self.expect(&token::EQ);
+ self.expect(&token::Eq);
let expr = self.parse_expr_res(RESTRICTION_NO_STRUCT_LITERAL);
let thn = self.parse_block();
let (hi, els) = if self.eat_keyword(keywords::Else) {
/// Parse a 'while' or 'while let' expression ('while' token already eaten)
pub fn parse_while_expr(&mut self, opt_ident: Option<ast::Ident>) -> P<Expr> {
- if self.is_keyword(keywords::Let) {
+ if self.token.is_keyword(keywords::Let) {
return self.parse_while_let_expr(opt_ident);
}
let lo = self.last_span.lo;
let lo = self.last_span.lo;
self.expect_keyword(keywords::Let);
let pat = self.parse_pat();
- self.expect(&token::EQ);
+ self.expect(&token::Eq);
let expr = self.parse_expr_res(RESTRICTION_NO_STRUCT_LITERAL);
let body = self.parse_block();
let hi = body.span.hi;
fn parse_match_expr(&mut self) -> P<Expr> {
let lo = self.last_span.lo;
let discriminant = self.parse_expr_res(RESTRICTION_NO_STRUCT_LITERAL);
- self.commit_expr_expecting(&*discriminant, token::LBRACE);
+ self.commit_expr_expecting(&*discriminant, token::LBrace);
let mut arms: Vec<Arm> = Vec::new();
- while self.token != token::RBRACE {
+ while self.token != token::RBrace {
arms.push(self.parse_arm());
}
let hi = self.span.hi;
if self.eat_keyword(keywords::If) {
guard = Some(self.parse_expr());
}
- self.expect(&token::FAT_ARROW);
+ self.expect(&token::FatArrow);
let expr = self.parse_expr_res(RESTRICTION_STMT_EXPR);
let require_comma =
!classify::expr_is_simple_block(&*expr)
- && self.token != token::RBRACE;
+ && self.token != token::RBrace;
if require_comma {
- self.commit_expr(&*expr, &[token::COMMA], &[token::RBRACE]);
+ self.commit_expr(&*expr, &[token::Comma], &[token::RBrace]);
} else {
- self.eat(&token::COMMA);
+ self.eat(&token::Comma);
}
ast::Arm {
/// Parse the RHS of a local variable declaration (e.g. '= 14;')
fn parse_initializer(&mut self) -> Option<P<Expr>> {
- if self.token == token::EQ {
+ if self.token == token::Eq {
self.bump();
Some(self.parse_expr())
} else {
let mut pats = Vec::new();
loop {
pats.push(self.parse_pat());
- if self.token == token::BINOP(token::OR) { self.bump(); }
+ if self.token == token::BinOp(token::Or) { self.bump(); }
else { return pats; }
};
}
let mut first = true;
let mut before_slice = true;
- while self.token != token::RBRACKET {
+ while self.token != token::RBracket {
if first {
first = false;
} else {
- self.expect(&token::COMMA);
+ self.expect(&token::Comma);
}
if before_slice {
- if self.token == token::DOTDOT {
+ if self.token == token::DotDot {
self.bump();
- if self.token == token::COMMA ||
- self.token == token::RBRACKET {
+ if self.token == token::Comma ||
+ self.token == token::RBracket {
slice = Some(P(ast::Pat {
id: ast::DUMMY_NODE_ID,
node: PatWild(PatWildMulti),
}
let subpat = self.parse_pat();
- if before_slice && self.token == token::DOTDOT {
+ if before_slice && self.token == token::DotDot {
self.bump();
slice = Some(subpat);
before_slice = false;
let mut fields = Vec::new();
let mut etc = false;
let mut first = true;
- while self.token != token::RBRACE {
+ while self.token != token::RBrace {
if first {
first = false;
} else {
- self.expect(&token::COMMA);
+ self.expect(&token::Comma);
// accept trailing commas
- if self.token == token::RBRACE { break }
+ if self.token == token::RBrace { break }
}
let lo = self.span.lo;
let hi;
- if self.token == token::DOTDOT {
+ if self.token == token::DotDot {
self.bump();
- if self.token != token::RBRACE {
+ if self.token != token::RBrace {
let token_str = self.this_token_to_string();
self.fatal(format!("expected `{}`, found `{}`", "}",
token_str).as_slice())
let fieldname = self.parse_ident();
- let (subpat, is_shorthand) = if self.token == token::COLON {
+ let (subpat, is_shorthand) = if self.token == token::Colon {
match bind_type {
BindByRef(..) | BindByValue(MutMutable) => {
let token_str = self.this_token_to_string();
let pat;
match self.token {
// parse _
- token::UNDERSCORE => {
+ token::Underscore => {
self.bump();
pat = PatWild(PatWildSingle);
hi = self.last_span.hi;
span: mk_sp(lo, hi)
})
}
- token::TILDE => {
+ token::Tilde => {
// parse ~pat
self.bump();
let sub = self.parse_pat();
span: mk_sp(lo, hi)
})
}
- token::BINOP(token::AND) | token::ANDAND => {
+ token::BinOp(token::And) | token::AndAnd => {
// parse &pat
let lo = self.span.lo;
self.expect_and();
span: mk_sp(lo, hi)
})
}
- token::LPAREN => {
+ token::LParen => {
// parse (pat,pat,pat,...) as tuple
self.bump();
- if self.token == token::RPAREN {
+ if self.token == token::RParen {
hi = self.span.hi;
self.bump();
let lit = P(codemap::Spanned {
pat = PatLit(expr);
} else {
let mut fields = vec!(self.parse_pat());
- if self.look_ahead(1, |t| *t != token::RPAREN) {
- while self.token == token::COMMA {
+ if self.look_ahead(1, |t| *t != token::RParen) {
+ while self.token == token::Comma {
self.bump();
- if self.token == token::RPAREN { break; }
+ if self.token == token::RParen { break; }
fields.push(self.parse_pat());
}
}
- if fields.len() == 1 { self.expect(&token::COMMA); }
- self.expect(&token::RPAREN);
+ if fields.len() == 1 { self.expect(&token::Comma); }
+ self.expect(&token::RParen);
pat = PatTup(fields);
}
hi = self.last_span.hi;
span: mk_sp(lo, hi)
})
}
- token::LBRACKET => {
+ token::LBracket => {
// parse [pat,pat,...] as vector pattern
self.bump();
let (before, slice, after) =
self.parse_pat_vec_elements();
- self.expect(&token::RBRACKET);
+ self.expect(&token::RBracket);
pat = ast::PatVec(before, slice, after);
hi = self.last_span.hi;
return P(ast::Pat {
}
// at this point, token != _, ~, &, &&, (, [
- if (!is_ident_or_path(&self.token) && self.token != token::MOD_SEP)
- || self.is_keyword(keywords::True)
- || self.is_keyword(keywords::False) {
+ if (!(self.token.is_ident() || self.token.is_path())
+ && self.token != token::ModSep)
+ || self.token.is_keyword(keywords::True)
+ || self.token.is_keyword(keywords::False) {
// Parse an expression pattern or exp .. exp.
//
// These expressions are limited to literals (possibly
// preceded by unary-minus) or identifiers.
let val = self.parse_literal_maybe_minus();
- if (self.token == token::DOTDOTDOT) &&
+ if (self.token == token::DotDotDot) &&
self.look_ahead(1, |t| {
- *t != token::COMMA && *t != token::RBRACKET
+ *t != token::Comma && *t != token::RBracket
}) {
self.bump();
- let end = if is_ident_or_path(&self.token) {
+ let end = if self.token.is_ident() || self.token.is_path() {
let path = self.parse_path(LifetimeAndTypesWithColons)
.path;
let hi = self.span.hi;
} else {
let can_be_enum_or_struct = self.look_ahead(1, |t| {
match *t {
- token::LPAREN | token::LBRACKET | token::LT |
- token::LBRACE | token::MOD_SEP => true,
+ token::LParen | token::LBracket | token::Lt |
+ token::LBrace | token::ModSep => true,
_ => false,
}
});
- if self.look_ahead(1, |t| *t == token::DOTDOTDOT) &&
+ if self.look_ahead(1, |t| *t == token::DotDotDot) &&
self.look_ahead(2, |t| {
- *t != token::COMMA && *t != token::RBRACKET
+ *t != token::Comma && *t != token::RBracket
}) {
let start = self.parse_expr_res(RESTRICTION_NO_BAR_OP);
- self.eat(&token::DOTDOTDOT);
+ self.eat(&token::DotDotDot);
let end = self.parse_expr_res(RESTRICTION_NO_BAR_OP);
pat = PatRange(start, end);
- } else if is_plain_ident(&self.token) && !can_be_enum_or_struct {
+ } else if self.token.is_plain_ident() && !can_be_enum_or_struct {
let id = self.parse_ident();
let id_span = self.last_span;
let pth1 = codemap::Spanned{span:id_span, node: id};
- if self.eat(&token::NOT) {
+ if self.eat(&token::Not) {
// macro invocation
- let ket = token::close_delimiter_for(&self.token)
+ let ket = self.token.get_close_delimiter()
.unwrap_or_else(|| self.fatal("expected open delimiter"));
self.bump();
let mac = MacInvocTT(ident_to_path(id_span,id), tts, EMPTY_CTXT);
pat = ast::PatMac(codemap::Spanned {node: mac, span: self.span});
} else {
- let sub = if self.eat(&token::AT) {
+ let sub = if self.eat(&token::At) {
// parse foo @ pat
Some(self.parse_pat())
} else {
let enum_path = self.parse_path(LifetimeAndTypesWithColons)
.path;
match self.token {
- token::LBRACE => {
+ token::LBrace => {
self.bump();
let (fields, etc) =
self.parse_pat_fields();
_ => {
let mut args: Vec<P<Pat>> = Vec::new();
match self.token {
- token::LPAREN => {
+ token::LParen => {
let is_dotdot = self.look_ahead(1, |t| {
match *t {
- token::DOTDOT => true,
+ token::DotDot => true,
_ => false,
}
});
// This is a "top constructor only" pat
self.bump();
self.bump();
- self.expect(&token::RPAREN);
+ self.expect(&token::RParen);
pat = PatEnum(enum_path, None);
} else {
args = self.parse_enum_variant_seq(
- &token::LPAREN,
- &token::RPAREN,
- seq_sep_trailing_allowed(token::COMMA),
+ &token::LParen,
+ &token::RParen,
+ seq_sep_trailing_allowed(token::Comma),
|p| p.parse_pat()
);
pat = PatEnum(enum_path, Some(args));
fn parse_pat_ident(&mut self,
binding_mode: ast::BindingMode)
-> ast::Pat_ {
- if !is_plain_ident(&self.token) {
+ if !self.token.is_plain_ident() {
let span = self.span;
let tok_str = self.this_token_to_string();
self.span_fatal(span,
let ident = self.parse_ident();
let last_span = self.last_span;
let name = codemap::Spanned{span: last_span, node: ident};
- let sub = if self.eat(&token::AT) {
+ let sub = if self.eat(&token::At) {
Some(self.parse_pat())
} else {
None
// leads to a parse error. Note that if there is no explicit
// binding mode then we do not end up here, because the lookahead
// will direct us over to parse_enum_variant()
- if self.token == token::LPAREN {
+ if self.token == token::LParen {
let last_span = self.last_span;
self.span_fatal(
last_span,
node: TyInfer,
span: mk_sp(lo, lo),
});
- if self.eat(&token::COLON) {
+ if self.eat(&token::Colon) {
ty = self.parse_ty(true);
}
let init = self.parse_initializer();
fn parse_name_and_ty(&mut self, pr: Visibility,
attrs: Vec<Attribute> ) -> StructField {
let lo = self.span.lo;
- if !is_plain_ident(&self.token) {
+ if !self.token.is_plain_ident() {
self.fatal("expected ident");
}
let name = self.parse_ident();
- self.expect(&token::COLON);
+ self.expect(&token::Colon);
let ty = self.parse_ty(true);
spanned(lo, self.last_span.hi, ast::StructField_ {
kind: NamedField(name, pr),
}
let lo = self.span.lo;
- if self.is_keyword(keywords::Let) {
+ if self.token.is_keyword(keywords::Let) {
check_expected_item(self, item_attrs.as_slice());
self.expect_keyword(keywords::Let);
let decl = self.parse_let();
P(spanned(lo, decl.span.hi, StmtDecl(decl, ast::DUMMY_NODE_ID)))
- } else if is_ident(&self.token)
- && !token::is_any_keyword(&self.token)
- && self.look_ahead(1, |t| *t == token::NOT) {
+ } else if self.token.is_ident()
+ && !self.token.is_any_keyword()
+ && self.look_ahead(1, |t| *t == token::Not) {
// it's a macro invocation:
check_expected_item(self, item_attrs.as_slice());
let pth = self.parse_path(NoTypesAllowed).path;
self.bump();
- let id = if token::close_delimiter_for(&self.token).is_some() {
+ let id = if self.token.get_close_delimiter().is_some() {
token::special_idents::invalid // no special identifier
} else {
self.parse_ident()
// check that we're pointing at delimiters (need to check
// again after the `if`, because of `parse_ident`
// consuming more tokens).
- let (bra, ket) = match token::close_delimiter_for(&self.token) {
+ let (bra, ket) = match self.token.get_close_delimiter() {
Some(ket) => (self.token.clone(), ket),
None => {
// we only expect an ident if we didn't parse one
maybe_whole!(no_clone self, NtBlock);
let lo = self.span.lo;
- self.expect(&token::LBRACE);
+ self.expect(&token::LBrace);
return self.parse_block_tail_(lo, DefaultBlock, Vec::new());
}
maybe_whole!(pair_empty self, NtBlock);
let lo = self.span.lo;
- self.expect(&token::LBRACE);
+ self.expect(&token::LBrace);
let (inner, next) = self.parse_inner_attrs_and_next();
(inner, self.parse_block_tail_(lo, DefaultBlock, next))
let mut attributes_box = attrs_remaining;
- while self.token != token::RBRACE {
+ while self.token != token::RBrace {
// parsing items even when they're not allowed lets us give
// better error messages and recover more gracefully.
attributes_box.push_all(self.parse_outer_attributes().as_slice());
match self.token {
- token::SEMI => {
+ token::Semi => {
if !attributes_box.is_empty() {
let last_span = self.last_span;
self.span_err(last_span,
}
self.bump(); // empty
}
- token::RBRACE => {
+ token::RBrace => {
// fall through and out.
}
_ => {
// expression without semicolon
if classify::expr_requires_semi_to_be_stmt(&*e) {
// Just check for errors and recover; do not eat semicolon yet.
- self.commit_stmt(&[], &[token::SEMI, token::RBRACE]);
+ self.commit_stmt(&[], &[token::Semi, token::RBrace]);
}
match self.token {
- token::SEMI => {
+ token::Semi => {
self.bump();
let span_with_semi = Span {
lo: span.lo,
span: span_with_semi,
}));
}
- token::RBRACE => {
+ token::RBrace => {
expr = Some(e);
}
_ => {
StmtMac(m, semi) => {
// statement macro; might be an expr
match self.token {
- token::SEMI => {
+ token::Semi => {
stmts.push(P(Spanned {
node: StmtMac(m, true),
span: span,
}));
self.bump();
}
- token::RBRACE => {
+ token::RBrace => {
// if a block ends in `m!(arg)` without
// a `;`, it must be an expr
expr = Some(
}
_ => { // all other kinds of statements:
if classify::stmt_ends_with_semi(&node) {
- self.commit_stmt_expecting(token::SEMI);
+ self.commit_stmt_expecting(token::Semi);
}
stmts.push(P(Spanned {
fn parse_colon_then_ty_param_bounds(&mut self)
-> OwnedSlice<TyParamBound>
{
- if !self.eat(&token::COLON) {
+ if !self.eat(&token::Colon) {
OwnedSlice::empty()
} else {
self.parse_ty_param_bounds()
{
let mut result = vec!();
loop {
- let lifetime_defs = if self.eat(&token::LT) {
+ let lifetime_defs = if self.eat(&token::Lt) {
let lifetime_defs = self.parse_lifetime_defs();
self.expect_gt();
lifetime_defs
Vec::new()
};
match self.token {
- token::LIFETIME(lifetime) => {
+ token::Lifetime(lifetime) => {
if lifetime_defs.len() > 0 {
let span = self.last_span;
self.span_err(span, "lifetime declarations are not \
}));
self.bump();
}
- token::MOD_SEP | token::IDENT(..) => {
+ token::ModSep | token::Ident(..) => {
let path =
self.parse_path(LifetimeAndTypesWithoutColons).path;
- if self.token == token::LPAREN {
+ if self.token == token::LParen {
self.bump();
let inputs = self.parse_seq_to_end(
- &token::RPAREN,
- seq_sep_trailing_allowed(token::COMMA),
+ &token::RParen,
+ seq_sep_trailing_allowed(token::Comma),
|p| p.parse_arg_general(false));
let (return_style, output) = self.parse_ret_ty();
result.push(UnboxedFnTyParamBound(P(UnboxedFnBound {
_ => break,
}
- if !self.eat(&token::BINOP(token::PLUS)) {
+ if !self.eat(&token::BinOp(token::Plus)) {
break;
}
}
let mut span = self.span;
let mut ident = self.parse_ident();
let mut unbound = None;
- if self.eat(&token::QUESTION) {
+ if self.eat(&token::Question) {
let tref = Parser::trait_ref_from_ident(ident, span);
unbound = Some(TraitTyParamBound(tref));
span = self.span;
let bounds = self.parse_colon_then_ty_param_bounds();
- let default = if self.token == token::EQ {
+ let default = if self.token == token::Eq {
self.bump();
Some(self.parse_ty(true))
}
/// | ( < lifetimes , typaramseq ( , )? > )
/// where typaramseq = ( typaram ) | ( typaram , typaramseq )
pub fn parse_generics(&mut self) -> ast::Generics {
- if self.eat(&token::LT) {
+ if self.eat(&token::Lt) {
let lifetime_defs = self.parse_lifetime_defs();
let mut seen_default = false;
- let ty_params = self.parse_seq_to_gt(Some(token::COMMA), |p| {
+ let ty_params = self.parse_seq_to_gt(Some(token::Comma), |p| {
p.forbid_lifetime();
let ty_param = p.parse_ty_param();
if ty_param.default.is_some() {
}
fn parse_generic_values_after_lt(&mut self) -> (Vec<ast::Lifetime>, Vec<P<Ty>> ) {
- let lifetimes = self.parse_lifetimes(token::COMMA);
+ let lifetimes = self.parse_lifetimes(token::Comma);
let result = self.parse_seq_to_gt(
- Some(token::COMMA),
+ Some(token::Comma),
|p| {
p.forbid_lifetime();
p.parse_ty(true)
}
fn forbid_lifetime(&mut self) {
- if Parser::token_is_lifetime(&self.token) {
+ if self.token.is_lifetime() {
let span = self.span;
self.span_fatal(span, "lifetime parameters must be declared \
prior to type parameters");
loop {
let lo = self.span.lo;
let ident = match self.token {
- token::IDENT(..) => self.parse_ident(),
+ token::Ident(..) => self.parse_ident(),
_ => break,
};
- self.expect(&token::COLON);
+ self.expect(&token::Colon);
let bounds = self.parse_ty_param_bounds();
let hi = self.span.hi;
});
parsed_something = true;
- if !self.eat(&token::COMMA) {
+ if !self.eat(&token::Comma) {
break
}
}
let sp = self.span;
let mut args: Vec<Option<Arg>> =
self.parse_unspanned_seq(
- &token::LPAREN,
- &token::RPAREN,
- seq_sep_trailing_allowed(token::COMMA),
+ &token::LParen,
+ &token::RParen,
+ seq_sep_trailing_allowed(token::Comma),
|p| {
- if p.token == token::DOTDOTDOT {
+ if p.token == token::DotDotDot {
p.bump();
if allow_variadic {
- if p.token != token::RPAREN {
+ if p.token != token::RParen {
let span = p.span;
p.span_fatal(span,
"`...` must be last in argument list for variadic function");
fn is_self_ident(&mut self) -> bool {
match self.token {
- token::IDENT(id, false) => id.name == special_idents::self_.name,
+ token::Ident(id, token::Plain) => id.name == special_idents::self_.name,
_ => false
}
}
fn expect_self_ident(&mut self) -> ast::Ident {
match self.token {
- token::IDENT(id, false) if id.name == special_idents::self_.name => {
+ token::Ident(id, token::Plain) if id.name == special_idents::self_.name => {
self.bump();
id
},
//
// We already know that the current token is `&`.
- if this.look_ahead(1, |t| token::is_keyword(keywords::Self, t)) {
+ if this.look_ahead(1, |t| t.is_keyword(keywords::Self)) {
this.bump();
SelfRegion(None, MutImmutable, this.expect_self_ident())
- } else if this.look_ahead(1, |t| Parser::token_is_mutability(t)) &&
- this.look_ahead(2,
- |t| token::is_keyword(keywords::Self,
- t)) {
+ } else if this.look_ahead(1, |t| t.is_mutability()) &&
+ this.look_ahead(2, |t| t.is_keyword(keywords::Self)) {
this.bump();
let mutability = this.parse_mutability();
SelfRegion(None, mutability, this.expect_self_ident())
- } else if this.look_ahead(1, |t| Parser::token_is_lifetime(t)) &&
- this.look_ahead(2,
- |t| token::is_keyword(keywords::Self,
- t)) {
+ } else if this.look_ahead(1, |t| t.is_lifetime()) &&
+ this.look_ahead(2, |t| t.is_keyword(keywords::Self)) {
this.bump();
let lifetime = this.parse_lifetime();
SelfRegion(Some(lifetime), MutImmutable, this.expect_self_ident())
- } else if this.look_ahead(1, |t| Parser::token_is_lifetime(t)) &&
- this.look_ahead(2, |t| {
- Parser::token_is_mutability(t)
- }) &&
- this.look_ahead(3, |t| token::is_keyword(keywords::Self,
- t)) {
+ } else if this.look_ahead(1, |t| t.is_lifetime()) &&
+ this.look_ahead(2, |t| t.is_mutability()) &&
+ this.look_ahead(3, |t| t.is_keyword(keywords::Self)) {
this.bump();
let lifetime = this.parse_lifetime();
let mutability = this.parse_mutability();
}
}
- self.expect(&token::LPAREN);
+ self.expect(&token::LParen);
// A bit of complexity and lookahead is needed here in order to be
// backwards compatible.
let mut mutbl_self = MutImmutable;
let explicit_self = match self.token {
- token::BINOP(token::AND) => {
+ token::BinOp(token::And) => {
let eself = maybe_parse_borrowed_explicit_self(self);
self_ident_lo = self.last_span.lo;
self_ident_hi = self.last_span.hi;
eself
}
- token::TILDE => {
+ token::Tilde => {
// We need to make sure it isn't a type
- if self.look_ahead(1, |t| token::is_keyword(keywords::Self, t)) {
+ if self.look_ahead(1, |t| t.is_keyword(keywords::Self)) {
self.bump();
drop(self.expect_self_ident());
let last_span = self.last_span;
}
SelfStatic
}
- token::BINOP(token::STAR) => {
+ token::BinOp(token::Star) => {
// Possibly "*self" or "*mut self" -- not supported. Try to avoid
// emitting cryptic "unexpected token" errors.
self.bump();
- let _mutability = if Parser::token_is_mutability(&self.token) {
+ let _mutability = if self.token.is_mutability() {
self.parse_mutability()
} else {
MutImmutable
// error case, making bogus self ident:
SelfValue(special_idents::self_)
}
- token::IDENT(..) => {
+ token::Ident(..) => {
if self.is_self_ident() {
let self_ident = self.expect_self_ident();
// Determine whether this is the fully explicit form, `self:
// TYPE`.
- if self.eat(&token::COLON) {
+ if self.eat(&token::Colon) {
SelfExplicit(self.parse_ty(false), self_ident)
} else {
SelfValue(self_ident)
}
- } else if Parser::token_is_mutability(&self.token) &&
- self.look_ahead(1, |t| {
- token::is_keyword(keywords::Self, t)
- }) {
+ } else if self.token.is_mutability() &&
+ self.look_ahead(1, |t| t.is_keyword(keywords::Self)) {
mutbl_self = self.parse_mutability();
let self_ident = self.expect_self_ident();
// Determine whether this is the fully explicit form,
// `self: TYPE`.
- if self.eat(&token::COLON) {
+ if self.eat(&token::Colon) {
SelfExplicit(self.parse_ty(false), self_ident)
} else {
SelfValue(self_ident)
}
- } else if Parser::token_is_mutability(&self.token) &&
- self.look_ahead(1, |t| *t == token::TILDE) &&
- self.look_ahead(2, |t| {
- token::is_keyword(keywords::Self, t)
- }) {
+ } else if self.token.is_mutability() &&
+ self.look_ahead(1, |t| *t == token::Tilde) &&
+ self.look_ahead(2, |t| t.is_keyword(keywords::Self)) {
mutbl_self = self.parse_mutability();
self.bump();
drop(self.expect_self_ident());
{
// If we parsed a self type, expect a comma before the argument list.
match self.token {
- token::COMMA => {
+ token::Comma => {
self.bump();
- let sep = seq_sep_trailing_allowed(token::COMMA);
+ let sep = seq_sep_trailing_allowed(token::Comma);
let mut fn_inputs = self.parse_seq_to_before_end(
- &token::RPAREN,
+ &token::RParen,
sep,
parse_arg_fn
);
fn_inputs.insert(0, Arg::new_self(explicit_self_sp, mutbl_self, $self_id));
fn_inputs
}
- token::RPAREN => {
+ token::RParen => {
vec!(Arg::new_self(explicit_self_sp, mutbl_self, $self_id))
}
_ => {
let fn_inputs = match explicit_self {
SelfStatic => {
- let sep = seq_sep_trailing_allowed(token::COMMA);
- self.parse_seq_to_before_end(&token::RPAREN, sep, parse_arg_fn)
+ let sep = seq_sep_trailing_allowed(token::Comma);
+ self.parse_seq_to_before_end(&token::RParen, sep, parse_arg_fn)
}
SelfValue(id) => parse_remaining_arguments!(id),
SelfRegion(_,_,id) => parse_remaining_arguments!(id),
};
- self.expect(&token::RPAREN);
+ self.expect(&token::RParen);
let hi = self.span.hi;
fn parse_fn_block_decl(&mut self)
-> (P<FnDecl>, Option<UnboxedClosureKind>) {
let (optional_unboxed_closure_kind, inputs_captures) = {
- if self.eat(&token::OROR) {
+ if self.eat(&token::OrOr) {
(None, Vec::new())
} else {
- self.expect(&token::BINOP(token::OR));
+ self.expect(&token::BinOp(token::Or));
let optional_unboxed_closure_kind =
self.parse_optional_unboxed_closure_kind();
let args = self.parse_seq_to_before_end(
- &token::BINOP(token::OR),
- seq_sep_trailing_allowed(token::COMMA),
+ &token::BinOp(token::Or),
+ seq_sep_trailing_allowed(token::Comma),
|p| p.parse_fn_block_arg()
);
self.bump();
(optional_unboxed_closure_kind, args)
}
};
- let (style, output) = if self.token == token::RARROW {
+ let (style, output) = if self.token == token::RArrow {
self.parse_ret_ty()
} else {
(Return, P(Ty {
/// Parses the `(arg, arg) -> return_type` header on a procedure.
fn parse_proc_decl(&mut self) -> P<FnDecl> {
let inputs =
- self.parse_unspanned_seq(&token::LPAREN,
- &token::RPAREN,
- seq_sep_trailing_allowed(token::COMMA),
+ self.parse_unspanned_seq(&token::LParen,
+ &token::RParen,
+ seq_sep_trailing_allowed(token::Comma),
|p| p.parse_fn_block_arg());
- let (style, output) = if self.token == token::RARROW {
+ let (style, output) = if self.token == token::RArrow {
self.parse_ret_ty()
} else {
(Return, P(Ty {
// code copied from parse_macro_use_or_failure... abstraction!
let (method_, hi, new_attrs) = {
- if !token::is_any_keyword(&self.token)
- && self.look_ahead(1, |t| *t == token::NOT)
- && (self.look_ahead(2, |t| *t == token::LPAREN)
- || self.look_ahead(2, |t| *t == token::LBRACE)) {
+ if !self.token.is_any_keyword()
+ && self.look_ahead(1, |t| *t == token::Not)
+ && (self.look_ahead(2, |t| *t == token::LParen)
+ || self.look_ahead(2, |t| *t == token::LBrace)) {
// method macro.
let pth = self.parse_path(NoTypesAllowed).path;
- self.expect(&token::NOT);
+ self.expect(&token::Not);
// eat a matched-delimiter token tree:
- let tts = match token::close_delimiter_for(&self.token) {
+ let tts = match self.token.get_close_delimiter() {
Some(ket) => {
self.bump();
self.parse_seq_to_end(&ket,
fn parse_impl_items(&mut self) -> (Vec<ImplItem>, Vec<Attribute>) {
let mut impl_items = Vec::new();
- self.expect(&token::LBRACE);
+ self.expect(&token::LBrace);
let (inner_attrs, mut method_attrs) =
self.parse_inner_attrs_and_next();
- while !self.eat(&token::RBRACE) {
+ while !self.eat(&token::RBrace) {
method_attrs.extend(self.parse_outer_attributes().into_iter());
let vis = self.parse_visibility();
if self.eat_keyword(keywords::Type) {
// Special case: if the next identifier that follows is '(', don't
// allow this to be parsed as a trait.
- let could_be_trait = self.token != token::LPAREN;
+ let could_be_trait = self.token != token::LParen;
// Parse the trait.
let mut ty = self.parse_ty(true);
let class_name = self.parse_ident();
let mut generics = self.parse_generics();
- if self.eat(&token::COLON) {
+ if self.eat(&token::Colon) {
let ty = self.parse_ty(true);
self.span_err(ty.span, "`virtual` structs have been removed from the language");
}
let mut fields: Vec<StructField>;
let is_tuple_like;
- if self.eat(&token::LBRACE) {
+ if self.eat(&token::LBrace) {
// It's a record-like struct.
is_tuple_like = false;
fields = Vec::new();
- while self.token != token::RBRACE {
+ while self.token != token::RBrace {
fields.push(self.parse_struct_decl_field());
}
if fields.len() == 0 {
token::get_ident(class_name)).as_slice());
}
self.bump();
- } else if self.token == token::LPAREN {
+ } else if self.token == token::LParen {
// It's a tuple-like struct.
is_tuple_like = true;
fields = self.parse_unspanned_seq(
- &token::LPAREN,
- &token::RPAREN,
- seq_sep_trailing_allowed(token::COMMA),
+ &token::LParen,
+ &token::RParen,
+ seq_sep_trailing_allowed(token::Comma),
|p| {
let attrs = p.parse_outer_attributes();
let lo = p.span.lo;
written as `struct {};`",
token::get_ident(class_name)).as_slice());
}
- self.expect(&token::SEMI);
- } else if self.eat(&token::SEMI) {
+ self.expect(&token::Semi);
+ } else if self.eat(&token::Semi) {
// It's a unit-like struct.
is_tuple_like = true;
fields = Vec::new();
-> StructField {
let a_var = self.parse_name_and_ty(vis, attrs);
match self.token {
- token::COMMA => {
+ token::Comma => {
self.bump();
}
- token::RBRACE => {}
+ token::RBrace => {}
_ => {
let span = self.span;
let token_str = self.this_token_to_string();
if self.eat_keyword(keywords::For) {
let span = self.span;
let ident = self.parse_ident();
- if !self.eat(&token::QUESTION) {
+ if !self.eat(&token::Question) {
self.span_err(span,
"expected 'Sized?' after `for` in trait item");
return None;
fn parse_item_const(&mut self, m: Option<Mutability>) -> ItemInfo {
let id = self.parse_ident();
- self.expect(&token::COLON);
+ self.expect(&token::Colon);
let ty = self.parse_ty(true);
- self.expect(&token::EQ);
+ self.expect(&token::Eq);
let e = self.parse_expr();
- self.commit_expr_expecting(&*e, token::SEMI);
+ self.commit_expr_expecting(&*e, token::Semi);
let item = match m {
Some(m) => ItemStatic(ty, m, e),
None => ItemConst(ty, e),
fn parse_item_mod(&mut self, outer_attrs: &[Attribute]) -> ItemInfo {
let id_span = self.span;
let id = self.parse_ident();
- if self.token == token::SEMI {
+ if self.token == token::Semi {
self.bump();
// This mod is in an external file. Let's go get it!
let (m, attrs) = self.eval_src_mod(id, outer_attrs, id_span);
(id, m, Some(attrs))
} else {
self.push_mod_path(id, outer_attrs);
- self.expect(&token::LBRACE);
+ self.expect(&token::LBrace);
let mod_inner_lo = self.span.lo;
let old_owns_directory = self.owns_directory;
self.owns_directory = true;
let (inner, next) = self.parse_inner_attrs_and_next();
- let m = self.parse_mod_items(token::RBRACE, next, mod_inner_lo);
- self.expect(&token::RBRACE);
+ let m = self.parse_mod_items(token::RBrace, next, mod_inner_lo);
+ self.expect(&token::RBrace);
self.owns_directory = old_owns_directory;
self.pop_mod_path();
(id, ItemMod(m), Some(inner))
let mod_inner_lo = p0.span.lo;
let (mod_attrs, next) = p0.parse_inner_attrs_and_next();
let first_item_outer_attrs = next;
- let m0 = p0.parse_mod_items(token::EOF, first_item_outer_attrs, mod_inner_lo);
+ let m0 = p0.parse_mod_items(token::Eof, first_item_outer_attrs, mod_inner_lo);
self.sess.included_mod_stack.borrow_mut().pop();
return (ast::ItemMod(m0), mod_attrs);
}
let decl = self.parse_fn_decl(true);
self.parse_where_clause(&mut generics);
let hi = self.span.hi;
- self.expect(&token::SEMI);
+ self.expect(&token::Semi);
P(ast::ForeignItem {
ident: ident,
attrs: attrs,
let mutbl = self.eat_keyword(keywords::Mut);
let ident = self.parse_ident();
- self.expect(&token::COLON);
+ self.expect(&token::Colon);
let ty = self.parse_ty(true);
let hi = self.span.hi;
- self.expect(&token::SEMI);
+ self.expect(&token::Semi);
P(ForeignItem {
ident: ident,
attrs: attrs,
self.span_err(last_span,
Parser::expected_item_err(attrs_remaining.as_slice()));
}
- assert!(self.token == token::RBRACE);
+ assert!(self.token == token::RBrace);
ast::ForeignMod {
abi: abi,
view_items: view_items,
let span = self.span;
let (maybe_path, ident) = match self.token {
- token::IDENT(..) => {
+ token::Ident(..) => {
let the_ident = self.parse_ident();
- let path = if self.eat(&token::EQ) {
+ let path = if self.eat(&token::Eq) {
let path = self.parse_str();
let span = self.span;
self.obsolete(span, ObsoleteExternCrateRenaming);
Some(path)
} else if self.eat_keyword(keywords::As) {
// skip the ident if there is one
- if is_ident(&self.token) { self.bump(); }
+ if self.token.is_ident() { self.bump(); }
self.span_err(span,
format!("expected `;`, found `as`; perhaps you meant \
} else {
None
};
- self.expect(&token::SEMI);
+ self.expect(&token::Semi);
(path, the_ident)
},
- token::LIT_STR(..) | token::LIT_STR_RAW(..) => {
+ token::LitStr(..) | token::LitStrRaw(..) => {
let path = self.parse_str();
self.expect_keyword(keywords::As);
let the_ident = self.parse_ident();
- self.expect(&token::SEMI);
+ self.expect(&token::Semi);
(Some(path), the_ident)
},
_ => {
attrs: Vec<Attribute> )
-> ItemOrViewItem {
- self.expect(&token::LBRACE);
+ self.expect(&token::LBrace);
let abi = opt_abi.unwrap_or(abi::C);
let (inner, next) = self.parse_inner_attrs_and_next();
let m = self.parse_foreign_mod_items(abi, next);
- self.expect(&token::RBRACE);
+ self.expect(&token::RBrace);
let last_span = self.last_span;
let item = self.mk_item(lo,
let ident = self.parse_ident();
let mut tps = self.parse_generics();
self.parse_where_clause(&mut tps);
- self.expect(&token::EQ);
+ self.expect(&token::Eq);
let ty = self.parse_ty(true);
- self.expect(&token::SEMI);
+ self.expect(&token::Semi);
(ident, ItemTy(ty, tps), None)
}
/// this should probably be renamed or refactored...
fn parse_struct_def(&mut self) -> P<StructDef> {
let mut fields: Vec<StructField> = Vec::new();
- while self.token != token::RBRACE {
+ while self.token != token::RBrace {
fields.push(self.parse_struct_decl_field());
}
self.bump();
let mut variants = Vec::new();
let mut all_nullary = true;
let mut any_disr = None;
- while self.token != token::RBRACE {
+ while self.token != token::RBrace {
let variant_attrs = self.parse_outer_attributes();
let vlo = self.span.lo;
let mut args = Vec::new();
let mut disr_expr = None;
ident = self.parse_ident();
- if self.eat(&token::LBRACE) {
+ if self.eat(&token::LBrace) {
// Parse a struct variant.
all_nullary = false;
kind = StructVariantKind(self.parse_struct_def());
- } else if self.token == token::LPAREN {
+ } else if self.token == token::LParen {
all_nullary = false;
let arg_tys = self.parse_enum_variant_seq(
- &token::LPAREN,
- &token::RPAREN,
- seq_sep_trailing_allowed(token::COMMA),
+ &token::LParen,
+ &token::RParen,
+ seq_sep_trailing_allowed(token::Comma),
|p| p.parse_ty(true)
);
for ty in arg_tys.into_iter() {
});
}
kind = TupleVariantKind(args);
- } else if self.eat(&token::EQ) {
+ } else if self.eat(&token::Eq) {
disr_expr = Some(self.parse_expr());
any_disr = disr_expr.as_ref().map(|expr| expr.span);
kind = TupleVariantKind(args);
};
variants.push(P(spanned(vlo, self.last_span.hi, vr)));
- if !self.eat(&token::COMMA) { break; }
+ if !self.eat(&token::Comma) { break; }
}
- self.expect(&token::RBRACE);
+ self.expect(&token::RBrace);
match any_disr {
Some(disr_span) if !all_nullary =>
self.span_err(disr_span,
let id = self.parse_ident();
let mut generics = self.parse_generics();
self.parse_where_clause(&mut generics);
- self.expect(&token::LBRACE);
+ self.expect(&token::LBrace);
let enum_definition = self.parse_enum_def(&generics);
(id, ItemEnum(enum_definition, generics), None)
fn fn_expr_lookahead(tok: &token::Token) -> bool {
match *tok {
- token::LPAREN | token::AT | token::TILDE | token::BINOP(_) => true,
+ token::LParen | token::At | token::Tilde | token::BinOp(_) => true,
_ => false
}
}
/// the `extern` keyword, if one is found.
fn parse_opt_abi(&mut self) -> Option<abi::Abi> {
match self.token {
- token::LIT_STR(s) | token::LIT_STR_RAW(s, _) => {
+ token::LitStr(s) | token::LitStrRaw(s, _) => {
self.bump();
let the_string = s.as_str();
match abi::lookup(the_string) {
macros_allowed: bool)
-> ItemOrViewItem {
let nt_item = match self.token {
- INTERPOLATED(token::NtItem(ref item)) => {
+ token::Interpolated(token::NtItem(ref item)) => {
Some((**item).clone())
}
_ => None
if self.eat_keyword(keywords::Use) {
// USE ITEM (IoviViewItem)
let view_item = self.parse_use();
- self.expect(&token::SEMI);
+ self.expect(&token::Semi);
return IoviViewItem(ast::ViewItem {
node: view_item,
attrs: attrs,
visibility,
maybe_append(attrs, extra_attrs));
return IoviItem(item);
- } else if self.token == token::LBRACE {
+ } else if self.token == token::LBrace {
return self.parse_item_foreign_mod(lo, opt_abi, visibility, attrs);
}
}
// the rest are all guaranteed to be items:
- if self.is_keyword(keywords::Static) {
+ if self.token.is_keyword(keywords::Static) {
// STATIC ITEM
self.bump();
let m = if self.eat_keyword(keywords::Mut) {MutMutable} else {MutImmutable};
maybe_append(attrs, extra_attrs));
return IoviItem(item);
}
- if self.is_keyword(keywords::Const) {
+ if self.token.is_keyword(keywords::Const) {
// CONST ITEM
self.bump();
if self.eat_keyword(keywords::Mut) {
maybe_append(attrs, extra_attrs));
return IoviItem(item);
}
- if self.is_keyword(keywords::Fn) &&
+ if self.token.is_keyword(keywords::Fn) &&
self.look_ahead(1, |f| !Parser::fn_expr_lookahead(f)) {
// FUNCTION ITEM
self.bump();
maybe_append(attrs, extra_attrs));
return IoviItem(item);
}
- if self.is_keyword(keywords::Unsafe)
- && self.look_ahead(1u, |t| *t != token::LBRACE) {
+ if self.token.is_keyword(keywords::Unsafe)
+ && self.look_ahead(1u, |t| *t != token::LBrace) {
// UNSAFE FUNCTION ITEM
self.bump();
let abi = if self.eat_keyword(keywords::Extern) {
let visibility = self.parse_visibility();
- if self.is_keyword(keywords::Static) {
+ if self.token.is_keyword(keywords::Static) {
// FOREIGN STATIC ITEM
let item = self.parse_item_foreign_static(visibility, attrs);
return IoviForeignItem(item);
}
- if self.is_keyword(keywords::Fn) || self.is_keyword(keywords::Unsafe) {
+ if self.token.is_keyword(keywords::Fn) || self.token.is_keyword(keywords::Unsafe) {
// FOREIGN FUNCTION ITEM
let item = self.parse_item_foreign_fn(visibility, attrs);
return IoviForeignItem(item);
lo: BytePos,
visibility: Visibility
) -> ItemOrViewItem {
- if macros_allowed && !token::is_any_keyword(&self.token)
- && self.look_ahead(1, |t| *t == token::NOT)
- && (self.look_ahead(2, |t| is_plain_ident(t))
- || self.look_ahead(2, |t| *t == token::LPAREN)
- || self.look_ahead(2, |t| *t == token::LBRACE)) {
+ if macros_allowed && !self.token.is_any_keyword()
+ && self.look_ahead(1, |t| *t == token::Not)
+ && (self.look_ahead(2, |t| t.is_plain_ident())
+ || self.look_ahead(2, |t| *t == token::LParen)
+ || self.look_ahead(2, |t| *t == token::LBrace)) {
// MACRO INVOCATION ITEM
// item macro.
let pth = self.parse_path(NoTypesAllowed).path;
- self.expect(&token::NOT);
+ self.expect(&token::Not);
// a 'special' identifier (like what `macro_rules!` uses)
// is optional. We should eventually unify invoc syntax
// and remove this.
- let id = if is_plain_ident(&self.token) {
+ let id = if self.token.is_plain_ident() {
self.parse_ident()
} else {
token::special_idents::invalid // no special identifier
};
// eat a matched-delimiter token tree:
- let tts = match token::close_delimiter_for(&self.token) {
+ let tts = match self.token.get_close_delimiter() {
Some(ket) => {
self.bump();
self.parse_seq_to_end(&ket,
fn parse_view_path(&mut self) -> P<ViewPath> {
let lo = self.span.lo;
- if self.token == token::LBRACE {
+ if self.token == token::LBrace {
// use {foo,bar}
let idents = self.parse_unspanned_seq(
- &token::LBRACE, &token::RBRACE,
- seq_sep_trailing_allowed(token::COMMA),
+ &token::LBrace, &token::RBrace,
+ seq_sep_trailing_allowed(token::Comma),
|p| p.parse_path_list_item());
let path = ast::Path {
span: mk_sp(lo, self.span.hi),
let first_ident = self.parse_ident();
let mut path = vec!(first_ident);
match self.token {
- token::EQ => {
+ token::Eq => {
// x = foo::bar
self.bump();
let path_lo = self.span.lo;
path = vec!(self.parse_ident());
- while self.token == token::MOD_SEP {
+ while self.token == token::ModSep {
self.bump();
let id = self.parse_ident();
path.push(id);
ast::DUMMY_NODE_ID)));
}
- token::MOD_SEP => {
+ token::ModSep => {
// foo::bar or foo::{a,b,c} or foo::*
- while self.token == token::MOD_SEP {
+ while self.token == token::ModSep {
self.bump();
match self.token {
- token::IDENT(i, _) => {
+ token::Ident(i, _) => {
self.bump();
path.push(i);
}
// foo::bar::{a,b,c}
- token::LBRACE => {
+ token::LBrace => {
let idents = self.parse_unspanned_seq(
- &token::LBRACE,
- &token::RBRACE,
- seq_sep_trailing_allowed(token::COMMA),
+ &token::LBrace,
+ &token::RBrace,
+ seq_sep_trailing_allowed(token::Comma),
|p| p.parse_path_list_item()
);
let path = ast::Path {
}
// foo::bar::*
- token::BINOP(token::STAR) => {
+ token::BinOp(token::Star) => {
self.bump();
let path = ast::Path {
span: mk_sp(lo, self.span.hi),
break;
}
IoviForeignItem(_) => {
- fail!();
+ panic!();
}
}
attrs = self.parse_outer_attributes();
items.push(item)
}
IoviForeignItem(_) => {
- fail!();
+ panic!();
}
}
}
loop {
match self.parse_foreign_item(attrs, macros_allowed) {
IoviNone(returned_attrs) => {
- if self.token == token::RBRACE {
+ if self.token == token::RBrace {
attrs = returned_attrs;
break
}
let (inner, next) = self.parse_inner_attrs_and_next();
let first_item_outer_attrs = next;
// parse the items inside the crate:
- let m = self.parse_mod_items(token::EOF, first_item_outer_attrs, lo);
+ let m = self.parse_mod_items(token::Eof, first_item_outer_attrs, lo);
ast::Crate {
module: m,
pub fn parse_optional_str(&mut self)
-> Option<(InternedString, ast::StrStyle)> {
let (s, style) = match self.token {
- token::LIT_STR(s) => (self.id_to_interned_str(s.ident()), ast::CookedStr),
- token::LIT_STR_RAW(s, n) => {
+ token::LitStr(s) => (self.id_to_interned_str(s.ident()), ast::CookedStr),
+ token::LitStrRaw(s, n) => {
(self.id_to_interned_str(s.ident()), ast::RawStr(n))
}
_ => return None
// except according to those terms.
use ast;
-use ast::{Ident, Name, Mrk};
use ext::mtwt;
-use parse::token;
use ptr::P;
use util::interner::{RcStr, StrInterner};
use util::interner;
use std::path::BytesContainer;
use std::rc::Rc;
+// NOTE(stage0): remove these re-exports after the next snapshot
+// (needed to allow quotations to pass stage0)
+#[cfg(stage0)] pub use self::Plus as PLUS;
+#[cfg(stage0)] pub use self::Minus as MINUS;
+#[cfg(stage0)] pub use self::Star as STAR;
+#[cfg(stage0)] pub use self::Slash as SLASH;
+#[cfg(stage0)] pub use self::Percent as PERCENT;
+#[cfg(stage0)] pub use self::Caret as CARET;
+#[cfg(stage0)] pub use self::And as AND;
+#[cfg(stage0)] pub use self::Or as OR;
+#[cfg(stage0)] pub use self::Shl as SHL;
+#[cfg(stage0)] pub use self::Shr as SHR;
+#[cfg(stage0)] pub use self::Eq as EQ;
+#[cfg(stage0)] pub use self::Lt as LT;
+#[cfg(stage0)] pub use self::Le as LE;
+#[cfg(stage0)] pub use self::EqEq as EQEQ;
+#[cfg(stage0)] pub use self::Ne as NE;
+#[cfg(stage0)] pub use self::Ge as GE;
+#[cfg(stage0)] pub use self::Gt as GT;
+#[cfg(stage0)] pub use self::AndAnd as ANDAND;
+#[cfg(stage0)] pub use self::OrOr as OROR;
+#[cfg(stage0)] pub use self::Not as NOT;
+#[cfg(stage0)] pub use self::Tilde as TILDE;
+#[cfg(stage0)] pub use self::BinOp as BINOP;
+#[cfg(stage0)] pub use self::BinOpEq as BINOPEQ;
+#[cfg(stage0)] pub use self::At as AT;
+#[cfg(stage0)] pub use self::Dot as DOT;
+#[cfg(stage0)] pub use self::DotDot as DOTDOT;
+#[cfg(stage0)] pub use self::DotDotDot as DOTDOTDOT;
+#[cfg(stage0)] pub use self::Comma as COMMA;
+#[cfg(stage0)] pub use self::Semi as SEMI;
+#[cfg(stage0)] pub use self::Colon as COLON;
+#[cfg(stage0)] pub use self::ModSep as MOD_SEP;
+#[cfg(stage0)] pub use self::RArrow as RARROW;
+#[cfg(stage0)] pub use self::LArrow as LARROW;
+#[cfg(stage0)] pub use self::FatArrow as FAT_ARROW;
+#[cfg(stage0)] pub use self::LParen as LPAREN;
+#[cfg(stage0)] pub use self::RParen as RPAREN;
+#[cfg(stage0)] pub use self::LBracket as LBRACKET;
+#[cfg(stage0)] pub use self::RBracket as RBRACKET;
+#[cfg(stage0)] pub use self::LBrace as LBRACE;
+#[cfg(stage0)] pub use self::RBrace as RBRACE;
+#[cfg(stage0)] pub use self::Pound as POUND;
+#[cfg(stage0)] pub use self::Dollar as DOLLAR;
+#[cfg(stage0)] pub use self::Question as QUESTION;
+#[cfg(stage0)] pub use self::LitByte as LIT_BYTE;
+#[cfg(stage0)] pub use self::LitChar as LIT_CHAR;
+#[cfg(stage0)] pub use self::LitInteger as LIT_INTEGER;
+#[cfg(stage0)] pub use self::LitFloat as LIT_FLOAT;
+#[cfg(stage0)] pub use self::LitStr as LIT_STR;
+#[cfg(stage0)] pub use self::LitStrRaw as LIT_STR_RAW;
+#[cfg(stage0)] pub use self::LitBinary as LIT_BINARY;
+#[cfg(stage0)] pub use self::LitBinaryRaw as LIT_BINARY_RAW;
+#[cfg(stage0)] pub use self::Ident as IDENT;
+#[cfg(stage0)] pub use self::Underscore as UNDERSCORE;
+#[cfg(stage0)] pub use self::Lifetime as LIFETIME;
+#[cfg(stage0)] pub use self::Interpolated as INTERPOLATED;
+#[cfg(stage0)] pub use self::DocComment as DOC_COMMENT;
+#[cfg(stage0)] pub use self::Whitespace as WS;
+#[cfg(stage0)] pub use self::Comment as COMMENT;
+#[cfg(stage0)] pub use self::Shebang as SHEBANG;
+#[cfg(stage0)] pub use self::Eof as EOF;
+
#[allow(non_camel_case_types)]
#[deriving(Clone, Encodable, Decodable, PartialEq, Eq, Hash, Show)]
-pub enum BinOp {
- PLUS,
- MINUS,
- STAR,
- SLASH,
- PERCENT,
- CARET,
- AND,
- OR,
- SHL,
- SHR,
+pub enum BinOpToken {
+ Plus,
+ Minus,
+ Star,
+ Slash,
+ Percent,
+ Caret,
+ And,
+ Or,
+ Shl,
+ Shr,
+}
+
+#[cfg(stage0)]
+#[allow(non_uppercase_statics)]
+pub const ModName: bool = true;
+#[cfg(stage0)]
+#[allow(non_uppercase_statics)]
+pub const Plain: bool = false;
+
+#[deriving(Clone, Encodable, Decodable, PartialEq, Eq, Hash, Show)]
+#[cfg(not(stage0))]
+pub enum IdentStyle {
+ /// `::` follows the identifier with no whitespace in-between.
+ ModName,
+ Plain,
}
#[allow(non_camel_case_types)]
#[deriving(Clone, Encodable, Decodable, PartialEq, Eq, Hash, Show)]
pub enum Token {
/* Expression-operator symbols. */
- EQ,
- LT,
- LE,
- EQEQ,
- NE,
- GE,
- GT,
- ANDAND,
- OROR,
- NOT,
- TILDE,
- BINOP(BinOp),
- BINOPEQ(BinOp),
+ Eq,
+ Lt,
+ Le,
+ EqEq,
+ Ne,
+ Ge,
+ Gt,
+ AndAnd,
+ OrOr,
+ Not,
+ Tilde,
+ BinOp(BinOpToken),
+ BinOpEq(BinOpToken),
/* Structural symbols */
- AT,
- DOT,
- DOTDOT,
- DOTDOTDOT,
- COMMA,
- SEMI,
- COLON,
- MOD_SEP,
- RARROW,
- LARROW,
- FAT_ARROW,
- LPAREN,
- RPAREN,
- LBRACKET,
- RBRACKET,
- LBRACE,
- RBRACE,
- POUND,
- DOLLAR,
- QUESTION,
+ At,
+ Dot,
+ DotDot,
+ DotDotDot,
+ Comma,
+ Semi,
+ Colon,
+ ModSep,
+ RArrow,
+ LArrow,
+ FatArrow,
+ LParen,
+ RParen,
+ LBracket,
+ RBracket,
+ LBrace,
+ RBrace,
+ Pound,
+ Dollar,
+ Question,
/* Literals */
- LIT_BYTE(Name),
- LIT_CHAR(Name),
- LIT_INTEGER(Name),
- LIT_FLOAT(Name),
- LIT_STR(Name),
- LIT_STR_RAW(Name, uint), /* raw str delimited by n hash symbols */
- LIT_BINARY(Name),
- LIT_BINARY_RAW(Name, uint), /* raw binary str delimited by n hash symbols */
+ LitByte(ast::Name),
+ LitChar(ast::Name),
+ LitInteger(ast::Name),
+ LitFloat(ast::Name),
+ LitStr(ast::Name),
+ LitStrRaw(ast::Name, uint), /* raw str delimited by n hash symbols */
+ LitBinary(ast::Name),
+ LitBinaryRaw(ast::Name, uint), /* raw binary str delimited by n hash symbols */
/* Name components */
- /// An identifier contains an "is_mod_name" boolean,
- /// indicating whether :: follows this token with no
- /// whitespace in between.
- IDENT(Ident, bool),
- UNDERSCORE,
- LIFETIME(Ident),
+ #[cfg(stage0)]
+ Ident(ast::Ident, bool),
+ #[cfg(not(stage0))]
+ Ident(ast::Ident, IdentStyle),
+ Underscore,
+ Lifetime(ast::Ident),
/* For interpolation */
- INTERPOLATED(Nonterminal),
- DOC_COMMENT(Name),
+ Interpolated(Nonterminal),
+ DocComment(ast::Name),
// Junk. These carry no data because we don't really care about the data
// they *would* carry, and don't really want to allocate a new ident for
// them. Instead, users could extract that from the associated span.
/// Whitespace
- WS,
+ Whitespace,
/// Comment
- COMMENT,
- SHEBANG(Name),
+ Comment,
+ Shebang(ast::Name),
- EOF,
+ Eof,
+}
+
+impl Token {
+ /// Returns `true` if the token can appear at the start of an expression.
+ pub fn can_begin_expr(&self) -> bool {
+ match *self {
+ LParen => true,
+ LBrace => true,
+ LBracket => true,
+ Ident(_, _) => true,
+ Underscore => true,
+ Tilde => true,
+ LitByte(_) => true,
+ LitChar(_) => true,
+ LitInteger(_) => true,
+ LitFloat(_) => true,
+ LitStr(_) => true,
+ LitStrRaw(_, _) => true,
+ LitBinary(_) => true,
+ LitBinaryRaw(_, _) => true,
+ Pound => true,
+ At => true,
+ Not => true,
+ BinOp(Minus) => true,
+ BinOp(Star) => true,
+ BinOp(And) => true,
+ BinOp(Or) => true, // in lambda syntax
+ OrOr => true, // in lambda syntax
+ ModSep => true,
+ Interpolated(NtExpr(..)) => true,
+ Interpolated(NtIdent(..)) => true,
+ Interpolated(NtBlock(..)) => true,
+ Interpolated(NtPath(..)) => true,
+ _ => false,
+ }
+ }
+
+ /// Returns the matching close delimiter if this is an open delimiter,
+ /// otherwise `None`.
+ pub fn get_close_delimiter(&self) -> Option<Token> {
+ match *self {
+ LParen => Some(RParen),
+ LBrace => Some(RBrace),
+ LBracket => Some(RBracket),
+ _ => None,
+ }
+ }
+
+ /// Returns `true` if the token is any literal
+ pub fn is_lit(&self) -> bool {
+ match *self {
+ LitByte(_) => true,
+ LitChar(_) => true,
+ LitInteger(_) => true,
+ LitFloat(_) => true,
+ LitStr(_) => true,
+ LitStrRaw(_, _) => true,
+ LitBinary(_) => true,
+ LitBinaryRaw(_, _) => true,
+ _ => false,
+ }
+ }
+
+ /// Returns `true` if the token is an identifier.
+ pub fn is_ident(&self) -> bool {
+ match *self {
+ Ident(_, _) => true,
+ _ => false,
+ }
+ }
+
+ /// Returns `true` if the token is an interpolated path.
+ pub fn is_path(&self) -> bool {
+ match *self {
+ Interpolated(NtPath(..)) => true,
+ _ => false,
+ }
+ }
+
+ /// Returns `true` if the token is a path that is not followed by a `::`
+ /// token.
+ #[allow(non_uppercase_statics)] // NOTE(stage0): remove this attribute after the next snapshot
+ pub fn is_plain_ident(&self) -> bool {
+ match *self {
+ Ident(_, Plain) => true,
+ _ => false,
+ }
+ }
+
+ /// Returns `true` if the token is a lifetime.
+ pub fn is_lifetime(&self) -> bool {
+ match *self {
+ Lifetime(..) => true,
+ _ => false,
+ }
+ }
+
+ /// Returns `true` if the token is either the `mut` or `const` keyword.
+ pub fn is_mutability(&self) -> bool {
+ self.is_keyword(keywords::Mut) ||
+ self.is_keyword(keywords::Const)
+ }
+
+ /// Maps a token to its corresponding binary operator.
+ pub fn to_binop(&self) -> Option<ast::BinOp> {
+ match *self {
+ BinOp(Star) => Some(ast::BiMul),
+ BinOp(Slash) => Some(ast::BiDiv),
+ BinOp(Percent) => Some(ast::BiRem),
+ BinOp(Plus) => Some(ast::BiAdd),
+ BinOp(Minus) => Some(ast::BiSub),
+ BinOp(Shl) => Some(ast::BiShl),
+ BinOp(Shr) => Some(ast::BiShr),
+ BinOp(And) => Some(ast::BiBitAnd),
+ BinOp(Caret) => Some(ast::BiBitXor),
+ BinOp(Or) => Some(ast::BiBitOr),
+ Lt => Some(ast::BiLt),
+ Le => Some(ast::BiLe),
+ Ge => Some(ast::BiGe),
+ Gt => Some(ast::BiGt),
+ EqEq => Some(ast::BiEq),
+ Ne => Some(ast::BiNe),
+ AndAnd => Some(ast::BiAnd),
+ OrOr => Some(ast::BiOr),
+ _ => None,
+ }
+ }
+
+ /// Returns `true` if the token is a given keyword, `kw`.
+ #[allow(non_uppercase_statics)] // NOTE(stage0): remove this attribute after the next snapshot
+ pub fn is_keyword(&self, kw: keywords::Keyword) -> bool {
+ match *self {
+ Ident(sid, Plain) => kw.to_name() == sid.name,
+ _ => false,
+ }
+ }
+
+ /// Returns `true` if the token is either a special identifier, or a strict
+ /// or reserved keyword.
+ #[allow(non_uppercase_statics)] // NOTE(stage0): remove this attribute after the next snapshot
+ pub fn is_any_keyword(&self) -> bool {
+ match *self {
+ Ident(sid, Plain) => {
+ let n = sid.name;
+
+ n == SELF_KEYWORD_NAME
+ || n == STATIC_KEYWORD_NAME
+ || n == SUPER_KEYWORD_NAME
+ || STRICT_KEYWORD_START <= n
+ && n <= RESERVED_KEYWORD_FINAL
+ },
+ _ => false
+ }
+ }
+
+ /// Returns `true` if the token may not appear as an identifier.
+ #[allow(non_uppercase_statics)] // NOTE(stage0): remove this attribute after the next snapshot
+ pub fn is_strict_keyword(&self) -> bool {
+ match *self {
+ Ident(sid, Plain) => {
+ let n = sid.name;
+
+ n == SELF_KEYWORD_NAME
+ || n == STATIC_KEYWORD_NAME
+ || n == SUPER_KEYWORD_NAME
+ || STRICT_KEYWORD_START <= n
+ && n <= STRICT_KEYWORD_FINAL
+ },
+ Ident(sid, ModName) => {
+ let n = sid.name;
+
+ n != SELF_KEYWORD_NAME
+ && n != SUPER_KEYWORD_NAME
+ && STRICT_KEYWORD_START <= n
+ && n <= STRICT_KEYWORD_FINAL
+ }
+ _ => false,
+ }
+ }
+
+ /// Returns `true` if the token is a keyword that has been reserved for
+ /// possible future use.
+ #[allow(non_uppercase_statics)] // NOTE(stage0): remove this attribute after the next snapshot
+ pub fn is_reserved_keyword(&self) -> bool {
+ match *self {
+ Ident(sid, Plain) => {
+ let n = sid.name;
+
+ RESERVED_KEYWORD_START <= n
+ && n <= RESERVED_KEYWORD_FINAL
+ },
+ _ => false,
+ }
+ }
+
+ /// Hygienic identifier equality comparison.
+ ///
+ /// See `styntax::ext::mtwt`.
+ pub fn mtwt_eq(&self, other : &Token) -> bool {
+ match (self, other) {
+ (&Ident(id1,_), &Ident(id2,_)) | (&Lifetime(id1), &Lifetime(id2)) =>
+ mtwt::resolve(id1) == mtwt::resolve(id2),
+ _ => *self == *other
+ }
+ }
}
#[deriving(Clone, Encodable, Decodable, PartialEq, Eq, Hash)]
NtPat( P<ast::Pat>),
NtExpr( P<ast::Expr>),
NtTy( P<ast::Ty>),
- /// See IDENT, above, for meaning of bool in NtIdent:
- NtIdent(Box<Ident>, bool),
+ #[cfg(stage0)]
+ NtIdent(Box<ast::Ident>, bool),
+ #[cfg(not(stage0))]
+ NtIdent(Box<ast::Ident>, IdentStyle),
/// Stuff inside brackets for attributes
NtMeta( P<ast::MetaItem>),
NtPath(Box<ast::Path>),
}
}
-pub fn binop_to_string(o: BinOp) -> &'static str {
- match o {
- PLUS => "+",
- MINUS => "-",
- STAR => "*",
- SLASH => "/",
- PERCENT => "%",
- CARET => "^",
- AND => "&",
- OR => "|",
- SHL => "<<",
- SHR => ">>"
- }
-}
-
-pub fn to_string(t: &Token) -> String {
- match *t {
- EQ => "=".into_string(),
- LT => "<".into_string(),
- LE => "<=".into_string(),
- EQEQ => "==".into_string(),
- NE => "!=".into_string(),
- GE => ">=".into_string(),
- GT => ">".into_string(),
- NOT => "!".into_string(),
- TILDE => "~".into_string(),
- OROR => "||".into_string(),
- ANDAND => "&&".into_string(),
- BINOP(op) => binop_to_string(op).into_string(),
- BINOPEQ(op) => {
- let mut s = binop_to_string(op).into_string();
- s.push_str("=");
- s
- }
-
- /* Structural symbols */
- AT => "@".into_string(),
- DOT => ".".into_string(),
- DOTDOT => "..".into_string(),
- DOTDOTDOT => "...".into_string(),
- COMMA => ",".into_string(),
- SEMI => ";".into_string(),
- COLON => ":".into_string(),
- MOD_SEP => "::".into_string(),
- RARROW => "->".into_string(),
- LARROW => "<-".into_string(),
- FAT_ARROW => "=>".into_string(),
- LPAREN => "(".into_string(),
- RPAREN => ")".into_string(),
- LBRACKET => "[".into_string(),
- RBRACKET => "]".into_string(),
- LBRACE => "{".into_string(),
- RBRACE => "}".into_string(),
- POUND => "#".into_string(),
- DOLLAR => "$".into_string(),
- QUESTION => "?".into_string(),
-
- /* Literals */
- LIT_BYTE(b) => {
- format!("b'{}'", b.as_str())
- }
- LIT_CHAR(c) => {
- format!("'{}'", c.as_str())
- }
- LIT_INTEGER(c) | LIT_FLOAT(c) => {
- c.as_str().into_string()
- }
-
- LIT_STR(s) => {
- format!("\"{}\"", s.as_str())
- }
- LIT_STR_RAW(s, n) => {
- format!("r{delim}\"{string}\"{delim}",
- delim="#".repeat(n), string=s.as_str())
- }
- LIT_BINARY(v) => {
- format!("b\"{}\"", v.as_str())
- }
- LIT_BINARY_RAW(s, n) => {
- format!("br{delim}\"{string}\"{delim}",
- delim="#".repeat(n), string=s.as_str())
- }
-
- /* Name components */
- IDENT(s, _) => get_ident(s).get().into_string(),
- LIFETIME(s) => {
- format!("{}", get_ident(s))
- }
- UNDERSCORE => "_".into_string(),
-
- /* Other */
- DOC_COMMENT(s) => s.as_str().into_string(),
- EOF => "<eof>".into_string(),
- WS => " ".into_string(),
- COMMENT => "/* */".into_string(),
- SHEBANG(s) => format!("/* shebang: {}*/", s.as_str()),
-
- INTERPOLATED(ref nt) => {
- match nt {
- &NtExpr(ref e) => ::print::pprust::expr_to_string(&**e),
- &NtMeta(ref e) => ::print::pprust::meta_item_to_string(&**e),
- &NtTy(ref e) => ::print::pprust::ty_to_string(&**e),
- &NtPath(ref e) => ::print::pprust::path_to_string(&**e),
- _ => {
- let mut s = "an interpolated ".into_string();
- match *nt {
- NtItem(..) => s.push_str("item"),
- NtBlock(..) => s.push_str("block"),
- NtStmt(..) => s.push_str("statement"),
- NtPat(..) => s.push_str("pattern"),
- NtMeta(..) => fail!("should have been handled"),
- NtExpr(..) => fail!("should have been handled"),
- NtTy(..) => fail!("should have been handled"),
- NtIdent(..) => s.push_str("identifier"),
- NtPath(..) => fail!("should have been handled"),
- NtTT(..) => s.push_str("tt"),
- NtMatchers(..) => s.push_str("matcher sequence")
- };
- s
- }
- }
- }
- }
-}
-
-pub fn can_begin_expr(t: &Token) -> bool {
- match *t {
- LPAREN => true,
- LBRACE => true,
- LBRACKET => true,
- IDENT(_, _) => true,
- UNDERSCORE => true,
- TILDE => true,
- LIT_BYTE(_) => true,
- LIT_CHAR(_) => true,
- LIT_INTEGER(_) => true,
- LIT_FLOAT(_) => true,
- LIT_STR(_) => true,
- LIT_STR_RAW(_, _) => true,
- LIT_BINARY(_) => true,
- LIT_BINARY_RAW(_, _) => true,
- POUND => true,
- AT => true,
- NOT => true,
- BINOP(MINUS) => true,
- BINOP(STAR) => true,
- BINOP(AND) => true,
- BINOP(OR) => true, // in lambda syntax
- OROR => true, // in lambda syntax
- MOD_SEP => true,
- INTERPOLATED(NtExpr(..))
- | INTERPOLATED(NtIdent(..))
- | INTERPOLATED(NtBlock(..))
- | INTERPOLATED(NtPath(..)) => true,
- _ => false
- }
-}
-
-/// Returns the matching close delimiter if this is an open delimiter,
-/// otherwise `None`.
-pub fn close_delimiter_for(t: &Token) -> Option<Token> {
- match *t {
- LPAREN => Some(RPAREN),
- LBRACE => Some(RBRACE),
- LBRACKET => Some(RBRACKET),
- _ => None
- }
-}
-
-pub fn is_lit(t: &Token) -> bool {
- match *t {
- LIT_BYTE(_) => true,
- LIT_CHAR(_) => true,
- LIT_INTEGER(_) => true,
- LIT_FLOAT(_) => true,
- LIT_STR(_) => true,
- LIT_STR_RAW(_, _) => true,
- LIT_BINARY(_) => true,
- LIT_BINARY_RAW(_, _) => true,
- _ => false
- }
-}
-
-pub fn is_ident(t: &Token) -> bool {
- match *t { IDENT(_, _) => true, _ => false }
-}
-
-pub fn is_ident_or_path(t: &Token) -> bool {
- match *t {
- IDENT(_, _) | INTERPOLATED(NtPath(..)) => true,
- _ => false
- }
-}
-
-pub fn is_plain_ident(t: &Token) -> bool {
- match *t { IDENT(_, false) => true, _ => false }
-}
-
// Get the first "argument"
macro_rules! first {
( $first:expr, $( $remainder:expr, )* ) => ( $first )
$( ($rk_name:expr, $rk_variant:ident, $rk_str:expr); )*
}
) => {
- static STRICT_KEYWORD_START: Name = first!($( Name($sk_name), )*);
- static STRICT_KEYWORD_FINAL: Name = last!($( Name($sk_name), )*);
- static RESERVED_KEYWORD_START: Name = first!($( Name($rk_name), )*);
- static RESERVED_KEYWORD_FINAL: Name = last!($( Name($rk_name), )*);
+ static STRICT_KEYWORD_START: ast::Name = first!($( ast::Name($sk_name), )*);
+ static STRICT_KEYWORD_FINAL: ast::Name = last!($( ast::Name($sk_name), )*);
+ static RESERVED_KEYWORD_START: ast::Name = first!($( ast::Name($rk_name), )*);
+ static RESERVED_KEYWORD_FINAL: ast::Name = last!($( ast::Name($rk_name), )*);
pub mod special_idents {
- use ast::{Ident, Name};
+ use ast;
$(
#[allow(non_uppercase_statics)]
- pub const $si_static: Ident = Ident { name: Name($si_name), ctxt: 0 };
+ pub const $si_static: ast::Ident = ast::Ident {
+ name: ast::Name($si_name),
+ ctxt: 0,
+ };
)*
}
pub mod special_names {
- use ast::Name;
- $( #[allow(non_uppercase_statics)] pub const $si_static: Name = Name($si_name); )*
+ use ast;
+ $(
+ #[allow(non_uppercase_statics)]
+ pub const $si_static: ast::Name = ast::Name($si_name);
+ )*
}
/**
* the language and may not appear as identifiers.
*/
pub mod keywords {
- use ast::Name;
+ use ast;
pub enum Keyword {
$( $sk_variant, )*
}
impl Keyword {
- pub fn to_name(&self) -> Name {
+ pub fn to_name(&self) -> ast::Name {
match *self {
- $( $sk_variant => Name($sk_name), )*
- $( $rk_variant => Name($rk_name), )*
+ $( $sk_variant => ast::Name($sk_name), )*
+ $( $rk_variant => ast::Name($rk_name), )*
}
}
}
}}
// If the special idents get renumbered, remember to modify these two as appropriate
-pub const SELF_KEYWORD_NAME: Name = Name(SELF_KEYWORD_NAME_NUM);
-const STATIC_KEYWORD_NAME: Name = Name(STATIC_KEYWORD_NAME_NUM);
-const SUPER_KEYWORD_NAME: Name = Name(SUPER_KEYWORD_NAME_NUM);
+pub const SELF_KEYWORD_NAME: ast::Name = ast::Name(SELF_KEYWORD_NAME_NUM);
+const STATIC_KEYWORD_NAME: ast::Name = ast::Name(STATIC_KEYWORD_NAME_NUM);
+const SUPER_KEYWORD_NAME: ast::Name = ast::Name(SUPER_KEYWORD_NAME_NUM);
pub const SELF_KEYWORD_NAME_NUM: u32 = 1;
const STATIC_KEYWORD_NAME_NUM: u32 = 2;
}
}
-/**
- * Maps a token to a record specifying the corresponding binary
- * operator
- */
-pub fn token_to_binop(tok: &Token) -> Option<ast::BinOp> {
- match *tok {
- BINOP(STAR) => Some(ast::BiMul),
- BINOP(SLASH) => Some(ast::BiDiv),
- BINOP(PERCENT) => Some(ast::BiRem),
- BINOP(PLUS) => Some(ast::BiAdd),
- BINOP(MINUS) => Some(ast::BiSub),
- BINOP(SHL) => Some(ast::BiShl),
- BINOP(SHR) => Some(ast::BiShr),
- BINOP(AND) => Some(ast::BiBitAnd),
- BINOP(CARET) => Some(ast::BiBitXor),
- BINOP(OR) => Some(ast::BiBitOr),
- LT => Some(ast::BiLt),
- LE => Some(ast::BiLe),
- GE => Some(ast::BiGe),
- GT => Some(ast::BiGt),
- EQEQ => Some(ast::BiEq),
- NE => Some(ast::BiNe),
- ANDAND => Some(ast::BiAnd),
- OROR => Some(ast::BiOr),
- _ => None
- }
-}
-
// looks like we can get rid of this completely...
pub type IdentInterner = StrInterner;
/// Returns the string contents of a name, using the task-local interner.
#[inline]
-pub fn get_name(name: Name) -> InternedString {
+pub fn get_name(name: ast::Name) -> InternedString {
let interner = get_ident_interner();
InternedString::new_from_rc_str(interner.get(name))
}
/// Returns the string contents of an identifier, using the task-local
/// interner.
#[inline]
-pub fn get_ident(ident: Ident) -> InternedString {
+pub fn get_ident(ident: ast::Ident) -> InternedString {
get_name(ident.name)
}
/// Maps a string to its interned representation.
#[inline]
-pub fn intern(s: &str) -> Name {
+pub fn intern(s: &str) -> ast::Name {
get_ident_interner().intern(s)
}
/// gensym's a new uint, using the current interner.
#[inline]
-pub fn gensym(s: &str) -> Name {
+pub fn gensym(s: &str) -> ast::Name {
get_ident_interner().gensym(s)
}
/// Maps a string to an identifier with an empty syntax context.
#[inline]
-pub fn str_to_ident(s: &str) -> Ident {
- Ident::new(intern(s))
+pub fn str_to_ident(s: &str) -> ast::Ident {
+ ast::Ident::new(intern(s))
}
/// Maps a string to a gensym'ed identifier.
#[inline]
-pub fn gensym_ident(s: &str) -> Ident {
- Ident::new(gensym(s))
+pub fn gensym_ident(s: &str) -> ast::Ident {
+ ast::Ident::new(gensym(s))
}
// create a fresh name that maps to the same string as the old one.
// note that this guarantees that str_ptr_eq(ident_to_string(src),interner_get(fresh_name(src)));
// that is, that the new name and the old one are connected to ptr_eq strings.
-pub fn fresh_name(src: &Ident) -> Name {
+pub fn fresh_name(src: &ast::Ident) -> ast::Name {
let interner = get_ident_interner();
interner.gensym_copy(src.name)
// following: debug version. Could work in final except that it's incompatible with
}
// create a fresh mark.
-pub fn fresh_mark() -> Mrk {
+pub fn fresh_mark() -> ast::Mrk {
gensym("mark").uint() as u32
}
-// See the macro above about the types of keywords
-
-pub fn is_keyword(kw: keywords::Keyword, tok: &Token) -> bool {
- match *tok {
- token::IDENT(sid, false) => { kw.to_name() == sid.name }
- _ => { false }
- }
-}
-
-pub fn is_any_keyword(tok: &Token) -> bool {
- match *tok {
- token::IDENT(sid, false) => {
- let n = sid.name;
-
- n == SELF_KEYWORD_NAME
- || n == STATIC_KEYWORD_NAME
- || n == SUPER_KEYWORD_NAME
- || STRICT_KEYWORD_START <= n
- && n <= RESERVED_KEYWORD_FINAL
- },
- _ => false
- }
-}
-
-pub fn is_strict_keyword(tok: &Token) -> bool {
- match *tok {
- token::IDENT(sid, false) => {
- let n = sid.name;
-
- n == SELF_KEYWORD_NAME
- || n == STATIC_KEYWORD_NAME
- || n == SUPER_KEYWORD_NAME
- || STRICT_KEYWORD_START <= n
- && n <= STRICT_KEYWORD_FINAL
- },
- token::IDENT(sid, true) => {
- let n = sid.name;
-
- n != SELF_KEYWORD_NAME
- && n != SUPER_KEYWORD_NAME
- && STRICT_KEYWORD_START <= n
- && n <= STRICT_KEYWORD_FINAL
- }
- _ => false,
- }
-}
-
-pub fn is_reserved_keyword(tok: &Token) -> bool {
- match *tok {
- token::IDENT(sid, false) => {
- let n = sid.name;
-
- RESERVED_KEYWORD_START <= n
- && n <= RESERVED_KEYWORD_FINAL
- },
- _ => false,
- }
-}
-
-pub fn mtwt_token_eq(t1 : &Token, t2 : &Token) -> bool {
- match (t1,t2) {
- (&IDENT(id1,_),&IDENT(id2,_)) | (&LIFETIME(id1),&LIFETIME(id2)) =>
- mtwt::resolve(id1) == mtwt::resolve(id2),
- _ => *t1 == *t2
- }
-}
-
-
#[cfg(test)]
mod test {
use super::*;
}
#[test] fn mtwt_token_eq_test() {
- assert!(mtwt_token_eq(>,>));
+ assert!(Gt.mtwt_eq(&Gt));
let a = str_to_ident("bac");
let a1 = mark_ident(a,92);
- assert!(mtwt_token_eq(&IDENT(a,true),&IDENT(a1,false)));
+ assert!(Ident(a, ModName).mtwt_eq(&Ident(a1, Plain)));
}
}
}
Eof => {
// Eof should never get here.
- fail!();
+ panic!();
}
}
}
use codemap::{CodeMap, BytePos};
use codemap;
use diagnostic;
+use parse::token::{BinOpToken, Token};
use parse::token;
use parse::lexer::comments;
use parse;
}
}
+pub fn binop_to_string(op: BinOpToken) -> &'static str {
+ match op {
+ token::Plus => "+",
+ token::Minus => "-",
+ token::Star => "*",
+ token::Slash => "/",
+ token::Percent => "%",
+ token::Caret => "^",
+ token::And => "&",
+ token::Or => "|",
+ token::Shl => "<<",
+ token::Shr => ">>",
+ }
+}
+
+pub fn token_to_string(tok: &Token) -> String {
+ match *tok {
+ token::Eq => "=".into_string(),
+ token::Lt => "<".into_string(),
+ token::Le => "<=".into_string(),
+ token::EqEq => "==".into_string(),
+ token::Ne => "!=".into_string(),
+ token::Ge => ">=".into_string(),
+ token::Gt => ">".into_string(),
+ token::Not => "!".into_string(),
+ token::Tilde => "~".into_string(),
+ token::OrOr => "||".into_string(),
+ token::AndAnd => "&&".into_string(),
+ token::BinOp(op) => binop_to_string(op).into_string(),
+ token::BinOpEq(op) => format!("{}=", binop_to_string(op)),
+
+ /* Structural symbols */
+ token::At => "@".into_string(),
+ token::Dot => ".".into_string(),
+ token::DotDot => "..".into_string(),
+ token::DotDotDot => "...".into_string(),
+ token::Comma => ",".into_string(),
+ token::Semi => ";".into_string(),
+ token::Colon => ":".into_string(),
+ token::ModSep => "::".into_string(),
+ token::RArrow => "->".into_string(),
+ token::LArrow => "<-".into_string(),
+ token::FatArrow => "=>".into_string(),
+ token::LParen => "(".into_string(),
+ token::RParen => ")".into_string(),
+ token::LBracket => "[".into_string(),
+ token::RBracket => "]".into_string(),
+ token::LBrace => "{".into_string(),
+ token::RBrace => "}".into_string(),
+ token::Pound => "#".into_string(),
+ token::Dollar => "$".into_string(),
+ token::Question => "?".into_string(),
+
+ /* Literals */
+ token::LitByte(b) => format!("b'{}'", b.as_str()),
+ token::LitChar(c) => format!("'{}'", c.as_str()),
+ token::LitFloat(c) => c.as_str().into_string(),
+ token::LitInteger(c) => c.as_str().into_string(),
+ token::LitStr(s) => format!("\"{}\"", s.as_str()),
+ token::LitStrRaw(s, n) => format!("r{delim}\"{string}\"{delim}",
+ delim="#".repeat(n),
+ string=s.as_str()),
+ token::LitBinary(v) => format!("b\"{}\"", v.as_str()),
+ token::LitBinaryRaw(s, n) => format!("br{delim}\"{string}\"{delim}",
+ delim="#".repeat(n),
+ string=s.as_str()),
+
+ /* Name components */
+ token::Ident(s, _) => token::get_ident(s).get().into_string(),
+ token::Lifetime(s) => format!("{}", token::get_ident(s)),
+ token::Underscore => "_".into_string(),
+
+ /* Other */
+ token::DocComment(s) => s.as_str().into_string(),
+ token::Eof => "<eof>".into_string(),
+ token::Whitespace => " ".into_string(),
+ token::Comment => "/* */".into_string(),
+ token::Shebang(s) => format!("/* shebang: {}*/", s.as_str()),
+
+ token::Interpolated(ref nt) => match *nt {
+ token::NtExpr(ref e) => expr_to_string(&**e),
+ token::NtMeta(ref e) => meta_item_to_string(&**e),
+ token::NtTy(ref e) => ty_to_string(&**e),
+ token::NtPath(ref e) => path_to_string(&**e),
+ token::NtItem(..) => "an interpolated item".into_string(),
+ token::NtBlock(..) => "an interpolated block".into_string(),
+ token::NtStmt(..) => "an interpolated statement".into_string(),
+ token::NtPat(..) => "an interpolated pattern".into_string(),
+ token::NtIdent(..) => "an interpolated identifier".into_string(),
+ token::NtTT(..) => "an interpolated tt".into_string(),
+ token::NtMatchers(..) => "an interpolated matcher sequence".into_string(),
+ }
+ }
+}
+
// FIXME (Issue #16472): the thing_to_string_impls macro should go away
// after we revise the syntax::ext::quote::ToToken impls to go directly
// to token-trees instead of thing -> string -> token-trees.
$to_string(|s| s.print_item(i))
}
+pub fn view_item_to_string(i: &ast::ViewItem) -> String {
+ $to_string(|s| s.print_view_item(i))
+}
+
pub fn generics_to_string(generics: &ast::Generics) -> String {
$to_string(|s| s.print_generics(generics))
}
Inconsistent, struct_def.fields.as_slice(),
|s, field| {
match field.node.kind {
- ast::NamedField(..) => fail!("unexpected named field"),
+ ast::NamedField(..) => panic!("unexpected named field"),
ast::UnnamedField(vis) => {
try!(s.print_visibility(vis));
try!(s.maybe_print_comment(field.span.lo));
for field in struct_def.fields.iter() {
match field.node.kind {
- ast::UnnamedField(..) => fail!("unexpected unnamed field"),
+ ast::UnnamedField(..) => panic!("unexpected unnamed field"),
ast::NamedField(ident, visibility) => {
try!(self.hardbreak_if_not_bol());
try!(self.maybe_print_comment(field.span.lo));
/// expression arguments as expressions). It can be done! I think.
pub fn print_tt(&mut self, tt: &ast::TokenTree) -> IoResult<()> {
match *tt {
- ast::TTDelim(ref tts) => self.print_tts(tts.as_slice()),
- ast::TTTok(_, ref tk) => {
- try!(word(&mut self.s, parse::token::to_string(tk).as_slice()));
+ ast::TtDelimited(_, ref delimed) => {
+ let (ref open, ref tts, ref close) = **delimed;
+ try!(word(&mut self.s, token_to_string(&open.token).as_slice()));
+ try!(space(&mut self.s));
+ try!(self.print_tts(tts.as_slice()));
+ try!(space(&mut self.s));
+ word(&mut self.s, token_to_string(&close.token).as_slice())
+ },
+ ast::TtToken(_, ref tk) => {
+ try!(word(&mut self.s, token_to_string(tk).as_slice()));
match *tk {
- parse::token::DOC_COMMENT(..) => {
+ parse::token::DocComment(..) => {
hardbreak(&mut self.s)
}
_ => Ok(())
}
}
- ast::TTSeq(_, ref tts, ref sep, zerok) => {
+ ast::TtSequence(_, ref tts, ref separator, kleene_op) => {
try!(word(&mut self.s, "$("));
for tt_elt in (*tts).iter() {
try!(self.print_tt(tt_elt));
}
try!(word(&mut self.s, ")"));
- match *sep {
+ match *separator {
Some(ref tk) => {
- try!(word(&mut self.s,
- parse::token::to_string(tk).as_slice()));
+ try!(word(&mut self.s, token_to_string(tk).as_slice()));
}
- None => ()
+ None => {},
+ }
+ match kleene_op {
+ ast::ZeroOrMore => word(&mut self.s, "*"),
+ ast::OneOrMore => word(&mut self.s, "+"),
}
- word(&mut self.s, if zerok { "*" } else { "+" })
}
- ast::TTNonterminal(_, name) => {
+ ast::TtNonterminal(_, name) => {
try!(word(&mut self.s, "$"));
self.print_ident(name)
}
}
// BLEAH, constraints would be great here
_ => {
- fail!("print_if saw if with weird alternative");
+ panic!("print_if saw if with weird alternative");
}
}
}
Consistent, fields.as_slice(),
|s, f| {
try!(s.cbox(indent_unit));
- try!(s.print_ident(f.node.ident));
- try!(s.word_nbsp(":"));
+ if !f.node.is_shorthand {
+ try!(s.print_ident(f.node.ident));
+ try!(s.word_nbsp(":"));
+ }
try!(s.print_pat(&*f.node.pat));
s.end()
},
match self.repr {
One(ref v) if idx == 0 => v,
Many(ref vs) => &vs[idx],
- _ => fail!("out of bounds access")
+ _ => panic!("out of bounds access")
}
}
if v.len() == 1 {
v.into_iter().next().unwrap()
} else {
- fail!(err)
+ panic!(err)
}
}
- _ => fail!(err)
+ _ => panic!(err)
}
}
walk_explicit_self(self, es)
}
fn visit_mac(&mut self, _macro: &'v Mac) {
- fail!("visit_mac disabled by default");
+ panic!("visit_mac disabled by default");
// NB: see note about macros above.
// if you really want a visitor that
// works on macros, use this
/// Return a Terminal wrapping stdout, or None if a terminal couldn't be
/// opened.
pub fn stdout() -> Option<Box<Terminal<WriterWrapper> + Send>> {
- let ti: Option<TerminfoTerminal<WriterWrapper>>
- = Terminal::new(WriterWrapper {
- wrapped: box std::io::stdout() as Box<Writer + Send>,
- });
- ti.map(|t| box t as Box<Terminal<WriterWrapper> + Send>)
+ TerminfoTerminal::new(WriterWrapper {
+ wrapped: box std::io::stdout() as Box<Writer + Send>,
+ })
}
#[cfg(windows)]
/// Return a Terminal wrapping stdout, or None if a terminal couldn't be
/// opened.
pub fn stdout() -> Option<Box<Terminal<WriterWrapper> + Send>> {
- let ti: Option<TerminfoTerminal<WriterWrapper>>
- = Terminal::new(WriterWrapper {
- wrapped: box std::io::stdout() as Box<Writer + Send>,
- });
+ let ti = TerminfoTerminal::new(WriterWrapper {
+ wrapped: box std::io::stdout() as Box<Writer + Send>,
+ });
match ti {
- Some(t) => Some(box t as Box<Terminal<WriterWrapper> + Send>),
+ Some(t) => Some(t),
None => {
- let wc: Option<WinConsole<WriterWrapper>>
- = Terminal::new(WriterWrapper {
- wrapped: box std::io::stdout() as Box<Writer + Send>,
- });
- wc.map(|w| box w as Box<Terminal<WriterWrapper> + Send>)
+ WinConsole::new(WriterWrapper {
+ wrapped: box std::io::stdout() as Box<Writer + Send>,
+ })
}
}
}
/// Return a Terminal wrapping stderr, or None if a terminal couldn't be
/// opened.
pub fn stderr() -> Option<Box<Terminal<WriterWrapper> + Send> + Send> {
- let ti: Option<TerminfoTerminal<WriterWrapper>>
- = Terminal::new(WriterWrapper {
- wrapped: box std::io::stderr() as Box<Writer + Send>,
- });
- ti.map(|t| box t as Box<Terminal<WriterWrapper> + Send>)
+ TerminfoTerminal::new(WriterWrapper {
+ wrapped: box std::io::stderr() as Box<Writer + Send>,
+ })
}
#[cfg(windows)]
/// Return a Terminal wrapping stderr, or None if a terminal couldn't be
/// opened.
pub fn stderr() -> Option<Box<Terminal<WriterWrapper> + Send> + Send> {
- let ti: Option<TerminfoTerminal<WriterWrapper>>
- = Terminal::new(WriterWrapper {
- wrapped: box std::io::stderr() as Box<Writer + Send>,
- });
+ let ti = TerminfoTerminal::new(WriterWrapper {
+ wrapped: box std::io::stderr() as Box<Writer + Send>,
+ });
match ti {
- Some(t) => Some(box t as Box<Terminal<WriterWrapper> + Send>),
+ Some(t) => Some(t),
None => {
- let wc: Option<WinConsole<WriterWrapper>>
- = Terminal::new(WriterWrapper {
- wrapped: box std::io::stderr() as Box<Writer + Send>,
- });
- wc.map(|w| box w as Box<Terminal<WriterWrapper> + Send>)
+ WinConsole::new(WriterWrapper {
+ wrapped: box std::io::stderr() as Box<Writer + Send>,
+ })
}
}
}
/// A terminal with similar capabilities to an ANSI Terminal
/// (foreground/background colors etc).
pub trait Terminal<T: Writer>: Writer {
- /// Returns `None` whenever the terminal cannot be created for some
- /// reason.
- fn new(out: T) -> Option<Self>;
-
/// Sets the foreground color to the given color.
///
/// If the color is a bright color, but the terminal only supports 8 colors,
/// Returns `Ok()`.
fn reset(&mut self) -> IoResult<()>;
- /// Returns the contained stream, destroying the `Terminal`
- fn unwrap(self) -> T;
-
/// Gets an immutable reference to the stream inside
fn get_ref<'a>(&'a self) -> &'a T;
/// Gets a mutable reference to the stream inside
fn get_mut<'a>(&'a mut self) -> &'a mut T;
}
+
+/// A terminal which can be unwrapped.
+pub trait UnwrappableTerminal<T: Writer>: Terminal<T> {
+ /// Returns the contained stream, destroying the `Terminal`
+ fn unwrap(self) -> T;
+}
use attr;
use color;
use Terminal;
+use UnwrappableTerminal;
use self::searcher::open;
use self::parser::compiled::{parse, msys_terminfo};
use self::parm::{expand, Number, Variables};
ti: Box<TermInfo>
}
-impl<T: Writer> Terminal<T> for TerminfoTerminal<T> {
- fn new(out: T) -> Option<TerminfoTerminal<T>> {
- let term = match os::getenv("TERM") {
- Some(t) => t,
- None => {
- debug!("TERM environment variable not defined");
- return None;
- }
- };
-
- let entry = open(term.as_slice());
- if entry.is_err() {
- if os::getenv("MSYSCON").map_or(false, |s| {
- "mintty.exe" == s.as_slice()
- }) {
- // msys terminal
- return Some(TerminfoTerminal {out: out, ti: msys_terminfo(), num_colors: 8});
- }
- debug!("error finding terminfo entry: {}", entry.err().unwrap());
- return None;
- }
-
- let mut file = entry.unwrap();
- let ti = parse(&mut file, false);
- if ti.is_err() {
- debug!("error parsing terminfo entry: {}", ti.unwrap_err());
- return None;
- }
-
- let inf = ti.unwrap();
- let nc = if inf.strings.find_equiv(&("setaf")).is_some()
- && inf.strings.find_equiv(&("setab")).is_some() {
- inf.numbers.find_equiv(&("colors")).map_or(0, |&n| n)
- } else { 0 };
-
- return Some(TerminfoTerminal {out: out, ti: inf, num_colors: nc});
- }
-
+impl<T: Writer+Send> Terminal<T> for TerminfoTerminal<T> {
fn fg(&mut self, color: color::Color) -> IoResult<bool> {
let color = self.dim_if_necessary(color);
if self.num_colors > color {
Ok(())
}
- fn unwrap(self) -> T { self.out }
-
fn get_ref<'a>(&'a self) -> &'a T { &self.out }
fn get_mut<'a>(&'a mut self) -> &'a mut T { &mut self.out }
}
-impl<T: Writer> TerminfoTerminal<T> {
+impl<T: Writer+Send> UnwrappableTerminal<T> for TerminfoTerminal<T> {
+ fn unwrap(self) -> T { self.out }
+}
+
+impl<T: Writer+Send> TerminfoTerminal<T> {
+ /// Returns `None` whenever the terminal cannot be created for some
+ /// reason.
+ pub fn new(out: T) -> Option<Box<Terminal<T>+Send+'static>> {
+ let term = match os::getenv("TERM") {
+ Some(t) => t,
+ None => {
+ debug!("TERM environment variable not defined");
+ return None;
+ }
+ };
+
+ let entry = open(term.as_slice());
+ if entry.is_err() {
+ if os::getenv("MSYSCON").map_or(false, |s| {
+ "mintty.exe" == s.as_slice()
+ }) {
+ // msys terminal
+ return Some(box TerminfoTerminal {out: out,
+ ti: msys_terminfo(),
+ num_colors: 8} as Box<Terminal<T>+Send>);
+ }
+ debug!("error finding terminfo entry: {}", entry.err().unwrap());
+ return None;
+ }
+
+ let mut file = entry.unwrap();
+ let ti = parse(&mut file, false);
+ if ti.is_err() {
+ debug!("error parsing terminfo entry: {}", ti.unwrap_err());
+ return None;
+ }
+
+ let inf = ti.unwrap();
+ let nc = if inf.strings.find_equiv(&("setaf")).is_some()
+ && inf.strings.find_equiv(&("setab")).is_some() {
+ inf.numbers.find_equiv(&("colors")).map_or(0, |&n| n)
+ } else { 0 };
+
+ return Some(box TerminfoTerminal {out: out,
+ ti: inf,
+ num_colors: nc} as Box<Terminal<T>+Send>);
+ }
+
fn dim_if_necessary(&self, color: color::Color) -> color::Color {
if color >= self.num_colors && color >= 8 && color < 16 {
color-8
'x' => FormatHex,
'X' => FormatHEX,
's' => FormatString,
- _ => fail!("bad FormatOp char")
+ _ => panic!("bad FormatOp char")
}
}
fn to_char(self) -> char {
use attr;
use color;
-use Terminal;
+use {Terminal,UnwrappableTerminal};
/// A Terminal implementation which uses the Win32 Console API.
pub struct WinConsole<T> {
}
fn bits_to_color(bits: u16) -> color::Color {
- let color = match bits & 0x7 {
+ let bits = bits & 0x7;
+ let color = match bits {
0 => color::BLACK,
0x1 => color::BLUE,
0x2 => color::GREEN,
}
}
-impl<T: Writer> WinConsole<T> {
+impl<T: Writer+Send> WinConsole<T> {
fn apply(&mut self) {
let _unused = self.buf.flush();
let mut accum: libc::WORD = 0;
SetConsoleTextAttribute(out, accum);
}
}
-}
-
-impl<T: Writer> Writer for WinConsole<T> {
- fn write(&mut self, buf: &[u8]) -> IoResult<()> {
- self.buf.write(buf)
- }
-
- fn flush(&mut self) -> IoResult<()> {
- self.buf.flush()
- }
-}
-impl<T: Writer> Terminal<T> for WinConsole<T> {
- fn new(out: T) -> Option<WinConsole<T>> {
+ /// Returns `None` whenever the terminal cannot be created for some
+ /// reason.
+ pub fn new(out: T) -> Option<Box<Terminal<T>+Send+'static>> {
let fg;
let bg;
unsafe {
bg = color::BLACK;
}
}
- Some(WinConsole { buf: out,
- def_foreground: fg, def_background: bg,
- foreground: fg, background: bg } )
+ Some(box WinConsole { buf: out,
+ def_foreground: fg, def_background: bg,
+ foreground: fg, background: bg } as Box<Terminal<T>+Send>)
}
+}
+impl<T: Writer> Writer for WinConsole<T> {
+ fn write(&mut self, buf: &[u8]) -> IoResult<()> {
+ self.buf.write(buf)
+ }
+
+ fn flush(&mut self) -> IoResult<()> {
+ self.buf.flush()
+ }
+}
+
+impl<T: Writer+Send> Terminal<T> for WinConsole<T> {
fn fg(&mut self, color: color::Color) -> IoResult<bool> {
self.foreground = color;
self.apply();
Ok(())
}
- fn unwrap(self) -> T { self.buf }
-
fn get_ref<'a>(&'a self) -> &'a T { &self.buf }
fn get_mut<'a>(&'a mut self) -> &'a mut T { &mut self.buf }
}
+
+impl<T: Writer+Send> UnwrappableTerminal<T> for WinConsole<T> {
+ fn unwrap(self) -> T { self.buf }
+}
}
// A function that runs a test. If the function returns successfully,
-// the test succeeds; if the function fails then the test fails. We
+// the test succeeds; if the function panics then the test fails. We
// may need to come up with a more clever definition of test in order
// to support isolation of tests into tasks.
pub enum TestFn {
let opts =
match parse_opts(args) {
Some(Ok(o)) => o,
- Some(Err(msg)) => fail!("{}", msg),
+ Some(Err(msg)) => panic!("{}", msg),
None => return
};
match run_tests_console(&opts, tests) {
Ok(true) => {}
- Ok(false) => fail!("Some tests failed"),
- Err(e) => fail!("io error when running tests: {}", e),
+ Ok(false) => panic!("Some tests failed"),
+ Err(e) => panic!("io error when running tests: {}", e),
}
}
// A variant optimized for invocation with a static test vector.
-// This will fail (intentionally) when fed any dynamic tests, because
+// This will panic (intentionally) when fed any dynamic tests, because
// it is copying the static values out into a dynamic vector and cannot
// copy dynamic values. It is doing this because from this point on
// a ~[TestDescAndFn] is used in order to effect ownership-transfer
match t.testfn {
StaticTestFn(f) => TestDescAndFn { testfn: StaticTestFn(f), desc: t.desc.clone() },
StaticBenchFn(f) => TestDescAndFn { testfn: StaticBenchFn(f), desc: t.desc.clone() },
- _ => fail!("non-static tests passed to test::test_main_static")
+ _ => panic!("non-static tests passed to test::test_main_static")
}
}).collect();
test_main(args, owned_tests)
#[bench] - Indicates a function is a benchmark to be run. This
function takes one argument (test::Bencher).
#[should_fail] - This function (also labeled with #[test]) will only pass if
- the code causes a failure (an assertion failure or fail!)
+ the code causes a failure (an assertion failure or panic!)
#[ignore] - When applied to a function which is already attributed as a
test, then the test runner will ignore these tests during
normal test runs. Running with --ignored will run these
it.next()) {
(Some(a), Some(b), None) => {
if a <= 0 || a > b {
- fail!("tried to run shard {a}.{b}, but {a} is out of bounds \
+ panic!("tried to run shard {a}.{b}, but {a} is out of bounds \
(should be between 1 and {b}", a=a, b=b)
}
Some((a, b))
let opt_n: Option<uint> = FromStr::from_str(s.as_slice());
match opt_n {
Some(n) if n > 0 => n,
- _ => fail!("RUST_TEST_TASKS is `{}`, should be a positive integer.", s)
+ _ => panic!("RUST_TEST_TASKS is `{}`, should be a positive integer.", s)
}
}
None => {
///
/// # Failure
///
- /// This function will fail if the path does not exist or the path does not
+ /// This function will panic if the path does not exist or the path does not
/// contain a valid metric map.
pub fn load(p: &Path) -> MetricMap {
assert!(p.exists());
let mut decoder = json::Decoder::new(value);
MetricMap(match Decodable::decode(&mut decoder) {
Ok(t) => t,
- Err(e) => fail!("failure decoding JSON: {}", e)
+ Err(e) => panic!("failure decoding JSON: {}", e)
})
}
#[test]
pub fn do_not_run_ignored_tests() {
- fn f() { fail!(); }
+ fn f() { panic!(); }
let desc = TestDescAndFn {
desc: TestDesc {
name: StaticTestName("whatever"),
#[test]
fn test_should_fail() {
- fn f() { fail!(); }
+ fn f() { panic!(); }
let desc = TestDescAndFn {
desc: TestDesc {
name: StaticTestName("whatever"),
let args = vec!("progname".to_string(), "some_regex_filter".to_string());
let opts = match parse_opts(args.as_slice()) {
Some(Ok(o)) => o,
- _ => fail!("Malformed arg in first_free_arg_should_be_a_filter")
+ _ => panic!("Malformed arg in first_free_arg_should_be_a_filter")
};
assert!(opts.filter.expect("should've found filter").is_match("some_regex_filter"))
}
"--ignored".to_string());
let opts = match parse_opts(args.as_slice()) {
Some(Ok(o)) => o,
- _ => fail!("Malformed arg in parse_ignored_flag")
+ _ => panic!("Malformed arg in parse_ignored_flag")
};
assert!((opts.run_ignored));
}
== Err(InvalidTime));
match strptime("Fri Feb 13 15:31:30.01234 2009", format) {
- Err(e) => fail!(e),
+ Err(e) => panic!(e),
Ok(ref tm) => {
assert!(tm.tm_sec == 30_i32);
assert!(tm.tm_min == 31_i32);
fn test(s: &str, format: &str) -> bool {
match strptime(s, format) {
Ok(ref tm) => tm.strftime(format).unwrap() == s.to_string(),
- Err(e) => fail!(e)
+ Err(e) => panic!(e)
}
}
use core::cmp;
use core::collections::Collection;
use core::iter::{Filter, AdditiveIterator, Iterator, DoubleEndedIterator};
+use core::kinds::Sized;
use core::option::{Option, None, Some};
use core::str::{CharSplits, StrSlice};
use u_char;
Filter<'a, &'a str, CharSplits<'a, extern "Rust" fn(char) -> bool>>;
/// Methods for Unicode string slices
-pub trait UnicodeStrSlice<'a> {
+pub trait UnicodeStrSlice for Sized? {
/// Returns an iterator over the
/// [grapheme clusters](http://www.unicode.org/reports/tr29/#Grapheme_Cluster_Boundaries)
/// of the string.
/// let b: &[_] = &["a", "\r\n", "b", "🇷🇺🇸🇹"];
/// assert_eq!(gr2.as_slice(), b);
/// ```
- fn graphemes(&self, is_extended: bool) -> Graphemes<'a>;
+ fn graphemes<'a>(&'a self, is_extended: bool) -> Graphemes<'a>;
/// Returns an iterator over the grapheme clusters of self and their byte offsets.
/// See `graphemes()` method for more information.
/// let b: &[_] = &[(0u, "a̐"), (3, "é"), (6, "ö̲"), (11, "\r\n")];
/// assert_eq!(gr_inds.as_slice(), b);
/// ```
- fn grapheme_indices(&self, is_extended: bool) -> GraphemeIndices<'a>;
+ fn grapheme_indices<'a>(&'a self, is_extended: bool) -> GraphemeIndices<'a>;
/// An iterator over the words of a string (subsequences separated
/// by any sequence of whitespace). Sequences of whitespace are
/// let v: Vec<&str> = some_words.words().collect();
/// assert_eq!(v, vec!["Mary", "had", "a", "little", "lamb"]);
/// ```
- fn words(&self) -> Words<'a>;
+ fn words<'a>(&'a self) -> Words<'a>;
/// Returns true if the string contains only whitespace.
///
fn width(&self, is_cjk: bool) -> uint;
/// Returns a string with leading and trailing whitespace removed.
- fn trim(&self) -> &'a str;
+ fn trim<'a>(&'a self) -> &'a str;
/// Returns a string with leading whitespace removed.
- fn trim_left(&self) -> &'a str;
+ fn trim_left<'a>(&'a self) -> &'a str;
/// Returns a string with trailing whitespace removed.
- fn trim_right(&self) -> &'a str;
+ fn trim_right<'a>(&'a self) -> &'a str;
}
-impl<'a> UnicodeStrSlice<'a> for &'a str {
+impl UnicodeStrSlice for str {
#[inline]
- fn graphemes(&self, is_extended: bool) -> Graphemes<'a> {
- Graphemes { string: *self, extended: is_extended, cat: None, catb: None }
+ fn graphemes(&self, is_extended: bool) -> Graphemes {
+ Graphemes { string: self, extended: is_extended, cat: None, catb: None }
}
#[inline]
- fn grapheme_indices(&self, is_extended: bool) -> GraphemeIndices<'a> {
+ fn grapheme_indices(&self, is_extended: bool) -> GraphemeIndices {
GraphemeIndices { start_offset: self.as_ptr() as uint, iter: self.graphemes(is_extended) }
}
#[inline]
- fn words(&self) -> Words<'a> {
+ fn words(&self) -> Words {
self.split(u_char::is_whitespace).filter(|s| !s.is_empty())
}
}
#[inline]
- fn trim(&self) -> &'a str {
+ fn trim(&self) -> &str {
self.trim_left().trim_right()
}
#[inline]
- fn trim_left(&self) -> &'a str {
+ fn trim_left(&self) -> &str {
self.trim_left_chars(u_char::is_whitespace)
}
#[inline]
- fn trim_right(&self) -> &'a str {
+ fn trim_right(&self) -> &str {
self.trim_right_chars(u_char::is_whitespace)
}
}
+S 2014-10-22 d44ea72
+ freebsd-x86_64 8bf5ee7c1ca8ab880800cf3a535e16bb7ffbf9e8
+ linux-i386 1fc8302b405406a3fc183b23c8397bef5a56c52a
+ linux-x86_64 3e04d8197a96b0c858e4e2763b3893df35ae2fb3
+ macos-i386 b9823771ae6237a3c1c19eb2e98a2372ce23439d
+ macos-x86_64 3cf9fc1cd252a80430d8673e35a1256674e122ae
+ winnt-i386 5a6d2ad82a31deffad5b6a17487a8cd5c21f7636
+ winnt-x86_64 7468b87eb5be238993ccd41ad74bbd88dd176d31
+
S 2014-10-10 78a7676
freebsd-x86_64 511061af382e2e837a6d615823e1a952e8281483
linux-i386 0644637db852db8a6c603ded0531ccaa60291bd3
return entry.value.clone();
}
}
- fail!();
+ panic!();
}
#[inline]
--- /dev/null
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Helper definition for test/run-pass/check-static-recursion-foreign.rs.
+
+#[crate_id = "check_static_recursion_foreign_helper"]
+#[crate_type = "lib"]
+
+extern crate libc;
+
+#[no_mangle]
+pub static test_static: libc::c_int = 0;
pub unsafe fn f(xs: Vec<int> ) {
- xs.iter().map(|_x| { unsafe fn q() { fail!(); } }).collect::<Vec<()>>();
+ xs.iter().map(|_x| { unsafe fn q() { panic!(); } }).collect::<Vec<()>>();
}
#[lang="sized"]
pub trait Sized for Sized? {}
-#[lang="fail"]
-fn fail(_: &(&'static str, &'static str, uint)) -> ! { loop {} }
+#[lang="panic"]
+fn panic(_: &(&'static str, &'static str, uint)) -> ! { loop {} }
#[lang = "stack_exhausted"]
extern fn stack_exhausted() {}
#[phase(plugin, link)] extern crate log;
pub fn foo<T>() {
- fn death() -> int { fail!() }
+ fn death() -> int { panic!() }
debug!("{}", (||{ death() })());
}
}
impl<'a> IntoMaybeOwned<'a> for Inv<'a> {
- fn into_maybe_owned(self) -> MaybeOwned<'a> { fail!() }
- fn into_inv(self) -> Inv<'a> { fail!() }
- fn bigger_region<'b:'a>(self, b: Inv<'b>) { fail!() }
+ fn into_maybe_owned(self) -> MaybeOwned<'a> { panic!() }
+ fn into_inv(self) -> Inv<'a> { panic!() }
+ fn bigger_region<'b:'a>(self, b: Inv<'b>) { panic!() }
}
extern crate rustc;
use syntax::codemap::Span;
-use syntax::parse::token::{IDENT, get_ident};
-use syntax::ast::{TokenTree, TTTok};
+use syntax::parse::token;
+use syntax::ast::{TokenTree, TtToken};
use syntax::ext::base::{ExtCtxt, MacResult, DummyResult, MacExpr};
use syntax::ext::build::AstBuilder; // trait for expr_uint
use rustc::plugin::Registry;
("I", 1)];
let text = match args {
- [TTTok(_, IDENT(s, _))] => get_ident(s).to_string(),
+ [TtToken(_, token::Ident(s, _))] => token::get_ident(s).to_string(),
_ => {
cx.span_err(sp, "argument should be a single identifier");
return DummyResult::any(sp);
pub fn read<T:read>(s: String) -> T {
match read::readMaybe(s) {
Some(x) => x,
- _ => fail!("read failed!")
+ _ => panic!("read panicked!")
}
}
pub fn foo() {
let _a = A;
- fail!("wut");
+ panic!("wut");
}
mod std {
for _ in range(0u, 20000) {
v.push('b' as u8);
if !str::is_utf8(v.as_slice()) {
- fail!("is_utf8 failed");
+ panic!("is_utf8 panicked");
}
}
}
for _ in range(0u, 5000) {
v.push_all(s.as_bytes());
if !str::is_utf8(v.as_slice()) {
- fail!("is_utf8 failed");
+ panic!("is_utf8 panicked");
}
}
}
7 => {" seven"}
8 => {" eight"}
9 => {" nine"}
- _ => {fail!("expected digits from 0 to 9...")}
+ _ => {panic!("expected digits from 0 to 9...")}
}
}
'C' => 1,
'G' => 2,
'T' => 3,
- _ => fail!("{}", c as char),
+ _ => panic!("{}", c as char),
}
}
for id in range(0u8, 10) {
if m & (1 << (id + 50) as uint) != 0 {return id;}
}
- fail!("{:016x} does not have a valid identifier", m);
+ panic!("{:016x} does not have a valid identifier", m);
}
// Converts a list of mask to a Vec<u8>.
Ok(ref m) => {
return Config {stress: m.opt_present("stress")}
}
- Err(_) => { fail!(); }
+ Err(_) => { panic!(); }
}
}
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
// OF THE POSSIBILITY OF SUCH DAMAGE.
-// ignore-android doesn't terminate?
+// ignore-android see #10393 #13206
-#![feature(slicing_syntax, asm, if_let, tuple_indexing)]
+#![feature(slicing_syntax, unboxed_closures, overloaded_calls)]
extern crate libc;
use std::io::stdio::{stdin_raw, stdout_raw};
-use std::sync::{Future};
use std::num::{div_rem};
use std::ptr::{copy_memory};
use std::io::{IoResult, EndOfFile};
-use std::slice::raw::{mut_buf_as_slice};
-use shared_memory::{SharedMemory};
-
-mod tables {
- use std::sync::{Once, ONCE_INIT};
-
- /// Lookup tables.
- static mut CPL16: [u16, ..1 << 16] = [0, ..1 << 16];
- static mut CPL8: [u8, ..1 << 8] = [0, ..1 << 8];
-
- /// Generates the tables.
- pub fn get() -> Tables {
- /// To make sure we initialize the tables only once.
- static INIT: Once = ONCE_INIT;
- INIT.doit(|| {
- unsafe {
- for i in range(0, 1 << 8) {
- CPL8[i] = match i as u8 {
- b'A' | b'a' => b'T',
- b'C' | b'c' => b'G',
- b'G' | b'g' => b'C',
- b'T' | b't' => b'A',
- b'U' | b'u' => b'A',
- b'M' | b'm' => b'K',
- b'R' | b'r' => b'Y',
- b'W' | b'w' => b'W',
- b'S' | b's' => b'S',
- b'Y' | b'y' => b'R',
- b'K' | b'k' => b'M',
- b'V' | b'v' => b'B',
- b'H' | b'h' => b'D',
- b'D' | b'd' => b'H',
- b'B' | b'b' => b'V',
- b'N' | b'n' => b'N',
- i => i,
- };
- }
-
- for (i, v) in CPL16.iter_mut().enumerate() {
- *v = *CPL8.unsafe_get(i & 255) as u16 << 8 |
- *CPL8.unsafe_get(i >> 8) as u16;
- }
- }
- });
- Tables { _dummy: () }
- }
-
- /// Accessor for the static arrays.
- ///
- /// To make sure that the tables can't be accessed without having been initialized.
- pub struct Tables {
- _dummy: ()
- }
-
- impl Tables {
- /// Retreives the complement for `i`.
- pub fn cpl8(self, i: u8) -> u8 {
- // Not really unsafe.
- unsafe { CPL8[i as uint] }
- }
-
- /// Retreives the complement for `i`.
- pub fn cpl16(self, i: u16) -> u16 {
- unsafe { CPL16[i as uint] }
- }
- }
+struct Tables {
+ table8: [u8, ..1 << 8],
+ table16: [u16, ..1 << 16]
}
-mod shared_memory {
- use std::sync::{Arc};
- use std::mem::{transmute};
- use std::raw::{Slice};
-
- /// Structure for sharing disjoint parts of a vector mutably across tasks.
- pub struct SharedMemory {
- ptr: Arc<Vec<u8>>,
- start: uint,
- len: uint,
- }
-
- impl SharedMemory {
- pub fn new(ptr: Vec<u8>) -> SharedMemory {
- let len = ptr.len();
- SharedMemory {
- ptr: Arc::new(ptr),
- start: 0,
- len: len,
- }
+impl Tables {
+ fn new() -> Tables {
+ let mut table8 = [0, ..1 << 8];
+ for (i, v) in table8.iter_mut().enumerate() {
+ *v = Tables::computed_cpl8(i as u8);
}
-
- pub fn as_mut_slice(&mut self) -> &mut [u8] {
- unsafe {
- transmute(Slice {
- data: self.ptr.as_ptr().offset(self.start as int) as *const u8,
- len: self.len,
- })
- }
+ let mut table16 = [0, ..1 << 16];
+ for (i, v) in table16.iter_mut().enumerate() {
+ *v = table8[i & 255] as u16 << 8 |
+ table8[i >> 8] as u16;
}
+ Tables { table8: table8, table16: table16 }
+ }
- pub fn len(&self) -> uint {
- self.len
+ fn computed_cpl8(c: u8) -> u8 {
+ match c {
+ b'A' | b'a' => b'T',
+ b'C' | b'c' => b'G',
+ b'G' | b'g' => b'C',
+ b'T' | b't' => b'A',
+ b'U' | b'u' => b'A',
+ b'M' | b'm' => b'K',
+ b'R' | b'r' => b'Y',
+ b'W' | b'w' => b'W',
+ b'S' | b's' => b'S',
+ b'Y' | b'y' => b'R',
+ b'K' | b'k' => b'M',
+ b'V' | b'v' => b'B',
+ b'H' | b'h' => b'D',
+ b'D' | b'd' => b'H',
+ b'B' | b'b' => b'V',
+ b'N' | b'n' => b'N',
+ i => i,
}
+ }
- pub fn split_at(self, mid: uint) -> (SharedMemory, SharedMemory) {
- assert!(mid <= self.len);
- let left = SharedMemory {
- ptr: self.ptr.clone(),
- start: self.start,
- len: mid,
- };
- let right = SharedMemory {
- ptr: self.ptr,
- start: self.start + mid,
- len: self.len - mid,
- };
- (left, right)
- }
+ /// Retreives the complement for `i`.
+ fn cpl8(&self, i: u8) -> u8 {
+ self.table8[i as uint]
+ }
- /// Resets the object so that it covers the whole range of the contained vector.
- ///
- /// You must not call this method if `self` is not the only reference to the
- /// shared memory.
- ///
- /// FIXME: If `Arc` had a method to check if the reference is unique, then we
- /// wouldn't need the `unsafe` here.
- ///
- /// FIXME: If `Arc` had a method to unwrap the contained value, then we could
- /// simply unwrap here.
- pub unsafe fn reset(self) -> SharedMemory {
- let len = self.ptr.len();
- SharedMemory {
- ptr: self.ptr,
- start: 0,
- len: len,
- }
- }
+ /// Retreives the complement for `i`.
+ fn cpl16(&self, i: u16) -> u16 {
+ self.table16[i as uint]
}
}
-
/// Reads all remaining bytes from the stream.
fn read_to_end<R: Reader>(r: &mut R) -> IoResult<Vec<u8>> {
+ // As reading the input stream in memory is a bottleneck, we tune
+ // Reader::read_to_end() with a fast growing policy to limit
+ // recopies. If MREMAP_RETAIN is implemented in the linux kernel
+ // and jemalloc use it, this trick will become useless.
const CHUNK: uint = 64 * 1024;
- let mut vec = Vec::with_capacity(1024 * 1024);
+ let mut vec = Vec::with_capacity(CHUNK);
loop {
+ // workaround: very fast growing
if vec.capacity() - vec.len() < CHUNK {
let cap = vec.capacity();
let mult = if cap < 256 * 1024 * 1024 {
- // FIXME (mahkoh): Temporary workaround for jemalloc on linux. Replace
- // this by 2x once the jemalloc preformance issue has been fixed.
16
} else {
2
};
vec.reserve_exact(mult * cap);
}
- unsafe {
- let ptr = vec.as_mut_ptr().offset(vec.len() as int);
- match mut_buf_as_slice(ptr, CHUNK, |s| r.read(s)) {
- Ok(n) => {
- let len = vec.len();
- vec.set_len(len + n);
- },
- Err(ref e) if e.kind == EndOfFile => break,
- Err(e) => return Err(e),
- }
+ match r.push_at_least(1, CHUNK, &mut vec) {
+ Ok(_) => {}
+ Err(ref e) if e.kind == EndOfFile => break,
+ Err(e) => return Err(e)
}
}
Ok(vec)
/// Finds the first position at which `b` occurs in `s`.
fn memchr(h: &[u8], n: u8) -> Option<uint> {
use libc::{c_void, c_int, size_t};
- extern {
- fn memchr(h: *const c_void, n: c_int, s: size_t) -> *mut c_void;
- }
let res = unsafe {
- memchr(h.as_ptr() as *const c_void, n as c_int, h.len() as size_t)
+ libc::memchr(h.as_ptr() as *const c_void, n as c_int, h.len() as size_t)
};
if res.is_null() {
None
}
}
+/// A mutable iterator over DNA sequences
+struct MutDnaSeqs<'a> { s: &'a mut [u8] }
+fn mut_dna_seqs<'a>(s: &'a mut [u8]) -> MutDnaSeqs<'a> {
+ MutDnaSeqs { s: s }
+}
+impl<'a> Iterator<&'a mut [u8]> for MutDnaSeqs<'a> {
+ fn next(&mut self) -> Option<&'a mut [u8]> {
+ let tmp = std::mem::replace(&mut self.s, &mut []);
+ let tmp = match memchr(tmp, b'\n') {
+ Some(i) => tmp.slice_from_mut(i + 1),
+ None => return None,
+ };
+ let (seq, tmp) = match memchr(tmp, b'>') {
+ Some(i) => tmp.split_at_mut(i),
+ None => {
+ let len = tmp.len();
+ tmp.split_at_mut(len)
+ }
+ };
+ self.s = tmp;
+ Some(seq)
+ }
+}
+
/// Length of a normal line without the terminating \n.
const LINE_LEN: uint = 60;
/// Compute the reverse complement.
-fn reverse_complement(mut view: SharedMemory, tables: tables::Tables) {
- // Drop the last newline
- let seq = view.as_mut_slice().init_mut();
+fn reverse_complement(seq: &mut [u8], tables: &Tables) {
+ let seq = seq.init_mut();// Drop the last newline
let len = seq.len();
let off = LINE_LEN - len % (LINE_LEN + 1);
let mut i = LINE_LEN;
}
}
-fn main() {
- let mut data = SharedMemory::new(read_to_end(&mut stdin_raw()).unwrap());
- let tables = tables::get();
-
- let mut futures = vec!();
- loop {
- let (_, mut tmp_data) = match memchr(data.as_mut_slice(), b'\n') {
- Some(i) => data.split_at(i + 1),
- _ => break,
- };
- let (view, tmp_data) = match memchr(tmp_data.as_mut_slice(), b'>') {
- Some(i) => tmp_data.split_at(i),
- None => {
- let len = tmp_data.len();
- tmp_data.split_at(len)
- },
- };
- futures.push(Future::spawn(proc() reverse_complement(view, tables)));
- data = tmp_data;
- }
-
- for f in futures.iter_mut() {
- f.get();
+/// Executes a closure in parallel over the given iterator over mutable slice.
+/// The closure `f` is run in parallel with an element of `iter`.
+fn parallel<'a, I, T, F>(mut iter: I, f: F)
+ where T: Send + Sync,
+ I: Iterator<&'a mut [T]>,
+ F: Fn(&'a mut [T]) + Sync {
+ use std::mem;
+ use std::raw::Repr;
+
+ let (tx, rx) = channel();
+ for chunk in iter {
+ let tx = tx.clone();
+
+ // Need to convert `f` and `chunk` to something that can cross the task
+ // boundary.
+ let f = &f as *const F as *const uint;
+ let raw = chunk.repr();
+ spawn(proc() {
+ let f = f as *const F;
+ unsafe { (*f)(mem::transmute(raw)) }
+ drop(tx)
+ });
}
+ drop(tx);
+ for () in rx.iter() {}
+}
- // Not actually unsafe. If Arc had a way to check uniqueness then we could do that in
- // `reset` and it would tell us that, yes, it is unique at this point.
- data = unsafe { data.reset() };
-
+fn main() {
+ let mut data = read_to_end(&mut stdin_raw()).unwrap();
+ let tables = &Tables::new();
+ parallel(mut_dna_seqs(data[mut]), |&: seq| reverse_complement(seq, tables));
stdout_raw().write(data.as_mut_slice()).unwrap();
}
from_str::<uint>(comps[2]).unwrap() as u8;
}
else {
- fail!("Invalid sudoku file");
+ panic!("Invalid sudoku file");
}
}
return Sudoku::new(g)
ptr = ptr + 1u;
} else {
// no: redo this field aft recoloring pred; unless there is none
- if ptr == 0u { fail!("No solution found for this sudoku"); }
+ if ptr == 0u { panic!("No solution found for this sudoku"); }
ptr = ptr - 1u;
}
}
for _ in range(0, repeat) {
println!("starting {:.4f}", precise_time_s());
task::try(proc() {
- recurse_or_fail(depth, None)
+ recurse_or_panic(depth, None)
});
println!("stopping {:.4f}", precise_time_s());
}
}
}
-fn recurse_or_fail(depth: int, st: Option<State>) {
+fn recurse_or_panic(depth: int, st: Option<State>) {
if depth == 0 {
println!("unwinding {:.4f}", precise_time_s());
- fail!();
+ panic!();
} else {
let depth = depth - 1;
}
};
- recurse_or_fail(depth, Some(st));
+ recurse_or_panic(depth, Some(st));
}
}
let (tx, rx) = channel();
child_generation(from_str::<uint>(args[1].as_slice()).unwrap(), tx);
if rx.recv_opt().is_err() {
- fail!("it happened when we slumbered");
+ panic!("it happened when we slumbered");
}
}
// Tests that a function with a ! annotation always actually fails
fn bad_bang(i: uint) -> ! {
- return 7u;
- //~^ ERROR expected `!`, found `uint`
+ return 7u; //~ ERROR `return` in a function declared as diverging [E0166]
}
fn main() { bad_bang(5u); }
// Tests that a function with a ! annotation always actually fails
-fn bad_bang(i: uint) -> ! {
- if i < 0u { } else { fail!(); }
- //~^ ERROR expected `!`, found `()`
+fn bad_bang(i: uint) -> ! { //~ ERROR computation may converge in a function marked as diverging
+ if i < 0u { } else { panic!(); }
}
fn main() { bad_bang(5u); }
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-fn f() -> ! {
- 3i //~ ERROR expected `!`, found `int`
+fn f() -> ! { //~ ERROR computation may converge in a function marked as diverging
+ 3i
}
fn main() { }
let x = Some((X { x: () }, X { x: () }));
match x {
Some((ref _y, _z)) => { }, //~ ERROR cannot bind by-move and by-ref in the same pattern
- None => fail!()
+ None => panic!()
}
}
let x = some2(X { x: () }, X { x: () });
match x {
some2(ref _y, _z) => { }, //~ ERROR cannot bind by-move and by-ref in the same pattern
- none2 => fail!()
+ none2 => panic!()
}
}
let x = Some((X { x: () }, X { x: () }));
match x {
Some((_y, ref _z)) => { }, //~ ERROR cannot bind by-move and by-ref in the same pattern
- None => fail!()
+ None => panic!()
}
}
let x = Some(rx);
tx.send(false);
match x {
- Some(z) if z.recv() => { fail!() }, //~ ERROR cannot bind by-move into a pattern guard
+ Some(z) if z.recv() => { panic!() }, //~ ERROR cannot bind by-move into a pattern guard
Some(z) => { assert!(!z.recv()); },
- None => fail!()
+ None => panic!()
}
}
--- /dev/null
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn foo() -> ! { panic!("quux"); }
+fn main() {
+ foo() //~ ERROR the type of this value must be known in this context
+ ==
+ foo();
+}
let a = match y {
Y(ref mut a, _) => a,
- X => fail!()
+ X => panic!()
};
let b = match y {
Y(_, ref mut b) => b,
- X => fail!()
+ X => panic!()
};
*a += 1;
let a = match y {
Y(ref mut a, _) => a,
- X => fail!()
+ X => panic!()
};
let b = match y {
Y(ref mut b, _) => b, //~ ERROR cannot borrow
- X => fail!()
+ X => panic!()
};
*a += 1;
x = X(Left((0,0)));
(*f)()
},
- _ => fail!()
+ _ => panic!()
}
})
}
int2: int,
}
-fn make_foo() -> Box<Foo> { fail!() }
+fn make_foo() -> Box<Foo> { panic!() }
fn borrow_same_field_twice_mut_mut() {
let mut foo = make_foo();
int2: int,
}
-fn make_foo() -> Foo { fail!() }
+fn make_foo() -> Foo { panic!() }
fn borrow_same_field_twice_mut_mut() {
let mut foo = make_foo();
}
fn e(x: &mut int) {
- let c1: || = || x = fail!(); //~ ERROR closure cannot assign to immutable local variable
+ let c1: || = || x = panic!(); //~ ERROR closure cannot assign to immutable local variable
}
fn main() {
fn borrow(_v: &int) {}
fn borrow_mut(_v: &mut int) {}
-fn cond() -> bool { fail!() }
-fn for_func(_f: || -> bool) { fail!() }
-fn produce<T>() -> T { fail!(); }
+fn cond() -> bool { panic!() }
+fn for_func(_f: || -> bool) { panic!() }
+fn produce<T>() -> T { panic!(); }
fn inc(v: &mut Box<int>) {
*v = box() (**v + 1);
fn borrow(_v: &int) {}
fn borrow_mut(_v: &mut int) {}
-fn cond() -> bool { fail!() }
-fn produce<T>() -> T { fail!(); }
+fn cond() -> bool { panic!() }
+fn produce<T>() -> T { panic!(); }
fn inc(v: &mut Box<int>) {
*v = box() (**v + 1);
fn borrow(_v: &int) {}
fn borrow_mut(_v: &mut int) {}
-fn cond() -> bool { fail!() }
-fn for_func(_f: || -> bool) { fail!() }
-fn produce<T>() -> T { fail!(); }
+fn cond() -> bool { panic!() }
+fn for_func(_f: || -> bool) { panic!() }
+fn produce<T>() -> T { panic!(); }
fn inc(v: &mut Box<int>) {
*v = box() (**v + 1);
*x = Right(1.0);
*z
}
- _ => fail!()
+ _ => panic!()
}
}
Some(ref m) => { //~ ERROR borrowed value does not live long enough
msg = m;
},
- None => { fail!() }
+ None => { panic!() }
}
println!("{}", *msg);
}
let vec: &[int] = vec.as_slice(); //~ ERROR does not live long enough
let tail = match vec {
[_, tail..] => tail,
- _ => fail!("a")
+ _ => panic!("a")
};
tail
}
let vec: &[int] = vec.as_slice(); //~ ERROR does not live long enough
let init = match vec {
[init.., _] => init,
- _ => fail!("b")
+ _ => panic!("b")
};
init
}
let vec: &[int] = vec.as_slice(); //~ ERROR does not live long enough
let slice = match vec {
[_, slice.., _] => slice,
- _ => fail!("c")
+ _ => panic!("c")
};
slice
}
let vec: &[int] = vec.as_slice(); //~ ERROR `vec` does not live long enough
let tail = match vec {
[_a, tail..] => &tail[0],
- _ => fail!("foo")
+ _ => panic!("foo")
};
tail
}
fn main() {
// Type inference didn't use to be able to handle this:
- foo(|| fail!());
- foo(|| -> ! fail!());
- foo(|| 22); //~ ERROR mismatched types
- foo(|| -> ! 22); //~ ERROR mismatched types
- let x = || -> ! 1; //~ ERROR mismatched types
+ foo(|| panic!());
+ foo(|| -> ! panic!());
+ foo(|| 22i); //~ ERROR computation may converge in a function marked as diverging
+ foo(|| -> ! 22i); //~ ERROR computation may converge in a function marked as diverging
+ let x = || -> ! 1i; //~ ERROR computation may converge in a function marked as diverging
}
impl<T> MyTrait<T> for T { //~ ERROR E0119
fn get(&self) -> T {
- fail!()
+ panic!()
}
}
#![deny(unreachable_code)]
fn main() {
- let x: || -> ! = || fail!();
+ let x: || -> ! = || panic!();
x();
println!("Foo bar"); //~ ERROR: unreachable statement
}
fn main() {
match *1 { //~ ERROR: cannot be dereferenced
- _ => { fail!(); }
+ _ => { panic!(); }
}
}
fn foo() { //~ ERROR function is never used
// none of these should have any dead_code exposed to the user
- fail!();
+ panic!();
- fail!("foo");
+ panic!("foo");
- fail!("bar {}", "baz")
+ panic!("bar {}", "baz")
}
fn foo() { //~ ERROR function is never used
// none of these should have any dead_code exposed to the user
- fail!();
+ panic!();
- fail!("foo");
+ panic!("foo");
- fail!("bar {}", "baz")
+ panic!("bar {}", "baz")
}
// error-pattern:unexpected token
fn main() {
- fail!(@);
+ panic!(@);
}
}
impl<'a> Foo<'a> for &'a str {
- fn bar<T: Bar<'a>>(self) -> &'a str { fail!() } //~ ERROR lifetime
+ fn bar<T: Bar<'a>>(self) -> &'a str { panic!() } //~ ERROR lifetime
}
fn main() {
// except according to those terms.
fn main() {
- (return)[0u]; //~ ERROR cannot index a value of type `!`
+ (return)[0u]; //~ ERROR the type of this value must be known in this context
}
struct A { foo: int }
-fn a() -> A { fail!() }
+fn a() -> A { panic!() }
fn main() {
let A { .., } = a(); //~ ERROR: expected `}`
struct A { foo: int }
-fn a() -> A { fail!() }
+fn a() -> A { panic!() }
fn main() {
let A { , } = a(); //~ ERROR: expected ident
match a {
Ok(a) => //~ ERROR: mismatched types
println!("{}",a),
- None => fail!()
+ None => panic!()
}
}
&Cons(val, box ref next_list) => tail(next_list),
&Cons(val, box Nil) => Cons(val, box Nil),
//~^ ERROR: unreachable pattern
- _ => fail!()
+ _ => panic!()
}
}
// except according to those terms.
fn new<T>() -> &'static T {
- fail!()
+ panic!()
}
fn main() {
// except according to those terms.
fn new<'r, T>() -> &'r T {
- fail!()
+ panic!()
}
fn main() {
--- /dev/null
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+mod foo { pub fn bar() {} }
+
+fn main() {
+ match () {
+ foo::bar => {} //~ ERROR `bar` is not an enum variant, struct or const
+ }
+}
// tricked into looking up a non-existing second type parameter.
let _x: uint = match Some(1u) {
Ok(u) => u, //~ ERROR mismatched types: expected `core::option::Option<uint>`
- Err(e) => fail!(e) //~ ERROR mismatched types: expected `core::option::Option<uint>`
+ Err(e) => panic!(e) //~ ERROR mismatched types: expected `core::option::Option<uint>`
};
}
// except according to those terms.
fn main() {
- return.is_failure
-//~^ ERROR attempted access of field `is_failure` on type `!`, but no field with that name was found
+ return.is_failure //~ ERROR the type of this value must be known in this context
}
--- /dev/null
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn main() {
+ let foo = "str";
+ println!("{}", foo.desc); //~ ERROR attempted access of field `desc` on type `&str`,
+ // but no field with that name was found
+}
// except according to those terms.
fn main() {
- loop { break.push(1); } //~ ERROR type `!` does not implement any method in scope named `push`
+ loop {
+ break.push(1) //~ ERROR the type of this value must be known in this context
+ //~^ ERROR multiple applicable methods in scope
+ ;
+ }
}
// except according to those terms.
fn main() {
- return { return () } (); //~ ERROR expected function, found `!`
+ return
+ { return () } //~ ERROR the type of this value must be known in this context
+ () //~^ ERROR the type of this value must be known in this context
+//~^^ ERROR notation; the first type parameter for the function trait is neither a tuple nor unit
+//~^^^ ERROR overloaded calls are experimental
+ ;
}
--- /dev/null
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+trait T<'a> {
+ fn a(&'a self) -> &'a bool;
+ fn b(&self) {
+ self.a(); //~ ERROR mismatched types: expected `&'a Self`, found `&Self` (lifetime mismatch)
+ }
+}
+
+fn main() {}
// except according to those terms.
fn main() {
- *return; //~ ERROR type `!` cannot be dereferenced
+ *return //~ ERROR the type of this value must be known in this context
+ ;
}
--- /dev/null
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+static X: uint = 0 as *const uint as uint;
+//~^ ERROR: can not cast a pointer to an integer in a constant expression
+
+fn main() {
+ assert_eq!(X, 0);
+}
--- /dev/null
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(unboxed_closures)]
+
+struct B<T>;
+
+fn main() {
+ let foo = B; //~ ERROR unable to infer enough type information to locate the impl of the trait
+ let closure = |:| foo;
+}
--- /dev/null
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+pub fn main() {
+ static z: &'static int = {
+ let p = 3;
+ &p
+//~^ ERROR cannot borrow a local variable inside a static block, define a separate static instead
+ };
+}
--- /dev/null
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(struct_variant)]
+
+enum Foo {
+ Variant { x: uint }
+}
+
+fn main() {
+ let f = Variant(42u); //~ ERROR expected function, found `Foo`
+}
--- /dev/null
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn main() {
+ const X: u32 = 1;
+ const Y: uint = &X as *const u32 as uint; //~ ERROR E0018
+ println!("{}", Y);
+}
--- /dev/null
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+struct Obj<'a> {
+ closure: ||: 'a -> u32
+}
+
+fn main() {
+ let o = Obj { closure: || 42 };
+ o.closure(); //~ ERROR type `Obj<'_>` does not implement any method in scope named `closure`
+ //~^ NOTE use `(s.closure)(...)` if you meant to call the function stored in the `closure` field
+}
impl<A> vec_monad<A> for Vec<A> {
fn bind<B>(&self, f: |A| -> Vec<B> ) {
- let mut r = fail!();
+ let mut r = panic!();
for elt in self.iter() { r = r + f(*elt); }
//~^ ERROR the type of this value must be known
//~^^ ERROR not implemented
fn fail_len(v: Vec<int> ) -> uint {
let mut i = 3;
- fail!();
+ panic!();
for x in v.iter() { i += 1u; }
//~^ ERROR: unreachable statement
return i;
// except according to those terms.
fn main() {
- let x = fail!();
+ let x = panic!();
x.clone(); //~ ERROR the type of this value must be known in this context
}
// `chan` is not a trait, it's an enum
impl chan for int { //~ ERROR `chan` is not a trait
- fn send(&self, v: int) { fail!() }
+ fn send(&self, v: int) { panic!() }
}
fn main() {
fn foo() { //~ NOTE Did you mean to close this delimiter?
match Some(x) {
- Some(y) { fail!(); }
- None { fail!(); }
+ Some(y) { panic!(); }
+ None { panic!(); }
}
fn bar() {
}
impl A for E {
- fn b<F: Sync, G>(_x: F) -> F { fail!() } //~ ERROR type parameter 0 requires `Sync`
+ fn b<F: Sync, G>(_x: F) -> F { panic!() } //~ ERROR type parameter 0 requires `Sync`
}
fn main() {}
impl A for E {
// n.b. The error message is awful -- see #3404
- fn b<F:Clone,G>(&self, _x: G) -> G { fail!() } //~ ERROR method `b` has an incompatible type
+ fn b<F:Clone,G>(&self, _x: G) -> G { panic!() } //~ ERROR method `b` has an incompatible type
}
fn main() {}
//~^ ERROR unresolved name `k0`.
}
}
- fail!();
+ panic!();
}
fn main() {}
box Element(ed) => match ed.kind { //~ ERROR non-exhaustive patterns
box HTMLImageElement(ref d) if d.image.is_some() => { true }
},
- _ => fail!("WAT") //~ ERROR unreachable pattern
+ _ => panic!("WAT") //~ ERROR unreachable pattern
};
}
fn getChildOption(&self) -> Option<Box<P>> {
static childVal: Box<P> = self.child.get();
//~^ ERROR attempt to use a non-constant value in a constant
- fail!();
+ panic!();
}
}
match (true, false) {
box (true, false) => ()
- //~^ ERROR mismatched types: expected `(bool,bool)`, found `Box<<generic #11>>`
+ //~^ ERROR mismatched types: expected `(bool,bool)`, found `Box<<generic #15>>`
// (expected tuple, found box)
}
match (true, false) {
&(true, false) => ()
- //~^ ERROR mismatched types: expected `(bool,bool)`, found `&<generic #15>`
+ //~^ ERROR mismatched types: expected `(bool,bool)`, found `&<generic #21>`
// (expected tuple, found &-ptr)
}
let a = 5;
let _iter = TrieMapIterator{node: &a};
_iter.node = & //~ ERROR cannot assign to immutable field
- fail!()
+ panic!()
}
--- /dev/null
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn main() {
+ &panic!()
+ //~^ ERROR mismatched types: expected `()`, found `&<generic #2>` (expected (), found &-ptr)
+}
// except according to those terms.
fn foo<T>(t: T) {}
-fn main() { foo(fail!()) }
+fn main() { foo(panic!()) }
//~^ ERROR type annotations required
--- /dev/null
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+static x: &'static uint = &1;
+static y: uint = *x;
+//~^ ERROR cannot refer to other statics by value,
+// use the address-of operator or a constant instead
+fn main() {}
--- /dev/null
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+enum A { B, C }
+
+mod foo { pub fn bar() {} }
+
+fn main() {
+ match (true, false) {
+ B => (), //~ ERROR expected `(bool,bool)`, found `A` (expected tuple, found enum A)
+ _ => ()
+ }
+
+ match &Some(42i) {
+ Some(x) => (), //~ ERROR expected `&core::option::Option<int>`,
+ // found `core::option::Option<<generic #4>>`
+ None => () //~ ERROR expected `&core::option::Option<int>`,
+ // found `core::option::Option<<generic #5>>`
+ }
+}
#![deny(unreachable_code)]
-fn g() -> ! { fail!(); }
+fn g() -> ! { panic!(); }
fn f() -> ! {
- return g();
- g(); //~ ERROR: unreachable statement
+ return g(); //~ ERROR `return` in a function declared as diverging
+ g();
+}
+fn h() -> ! {
+ loop {}
+ g();
}
fn main() { f() }
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// error-pattern: unreachable statement
-
#![deny(unreachable_code)]
fn f() -> ! {
- return fail!();
- fail!(); // the unreachable statement error is in <std macro>, at this line, there
+ return panic!(); //~ ERROR `return` in a function declared as diverging
+ panic!(); // the unreachable statement error is in <std macro>, at this line, there
// only is a note
}
// Lifetime annotation needed because we have no arguments.
fn f() -> &int { //~ ERROR missing lifetime specifier
//~^ NOTE there is no value for it to be borrowed from
- fail!()
+ panic!()
}
// Lifetime annotation needed because we have two by-reference parameters.
fn g(_x: &int, _y: &int) -> &int { //~ ERROR missing lifetime specifier
//~^ NOTE the signature does not say whether it is borrowed from `_x` or `_y`
- fail!()
+ panic!()
}
struct Foo<'a> {
// and one on the reference.
fn h(_x: &Foo) -> &int { //~ ERROR missing lifetime specifier
//~^ NOTE the signature does not say which one of `_x`'s 2 elided lifetimes it is borrowed from
- fail!()
+ panic!()
}
fn main() {}
}
}
-fn callback<T>(_f: || -> T) -> T { fail!() }
+fn callback<T>(_f: || -> T) -> T { panic!() }
unsafe fn unsf() {}
fn bad1() { unsafe {} } //~ ERROR: unnecessary `unsafe` block
sure that when purity is inherited that the source of the unsafe-ness
is tracked correctly */
unsafe {
- unsafe fn what() -> Vec<String> { fail!() }
+ unsafe fn what() -> Vec<String> { panic!() }
callback(|| {
what();
pub struct Public<T>;
impl Private<Public<int>> {
- pub fn a(&self) -> Private<int> { fail!() }
- fn b(&self) -> Private<int> { fail!() }
+ pub fn a(&self) -> Private<int> { panic!() }
+ fn b(&self) -> Private<int> { panic!() }
- pub fn c() -> Private<int> { fail!() }
- fn d() -> Private<int> { fail!() }
+ pub fn c() -> Private<int> { panic!() }
+ fn d() -> Private<int> { panic!() }
}
impl Private<int> {
- pub fn e(&self) -> Private<int> { fail!() }
- fn f(&self) -> Private<int> { fail!() }
+ pub fn e(&self) -> Private<int> { panic!() }
+ fn f(&self) -> Private<int> { panic!() }
}
impl Public<Private<int>> {
- pub fn a(&self) -> Private<int> { fail!() }
- fn b(&self) -> Private<int> { fail!() }
+ pub fn a(&self) -> Private<int> { panic!() }
+ fn b(&self) -> Private<int> { panic!() }
- pub fn c() -> Private<int> { fail!() } //~ ERROR private type in exported type signature
- fn d() -> Private<int> { fail!() }
+ pub fn c() -> Private<int> { panic!() } //~ ERROR private type in exported type signature
+ fn d() -> Private<int> { panic!() }
}
impl Public<int> {
- pub fn e(&self) -> Private<int> { fail!() } //~ ERROR private type in exported type signature
- fn f(&self) -> Private<int> { fail!() }
+ pub fn e(&self) -> Private<int> { panic!() } //~ ERROR private type in exported type signature
+ fn f(&self) -> Private<int> { panic!() }
}
pub fn x(_: Private<int>) {} //~ ERROR private type in exported type signature
}
pub trait PubTrait {
- fn foo(&self) -> Private<int> { fail!( )} //~ ERROR private type in exported type signature
+ fn foo(&self) -> Private<int> { panic!( )} //~ ERROR private type in exported type signature
fn bar(&self) -> Private<int>; //~ ERROR private type in exported type signature
fn baz() -> Private<int>; //~ ERROR private type in exported type signature
}
impl PubTrait for Public<int> {
- fn bar(&self) -> Private<int> { fail!() }
- fn baz() -> Private<int> { fail!() }
+ fn bar(&self) -> Private<int> { panic!() }
+ fn baz() -> Private<int> { panic!() }
}
impl PubTrait for Public<Private<int>> {
- fn bar(&self) -> Private<int> { fail!() }
- fn baz() -> Private<int> { fail!() }
+ fn bar(&self) -> Private<int> { panic!() }
+ fn baz() -> Private<int> { panic!() }
}
impl PubTrait for Private<int> {
- fn bar(&self) -> Private<int> { fail!() }
- fn baz() -> Private<int> { fail!() }
+ fn bar(&self) -> Private<int> { panic!() }
+ fn baz() -> Private<int> { panic!() }
}
impl PubTrait for (Private<int>,) {
- fn bar(&self) -> Private<int> { fail!() }
- fn baz() -> Private<int> { fail!() }
+ fn bar(&self) -> Private<int> { panic!() }
+ fn baz() -> Private<int> { panic!() }
}
trait PrivTrait {
- fn foo(&self) -> Private<int> { fail!( )}
+ fn foo(&self) -> Private<int> { panic!( )}
fn bar(&self) -> Private<int>;
}
impl PrivTrait for Private<int> {
- fn bar(&self) -> Private<int> { fail!() }
+ fn bar(&self) -> Private<int> { panic!() }
}
impl PrivTrait for (Private<int>,) {
- fn bar(&self) -> Private<int> { fail!() }
+ fn bar(&self) -> Private<int> { panic!() }
}
pub trait ParamTrait<T> {
impl ParamTrait<Private<int>> //~ ERROR private type in exported type signature
for Public<int> {
- fn foo() -> Private<int> { fail!() }
+ fn foo() -> Private<int> { panic!() }
}
impl ParamTrait<Private<int>> for Private<int> {
- fn foo() -> Private<int> { fail!( )}
+ fn foo() -> Private<int> { panic!( )}
}
impl<T: ParamTrait<Private<int>>> //~ ERROR private type in exported type signature
ParamTrait<T> for Public<i8> {
- fn foo() -> T { fail!() }
+ fn foo() -> T { panic!() }
}
// except according to those terms.
// Tests that a function with a ! annotation always actually fails
-// error-pattern: some control paths may return
-fn bad_bang(i: uint) -> ! { println!("{}", 3i); }
+fn bad_bang(i: uint) -> ! { //~ ERROR computation may converge in a function marked as diverging
+ println!("{}", 3i);
+}
fn main() { bad_bang(5u); }
fn send<T:Send + std::fmt::Show>(ch: _chan<T>, data: T) {
println!("{}", ch);
println!("{}", data);
- fail!();
+ panic!();
}
#[deriving(Show)]
println!("{}", message); //~ ERROR use of moved value: `message`
}
-fn main() { fail!(); }
+fn main() { panic!(); }
loop {
break;
}
- return 42i; //~ ERROR expected `!`, found `int`
+ return 42i; //~ ERROR `return` in a function declared as diverging
}
fn main() {
}
pub fn opt_str2<'a>(maybestr: &'a Option<String>) -> &'static str {
- match *maybestr { //~ ERROR cannot infer an appropriate lifetime for automatic coercion due to
+ match *maybestr {
+ //~^ ERROR cannot infer an appropriate lifetime due to conflicting requirements
None => "(none)",
Some(ref s) => {
let s: &'a str = s.as_slice();
}
pub fn opt_str3<'a>(maybestr: &'a Option<String>) -> &'static str {
- match *maybestr { //~ ERROR cannot infer an appropriate lifetime for automatic coercion due to
+ match *maybestr {
+ //~^ ERROR cannot infer an appropriate lifetime due to conflicting requirements
Some(ref s) => {
let s: &'a str = s.as_slice();
s
// a good test that we merge paths correctly in the presence of a
// variable that's used before it's declared
-fn my_fail() -> ! { fail!(); }
+fn my_panic() -> ! { panic!(); }
fn main() {
- match true { false => { my_fail(); } true => { } }
+ match true { false => { my_panic(); } true => { } }
println!("{}", x); //~ ERROR unresolved name `x`.
let x: int;
struct Foo<A> { f: A }
-fn guard(_s: String) -> bool {fail!()}
+fn guard(_s: String) -> bool {panic!()}
fn touch<A>(_a: &A) {}
fn f10() {
// terms of the binding, not the discriminant.
struct Foo<A> { f: A }
-fn guard(_s: String) -> bool {fail!()}
+fn guard(_s: String) -> bool {panic!()}
fn touch<A>(_a: &A) {}
fn f10() {
//~^ ERROR: cannot borrow `*f` as mutable because
println!("{}", msg);
},
- None => fail!("oops"),
+ None => panic!("oops"),
}
}
})
fn main() {
let x = a(c);
match x { //~ ERROR non-exhaustive patterns: `a(c)` not covered
- a(d) => { fail!("hello"); }
- b => { fail!("goodbye"); }
+ a(d) => { panic!("hello"); }
+ b => { panic!("goodbye"); }
}
}
// unrelated errors.
fn foo(a: int, b: int, c: int, d:int) {
- fail!();
+ panic!();
}
fn main() {
enum bar { t1((), Option<Vec<int>>), t2, }
// n.b. my change changes this error message, but I think it's right -- tjc
-fn foo(t: bar) -> int { match t { t1(_, Some(x)) => { return x * 3; } _ => { fail!(); } } }
+fn foo(t: bar) -> int { match t { t1(_, Some(x)) => { return x * 3; } _ => { panic!(); } } }
//~^ ERROR binary operation `*` cannot be applied to
fn main() { }
t1(_, Some::<int>(x)) => {
println!("{}", x);
}
- _ => { fail!(); }
+ _ => { panic!(); }
}
}
}
fn check_pp<T>(expr: T, f: |pprust::ps, T|, expect: str) {
- fail!();
+ panic!();
}
}
fn check_pp<T>(expr: T, f: |pprust::ps, T|, expect: str) {
- fail!();
+ panic!();
}
// Test that attempts to implicitly coerce a value into an
// object respect the lifetime bound on the object type.
-fn a(v: &[u8]) -> Box<Clone + 'static> {
- let x: Box<Clone + 'static> = box v; //~ ERROR does not outlive
+trait Foo {}
+impl<'a> Foo for &'a [u8] {}
+
+fn a(v: &[u8]) -> Box<Foo + 'static> {
+ let x: Box<Foo + 'static> = box v; //~ ERROR does not outlive
x
}
-fn b(v: &[u8]) -> Box<Clone + 'static> {
+fn b(v: &[u8]) -> Box<Foo + 'static> {
box v //~ ERROR does not outlive
}
-fn c(v: &[u8]) -> Box<Clone> {
+fn c(v: &[u8]) -> Box<Foo> {
box v // OK thanks to lifetime elision
}
-fn d<'a,'b>(v: &'a [u8]) -> Box<Clone+'b> {
+fn d<'a,'b>(v: &'a [u8]) -> Box<Foo+'b> {
box v //~ ERROR does not outlive
}
-fn e<'a:'b,'b>(v: &'a [u8]) -> Box<Clone+'b> {
+fn e<'a:'b,'b>(v: &'a [u8]) -> Box<Foo+'b> {
box v // OK, thanks to 'a:'b
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-fn of<T>() -> |T| { fail!(); }
-fn subtype<T>(x: |T|) { fail!(); }
+fn of<T>() -> |T| { panic!(); }
+fn subtype<T>(x: |T|) { panic!(); }
fn test_fn<'x, 'y, 'z, T>(_x: &'x T, _y: &'y T, _z: &'z T) {
// Here, x, y, and z are free. Other letters
// Should meet both.
fn foo(x: &S) -> &'static S {
- fail!()
+ panic!()
}
// Should meet both.
fn bar<'a,'b>(x: &'a S) -> &'b S {
- fail!()
+ panic!()
}
// Meets F, but not G.
fn baz(x: &S) -> &S {
- fail!()
+ panic!()
}
fn supply_F() {
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-fn of<'a,T>() -> |T|:'a { fail!(); }
-fn subtype<T>(x: |T|) { fail!(); }
+fn of<'a,T>() -> |T|:'a { panic!(); }
+fn subtype<T>(x: |T|) { panic!(); }
fn test_fn<'x,'y,'z,T>(_x: &'x T, _y: &'y T, _z: &'z T) {
// Here, x, y, and z are free. Other letters
// Do not infer an ordering from the return value.
let z: &'b uint = &*x;
//~^ ERROR cannot infer
- fail!();
+ panic!();
}
fn ordering4<'a, 'b>(a: &'a uint, b: &'b uint, x: |&'a &'b uint|) {
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-type t = { f: () }; //~ ERROR expected type, found token LBRACE
+type t = { f: () }; //~ ERROR expected type, found token LBrace
+++ /dev/null
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-
-trait add {
- fn plus(&self, x: Self) -> Self;
-}
-
-fn do_add(x: Box<add+'static>, y: Box<add+'static>) -> Box<add+'static> {
- x.plus(y) //~ ERROR E0038
-}
-
-fn main() {}
use std::vec::Vec;
fn last<T>(v: Vec<&T> ) -> std::option::Option<T> {
- fail!();
+ panic!();
}
fn main() {
fn foo(c: quux) { assert!((false)); }
-fn main() { fail!(); }
+fn main() { panic!(); }
x: 3i
};
- let baz: Foo<uint> = fail!();
+ let baz: Foo<uint> = panic!();
//~^ ERROR not implemented
}
--- /dev/null
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+trait Foo {
+ fn foo(self);
+}
+
+trait Bar {
+ fn bar(&self, x: &Self);
+}
+
+trait Baz {
+ fn baz<T>(&self, x: &T);
+}
+
+impl Foo for int {
+ fn foo(self) {}
+}
+
+impl Bar for int {
+ fn bar(&self, _x: &int) {}
+}
+
+impl Baz for int {
+ fn baz<T>(&self, _x: &T) {}
+}
+
+fn main() {
+ let _: &Foo = &42i; //~ ERROR cannot convert to a trait object
+ let _: &Bar = &42i; //~ ERROR cannot convert to a trait object
+ let _: &Baz = &42i; //~ ERROR cannot convert to a trait object
+
+ let _ = &42i as &Foo; //~ ERROR cannot convert to a trait object
+ let _ = &42i as &Bar; //~ ERROR cannot convert to a trait object
+ let _ = &42i as &Baz; //~ ERROR cannot convert to a trait object
+}
fn main() {
10i.dup::<int>(); //~ ERROR does not take type parameters
10i.blah::<int, int>(); //~ ERROR incorrect number of type parameters
- (box 10i as Box<bar>).dup(); //~ ERROR contains a self-type
+ (box 10i as Box<bar>).dup(); //~ ERROR cannot convert to a trait object
}
--- /dev/null
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(unboxed_closures)]
+
+// Test that even unboxed closures that are capable of mutating their
+// environment cannot mutate captured variables that have not been
+// declared mutable (#18335)
+
+fn set(x: &mut uint) { *x = 0; }
+
+fn main() {
+ let x = 0u;
+ move |&mut:| x = 1; //~ ERROR cannot assign
+ move |&mut:| set(&mut x); //~ ERROR cannot borrow
+ move |:| x = 1; //~ ERROR cannot assign
+ move |:| set(&mut x); //~ ERROR cannot borrow
+ |&mut:| x = 1; //~ ERROR cannot assign
+ // FIXME: this should be `cannot borrow` (issue #18330)
+ |&mut:| set(&mut x); //~ ERROR cannot assign
+ |:| x = 1; //~ ERROR cannot assign
+ // FIXME: this should be `cannot borrow` (issue #18330)
+ |:| set(&mut x); //~ ERROR cannot assign
+}
#[must_use = "some message"]
enum MustUseMsg { Test2 }
-fn foo<T>() -> T { fail!() }
+fn foo<T>() -> T { panic!() }
fn bar() -> int { return foo::<int>(); }
fn baz() -> MustUse { return foo::<MustUse>(); }
// except according to those terms.
// aux-build:weak-lang-items.rs
-// error-pattern: language item required, but not found: `fail_fmt`
+// error-pattern: language item required, but not found: `panic_fmt`
// error-pattern: language item required, but not found: `stack_exhausted`
// error-pattern: language item required, but not found: `eh_personality`
}
fn _zzz() {()}
-fn _yyy() -> ! {fail!()}
+fn _yyy() -> ! {panic!()}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-fn f() { if (1i == fail!()) { } else { } }
+fn f() { if (1i == panic!()) { } else { } }
fn main() { }
--- /dev/null
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// pp-exact
+// pretty-compare-only
+// Testing that shorthand struct patterns are preserved
+
+fn main() { let Foo { a, ref b, mut c, x: y, z: z } = foo; }
// error-pattern:meep
-fn f(_a: int, _b: int, _c: Box<int>) { fail!("moop"); }
+fn f(_a: int, _b: int, _c: Box<int>) { panic!("moop"); }
-fn main() { f(1, fail!("meep"), box 42); }
+fn main() { f(1, panic!("meep"), box 42); }
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// error-pattern:failed at 'assertion failed: false'
+// error-pattern:panicked at 'assertion failed: false'
fn main() {
assert!(false);
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// error-pattern:failed at 'test-assert-fmt 42 rust'
+// error-pattern:panicked at 'test-assert-fmt 42 rust'
fn main() {
assert!(false, "test-assert-fmt {} {}", 42i, "rust");
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// error-pattern:failed at 'test-assert-owned'
+// error-pattern:panicked at 'test-assert-owned'
fn main() {
assert!(false, "test-assert-owned".to_string());
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// error-pattern:failed at 'test-assert-static'
+// error-pattern:panicked at 'test-assert-static'
fn main() {
assert!(false, "test-assert-static");
+++ /dev/null
-// Copyright 2013 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.
-
-// error-pattern:quux
-fn foo() -> ! { fail!("quux"); }
-fn main() { foo() == foo(); }
// except according to those terms.
// error-pattern:quux
-fn my_err(s: String) -> ! { println!("{}", s); fail!("quux"); }
+fn my_err(s: String) -> ! { println!("{}", s); panic!("quux"); }
fn main() { 3u == my_err("bye".to_string()); }
fn main() {
let x = vec!(1u,2u,3u);
- // This should cause a bounds-check failure, but may not if we do our
+ // This should cause a bounds-check panic, but may not if we do our
// bounds checking by comparing a scaled index value to the vector's
// length (in bytes), because the scaling of the index will cause it to
// wrap around to a small number.
let idx = uint::MAX & !(uint::MAX >> 1u);
println!("ov2 idx = 0x%x", idx);
- // This should fail.
+ // This should panic.
println!("ov2 0x%x", x[idx]);
}
fn main() {
let x = vec!(1u,2u,3u);
- // This should cause a bounds-check failure, but may not if we do our
+ // This should cause a bounds-check panic, but may not if we do our
// bounds checking by truncating the index value to the size of the
// machine word, losing relevant bits of the index value.
(idx >> 32) as uint,
idx as uint);
- // This should fail.
+ // This should panic.
println!("ov3 0x%x", x.as_slice()[idx]);
}
#[cfg(target_arch="x86_64")]
fn main() {
- // This version just fails anyways, for symmetry on 64-bit hosts.
+ // This version just panics anyways, for symmetry on 64-bit hosts.
let x = vec!(1u,2u,3u);
error!("ov3 0x%x", x.as_slice()[200]);
}
fn main() {
- // This should cause a bounds-check failure, but may not if we do our
+ // This should cause a bounds-check panic, but may not if we do our
// bounds checking by comparing the scaled index to the vector's
// address-bounds, since we've scaled the index to wrap around to the
// address of the 0th cell in the array (even though the index is
println!("ov1 idx * sizeof::<uint>() = 0x{:x}",
idx * mem::size_of::<uint>());
- // This should fail.
+ // This should panic.
println!("ov1 0x{:x}", x[idx]);
}
port: port_id,
}
-fn send<T:Send>(_ch: chan_t<T>, _data: T) { fail!(); }
+fn send<T:Send>(_ch: chan_t<T>, _data: T) { panic!(); }
-fn main() { fail!("quux"); }
+fn main() { panic!("quux"); }
+++ /dev/null
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// error-pattern:explicit failure
-
-trait Foo {
- fn foo(self, x: int);
-}
-
-struct S {
- x: int,
- y: int,
- z: int,
- s: String,
-}
-
-impl Foo for S {
- fn foo(self, x: int) {
- fail!()
- }
-}
-
-impl Drop for S {
- fn drop(&mut self) {
- println!("bye 1!");
- }
-}
-
-fn f() {
- let s = S {
- x: 2,
- y: 3,
- z: 4,
- s: "hello".to_string(),
- };
- let st = box s as Box<Foo>;
- st.foo(5);
-}
-
-fn main() {
- f();
-}
-
-
// error-pattern:test
fn main() {
- let _i: int = fail!("test");
+ let _i: int = panic!("test");
}
// error-pattern:test
fn f() {
- fail!("test");
+ panic!("test");
}
fn main() {
// error-pattern:test
fn main() {
- fail!("test");
+ panic!("test");
}
//error-pattern:One
fn main() {
- fail!("One");
- fail!("Two");
+ panic!("One");
+ panic!("Two");
}
fn main() {
let mut a = 1i;
if 1i == 1 { a = 2; }
- fail!(format!("woooo{}", "o"));
+ panic!(format!("woooo{}", "o"));
}
// error-pattern:explicit
-fn main() { fail!(); }
+fn main() { panic!(); }
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+// error-pattern:explicit panic
-
-
-// error-pattern:explicit failure
-fn f() -> ! { fail!() }
+fn f() -> ! { panic!() }
fn main() { f(); }
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+// error-pattern:explicit panic
-
-
-// error-pattern:explicit failure
-fn f() -> ! { fail!() }
+fn f() -> ! { panic!() }
fn g() -> int { let x = if true { f() } else { 10 }; return x; }
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+// error-pattern:explicit panic
-
-
-// error-pattern:explicit failure
-fn main() { let _x = if false { 0i } else if true { fail!() } else { 10i }; }
+fn main() { let _x = if false { 0i } else if true { panic!() } else { 10i }; }
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+// error-pattern:explicit panic
-
-
-// error-pattern:explicit failure
-fn f() -> ! { fail!() }
+fn f() -> ! { panic!() }
fn g() -> int { let x = match true { true => { f() } false => { 10 } }; return x; }
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+// error-pattern:explicit panic
-
-
-// error-pattern:explicit failure
-fn main() { let _x = match true { false => { 0i } true => { fail!() } }; }
+fn main() { let _x = match true { false => { 0i } true => { panic!() } }; }
task::spawn(proc() {
let result = count(5u);
println!("result = %?", result);
- fail!();
+ panic!();
});
}
}
// error-pattern:woe
fn f(a: int) { println!("{}", a); }
-fn main() { f(fail!("woe")); }
+fn main() { f(panic!("woe")); }
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// error-pattern:failed at 'Box<Any>'
+// error-pattern:panicked at 'Box<Any>'
fn main() {
- fail!(box 612_i64);
+ panic!(box 612_i64);
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// error-pattern:failed at 'Box<Any>'
-
+// error-pattern:panicked at 'Box<Any>'
fn main() {
- fail!(box 413i as Box<::std::any::Any+Send>);
+ panic!(box 413i as Box<::std::any::Any+Send>);
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// error-pattern:failed at 'explicit failure'
+// error-pattern:panicked at 'explicit panic'
fn main() {
- fail!();
+ panic!();
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// error-pattern:failed at 'test-fail-fmt 42 rust'
+// error-pattern:panicked at 'test-fail-fmt 42 rust'
fn main() {
- fail!("test-fail-fmt {} {}", 42i, "rust");
+ panic!("test-fail-fmt {} {}", 42i, "rust");
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// error-pattern:failed at 'test-fail-owned'
+// error-pattern:panicked at 'test-fail-owned'
fn main() {
- fail!("test-fail-owned");
+ panic!("test-fail-owned");
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// error-pattern:failed at 'test-fail-static'
+// error-pattern:panicked at 'test-fail-static'
fn main() {
- fail!("test-fail-static");
+ panic!("test-fail-static");
}
// except according to those terms.
// error-pattern:moop
-fn main() { fail!("moop"); }
+fn main() { panic!("moop"); }
// Previously failed formating invalid utf8.
// cc #16877
-// error-pattern:failed at 'hello�'
+// error-pattern:panicked at 'hello�'
struct Foo;
impl std::fmt::Show for Foo {
}
}
fn main() {
- fail!("{}", Foo)
+ panic!("{}", Foo)
}
// certain positions
// error-pattern:oops
-fn bigfail() {
- while (fail!("oops")) { if (fail!()) {
- match (fail!()) { () => {
+fn bigpanic() {
+ while (panic!("oops")) { if (panic!()) {
+ match (panic!()) { () => {
}
}
}};
}
-fn main() { bigfail(); }
+fn main() { bigpanic(); }
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// error-pattern:task '<unnamed>' failed at 'test'
+// error-pattern:task '<unnamed>' panicked at 'test'
use std::task;
fn main() {
let r: Result<int,_> = task::try(proc() {
- fail!("test");
+ panic!("test");
1i
});
assert!(r.is_ok());
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// error-pattern:task 'owned name' failed at 'test'
+// error-pattern:task 'owned name' panicked at 'test'
use std::task::TaskBuilder;
fn main() {
let r: Result<int,_> = TaskBuilder::new().named("owned name".to_string())
.try(proc() {
- fail!("test");
+ panic!("test");
1i
});
assert!(r.is_ok());
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// error-pattern:task 'send name' failed at 'test'
+// error-pattern:task 'send name' panicked at 'test'
fn main() {
let r: Result<int,_> =
::std::task::TaskBuilder::new().named("send name".into_maybe_owned())
.try(proc() {
- fail!("test");
+ panic!("test");
3i
});
assert!(r.is_ok());
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// error-pattern:task 'static name' failed at 'test'
+// error-pattern:task 'static name' panicked at 'test'
fn main() {
let r: Result<int,_> =
::std::task::TaskBuilder::new().named("static name").try(proc() {
- fail!("test");
+ panic!("test");
});
assert!(r.is_ok());
}
fn main() {
let str_var: String = "meh".to_string();
- fail!("{}", str_var);
+ panic!("{}", str_var);
}
// error-pattern:moop
-fn main() { for _ in range(0u, 10u) { fail!("moop"); } }
+fn main() { for _ in range(0u, 10u) { panic!("moop"); } }
//
// Expanded pretty printing causes resolve conflicts.
-// error-pattern:fail works
+// error-pattern:panic works
#![feature(globs)]
use std::*;
fn main() {
- fail!("fail works")
+ panic!("panic works")
}
if even(x) {
println!("{}", x);
} else {
- fail!("Number is odd");
+ panic!("Number is odd");
}
}
// except according to those terms.
// error-pattern:quux
-fn my_err(s: String) -> ! { println!("{}", s); fail!("quux"); }
+fn my_err(s: String) -> ! { println!("{}", s); panic!("quux"); }
fn main() { if my_err("bye".to_string()) { } }
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// error-pattern:explicit failure
+// error-pattern:explicit panic
pub fn main() {
- fail!(); println!("{}", 1i);
+ panic!(); println!("{}", 1i);
}
// error-pattern:bad input
fn main() {
- Some("foo").unwrap_or(fail!("bad input")).to_string();
+ Some("foo").unwrap_or(panic!("bad input")).to_string();
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// error-pattern:explicit failure
+// error-pattern:explicit panic
use std::sync::Arc;
enum e<T> { ee(Arc<T>) }
-fn foo() -> e<int> {fail!();}
+fn foo() -> e<int> {panic!();}
fn main() {
let _f = foo();
fn main() {
let mut x = Vec::new();
let y = vec!(3i);
- fail!("so long");
+ panic!("so long");
x.extend(y.into_iter());
}
+++ /dev/null
-// Copyright 2013 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.
-
-// error-pattern:explicit failure
-
-fn main() {
- &fail!()
-}
fn main() {
let origin = Point {x: 0, y: 0};
- let f: Point = Point {x: (fail!("beep boop")),.. origin};
+ let f: Point = Point {x: (panic!("beep boop")),.. origin};
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// error-pattern:task '<main>' failed at
+// error-pattern:task '<main>' panicked at
fn main() {
- fail!()
+ panic!()
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// error-pattern:explicit failure
+// error-pattern:explicit panic
#![allow(unreachable_code)]
#![allow(unused_variable)]
fn main() {
let i =
- match Some::<int>(3) { None::<int> => { fail!() } Some::<int>(_) => { fail!() } };
+ match Some::<int>(3) { None::<int> => { panic!() } Some::<int>(_) => { panic!() } };
foo(i);
}
// except according to those terms.
// error-pattern:quux
-fn f() -> ! { fail!("quux") }
+fn f() -> ! { panic!("quux") }
fn g() -> int { match f() { true => { 1 } false => { 0 } } }
fn main() { g(); }
// error-pattern:squirrelcupcake
fn cmp() -> int {
match (Some('a'), None::<char>) {
- (Some(_), _) => { fail!("squirrelcupcake"); }
- (_, Some(_)) => { fail!(); }
- _ => { fail!("wat"); }
+ (Some(_), _) => { panic!("squirrelcupcake"); }
+ (_, Some(_)) => { panic!(); }
+ _ => { panic!("wat"); }
}
}
// except according to those terms.
// ignore-android (FIXME #11419)
-// error-pattern:explicit failure
+// error-pattern:explicit panic
extern crate native;
#[start]
fn start(argc: int, argv: *const *const u8) -> int {
native::start(argc, argv, proc() {
- fail!();
+ panic!();
})
}
struct T { t: String }
fn main() {
- let pth = fail!("bye");
+ let pth = panic!("bye");
let _rs: T = T {t: pth};
}
fn main() {
error!("whatever");
// Setting the exit status only works when the scheduler terminates
- // normally. In this case we're going to fail, so instead of
+ // normally. In this case we're going to panic, so instead of
// returning 50 the process will return the typical rt failure code.
os::set_exit_status(50);
- fail!();
+ panic!();
}
}
// Setting the exit status after the runtime has already
-// failed has no effect and the process exits with the
+// panicked has no effect and the process exits with the
// runtime's exit code
impl Drop for r {
fn drop(&mut self) {
task::spawn(proc() {
let _i = r(5);
});
- fail!();
+ panic!();
}
fn main() {
error!("whatever");
- // 101 is the code the runtime uses on task failure and the value
+ // 101 is the code the runtime uses on task panic and the value
// compiletest expects run-fail tests to return.
os::set_exit_status(101);
}
pub fn exported() { }
#[test]
- fn unexported() { fail!("runned an unexported test"); }
+ fn unexported() { panic!("runned an unexported test"); }
}
fn main() {
let s: String = "hello".to_string();
- // Bounds-check failure.
+ // Bounds-check panic.
assert_eq!(s.as_bytes()[5], 0x0 as u8);
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// error-pattern:Ensure that the child task runs by failing
+// error-pattern:Ensure that the child task runs by panicking
use std::task;
// works when provided with a bare function:
let r = task::try(startfn);
if r.is_err() {
- fail!()
+ panic!()
}
}
fn startfn() {
- assert!("Ensure that the child task runs by failing".is_empty());
+ assert!("Ensure that the child task runs by panicking".is_empty());
}
// except according to those terms.
// check-stdout
-// error-pattern:task 'test_foo' failed at
+// error-pattern:task 'test_foo' panicked at
// compile-flags: --test
// ignore-pretty: does not work well with `--test`
#[test]
fn test_foo() {
- fail!()
+ panic!()
}
fn main() {
os::args();
- fail!("please have a nonzero exit status");
+ panic!("please have a nonzero exit status");
}
// ignore-test leaks
// error-pattern:ran out of stack
-// Test that the task fails after hitting the recursion limit
+// Test that the task panicks after hitting the recursion limit
// during unwinding
fn recurse() {
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// error-pattern: fail
-fn main() { box fail!(); }
+// error-pattern: panic
+fn main() { box panic!(); }
fn a() { }
-fn b() { fail!(); }
+fn b() { panic!(); }
fn main() {
let _x = vec!(0i);
fn build() -> Vec<int> {
- fail!();
+ panic!();
}
struct Blk { node: Vec<int> }
}
fn build2() -> Vec<int> {
- fail!();
+ panic!();
}
struct Blk { node: Vec<int> , span: Vec<int> }
fn failfn() {
- fail!();
+ panic!();
}
fn main() {
let v: Vec<int> = vec!(10);
let x: uint = 0;
assert_eq!(v[x], 10);
- // Bounds-check failure.
+ // Bounds-check panic.
assert_eq!(v[x + 2], 20);
}
#![allow(while_true)]
// error-pattern:quux
-fn main() { let _x: int = { while true { fail!("quux"); } ; 8 } ; }
+fn main() { let _x: int = { while true { panic!("quux"); } ; 8 } ; }
// error-pattern:giraffe
fn main() {
- fail!({ while true { fail!("giraffe") }; "clandestine" });
+ panic!({ while true { panic!("giraffe") }; "clandestine" });
}
#[lang = "stack_exhausted"] fn stack_exhausted() {}
#[lang = "eh_personality"] fn eh_personality() {}
-#[lang = "fail_fmt"] fn fail_fmt() -> ! { loop {} }
+#[lang = "panic_fmt"] fn panic_fmt() -> ! { loop {} }
#[lang = "stack_exhausted"] fn stack_exhausted() {}
#[lang = "eh_personality"] fn eh_personality() {}
-#[lang = "fail_fmt"] fn fail_fmt() -> ! { loop {} }
+#[lang = "panic_fmt"] fn panic_fmt() -> ! { loop {} }
fn main() {
task::try(proc() {
let _a = A;
- lib::callback(|| fail!());
+ lib::callback(|| panic!());
1i
});
pub fn main() {
- fail!()
+ panic!()
}
#[main]
fn foo() {
let _v = vec![1i, 2, 3];
if os::getenv("IS_TEST").is_some() {
- fail!()
+ panic!()
}
}
#[inline(never)]
fn double() {
(|| {
- fail!("once");
+ panic!("once");
}).finally(|| {
- fail!("twice");
+ panic!("twice");
})
}
// Check that issue #954 stays fixed
pub fn main() {
- match -1i { -1 => {}, _ => fail!("wat") }
+ match -1i { -1 => {}, _ => panic!("wat") }
assert_eq!(1i-1, 0i);
}
let x = Some(p);
match x {
Some(z) => { dispose(z); },
- None => fail!()
+ None => panic!()
}
}
);
match s {
box Bar2(id, rest) => declare!(id, self.elaborate_stm(rest)),
- _ => fail!()
+ _ => panic!()
}
}
- fn check_id(&mut self, s: int) { fail!() }
+ fn check_id(&mut self, s: int) { panic!() }
}
pub fn main() { }
+++ /dev/null
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-static mut destructor_count: uint = 0;
-
-trait Foo {
- fn foo(self, x: int);
-}
-
-struct S {
- x: int,
- y: int,
- z: int,
- s: String,
-}
-
-impl Foo for S {
- fn foo(self, x: int) {
- assert!(self.x == 2);
- assert!(self.y == 3);
- assert!(self.z == 4);
- assert!(self.s.as_slice() == "hello");
- assert!(x == 5);
- }
-}
-
-impl Drop for S {
- fn drop(&mut self) {
- println!("bye 1!");
- unsafe {
- destructor_count += 1;
- }
- }
-}
-
-impl Foo for int {
- fn foo(self, x: int) {
- println!("{}", x * x);
- }
-}
-
-fn f() {
- let s = S {
- x: 2,
- y: 3,
- z: 4,
- s: "hello".to_string(),
- };
- let st = box s as Box<Foo>;
- st.foo(5);
- println!("bye 2!");
-}
-
-fn g() {
- let s = 2i;
- let st = box s as Box<Foo>;
- st.foo(3);
- println!("bye 3!");
-}
-
-fn main() {
- f();
-
- unsafe {
- assert!(destructor_count == 1);
- }
-
- g();
-}
-
match 42 {
b'*' => {},
- _ => fail!()
+ _ => panic!()
}
match 100 {
b'a' ... b'z' => {},
- _ => fail!()
+ _ => panic!()
}
let expected: &[_] = &[97u8, 10u8, 13u8, 9u8, 92u8, 39u8, 34u8, 0u8, 240u8];
let val: &[_] = &[97u8, 10u8];
match val {
b"a\n" => {},
- _ => fail!(),
+ _ => panic!(),
}
let buf = vec!(97u8, 98, 99, 100);
// invoked -- after all, that would permit evil user code to
// abuse `Cell` and trigger crashes.
- fail!();
+ panic!();
}
}
--- /dev/null
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Static recursion check shouldn't fail when given a foreign item (#18279)
+
+// aux-build:check_static_recursion_foreign_helper.rs
+extern crate check_static_recursion_foreign_helper;
+extern crate libc;
+
+use libc::c_int;
+
+#[link_name = "check_static_recursion_foreign_helper"]
+extern "C" {
+ #[allow(dead_code)]
+ static test_static: c_int;
+}
+
+static B: &'static c_int = &test_static;
+
+pub fn main() {}
true
}
- fn find_mut(&mut self, _k: &int) -> Option<&mut T> { fail!() }
+ fn find_mut(&mut self, _k: &int) -> Option<&mut T> { panic!() }
fn remove(&mut self, k: &int) -> bool {
if self.find(k).is_some() {
}
}
- fn pop(&mut self, _k: &int) -> Option<T> { fail!() }
+ fn pop(&mut self, _k: &int) -> Option<T> { panic!() }
- fn swap(&mut self, _k: int, _v: T) -> Option<T> { fail!() }
+ fn swap(&mut self, _k: int, _v: T) -> Option<T> { panic!() }
}
impl<T> cat<T> {
pub fn get(&self, k: &int) -> &T {
match self.find(k) {
Some(v) => { v }
- None => { fail!("epic fail"); }
+ None => { panic!("epic fail"); }
}
}
//
// 1. Partial cleanup of `box` is in scope,
// 2. cleanup of return value from `get_bar()` is in scope,
-// 3. do_it() fails.
+// 3. do_it() panics.
//
// This led to a bug because `the top-most frame that was to be
// cleaned (which happens to be the partial cleanup of `box`) required
struct Foo { field: Box<uint> }
fn do_it(x: &[uint]) -> Foo {
- fail!()
+ panic!()
}
fn get_bar(x: uint) -> Vec<uint> { vec!(x * 2) }
}
fn main() {
- let x: || -> ! = || fail!();
+ let x: || -> ! = || panic!();
let _y: || -> ! = || x();
}
// except according to those terms.
#![allow(dead_code)]
+#![feature(unboxed_closures, unboxed_closure_sugar)]
+
+// compile-flags:-g
fn foo<T>() {}
// issue #13490
let _ = || -> ! loop {};
let _ = proc() -> ! loop {};
+
+ // issue #17021
+ let c = box |&:| {};
}
struct B<T>;
// Since the bogus configuration isn't defined main will just be
// parsed, but nothing further will be done with it
#[cfg(bogus)]
-pub fn main() { fail!() }
+pub fn main() { panic!() }
pub fn main() {
// Exercise some of the configured items in ways that wouldn't be possible
fn test_in_fn_ctxt() {
#[cfg(bogus)]
- fn f() { fail!() }
+ fn f() { panic!() }
fn f() { }
f();
extern crate log;
pub fn main() {
- // only fails if println! evaluates its argument.
- debug!("{}", { if true { fail!() } });
+ // only panics if println! evaluates its argument.
+ debug!("{}", { if true { panic!() } });
}
pub fn main() {
// exits early if println! evaluates its arguments, otherwise it
- // will hit the fail.
+ // will hit the panic.
println!("{}", { if true { return; } });
- fail!();
+ panic!();
}
pub fn main() {
match X {
Baz => {}
- _ => fail!()
+ _ => panic!()
}
match Y {
Bar(s) => assert!(s == 2654435769),
- _ => fail!()
+ _ => panic!()
}
match Z {
Quux(d,h) => {
assert_eq!(d, 0x123456789abcdef0);
assert_eq!(h, 0x1234);
}
- _ => fail!()
+ _ => panic!()
}
}
pub fn method(&self) {
match *self {
V => {}
- VV(..) => fail!()
+ VV(..) => panic!()
}
}
}
fn f(a: &E) {
match *a {
V => {}
- VV(..) => fail!()
+ VV(..) => panic!()
}
}
pub fn main() {
match *C {
V0 => (),
- _ => fail!()
+ _ => panic!()
}
}
pub fn main() {
match C {
- S0 { .. } => fail!(),
+ S0 { .. } => panic!(),
S1 { u } => assert!(u == 23)
}
}
pub fn main() {
match C0 {
V0 => (),
- _ => fail!()
+ _ => panic!()
}
match C1 {
V1(n) => assert!(n == 0xDEADBEE),
- _ => fail!()
+ _ => panic!()
}
match D0 {
V0 => (),
- _ => fail!()
+ _ => panic!()
}
match D1 {
V1(n) => assert!(n == 0xDEADBEE),
- _ => fail!()
+ _ => panic!()
}
}
pub fn main() {
match C[1] {
V1(n) => assert!(n == 0xDEADBEE),
- _ => fail!()
+ _ => panic!()
}
match C[2] {
V0 => (),
- _ => fail!()
+ _ => panic!()
}
}
pub fn main() {
match C[1] {
V1(n) => assert!(n == 0xDEADBEE),
- _ => fail!()
+ _ => panic!()
}
match C[2] {
V0 => (),
- _ => fail!()
+ _ => panic!()
}
}
pub fn main() {
match X {
Bar => {}
- Baz | Boo => fail!()
+ Baz | Boo => panic!()
}
match Y {
Baz => {}
- Bar | Boo => fail!()
+ Bar | Boo => panic!()
}
}
use std::str;
macro_rules! succeed( ($e:expr) => (
- match $e { Ok(..) => {}, Err(e) => fail!("failure: {}", e) }
+ match $e { Ok(..) => {}, Err(e) => panic!("panic: {}", e) }
) )
fn test_destroy_once() {
let mut p = sleeper();
match p.signal_exit() {
Ok(()) => {}
- Err(e) => fail!("error: {}", e),
+ Err(e) => panic!("error: {}", e),
}
}
}
});
match p.wait().unwrap() {
- ExitStatus(..) => fail!("expected a signal"),
+ ExitStatus(..) => panic!("expected a signal"),
ExitSignal(..) => tx.send(()),
}
}
// except according to those terms.
// check that the derived impls for the comparison traits shortcircuit
-// where possible, by having a type that fails when compared as the
+// where possible, by having a type that panics when compared as the
// second element, so this passes iff the instances shortcircuit.
pub struct FailCmp;
impl PartialEq for FailCmp {
- fn eq(&self, _: &FailCmp) -> bool { fail!("eq") }
+ fn eq(&self, _: &FailCmp) -> bool { panic!("eq") }
}
impl PartialOrd for FailCmp {
- fn partial_cmp(&self, _: &FailCmp) -> Option<Ordering> { fail!("partial_cmp") }
+ fn partial_cmp(&self, _: &FailCmp) -> Option<Ordering> { panic!("partial_cmp") }
}
impl Eq for FailCmp {}
impl Ord for FailCmp {
- fn cmp(&self, _: &FailCmp) -> Ordering { fail!("cmp") }
+ fn cmp(&self, _: &FailCmp) -> Ordering { panic!("cmp") }
}
#[deriving(PartialEq,PartialOrd,Eq,Ord)]
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// Just testing that fail!() type checks in statement or expr
+// Just testing that panic!() type checks in statement or expr
#![allow(unreachable_code)]
fn f() {
- fail!();
+ panic!();
- let _x: int = fail!();
+ let _x: int = panic!();
}
pub fn main() {
sender.send(DestructorRan);
}
&FailingVariant { .. } => {
- fail!("Failed");
+ panic!("Failed");
}
}
}
let x: *mut S = &mut S;
- // Test we can chnage the mutability from mut to const.
+ // Test we can change the mutability from mut to const.
let x: &T = &mut S;
let x: *const T = &mut S;
}
impl Deref<[uint]> for Arr {
fn deref(&self) -> &[uint] {
- fail!();
+ panic!();
}
}
pub fn main() {
let x = Some(0u64);
match x {
- None => fail!(),
+ None => panic!(),
Some(ref y) => assert!(is_aligned(y))
}
}
match Cons(10i, box Nil) {
Cons(10i, _) => {}
Nil => {}
- _ => fail!()
+ _ => panic!()
}
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// When all branches of an if expression result in fail, the entire if
-// expression results in fail.
+// When all branches of an if expression result in panic, the entire if
+// expression results in panic.
pub fn main() {
let _x = if true {
10i
} else {
- if true { fail!() } else { fail!() }
+ if true { panic!() } else { panic!() }
};
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-fn test_if_fail() {
- let x = if false { fail!() } else { 10i };
+fn test_if_panic() {
+ let x = if false { panic!() } else { 10i };
assert!((x == 10));
}
-fn test_else_fail() {
- let x = if true { 10i } else { fail!() };
+fn test_else_panic() {
+ let x = if true { 10i } else { panic!() };
assert_eq!(x, 10i);
}
-fn test_elseif_fail() {
- let x = if false { 0i } else if false { fail!() } else { 10i };
+fn test_elseif_panic() {
+ let x = if false { 0i } else if false { panic!() } else { 10i };
assert_eq!(x, 10i);
}
-pub fn main() { test_if_fail(); test_else_fail(); test_elseif_fail(); }
+pub fn main() { test_if_panic(); test_else_panic(); test_elseif_panic(); }
-// When all branches of a match expression result in fail, the entire
-// match expression results in fail.
+// When all branches of a match expression result in panic, the entire
+// match expression results in panic.
pub fn main() {
let _x =
match true {
true => { 10i }
- false => { match true { true => { fail!() } false => { fail!() } } }
+ false => { match true { true => { panic!() } false => { panic!() } } }
};
}
fn test_simple() {
- let r = match true { true => { true } false => { fail!() } };
+ let r = match true { true => { true } false => { panic!() } };
assert_eq!(r, true);
}
fn test_box() {
- let r = match true { true => { vec!(10i) } false => { fail!() } };
+ let r = match true { true => { vec!(10i) } false => { panic!() } };
assert_eq!(r[0], 10i);
}
fn test_generic<T:Clone>(expected: Box<T>, eq: compare<T>) {
let actual: Box<T> = match true {
true => { expected.clone() },
- _ => fail!("wat")
+ _ => panic!("wat")
};
assert!((eq(expected, actual)));
}
fn test_generic<T:Clone>(expected: T, eq: compare<T>) {
let actual: T = match true {
true => expected.clone(),
- _ => fail!("wat")
+ _ => panic!("wat")
};
assert!((eq(expected, actual)));
}
type compare<T> = extern "Rust" fn(T, T) -> bool;
fn test_generic<T:Clone>(expected: T, eq: compare<T>) {
- let actual: T = match true { true => { expected.clone() }, _ => fail!("wat") };
+ let actual: T = match true { true => { expected.clone() }, _ => panic!("wat") };
assert!((eq(expected, actual)));
}
struct R { i: int }
fn test_rec() {
- let rs = match true { true => R {i: 100}, _ => fail!() };
+ let rs = match true { true => R {i: 100}, _ => panic!() };
assert_eq!(rs.i, 100);
}
// Tests for match as expressions resulting in boxed types
fn test_box() {
- let res = match true { true => { box 100i }, _ => fail!() };
+ let res = match true { true => { box 100i }, _ => panic!() };
assert_eq!(*res, 100i);
}
impl Drop for Foo {
fn drop(&mut self) {
unsafe { DROPS += 1; }
- fail!()
+ panic!()
}
}
impl Drop for A {
fn drop(&mut self) {
- fail!()
+ panic!()
}
}
// except according to those terms.
-pub fn main() { let x: Vec<int> = Vec::new(); for _ in x.iter() { fail!("moop"); } }
+pub fn main() { let x: Vec<int> = Vec::new(); for _ in x.iter() { panic!("moop"); } }
match getopts(args.as_slice(), opts.as_slice()) {
Ok(ref m) =>
assert!(!m.opt_present("b")),
- Err(ref f) => fail!("{}", *f)
+ Err(ref f) => panic!("{}", *f)
};
}
'x: for _ in range(0i, 1) {
// this 'x should refer to the outer loop, lexically
loop_x!(break 'x);
- fail!("break doesn't act hygienically inside for loop");
+ panic!("break doesn't act hygienically inside for loop");
}
'x: loop {
// ditto
loop_x!(break 'x);
- fail!("break doesn't act hygienically inside infinite loop");
+ panic!("break doesn't act hygienically inside infinite loop");
}
'x: while 1i + 1 == 2 {
while_x!(break 'x);
- fail!("break doesn't act hygienically inside infinite while loop");
+ panic!("break doesn't act hygienically inside infinite while loop");
}
'x: for _ in range(0i, 1) {
// ditto
run_once!(continue 'x);
- fail!("continue doesn't act hygienically inside for loop");
+ panic!("continue doesn't act hygienically inside for loop");
}
}
// except according to those terms.
pub fn main() {
- let i: int = if false { fail!() } else { 5 };
+ let i: int = if false { panic!() } else { 5 };
println!("{}", i);
}
if even(x) {
println!("{}", x);
} else {
- fail!();
+ panic!();
}
}
if let Some(y) = x {
assert_eq!(y, 3i);
} else {
- fail!("if-let failed");
+ panic!("if-let panicked");
}
let mut worked = false;
if let Some(_) = x {
assert_eq!(clause, 4u);
if 3i > 4 {
- fail!("bad math");
+ panic!("bad math");
} else if let 1 = 2i {
- fail!("bad pattern match");
+ panic!("bad pattern match");
}
enum Foo {
let foo = Three("three".to_string(), 42i);
if let One = foo {
- fail!("bad pattern match");
+ panic!("bad pattern match");
} else if let Two(_x) = foo {
- fail!("bad pattern match");
+ panic!("bad pattern match");
} else if let Three(s, _) = foo {
assert_eq!(s.as_slice(), "three");
} else {
- fail!("bad else");
+ panic!("bad else");
}
if false {
- fail!("wat");
+ panic!("wat");
} else if let a@Two(_) = Two(42u) {
if let Two(b) = a {
assert_eq!(b, 42u);
} else {
- fail!("fail in nested if-let");
+ panic!("panic in nested if-let");
}
}
}
impl Foo {
#[allow(dead_code)]
fn foo(self) {
- fail!("wrong method!")
+ panic!("wrong method!")
}
}
struct A { foo: int }
struct B { a: int, b: int, c: int }
-fn mka() -> A { fail!() }
-fn mkb() -> B { fail!() }
+fn mka() -> A { panic!() }
+fn mkb() -> B { panic!() }
fn test() {
let A { foo, } = mka();
// An `if false {} else { expr }` statement should compile the same as `{ expr }`.
if false {
- fail!();
+ panic!();
} else {
let _a = Foo{ dropped: false };
}
struct Empty;
-impl Iterator<int> for Empty {
+trait T<U> {
+ fn next(&mut self) -> Option<U>;
+}
+impl T<int> for Empty {
fn next(&mut self) -> Option<int> { None }
}
-fn do_something_with(a : &mut Iterator<int>) {
+fn do_something_with(a : &mut T<int>) {
println!("{}", a.next())
}
{
match n {
&Cell(box Atom(2), box Cell(ref a, _)) => (**a).clone(),
- _ => fail!("Invalid fas pattern")
+ _ => panic!("Invalid fas pattern")
}
}
// ignore-pretty
-// Don't fail on blocks without results
+// Don't panic on blocks without results
// There are several tests in this run-pass that raised
// when this bug was opened. The cases where the compiler
-// failed before the fix have a comment.
+// panics before the fix have a comment.
struct S {x:()}
if b {
!b
} else {
- // `fail!(...)` would break
- fail!("Break the compiler");
+ // `panic!(...)` would break
+ panic!("Break the compiler");
}
}
--- /dev/null
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+trait Hash<H> {
+ fn hash2(&self, hasher: &H) -> u64;
+}
+
+trait Stream {
+ fn input(&mut self, bytes: &[u8]);
+ fn result(&self) -> u64;
+}
+
+trait StreamHasher<S: Stream> {
+ fn stream(&self) -> S;
+}
+
+//////////////////////////////////////////////////////////////////////////////
+
+trait StreamHash<S: Stream, H: StreamHasher<S>>: Hash<H> {
+ fn input_stream(&self, stream: &mut S);
+}
+
+impl<S: Stream, H: StreamHasher<S>> Hash<H> for u8 {
+ fn hash2(&self, hasher: &H) -> u64 {
+ let mut stream = hasher.stream();
+ self.input_stream(&mut stream);
+ stream.result()
+ }
+}
+
+impl<S: Stream, H: StreamHasher<S>> StreamHash<S, H> for u8 {
+ fn input_stream(&self, stream: &mut S) {
+ stream.input([*self]);
+ }
+}
+
+fn main() {}
FormatMessageW(0x1000, 0 as *mut c_void, 1, 0x400,
buf.as_mut_ptr(), buf.len() as u32, 0 as *const c_void)
};
- // On some 32-bit Windowses (Win7-8 at least) this will fail with segmented
+ // On some 32-bit Windowses (Win7-8 at least) this will panic with segmented
// stacks taking control of pvArbitrary
assert!(ret != 0);
}
unsafe { libc::exit(0 as libc::c_int); }
});
2u + (loop {});
- -(loop {});
}
let x = match Foo(42) {
Foo(..) => 1i,
_ if true => 0,
- Bar(..) => fail!("Oh dear")
+ Bar(..) => panic!("Oh dear")
};
assert_eq!(x, 1);
let x = match Foo(42) {
_ if true => 0i,
Foo(..) => 1,
- Bar(..) => fail!("Oh dear")
+ Bar(..) => panic!("Oh dear")
};
assert_eq!(x, 0);
}
--- /dev/null
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use std::io::Reader;
+
+enum Wrapper<'a> {
+ WrapReader(&'a Reader + 'a)
+}
+
+trait Wrap<'a> {
+ fn wrap(self) -> Wrapper<'a>;
+}
+
+impl<'a, R: Reader> Wrap<'a> for &'a mut R {
+ fn wrap(self) -> Wrapper<'a> {
+ WrapReader(self as &'a mut Reader)
+ }
+}
+
+pub fn main() {}
// except according to those terms.
pub fn main() {
- let early_error: |&str|: 'static -> ! = |_msg| { fail!() };
+ let early_error: |&str|: 'static -> ! = |_msg| { panic!() };
}
}
trait A {
- fn aaa(self) -> int {
+ fn aaa(&self) -> int {
3
}
- fn bbb(self) -> int {
+ fn bbb(&self) -> int {
return 3;
}
- fn ccc(self) -> Result<int, int> {
+ fn ccc(&self) -> Result<int, int> {
Ok(3)
}
- fn ddd(self) -> Result<int, int> {
+ fn ddd(&self) -> Result<int, int> {
return Ok(3);
}
}
--- /dev/null
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(unboxed_closures)]
+
+use std::mem;
+
+fn main() {
+ let y = 0u8;
+ let closure = move |&: x| y + x;
+
+ // Check that both closures are capturing by value
+ assert_eq!(1, mem::size_of_val(&closure));
+
+ spawn(proc() {
+ let ok = closure;
+ })
+}
--- /dev/null
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// ignore-pretty
+
+#![feature(unboxed_closures)]
+
+struct Parser<'a, I, O> {
+ parse: Box<FnMut<(I,), Result<O, String>> + 'a>
+}
+
+impl<'a, I, O: 'a> Parser<'a, I, O> {
+ fn compose<K: 'a>(mut self, mut rhs: Parser<O, K>) -> Parser<'a, I, K> {
+ Parser {
+ parse: box move |&mut: x: I| {
+ match self.parse.call_mut((x,)) {
+ Ok(r) => rhs.parse.call_mut((r,)),
+ Err(e) => Err(e)
+ }
+ }
+ }
+ }
+}
+
+fn main() {}
--- /dev/null
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Test that astconv doesn't forget about mutability of &mut str
+
+fn main() {
+ fn foo<Sized? T>(_: &mut T) {}
+ let _f: fn(&mut str) = foo;
+}
+++ /dev/null
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-static X: uint = 0 as *const uint as uint;
-
-fn main() {
- assert_eq!(X, 0);
-}
--- /dev/null
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+const X: &'static str = "12345";
+
+fn test(s: String) -> bool {
+ match s.as_slice() {
+ X => true,
+ _ => false
+ }
+}
+
+fn main() {
+ assert!(test("12345".to_string()));
+}
impl<A> foo<A> {
pub fn bar<B,C:clam<A>>(&self, _c: C) -> B {
- fail!();
+ panic!();
}
}
struct foo(int);
impl foo {
- pub fn bar<B,C:clam<B>>(&self, _c: C) -> B { fail!(); }
+ pub fn bar<B,C:clam<B>>(&self, _c: C) -> B { panic!(); }
}
pub fn main() { }
}
impl A for E {
- fn b<F,G>(_x: F) -> F { fail!() }
+ fn b<F,G>(_x: F) -> F { panic!() }
//~^ ERROR in method `b`, type parameter 0 has 1 bound, but
}
}
mod rusti {
- pub fn atomic_xchg(_dst: &mut int, _src: int) -> int { fail!(); }
- pub fn atomic_xchg_acq(_dst: &mut int, _src: int) -> int { fail!(); }
- pub fn atomic_xchg_rel(_dst: &mut int, _src: int) -> int { fail!(); }
+ pub fn atomic_xchg(_dst: &mut int, _src: int) -> int { panic!(); }
+ pub fn atomic_xchg_acq(_dst: &mut int, _src: int) -> int { panic!(); }
+ pub fn atomic_xchg_rel(_dst: &mut int, _src: int) -> int { panic!(); }
}
// We should consider moving this to ::std::unsafe, although I
// The receiver will eventually clean this up.
unsafe { forget(p); }
}
- full => { fail!("duplicate send") }
+ full => { panic!("duplicate send") }
blocked => {
// The receiver will eventually clean this up.
}
full => {
// This is impossible
- fail!("you dun goofed")
+ panic!("you dun goofed")
}
terminated => {
// I have to clean up, use drop_glue
}
blocked => {
// this shouldn't happen.
- fail!("terminating a blocked packet")
+ panic!("terminating a blocked packet")
}
terminated | full => {
// I have to clean up, use drop_glue
let _addr : *const ::pipes::send_packet<pong> = match &p {
&ping(ref x) => { mem::transmute(x) }
};
- fail!()
+ panic!()
}
}
let _addr : *const ::pipes::send_packet<ping> = match &p {
&pong(ref x) => { mem::transmute(x) }
};
- fail!()
+ panic!()
}
}
pub fn do_pong(c: pong) -> (ping, ()) {
let packet = ::pipes::recv(c);
if packet.is_none() {
- fail!("sender closed the connection")
+ panic!("sender closed the connection")
}
(pingpong::liberate_pong(packet.unwrap()), ())
}
pub fn do_ping(c: ping) -> (pong, ()) {
let packet = ::pipes::recv(c);
if packet.is_none() {
- fail!("sender closed the connection")
+ panic!("sender closed the connection")
}
(pingpong::liberate_ping(packet.unwrap()), ())
}
' ' => { empty }
_ => {
println!("invalid square: {}", c);
- fail!()
+ panic!()
}
}
}
match BadChar {
_ if true => BadChar,
- BadChar | BadSyntax => fail!() ,
+ BadChar | BadSyntax => panic!() ,
};
}
let doc = json::from_str("").unwrap();
let mut decoder = json::Decoder::new(doc);
let _v: T = Decodable::decode(&mut decoder).unwrap();
- fail!()
+ panic!()
}
pub fn main() {}
let v = match io.read_char() {
'$' => parse_bulk(io),
':' => parse_int(io),
- _ => fail!()
+ _ => panic!()
};
list.push(v);
}
priv fn parse_bulk(io: @io::Reader) -> Result {
match from_str::<int>(chop(io.read_line())) {
- None => fail!(),
+ None => panic!(),
Some(-1) => Nil,
Some(len) if len >= 0 => parse_data(len as uint, io),
- Some(_) => fail!()
+ Some(_) => panic!()
}
}
priv fn parse_multi(io: @io::Reader) -> Result {
match from_str::<int>(chop(io.read_line())) {
- None => fail!(),
+ None => panic!(),
Some(-1) => Nil,
Some(0) => List(~[]),
Some(len) if len >= 0 => parse_list(len as uint, io),
- Some(_) => fail!()
+ Some(_) => panic!()
}
}
priv fn parse_int(io: @io::Reader) -> Result {
match from_str::<int>(chop(io.read_line())) {
- None => fail!(),
+ None => panic!(),
Some(i) => Int(i)
}
}
'+' => Status(chop(io.read_line())),
'-' => Error(chop(io.read_line())),
':' => parse_int(io),
- _ => fail!()
+ _ => panic!()
}
}
fn bar(a: foo::map) {
if false {
- fail!();
+ panic!();
} else {
let _b = &(*a)[2];
}
impl<E> Graph<int, E> for HashMap<int, int> {
fn f(&self, _e: E) {
- fail!();
+ panic!();
}
}
fn main() {
match Baz {
- ::Bar(3) => fail!(),
- ::Bar(_) if false => fail!(),
- ::Bar(..) if false => fail!(),
- ::Bar(_n) => fail!(),
+ ::Bar(3) => panic!(),
+ ::Bar(_) if false => panic!(),
+ ::Bar(..) if false => panic!(),
+ ::Bar(_n) => panic!(),
::Baz => {}
}
match Bar(3) {
::Bar(3) => {}
- ::Bar(_) if false => fail!(),
- ::Bar(..) if false => fail!(),
- ::Bar(_n) => fail!(),
- ::Baz => fail!(),
+ ::Bar(_) if false => panic!(),
+ ::Bar(..) if false => panic!(),
+ ::Bar(_n) => panic!(),
+ ::Baz => panic!(),
}
match Bar(4) {
- ::Bar(3) => fail!(),
- ::Bar(_) if false => fail!(),
- ::Bar(..) if false => fail!(),
+ ::Bar(3) => panic!(),
+ ::Bar(_) if false => panic!(),
+ ::Bar(..) if false => panic!(),
::Bar(n) => assert_eq!(n, 4),
- ::Baz => fail!(),
+ ::Baz => panic!(),
}
match Other1(Baz) {
pub fn main() {
let e = Foo{f: 0};
match e {
- Foo{f: 1} => fail!(),
+ Foo{f: 1} => panic!(),
Foo{..} => (),
- _ => fail!(),
+ _ => panic!(),
}
}
pub fn main() {
let e = Foo{f: 0, b: false};
match e {
- Foo{f: 1, b: true} => fail!(),
+ Foo{f: 1, b: true} => panic!(),
Foo{b: false, f: 0} => (),
- _ => fail!(),
+ _ => panic!(),
}
}
let r = f(s);
return (r);
}
- fail!();
+ panic!();
}
fn apply<T>(s: String, f: |String| -> T) -> T {
pub fn main() {
if log_enabled!(log::DEBUG) {
- fail!("what?! debugging?");
+ panic!("what?! debugging?");
}
}
pub fn main() {
if log_enabled!(log::DEBUG) {
- fail!("what?! debugging?");
+ panic!("what?! debugging?");
}
if !log_enabled!(log::INFO) {
- fail!("what?! no info?");
+ panic!("what?! no info?");
}
}
// monomorphized functions from other crates had logging turned on (their
// logging module names were all incorrect). This test ensures that this no
// longer happens by enabling logging for *this* crate and then invoking a
-// function in an external crate which will fail when logging is enabled.
+// function in an external crate which will panic when logging is enabled.
extern crate logging_right_crate;
pub fn main() {
- // this function fails if logging is turned on
+ // this function panicks if logging is turned on
logging_right_crate::foo::<int>();
}
impl Drop for S { fn drop(&mut self) { } }
// user-defined function "returning" bottom (i.e. no return at all).
-fn my_fail() -> ! { loop {} }
+fn my_panic() -> ! { loop {} }
pub fn step(f: bool) {
let mut g = S;
continue;
}
- my_fail();
+ my_panic();
// we never get here, so we do not need to re-initialize g.
}
Some($pat) => {
$res
}
- _ => { fail!(); }
+ _ => { panic!(); }
}
})
// except according to those terms.
// n.b. This was only ever failing with optimization disabled.
-fn a() -> int { match return 1i { 2i => 3i, _ => fail!() } }
+fn a() -> int { match return 1i { 2i => 3i, _ => panic!() } }
pub fn main() { a(); }
pub fn main() {
let i: int =
- match Some::<int>(3) { None::<int> => { fail!() } Some::<int>(_) => { 5 } };
+ match Some::<int>(3) { None::<int> => { panic!() } Some::<int>(_) => { 5 } };
println!("{}", i);
}
pub fn main() {
let e = Bar;
match e {
- Foo{f: _f} => fail!(),
+ Foo{f: _f} => panic!(),
_ => (),
}
}
let e = Foo{f: 1};
match e {
Foo{..} => (),
- _ => fail!(),
+ _ => panic!(),
}
match e {
Foo{f: _f} => (),
- _ => fail!(),
+ _ => panic!(),
}
}
match f {
10 => { println!("case 10"); return 20; }
11 => { println!("case 11"); return 22; }
- _ => fail!("the impossible happened")
+ _ => panic!("the impossible happened")
}
}
assert_eq!(a, "a".to_string());
assert_eq!(b, "b".to_string());
},
- _ => fail!(),
+ _ => panic!(),
}
}
assert_eq!(a, 2);
assert_eq!(b, 3);
},
- _ => fail!(),
+ _ => panic!(),
}
}
assert_eq!(*a, 2);
assert_eq!(*b, 3);
},
- _ => fail!(),
+ _ => panic!(),
}
}
assert_eq!(a, 2);
assert_eq!(b, 3);
},
- _ => fail!(),
+ _ => panic!(),
}
}
assert_eq!(*a, 2);
assert_eq!(*b, 3);
},
- _ => fail!(),
+ _ => panic!(),
}
}
pub fn main() {
match 5u {
1u...5u => {}
- _ => fail!("should match range"),
+ _ => panic!("should match range"),
}
match 5u {
- 6u...7u => fail!("shouldn't match range"),
+ 6u...7u => panic!("shouldn't match range"),
_ => {}
}
match 5u {
- 1u => fail!("should match non-first range"),
+ 1u => panic!("should match non-first range"),
2u...6u => {}
- _ => fail!("math is broken")
+ _ => panic!("math is broken")
}
match 'c' {
'a'...'z' => {}
- _ => fail!("should suppport char ranges")
+ _ => panic!("should suppport char ranges")
}
match -3i {
-7...5 => {}
- _ => fail!("should match signed range")
+ _ => panic!("should match signed range")
}
match 3.0f64 {
1.0...5.0 => {}
- _ => fail!("should match float range")
+ _ => panic!("should match float range")
}
match -1.5f64 {
-3.6...3.6 => {}
- _ => fail!("should match negative float range")
+ _ => panic!("should match negative float range")
}
}
Some(ref z) if *z.lock() => {
assert!(*z.lock());
},
- _ => fail!()
+ _ => panic!()
}
}
}
// Issue #53
pub fn main() {
- match "test" { "not-test" => fail!(), "test" => (), _ => fail!() }
+ match "test" { "not-test" => panic!(), "test" => (), _ => panic!() }
enum t { tag1(String), tag2, }
match tag1("test".to_string()) {
- tag2 => fail!(),
- tag1(ref s) if "test" != s.as_slice() => fail!(),
+ tag2 => panic!(),
+ tag1(ref s) if "test" != s.as_slice() => panic!(),
tag1(ref s) if "test" == s.as_slice() => (),
- _ => fail!()
+ _ => panic!()
}
- let x = match "a" { "a" => 1i, "b" => 2i, _ => fail!() };
+ let x = match "a" { "a" => 1i, "b" => 2i, _ => panic!() };
assert_eq!(x, 1);
- match "a" { "a" => { } "b" => { }, _ => fail!() }
+ match "a" { "a" => { } "b" => { }, _ => panic!() }
}
pub fn main() {
let f = Foo{f: 1};
match f {
- Foo{f: 0} => fail!(),
+ Foo{f: 0} => panic!(),
Foo{..} => (),
}
match f {
- Foo{f: 0} => fail!(),
+ Foo{f: 0} => panic!(),
Foo{f: _f} => (),
}
match f {
- Foo{f: 0} => fail!(),
+ Foo{f: 0} => panic!(),
_ => (),
}
}
pub fn main() {
match -5i {
-5 => {}
- _ => { fail!() }
+ _ => { panic!() }
}
}
/* This test checks that nested comments are supported
/*
- This should not fail
+ This should not panic
*/
*/
}
}
- // fn b(x:int) -> int { fail!(); }
+ // fn b(x:int) -> int { panic!(); }
let z = b(42);
assert_eq!(z.i, 42);
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-fn baz() -> ! { fail!(); }
+fn baz() -> ! { panic!(); }
fn foo() {
match Some::<int>(5) {
fn nested(o: t) {
match o {
- bar(_i, Some::<int>(_)) => { println!("wrong pattern matched"); fail!(); }
+ bar(_i, Some::<int>(_)) => { println!("wrong pattern matched"); panic!(); }
_ => { println!("succeeded"); }
}
}
fn main() {
task::try::<()>(proc() {
let _a = A;
- fail!();
+ panic!();
});
assert!(unsafe { !HIT });
}
}
fn get_ref(&self) -> (int, &T) {
match *self {
- Nothing(..) => fail!("E::get_ref(Nothing::<{}>)", stringify!(T)),
+ Nothing(..) => panic!("E::get_ref(Nothing::<{}>)", stringify!(T)),
Thing(x, ref y) => (x, y)
}
}
let t_ = Thing::<$T>(23, e);
match t_.get_ref() {
(23, $v) => { $chk }
- _ => fail!("Thing::<{}>(23, {}).get_ref() != (23, _)",
+ _ => panic!("Thing::<{}>(23, {}).get_ref() != (23, _)",
stringify!($T), stringify!($e))
}
}}
fn unwrap<T>(o: Option<T>) -> T {
match o {
Some(v) => v,
- None => fail!()
+ None => panic!()
}
}
--- /dev/null
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+pub struct Foo {
+ f1: int,
+ _f2: int,
+}
+
+#[inline(never)]
+pub fn foo(f: &mut Foo) -> Foo {
+ let ret = *f;
+ f.f1 = 0;
+ ret
+}
+
+pub fn main() {
+ let mut f = Foo {
+ f1: 8,
+ _f2: 9,
+ };
+ f = foo(&mut f);
+ assert_eq!(f.f1, 8);
+}
return &pair.value
}
}
- fail!("No value found for key: {}", index);
+ panic!("No value found for key: {}", index);
}
}
let mut_s = Rc::new(RefCell::new(String::from_str("foo")));
mut_s.borrow_mut().push_str("bar");
- // HACK assert_eq! would fail here because it stores the LHS and RHS in two locals.
+ // HACK assert_eq! would panic here because it stores the LHS and RHS in two locals.
assert!(mut_s.borrow().as_slice() == "foobar");
assert!(mut_s.borrow_mut().as_slice() == "foobar");
let mut_s = Rc::new(RefCell::new(String::from_str("foo")));
(*(*mut_s).borrow_mut()).push_str("bar");
- // assert_eq! would fail here because it stores the LHS and RHS in two locals.
+ // assert_eq! would panic here because it stores the LHS and RHS in two locals.
assert!((*(*mut_s).borrow()).as_slice() == "foobar");
assert!((*(*mut_s).borrow_mut()).as_slice() == "foobar");
#![allow(unreachable_code)]
-fn dont_call_me() { fail!(); println!("{}", 1i); }
+fn dont_call_me() { panic!(); println!("{}", 1i); }
pub fn main() { }
drop(p.stdin.take());
match p.wait().unwrap() {
process::ExitStatus(..) => {}
- process::ExitSignal(..) => fail!()
+ process::ExitSignal(..) => panic!()
}
}
let ascend = ascend.as_mut_slice();
static ALIGN : uint = 1;
- // Checks that `ascend` forms triangle of acending size formed
+ // Checks that `ascend` forms triangle of ascending size formed
// from pairs of rows (where each pair of rows is equally sized),
// and the elements of the triangle match their row-pair index.
unsafe fn sanity_check(ascend: &[*mut u8]) {
// A very limited test of the "bottom" region
-fn produce_static<T>() -> &'static T { fail!(); }
+fn produce_static<T>() -> &'static T { panic!(); }
fn foo<T>(_x: &T) -> &uint { produce_static() }
fn get_v6_a(a: &A, _i: uint) -> &int {
match a.value.v6 {
Some(ref v) => &v.f,
- None => fail!()
+ None => panic!()
}
}
fn get_v6_b(a: &A, _i: uint) -> &int {
match *a {
A { value: B { v6: Some(ref v), .. } } => &v.f,
- _ => fail!()
+ _ => panic!()
}
}
fn get_v6_c(a: &A, _i: uint) -> &int {
match a {
&A { value: B { v6: Some(ref v), .. } } => &v.f,
- _ => fail!()
+ _ => panic!()
}
}
fn car<'m>(&'m self) -> int {
match self {
&Cons(car, _) => car,
- &Null => fail!(),
+ &Null => panic!(),
}
}
fn cdr<'n>(&'n self) -> &'l List<'l> {
match self {
&Cons(_, cdr) => cdr,
- &Null => fail!(),
+ &Null => panic!(),
}
}
}
fn get<T>(opt: &Option<T>) -> &T {
match *opt {
Some(ref v) => v,
- None => fail!("none")
+ None => panic!("none")
}
}
-fn my_err(s: String) -> ! { println!("{}", s); fail!(); }
+fn my_err(s: String) -> ! { println!("{}", s); panic!(); }
fn okay(i: uint) -> int {
if i == 3u {
unsafe { calls += 1 }
if n >= 0 { return; }
- fail!()
+ panic!()
};
return_works(10);
unsafe { calls += 1 }
if n >= 0 { return; }
- fail!()
+ panic!()
};
return_works_proc(10);
1 => {}
2 => println!("foo"),
3 => assert!(try(|| {}).is_ok()),
- 4 => assert!(try(|| fail!()).is_err()),
+ 4 => assert!(try(|| panic!()).is_err()),
5 => assert!(try(|| spawn(proc() {})).is_err()),
6 => assert!(Command::new("test").spawn().is_err()),
7 => assert!(foo.get().is_none()),
8 => assert!(try(|| { foo.replace(Some(3)); }).is_err()),
- _ => fail!()
+ _ => panic!()
}
}
return 0
mod a {
pub fn f() {
- fail!();
+ panic!();
}
}
match status {
ExitSignal(_) if cfg!(unix) => {},
ExitStatus(0xC0000028) if cfg!(windows) => {},
- _ => fail!("invalid termination (was not signalled): {}", status)
+ _ => panic!("invalid termination (was not signalled): {}", status)
}
}
}
a::<T>(ref _t, ref u) => {
println!("incorrect");
println!("{}", u);
- fail!();
+ panic!();
}
b::<T> => { println!("correct"); }
}
}
fn bar() -> uint {
- fail!();
+ panic!();
}
fn foo() {
#[lang = "stack_exhausted"] extern fn stack_exhausted() {}
#[lang = "eh_personality"] extern fn eh_personality() {}
-#[lang = "fail_fmt"] fn fail_fmt() -> ! { loop {} }
+#[lang = "panic_fmt"] fn panic_fmt() -> ! { loop {} }
#[start]
#[no_stack_check]
pub fn main() {
// check
- if ! cfg!(foo) { fail!() }
- if cfg!(not(foo)) { fail!() }
+ if ! cfg!(foo) { panic!() }
+ if cfg!(not(foo)) { panic!() }
- if ! cfg!(qux="foo") { fail!() }
- if cfg!(not(qux="foo")) { fail!() }
+ if ! cfg!(qux="foo") { panic!() }
+ if cfg!(not(qux="foo")) { panic!() }
- if ! cfg!(all(foo, qux="foo")) { fail!() }
- if cfg!(not(all(foo, qux="foo"))) { fail!() }
- if cfg!(all(not(all(foo, qux="foo")))) { fail!() }
+ if ! cfg!(all(foo, qux="foo")) { panic!() }
+ if cfg!(not(all(foo, qux="foo"))) { panic!() }
+ if cfg!(all(not(all(foo, qux="foo")))) { panic!() }
- if cfg!(not_a_cfg) { fail!() }
- if cfg!(all(not_a_cfg, foo, qux="foo")) { fail!() }
- if cfg!(all(not_a_cfg, foo, qux="foo")) { fail!() }
- if ! cfg!(any(not_a_cfg, foo)) { fail!() }
+ if cfg!(not_a_cfg) { panic!() }
+ if cfg!(all(not_a_cfg, foo, qux="foo")) { panic!() }
+ if cfg!(all(not_a_cfg, foo, qux="foo")) { panic!() }
+ if ! cfg!(any(not_a_cfg, foo)) { panic!() }
- if ! cfg!(not(not_a_cfg)) { fail!() }
- if ! cfg!(all(not(not_a_cfg), foo, qux="foo")) { fail!() }
+ if ! cfg!(not(not_a_cfg)) { panic!() }
+ if ! cfg!(all(not(not_a_cfg), foo, qux="foo")) { panic!() }
}
let stderr = ChanWriter::new(tx);
let res = TaskBuilder::new().stderr(box stderr as Box<Writer + Send>).try(proc() -> () {
- fail!("Hello, world!")
+ panic!("Hello, world!")
});
assert!(res.is_err());
}
}
Err(ref e) if e.kind == EndOfFile => break,
- Err(e) => fail!("{}", e),
+ Err(e) => panic!("{}", e),
}
}
srv_tx.send(());
// wait for senders
if cli_rx.iter().take(N).count() != N {
a.close_accept().unwrap();
- fail!("clients failed");
+ panic!("clients panicked");
}
// wait for one acceptor to die
match TcpStream::connect_timeout(addr, Duration::milliseconds(100)) {
Ok(e) => v.push(e),
Err(ref e) if e.kind == io::TimedOut => return,
- Err(e) => fail!("other error: {}", e),
+ Err(e) => panic!("other error: {}", e),
}
}
- fail!("never timed out!");
+ panic!("never timed out!");
}
fn timeout_success() {
let mut stream = match acceptor.accept() {
Ok(stream) => stream,
Err(error) => {
- debug!("accept failed: {}", error);
+ debug!("accept panicked: {}", error);
continue;
}
};
let f: proc():Send = proc() {
let tmp = TempDir::new("test_rm_tempdir").unwrap();
tx.send(tmp.path().clone());
- fail!("fail to unwind past `tmp`");
+ panic!("panic to unwind past `tmp`");
};
task::try(f);
let path = rx.recv();
let path = tmp.path().clone();
let f: proc():Send = proc() {
let _tmp = tmp;
- fail!("fail to unwind past `tmp`");
+ panic!("panic to unwind past `tmp`");
};
task::try(f);
assert!(!path.exists());
let tmp = TempDir::new("test_rm_tempdir").unwrap();
tx.send(tmp.path().clone());
tmp.close();
- fail!("fail to unwind past `tmp`");
+ panic!("panic when unwinding past `tmp`");
};
task::try(f);
let path = rx.recv();
let f: proc():Send = proc() {
let tmp = tmp;
tmp.close();
- fail!("fail to unwind past `tmp`");
+ panic!("panic when unwinding past `tmp`");
};
task::try(f);
assert!(!path.exists());
assert!(!root.join("bar").join("blat").exists());
}
-pub fn dont_double_fail() {
+pub fn dont_double_panic() {
let r: Result<(), _> = task::try(proc() {
let tmpdir = TempDir::new("test").unwrap();
// Remove the temporary directory so that TempDir sees
// an error on drop
fs::rmdir(tmpdir.path());
- // Trigger failure. If TempDir fails *again* due to the rmdir
+ // Panic. If TempDir panics *again* due to the rmdir
// error then the process will abort.
- fail!();
+ panic!();
});
assert!(r.is_err());
}
in_tmpdir(recursive_mkdir_dot);
in_tmpdir(recursive_mkdir_rel_2);
in_tmpdir(test_rmdir_recursive_ok);
- in_tmpdir(dont_double_fail);
+ in_tmpdir(dont_double_panic);
}
fn test_ret() { let _x: Box<int> = return; }
-fn test_fail() {
- fn f() { let _x: Box<int> = fail!(); }
+fn test_panic() {
+ fn f() { let _x: Box<int> = panic!(); }
task::try(proc() f() );
}
-fn test_fail_indirect() {
- fn f() -> ! { fail!(); }
+fn test_panic_indirect() {
+ fn f() -> ! { panic!(); }
fn g() { let _x: Box<int> = f(); }
task::try(proc() g() );
}
test_break();
test_cont();
test_ret();
- test_fail();
- test_fail_indirect();
+ test_panic();
+ test_panic_indirect();
}
// Building as a test runner means that a synthetic main will be run,
// not ours
-pub fn main() { fail!(); }
+pub fn main() { panic!(); }
--- /dev/null
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Test that the cache results from the default method do not pollute
+// the cache for the later call in `load()`.
+//
+// See issue #18209.
+
+pub trait Foo {
+ fn load_from() -> Box<Self>;
+ fn load() -> Box<Self> {
+ Foo::load_from()
+ }
+}
+
+pub fn load<M: Foo>() -> Box<M> {
+ Foo::load()
+}
+
+fn main() { }
+++ /dev/null
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// Testing casting of a generic Struct to a Trait with a generic method.
-// This is test for issue 10955.
-#![allow(unused_variable)]
-
-trait Foo {
- fn f<A>(a: A) -> A {
- a
- }
-}
-
-struct Bar<T> {
- x: T,
-}
-
-impl<T> Foo for Bar<T> { }
-
-pub fn main() {
- let a = Bar { x: 1u };
- let b = &a as &Foo;
-}
assert_eq!(g(0i, 3.14f64, 1i), (3.14f64, 1i));
assert_eq!(g(false, 3.14f64, 1i), (3.14, 1));
- let obj = box 0i as Box<A>;
- assert_eq!(obj.h(), 11);
-
// Trying out a real one
assert!(12i.test_neq(&10i));
pub fn main() {
match default_instance() {
&Request { foo: TestNone, bar: 17 } => {},
- _ => fail!(),
+ _ => panic!(),
};
match non_default_instance() {
&Request { foo: TestSome(0x1020304050607080), bar: 19 } => {},
- _ => fail!(),
+ _ => panic!(),
};
}
match (a, b) {
(A($id1), A($id2)) => A($e),
(B($id1), B($id2)) => B($e),
- _ => fail!()
+ _ => panic!()
}
}
)
--- /dev/null
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Test that unboxed closures in contexts with free type parameters
+// monomorphize correctly (issue #16791)
+
+#![feature(unboxed_closures)]
+
+fn main(){
+ fn bar<'a, T:'a> (t: T) -> Box<FnOnce<(),T> + 'a> {
+ box move |:| t
+ }
+
+ let f = bar(42u);
+ assert_eq!(f.call_once(()), 42);
+
+ let f = bar("forty-two");
+ assert_eq!(f.call_once(()), "forty-two");
+
+ let x = 42u;
+ let f = bar(&x);
+ assert_eq!(f.call_once(()), &x);
+
+ #[deriving(Show, PartialEq)]
+ struct Foo(uint, &'static str);
+ let x = Foo(42, "forty-two");
+ let f = bar(x);
+ assert_eq!(f.call_once(()), x);
+}
--- /dev/null
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(unboxed_closures)]
+#![deny(unused_mut)]
+
+// Test that mutating a mutable upvar in a capture-by-value unboxed
+// closure does not ice (issue #18238) and marks the upvar as used
+// mutably so we do not get a spurious warning about it not needing to
+// be declared mutable (issue #18336).
+
+fn main() {
+ {
+ let mut x = 0u;
+ move |&mut:| x += 1;
+ }
+ {
+ let mut x = 0u;
+ move |:| x += 1;
+ }
+}
t1(a) {
assert_eq!(a, 10);
}
- _ { fail!(); }
+ _ { panic!(); }
}*/
/*alt x {
box t1(a) {
assert_eq!(a, 10);
}
- _ { fail!(); }
+ _ { panic!(); }
}*/
}
}
fn f(_i: Box<int>) -> Box<int> {
- fail!();
+ panic!();
}
fn simple() {
match box true {
box true => { }
- _ => { fail!(); }
+ _ => { panic!(); }
}
}
impl Drop for Foo {
fn drop(&mut self) {
- fail!("This failure should happen.");
+ panic!("This panic should happen.");
}
}
});
let s = x.unwrap_err().downcast::<&'static str>().unwrap();
- assert_eq!(s.as_slice(), "This failure should happen.");
+ assert_eq!(s.as_slice(), "This panic should happen.");
}
};
match process::Process::spawn(cfg) {
- Ok(_) => { fail!("spawn() should have failled"); }
+ Ok(_) => { panic!("spawn() should have panicked"); }
Err(rtio::IoError { code: err, ..}) => {
assert_eq!(err as c_int, EXPECTED_ERRNO);
}
fn id(x: bool) -> bool { x }
fn call_id() {
- let c = fail!();
+ let c = panic!();
id(c); //~ WARNING unreachable statement
}
fn id(x: bool) -> bool { x }
fn call_id() {
- let c = fail!();
+ let c = panic!();
id(c);
}
fn call_id_3() { id(return) && id(return); }
-fn ret_ret() -> int { return (return 2i) + 3i; }
-
fn ret_guard() {
match 2i {
x if (return) => { x; }
fn f(tx: Sender<bool>) {
let _tx = complainer(tx);
- fail!();
+ panic!();
}
pub fn main() {
fn f() {
let _a = box 0i;
- fail!();
+ panic!();
}
pub fn main() {
fn foo<T>(o: myoption<T>) -> int {
let mut x: int;
match o {
- none::<T> => { fail!(); }
+ none::<T> => { panic!(); }
some::<T>(_t) => { x = 5; }
}
return x;
fn sub_expr() {
// Test for a &[T] => &&[T] coercion in sub-expression position
- // (surpisingly, this can cause errors which are not caused by either of:
+ // (surprisingly, this can cause errors which are not caused by either of:
// `let x = vec.slice_mut(0, 2);`
// `foo(vec.slice_mut(0, 2));` ).
let mut vec: Vec<int> = vec!(1, 2, 3, 4);
pub fn main() {
let x = [1i, 2, 3];
match x {
- [2, _, _] => fail!(),
+ [2, _, _] => panic!(),
[1, a, b] => {
assert!([a, b] == [2, 3]);
}
- [_, _, _] => fail!(),
+ [_, _, _] => panic!(),
}
let y = ([(1i, true), (2i, false)], 0.5f64);
assert_eq!(a, true);
assert_eq!(b, 2);
}
- ([_, _], 0.5) => fail!(),
- ([_, _], _) => fail!(),
+ ([_, _], 0.5) => panic!(),
+ ([_, _], _) => panic!(),
}
}
fn c() {
let x = [1i];
match x {
- [2, ..] => fail!(),
+ [2, ..] => panic!(),
[..] => ()
}
}
let mut count = 0;
main.clone().as_mut_slice().sort_by(|a, b| { count += 1; a.cmp(b) });
- // ... and then fail on each and every single one.
- for fail_countdown in range(0i, count) {
+ // ... and then panic on each and every single one.
+ for panic_countdown in range(0i, count) {
// refresh the counters.
for c in drop_counts.iter() {
c.store(0, Relaxed);
let _ = task::try(proc() {
let mut v = v;
- let mut fail_countdown = fail_countdown;
+ let mut panic_countdown = panic_countdown;
v.as_mut_slice().sort_by(|a, b| {
- if fail_countdown == 0 {
- fail!()
+ if panic_countdown == 0 {
+ panic!()
}
- fail_countdown -= 1;
+ panic_countdown -= 1;
a.cmp(b)
})
});
fn angrydome() {
loop { if break { } }
let mut i = 0i;
- loop { i += 1; if i == 1 { match (continue) { 1i => { }, _ => fail!("wat") } }
+ loop { i += 1; if i == 1 { match (continue) { 1i => { }, _ => panic!("wat") } }
break; }
}
i -= 1;
if i == 95 {
break 'w;
- fail!("Should have broken out of loop");
+ panic!("Should have broken out of loop");
}
}
assert_eq!(i, 95);
Some(ref z) if *z.lock() => {
assert!(*z.lock());
},
- _ => fail!()
+ _ => panic!()
}
}
}