Merge branch 'master' into mulit-decor

This commit is contained in:
Nick Cameron 2015-04-30 22:30:50 +12:00
commit b2ddd937b2
488 changed files with 12552 additions and 7327 deletions

13
configure vendored
View File

@ -551,6 +551,7 @@ opt valgrind-rpass 1 "run rpass-valgrind tests with valgrind"
opt docs 1 "build standard library documentation"
opt compiler-docs 0 "build compiler documentation"
opt optimize-tests 1 "build tests with optimizations"
opt debuginfo-tests 0 "build tests with debugger metadata"
opt libcpp 1 "build with llvm with libc++ instead of libstdc++ when using clang"
opt llvm-assertions 0 "build LLVM with assertions"
opt debug-assertions 0 "build with debugging assertions"
@ -583,6 +584,7 @@ valopt jemalloc-root "" "set directory where libjemalloc_pic.a is located"
valopt build "${DEFAULT_BUILD}" "GNUs ./configure syntax LLVM build triple"
valopt android-cross-path "/opt/ndk_standalone" "Android NDK standalone path"
valopt release-channel "dev" "the name of the release channel to build"
valopt musl-root "/usr/local" "MUSL root installation directory"
# Many of these are saved below during the "writing configuration" step
# (others are conditionally saved).
@ -659,9 +661,10 @@ if [ -n "$CFG_ENABLE_DEBUG" ]; then
CFG_DISABLE_OPTIMIZE=1
CFG_DISABLE_OPTIMIZE_CXX=1
fi
CFG_ENABLE_LLVM_ASSERTIONS=1
CFG_ENABLE_DEBUG_ASSERTIONS=1
CFG_ENABLE_DEBUG_JEMALLOC=1
CFG_ENABLE_DEBUGINFO=1
CFG_ENABLE_LLVM_ASSERTIONS=1
fi
# OK, now write the debugging options
@ -1057,6 +1060,13 @@ do
fi
;;
*-musl)
if [ ! -f $CFG_MUSL_ROOT/lib/libc.a ]
then
err "musl libc $CFG_MUSL_ROOT/lib/libc.a not found"
fi
;;
*)
;;
esac
@ -1143,6 +1153,7 @@ do
make_dir $h/test/run-pass-valgrind
make_dir $h/test/run-pass-fulldeps
make_dir $h/test/run-fail
make_dir $h/test/run-fail-fulldeps
make_dir $h/test/compile-fail
make_dir $h/test/parse-fail
make_dir $h/test/compile-fail-fulldeps

View File

@ -20,16 +20,12 @@ CFG_GCCISH_CFLAGS_aarch64-apple-ios := -Wall -Werror -fPIC $(CFG_IOS_SDK_FLAGS_a
CFG_GCCISH_CXXFLAGS_aarch64-apple-ios := -fno-rtti $(CFG_IOS_SDK_FLAGS_aarch64-apple-ios) -I$(CFG_IOS_SDK_aarch64-apple-ios)/usr/include/c++/4.2.1
CFG_GCCISH_LINK_FLAGS_aarch64-apple-ios := -lpthread -syslibroot $(CFG_IOS_SDK_aarch64-apple-ios) -Wl,-no_compact_unwind
CFG_GCCISH_DEF_FLAG_aarch64-apple-ios := -Wl,-exported_symbols_list,
CFG_GCCISH_PRE_LIB_FLAGS_aarch64-apple-ios :=
CFG_GCCISH_POST_LIB_FLAGS_aarch64-apple-ios :=
CFG_DEF_SUFFIX_aarch64-apple-ios := .darwin.def
CFG_LLC_FLAGS_aarch64-apple-ios := -mattr=+neon,+cyclone,+fp-armv8
CFG_INSTALL_NAME_aarch64-apple-ios = -Wl,-install_name,@rpath/$(1)
CFG_LIBUV_LINK_FLAGS_aarch64-apple-ios =
CFG_EXE_SUFFIX_aarch64-apple-ios :=
CFG_WINDOWSY_aarch64-apple-ios :=
CFG_UNIXY_aarch64-apple-ios := 1
CFG_PATH_MUNGE_aarch64-apple-ios := true
CFG_LDPATH_aarch64-apple-ios :=
CFG_RUN_aarch64-apple-ios = $(2)
CFG_RUN_TARG_aarch64-apple-ios = $(call CFG_RUN_aarch64-apple-ios,,$(2))

View File

@ -13,15 +13,11 @@ CFG_GCCISH_CFLAGS_aarch64-linux-android := -Wall -g -fPIC -D__aarch64__ -DANDROI
CFG_GCCISH_CXXFLAGS_aarch64-linux-android := -fno-rtti $(CXXFLAGS)
CFG_GCCISH_LINK_FLAGS_aarch64-linux-android := -shared -fPIC -ldl -g -lm -lsupc++
CFG_GCCISH_DEF_FLAG_aarch64-linux-android := -Wl,--export-dynamic,--dynamic-list=
CFG_GCCISH_PRE_LIB_FLAGS_aarch64-linux-android := -Wl,-whole-archive
CFG_GCCISH_POST_LIB_FLAGS_aarch64-linux-android := -Wl,-no-whole-archive
CFG_DEF_SUFFIX_aarch64-linux-android := .android.def
CFG_LLC_FLAGS_aarch64-linux-android :=
CFG_INSTALL_NAME_aarch64-linux-android =
CFG_EXE_SUFFIX_aarch64-linux-android :=
CFG_WINDOWSY_aarch64-linux-android :=
CFG_UNIXY_aarch64-linux-android := 1
CFG_PATH_MUNGE_aarch64-linux-android := true
CFG_LDPATH_aarch64-linux-android :=
CFG_RUN_aarch64-linux-android=
CFG_RUN_TARG_aarch64-linux-android=

View File

@ -13,15 +13,11 @@ CFG_GCCISH_CFLAGS_aarch64-unknown-linux-gnu := -Wall -g -fPIC -D__aarch64__ $(CF
CFG_GCCISH_CXXFLAGS_aarch64-unknown-linux-gnu := -fno-rtti $(CXXFLAGS)
CFG_GCCISH_LINK_FLAGS_aarch64-unknown-linux-gnu := -shared -fPIC -g
CFG_GCCISH_DEF_FLAG_aarch64-unknown-linux-gnu := -Wl,--export-dynamic,--dynamic-list=
CFG_GCCISH_PRE_LIB_FLAGS_aarch64-unknown-linux-gnu := -Wl,-whole-archive
CFG_GCCISH_POST_LIB_FLAGS_aarch64-unknown-linux-gnu := -Wl,-no-whole-archive
CFG_DEF_SUFFIX_aarch64-unknown-linux-gnu := .linux.def
CFG_LLC_FLAGS_aarch64-unknown-linux-gnu :=
CFG_INSTALL_NAME_aarch64-unknown-linux-gnu =
CFG_EXE_SUFFIX_aarch64-unknown-linux-gnu :=
CFG_WINDOWSY_aarch64-unknown-linux-gnu :=
CFG_UNIXY_aarch64-unknown-linux-gnu := 1
CFG_PATH_MUNGE_aarch64-unknown-linux-gnu := true
CFG_LDPATH_aarch64-unknown-linux-gnu :=
CFG_RUN_aarch64-unknown-linux-gnu=$(2)
CFG_RUN_TARG_aarch64-unknown-linux-gnu=$(call CFG_RUN_aarch64-unknown-linux-gnu,,$(2))

View File

@ -12,15 +12,11 @@ CFG_GCCISH_CFLAGS_arm-linux-androideabi := -Wall -g -fPIC -D__arm__ -DANDROID -D
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=

View File

@ -13,15 +13,11 @@ CFG_GCCISH_CFLAGS_arm-unknown-linux-gnueabi := -Wall -g -fPIC -D__arm__ -mfpu=vf
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))

View File

@ -13,15 +13,11 @@ CFG_GCCISH_CFLAGS_arm-unknown-linux-gnueabihf := -Wall -g -fPIC -D__arm__ $(CFLA
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))

View File

@ -19,15 +19,11 @@ CFG_GCCISH_CFLAGS_armv7-apple-ios := -Wall -Werror -g -fPIC $(CFG_IOS_SDK_FLAGS_
CFG_GCCISH_CXXFLAGS_armv7-apple-ios := -fno-rtti $(CFG_IOS_SDK_FLAGS_armv7-apple-ios) -I$(CFG_IOS_SDK_armv7-apple-ios)/usr/include/c++/4.2.1
CFG_GCCISH_LINK_FLAGS_armv7-apple-ios := -lpthread -syslibroot $(CFG_IOS_SDK_armv7-apple-ios) -Wl,-no_compact_unwind
CFG_GCCISH_DEF_FLAG_armv7-apple-ios := -Wl,-exported_symbols_list,
CFG_GCCISH_PRE_LIB_FLAGS_armv7-apple-ios :=
CFG_GCCISH_POST_LIB_FLAGS_armv7-apple-ios :=
CFG_DEF_SUFFIX_armv7-apple-ios := .darwin.def
CFG_LLC_FLAGS_armv7-apple-ios := -mattr=+vfp3,+v7,+neon -march=arm
CFG_INSTALL_NAME_armv7-apple-ios = -Wl,-install_name,@rpath/$(1)
CFG_EXE_SUFFIX_armv7-apple-ios :=
CFG_WINDOWSY_armv7-apple-ios :=
CFG_UNIXY_armv7-apple-ios := 1
CFG_PATH_MUNGE_armv7-apple-ios := true
CFG_LDPATH_armv7-apple-ios :=
CFG_RUN_armv7-apple-ios = $(2)
CFG_RUN_TARG_armv7-apple-ios = $(call CFG_RUN_armv7-apple-ios,,$(2))

View File

@ -19,15 +19,11 @@ CFG_GCCISH_CFLAGS_armv7s-apple-ios := -Wall -Werror -g -fPIC $(CFG_IOS_SDK_FLAGS
CFG_GCCISH_CXXFLAGS_armv7s-apple-ios := -fno-rtti $(CFG_IOS_SDK_FLAGS_armv7s-apple-ios) -I$(CFG_IOS_SDK_armv7s-apple-ios)/usr/include/c++/4.2.1
CFG_GCCISH_LINK_FLAGS_armv7s-apple-ios := -lpthread -syslibroot $(CFG_IOS_SDK_armv7s-apple-ios) -Wl,-no_compact_unwind
CFG_GCCISH_DEF_FLAG_armv7s-apple-ios := -Wl,-exported_symbols_list,
CFG_GCCISH_PRE_LIB_FLAGS_armv7s-apple-ios :=
CFG_GCCISH_POST_LIB_FLAGS_armv7s-apple-ios :=
CFG_DEF_SUFFIX_armv7s-apple-ios := .darwin.def
CFG_LLC_FLAGS_armv7s-apple-ios := -mattr=+vfp4,+v7,+neon
CFG_INSTALL_NAME_armv7s-apple-ios = -Wl,-install_name,@rpath/$(1)
CFG_EXE_SUFFIX_armv7s-apple-ios :=
CFG_WINDOWSY_armv7s-apple-ios :=
CFG_UNIXY_armv7s-apple-ios := 1
CFG_PATH_MUNGE_armv7s-apple-ios := true
CFG_LDPATH_armv7s-apple-ios :=
CFG_RUN_armv7s-apple-ios = $(2)
CFG_RUN_TARG_armv7s-apple-ios = $(call CFG_RUN_armv7s-apple-ios,,$(2))

View File

@ -18,15 +18,11 @@ CFG_GCCISH_CFLAGS_i386-apple-ios := -Wall -Werror -g -fPIC -m32 $(CFG_IOSSIM_FLA
CFG_GCCISH_CXXFLAGS_i386-apple-ios := -fno-rtti $(CFG_IOSSIM_FLAGS_i386-apple-ios) -I$(CFG_IOSSIM_SDK_i386-apple-ios)/usr/include/c++/4.2.1
CFG_GCCISH_LINK_FLAGS_i386-apple-ios := -lpthread -m32 -Wl,-no_compact_unwind -m32 -Wl,-syslibroot $(CFG_IOSSIM_SDK_i386-apple-ios)
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))

View File

@ -12,15 +12,11 @@ CFG_GCCISH_CFLAGS_i686-apple-darwin := -Wall -Werror -g -fPIC -m32 -arch i386 $(
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))

View File

@ -13,15 +13,11 @@ CFG_GCCISH_CFLAGS_i686-pc-windows-gnu := -Wall -Werror -g -m32 -D_WIN32_WINNT=0x
CFG_GCCISH_CXXFLAGS_i686-pc-windows-gnu := -fno-rtti $(CXXFLAGS)
CFG_GCCISH_LINK_FLAGS_i686-pc-windows-gnu := -shared -g -m32
CFG_GCCISH_DEF_FLAG_i686-pc-windows-gnu :=
CFG_GCCISH_PRE_LIB_FLAGS_i686-pc-windows-gnu :=
CFG_GCCISH_POST_LIB_FLAGS_i686-pc-windows-gnu :=
CFG_DEF_SUFFIX_i686-pc-windows-gnu := .windows.def
CFG_LLC_FLAGS_i686-pc-windows-gnu :=
CFG_INSTALL_NAME_i686-pc-windows-gnu =
CFG_EXE_SUFFIX_i686-pc-windows-gnu := .exe
CFG_WINDOWSY_i686-pc-windows-gnu := 1
CFG_UNIXY_i686-pc-windows-gnu :=
CFG_PATH_MUNGE_i686-pc-windows-gnu :=
CFG_LDPATH_i686-pc-windows-gnu :=
CFG_RUN_i686-pc-windows-gnu=$(2)
CFG_RUN_TARG_i686-pc-windows-gnu=$(call CFG_RUN_i686-pc-windows-gnu,,$(2))

View File

@ -12,15 +12,11 @@ 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))

View File

@ -12,15 +12,11 @@ CFG_GCCISH_CFLAGS_mips-unknown-linux-gnu := -Wall -g -fPIC -mips32r2 -msoft-floa
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=

View File

@ -12,15 +12,11 @@ CFG_GCCISH_CFLAGS_mipsel-unknown-linux-gnu := -Wall -g -fPIC -mips32 -mabi=32 $(
CFG_GCCISH_CXXFLAGS_mipsel-unknown-linux-gnu := -fno-rtti $(CXXFLAGS)
CFG_GCCISH_LINK_FLAGS_mipsel-unknown-linux-gnu := -shared -fPIC -g -mips32
CFG_GCCISH_DEF_FLAG_mipsel-unknown-linux-gnu := -Wl,--export-dynamic,--dynamic-list=
CFG_GCCISH_PRE_LIB_FLAGS_mipsel-unknown-linux-gnu := -Wl,-whole-archive
CFG_GCCISH_POST_LIB_FLAGS_mipsel-unknown-linux-gnu := -Wl,-no-whole-archive
CFG_DEF_SUFFIX_mipsel-unknown-linux-gnu := .linux.def
CFG_LLC_FLAGS_mipsel-unknown-linux-gnu :=
CFG_INSTALL_NAME_mipsel-unknown-linux-gnu =
CFG_EXE_SUFFIX_mipsel-unknown-linux-gnu :=
CFG_WINDOWSY_mipsel-unknown-linux-gnu :=
CFG_UNIXY_mipsel-unknown-linux-gnu := 1
CFG_PATH_MUNGE_mipsel-unknown-linux-gnu := true
CFG_LDPATH_mipsel-unknown-linux-gnu :=
CFG_RUN_mipsel-unknown-linux-gnu=
CFG_RUN_TARG_mipsel-unknown-linux-gnu=

View File

@ -13,15 +13,11 @@ CFG_GCCISH_CFLAGS_powerpc-unknown-linux-gnu := -Wall -Werror -g -fPIC -m32 $(CFL
CFG_GCCISH_CXXFLAGS_powerpc-unknown-linux-gnu := -fno-rtti $(CXXFLAGS)
CFG_GCCISH_LINK_FLAGS_powerpc-unknown-linux-gnu := -shared -fPIC -ldl -pthread -lrt -g -m32
CFG_GCCISH_DEF_FLAG_powerpc-unknown-linux-gnu := -Wl,--export-dynamic,--dynamic-list=
CFG_GCCISH_PRE_LIB_FLAGS_powerpc-unknown-linux-gnu := -Wl,-whole-archive
CFG_GCCISH_POST_LIB_FLAGS_powerpc-unknown-linux-gnu := -Wl,-no-whole-archive
CFG_DEF_SUFFIX_powerpc-unknown-linux-gnu := .linux.def
CFG_LLC_FLAGS_powerpc-unknown-linux-gnu :=
CFG_INSTALL_NAME_powerpc-unknown-linux-gnu =
CFG_EXE_SUFFIX_powerpc-unknown-linux-gnu =
CFG_WINDOWSY_powerpc-unknown-linux-gnu :=
CFG_UNIXY_powerpc-unknown-linux-gnu := 1
CFG_PATH_MUNGE_powerpc-unknown-linux-gnu := true
CFG_LDPATH_powerpc-unknown-linux-gnu :=
CFG_RUN_powerpc-unknown-linux-gnu=$(2)
CFG_RUN_TARG_powerpc-unknown-linux-gnu=$(call CFG_RUN_powerpc-unknown-linux-gnu,,$(2))

View File

@ -12,15 +12,11 @@ CFG_GCCISH_CFLAGS_x86_64-apple-darwin := -Wall -Werror -g -fPIC -m64 -arch x86_6
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))

View File

@ -20,16 +20,12 @@ CFG_GCCISH_CFLAGS_x86_64-apple-ios := -Wall -Werror -fPIC $(CFG_IOSSIM_FLAGS_x86
CFG_GCCISH_CXXFLAGS_x86_64-apple-ios := -fno-rtti $(CFG_IOSSIM_FLAGS_x86_64-apple-ios) -I$(CFG_IOSSIM_SDK_x86_64-apple-ios)/usr/include/c++/4.2.1
CFG_GCCISH_LINK_FLAGS_x86_64-apple-ios := -lpthread -Wl,-no_compact_unwind -m64 -Wl,-syslibroot $(CFG_IOSSIM_SDK_x86_64-apple-ios)
CFG_GCCISH_DEF_FLAG_x86_64-apple-ios := -Wl,-exported_symbols_list,
CFG_GCCISH_PRE_LIB_FLAGS_x86_64-apple-ios :=
CFG_GCCISH_POST_LIB_FLAGS_x86_64-apple-ios :=
CFG_DEF_SUFFIX_x86_64-apple-ios := .darwin.def
CFG_LLC_FLAGS_x86_64-apple-ios :=
CFG_INSTALL_NAME_x86_64-apple-ios = -Wl,-install_name,@rpath/$(1)
CFG_LIBUV_LINK_FLAGS_x86_64-apple-ios :=
CFG_EXE_SUFFIX_x86_64-apple-ios :=
CFG_WINDOWSY_x86_64-apple-ios :=
CFG_UNIXY_x86_64-apple-ios := 1
CFG_PATH_MUNGE_x86_64-apple-ios := true
CFG_LDPATH_x86_64-apple-ios :=
CFG_RUN_x86_64-apple-ios = $(2)
CFG_RUN_TARG_x86_64-apple-ios = $(call CFG_RUN_x86_64-apple-ios,,$(2))

View File

@ -13,15 +13,11 @@ CFG_GCCISH_CFLAGS_x86_64-pc-windows-gnu := -Wall -Werror -g -m64 -D_WIN32_WINNT=
CFG_GCCISH_CXXFLAGS_x86_64-pc-windows-gnu := -fno-rtti $(CXXFLAGS)
CFG_GCCISH_LINK_FLAGS_x86_64-pc-windows-gnu := -shared -g -m64
CFG_GCCISH_DEF_FLAG_x86_64-pc-windows-gnu :=
CFG_GCCISH_PRE_LIB_FLAGS_x86_64-pc-windows-gnu :=
CFG_GCCISH_POST_LIB_FLAGS_x86_64-pc-windows-gnu :=
CFG_DEF_SUFFIX_x86_64-pc-windows-gnu := .windows.def
CFG_LLC_FLAGS_x86_64-pc-windows-gnu :=
CFG_INSTALL_NAME_x86_64-pc-windows-gnu =
CFG_EXE_SUFFIX_x86_64-pc-windows-gnu := .exe
CFG_WINDOWSY_x86_64-pc-windows-gnu := 1
CFG_UNIXY_x86_64-pc-windows-gnu :=
CFG_PATH_MUNGE_x86_64-pc-windows-gnu :=
CFG_LDPATH_x86_64-pc-windows-gnu :=
CFG_RUN_x86_64-pc-windows-gnu=$(2)
CFG_RUN_TARG_x86_64-pc-windows-gnu=$(call CFG_RUN_x86_64-pc-windows-gnu,,$(2))

View File

@ -11,15 +11,11 @@ CFG_JEMALLOC_CFLAGS_x86_64-unknown-bitrig := -m64 -I/usr/include $(CFLAGS)
CFG_GCCISH_CFLAGS_x86_64-unknown-bitrig := -Wall -Werror -fPIC -m64 -I/usr/include $(CFLAGS)
CFG_GCCISH_LINK_FLAGS_x86_64-unknown-bitrig := -shared -pic -pthread -m64 $(LDFLAGS)
CFG_GCCISH_DEF_FLAG_x86_64-unknown-bitrig := -Wl,--export-dynamic,--dynamic-list=
CFG_GCCISH_PRE_LIB_FLAGS_x86_64-unknown-bitrig := -Wl,-pic -Wl,-whole-archive
CFG_GCCISH_POST_LIB_FLAGS_x86_64-unknown-bitrig := -Wl,-no-whole-archive
CFG_DEF_SUFFIX_x86_64-unknown-bitrig := .bsd.def
CFG_LLC_FLAGS_x86_64-unknown-bitrig :=
CFG_INSTALL_NAME_x86_64-unknown-bitrig =
CFG_EXE_SUFFIX_x86_64-unknown-bitrig :=
CFG_WINDOWSY_x86_64-unknown-bitrig :=
CFG_UNIXY_x86_64-unknown-bitrig := 1
CFG_PATH_MUNGE_x86_64-unknown-bitrig :=
CFG_LDPATH_x86_64-unknown-bitrig :=
CFG_RUN_x86_64-unknown-bitrig=$(2)
CFG_RUN_TARG_x86_64-unknown-bitrig=$(call CFG_RUN_x86_64-unknown-bitrig,,$(2))

View File

@ -11,15 +11,11 @@ CFG_JEMALLOC_CFLAGS_x86_64-unknown-dragonfly := -m64 -I/usr/include -I/usr/local
CFG_GCCISH_CFLAGS_x86_64-unknown-dragonfly := -Wall -Werror -g -fPIC -m64 -I/usr/include -I/usr/local/include $(CFLAGS)
CFG_GCCISH_LINK_FLAGS_x86_64-unknown-dragonfly := -shared -fPIC -g -pthread -lrt -m64
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))

View File

@ -11,15 +11,11 @@ CFG_JEMALLOC_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))

View File

@ -12,15 +12,11 @@ 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))

View File

@ -0,0 +1,27 @@
# x86_64-unknown-linux-musl configuration
CC_x86_64-unknown-linux-musl=$(CFG_MUSL_ROOT)/bin/musl-gcc
CXX_x86_64-unknown-linux-musl=notaprogram
CPP_x86_64-unknown-linux-musl=$(CFG_MUSL_ROOT)/bin/musl-gcc -E
AR_x86_64-unknown-linux-musl=$(AR)
CFG_LIB_NAME_x86_64-unknown-linux-musl=lib$(1).so
CFG_STATIC_LIB_NAME_x86_64-unknown-linux-musl=lib$(1).a
CFG_LIB_GLOB_x86_64-unknown-linux-musl=lib$(1)-*.so
CFG_JEMALLOC_CFLAGS_x86_64-unknown-linux-musl := -m64
CFG_GCCISH_CFLAGS_x86_64-unknown-linux-musl := -Wall -Werror -g -fPIC -m64
CFG_GCCISH_CXXFLAGS_x86_64-unknown-linux-musl :=
CFG_GCCISH_LINK_FLAGS_x86_64-unknown-linux-musl :=
CFG_GCCISH_DEF_FLAG_x86_64-unknown-linux-musl :=
CFG_LLC_FLAGS_x86_64-unknown-linux-musl :=
CFG_INSTALL_NAME_x86_64-unknown-linux-musl =
CFG_EXE_SUFFIX_x86_64-unknown-linux-musl =
CFG_WINDOWSY_x86_64-unknown-linux-musl :=
CFG_UNIXY_x86_64-unknown-linux-musl := 1
CFG_LDPATH_x86_64-unknown-linux-musl :=
CFG_RUN_x86_64-unknown-linux-musl=$(2)
CFG_RUN_TARG_x86_64-unknown-linux-musl=$(call CFG_RUN_x86_64-unknown-linux-musl,,$(2))
CFG_GNU_TRIPLE_x86_64-unknown-linux-musl := x86_64-unknown-linux-musl
NATIVE_DEPS_libc_T_x86_64-unknown-linux-musl += libc.a
NATIVE_DEPS_std_T_x86_64-unknown-linux-musl += libunwind.a \
crt1.o crti.o crtn.o
INSTALLED_OBJECTS_x86_64-unknown-linux-musl += crt1.o crti.o crtn.o

View File

@ -11,15 +11,11 @@ CFG_JEMALLOC_CFLAGS_x86_64-unknown-openbsd := -m64 -I/usr/include $(CFLAGS)
CFG_GCCISH_CFLAGS_x86_64-unknown-openbsd := -Wall -Werror -g -fPIC -m64 -I/usr/include $(CFLAGS)
CFG_GCCISH_LINK_FLAGS_x86_64-unknown-openbsd := -shared -fPIC -g -pthread -m64
CFG_GCCISH_DEF_FLAG_x86_64-unknown-openbsd := -Wl,--export-dynamic,--dynamic-list=
CFG_GCCISH_PRE_LIB_FLAGS_x86_64-unknown-openbsd := -Wl,-whole-archive
CFG_GCCISH_POST_LIB_FLAGS_x86_64-unknown-openbsd := -Wl,-no-whole-archive
CFG_DEF_SUFFIX_x86_64-unknown-openbsd := .bsd.def
CFG_LLC_FLAGS_x86_64-unknown-openbsd :=
CFG_INSTALL_NAME_x86_64-unknown-openbsd =
CFG_EXE_SUFFIX_x86_64-unknown-openbsd :=
CFG_WINDOWSY_x86_64-unknown-openbsd :=
CFG_UNIXY_x86_64-unknown-openbsd := 1
CFG_PATH_MUNGE_x86_64-unknown-openbsd :=
CFG_LDPATH_x86_64-unknown-openbsd :=
CFG_RUN_x86_64-unknown-openbsd=$(2)
CFG_RUN_TARG_x86_64-unknown-openbsd=$(call CFG_RUN_x86_64-unknown-openbsd,,$(2))

View File

@ -123,6 +123,9 @@ ONLY_RLIB_rustc_bitflags := 1
# Documented-by-default crates
DOC_CRATES := std alloc collections core libc rustc_unicode
# Installed objects/libraries by default
INSTALLED_OBJECTS := libmorestack.a libcompiler-rt.a
################################################################################
# You should not need to edit below this line
################################################################################

View File

@ -399,8 +399,10 @@ endif
# Prerequisites for using the stageN compiler to build target artifacts
TSREQ$(1)_T_$(2)_H_$(3) = \
$$(HSREQ$(1)_H_$(3)) \
$$(TLIB$(1)_T_$(2)_H_$(3))/libmorestack.a \
$$(TLIB$(1)_T_$(2)_H_$(3))/libcompiler-rt.a
$$(foreach obj,$$(INSTALLED_OBJECTS),\
$$(TLIB$(1)_T_$(2)_H_$(3))/$$(obj)) \
$$(foreach obj,$$(INSTALLED_OBJECTS_$(2)),\
$$(TLIB$(1)_T_$(2)_H_$(3))/$$(obj))
# Prerequisites for a working stageN compiler and libraries, for a specific
# target

View File

@ -140,8 +140,8 @@ prepare-target-$(2)-host-$(3)-$(1)-$(4): prepare-maybe-clean-$(4) \
$$(if $$(findstring $(2),$$(CFG_HOST)), \
$$(foreach crate,$$(HOST_CRATES), \
$$(call PREPARE_LIB,$$(call CFG_LIB_GLOB_$(2),$$(crate)))),) \
$$(call PREPARE_LIB,libmorestack.a) \
$$(call PREPARE_LIB,libcompiler-rt.a),),),)
$$(foreach object,$$(INSTALLED_OBJECTS) $$(INSTALLED_OBJECTS_$(2)),\
$$(call PREPARE_LIB,$$(object))),),),)
endef
define INSTALL_GDB_DEBUGGER_SCRIPTS_COMMANDS

View File

@ -74,7 +74,8 @@ $$(RT_OUTPUT_DIR_$(1))/%.o: $(S)src/rt/%.ll $$(MKFILE_DEPS) \
@mkdir -p $$(@D)
@$$(call E, compile: $$@)
$$(Q)$$(LLC_$$(CFG_BUILD)) $$(CFG_LLC_FLAGS_$(1)) \
-filetype=obj -mtriple=$$(CFG_LLVM_TARGET_$(1)) -relocation-model=pic -o $$@ $$<
-filetype=obj -mtriple=$$(CFG_LLVM_TARGET_$(1)) \
-relocation-model=pic -o $$@ $$<
$$(RT_OUTPUT_DIR_$(1))/%.o: $(S)src/rt/%.c $$(MKFILE_DEPS)
@mkdir -p $$(@D)
@ -110,6 +111,11 @@ $$(RT_OUTPUT_DIR_$(1))/$$(NATIVE_$(2)_$(1)): $$(OBJS_$(2)_$(1))
@$$(call E, link: $$@)
$$(Q)$$(AR_$(1)) rcs $$@ $$^
ifeq ($$(findstring windows,$(1)),windows)
$$(RT_OUTPUT_DIR_$(1))/lib$(2).a: $$(RT_OUTPUT_DIR_$(1))/$$(NATIVE_$(2)_$(1))
$$(Q)cp $$^ $$@
endif
endef
$(foreach target,$(CFG_TARGET), \
@ -221,7 +227,7 @@ COMPRT_DEPS := $(wildcard \
$(S)src/compiler-rt/*/*/*/*)
endif
COMPRT_NAME_$(1) := $$(call CFG_STATIC_LIB_NAME_$(1),compiler-rt)
COMPRT_NAME_$(1) := libcompiler-rt.a
COMPRT_LIB_$(1) := $$(RT_OUTPUT_DIR_$(1))/$$(COMPRT_NAME_$(1))
COMPRT_BUILD_DIR_$(1) := $$(RT_OUTPUT_DIR_$(1))/compiler-rt
@ -312,6 +318,19 @@ endif # endif for windowsy
endif # endif for ios
endif # endif for darwin
################################################################################
# libc/libunwind for musl
#
# When we're building a musl-like target we're going to link libc/libunwind
# statically into the standard library and liblibc, so we need to make sure
# they're in a location that we can find
################################################################################
ifeq ($$(findstring musl,$(1)),musl)
$$(RT_OUTPUT_DIR_$(1))/%: $$(CFG_MUSL_ROOT)/lib/%
cp $$^ $$@
endif
endef
# Instantiate template for all stages/targets

View File

@ -25,8 +25,6 @@ endif
RUSTLLVM_OBJS_CS_$(1) := $$(addprefix rustllvm/, \
ExecutionEngineWrapper.cpp RustWrapper.cpp PassWrapper.cpp)
RUSTLLVM_DEF_$(1) := $(1)/rustllvm/rustllvm$(CFG_DEF_SUFFIX_$(1))
RUSTLLVM_INCS_$(1) = $$(LLVM_EXTRA_INCDIRS_$(1)) \
-iquote $$(LLVM_INCDIR_$(1)) \
-iquote $$(S)src/rustllvm/include

View File

@ -35,7 +35,9 @@ CRATE_FULLDEPS_$(1)_T_$(2)_H_$(3)_$(4) := \
$$(foreach dep,$$(RUST_DEPS_$(4)), \
$$(TLIB$(1)_T_$(2)_H_$(3))/stamp.$$(dep)) \
$$(foreach dep,$$(NATIVE_DEPS_$(4)), \
$$(RT_OUTPUT_DIR_$(2))/$$(call CFG_STATIC_LIB_NAME_$(2),$$(dep)))
$$(RT_OUTPUT_DIR_$(2))/$$(call CFG_STATIC_LIB_NAME_$(2),$$(dep))) \
$$(foreach dep,$$(NATIVE_DEPS_$(4)_T_$(2)), \
$$(RT_OUTPUT_DIR_$(2))/$$(dep))
endef
$(foreach host,$(CFG_HOST), \
@ -143,14 +145,7 @@ $$(TBIN$(1)_T_$(2)_H_$(3))/:
$$(TLIB$(1)_T_$(2)_H_$(3))/:
mkdir -p $$@
$$(TLIB$(1)_T_$(2)_H_$(3))/libcompiler-rt.a: \
$$(RT_OUTPUT_DIR_$(2))/$$(call CFG_STATIC_LIB_NAME_$(2),compiler-rt) \
| $$(TLIB$(1)_T_$(2)_H_$(3))/ $$(SNAPSHOT_RUSTC_POST_CLEANUP)
@$$(call E, cp: $$@)
$$(Q)cp $$< $$@
$$(TLIB$(1)_T_$(2)_H_$(3))/libmorestack.a: \
$$(RT_OUTPUT_DIR_$(2))/$$(call CFG_STATIC_LIB_NAME_$(2),morestack) \
$$(TLIB$(1)_T_$(2)_H_$(3))/%: $$(RT_OUTPUT_DIR_$(2))/% \
| $$(TLIB$(1)_T_$(2)_H_$(3))/ $$(SNAPSHOT_RUSTC_POST_CLEANUP)
@$$(call E, cp: $$@)
$$(Q)cp $$< $$@

View File

@ -304,6 +304,7 @@ check-stage$(1)-T-$(2)-H-$(3)-exec: \
check-stage$(1)-T-$(2)-H-$(3)-pfail-exec \
check-stage$(1)-T-$(2)-H-$(3)-rpass-valgrind-exec \
check-stage$(1)-T-$(2)-H-$(3)-rpass-full-exec \
check-stage$(1)-T-$(2)-H-$(3)-rfail-full-exec \
check-stage$(1)-T-$(2)-H-$(3)-cfail-full-exec \
check-stage$(1)-T-$(2)-H-$(3)-rmake-exec \
check-stage$(1)-T-$(2)-H-$(3)-rustdocck-exec \
@ -345,6 +346,7 @@ check-stage$(1)-T-$(2)-H-$(3)-pretty-exec: \
check-stage$(1)-T-$(2)-H-$(3)-pretty-rpass-valgrind-exec \
check-stage$(1)-T-$(2)-H-$(3)-pretty-rpass-full-exec \
check-stage$(1)-T-$(2)-H-$(3)-pretty-rfail-exec \
check-stage$(1)-T-$(2)-H-$(3)-pretty-rfail-full-exec \
check-stage$(1)-T-$(2)-H-$(3)-pretty-bench-exec \
check-stage$(1)-T-$(2)-H-$(3)-pretty-pretty-exec
@ -464,6 +466,7 @@ $(foreach host,$(CFG_HOST), \
RPASS_RS := $(wildcard $(S)src/test/run-pass/*.rs)
RPASS_VALGRIND_RS := $(wildcard $(S)src/test/run-pass-valgrind/*.rs)
RPASS_FULL_RS := $(wildcard $(S)src/test/run-pass-fulldeps/*.rs)
RFAIL_FULL_RS := $(wildcard $(S)src/test/run-fail-fulldeps/*.rs)
CFAIL_FULL_RS := $(wildcard $(S)src/test/compile-fail-fulldeps/*.rs)
RFAIL_RS := $(wildcard $(S)src/test/run-fail/*.rs)
CFAIL_RS := $(wildcard $(S)src/test/compile-fail/*.rs)
@ -483,6 +486,7 @@ PERF_RS := $(wildcard $(S)src/test/bench/*.rs)
RPASS_TESTS := $(RPASS_RS)
RPASS_VALGRIND_TESTS := $(RPASS_VALGRIND_RS)
RPASS_FULL_TESTS := $(RPASS_FULL_RS)
RFAIL_FULL_TESTS := $(RFAIL_FULL_RS)
CFAIL_FULL_TESTS := $(CFAIL_FULL_RS)
RFAIL_TESTS := $(RFAIL_RS)
CFAIL_TESTS := $(CFAIL_RS)
@ -510,6 +514,11 @@ CTEST_BUILD_BASE_rpass-full = run-pass-fulldeps
CTEST_MODE_rpass-full = run-pass
CTEST_RUNTOOL_rpass-full = $(CTEST_RUNTOOL)
CTEST_SRC_BASE_rfail-full = run-fail-fulldeps
CTEST_BUILD_BASE_rfail-full = run-fail-fulldeps
CTEST_MODE_rfail-full = run-fail
CTEST_RUNTOOL_rfail-full = $(CTEST_RUNTOOL)
CTEST_SRC_BASE_cfail-full = compile-fail-fulldeps
CTEST_BUILD_BASE_cfail-full = compile-fail-fulldeps
CTEST_MODE_cfail-full = compile-fail
@ -623,6 +632,13 @@ ifndef CFG_DISABLE_OPTIMIZE_TESTS
CTEST_RUSTC_FLAGS += -O
endif
# Analogously to the above, whether to pass `-g` when compiling tests
# is a separate choice from whether to pass `-g` when building the
# compiler and standard library themselves.
CTEST_RUSTC_FLAGS := $$(subst -g,,$$(CTEST_RUSTC_FLAGS))
ifdef CFG_ENABLE_DEBUGINFO_TESTS
CTEST_RUSTC_FLAGS += -g
endif
CTEST_COMMON_ARGS$(1)-T-$(2)-H-$(3) := \
--compile-lib-path $$(HLIB$(1)_H_$(3)) \
@ -661,6 +677,7 @@ endif
CTEST_DEPS_rpass_$(1)-T-$(2)-H-$(3) = $$(RPASS_TESTS)
CTEST_DEPS_rpass-valgrind_$(1)-T-$(2)-H-$(3) = $$(RPASS_VALGRIND_TESTS)
CTEST_DEPS_rpass-full_$(1)-T-$(2)-H-$(3) = $$(RPASS_FULL_TESTS) $$(CSREQ$(1)_T_$(3)_H_$(3)) $$(SREQ$(1)_T_$(2)_H_$(3))
CTEST_DEPS_rfail-full_$(1)-T-$(2)-H-$(3) = $$(RFAIL_FULL_TESTS) $$(CSREQ$(1)_T_$(3)_H_$(3)) $$(SREQ$(1)_T_$(2)_H_$(3))
CTEST_DEPS_cfail-full_$(1)-T-$(2)-H-$(3) = $$(CFAIL_FULL_TESTS) $$(CSREQ$(1)_T_$(3)_H_$(3)) $$(SREQ$(1)_T_$(2)_H_$(3))
CTEST_DEPS_rfail_$(1)-T-$(2)-H-$(3) = $$(RFAIL_TESTS)
CTEST_DEPS_cfail_$(1)-T-$(2)-H-$(3) = $$(CFAIL_TESTS)
@ -737,7 +754,7 @@ endif
endef
CTEST_NAMES = rpass rpass-valgrind rpass-full cfail-full rfail cfail pfail \
CTEST_NAMES = rpass rpass-valgrind rpass-full rfail-full cfail-full rfail cfail pfail \
bench perf debuginfo-gdb debuginfo-lldb codegen rustdocck
$(foreach host,$(CFG_HOST), \
@ -746,22 +763,26 @@ $(foreach host,$(CFG_HOST), \
$(eval $(foreach name,$(CTEST_NAMES), \
$(eval $(call DEF_RUN_COMPILETEST,$(stage),$(target),$(host),$(name))))))))))
PRETTY_NAMES = pretty-rpass pretty-rpass-valgrind pretty-rpass-full pretty-rfail pretty-bench pretty-pretty
PRETTY_NAMES = pretty-rpass pretty-rpass-valgrind pretty-rpass-full pretty-rfail-full pretty-rfail \
pretty-bench pretty-pretty
PRETTY_DEPS_pretty-rpass = $(RPASS_TESTS)
PRETTY_DEPS_pretty-rpass-valgrind = $(RPASS_VALGRIND_TESTS)
PRETTY_DEPS_pretty-rpass-full = $(RPASS_FULL_TESTS)
PRETTY_DEPS_pretty-rfail-full = $(RFAIL_FULL_TESTS)
PRETTY_DEPS_pretty-rfail = $(RFAIL_TESTS)
PRETTY_DEPS_pretty-bench = $(BENCH_TESTS)
PRETTY_DEPS_pretty-pretty = $(PRETTY_TESTS)
PRETTY_DIRNAME_pretty-rpass = run-pass
PRETTY_DIRNAME_pretty-rpass-valgrind = run-pass-valgrind
PRETTY_DIRNAME_pretty-rpass-full = run-pass-fulldeps
PRETTY_DIRNAME_pretty-rfail-full = run-fail-fulldeps
PRETTY_DIRNAME_pretty-rfail = run-fail
PRETTY_DIRNAME_pretty-bench = bench
PRETTY_DIRNAME_pretty-pretty = pretty
define DEF_PRETTY_FULLDEPS
PRETTY_DEPS$(1)_T_$(2)_H_$(3)_pretty-rpass-full = $$(CSREQ$(1)_T_$(3)_H_$(3))
PRETTY_DEPS$(1)_T_$(2)_H_$(3)_pretty-rfail-full = $$(CSREQ$(1)_T_$(3)_H_$(3))
endef
$(foreach host,$(CFG_HOST), \
@ -901,6 +922,7 @@ TEST_GROUPS = \
rpass \
rpass-valgrind \
rpass-full \
rfail-full \
cfail-full \
rfail \
cfail \
@ -918,6 +940,7 @@ TEST_GROUPS = \
pretty-rpass \
pretty-rpass-valgrind \
pretty-rpass-full \
pretty-rfail-full \
pretty-rfail \
pretty-bench \
pretty-pretty \

View File

@ -170,6 +170,9 @@ pub fn is_test_ignored(config: &Config, testfile: &Path) -> bool {
format!("ignore-{}",
config.stage_id.split('-').next().unwrap())
}
fn ignore_env(config: &Config) -> String {
format!("ignore-{}", util::get_env(&config.target).unwrap_or("<unknown>"))
}
fn ignore_gdb(config: &Config, line: &str) -> bool {
if config.mode != common::DebugInfoGdb {
return false;
@ -231,6 +234,7 @@ pub fn is_test_ignored(config: &Config, testfile: &Path) -> bool {
!parse_name_directive(ln, &ignore_target(config)) &&
!parse_name_directive(ln, &ignore_architecture(config)) &&
!parse_name_directive(ln, &ignore_stage(config)) &&
!parse_name_directive(ln, &ignore_env(config)) &&
!(config.mode == common::Pretty && parse_name_directive(ln, "ignore-pretty")) &&
!(config.target != config.host && parse_name_directive(ln, "ignore-cross-compile")) &&
!ignore_gdb(config, ln) &&

View File

@ -1233,7 +1233,20 @@ fn compose_and_run_compiler(config: &Config, props: &TestProps,
let mut crate_type = if aux_props.no_prefer_dynamic {
Vec::new()
} else {
vec!("--crate-type=dylib".to_string())
// We primarily compile all auxiliary libraries as dynamic libraries
// to avoid code size bloat and large binaries as much as possible
// for the test suite (otherwise including libstd statically in all
// executables takes up quite a bit of space).
//
// For targets like MUSL, however, there is no support for dynamic
// libraries so we just go back to building a normal library. Note,
// however, that if the library is built with `force_host` then it's
// ok to be a dylib as the host should always support dylibs.
if config.target.contains("musl") && !aux_props.force_host {
vec!("--crate-type=lib".to_string())
} else {
vec!("--crate-type=dylib".to_string())
}
};
crate_type.extend(extra_link_args.clone().into_iter());
let aux_args =

View File

@ -60,6 +60,10 @@ pub fn get_arch(triple: &str) -> &'static str {
panic!("Cannot determine Architecture from triple");
}
pub fn get_env(triple: &str) -> Option<&str> {
triple.split('-').nth(3)
}
pub fn make_new_path(path: &str) -> String {
assert!(cfg!(windows));
// Windows just uses PATH as the library search path, so we have to

View File

@ -96,12 +96,16 @@ explicit codepoint lists. [^inputformat]
## Special Unicode Productions
The following productions in the Rust grammar are defined in terms of Unicode
properties: `ident`, `non_null`, `non_star`, `non_eol`, `non_slash_or_star`,
`non_single_quote` and `non_double_quote`.
properties: `ident`, `non_null`, `non_eol`, `non_single_quote` and
`non_double_quote`.
### Identifiers
The `ident` production is any nonempty Unicode string of the following form:
The `ident` production is any nonempty Unicode[^non_ascii_idents] string of
the following form:
[^non_ascii_idents]: Non-ASCII characters in identifiers are currently feature
gated. This is expected to improve soon.
- The first character has property `XID_start`
- The remaining characters have property `XID_continue`
@ -118,8 +122,6 @@ Some productions are defined by exclusion of particular Unicode characters:
- `non_null` is any single Unicode character aside from `U+0000` (null)
- `non_eol` is `non_null` restricted to exclude `U+000A` (`'\n'`)
- `non_star` is `non_null` restricted to exclude `U+002A` (`*`)
- `non_slash_or_star` is `non_null` restricted to exclude `U+002F` (`/`) and `U+002A` (`*`)
- `non_single_quote` is `non_null` restricted to exclude `U+0027` (`'`)
- `non_double_quote` is `non_null` restricted to exclude `U+0022` (`"`)
@ -152,19 +154,19 @@ token : simple_token | ident | literal | symbol | whitespace token ;
<p id="keyword-table-marker"></p>
| | | | | |
|----------|----------|----------|----------|--------|
| abstract | alignof | as | become | 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 | | | | |
| | | | | |
|----------|----------|----------|----------|---------|
| abstract | alignof | as | become | box |
| break | const | continue | crate | do |
| else | enum | extern | false | final |
| fn | for | if | impl | in |
| let | loop | macro | match | mod |
| move | mut | offsetof | override | priv |
| proc | pub | pure | ref | return |
| Self | self | sizeof | static | struct |
| super | trait | true | type | typeof |
| unsafe | unsized | use | virtual | where |
| while | yield | | | |
Each of these keywords has special meaning in its grammar, and all of them are
@ -524,6 +526,15 @@ array_elems : [expr [',' expr]*] | [expr ',' ".." expr] ;
idx_expr : expr '[' expr ']' ;
```
### Range expressions
```antlr
range_expr : expr ".." expr |
expr ".." |
".." expr |
".." ;
```
### Unary operator expressions
**FIXME:** grammar?
@ -610,7 +621,7 @@ lambda_expr : '|' ident_list '|' expr ;
### While loops
```antlr
while_expr : "while" no_struct_literal_expr '{' block '}' ;
while_expr : [ lifetime ':' ] "while" no_struct_literal_expr '{' block '}' ;
```
### Infinite loops
@ -634,7 +645,7 @@ continue_expr : "continue" [ lifetime ];
### For expressions
```antlr
for_expr : "for" pat "in" no_struct_literal_expr '{' block '}' ;
for_expr : [ lifetime ':' ] "for" pat "in" no_struct_literal_expr '{' block '}' ;
```
### If expressions

View File

@ -57,8 +57,12 @@ function populate_rust_search() {
// #18540, use a single token
var a = document.createElement("a");
a.href = "http://doc.rust-lang.org/core/?search=" + encodeURIComponent(lt);
a.textContent = lt;
var search = document.getElementById('core-search');
search.innerHTML = "<a href=\"http://doc.rust-lang.org/core/?search=" + lt + "\">" + lt + "</a>";
search.innerHTML = "";
search.appendChild(a);
}
populate_site_search();
populate_rust_search();

View File

@ -29,41 +29,6 @@ You may also be interested in the [grammar].
# Notation
Rust's grammar is defined over Unicode code points, each conventionally denoted
`U+XXXX`, for 4 or more hexadecimal digits `X`. _Most_ of Rust's grammar is
confined to the ASCII range of Unicode, and is described in this document by a
dialect of Extended Backus-Naur Form (EBNF), specifically a dialect of EBNF
supported by common automated LL(k) parsing tools such as `llgen`, rather than
the dialect given in ISO 14977. The dialect can be defined self-referentially
as follows:
```{.ebnf .notation}
grammar : rule + ;
rule : nonterminal ':' productionrule ';' ;
productionrule : production [ '|' production ] * ;
production : term * ;
term : element repeats ;
element : LITERAL | IDENTIFIER | '[' productionrule ']' ;
repeats : [ '*' | '+' ] NUMBER ? | NUMBER ? | '?' ;
```
Where:
- Whitespace in the grammar is ignored.
- Square brackets are used to group rules.
- `LITERAL` is a single printable ASCII character, or an escaped hexadecimal
ASCII code of the form `\xQQ`, in single quotes, denoting the corresponding
Unicode code point `U+00QQ`.
- `IDENTIFIER` is a nonempty string of ASCII letters and underscores.
- The `repeat` forms apply to the adjacent `element`, and are as follows:
- `?` means zero or one repetition
- `*` means zero or more repetitions
- `+` means one or more repetitions
- NUMBER trailing a repeat symbol gives a maximum repetition count
- NUMBER on its own gives an exact repetition count
This EBNF dialect should hopefully be familiar to many readers.
## Unicode productions
A few productions in Rust's grammar permit Unicode code points outside the ASCII
@ -100,15 +65,12 @@ explicit code point lists. [^inputformat]
provided to the grammar verifier, restricted to ASCII range, when verifying the
grammar in this document.
## Special Unicode Productions
## Identifiers
The following productions in the Rust grammar are defined in terms of Unicode
properties: `ident`, `non_null`, `non_star`, `non_eol`, `non_slash_or_star`,
`non_single_quote` and `non_double_quote`.
An identifier is any nonempty Unicode[^non_ascii_idents] string of the following form:
### Identifiers
The `ident` production is any nonempty Unicode string of the following form:
[^non_ascii_idents]: Non-ASCII characters in identifiers are currently feature
gated. This is expected to improve soon.
- The first character has property `XID_start`
- The remaining characters have property `XID_continue`
@ -119,54 +81,34 @@ that does _not_ occur in the set of [keywords](#keywords).
> character ranges used to form the more familiar C and Java language-family
> identifiers.
### Delimiter-restricted productions
Some productions are defined by exclusion of particular Unicode characters:
- `non_null` is any single Unicode character aside from `U+0000` (null)
- `non_eol` is `non_null` restricted to exclude `U+000A` (`'\n'`)
- `non_star` is `non_null` restricted to exclude `U+002A` (`*`)
- `non_slash_or_star` is `non_null` restricted to exclude `U+002F` (`/`) and `U+002A` (`*`)
- `non_single_quote` is `non_null` restricted to exclude `U+0027` (`'`)
- `non_double_quote` is `non_null` restricted to exclude `U+0022` (`"`)
## Comments
```{.ebnf .gram}
comment : block_comment | line_comment ;
block_comment : "/*" block_comment_body * "*/" ;
block_comment_body : [block_comment | character] * ;
line_comment : "//" non_eol * ;
```
Comments in Rust code follow the general C++ style of line and block-comment
forms. Nested block comments are supported.
Comments in Rust code follow the general C++ style of line (`//`) and
block (`/* ... */`) comment forms. Nested block comments are supported.
Line comments beginning with exactly _three_ slashes (`///`), and block
comments beginning with exactly one repeated asterisk in the block-open
sequence (`/**`), are interpreted as a special syntax for `doc`
[attributes](#attributes). That is, they are equivalent to writing
`#[doc="..."]` around the body of the comment (this includes the comment
characters themselves, i.e. `/// Foo` turns into `#[doc="/// Foo"]`).
`#[doc="..."]` around the body of the comment, i.e., `/// Foo` turns into
`#[doc="Foo"]`.
Line comments beginning with `//!` and block comments beginning with `/*!` are
doc comments that apply to the parent of the comment, rather than the item
that follows. That is, they are equivalent to writing `#![doc="..."]` around
the body of the comment. `//!` comments are usually used to display
information on the crate index page.
the body of the comment. `//!` comments are usually used to document
modules that occupy a source file.
Non-doc comments are interpreted as a form of whitespace.
## Whitespace
```{.ebnf .gram}
whitespace_char : '\x20' | '\x09' | '\x0a' | '\x0d' ;
whitespace : [ whitespace_char | comment ] + ;
```
Whitespace is any non-empty string containing only the following characters:
The `whitespace_char` production is any nonempty Unicode string consisting of
any of the following Unicode characters: `U+0020` (space, `' '`), `U+0009`
(tab, `'\t'`), `U+000A` (LF, `'\n'`), `U+000D` (CR, `'\r'`).
- `U+0020` (space, `' '`)
- `U+0009` (tab, `'\t'`)
- `U+000A` (LF, `'\n'`)
- `U+000D` (CR, `'\r'`)
Rust is a "free-form" language, meaning that all forms of whitespace serve only
to separate _tokens_ in the grammar, and have no semantic significance.
@ -176,41 +118,11 @@ with any other legal whitespace element, such as a single space character.
## Tokens
```{.ebnf .gram}
simple_token : keyword | unop | binop ;
token : simple_token | ident | literal | symbol | whitespace token ;
```
Tokens are primitive productions in the grammar defined by regular
(non-recursive) languages. "Simple" tokens are given in [string table
production](#string-table-productions) form, and occur in the rest of the
grammar as double-quoted strings. Other tokens have exact rules given.
### Keywords
<p id="keyword-table-marker"></p>
| | | | | |
|----------|----------|----------|----------|---------|
| abstract | alignof | as | become | box |
| break | const | continue | crate | do |
| else | enum | extern | false | final |
| fn | for | if | impl | in |
| let | loop | macro | match | mod |
| move | mut | offsetof | override | priv |
| proc | pub | pure | ref | return |
| Self | self | sizeof | static | struct |
| super | trait | true | 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
@ -218,11 +130,6 @@ of tokens, that immediately and directly denotes the value it evaluates to,
rather than referring to it by name or some other evaluation rule. A literal is
a form of constant expression, so is evaluated (primarily) at compile time.
```{.ebnf .gram}
lit_suffix : ident;
literal : [ string_lit | char_lit | byte_string_lit | byte_lit | num_lit ] lit_suffix ?;
```
The optional suffix is only used for certain numeric literals, but is
reserved for future extension, that is, the above gives the lexical
grammar, but a Rust parser will reject everything but the 12 special
@ -275,32 +182,6 @@ cases mentioned in [Number literals](#number-literals) below.
#### Character and string literals
```{.ebnf .gram}
char_lit : '\x27' char_body '\x27' ;
string_lit : '"' string_body * '"' | 'r' raw_string ;
char_body : non_single_quote
| '\x5c' [ '\x27' | common_escape | unicode_escape ] ;
string_body : non_double_quote
| '\x5c' [ '\x22' | common_escape | unicode_escape ] ;
raw_string : '"' raw_string_body '"' | '#' raw_string '#' ;
common_escape : '\x5c'
| 'n' | 'r' | 't' | '0'
| 'x' hex_digit 2
unicode_escape : 'u' '{' hex_digit+ 6 '}';
hex_digit : 'a' | 'b' | 'c' | 'd' | 'e' | 'f'
| 'A' | 'B' | 'C' | 'D' | 'E' | 'F'
| dec_digit ;
oct_digit : '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' ;
dec_digit : '0' | nonzero_dec ;
nonzero_dec: '1' | '2' | '3' | '4'
| '5' | '6' | '7' | '8' | '9' ;
```
##### Character literals
A _character literal_ is a single Unicode character enclosed within two
@ -311,13 +192,13 @@ which must be _escaped_ by a preceding `U+005C` character (`\`).
A _string literal_ is a sequence of any Unicode characters enclosed within two
`U+0022` (double-quote) characters, with the exception of `U+0022` itself,
which must be _escaped_ by a preceding `U+005C` character (`\`), or a _raw
string literal_.
which must be _escaped_ by a preceding `U+005C` character (`\`).
A multi-line string literal may be defined by terminating each line with a
`U+005C` character (`\`) immediately before the newline. This causes the
`U+005C` character, the newline, and all whitespace at the beginning of the
next line to be ignored.
Line-break characters are allowed in string literals. Normally they represent
themselves (i.e. no translation), but as a special exception, when a `U+005C`
character (`\`) occurs immediately before the newline, the `U+005C` character,
the newline, and all whitespace at the beginning of the next line are ignored.
Thus `a` and `b` are equal:
```rust
let a = "foobar";
@ -349,11 +230,10 @@ following forms:
Raw string literals do not process any escapes. They start with the character
`U+0072` (`r`), followed by zero or more of the character `U+0023` (`#`) and a
`U+0022` (double-quote) character. The _raw string body_ is not defined in the
EBNF grammar above: it can contain any sequence of Unicode characters and is
terminated only by another `U+0022` (double-quote) character, followed by the
same number of `U+0023` (`#`) characters that preceded the opening `U+0022`
(double-quote) character.
`U+0022` (double-quote) character. The _raw string body_ can contain any sequence
of Unicode characters and is terminated only by another `U+0022` (double-quote)
character, followed by the same number of `U+0023` (`#`) characters that preceded
the opening `U+0022` (double-quote) character.
All Unicode characters contained in the raw string body represent themselves,
the characters `U+0022` (double-quote) (except when followed by at least as
@ -375,26 +255,14 @@ r##"foo #"# bar"##; // foo #"# bar
#### Byte and byte string literals
```{.ebnf .gram}
byte_lit : "b\x27" byte_body '\x27' ;
byte_string_lit : "b\x22" string_body * '\x22' | "br" raw_byte_string ;
byte_body : ascii_non_single_quote
| '\x5c' [ '\x27' | common_escape ] ;
byte_string_body : ascii_non_double_quote
| '\x5c' [ '\x22' | common_escape ] ;
raw_byte_string : '"' raw_byte_string_body '"' | '#' raw_byte_string '#' ;
```
##### Byte literals
A _byte literal_ is a single ASCII character (in the `U+0000` to `U+007F`
range) enclosed within two `U+0027` (single-quote) characters, with the
exception of `U+0027` itself, which must be _escaped_ by a preceding U+005C
character (`\`), or a single _escape_. It is equivalent to a `u8` unsigned
8-bit integer _number literal_.
range) or a single _escape_ preceded by the characters `U+0062` (`b`) and
`U+0027` (single-quote), and followed by the character `U+0027`. If the character
`U+0027` is present within the literal, it must be _escaped_ by a preceding
`U+005C` (`\`) character. It is equivalent to a `u8` unsigned 8-bit integer
_number literal_.
##### Byte string literals
@ -403,7 +271,7 @@ preceded by the characters `U+0062` (`b`) and `U+0022` (double-quote), and
followed by the character `U+0022`. If the character `U+0022` is present within
the literal, it must be _escaped_ by a preceding `U+005C` (`\`) character.
Alternatively, a byte string literal can be a _raw byte string literal_, defined
below. A byte string literal is equivalent to a `&'static [u8]` borrowed array
below. A byte string literal of length `n` is equivalent to a `&'static [u8; n]` borrowed fixed-sized array
of unsigned 8-bit integers.
Some additional _escapes_ are available in either byte or non-raw byte string
@ -424,11 +292,10 @@ following forms:
Raw byte string literals do not process any escapes. They start with the
character `U+0062` (`b`), followed by `U+0072` (`r`), followed by zero or more
of the character `U+0023` (`#`), and a `U+0022` (double-quote) character. The
_raw string body_ is not defined in the EBNF grammar above: it can contain any
sequence of ASCII characters and is terminated only by another `U+0022`
(double-quote) character, followed by the same number of `U+0023` (`#`)
characters that preceded the opening `U+0022` (double-quote) character. A raw
byte string literal can not contain any non-ASCII byte.
_raw string body_ can contain any sequence of ASCII characters and is terminated
only by another `U+0022` (double-quote) character, followed by the same number of
`U+0023` (`#`) characters that preceded the opening `U+0022` (double-quote)
character. A raw byte string literal can not contain any non-ASCII byte.
All characters contained in the raw string body represent their ASCII encoding,
the characters `U+0022` (double-quote) (except when followed by at least as
@ -450,19 +317,6 @@ b"\\x52"; br"\x52"; // \x52
#### Number literals
```{.ebnf .gram}
num_lit : nonzero_dec [ dec_digit | '_' ] * float_suffix ?
| '0' [ [ dec_digit | '_' ] * float_suffix ?
| 'b' [ '1' | '0' | '_' ] +
| 'o' [ oct_digit | '_' ] +
| 'x' [ hex_digit | '_' ] + ] ;
float_suffix : [ exponent | '.' dec_lit exponent ? ] ? ;
exponent : ['E' | 'e'] ['-' | '+' ] ? dec_lit ;
dec_lit : [ dec_digit | '_' ] + ;
```
A _number literal_ is either an _integer literal_ or a _floating-point
literal_. The grammar for recognizing the two kinds of literals is mixed.
@ -512,11 +366,19 @@ A _floating-point literal_ has one of two forms:
optionally followed by another decimal literal, with an optional _exponent_.
* A single _decimal literal_ followed by an _exponent_.
By default, a floating-point literal has a generic type, and, like integer
literals, the type must be uniquely determined from the context. There are two valid
Like integer literals, a floating-point literal may be followed by a
suffix, so long as the pre-suffix part does not end with `U+002E` (`.`).
The suffix forcibly sets the type of the literal. There are two valid
_floating-point suffixes_, `f32` and `f64` (the 32-bit and 64-bit floating point
types), which explicitly determine the type of the literal.
The type of an _unsuffixed_ floating-point literal is determined by type
inference. If a floating-point type can be _uniquely_ determined from the
surrounding program context, the unsuffixed floating-point literal has that type.
If the program context underconstrains the type, it defaults to double-precision `f64`;
if the program context overconstrains the type, it is considered a static type
error.
Examples of floating-point literals of various forms:
```
@ -540,12 +402,6 @@ The two values of the boolean type are written `true` and `false`.
### Symbols
```{.ebnf .gram}
symbol : "::" | "->"
| '#' | '[' | ']' | '(' | ')' | '{' | '}'
| ',' | ';' ;
```
Symbols are a general class of printable [token](#tokens) that play structural
roles in a variety of grammar productions. They are catalogued here for
completeness as the set of remaining miscellaneous printable tokens that do not
@ -555,16 +411,6 @@ operators](#binary-operator-expressions), or [keywords](#keywords).
## Paths
```{.ebnf .gram}
expr_path : [ "::" ] ident [ "::" expr_path_tail ] + ;
expr_path_tail : '<' type_expr [ ',' type_expr ] + '>'
| expr_path ;
type_path : ident [ type_path_tail ] + ;
type_path_tail : '<' type_expr [ ',' type_expr ] + '>'
| "::" type_path ;
```
A _path_ is a sequence of one or more path components _logically_ separated by
a namespace qualifier (`::`). If a path consists of only one component, it may
refer to either an [item](#items) or a [variable](#variables) in a local control
@ -660,19 +506,6 @@ Users of `rustc` can define new syntax extensions in two ways:
## Macros
```{.ebnf .gram}
expr_macro_rules : "macro_rules" '!' ident '(' macro_rule * ')' ;
macro_rule : '(' matcher * ')' "=>" '(' transcriber * ')' ';' ;
matcher : '(' matcher * ')' | '[' matcher * ']'
| '{' matcher * '}' | '$' ident ':' ident
| '$' '(' matcher * ')' sep_token? [ '*' | '+' ]
| non_special_token ;
transcriber : '(' transcriber * ')' | '[' transcriber * ']'
| '{' transcriber * '}' | '$' ident
| '$' '(' transcriber * ')' sep_token? [ '*' | '+' ]
| non_special_token ;
```
`macro_rules` allows users to define syntax extension in a declarative way. We
call such extensions "macros by example" or simply "macros" — to be distinguished
from the "procedural macros" defined in [compiler plugins][plugin].
@ -811,12 +644,6 @@ Crates contain [items](#items), each of which may have some number of
## Items
```{.ebnf .gram}
item : extern_crate_decl | use_decl | mod_item | fn_item | type_item
| struct_item | enum_item | static_item | trait_item | impl_item
| extern_block ;
```
An _item_ is a component of a crate. Items are organized within a crate by a
nested set of [modules](#modules). Every crate has a single "outermost"
anonymous module; all further items within the crate have [paths](#paths)
@ -863,11 +690,6 @@ no notion of type abstraction: there are no first-class "forall" types.
### Modules
```{.ebnf .gram}
mod_item : "mod" ident ( ';' | '{' mod '}' );
mod : item * ;
```
A module is a container for zero or more [items](#items).
A _module item_ is a module, surrounded in braces, named, and prefixed with the
@ -928,11 +750,6 @@ mod thread {
##### Extern crate declarations
```{.ebnf .gram}
extern_crate_decl : "extern" "crate" crate_name
crate_name: ident | ( string_lit "as" ident )
```
An _`extern crate` declaration_ specifies a dependency on an external crate.
The external crate is then bound into the declaring scope as the `ident`
provided in the `extern_crate_decl`.
@ -958,17 +775,6 @@ extern crate std as ruststd; // linking to 'std' under another name
##### Use declarations
```{.ebnf .gram}
use_decl : "pub" ? "use" [ path "as" ident
| path_glob ] ;
path_glob : ident [ "::" [ path_glob
| '*' ] ] ?
| '{' path_item [ ',' path_item ] * '}' ;
path_item : ident | "self" ;
```
A _use declaration_ creates one or more local name bindings synonymous with
some other [path](#paths). Usually a `use` declaration is used to shorten the
path required to refer to a module item. These declarations may appear at the
@ -1413,10 +1219,6 @@ it were `Bar(i32)`, this is disallowed.
### Constant items
```{.ebnf .gram}
const_item : "const" ident ':' type '=' expr ';' ;
```
A *constant item* is a named _constant value_ which is not associated with a
specific memory location in the program. Constants are essentially inlined
wherever they are used, meaning that they are copied directly into the relevant
@ -1453,10 +1255,6 @@ const BITS_N_STRINGS: BitsNStrings<'static> = BitsNStrings {
### Static items
```{.ebnf .gram}
static_item : "static" ident ':' type '=' expr ';' ;
```
A *static item* is similar to a *constant*, except that it represents a precise
memory location in the program. A static is never "inlined" at the usage site,
and all references to it refer to the same memory location. Static items have
@ -1711,11 +1509,6 @@ impl Seq<bool> for u32 {
### External blocks
```{.ebnf .gram}
extern_block_item : "extern" '{' extern_block '}' ;
extern_block : [ foreign_fn ] * ;
```
External blocks form the basis for Rust's foreign function interface.
Declarations in an external block describe symbols in external, non-Rust
libraries.
@ -1915,13 +1708,6 @@ the namespace hierarchy as it normally would.
## Attributes
```{.ebnf .gram}
attribute : '#' '!' ? '[' meta_item ']' ;
meta_item : ident [ '=' literal
| '(' meta_seq ')' ] ? ;
meta_seq : meta_item [ ',' meta_seq ] ? ;
```
Any item declaration may have an _attribute_ applied to it. Attributes in Rust
are modeled on Attributes in ECMA-335, with the syntax coming from ECMA-334
(C#). An attribute is a general, free-form metadatum that is interpreted
@ -2111,8 +1897,8 @@ release builds.
There are two kinds of configuration options, one that is either defined or not
(`#[cfg(foo)]`), and the other that contains a string that can be checked
against (`#[cfg(bar = "baz")]` (currently only compiler-defined configuration
options can have the latter form).
against (`#[cfg(bar = "baz")]`). Currently, only compiler-defined configuration
options can have the latter form.
```
// The function is only included in the build when compiling for OSX
@ -2188,7 +1974,7 @@ For any lint check `C`:
The lint checks supported by the compiler can be found via `rustc -W help`,
along with their default settings. [Compiler
plugins](book/plugins.html#lint-plugins) can provide additional lint checks.
plugins](book/compiler-plugins.html#lint-plugins) can provide additional lint checks.
```{.ignore}
mod m1 {
@ -2349,7 +2135,10 @@ The currently implemented features of the reference compiler are:
semantics are likely to change, so this macro usage must be opted
into.
* `associated_types` - Allows type aliases in traits. Experimental.
* `associated_consts` - Allows constants to be defined in `impl` and `trait`
blocks, so that they can be associated with a type or
trait in a similar manner to methods and associated
types.
* `box_patterns` - Allows `box` patterns, the exact semantics of which
is subject to change.
@ -2503,7 +2292,7 @@ The currently implemented features of the reference compiler are:
terms of encapsulation).
If a feature is promoted to a language feature, then all existing programs will
start to receive compilation warnings about #[feature] directives which enabled
start to receive compilation warnings about `#![feature]` directives which enabled
the new feature (because the directive is no longer necessary). However, if a
feature is decided to be removed from the language, errors will be issued (if
there isn't a parser error first). The directive in this case is no longer
@ -2554,11 +2343,6 @@ in meaning to declaring the item outside the statement block.
#### Variable declarations
```{.ebnf .gram}
let_decl : "let" pat [':' type ] ? [ init ] ? ';' ;
init : [ '=' ] expr ;
```
A _variable declaration_ introduces a new set of variable, given by a pattern. The
pattern may be followed by a type annotation, and/or an initializer expression.
When no type annotation is given, the compiler will infer the type, or signal
@ -2649,7 +2433,7 @@ parentheses. They are used to create [tuple-typed](#tuple-types) values.
```{.tuple}
(0,);
(0.0, 4.5);
("a", 4us, true);
("a", 4usize, true);
```
### Unit expressions
@ -2659,15 +2443,6 @@ the same name.
### Structure expressions
```{.ebnf .gram}
struct_expr : expr_path '{' ident ':' expr
[ ',' ident ':' expr ] *
[ ".." expr ] '}' |
expr_path '(' expr
[ ',' expr ] * ')' |
expr_path ;
```
There are several forms of structure expressions. A _structure expression_
consists of the [path](#paths) of a [structure item](#structures), followed by
a brace-enclosed list of one or more comma-separated name-value pairs,
@ -2718,11 +2493,6 @@ Point3d {y: 0, z: 10, .. base};
### Block expressions
```{.ebnf .gram}
block_expr : '{' [ stmt ';' | item ] *
[ expr ] '}' ;
```
A _block expression_ is similar to a module in terms of the declarations that
are possible. Each block conceptually introduces a new namespace scope. Use
items can bring new names into scopes and declared items are in scope for only
@ -2745,10 +2515,6 @@ assert_eq!(5, x);
### Method-call expressions
```{.ebnf .gram}
method_call_expr : expr '.' ident paren_expr_list ;
```
A _method call_ consists of an expression followed by a single dot, an
identifier, and a parenthesized expression-list. Method calls are resolved to
methods on specific traits, either statically dispatching to a method if the
@ -2757,10 +2523,6 @@ the left-hand-side expression is an indirect [trait object](#trait-objects).
### Field expressions
```{.ebnf .gram}
field_expr : expr '.' ident ;
```
A _field expression_ consists of an expression followed by a single dot and an
identifier, when not immediately followed by a parenthesized expression-list
(the latter is a [method call expression](#method-call-expressions)). A field
@ -2781,12 +2543,6 @@ automatically dereferenced to make the field access possible.
### Array expressions
```{.ebnf .gram}
array_expr : '[' "mut" ? array_elems? ']' ;
array_elems : [expr [',' expr]*] | [expr ';' expr] ;
```
An [array](#array,-and-slice-types) _expression_ is written by enclosing zero
or more comma-separated expressions of uniform type in square brackets.
@ -2803,10 +2559,6 @@ constant expression that can be evaluated at compile time, such as a
### Index expressions
```{.ebnf .gram}
idx_expr : expr '[' expr ']' ;
```
[Array](#array,-and-slice-types)-typed expressions can be indexed by
writing a square-bracket-enclosed expression (the index) after them. When the
array is mutable, the resulting [lvalue](#lvalues,-rvalues-and-temporaries) can
@ -2823,13 +2575,6 @@ _panicked state_.
### Range expressions
```{.ebnf .gram}
range_expr : expr ".." expr |
expr ".." |
".." expr |
".." ;
```
The `..` operator will construct an object of one of the `std::ops::Range` variants.
```
@ -2872,10 +2617,6 @@ before the expression they apply to.
### Binary operator expressions
```{.ebnf .gram}
binop_expr : expr binop expr ;
```
Binary operators expressions are given in terms of [operator
precedence](#operator-precedence).
@ -3036,10 +2777,6 @@ An expression enclosed in parentheses evaluates to the result of the enclosed
expression. Parentheses can be used to explicitly specify evaluation order
within an expression.
```{.ebnf .gram}
paren_expr : '(' expr ')' ;
```
An example of a parenthesized expression:
```
@ -3049,12 +2786,6 @@ let x: i32 = (2 + 3) * 4;
### Call expressions
```{.ebnf .gram}
expr_list : [ expr [ ',' expr ]* ] ? ;
paren_expr_list : '(' expr_list ')' ;
call_expr : expr paren_expr_list ;
```
A _call expression_ invokes a function, providing zero or more input variables
and an optional location to move the function's output into. If the function
eventually returns, then the expression completes.
@ -3070,11 +2801,6 @@ let pi: Result<f32, _> = "3.14".parse();
### Lambda expressions
```{.ebnf .gram}
ident_list : [ ident [ ',' ident ]* ] ? ;
lambda_expr : '|' ident_list '|' expr ;
```
A _lambda expression_ (sometimes called an "anonymous function expression")
defines a function and denotes it as a value, in a single expression. A lambda
expression is a pipe-symbol-delimited (`|`) list of identifiers followed by an
@ -3118,10 +2844,6 @@ ten_times(|j| println!("hello, {}", j));
A `loop` expression denotes an infinite loop.
```{.ebnf .gram}
loop_expr : [ lifetime ':' ] "loop" '{' block '}';
```
A `loop` expression may optionally have a _label_. The label is written as
a lifetime preceding the loop expression, as in `'foo: loop{ }`. If a
label is present, then labeled `break` and `continue` expressions nested
@ -3131,10 +2853,6 @@ expressions](#continue-expressions).
### Break expressions
```{.ebnf .gram}
break_expr : "break" [ lifetime ];
```
A `break` expression has an optional _label_. If the label is absent, then
executing a `break` expression immediately terminates the innermost loop
enclosing it. It is only permitted in the body of a loop. If the label is
@ -3143,10 +2861,6 @@ be the innermost label enclosing the `break` expression, but must enclose it.
### Continue expressions
```{.ebnf .gram}
continue_expr : "continue" [ lifetime ];
```
A `continue` expression has an optional _label_. If the label is absent, then
executing a `continue` expression immediately terminates the current iteration
of the innermost loop enclosing it, returning control to the loop *head*. In
@ -3160,10 +2874,6 @@ A `continue` expression is only permitted in the body of a loop.
### While loops
```{.ebnf .gram}
while_expr : [ lifetime ':' ] "while" no_struct_literal_expr '{' block '}' ;
```
A `while` loop begins by evaluating the boolean loop conditional expression.
If the loop conditional expression evaluates to `true`, the loop body block
executes and control returns to the loop conditional expression. If the loop
@ -3187,26 +2897,22 @@ loops](#infinite-loops), [break expressions](#break-expressions), and
### For expressions
```{.ebnf .gram}
for_expr : [ lifetime ':' ] "for" pat "in" no_struct_literal_expr '{' block '}' ;
```
A `for` expression is a syntactic construct for looping over elements provided
by an implementation of `std::iter::Iterator`.
by an implementation of `std::iter::IntoIterator`.
An example of a for loop over the contents of an array:
```
# type Foo = i32;
# fn bar(f: Foo) { }
# fn bar(f: &Foo) { }
# let a = 0;
# let b = 0;
# let c = 0;
let v: &[Foo] = &[a, b, c];
for e in v.iter() {
bar(*e);
for e in v {
bar(e);
}
```
@ -3226,14 +2932,6 @@ loops](#infinite-loops), [break expressions](#break-expressions), and
### If expressions
```{.ebnf .gram}
if_expr : "if" no_struct_literal_expr '{' block '}'
else_tail ? ;
else_tail : "else" [ if_expr | if_let_expr
| '{' block '}' ] ;
```
An `if` expression is a conditional branch in program control. The form of an
`if` expression is a condition expression, followed by a consequent block, any
number of `else if` conditions and blocks, and an optional trailing `else`
@ -3246,14 +2944,6 @@ if` condition is evaluated. If all `if` and `else if` conditions evaluate to
### Match expressions
```{.ebnf .gram}
match_expr : "match" no_struct_literal_expr '{' match_arm * '}' ;
match_arm : attribute * match_pat "=>" [ expr "," | '{' block '}' ] ;
match_pat : pat [ '|' pat ] * [ "if" expr ] ? ;
```
A `match` expression branches on a *pattern*. The exact form of matching that
occurs depends on the pattern. Patterns consist of some combination of
literals, destructured arrays or enum constructors, structures and tuples,
@ -3370,12 +3060,6 @@ let message = match maybe_digit {
### If let expressions
```{.ebnf .gram}
if_let_expr : "if" "let" pat '=' expr '{' block '}'
else_tail ? ;
else_tail : "else" [ if_expr | if_let_expr | '{' block '}' ] ;
```
An `if let` expression is semantically identical to an `if` expression but in place
of a condition expression it expects a refutable let statement. If the value of the
expression on the right hand side of the let statement matches the pattern, the corresponding
@ -3383,10 +3067,6 @@ block will execute, otherwise flow proceeds to the first `else` block that follo
### While let loops
```{.ebnf .gram}
while_let_expr : "while" "let" pat '=' expr '{' block '}' ;
```
A `while let` loop is semantically identical to a `while` loop but in place of a
condition expression it expects a refutable let statement. If the value of the
expression on the right hand side of the let statement matches the pattern, the
@ -3395,10 +3075,6 @@ Otherwise, the while expression completes.
### Return expressions
```{.ebnf .gram}
return_expr : "return" expr ? ;
```
Return expressions are denoted with the keyword `return`. Evaluating a `return`
expression moves its argument into the designated output location for the
current function call, destroys the current function activation frame, and
@ -3971,4 +3647,4 @@ that have since been removed):
pattern syntax
[ffi]: book/ffi.html
[plugin]: book/plugins.html
[plugin]: book/compiler-plugins.html

View File

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

View File

@ -8,7 +8,7 @@ good at: embedding in other languages, programs with specific space and time
requirements, and writing low-level code, like device drivers and operating
systems. It improves on current languages targeting this space by having a
number of compile-time safety checks that produce no runtime overhead, while
eliminating all data races. Rust also aims to achieve zero-cost abstrations
eliminating all data races. Rust also aims to achieve zero-cost abstractions
even though some of these abstractions feel like those of a high-level
language. Even then, Rust still allows precise control like a low-level
language would.
@ -127,7 +127,7 @@ vector. When we try to compile this program, we get an error:
```text
error: cannot borrow `x` as mutable because it is also borrowed as immutable
x.push(4);
x.push("foo");
^
note: previous borrow of `x` occurs here; the immutable borrow prevents
subsequent moves or mutable borrows of `x` until the borrow ends

View File

@ -36,7 +36,6 @@
* [Strings](strings.md)
* [Generics](generics.md)
* [Traits](traits.md)
* [Operators and Overloading](operators-and-overloading.md)
* [Drop](drop.md)
* [if let](if-let.md)
* [Trait Objects](trait-objects.md)
@ -50,6 +49,7 @@
* [Casting between types](casting-between-types.md)
* [Associated Types](associated-types.md)
* [Unsized Types](unsized-types.md)
* [Operators and Overloading](operators-and-overloading.md)
* [Deref coercions](deref-coercions.md)
* [Macros](macros.md)
* [Raw Pointers](raw-pointers.md)

View File

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

View File

@ -294,7 +294,7 @@ is `Fn(i32) -> i32`.
Theres one other key point here: because were bounding a generic with a
trait, this will get monomorphized, and therefore, well be doing static
dispatch into the closure. Thats pretty neat. In many langauges, closures are
dispatch into the closure. Thats pretty neat. In many languages, closures are
inherently heap allocated, and will always involve dynamic dispatch. In Rust,
we can stack allocate our closure environment, and statically dispatch the
call. This happens quite often with iterators and their adapters, which often

View File

@ -66,6 +66,8 @@ unsafe {
}
```
[unsafe]: unsafe.html
Furthermore, any type stored in a `static` must be `Sync`.
# Initializing

View File

@ -1,3 +1,119 @@
% `Deref` coercions
Coming soon!
The standard library provides a special trait, [`Deref`][deref]. Its normally
used to overload `*`, the dereference operator:
```rust
use std::ops::Deref;
struct DerefExample<T> {
value: T,
}
impl<T> Deref for DerefExample<T> {
type Target = T;
fn deref(&self) -> &T {
&self.value
}
}
fn main() {
let x = DerefExample { value: 'a' };
assert_eq!('a', *x);
}
```
[deref]: ../std/ops/trait.Deref.html
This is useful for writing custom pointer types. However, theres a language
feature related to `Deref`: deref coercions. Heres the rule: If you have a
type `U`, and it implements `Deref<Target=T>`, values of `&U` will
automatically coerce to a `&T`. Heres an example:
```rust
fn foo(s: &str) {
// borrow a string for a second
}
// String implements Deref<Target=str>
let owned = "Hello".to_string();
// therefore, this works:
foo(&owned);
```
Using an ampersand in front of a value takes a reference to it. So `owned` is a
`String`, `&owned` is an `&String`, and since `impl Deref<Target=str> for
String`, `&String` will deref to `&str`, which `foo()` takes.
Thats it. This rule is one of the only places in which Rust does an automatic
conversion for you, but it adds a lot of flexibility. For example, the `Rc<T>`
type implements `Deref<Target=T>`, so this works:
```rust
use std::rc::Rc;
fn foo(s: &str) {
// borrow a string for a second
}
// String implements Deref<Target=str>
let owned = "Hello".to_string();
let counted = Rc::new(owned);
// therefore, this works:
foo(&counted);
```
All weve done is wrap our `String` in an `Rc<T>`. But we can now pass the
`Rc<String>` around anywhere wed have a `String`. The signature of `foo`
didnt change, but works just as well with either type. This example has two
conversions: `Rc<String>` to `String` and then `String` to `&str`. Rust will do
this as many times as possible until the types match.
Another very common implementation provided by the standard library is:
```rust
fn foo(s: &[i32]) {
// borrow a slice for a second
}
// Vec<T> implements Deref<Target=[T]>
let owned = vec![1, 2, 3];
foo(&owned);
```
Vectors can `Deref` to a slice.
## Deref and method calls
`Deref` will also kick in when calling a method. In other words, these are
the same two things in Rust:
```rust
struct Foo;
impl Foo {
fn foo(&self) { println!("Foo"); }
}
let f = Foo;
f.foo();
```
Even though `f` isnt a reference, and `foo` takes `&self`, this works.
Thats because these things are the same:
```rust,ignore
f.foo();
(&f).foo();
(&&f).foo();
(&&&&&&&&f).foo();
```
A value of type `&&&&&&&&&&&&&&&&Foo` can still have methods defined on `Foo`
called, because the compiler will insert as many * operations as necessary to
get it right. And since its inserting `*`s, that uses `Deref`.

View File

@ -556,7 +556,7 @@ This sets a few different options, with a logo, favicon, and a root URL.
## Generation options
`rustdoc` also contains a few other options on the command line, for further customiziation:
`rustdoc` also contains a few other options on the command line, for further customization:
- `--html-in-header FILE`: includes the contents of FILE at the end of the
`<head>...</head>` section.

View File

@ -1,5 +1,5 @@
% Getting Started
This first section of the book will get you going with Rust and its tooling.
First, well install Rust. Then: the classic Hello World program. Finally,
First, well install Rust. Then, the classic Hello World program. Finally,
well talk about Cargo, Rusts build system and package manager.

View File

@ -19,7 +19,7 @@ In the example above `x` and `y` have arity 2. `z` has arity 3.
When a compiler is compiling your program, it does a number of different
things. One of the things that it does is turn the text of your program into an
'abstract syntax tree,' or 'AST.' This tree is a representation of the
abstract syntax tree, orAST. This tree is a representation of the
structure of your program. For example, `2 + 3` can be turned into a tree:
```text

View File

@ -32,6 +32,13 @@ $ mkdir src
$ mv main.rs src/main.rs
```
Note that since we're creating an executable, we used `main.rs`. If we
want to make a library instead, we should use `lib.rs`.
Custom file locations for the entry point can be specified
with a [`[[lib]]` or `[[bin]]`][crates-custom] key in the TOML file described below.
[crates-custom]: http://doc.crates.io/manifest.html#configuring-a-target
Cargo expects your source files to live inside a `src` directory. That leaves
the top level for other things, like READMEs, license information, and anything
not related to your code. Cargo helps us keep our projects nice and tidy. A

View File

@ -765,7 +765,7 @@ as `unimplemented!` until youre ready to write them.
# Procedural macros
If Rusts macro system cant do what you need, you may want to write a
[compiler plugin](plugins.html) instead. Compared to `macro_rules!`
[compiler plugin](compiler-plugins.html) instead. Compared to `macro_rules!`
macros, this is significantly more work, the interfaces are much less stable,
and bugs can be much harder to track down. In exchange you get the
flexibility of running arbitrary Rust code within the compiler. Syntax

View File

@ -18,7 +18,7 @@ foo.bar().baz();
Luckily, as you may have guessed with the leading question, you can! Rust provides
the ability to use this method call syntax via the `impl` keyword.
## Method calls
# Method calls
Heres how it works:
@ -83,7 +83,7 @@ impl Circle {
}
```
## Chaining method calls
# Chaining method calls
So, now we know how to call a method, such as `foo.bar()`. But what about our
original example, `foo.bar().baz()`? This is called method chaining, and we
@ -127,7 +127,7 @@ fn grow(&self) -> Circle {
We just say were returning a `Circle`. With this method, we can grow a new
circle to any arbitrary size.
## Static methods
# Static methods
You can also define methods that do not take a `self` parameter. Heres a
pattern thats very common in Rust code:
@ -158,7 +158,7 @@ This static method builds a new `Circle` for us. Note that static methods
are called with the `Struct::method()` syntax, rather than the `ref.method()`
syntax.
## Builder Pattern
# Builder Pattern
Lets say that we want our users to be able to create Circles, but we will
allow them to only set the properties they care about. Otherwise, the `x`

View File

@ -1,3 +1,179 @@
% Mutability
Coming Soon
Mutability, the ability to change something, works a bit differently in Rust
than in other languages. The first aspect of mutability is its non-default
status:
```rust,ignore
let x = 5;
x = 6; // error!
```
We can introduce mutability with the `mut` keyword:
```rust
let mut x = 5;
x = 6; // no problem!
```
This is a mutable [variable binding][vb]. When a binding is mutable, it means
youre allowed to change what the binding points to. So in the above example,
its not so much that the value at `x` is changing, but that the binding
changed from one `i32` to another.
[vb]: variable-bindings.html
If you want to change what the binding points to, youll need a [mutable reference][mr]:
```rust
let mut x = 5;
let y = &mut x;
```
[mr]: references-and-borrowing.html
`y` is an immutable binding to a mutable reference, which means that you cant
bind `y` to something else (`y = &mut z`), but you can mutate the thing thats
bound to `y`. (`*y = 5`) A subtle distinction.
Of course, if you need both:
```rust
let mut x = 5;
let mut y = &mut x;
```
Now `y` can be bound to another value, and the value its referencing can be
changed.
Its important to note that `mut` is part of a [pattern][pattern], so you
can do things like this:
```rust
let (mut x, y) = (5, 6);
fn foo(mut x: i32) {
# }
```
[pattern]: patterns.html
# Interior vs. Exterior Mutability
However, when we say something is immutable in Rust, that doesnt mean that
its not able to be changed: We mean something has exterior mutability. Consider,
for example, [`Arc<T>`][arc]:
```rust
use std::sync::Arc;
let x = Arc::new(5);
let y = x.clone();
```
[arc]: ../std/sync/struct.Arc.html
When we call `clone()`, the `Arc<T>` needs to update the reference count. Yet
weve not used any `mut`s here, `x` is an immutable binding, and we didnt take
`&mut 5` or anything. So what gives?
To this, we have to go back to the core of Rusts guiding philosophy, memory
safety, and the mechanism by which Rust guarantees it, the
[ownership][ownership] system, and more specifically, [borrowing][borrowing]:
> You may have one or the other of these two kinds of borrows, but not both at
> the same time:
>
> * 0 to N references (`&T`) to a resource.
> * exactly one mutable reference (`&mut T`)
[ownership]: ownership.html
[borrowing]: borrowing.html#The-Rules
So, thats the real definition of immutability: is this safe to have two
pointers to? In `Arc<T>`s case, yes: the mutation is entirely contained inside
the structure itself. Its not user facing. For this reason, it hands out `&T`
with `clone()`. If it handed out `&mut T`s, though, that would be a problem.
Other types, like the ones in the [`std::cell`][stdcell] module, have the
opposite: interior mutability. For example:
```rust
use std::cell::RefCell;
let x = RefCell::new(42);
let y = x.borrow_mut();
```
[stdcell]: ../std/cell/index.html
RefCell hands out `&mut` references to whats inside of it with the
`borrow_mut()` method. Isnt that dangerous? What if we do:
```rust,ignore
use std::cell::RefCell;
let x = RefCell::new(42);
let y = x.borrow_mut();
let z = x.borrow_mut();
# (y, z);
```
This will in fact panic, at runtime. This is what `RefCell` does: it enforces
Rusts borrowing rules at runtime, and `panic!`s if theyre violated. This
allows us to get around another aspect of Rusts mutability rules. Lets talk
about it first.
## Field-level mutability
Mutability is a property of either a borrow (`&mut`) or a binding (`let mut`).
This means that, for example, you cannot have a [`struct`][struct] with
some fields mutable and some immutable:
```rust,ignore
struct Point {
x: i32,
mut y: i32, // nope
}
```
The mutability of a struct is in its binding:
```rust,ignore
struct Point {
x: i32,
y: i32,
}
let mut a = Point { x: 5, y: 6 };
a.x = 10;
let b = Point { x: 5, y: 6};
b.x = 10; // error: cannot assign to immutable field `b.x`
```
[struct]: structs.html
However, by using `Cell<T>`, you can emulate field-level mutability:
```
use std::cell::Cell;
struct Point {
x: i32,
y: Cell<i32>,
}
let mut point = Point { x: 5, y: Cell::new(6) };
point.y.set(7);
println!("y: {:?}", point.y);
```
This will print `y: Cell { value: 7 }`. Weve successfully updated `y`.

View File

@ -1,3 +1,83 @@
% Operators and Overloading
Coming soon!
Rust allows for a limited form of operator overloading. There are certain
operators that are able to be overloaded. To support a particular operator
between types, theres a specific trait that you can implement, which then
overloads the operator.
For example, the `+` operator can be overloaded with the `Add` trait:
```rust
use std::ops::Add;
#[derive(Debug)]
struct Point {
x: i32,
y: i32,
}
impl Add for Point {
type Output = Point;
fn add(self, other: Point) -> Point {
Point { x: self.x + other.x, y: self.y + other.y }
}
}
fn main() {
let p1 = Point { x: 1, y: 0 };
let p2 = Point { x: 2, y: 3 };
let p3 = p1 + p2;
println!("{:?}", p3);
}
```
In `main`, we can use `+` on our two `Point`s, since weve implemented
`Add<Output=Point>` for `Point`.
There are a number of operators that can be overloaded this way, and all of
their associated traits live in the [`std::ops`][stdops] module. Check out its
documentation for the full list.
[stdops]: ../std/ops/index.html
Implementing these traits follows a pattern. Lets look at [`Add`][add] in more
detail:
```rust
# mod foo {
pub trait Add<RHS = Self> {
type Output;
fn add(self, rhs: RHS) -> Self::Output;
}
# }
```
[add]: ../std/ops/trait.Add.html
Theres three types in total involved here: the type you `impl Add` for, `RHS`,
which defaults to `Self`, and `Output`. For an expression `let z = x + y`, `x`
is the `Self` type, `y` is the RHS, and `z` is the `Self::Output` type.
```rust
# struct Point;
# use std::ops::Add;
impl Add<i32> for Point {
type Output = f64;
fn add(self, rhs: i32) -> f64 {
// add an i32 to a Point and get an f64
# 1.0
}
}
```
will let you do this:
```rust,ignore
let p: Point = // ...
let x: f64 = p + 2i32;
```

View File

@ -62,14 +62,14 @@ let y = 1.0; // y has type f64
Heres a list of the different numeric types, with links to their documentation
in the standard library:
* [i8](../std/primitive.i8.html)
* [i16](../std/primitive.i16.html)
* [i32](../std/primitive.i32.html)
* [i64](../std/primitive.i64.html)
* [i8](../std/primitive.i8.html)
* [u8](../std/primitive.u8.html)
* [u16](../std/primitive.u16.html)
* [u32](../std/primitive.u32.html)
* [u64](../std/primitive.u64.html)
* [u8](../std/primitive.u8.html)
* [isize](../std/primitive.isize.html)
* [usize](../std/primitive.usize.html)
* [f32](../std/primitive.f32.html)
@ -82,12 +82,12 @@ Lets go over them by category:
Integer types come in two varieties: signed and unsigned. To understand the
difference, lets consider a number with four bits of size. A signed, four-bit
number would let you store numbers from `-8` to `+7`. Signed numbers use
twos compliment representation. An unsigned four bit number, since it does
“twos compliment representation”. An unsigned four bit number, since it does
not need to store negatives, can store values from `0` to `+15`.
Unsigned types use a `u` for their category, and signed types use `i`. The `i`
is for integer. So `u8` is an eight-bit unsigned number, and `i8` is an
eight-bit signed number.
eight-bit signed number.
## Fixed size types
@ -103,7 +103,7 @@ and unsigned varieties. This makes for two types: `isize` and `usize`.
## Floating-point types
Rust also two floating point types: `f32` and `f64`. These correspond to
Rust also has two floating point types: `f32` and `f64`. These correspond to
IEEE-754 single and double precision numbers.
# Arrays
@ -241,8 +241,8 @@ println!("x is {}", x);
Remember [before][let] when I said the left-hand side of a `let` statement was more
powerful than just assigning a binding? Here we are. We can put a pattern on
the left-hand side of the `let`, and if it matches up to the right-hand side,
we can assign multiple bindings at once. In this case, `let` "destructures,"
or "breaks up," the tuple, and assigns the bits to three bindings.
we can assign multiple bindings at once. In this case, `let` “destructures”
or “breaks up” the tuple, and assigns the bits to three bindings.
[let]: variable-bindings.html

View File

@ -219,10 +219,10 @@ fn it_works() {
This is a very common use of `assert_eq!`: call some function with
some known arguments and compare it to the expected output.
# The `test` module
# The `tests` module
There is one way in which our existing example is not idiomatic: it's
missing the test module. The idiomatic way of writing our example
missing the `tests` module. The idiomatic way of writing our example
looks like this:
```{rust,ignore}
@ -231,7 +231,7 @@ pub fn add_two(a: i32) -> i32 {
}
#[cfg(test)]
mod test {
mod tests {
use super::add_two;
#[test]
@ -241,7 +241,7 @@ mod test {
}
```
There's a few changes here. The first is the introduction of a `mod test` with
There's a few changes here. The first is the introduction of a `mod tests` with
a `cfg` attribute. The module allows us to group all of our tests together, and
to also define helper functions if needed, that don't become a part of the rest
of our crate. The `cfg` attribute only compiles our test code if we're
@ -260,7 +260,7 @@ pub fn add_two(a: i32) -> i32 {
}
#[cfg(test)]
mod test {
mod tests {
use super::*;
#[test]
@ -279,7 +279,7 @@ $ cargo test
Running target/adder-91b3e234d4ed382a
running 1 test
test test::it_works ... ok
test tests::it_works ... ok
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured
@ -292,7 +292,7 @@ test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured
It works!
The current convention is to use the `test` module to hold your "unit-style"
The current convention is to use the `tests` module to hold your "unit-style"
tests. Anything that just tests one small bit of functionality makes sense to
go here. But what about "integration-style" tests instead? For that, we have
the `tests` directory
@ -325,7 +325,7 @@ $ cargo test
Running target/adder-91b3e234d4ed382a
running 1 test
test test::it_works ... ok
test tests::it_works ... ok
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured
@ -346,7 +346,7 @@ test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured
Now we have three sections: our previous test is also run, as well as our new
one.
That's all there is to the `tests` directory. The `test` module isn't needed
That's all there is to the `tests` directory. The `tests` module isn't needed
here, since the whole thing is focused on tests.
Let's finally check out that third section: documentation tests.
@ -382,7 +382,7 @@ pub fn add_two(a: i32) -> i32 {
}
#[cfg(test)]
mod test {
mod tests {
use super::*;
#[test]
@ -405,7 +405,7 @@ $ cargo test
Running target/adder-91b3e234d4ed382a
running 1 test
test test::it_works ... ok
test tests::it_works ... ok
test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured

View File

@ -155,7 +155,7 @@ A function that takes a trait object is not specialized to each of the types
that implements `Foo`: only one copy is generated, often (but not always)
resulting in less code bloat. However, this comes at the cost of requiring
slower virtual function calls, and effectively inhibiting any chance of
inlining and related optimisations from occurring.
inlining and related optimizations from occurring.
### Why pointers?

View File

@ -184,7 +184,7 @@ wont have its methods:
```rust,ignore
let mut f = std::fs::File::open("foo.txt").ok().expect("Couldnt open foo.txt");
let result = f.write("whatever".as_bytes());
# result.unwrap(); // ignore the erorr
# result.unwrap(); // ignore the error
```
Heres the error:
@ -203,7 +203,7 @@ use std::io::Write;
let mut f = std::fs::File::open("foo.txt").ok().expect("Couldnt open foo.txt");
let result = f.write("whatever".as_bytes());
# result.unwrap(); // ignore the erorr
# result.unwrap(); // ignore the error
```
This will compile without error.

View File

@ -89,7 +89,7 @@ not, and so we need to pass an explicit `&b`.
The form of UFCS we just talked about:
```rust,ignore
Type::method(args);
Trait::method(args);
```
Is a short-hand. Theres an expanded form of this thats needed in some

View File

@ -1,6 +1,6 @@
% Variable Bindings
Vitually every non-Hello World Rust program uses *variable bindings*. They
Virtually every non-'Hello World Rust program uses *variable bindings*. They
look like this:
```rust

View File

@ -1,8 +1,9 @@
% Vectors
A vector is a dynamic or growable array, implemented as the standard
library type [`Vec<T>`][vec]. That `<T>` is a [generic][generic], meaning we
can have vectors of any type. Vectors always allocate their data on the heap.
library type [`Vec<T>`][vec]. The `T` means that we can have vectors
of any type (see the chapter on [generics][generic] for more).
Vectors always allocate their data on the heap.
You can create them with the `vec!` macro:
```rust
@ -56,3 +57,4 @@ Vectors have many more useful methods, which you can read about in [their
API documentation][vec].
[vec]: ../std/vec/index.html
[generic]: generics.html

View File

@ -505,10 +505,20 @@ trait_items
;
trait_item
: trait_type
: trait_const
| trait_type
| trait_method
;
trait_const
: maybe_outer_attrs CONST ident maybe_const_default ';' { $$ = mk_node("ConstTraitItem", 3, $1, $3, $4); }
;
maybe_const_default
: '=' expr { $$ = mk_node("ConstDefault", 1, $2); }
| %empty { $$ = mk_none(); }
;
trait_type
: maybe_outer_attrs TYPE ty_param ';' { $$ = mk_node("TypeTraitItem", 2, $1, $3); }
;
@ -611,7 +621,16 @@ impl_items
impl_item
: impl_method
| item_macro
| trait_type
| impl_const
| impl_type
;
impl_const
: attrs_and_vis item_const { $$ = mk_node("ImplConst", 1, $1, $2); }
;
impl_type
: attrs_and_vis TYPE ident generic_params '=' ty_sum ';' { $$ = mk_node("ImplType", 4, $1, $3, $4, $6); }
;
item_fn

View File

@ -355,7 +355,6 @@ impl<T: Clone> Arc<T> {
}
}
#[unsafe_destructor]
#[stable(feature = "rust1", since = "1.0.0")]
impl<T> Drop for Arc<T> {
/// Drops the `Arc<T>`.
@ -489,7 +488,6 @@ impl<T> Clone for Weak<T> {
}
}
#[unsafe_destructor]
#[stable(feature = "rust1", since = "1.0.0")]
impl<T> Drop for Weak<T> {
/// Drops the `Weak<T>`.

View File

@ -211,7 +211,9 @@ mod imp {
}
// -lpthread needs to occur after -ljemalloc, the earlier argument isn't enough
#[cfg(all(not(windows), not(target_os = "android")))]
#[cfg(all(not(windows),
not(target_os = "android"),
not(target_env = "musl")))]
#[link(name = "pthread")]
extern {}
@ -384,7 +386,7 @@ mod imp {
}
#[cfg(test)]
mod test {
mod tests {
extern crate test;
use self::test::Bencher;
use boxed::Box;

View File

@ -73,7 +73,7 @@
#![feature(allocator)]
#![feature(custom_attribute)]
#![feature(fundamental)]
#![feature(lang_items, unsafe_destructor)]
#![feature(lang_items)]
#![feature(box_syntax)]
#![feature(optin_builtin_traits)]
#![feature(unboxed_closures)]

View File

@ -375,7 +375,6 @@ impl<T> Deref for Rc<T> {
}
}
#[unsafe_destructor]
#[stable(feature = "rust1", since = "1.0.0")]
impl<T> Drop for Rc<T> {
/// Drops the `Rc<T>`.
@ -693,7 +692,6 @@ impl<T> Weak<T> {
}
}
#[unsafe_destructor]
#[stable(feature = "rust1", since = "1.0.0")]
impl<T> Drop for Weak<T> {
/// Drops the `Weak<T>`.

View File

@ -35,7 +35,6 @@
#![feature(core)]
#![feature(staged_api)]
#![feature(unboxed_closures)]
#![feature(unsafe_destructor)]
#![cfg_attr(test, feature(test))]
extern crate alloc;
@ -124,7 +123,6 @@ fn chunk(size: usize, is_copy: bool) -> Chunk {
}
}
#[unsafe_destructor]
impl<'longer_than_self> Drop for Arena<'longer_than_self> {
fn drop(&mut self) {
unsafe {
@ -510,7 +508,6 @@ impl<T> TypedArena<T> {
}
}
#[unsafe_destructor]
impl<T> Drop for TypedArena<T> {
fn drop(&mut self) {
unsafe {

View File

@ -546,7 +546,7 @@ impl<T: Ord> BinaryHeap<T> {
#[unstable(feature = "collections",
reason = "matches collection reform specification, waiting for dust to settle")]
pub fn drain(&mut self) -> Drain<T> {
Drain { iter: self.data.drain() }
Drain { iter: self.data.drain(..) }
}
/// Drops all items from the binary heap.

View File

@ -270,14 +270,12 @@ impl<T> DoubleEndedIterator for RawItems<T> {
}
}
#[unsafe_destructor]
impl<T> Drop for RawItems<T> {
fn drop(&mut self) {
for _ in self.by_ref() {}
}
}
#[unsafe_destructor]
impl<K, V> Drop for Node<K, V> {
fn drop(&mut self) {
if self.keys.is_null() ||
@ -1394,7 +1392,6 @@ impl<K, V> TraversalImpl for MoveTraversalImpl<K, V> {
}
}
#[unsafe_destructor]
impl<K, V> Drop for MoveTraversalImpl<K, V> {
fn drop(&mut self) {
// We need to cleanup the stored values manually, as the RawItems destructor would run

View File

@ -394,14 +394,71 @@
//!
//! ## Precision
//!
//! For non-numeric types, this can be considered a "maximum width". If the
//! resulting string is longer than this width, then it is truncated down to
//! this many characters and only those are emitted.
//! For non-numeric types, this can be considered a "maximum width". If the resulting string is
//! longer than this width, then it is truncated down to this many characters and only those are
//! emitted.
//!
//! For integral types, this has no meaning currently.
//!
//! For floating-point types, this indicates how many digits after the decimal
//! point should be printed.
//! For floating-point types, this indicates how many digits after the decimal point should be
//! printed.
//!
//! There are three possible ways to specify the desired `precision`:
//!
//! There are three possible ways to specify the desired `precision`:
//! 1. An integer `.N`,
//! 2. an integer followed by dollar sign `.N$`, or
//! 3. an asterisk `.*`.
//!
//! The first specification, `.N`, means the integer `N` itself is the precision.
//!
//! The second, `.N$`, means use format *argument* `N` (which must be a `usize`) as the precision.
//!
//! Finally, `.*` means that this `{...}` is associated with *two* format inputs rather than one:
//! the first input holds the `usize` precision, and the second holds the value to print. Note
//! that in this case, if one uses the format string `{<arg>:<spec>.*}`, then the `<arg>` part
//! refers to the *value* to print, and the `precision` must come in the input preceding `<arg>`.
//!
//! For example, these:
//!
//! ```
//! // Hello {arg 0 (x)} is {arg 1 (0.01} with precision specified inline (5)}
//! println!("Hello {0} is {1:.5}", "x", 0.01);
//!
//! // Hello {arg 1 (x)} is {arg 2 (0.01} with precision specified in arg 0 (5)}
//! println!("Hello {1} is {2:.0$}", 5, "x", 0.01);
//!
//! // Hello {arg 0 (x)} is {arg 2 (0.01} with precision specified in arg 1 (5)}
//! println!("Hello {0} is {2:.1$}", "x", 5, 0.01);
//!
//! // Hello {next arg (x)} is {second of next two args (0.01} with precision
//! // specified in first of next two args (5)}
//! println!("Hello {} is {:.*}", "x", 5, 0.01);
//!
//! // Hello {next arg (x)} is {arg 2 (0.01} with precision
//! // specified in its predecessor (5)}
//! println!("Hello {} is {2:.*}", "x", 5, 0.01);
//! ```
//!
//! All print the same thing:
//!
//! ```text
//! Hello x is 0.01000
//! ```
//!
//! While these:
//!
//! ```
//! println!("{}, `{name:.*}` has 3 fractional digits", "Hello", 3, name=1234.56);
//! println!("{}, `{name:.*}` has 3 characters", "Hello", 3, name="1234.56");
//! ```
//!
//! print two significantly different things:
//!
//! ```text
//! Hello, `1234.560` has 3 fractional digits
//! Hello, `123` has 3 characters
//! ```
//!
//! # Escaping
//!

View File

@ -33,7 +33,6 @@
#![feature(staged_api)]
#![feature(unboxed_closures)]
#![feature(unicode)]
#![feature(unsafe_destructor)]
#![feature(unique)]
#![feature(unsafe_no_drop_flag, filling_drop)]
#![feature(step_by)]
@ -42,7 +41,8 @@
#![feature(slice_patterns)]
#![feature(debug_builders)]
#![feature(utf8_error)]
#![cfg_attr(test, feature(rand, rustc_private, test, hash, collections))]
#![cfg_attr(test, feature(rand, rustc_private, test, hash, collections,
collections_drain, collections_range))]
#![cfg_attr(test, allow(deprecated))] // rand
#![feature(no_std)]
@ -82,6 +82,7 @@ pub mod borrow;
pub mod enum_set;
pub mod fmt;
pub mod linked_list;
pub mod range;
pub mod slice;
pub mod str;
pub mod string;

View File

@ -624,7 +624,6 @@ impl<T> LinkedList<T> {
}
}
#[unsafe_destructor]
#[stable(feature = "rust1", since = "1.0.0")]
impl<T> Drop for LinkedList<T> {
fn drop(&mut self) {
@ -933,7 +932,7 @@ impl<A: Hash> Hash for LinkedList<A> {
}
#[cfg(test)]
mod test {
mod tests {
use std::clone::Clone;
use std::iter::{Iterator, IntoIterator};
use std::option::Option::{Some, None, self};

View File

@ -0,0 +1,45 @@
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![unstable(feature = "collections_range", reason = "was just added")]
//! Range syntax.
use core::option::Option::{self, None, Some};
use core::ops::{RangeFull, Range, RangeTo, RangeFrom};
/// **RangeArgument** is implemented by Rust's built-in range types, produced
/// by range syntax like `..`, `a..`, `..b` or `c..d`.
pub trait RangeArgument<T> {
/// Start index (inclusive)
///
/// Return start value if present, else `None`.
fn start(&self) -> Option<&T> { None }
/// End index (exclusive)
///
/// Return end value if present, else `None`.
fn end(&self) -> Option<&T> { None }
}
impl<T> RangeArgument<T> for RangeFull {}
impl<T> RangeArgument<T> for RangeFrom<T> {
fn start(&self) -> Option<&T> { Some(&self.start) }
}
impl<T> RangeArgument<T> for RangeTo<T> {
fn end(&self) -> Option<&T> { Some(&self.end) }
}
impl<T> RangeArgument<T> for Range<T> {
fn start(&self) -> Option<&T> { Some(&self.start) }
fn end(&self) -> Option<&T> { Some(&self.end) }
}

View File

@ -951,12 +951,13 @@ impl<'a> Deref for DerefString<'a> {
/// # #![feature(collections)]
/// use std::string::as_string;
///
/// fn string_consumer(s: String) {
/// assert_eq!(s, "foo".to_string());
/// // Let's pretend we have a function that requires `&String`
/// fn string_consumer(s: &String) {
/// assert_eq!(s, "foo");
/// }
///
/// let string = as_string("foo").clone();
/// string_consumer(string);
/// // Provide a `&String` from a `&str` without allocating
/// string_consumer(&as_string("foo"));
/// ```
#[unstable(feature = "collections")]
pub fn as_string<'a>(x: &'a str) -> DerefString<'a> {

View File

@ -69,6 +69,8 @@ use core::usize;
use borrow::{Cow, IntoCow};
use super::range::RangeArgument;
// FIXME- fix places which assume the max vector allowed has memory usize::MAX.
static MAX_MEMORY_SIZE: usize = isize::MAX as usize;
@ -116,11 +118,7 @@ static MAX_MEMORY_SIZE: usize = isize::MAX as usize;
/// stack.push(2);
/// stack.push(3);
///
/// loop {
/// let top = match stack.pop() {
/// None => break, // empty
/// Some(x) => x,
/// };
/// while let Some(top) = stack.pop() {
/// // Prints 3, 2, 1
/// println!("{}", top);
/// }
@ -540,7 +538,7 @@ impl<T> Vec<T> {
///
/// # Panics
///
/// Panics if `i` is out of bounds.
/// Panics if `index` is out of bounds.
///
/// # Examples
///
@ -718,36 +716,61 @@ impl<T> Vec<T> {
unsafe { other.set_len(0); }
}
/// Creates a draining iterator that clears the `Vec` and iterates over
/// the removed items from start to end.
/// Create a draining iterator that removes the specified range in the vector
/// and yields the removed items from start to end. The element range is
/// removed even if the iterator is not consumed until the end.
///
/// Note: It is unspecified how many elements are removed from the vector,
/// if the `Drain` value is leaked.
///
/// # Panics
///
/// Panics if the starting point is greater than the end point or if
/// the end point is greater than the length of the vector.
///
/// # Examples
///
/// ```
/// # #![feature(collections)]
/// let mut v = vec!["a".to_string(), "b".to_string()];
/// for s in v.drain() {
/// // s has type String, not &String
/// println!("{}", s);
/// }
/// assert!(v.is_empty());
/// # #![feature(collections_drain, collections_range)]
///
/// // Draining using `..` clears the whole vector.
/// let mut v = vec![1, 2, 3];
/// let u: Vec<_> = v.drain(..).collect();
/// assert_eq!(v, &[]);
/// assert_eq!(u, &[1, 2, 3]);
/// ```
#[inline]
#[unstable(feature = "collections",
reason = "matches collection reform specification, waiting for dust to settle")]
pub fn drain(&mut self) -> Drain<T> {
#[unstable(feature = "collections_drain",
reason = "recently added, matches RFC")]
pub fn drain<R>(&mut self, range: R) -> Drain<T> where R: RangeArgument<usize> {
// Memory safety
//
// When the Drain is first created, it shortens the length of
// the source vector to make sure no uninitalized or moved-from elements
// are accessible at all if the Drain's destructor never gets to run.
//
// Drain will ptr::read out the values to remove.
// When finished, remaining tail of the vec is copied back to cover
// the hole, and the vector length is restored to the new length.
//
let len = self.len();
let start = *range.start().unwrap_or(&0);
let end = *range.end().unwrap_or(&len);
assert!(start <= end);
assert!(end <= len);
unsafe {
let begin = *self.ptr as *const T;
let end = if mem::size_of::<T>() == 0 {
(*self.ptr as usize + self.len()) as *const T
} else {
(*self.ptr).offset(self.len() as isize) as *const T
};
self.set_len(0);
// set self.vec length's to start, to be safe in case Drain is leaked
self.set_len(start);
// Use the borrow in the IterMut to indicate borrowing behavior of the
// whole Drain iterator (like &mut T).
let range_slice = slice::from_raw_parts_mut(
self.as_mut_ptr().offset(start as isize),
end - start);
Drain {
ptr: begin,
end: end,
marker: PhantomData,
tail_start: end,
tail_len: len - end,
iter: range_slice.iter_mut(),
vec: self as *mut _,
}
}
}
@ -1603,7 +1626,6 @@ impl<'a, T: Clone> Add<&'a [T]> for Vec<T> {
}
}
#[unsafe_destructor]
#[stable(feature = "rust1", since = "1.0.0")]
impl<T> Drop for Vec<T> {
fn drop(&mut self) {
@ -1785,7 +1807,6 @@ impl<T> DoubleEndedIterator for IntoIter<T> {
#[stable(feature = "rust1", since = "1.0.0")]
impl<T> ExactSizeIterator for IntoIter<T> {}
#[unsafe_destructor]
#[stable(feature = "rust1", since = "1.0.0")]
impl<T> Drop for IntoIter<T> {
fn drop(&mut self) {
@ -1799,14 +1820,16 @@ impl<T> Drop for IntoIter<T> {
}
}
/// An iterator that drains a vector.
#[unsafe_no_drop_flag]
#[unstable(feature = "collections",
reason = "recently added as part of collections reform 2")]
pub struct Drain<'a, T:'a> {
ptr: *const T,
end: *const T,
marker: PhantomData<&'a T>,
/// A draining iterator for `Vec<T>`.
#[unstable(feature = "collections_drain", reason = "recently added")]
pub struct Drain<'a, T: 'a> {
/// Index of tail to preserve
tail_start: usize,
/// Length of tail
tail_len: usize,
/// Current remaining range to remove
iter: slice::IterMut<'a, T>,
vec: *mut Vec<T>,
}
unsafe impl<'a, T: Sync> Sync for Drain<'a, T> {}
@ -1818,34 +1841,15 @@ impl<'a, T> Iterator for Drain<'a, T> {
#[inline]
fn next(&mut self) -> Option<T> {
unsafe {
if self.ptr == self.end {
None
} else {
if mem::size_of::<T>() == 0 {
// purposefully don't use 'ptr.offset' because for
// vectors with 0-size elements this would return the
// same pointer.
self.ptr = mem::transmute(self.ptr as usize + 1);
// Use a non-null pointer value
Some(ptr::read(EMPTY as *mut T))
} else {
let old = self.ptr;
self.ptr = self.ptr.offset(1);
Some(ptr::read(old))
}
self.iter.next().map(|elt|
unsafe {
ptr::read(elt as *const _)
}
}
)
}
#[inline]
fn size_hint(&self) -> (usize, Option<usize>) {
let diff = (self.end as usize) - (self.ptr as usize);
let size = mem::size_of::<T>();
let exact = diff / (if size == 0 {1} else {size});
(exact, Some(exact))
self.iter.size_hint()
}
}
@ -1853,41 +1857,39 @@ impl<'a, T> Iterator for Drain<'a, T> {
impl<'a, T> DoubleEndedIterator for Drain<'a, T> {
#[inline]
fn next_back(&mut self) -> Option<T> {
unsafe {
if self.end == self.ptr {
None
} else {
if mem::size_of::<T>() == 0 {
// See above for why 'ptr.offset' isn't used
self.end = mem::transmute(self.end as usize - 1);
self.iter.next_back().map(|elt|
unsafe {
ptr::read(elt as *const _)
}
)
}
}
// Use a non-null pointer value
Some(ptr::read(EMPTY as *mut T))
} else {
self.end = self.end.offset(-1);
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T> Drop for Drain<'a, T> {
fn drop(&mut self) {
// exhaust self first
while let Some(_) = self.next() { }
Some(ptr::read(self.end))
}
if self.tail_len > 0 {
unsafe {
let source_vec = &mut *self.vec;
// memmove back untouched tail, update to new length
let start = source_vec.len();
let tail = self.tail_start;
let src = source_vec.as_ptr().offset(tail as isize);
let dst = source_vec.as_mut_ptr().offset(start as isize);
ptr::copy(src, dst, self.tail_len);
source_vec.set_len(start + self.tail_len);
}
}
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T> ExactSizeIterator for Drain<'a, T> {}
#[unsafe_destructor]
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T> Drop for Drain<'a, T> {
fn drop(&mut self) {
// self.ptr == self.end == mem::POST_DROP_USIZE if drop has already been called,
// so we can use #[unsafe_no_drop_flag].
// destroy the remaining elements
for _x in self.by_ref() {}
}
}
////////////////////////////////////////////////////////////////////////////////
// Conversion from &[T] to &Vec<T>
////////////////////////////////////////////////////////////////////////////////
@ -1909,7 +1911,6 @@ impl<'a, T> Deref for DerefVec<'a, T> {
}
// Prevent the inner `Vec<T>` from attempting to deallocate memory.
#[unsafe_destructor]
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T> Drop for DerefVec<'a, T> {
fn drop(&mut self) {
@ -1919,6 +1920,22 @@ impl<'a, T> Drop for DerefVec<'a, T> {
}
/// Converts a slice to a wrapper type providing a `&Vec<T>` reference.
///
/// # Examples
///
/// ```
/// # #![feature(collections)]
/// use std::vec::as_vec;
///
/// // Let's pretend we have a function that requires `&Vec<i32>`
/// fn vec_consumer(s: &Vec<i32>) {
/// assert_eq!(s, &[1, 2, 3]);
/// }
///
/// // Provide a `&Vec<i32>` from a `&[i32]` without allocating
/// let values = [1, 2, 3];
/// vec_consumer(&as_vec(&values));
/// ```
#[unstable(feature = "collections")]
pub fn as_vec<'a, T>(x: &'a [T]) -> DerefVec<'a, T> {
unsafe {
@ -1962,7 +1979,6 @@ struct PartialVecZeroSized<T,U> {
marker: PhantomData<::core::cell::Cell<(T,U)>>,
}
#[unsafe_destructor]
impl<T,U> Drop for PartialVecNonZeroSized<T,U> {
fn drop(&mut self) {
unsafe {
@ -1988,7 +2004,6 @@ impl<T,U> Drop for PartialVecNonZeroSized<T,U> {
}
}
#[unsafe_destructor]
impl<T,U> Drop for PartialVecZeroSized<T,U> {
fn drop(&mut self) {
unsafe {

View File

@ -59,7 +59,6 @@ impl<T: Clone> Clone for VecDeque<T> {
}
}
#[unsafe_destructor]
#[stable(feature = "rust1", since = "1.0.0")]
impl<T> Drop for VecDeque<T> {
fn drop(&mut self) {
@ -1612,7 +1611,6 @@ pub struct Drain<'a, T: 'a> {
inner: &'a mut VecDeque<T>,
}
#[unsafe_destructor]
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T: 'a> Drop for Drain<'a, T> {
fn drop(&mut self) {
@ -1772,7 +1770,7 @@ impl<T: fmt::Debug> fmt::Debug for VecDeque<T> {
}
#[cfg(test)]
mod test {
mod tests {
use core::iter::{Iterator, self};
use core::option::Option::Some;

View File

@ -418,7 +418,7 @@ impl<V> VecMap<V> {
}
let filter: fn((usize, Option<V>)) -> Option<(usize, V)> = filter; // coerce to fn ptr
Drain { iter: self.v.drain().enumerate().filter_map(filter) }
Drain { iter: self.v.drain(..).enumerate().filter_map(filter) }
}
/// Returns the number of elements in the map.

View File

@ -10,6 +10,7 @@
#![feature(box_syntax)]
#![feature(collections)]
#![feature(collections_drain)]
#![feature(core)]
#![feature(hash)]
#![feature(rand)]
@ -17,7 +18,6 @@
#![feature(test)]
#![feature(unboxed_closures)]
#![feature(unicode)]
#![feature(unsafe_destructor)]
#![feature(into_cow)]
#![feature(step_by)]
#![cfg_attr(test, feature(str_char))]

View File

@ -18,7 +18,6 @@ struct DropCounter<'a> {
count: &'a mut u32
}
#[unsafe_destructor]
impl<'a> Drop for DropCounter<'a> {
fn drop(&mut self) {
*self.count += 1;
@ -460,7 +459,7 @@ fn test_move_items_zero_sized() {
fn test_drain_items() {
let mut vec = vec![1, 2, 3];
let mut vec2 = vec![];
for i in vec.drain() {
for i in vec.drain(..) {
vec2.push(i);
}
assert_eq!(vec, []);
@ -471,7 +470,7 @@ fn test_drain_items() {
fn test_drain_items_reverse() {
let mut vec = vec![1, 2, 3];
let mut vec2 = vec![];
for i in vec.drain().rev() {
for i in vec.drain(..).rev() {
vec2.push(i);
}
assert_eq!(vec, []);
@ -482,13 +481,43 @@ fn test_drain_items_reverse() {
fn test_drain_items_zero_sized() {
let mut vec = vec![(), (), ()];
let mut vec2 = vec![];
for i in vec.drain() {
for i in vec.drain(..) {
vec2.push(i);
}
assert_eq!(vec, []);
assert_eq!(vec2, [(), (), ()]);
}
#[test]
#[should_panic]
fn test_drain_out_of_bounds() {
let mut v = vec![1, 2, 3, 4, 5];
v.drain(5..6);
}
#[test]
fn test_drain_range() {
let mut v = vec![1, 2, 3, 4, 5];
for _ in v.drain(4..) {
}
assert_eq!(v, &[1, 2, 3, 4]);
let mut v: Vec<_> = (1..6).map(|x| x.to_string()).collect();
for _ in v.drain(1..4) {
}
assert_eq!(v, &[1.to_string(), 5.to_string()]);
let mut v: Vec<_> = (1..6).map(|x| x.to_string()).collect();
for _ in v.drain(1..4).rev() {
}
assert_eq!(v, &[1.to_string(), 5.to_string()]);
let mut v: Vec<_> = vec![(); 5];
for _ in v.drain(1..4).rev() {
}
assert_eq!(v, &[(), ()]);
}
#[test]
fn test_into_boxed_slice() {
let xs = vec![1, 2, 3];

View File

@ -129,6 +129,12 @@ pub struct AtomicPtr<T> {
_marker: PhantomData<*mut T>,
}
impl<T> Default for AtomicPtr<T> {
fn default() -> AtomicPtr<T> {
AtomicPtr::new(::ptr::null_mut())
}
}
unsafe impl<T> Sync for AtomicPtr<T> {}
/// Atomic memory orderings

View File

@ -417,7 +417,7 @@ impl<T> RefCell<T> {
///
/// let result = thread::spawn(move || {
/// let c = RefCell::new(5);
/// let m = c.borrow_mut();
/// let m = c.borrow();
///
/// let b = c.borrow_mut(); // this causes a panic
/// }).join();
@ -493,7 +493,6 @@ impl<'b> BorrowRef<'b> {
}
}
#[unsafe_destructor]
impl<'b> Drop for BorrowRef<'b> {
#[inline]
fn drop(&mut self) {
@ -557,7 +556,6 @@ struct BorrowRefMut<'b> {
_borrow: &'b Cell<BorrowFlag>,
}
#[unsafe_destructor]
impl<'b> Drop for BorrowRefMut<'b> {
#[inline]
fn drop(&mut self) {

View File

@ -11,7 +11,7 @@
//! Traits for conversions between types.
//!
//! The traits in this module provide a general way to talk about conversions from one type to
//! another. They follow the standard Rust conventions of `as`/`to`/`into`/`from`.
//! another. They follow the standard Rust conventions of `as`/`into`/`from`.
//!
//! Like many traits, these are often used as bounds for generic functions, to support arguments of
//! multiple types.
@ -83,10 +83,8 @@ pub trait Into<T>: Sized {
/// `String` implements `From<&str>`:
///
/// ```
/// let s = "hello";
/// let string = "hello".to_string();
///
/// let other_string: String = From::from(s);
/// let other_string = String::from("hello");
///
/// assert_eq!(string, other_string);
/// ```

View File

@ -34,8 +34,7 @@ mod num;
mod float;
mod builders;
#[cfg_attr(stage0, stable(feature = "rust1", since = "1.0.0"))]
#[cfg_attr(not(stage0), unstable(feature = "core", reason = "internal to format_args!"))]
#[unstable(feature = "core", reason = "internal to format_args!")]
#[doc(hidden)]
pub mod rt {
pub mod v1;
@ -148,8 +147,7 @@ enum Void {}
/// compile time it is ensured that the function and the value have the correct
/// types, and then this struct is used to canonicalize arguments to one type.
#[derive(Copy)]
#[cfg_attr(stage0, stable(feature = "rust1", since = "1.0.0"))]
#[cfg_attr(not(stage0), unstable(feature = "core", reason = "internal to format_args!"))]
#[unstable(feature = "core", reason = "internal to format_args!")]
#[doc(hidden)]
pub struct ArgumentV1<'a> {
value: &'a Void,
@ -169,8 +167,7 @@ impl<'a> ArgumentV1<'a> {
}
#[doc(hidden)]
#[cfg_attr(stage0, stable(feature = "rust1", since = "1.0.0"))]
#[cfg_attr(not(stage0), unstable(feature = "core", reason = "internal to format_args!"))]
#[unstable(feature = "core", reason = "internal to format_args!")]
pub fn new<'b, T>(x: &'b T,
f: fn(&T, &mut Formatter) -> Result) -> ArgumentV1<'b> {
unsafe {
@ -182,8 +179,7 @@ impl<'a> ArgumentV1<'a> {
}
#[doc(hidden)]
#[cfg_attr(stage0, stable(feature = "rust1", since = "1.0.0"))]
#[cfg_attr(not(stage0), unstable(feature = "core", reason = "internal to format_args!"))]
#[unstable(feature = "core", reason = "internal to format_args!")]
pub fn from_usize(x: &usize) -> ArgumentV1 {
ArgumentV1::new(x, ArgumentV1::show_usize)
}
@ -206,8 +202,7 @@ impl<'a> Arguments<'a> {
/// When using the format_args!() macro, this function is used to generate the
/// Arguments structure.
#[doc(hidden)] #[inline]
#[cfg_attr(stage0, stable(feature = "rust1", since = "1.0.0"))]
#[cfg_attr(not(stage0), unstable(feature = "core", reason = "internal to format_args!"))]
#[unstable(feature = "core", reason = "internal to format_args!")]
pub fn new_v1(pieces: &'a [&'a str],
args: &'a [ArgumentV1<'a>]) -> Arguments<'a> {
Arguments {
@ -224,8 +219,7 @@ impl<'a> Arguments<'a> {
/// created with `argumentusize`. However, failing to do so doesn't cause
/// unsafety, but will ignore invalid .
#[doc(hidden)] #[inline]
#[cfg_attr(stage0, stable(feature = "rust1", since = "1.0.0"))]
#[cfg_attr(not(stage0), unstable(feature = "core", reason = "internal to format_args!"))]
#[unstable(feature = "core", reason = "internal to format_args!")]
pub fn new_v1_formatted(pieces: &'a [&'a str],
args: &'a [ArgumentV1<'a>],
fmt: &'a [rt::v1::Argument]) -> Arguments<'a> {

View File

@ -14,69 +14,46 @@
//! These definitions are similar to their `ct` equivalents, but differ in that
//! these can be statically allocated and are slightly optimized for the runtime
#![cfg_attr(stage0, stable(feature = "rust1", since = "1.0.0"))]
#![cfg_attr(not(stage0), unstable(feature = "core", reason = "internal to format_args!"))]
#![unstable(feature = "core", reason = "internal to format_args!")]
#[derive(Copy, Clone)]
#[cfg_attr(stage0, stable(feature = "rust1", since = "1.0.0"))]
pub struct Argument {
#[cfg_attr(stage0, stable(feature = "rust1", since = "1.0.0"))]
pub position: Position,
#[cfg_attr(stage0, stable(feature = "rust1", since = "1.0.0"))]
pub format: FormatSpec,
}
#[derive(Copy, Clone)]
#[cfg_attr(stage0, stable(feature = "rust1", since = "1.0.0"))]
pub struct FormatSpec {
#[cfg_attr(stage0, stable(feature = "rust1", since = "1.0.0"))]
pub fill: char,
#[cfg_attr(stage0, stable(feature = "rust1", since = "1.0.0"))]
pub align: Alignment,
#[cfg_attr(stage0, stable(feature = "rust1", since = "1.0.0"))]
pub flags: u32,
#[cfg_attr(stage0, stable(feature = "rust1", since = "1.0.0"))]
pub precision: Count,
#[cfg_attr(stage0, stable(feature = "rust1", since = "1.0.0"))]
pub width: Count,
}
/// Possible alignments that can be requested as part of a formatting directive.
#[derive(Copy, Clone, PartialEq)]
#[cfg_attr(stage0, stable(feature = "rust1", since = "1.0.0"))]
pub enum Alignment {
/// Indication that contents should be left-aligned.
#[cfg_attr(stage0, stable(feature = "rust1", since = "1.0.0"))]
Left,
/// Indication that contents should be right-aligned.
#[cfg_attr(stage0, stable(feature = "rust1", since = "1.0.0"))]
Right,
/// Indication that contents should be center-aligned.
#[cfg_attr(stage0, stable(feature = "rust1", since = "1.0.0"))]
Center,
/// No alignment was requested.
#[cfg_attr(stage0, stable(feature = "rust1", since = "1.0.0"))]
Unknown,
}
#[derive(Copy, Clone)]
#[cfg_attr(stage0, stable(feature = "rust1", since = "1.0.0"))]
pub enum Count {
#[cfg_attr(stage0, stable(feature = "rust1", since = "1.0.0"))]
Is(usize),
#[cfg_attr(stage0, stable(feature = "rust1", since = "1.0.0"))]
Param(usize),
#[cfg_attr(stage0, stable(feature = "rust1", since = "1.0.0"))]
NextParam,
#[cfg_attr(stage0, stable(feature = "rust1", since = "1.0.0"))]
Implied,
}
#[derive(Copy, Clone)]
#[cfg_attr(stage0, stable(feature = "rust1", since = "1.0.0"))]
pub enum Position {
#[cfg_attr(stage0, stable(feature = "rust1", since = "1.0.0"))]
Next,
#[cfg_attr(stage0, stable(feature = "rust1", since = "1.0.0"))]
At(usize)
}

View File

@ -139,6 +139,21 @@ extern "rust-intrinsic" {
pub fn atomic_fence_rel();
pub fn atomic_fence_acqrel();
/// A compiler-only memory barrier.
///
/// Memory accesses will never be reordered across this barrier by the compiler,
/// but no instructions will be emitted for it. This is appropriate for operations
/// on the same thread that may be preempted, such as when interacting with signal
/// handlers.
#[cfg(not(stage0))] // SNAP 857ef6e
pub fn atomic_singlethreadfence();
#[cfg(not(stage0))] // SNAP 857ef6e
pub fn atomic_singlethreadfence_acq();
#[cfg(not(stage0))] // SNAP 857ef6e
pub fn atomic_singlethreadfence_rel();
#[cfg(not(stage0))] // SNAP 857ef6e
pub fn atomic_singlethreadfence_acqrel();
/// Aborts the execution of the process.
pub fn abort() -> !;
@ -255,12 +270,17 @@ extern "rust-intrinsic" {
/// Returns `true` if a type is managed (will be allocated on the local heap)
pub fn owns_managed<T>() -> bool;
/// Calculates the offset from a pointer. The offset *must* be in-bounds of
/// the object, or one-byte-past-the-end. An arithmetic overflow is also
/// undefined behaviour.
/// Calculates the offset from a pointer.
///
/// This is implemented as an intrinsic to avoid converting to and from an
/// integer, since the conversion would throw away aliasing information.
///
/// # Safety
///
/// Both the starting and resulting pointer must be either in bounds or one
/// byte past the end of an allocated object. If either pointer is out of
/// bounds or arithmetic overflow occurs then any further use of the
/// returned value will result in undefined behavior.
pub fn offset<T>(dst: *const T, offset: isize) -> *const T;
/// Copies `count * size_of<T>` bytes from `src` to `dst`. The source
@ -303,14 +323,8 @@ extern "rust-intrinsic" {
/// }
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[cfg(not(stage0))]
pub fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: usize);
/// dox
#[stable(feature = "rust1", since = "1.0.0")]
#[cfg(stage0)]
pub fn copy_nonoverlapping<T>(dst: *mut T, src: *const T, count: usize);
/// Copies `count * size_of<T>` bytes from `src` to `dst`. The source
/// and destination may overlap.
///
@ -340,14 +354,8 @@ extern "rust-intrinsic" {
/// ```
///
#[stable(feature = "rust1", since = "1.0.0")]
#[cfg(not(stage0))]
pub fn copy<T>(src: *const T, dst: *mut T, count: usize);
/// dox
#[stable(feature = "rust1", since = "1.0.0")]
#[cfg(stage0)]
pub fn copy<T>(dst: *mut T, src: *const T, count: usize);
/// Invokes memset on the specified pointer, setting `count * size_of::<T>()`
/// bytes of memory starting at `dst` to `c`.
#[stable(feature = "rust1", since = "1.0.0")]
@ -572,7 +580,22 @@ extern "rust-intrinsic" {
/// Returns the value of the discriminant for the variant in 'v',
/// cast to a `u64`; if `T` has no discriminant, returns 0.
// SNAP 5520801
#[cfg(not(stage0))]
pub fn discriminant_value<T>(v: &T) -> u64;
}
#[cfg(not(stage0))]
extern "rust-intrinsic" {
/// Performs an unchecked signed division, which results in undefined behavior,
/// in cases where y == 0, or x == int::MIN and y == -1
pub fn unchecked_sdiv<T>(x: T, y: T) -> T;
/// Performs an unchecked unsigned division, which results in undefined behavior,
/// in cases where y == 0
pub fn unchecked_udiv<T>(x: T, y: T) -> T;
/// Returns the remainder of an unchecked signed division, which results in
/// undefined behavior, in cases where y == 0, or x == int::MIN and y == -1
pub fn unchecked_urem<T>(x: T, y: T) -> T;
/// Returns the remainder of an unchecked signed division, which results in
/// undefined behavior, in cases where y == 0
pub fn unchecked_srem<T>(x: T, y: T) -> T;
}

View File

@ -179,8 +179,8 @@ pub trait Iterator {
/// Creates an iterator that iterates over both this and the specified
/// iterators simultaneously, yielding the two elements as pairs. When
/// either iterator returns `None`, all further invocations of next() will
/// return `None`.
/// either iterator returns `None`, all further invocations of `next()`
/// will return `None`.
///
/// # Examples
///
@ -2407,12 +2407,14 @@ pub trait Step: PartialOrd {
/// `start` should always be less than `end`, so the result should never
/// be negative.
///
/// `by` must be > 0.
///
/// Returns `None` if it is not possible to calculate steps_between
/// without overflow.
fn steps_between(start: &Self, end: &Self, by: &Self) -> Option<usize>;
}
macro_rules! step_impl {
macro_rules! step_impl_unsigned {
($($t:ty)*) => ($(
impl Step for $t {
#[inline]
@ -2423,7 +2425,33 @@ macro_rules! step_impl {
#[allow(trivial_numeric_casts)]
fn steps_between(start: &$t, end: &$t, by: &$t) -> Option<usize> {
if *start <= *end {
Some(((*end - *start) / *by) as usize)
// Note: We assume $t <= usize here
Some((*end - *start) as usize / (*by as usize))
} else {
Some(0)
}
}
}
)*)
}
macro_rules! step_impl_signed {
($($t:ty)*) => ($(
impl Step for $t {
#[inline]
fn step(&self, by: &$t) -> Option<$t> {
(*self).checked_add(*by)
}
#[inline]
#[allow(trivial_numeric_casts)]
fn steps_between(start: &$t, end: &$t, by: &$t) -> Option<usize> {
if *start <= *end {
// Note: We assume $t <= isize here
// Use .wrapping_sub and cast to usize to compute the
// difference that may not fit inside the range of isize.
Some(
((*end as isize).wrapping_sub(*start as isize) as usize
/ (*by as usize))
)
} else {
Some(0)
}
@ -2447,9 +2475,12 @@ macro_rules! step_impl_no_between {
)*)
}
step_impl!(usize u8 u16 u32 isize i8 i16 i32);
step_impl_unsigned!(usize u8 u16 u32);
step_impl_signed!(isize i8 i16 i32);
#[cfg(target_pointer_width = "64")]
step_impl!(u64 i64);
step_impl_unsigned!(u64);
#[cfg(target_pointer_width = "64")]
step_impl_signed!(i64);
#[cfg(target_pointer_width = "32")]
step_impl_no_between!(u64 i64);

View File

@ -65,7 +65,7 @@
#![feature(intrinsics, lang_items)]
#![feature(on_unimplemented)]
#![feature(simd, unsafe_destructor)]
#![feature(simd)]
#![feature(staged_api)]
#![feature(unboxed_closures)]
#![feature(rustc_attrs)]

View File

@ -35,20 +35,10 @@ use hash::Hasher;
#[stable(feature = "rust1", since = "1.0.0")]
#[lang="send"]
#[rustc_on_unimplemented = "`{Self}` cannot be sent between threads safely"]
#[cfg(not(stage0))]
pub unsafe trait Send {
// empty.
}
/// Types able to be transferred across thread boundaries.
#[stable(feature = "rust1", since = "1.0.0")]
#[lang="send"]
#[rustc_on_unimplemented = "`{Self}` cannot be sent between threads safely"]
#[cfg(stage0)]
pub unsafe trait Send : MarkerTrait {
// empty.
}
unsafe impl Send for .. { }
impl<T> !Send for *const T { }
@ -60,21 +50,10 @@ impl !Send for Managed { }
#[lang="sized"]
#[rustc_on_unimplemented = "`{Self}` does not have a constant size known at compile-time"]
#[fundamental] // for Default, for example, which requires that `[T]: !Default` be evaluatable
#[cfg(not(stage0))]
pub trait Sized {
// Empty.
}
/// Types with a constant size known at compile-time.
#[stable(feature = "rust1", since = "1.0.0")]
#[lang="sized"]
#[rustc_on_unimplemented = "`{Self}` does not have a constant size known at compile-time"]
#[fundamental] // for Default, for example, which requires that `[T]: !Default` be evaluatable
#[cfg(stage0)]
pub trait Sized : MarkerTrait {
// Empty.
}
/// Types that can be copied by simply copying bits (i.e. `memcpy`).
///
/// By default, variable bindings have 'move semantics.' In other
@ -222,7 +201,6 @@ pub trait Copy : Clone {
/// wrapper around the value(s) which can be mutated when behind a `&`
/// reference; not doing this is undefined behaviour (for example,
/// `transmute`-ing from `&T` to `&mut T` is illegal).
#[cfg(not(stage0))]
#[stable(feature = "rust1", since = "1.0.0")]
#[lang="sync"]
#[rustc_on_unimplemented = "`{Self}` cannot be shared between threads safely"]
@ -230,15 +208,6 @@ pub unsafe trait Sync {
// Empty
}
/// dox
#[cfg(stage0)]
#[stable(feature = "rust1", since = "1.0.0")]
#[lang="sync"]
#[rustc_on_unimplemented = "`{Self}` cannot be shared between threads safely"]
pub unsafe trait Sync : MarkerTrait {
// Empty
}
unsafe impl Sync for .. { }
impl<T> !Sync for *const T { }
@ -301,20 +270,6 @@ macro_rules! impls{
)
}
/// dox
#[stable(feature = "rust1", since = "1.0.0")]
#[cfg(stage0)]
pub trait MarkerTrait : PhantomFn<Self,Self> { }
#[cfg(stage0)]
impl<T: ?Sized> MarkerTrait for T {}
/// dox
#[lang="phantom_fn"]
#[cfg(stage0)]
pub trait PhantomFn<A:?Sized,R:?Sized=()> {
}
/// `PhantomData<T>` allows you to describe that a type acts as if it stores a value of type `T`,
/// even though it does not. This allows you to inform the compiler about certain safety properties
/// of your code.
@ -461,14 +416,6 @@ mod impls {
#[rustc_reflect_like]
#[unstable(feature = "core", reason = "requires RFC and more experience")]
#[allow(deprecated)]
#[cfg(not(stage0))]
pub trait Reflect {}
/// dox
#[rustc_reflect_like]
#[unstable(feature = "core", reason = "requires RFC and more experience")]
#[cfg(stage0)]
pub trait Reflect: MarkerTrait {}
impl Reflect for .. { }

View File

@ -12,16 +12,10 @@
use marker::Sized;
use ops::Deref;
#[cfg(stage0)] use marker::MarkerTrait;
/// Unsafe trait to indicate what types are usable with the NonZero struct
#[cfg(not(stage0))]
pub unsafe trait Zeroable {}
/// Unsafe trait to indicate what types are usable with the NonZero struct
#[cfg(stage0)]
pub unsafe trait Zeroable: MarkerTrait {}
unsafe impl<T:?Sized> Zeroable for *const T {}
unsafe impl<T:?Sized> Zeroable for *mut T {}
unsafe impl Zeroable for isize {}

View File

@ -745,7 +745,20 @@ macro_rules! uint_impl {
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn trailing_zeros(self) -> u32 {
unsafe { $cttz(self as $ActualT) as u32 }
// As of LLVM 3.6 the codegen for the zero-safe cttz8 intrinsic
// emits two conditional moves on x86_64. By promoting the value to
// u16 and setting bit 8, we get better code without any conditional
// operations.
// FIXME: There's a LLVM patch (http://reviews.llvm.org/D9284)
// pending, remove this workaround once LLVM generates better code
// for cttz8.
unsafe {
if $BITS == 8 {
intrinsics::cttz16(self as u16 | 0x100) as u32
} else {
$cttz(self as $ActualT) as u32
}
}
}
/// Shifts the bits to the left by a specified amount, `n`,

View File

@ -508,8 +508,6 @@ macro_rules! neg_impl_numeric {
macro_rules! neg_impl_unsigned {
($($t:ty)*) => {
neg_impl_core!{ x => {
#[cfg(stage0)]
use ::num::wrapping::WrappingOps;
!x.wrapping_add(1)
}, $($t)*} }
}
@ -1162,7 +1160,6 @@ pub trait FnOnce<Args> {
extern "rust-call" fn call_once(self, args: Args) -> Self::Output;
}
#[cfg(not(stage0))]
mod impls {
use marker::Sized;
use super::{Fn, FnMut, FnOnce};

View File

@ -106,28 +106,11 @@ use cmp::Ordering::{self, Less, Equal, Greater};
// FIXME #19649: intrinsic docs don't render, so these have no docs :(
#[stable(feature = "rust1", since = "1.0.0")]
#[cfg(not(stage0))]
pub use intrinsics::copy_nonoverlapping;
/// dox
#[cfg(stage0)]
#[stable(feature = "rust1", since = "1.0.0")]
pub unsafe fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: usize) {
intrinsics::copy_nonoverlapping(dst, src, count)
}
#[stable(feature = "rust1", since = "1.0.0")]
#[cfg(not(stage0))]
pub use intrinsics::copy;
/// dox
#[cfg(stage0)]
#[stable(feature = "rust1", since = "1.0.0")]
pub unsafe fn copy<T>(src: *const T, dst: *mut T, count: usize) {
intrinsics::copy(dst, src, count)
}
#[stable(feature = "rust1", since = "1.0.0")]
pub use intrinsics::write_bytes;
@ -301,9 +284,10 @@ impl<T: ?Sized> *const T {
///
/// # Safety
///
/// The offset must be in-bounds of the object, or one-byte-past-the-end.
/// Otherwise `offset` invokes Undefined Behaviour, regardless of whether
/// the pointer is used.
/// Both the starting and resulting pointer must be either in bounds or one
/// byte past the end of an allocated object. If either pointer is out of
/// bounds or arithmetic overflow occurs then
/// any further use of the returned value will result in undefined behavior.
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub unsafe fn offset(self, count: isize) -> *const T where T: Sized {

View File

@ -625,6 +625,36 @@ impl<'a, T> IntoIterator for &'a mut [T] {
}
}
#[inline(always)]
fn size_from_ptr<T>(_: *const T) -> usize {
mem::size_of::<T>()
}
// Use macro to be generic over const/mut
macro_rules! slice_offset {
($ptr:expr, $by:expr) => {{
let ptr = $ptr;
if size_from_ptr(ptr) == 0 {
transmute(ptr as usize + $by)
} else {
ptr.offset($by)
}
}};
}
macro_rules! slice_ref {
($ptr:expr) => {{
let ptr = $ptr;
if size_from_ptr(ptr) == 0 {
// Use a non-null pointer value
&mut *(1 as *mut _)
} else {
transmute(ptr)
}
}};
}
// The shared definition of the `Iter` and `IterMut` iterators
macro_rules! iterator {
(struct $name:ident -> $ptr:ty, $elem:ty) => {
@ -641,20 +671,9 @@ macro_rules! iterator {
if self.ptr == self.end {
None
} else {
if mem::size_of::<T>() == 0 {
// purposefully don't use 'ptr.offset' because for
// vectors with 0-size elements this would return the
// same pointer.
self.ptr = transmute(self.ptr as usize + 1);
// Use a non-null pointer value
Some(&mut *(1 as *mut _))
} else {
let old = self.ptr;
self.ptr = self.ptr.offset(1);
Some(transmute(old))
}
let old = self.ptr;
self.ptr = slice_offset!(self.ptr, 1);
Some(slice_ref!(old))
}
}
}
@ -666,6 +685,22 @@ macro_rules! iterator {
let exact = diff / (if size == 0 {1} else {size});
(exact, Some(exact))
}
#[inline]
fn count(self) -> usize {
self.size_hint().0
}
#[inline]
fn nth(&mut self, n: usize) -> Option<$elem> {
// Call helper method. Can't put the definition here because mut versus const.
self.iter_nth(n)
}
#[inline]
fn last(mut self) -> Option<$elem> {
self.next_back()
}
}
#[stable(feature = "rust1", since = "1.0.0")]
@ -679,17 +714,8 @@ macro_rules! iterator {
if self.end == self.ptr {
None
} else {
if mem::size_of::<T>() == 0 {
// See above for why 'ptr.offset' isn't used
self.end = transmute(self.end as usize - 1);
// Use a non-null pointer value
Some(&mut *(1 as *mut _))
} else {
self.end = self.end.offset(-1);
Some(transmute(self.end))
}
self.end = slice_offset!(self.end, -1);
Some(slice_ref!(self.end))
}
}
}
@ -785,6 +811,20 @@ impl<'a, T> Iter<'a, T> {
pub fn as_slice(&self) -> &'a [T] {
make_slice!(T => &'a [T]: self.ptr, self.end)
}
// Helper function for Iter::nth
fn iter_nth(&mut self, n: usize) -> Option<&'a T> {
match self.as_slice().get(n) {
Some(elem_ref) => unsafe {
self.ptr = slice_offset!(elem_ref as *const _, 1);
Some(slice_ref!(elem_ref))
},
None => {
self.ptr = self.end;
None
}
}
}
}
iterator!{struct Iter -> *const T, &'a T}
@ -914,6 +954,20 @@ impl<'a, T> IterMut<'a, T> {
pub fn into_slice(self) -> &'a mut [T] {
make_mut_slice!(T => &'a mut [T]: self.ptr, self.end)
}
// Helper function for IterMut::nth
fn iter_nth(&mut self, n: usize) -> Option<&'a mut T> {
match make_mut_slice!(T => &'a mut [T]: self.ptr, self.end).get_mut(n) {
Some(elem_ref) => unsafe {
self.ptr = slice_offset!(elem_ref as *mut _, 1);
Some(slice_ref!(elem_ref))
},
None => {
self.ptr = self.end;
None
}
}
}
}
iterator!{struct IterMut -> *mut T, &'a mut T}

View File

@ -11,6 +11,7 @@
use core::iter::*;
use core::iter::order::*;
use core::iter::MinMaxResult::*;
use core::isize;
use core::usize;
use core::cmp;
@ -758,6 +759,11 @@ fn test_range() {
assert_eq!((usize::MAX - 1..usize::MAX).size_hint(), (1, Some(1)));
assert_eq!((-10..-1).size_hint(), (9, Some(9)));
assert_eq!((-1..-10).size_hint(), (0, Some(0)));
assert_eq!((-70..58i8).size_hint(), (128, Some(128)));
assert_eq!((-128..127i8).size_hint(), (255, Some(255)));
assert_eq!((-2..isize::MAX).size_hint(),
(isize::MAX as usize + 2, Some(isize::MAX as usize + 2)));
}
#[test]

View File

@ -13,7 +13,6 @@
#![feature(box_syntax)]
#![feature(unboxed_closures)]
#![feature(unsafe_destructor)]
#![feature(core)]
#![feature(test)]
#![feature(rand)]

View File

@ -45,7 +45,7 @@ pub fn test_num<T>(ten: T, two: T) where
}
#[cfg(test)]
mod test {
mod tests {
use core::option::Option;
use core::option::Option::{Some, None};
use core::num::Float;

View File

@ -44,8 +44,7 @@ fn test_get_resource() {
i: Rc<RefCell<isize>>,
}
#[unsafe_destructor]
impl Drop for R {
impl Drop for R {
fn drop(&mut self) {
let ii = &*self.i;
let i = *ii.borrow();
@ -220,7 +219,6 @@ fn test_ord() {
assert!(big > None);
}
/* FIXME(#20575)
#[test]
fn test_collect() {
let v: Option<Vec<isize>> = (0..0).map(|_| Some(0)).collect();
@ -242,28 +240,26 @@ fn test_collect() {
assert!(v == None);
}
*/
#[test]
fn test_cloned() {
let val1 = 1u32;
let mut val2 = 2u32;
let val1_ref = &val1;
let val = 1u32;
let val_ref = &val;
let opt_none: Option<&'static u32> = None;
let opt_ref = Some(&val1);
let opt_ref_ref = Some(&val1_ref);
let opt_mut_ref = Some(&mut val2);
let opt_ref = Some(&val);
let opt_ref_ref = Some(&val_ref);
// None works
assert_eq!(opt_none.clone(), None);
assert_eq!(opt_none.cloned(), None);
// Immutable ref works
assert_eq!(opt_ref.clone(), Some(&val1));
assert_eq!(opt_ref.clone(), Some(&val));
assert_eq!(opt_ref.cloned(), Some(1u32));
// Double Immutable ref works
assert_eq!(opt_ref_ref.clone(), Some(&val1_ref));
assert_eq!(opt_ref_ref.clone().cloned(), Some(&val1));
assert_eq!(opt_ref_ref.clone(), Some(&val_ref));
assert_eq!(opt_ref_ref.clone().cloned(), Some(&val));
assert_eq!(opt_ref_ref.cloned().cloned(), Some(1u32));
}

View File

@ -8,11 +8,11 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
pub fn op1() -> Result<isize, &'static str> { Ok(666) }
pub fn op2() -> Result<isize, &'static str> { Err("sadface") }
fn op1() -> Result<isize, &'static str> { Ok(666) }
fn op2() -> Result<isize, &'static str> { Err("sadface") }
#[test]
pub fn test_and() {
fn test_and() {
assert_eq!(op1().and(Ok(667)).unwrap(), 667);
assert_eq!(op1().and(Err::<i32, &'static str>("bad")).unwrap_err(),
"bad");
@ -23,7 +23,7 @@ pub fn test_and() {
}
#[test]
pub fn test_and_then() {
fn test_and_then() {
assert_eq!(op1().and_then(|i| Ok::<isize, &'static str>(i + 1)).unwrap(), 667);
assert_eq!(op1().and_then(|_| Err::<isize, &'static str>("bad")).unwrap_err(),
"bad");
@ -35,7 +35,7 @@ pub fn test_and_then() {
}
#[test]
pub fn test_or() {
fn test_or() {
assert_eq!(op1().or(Ok::<_, &'static str>(667)).unwrap(), 666);
assert_eq!(op1().or(Err("bad")).unwrap(), 666);
@ -44,7 +44,7 @@ pub fn test_or() {
}
#[test]
pub fn test_or_else() {
fn test_or_else() {
assert_eq!(op1().or_else(|_| Ok::<isize, &'static str>(667)).unwrap(), 666);
assert_eq!(op1().or_else(|e| Err::<isize, &'static str>(e)).unwrap(), 666);
@ -54,18 +54,17 @@ pub fn test_or_else() {
}
#[test]
pub fn test_impl_map() {
fn test_impl_map() {
assert!(Ok::<isize, isize>(1).map(|x| x + 1) == Ok(2));
assert!(Err::<isize, isize>(1).map(|x| x + 1) == Err(1));
}
#[test]
pub fn test_impl_map_err() {
fn test_impl_map_err() {
assert!(Ok::<isize, isize>(1).map_err(|x| x + 1) == Ok(1));
assert!(Err::<isize, isize>(1).map_err(|x| x + 1) == Err(2));
}
/* FIXME(#20575)
#[test]
fn test_collect() {
let v: Result<Vec<isize>, ()> = (0..0).map(|_| Ok::<isize, ()>(0)).collect();
@ -86,10 +85,9 @@ fn test_collect() {
let v: Result<Vec<()>, isize> = functions.iter_mut().map(|f| (*f)()).collect();
assert!(v == Err(1));
}
*/
#[test]
pub fn test_fmt_default() {
fn test_fmt_default() {
let ok: Result<isize, &'static str> = Ok(100);
let err: Result<isize, &'static str> = Err("Err");
@ -100,7 +98,7 @@ pub fn test_fmt_default() {
}
#[test]
pub fn test_unwrap_or() {
fn test_unwrap_or() {
let ok: Result<isize, &'static str> = Ok(100);
let ok_err: Result<isize, &'static str> = Err("Err");
@ -109,7 +107,7 @@ pub fn test_unwrap_or() {
}
#[test]
pub fn test_unwrap_or_else() {
fn test_unwrap_or_else() {
fn handler(msg: &'static str) -> isize {
if msg == "I got this." {
50

View File

@ -82,3 +82,34 @@ fn iterator_to_slice() {
test!([1u8,2,3]);
test!([(),(),()]);
}
#[test]
fn test_iterator_nth() {
let v: &[_] = &[0, 1, 2, 3, 4];
for i in 0..v.len() {
assert_eq!(v.iter().nth(i).unwrap(), &v[i]);
}
assert_eq!(v.iter().nth(v.len()), None);
let mut iter = v.iter();
assert_eq!(iter.nth(2).unwrap(), &v[2]);
assert_eq!(iter.nth(1).unwrap(), &v[4]);
}
#[test]
fn test_iterator_last() {
let v: &[_] = &[0, 1, 2, 3, 4];
assert_eq!(v.iter().last().unwrap(), &4);
assert_eq!(v[..1].iter().last().unwrap(), &0);
}
#[test]
fn test_iterator_count() {
let v: &[_] = &[0, 1, 2, 3, 4];
assert_eq!(v.iter().count(), 5);
let mut iter2 = v.iter();
iter2.next();
iter2.next();
assert_eq!(iter2.count(), 3);
}

View File

@ -140,11 +140,15 @@ pub use funcs::bsd43::*;
// On NaCl, these libraries are static. Thus it would be a Bad Idea to link them
// in when creating a test crate.
#[cfg(not(any(windows, all(target_os = "nacl", test))))]
#[cfg(not(any(windows, target_env = "musl", all(target_os = "nacl", test))))]
#[link(name = "c")]
#[link(name = "m")]
extern {}
#[cfg(all(target_env = "musl", not(test)))]
#[link(name = "c", kind = "static")]
extern {}
// libnacl provides functions that require a trip through the IRT to work.
// ie: _exit, mmap, nanosleep, etc. Anything that would otherwise require a trip
// to the kernel.

View File

@ -202,7 +202,7 @@ impl Rand for ChaChaRng {
#[cfg(test)]
mod test {
mod tests {
use std::prelude::v1::*;
use core::iter::order;

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