auto merge of #19049 : jakub-/rust/roll-up, r=alexcrichton

r? @alexcrichton
This commit is contained in:
bors 2014-11-18 01:02:19 +00:00
commit 9c96a79a74
84 changed files with 744 additions and 367 deletions

View File

@ -13,7 +13,7 @@ CFG_LIB_NAME_arm-apple-ios = lib$(1).a
CFG_LIB_GLOB_arm-apple-ios = lib$(1)-*.a CFG_LIB_GLOB_arm-apple-ios = lib$(1)-*.a
CFG_STATIC_LIB_NAME_arm-apple-ios=lib$(1).a CFG_STATIC_LIB_NAME_arm-apple-ios=lib$(1).a
CFG_LIB_DSYM_GLOB_arm-apple-ios = lib$(1)-*.a.dSYM CFG_LIB_DSYM_GLOB_arm-apple-ios = lib$(1)-*.a.dSYM
CFG_CFLAGS_arm-apple-ios := -arch armv7 -mfpu=vfp3 $(CFG_IOS_FLAGS) CFG_JEMALLOC_CFLAGS_arm-apple-ios := -arch armv7 -mfpu=vfp3 $(CFG_IOS_FLAGS)
CFG_GCCISH_CFLAGS_arm-apple-ios := -Wall -Werror -g -fPIC $(CFG_IOS_FLAGS) -mfpu=vfp3 -arch armv7 CFG_GCCISH_CFLAGS_arm-apple-ios := -Wall -Werror -g -fPIC $(CFG_IOS_FLAGS) -mfpu=vfp3 -arch armv7
CFG_GCCISH_CXXFLAGS_arm-apple-ios := -fno-rtti $(CFG_IOS_FLAGS) -I$(CFG_IOS_SDK)/usr/include/c++/4.2.1 CFG_GCCISH_CXXFLAGS_arm-apple-ios := -fno-rtti $(CFG_IOS_FLAGS) -I$(CFG_IOS_SDK)/usr/include/c++/4.2.1
CFG_GCCISH_LINK_FLAGS_arm-apple-ios := -lpthread -syslibroot $(CFG_IOS_SDK) -Wl,-no_compact_unwind CFG_GCCISH_LINK_FLAGS_arm-apple-ios := -lpthread -syslibroot $(CFG_IOS_SDK) -Wl,-no_compact_unwind

View File

@ -7,7 +7,7 @@ CFG_LIB_NAME_arm-linux-androideabi=lib$(1).so
CFG_STATIC_LIB_NAME_arm-linux-androideabi=lib$(1).a CFG_STATIC_LIB_NAME_arm-linux-androideabi=lib$(1).a
CFG_LIB_GLOB_arm-linux-androideabi=lib$(1)-*.so CFG_LIB_GLOB_arm-linux-androideabi=lib$(1)-*.so
CFG_LIB_DSYM_GLOB_arm-linux-androideabi=lib$(1)-*.dylib.dSYM CFG_LIB_DSYM_GLOB_arm-linux-androideabi=lib$(1)-*.dylib.dSYM
CFG_CFLAGS_arm-linux-androideabi := -D__arm__ -DANDROID -D__ANDROID__ $(CFLAGS) CFG_JEMALLOC_CFLAGS_arm-linux-androideabi := -D__arm__ -DANDROID -D__ANDROID__ $(CFLAGS)
CFG_GCCISH_CFLAGS_arm-linux-androideabi := -Wall -g -fPIC -D__arm__ -DANDROID -D__ANDROID__ $(CFLAGS) CFG_GCCISH_CFLAGS_arm-linux-androideabi := -Wall -g -fPIC -D__arm__ -DANDROID -D__ANDROID__ $(CFLAGS)
CFG_GCCISH_CXXFLAGS_arm-linux-androideabi := -fno-rtti $(CXXFLAGS) CFG_GCCISH_CXXFLAGS_arm-linux-androideabi := -fno-rtti $(CXXFLAGS)
CFG_GCCISH_LINK_FLAGS_arm-linux-androideabi := -shared -fPIC -ldl -g -lm -lsupc++ CFG_GCCISH_LINK_FLAGS_arm-linux-androideabi := -shared -fPIC -ldl -g -lm -lsupc++

View File

@ -8,7 +8,7 @@ CFG_LIB_NAME_arm-unknown-linux-gnueabi=lib$(1).so
CFG_STATIC_LIB_NAME_arm-unknown-linux-gnueabi=lib$(1).a CFG_STATIC_LIB_NAME_arm-unknown-linux-gnueabi=lib$(1).a
CFG_LIB_GLOB_arm-unknown-linux-gnueabi=lib$(1)-*.so CFG_LIB_GLOB_arm-unknown-linux-gnueabi=lib$(1)-*.so
CFG_LIB_DSYM_GLOB_arm-unknown-linux-gnueabi=lib$(1)-*.dylib.dSYM CFG_LIB_DSYM_GLOB_arm-unknown-linux-gnueabi=lib$(1)-*.dylib.dSYM
CFG_CFLAGS_arm-unknown-linux-gnueabi := -D__arm__ -mfpu=vfp $(CFLAGS) CFG_JEMALLOC_CFLAGS_arm-unknown-linux-gnueabi := -D__arm__ -mfpu=vfp $(CFLAGS)
CFG_GCCISH_CFLAGS_arm-unknown-linux-gnueabi := -Wall -g -fPIC -D__arm__ -mfpu=vfp $(CFLAGS) CFG_GCCISH_CFLAGS_arm-unknown-linux-gnueabi := -Wall -g -fPIC -D__arm__ -mfpu=vfp $(CFLAGS)
CFG_GCCISH_CXXFLAGS_arm-unknown-linux-gnueabi := -fno-rtti $(CXXFLAGS) CFG_GCCISH_CXXFLAGS_arm-unknown-linux-gnueabi := -fno-rtti $(CXXFLAGS)
CFG_GCCISH_LINK_FLAGS_arm-unknown-linux-gnueabi := -shared -fPIC -g CFG_GCCISH_LINK_FLAGS_arm-unknown-linux-gnueabi := -shared -fPIC -g

View File

@ -8,7 +8,7 @@ CFG_LIB_NAME_arm-unknown-linux-gnueabihf=lib$(1).so
CFG_STATIC_LIB_NAME_arm-unknown-linux-gnueabihf=lib$(1).a CFG_STATIC_LIB_NAME_arm-unknown-linux-gnueabihf=lib$(1).a
CFG_LIB_GLOB_arm-unknown-linux-gnueabihf=lib$(1)-*.so CFG_LIB_GLOB_arm-unknown-linux-gnueabihf=lib$(1)-*.so
CFG_LIB_DSYM_GLOB_arm-unknown-linux-gnueabihf=lib$(1)-*.dylib.dSYM CFG_LIB_DSYM_GLOB_arm-unknown-linux-gnueabihf=lib$(1)-*.dylib.dSYM
CFG_CFLAGS_arm-unknown-linux-gnueabihf := -D__arm__ $(CFLAGS) CFG_JEMALLOC_CFLAGS_arm-unknown-linux-gnueabihf := -D__arm__ $(CFLAGS)
CFG_GCCISH_CFLAGS_arm-unknown-linux-gnueabihf := -Wall -g -fPIC -D__arm__ $(CFLAGS) CFG_GCCISH_CFLAGS_arm-unknown-linux-gnueabihf := -Wall -g -fPIC -D__arm__ $(CFLAGS)
CFG_GCCISH_CXXFLAGS_arm-unknown-linux-gnueabihf := -fno-rtti $(CXXFLAGS) CFG_GCCISH_CXXFLAGS_arm-unknown-linux-gnueabihf := -fno-rtti $(CXXFLAGS)
CFG_GCCISH_LINK_FLAGS_arm-unknown-linux-gnueabihf := -shared -fPIC -g CFG_GCCISH_LINK_FLAGS_arm-unknown-linux-gnueabihf := -shared -fPIC -g

View File

@ -13,7 +13,6 @@ CFG_LIB_NAME_i386-apple-ios = lib$(1).a
CFG_LIB_GLOB_i386-apple-ios = lib$(1)-*.dylib CFG_LIB_GLOB_i386-apple-ios = lib$(1)-*.dylib
CFG_STATIC_LIB_NAME_i386-apple-ios=lib$(1).a CFG_STATIC_LIB_NAME_i386-apple-ios=lib$(1).a
CFG_LIB_DSYM_GLOB_i386-apple-ios = lib$(1)-*.dylib.dSYM CFG_LIB_DSYM_GLOB_i386-apple-ios = lib$(1)-*.dylib.dSYM
CFG_CFLAGS_i386-apple-ios = $(CFG_IOSSIM_FLAGS)
CFG_GCCISH_CFLAGS_i386-apple-ios = -Wall -Werror -g -fPIC -m32 $(CFG_IOSSIM_FLAGS) CFG_GCCISH_CFLAGS_i386-apple-ios = -Wall -Werror -g -fPIC -m32 $(CFG_IOSSIM_FLAGS)
CFG_GCCISH_CXXFLAGS_i386-apple-ios = -fno-rtti $(CFG_IOSSIM_FLAGS) -I$(CFG_IOSSIM_SDK)/usr/include/c++/4.2.1 CFG_GCCISH_CXXFLAGS_i386-apple-ios = -fno-rtti $(CFG_IOSSIM_FLAGS) -I$(CFG_IOSSIM_SDK)/usr/include/c++/4.2.1
CFG_GCCISH_LINK_FLAGS_i386-apple-ios = -lpthread -Wl,-no_compact_unwind -m32 -Wl,-syslibroot $(CFG_IOSSIM_SDK) CFG_GCCISH_LINK_FLAGS_i386-apple-ios = -lpthread -Wl,-no_compact_unwind -m32 -Wl,-syslibroot $(CFG_IOSSIM_SDK)
@ -30,5 +29,5 @@ CFG_PATH_MUNGE_i386-apple-ios = true
CFG_LDPATH_i386-apple-ios = CFG_LDPATH_i386-apple-ios =
CFG_RUN_i386-apple-ios = $(2) CFG_RUN_i386-apple-ios = $(2)
CFG_RUN_TARG_i386-apple-ios = $(call CFG_RUN_i386-apple-ios,,$(2)) CFG_RUN_TARG_i386-apple-ios = $(call CFG_RUN_i386-apple-ios,,$(2))
CFG_JEMALLOC_CFLAGS_i386-apple-ios = -target i386-apple-ios -Wl,-syslibroot $(CFG_IOSSIM_SDK) -Wl,-no_compact_unwind CFG_JEMALLOC_CFLAGS_i386-apple-ios = $(CFG_IOSSIM_FLAGS) -target i386-apple-ios -Wl,-syslibroot $(CFG_IOSSIM_SDK) -Wl,-no_compact_unwind
CFG_GNU_TRIPLE_i386-apple-ios := i386-apple-ios CFG_GNU_TRIPLE_i386-apple-ios := i386-apple-ios

View File

@ -7,7 +7,7 @@ CFG_LIB_NAME_i686-apple-darwin=lib$(1).dylib
CFG_STATIC_LIB_NAME_i686-apple-darwin=lib$(1).a CFG_STATIC_LIB_NAME_i686-apple-darwin=lib$(1).a
CFG_LIB_GLOB_i686-apple-darwin=lib$(1)-*.dylib CFG_LIB_GLOB_i686-apple-darwin=lib$(1)-*.dylib
CFG_LIB_DSYM_GLOB_i686-apple-darwin=lib$(1)-*.dylib.dSYM CFG_LIB_DSYM_GLOB_i686-apple-darwin=lib$(1)-*.dylib.dSYM
CFG_CFLAGS_i686-apple-darwin := -m32 -arch i386 $(CFLAGS) CFG_JEMALLOC_CFLAGS_i686-apple-darwin := -m32 -arch i386 $(CFLAGS)
CFG_GCCISH_CFLAGS_i686-apple-darwin := -Wall -Werror -g -fPIC -m32 -arch i386 $(CFLAGS) CFG_GCCISH_CFLAGS_i686-apple-darwin := -Wall -Werror -g -fPIC -m32 -arch i386 $(CFLAGS)
CFG_GCCISH_CXXFLAGS_i686-apple-darwin := -fno-rtti $(CXXFLAGS) CFG_GCCISH_CXXFLAGS_i686-apple-darwin := -fno-rtti $(CXXFLAGS)
CFG_GCCISH_LINK_FLAGS_i686-apple-darwin := -dynamiclib -pthread -framework CoreServices -m32 CFG_GCCISH_LINK_FLAGS_i686-apple-darwin := -dynamiclib -pthread -framework CoreServices -m32

View File

@ -8,7 +8,7 @@ CFG_LIB_NAME_i686-pc-windows-gnu=$(1).dll
CFG_STATIC_LIB_NAME_i686-pc-windows-gnu=$(1).lib CFG_STATIC_LIB_NAME_i686-pc-windows-gnu=$(1).lib
CFG_LIB_GLOB_i686-pc-windows-gnu=$(1)-*.dll CFG_LIB_GLOB_i686-pc-windows-gnu=$(1)-*.dll
CFG_LIB_DSYM_GLOB_i686-pc-windows-gnu=$(1)-*.dylib.dSYM CFG_LIB_DSYM_GLOB_i686-pc-windows-gnu=$(1)-*.dylib.dSYM
CFG_CFLAGS_i686-pc-windows-gnu := -march=i686 -m32 -D_WIN32_WINNT=0x0600 $(CFLAGS) CFG_JEMALLOC_CFLAGS_i686-pc-windows-gnu := -march=i686 -m32 -D_WIN32_WINNT=0x0600 $(CFLAGS)
CFG_GCCISH_CFLAGS_i686-pc-windows-gnu := -Wall -Werror -g -m32 -D_WIN32_WINNT=0x0600 $(CFLAGS) CFG_GCCISH_CFLAGS_i686-pc-windows-gnu := -Wall -Werror -g -m32 -D_WIN32_WINNT=0x0600 $(CFLAGS)
CFG_GCCISH_CXXFLAGS_i686-pc-windows-gnu := -fno-rtti $(CXXFLAGS) CFG_GCCISH_CXXFLAGS_i686-pc-windows-gnu := -fno-rtti $(CXXFLAGS)
CFG_GCCISH_LINK_FLAGS_i686-pc-windows-gnu := -shared -g -m32 CFG_GCCISH_LINK_FLAGS_i686-pc-windows-gnu := -shared -g -m32

View File

@ -7,7 +7,7 @@ CFG_LIB_NAME_i686-unknown-linux-gnu=lib$(1).so
CFG_STATIC_LIB_NAME_i686-unknown-linux-gnu=lib$(1).a CFG_STATIC_LIB_NAME_i686-unknown-linux-gnu=lib$(1).a
CFG_LIB_GLOB_i686-unknown-linux-gnu=lib$(1)-*.so CFG_LIB_GLOB_i686-unknown-linux-gnu=lib$(1)-*.so
CFG_LIB_DSYM_GLOB_i686-unknown-linux-gnu=lib$(1)-*.dylib.dSYM CFG_LIB_DSYM_GLOB_i686-unknown-linux-gnu=lib$(1)-*.dylib.dSYM
CFG_CFLAGS_i686-unknown-linux-gnu := -m32 $(CFLAGS) CFG_JEMALLOC_CFLAGS_i686-unknown-linux-gnu := -m32 $(CFLAGS)
CFG_GCCISH_CFLAGS_i686-unknown-linux-gnu := -Wall -Werror -g -fPIC -m32 $(CFLAGS) CFG_GCCISH_CFLAGS_i686-unknown-linux-gnu := -Wall -Werror -g -fPIC -m32 $(CFLAGS)
CFG_GCCISH_CXXFLAGS_i686-unknown-linux-gnu := -fno-rtti $(CXXFLAGS) CFG_GCCISH_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_LINK_FLAGS_i686-unknown-linux-gnu := -shared -fPIC -ldl -pthread -lrt -g -m32

View File

@ -7,7 +7,7 @@ CFG_LIB_NAME_mips-unknown-linux-gnu=lib$(1).so
CFG_STATIC_LIB_NAME_mips-unknown-linux-gnu=lib$(1).a CFG_STATIC_LIB_NAME_mips-unknown-linux-gnu=lib$(1).a
CFG_LIB_GLOB_mips-unknown-linux-gnu=lib$(1)-*.so CFG_LIB_GLOB_mips-unknown-linux-gnu=lib$(1)-*.so
CFG_LIB_DSYM_GLOB_mips-unknown-linux-gnu=lib$(1)-*.dylib.dSYM CFG_LIB_DSYM_GLOB_mips-unknown-linux-gnu=lib$(1)-*.dylib.dSYM
CFG_CFLAGS_mips-unknown-linux-gnu := -mips32r2 -msoft-float -mabi=32 -mno-compact-eh $(CFLAGS) CFG_JEMALLOC_CFLAGS_mips-unknown-linux-gnu := -mips32r2 -msoft-float -mabi=32 -mno-compact-eh $(CFLAGS)
CFG_GCCISH_CFLAGS_mips-unknown-linux-gnu := -Wall -g -fPIC -mips32r2 -msoft-float -mabi=32 -mno-compact-eh $(CFLAGS) CFG_GCCISH_CFLAGS_mips-unknown-linux-gnu := -Wall -g -fPIC -mips32r2 -msoft-float -mabi=32 -mno-compact-eh $(CFLAGS)
CFG_GCCISH_CXXFLAGS_mips-unknown-linux-gnu := -fno-rtti $(CXXFLAGS) CFG_GCCISH_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_LINK_FLAGS_mips-unknown-linux-gnu := -shared -fPIC -g -mips32r2 -msoft-float -mabi=32

View File

@ -7,7 +7,7 @@ CFG_LIB_NAME_mipsel-unknown-linux-gnu=lib$(1).so
CFG_STATIC_LIB_NAME_mipsel-unknown-linux-gnu=lib$(1).a CFG_STATIC_LIB_NAME_mipsel-unknown-linux-gnu=lib$(1).a
CFG_LIB_GLOB_mipsel-unknown-linux-gnu=lib$(1)-*.so CFG_LIB_GLOB_mipsel-unknown-linux-gnu=lib$(1)-*.so
CFG_LIB_DSYM_GLOB_mipsel-unknown-linux-gnu=lib$(1)-*.dylib.dSYM CFG_LIB_DSYM_GLOB_mipsel-unknown-linux-gnu=lib$(1)-*.dylib.dSYM
CFG_CFLAGS_mipsel-unknown-linux-gnu := -mips32 -mabi=32 $(CFLAGS) CFG_JEMALLOC_CFLAGS_mipsel-unknown-linux-gnu := -mips32 -mabi=32 $(CFLAGS)
CFG_GCCISH_CFLAGS_mipsel-unknown-linux-gnu := -Wall -g -fPIC -mips32 -mabi=32 $(CFLAGS) CFG_GCCISH_CFLAGS_mipsel-unknown-linux-gnu := -Wall -g -fPIC -mips32 -mabi=32 $(CFLAGS)
CFG_GCCISH_CXXFLAGS_mipsel-unknown-linux-gnu := -fno-rtti $(CXXFLAGS) CFG_GCCISH_CXXFLAGS_mipsel-unknown-linux-gnu := -fno-rtti $(CXXFLAGS)
CFG_GCCISH_LINK_FLAGS_mipsel-unknown-linux-gnu := -shared -fPIC -g -mips32 CFG_GCCISH_LINK_FLAGS_mipsel-unknown-linux-gnu := -shared -fPIC -g -mips32

View File

@ -7,7 +7,7 @@ CFG_LIB_NAME_x86_64-apple-darwin=lib$(1).dylib
CFG_STATIC_LIB_NAME_x86_64-apple-darwin=lib$(1).a CFG_STATIC_LIB_NAME_x86_64-apple-darwin=lib$(1).a
CFG_LIB_GLOB_x86_64-apple-darwin=lib$(1)-*.dylib CFG_LIB_GLOB_x86_64-apple-darwin=lib$(1)-*.dylib
CFG_LIB_DSYM_GLOB_x86_64-apple-darwin=lib$(1)-*.dylib.dSYM CFG_LIB_DSYM_GLOB_x86_64-apple-darwin=lib$(1)-*.dylib.dSYM
CFG_CFLAGS_x86_64-apple-darwin := -m64 -arch x86_64 $(CFLAGS) CFG_JEMALLOC_CFLAGS_x86_64-apple-darwin := -m64 -arch x86_64 $(CFLAGS)
CFG_GCCISH_CFLAGS_x86_64-apple-darwin := -Wall -Werror -g -fPIC -m64 -arch x86_64 $(CFLAGS) CFG_GCCISH_CFLAGS_x86_64-apple-darwin := -Wall -Werror -g -fPIC -m64 -arch x86_64 $(CFLAGS)
CFG_GCCISH_CXXFLAGS_x86_64-apple-darwin := -fno-rtti $(CXXFLAGS) CFG_GCCISH_CXXFLAGS_x86_64-apple-darwin := -fno-rtti $(CXXFLAGS)
CFG_GCCISH_LINK_FLAGS_x86_64-apple-darwin := -dynamiclib -pthread -framework CoreServices -m64 CFG_GCCISH_LINK_FLAGS_x86_64-apple-darwin := -dynamiclib -pthread -framework CoreServices -m64

View File

@ -8,7 +8,7 @@ CFG_LIB_NAME_x86_64-pc-windows-gnu=$(1).dll
CFG_STATIC_LIB_NAME_x86_64-pc-windows-gnu=$(1).lib CFG_STATIC_LIB_NAME_x86_64-pc-windows-gnu=$(1).lib
CFG_LIB_GLOB_x86_64-pc-windows-gnu=$(1)-*.dll CFG_LIB_GLOB_x86_64-pc-windows-gnu=$(1)-*.dll
CFG_LIB_DSYM_GLOB_x86_64-pc-windows-gnu=$(1)-*.dylib.dSYM CFG_LIB_DSYM_GLOB_x86_64-pc-windows-gnu=$(1)-*.dylib.dSYM
CFG_CFLAGS_x86_64-pc-windows-gnu := -m64 -D_WIN32_WINNT=0x0600 $(CFLAGS) CFG_JEMALLOC_CFLAGS_x86_64-pc-windows-gnu := -m64 -D_WIN32_WINNT=0x0600 $(CFLAGS)
CFG_GCCISH_CFLAGS_x86_64-pc-windows-gnu := -Wall -Werror -g -m64 -D_WIN32_WINNT=0x0600 $(CFLAGS) CFG_GCCISH_CFLAGS_x86_64-pc-windows-gnu := -Wall -Werror -g -m64 -D_WIN32_WINNT=0x0600 $(CFLAGS)
CFG_GCCISH_CXXFLAGS_x86_64-pc-windows-gnu := -fno-rtti $(CXXFLAGS) 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_LINK_FLAGS_x86_64-pc-windows-gnu := -shared -g -m64

View File

@ -7,7 +7,7 @@ CFG_LIB_NAME_x86_64-unknown-dragonfly=lib$(1).so
CFG_STATIC_LIB_NAME_x86_64-unknown-dragonfly=lib$(1).a CFG_STATIC_LIB_NAME_x86_64-unknown-dragonfly=lib$(1).a
CFG_LIB_GLOB_x86_64-unknown-dragonfly=lib$(1)-*.so CFG_LIB_GLOB_x86_64-unknown-dragonfly=lib$(1)-*.so
CFG_LIB_DSYM_GLOB_x86_64-unknown-dragonfly=$(1)-*.dylib.dSYM CFG_LIB_DSYM_GLOB_x86_64-unknown-dragonfly=$(1)-*.dylib.dSYM
CFG_CFLAGS_x86_64-unknown-dragonfly := -I/usr/include -I/usr/local/include $(CFLAGS) CFG_JEMALLOC_CFLAGS_x86_64-unknown-dragonfly := -I/usr/include -I/usr/local/include $(CFLAGS)
CFG_GCCISH_CFLAGS_x86_64-unknown-dragonfly := -Wall -Werror -g -fPIC -I/usr/include -I/usr/local/include $(CFLAGS) CFG_GCCISH_CFLAGS_x86_64-unknown-dragonfly := -Wall -Werror -g -fPIC -I/usr/include -I/usr/local/include $(CFLAGS)
CFG_GCCISH_LINK_FLAGS_x86_64-unknown-dragonfly := -shared -fPIC -g -pthread -lrt CFG_GCCISH_LINK_FLAGS_x86_64-unknown-dragonfly := -shared -fPIC -g -pthread -lrt
CFG_GCCISH_DEF_FLAG_x86_64-unknown-dragonfly := -Wl,--export-dynamic,--dynamic-list= CFG_GCCISH_DEF_FLAG_x86_64-unknown-dragonfly := -Wl,--export-dynamic,--dynamic-list=

View File

@ -7,7 +7,7 @@ CFG_LIB_NAME_x86_64-unknown-freebsd=lib$(1).so
CFG_STATIC_LIB_NAME_x86_64-unknown-freebsd=lib$(1).a CFG_STATIC_LIB_NAME_x86_64-unknown-freebsd=lib$(1).a
CFG_LIB_GLOB_x86_64-unknown-freebsd=lib$(1)-*.so CFG_LIB_GLOB_x86_64-unknown-freebsd=lib$(1)-*.so
CFG_LIB_DSYM_GLOB_x86_64-unknown-freebsd=$(1)-*.dylib.dSYM CFG_LIB_DSYM_GLOB_x86_64-unknown-freebsd=$(1)-*.dylib.dSYM
CFG_CFLAGS_x86_64-unknown-freebsd := -I/usr/local/include $(CFLAGS) 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_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_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_DEF_FLAG_x86_64-unknown-freebsd := -Wl,--export-dynamic,--dynamic-list=

View File

@ -7,7 +7,7 @@ CFG_LIB_NAME_x86_64-unknown-linux-gnu=lib$(1).so
CFG_STATIC_LIB_NAME_x86_64-unknown-linux-gnu=lib$(1).a CFG_STATIC_LIB_NAME_x86_64-unknown-linux-gnu=lib$(1).a
CFG_LIB_GLOB_x86_64-unknown-linux-gnu=lib$(1)-*.so CFG_LIB_GLOB_x86_64-unknown-linux-gnu=lib$(1)-*.so
CFG_LIB_DSYM_GLOB_x86_64-unknown-linux-gnu=lib$(1)-*.dylib.dSYM CFG_LIB_DSYM_GLOB_x86_64-unknown-linux-gnu=lib$(1)-*.dylib.dSYM
CFG_CFLAGS_x86_64-unknown-linux-gnu := -m64 CFG_JEMALLOC_CFLAGS_x86_64-unknown-linux-gnu := -m64
CFG_GCCISH_CFLAGS_x86_64-unknown-linux-gnu := -Wall -Werror -g -fPIC -m64 CFG_GCCISH_CFLAGS_x86_64-unknown-linux-gnu := -Wall -Werror -g -fPIC -m64
CFG_GCCISH_CXXFLAGS_x86_64-unknown-linux-gnu := -fno-rtti CFG_GCCISH_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_LINK_FLAGS_x86_64-unknown-linux-gnu := -shared -fPIC -ldl -pthread -lrt -g -m64

View File

@ -177,11 +177,11 @@ $$(JEMALLOC_LOCAL_$(1)): $$(JEMALLOC_DEPS) $$(MKFILE_DEPS)
cd "$$(JEMALLOC_BUILD_DIR_$(1))"; "$(S)src/jemalloc/configure" \ cd "$$(JEMALLOC_BUILD_DIR_$(1))"; "$(S)src/jemalloc/configure" \
$$(JEMALLOC_ARGS_$(1)) --with-jemalloc-prefix=je_ $(CFG_JEMALLOC_FLAGS) \ $$(JEMALLOC_ARGS_$(1)) --with-jemalloc-prefix=je_ $(CFG_JEMALLOC_FLAGS) \
--build=$$(CFG_GNU_TRIPLE_$(CFG_BUILD)) --host=$$(CFG_GNU_TRIPLE_$(1)) \ --build=$$(CFG_GNU_TRIPLE_$(CFG_BUILD)) --host=$$(CFG_GNU_TRIPLE_$(1)) \
CC="$$(CC_$(1))" \ CC="$$(CC_$(1)) $$(CFG_JEMALLOC_CFLAGS_$(1))" \
AR="$$(AR_$(1))" \ AR="$$(AR_$(1))" \
RANLIB="$$(AR_$(1)) s" \ RANLIB="$$(AR_$(1)) s" \
CPPFLAGS="-I $(S)src/rt/" \ CPPFLAGS="-I $(S)src/rt/" \
EXTRA_CFLAGS="$$(CFG_CFLAGS_$(1)) $$(CFG_JEMALLOC_CFLAGS_$(1)) -g1" EXTRA_CFLAGS="-g1"
$$(Q)$$(MAKE) -C "$$(JEMALLOC_BUILD_DIR_$(1))" build_lib_static $$(Q)$$(MAKE) -C "$$(JEMALLOC_BUILD_DIR_$(1))" build_lib_static
ifeq ($$(CFG_DISABLE_JEMALLOC),) ifeq ($$(CFG_DISABLE_JEMALLOC),)

View File

@ -304,8 +304,8 @@ r##"foo #"# bar"##; // foo #"# bar
#### Byte and byte string literals #### Byte and byte string literals
```{.ebnf .gram} ```{.ebnf .gram}
byte_lit : 'b' '\x27' byte_body '\x27' ; byte_lit : "b\x27" byte_body '\x27' ;
byte_string_lit : 'b' '"' string_body * '"' | 'b' 'r' raw_byte_string ; byte_string_lit : "b\x22" string_body * '\x22' | "br" raw_byte_string ;
byte_body : ascii_non_single_quote byte_body : ascii_non_single_quote
| '\x5c' [ '\x27' | common_escape ] ; | '\x5c' [ '\x27' | common_escape ] ;
@ -381,10 +381,10 @@ num_suffix : int_suffix | float_suffix ;
int_suffix : 'u' int_suffix_size ? int_suffix : 'u' int_suffix_size ?
| 'i' int_suffix_size ? ; | 'i' int_suffix_size ? ;
int_suffix_size : [ '8' | '1' '6' | '3' '2' | '6' '4' ] ; int_suffix_size : [ '8' | "16" | "32" | "64" ] ;
float_suffix : [ exponent | '.' dec_lit exponent ? ] ? float_suffix_ty ? ; float_suffix : [ exponent | '.' dec_lit exponent ? ] ? float_suffix_ty ? ;
float_suffix_ty : 'f' [ '3' '2' | '6' '4' ] ; float_suffix_ty : 'f' [ "32" | "64" ] ;
exponent : ['E' | 'e'] ['-' | '+' ] ? dec_lit ; exponent : ['E' | 'e'] ['-' | '+' ] ? dec_lit ;
dec_lit : [ dec_digit | '_' ] + ; dec_lit : [ dec_digit | '_' ] + ;
``` ```
@ -1862,7 +1862,7 @@ the namespace hierarchy as it normally would.
## Attributes ## Attributes
```{.ebnf .gram} ```{.ebnf .gram}
attribute : '#' '!' ? '[' meta_item ']' ; attribute : "#!" ? '[' meta_item ']' ;
meta_item : ident [ '=' literal meta_item : ident [ '=' literal
| '(' meta_seq ')' ] ? ; | '(' meta_seq ')' ] ? ;
meta_seq : meta_item [ ',' meta_seq ] ? ; meta_seq : meta_item [ ',' meta_seq ] ? ;

View File

@ -178,7 +178,7 @@ fn parse_antlr_token(s: &str, tokens: &HashMap<String, Token>) -> TokenAndSpan {
let toknum = m.name("toknum"); let toknum = m.name("toknum");
let content = m.name("content"); let content = m.name("content");
let proto_tok = tokens.find_equiv(&toknum).expect(format!("didn't find token {} in the map", let proto_tok = tokens.get(&toknum).expect(format!("didn't find token {} in the map",
toknum).as_slice()); toknum).as_slice());
let nm = parse::token::intern(content); let nm = parse::token::intern(content);

View File

@ -283,7 +283,7 @@ impl Bitv {
x != 0 x != 0
} }
/// Sets the value of a bit at a index `i`. /// Sets the value of a bit at an index `i`.
/// ///
/// # Panics /// # Panics
/// ///
@ -582,7 +582,7 @@ impl Bitv {
/// ///
/// # Panics /// # Panics
/// ///
/// Panics if the the `Bitv` and slice are of different length. /// Panics if the `Bitv` and slice are of different length.
/// ///
/// # Example /// # Example
/// ///

View File

@ -21,6 +21,7 @@ use core::prelude::*;
use self::StackOp::*; use self::StackOp::*;
use super::node::*; use super::node::*;
use core::borrow::BorrowFrom;
use std::hash::{Writer, Hash}; use std::hash::{Writer, Hash};
use core::default::Default; use core::default::Default;
use core::{iter, fmt, mem}; use core::{iter, fmt, mem};
@ -56,7 +57,7 @@ use ring_buf::RingBuf;
/// and possibly other factors. Using linear search, searching for a random element is expected /// and possibly other factors. Using linear search, searching for a random element is expected
/// to take O(B log<sub>B</sub>n) comparisons, which is generally worse than a BST. In practice, /// to take O(B log<sub>B</sub>n) comparisons, which is generally worse than a BST. In practice,
/// however, performance is excellent. `BTreeMap` is able to readily outperform `TreeMap` under /// however, performance is excellent. `BTreeMap` is able to readily outperform `TreeMap` under
/// many workloads, and is competetive where it doesn't. BTreeMap also generally *scales* better /// many workloads, and is competitive where it doesn't. BTreeMap also generally *scales* better
/// than TreeMap, making it more appropriate for large datasets. /// than TreeMap, making it more appropriate for large datasets.
/// ///
/// However, `TreeMap` may still be more appropriate to use in many contexts. If elements are very /// However, `TreeMap` may still be more appropriate to use in many contexts. If elements are very
@ -184,6 +185,9 @@ impl<K: Ord, V> BTreeMap<K, V> {
/// Returns a reference to the value corresponding to the key. /// Returns a reference to the value corresponding to the key.
/// ///
/// The key may be any borrowed form of the map's key type, but the ordering
/// on the borrowed form *must* match the ordering on the key type.
///
/// # Example /// # Example
/// ///
/// ``` /// ```
@ -195,7 +199,7 @@ impl<K: Ord, V> BTreeMap<K, V> {
/// assert_eq!(map.get(&2), None); /// assert_eq!(map.get(&2), None);
/// ``` /// ```
#[unstable = "matches collection reform specification, waiting for dust to settle"] #[unstable = "matches collection reform specification, waiting for dust to settle"]
pub fn get(&self, key: &K) -> Option<&V> { pub fn get<Sized? Q>(&self, key: &Q) -> Option<&V> where Q: BorrowFrom<K> + Ord {
let mut cur_node = &self.root; let mut cur_node = &self.root;
loop { loop {
match cur_node.search(key) { match cur_node.search(key) {
@ -213,6 +217,9 @@ impl<K: Ord, V> BTreeMap<K, V> {
/// Returns true if the map contains a value for the specified key. /// Returns true if the map contains a value for the specified key.
/// ///
/// The key may be any borrowed form of the map's key type, but the ordering
/// on the borrowed form *must* match the ordering on the key type.
///
/// # Example /// # Example
/// ///
/// ``` /// ```
@ -224,7 +231,7 @@ impl<K: Ord, V> BTreeMap<K, V> {
/// assert_eq!(map.contains_key(&2), false); /// assert_eq!(map.contains_key(&2), false);
/// ``` /// ```
#[unstable = "matches collection reform specification, waiting for dust to settle"] #[unstable = "matches collection reform specification, waiting for dust to settle"]
pub fn contains_key(&self, key: &K) -> bool { pub fn contains_key<Sized? Q>(&self, key: &Q) -> bool where Q: BorrowFrom<K> + Ord {
self.get(key).is_some() self.get(key).is_some()
} }
@ -236,6 +243,9 @@ impl<K: Ord, V> BTreeMap<K, V> {
/// Returns a mutable reference to the value corresponding to the key. /// Returns a mutable reference to the value corresponding to the key.
/// ///
/// The key may be any borrowed form of the map's key type, but the ordering
/// on the borrowed form *must* match the ordering on the key type.
///
/// # Example /// # Example
/// ///
/// ``` /// ```
@ -251,7 +261,7 @@ impl<K: Ord, V> BTreeMap<K, V> {
/// ``` /// ```
// See `get` for implementation notes, this is basically a copy-paste with mut's added // See `get` for implementation notes, this is basically a copy-paste with mut's added
#[unstable = "matches collection reform specification, waiting for dust to settle"] #[unstable = "matches collection reform specification, waiting for dust to settle"]
pub fn get_mut(&mut self, key: &K) -> Option<&mut V> { pub fn get_mut<Sized? Q>(&mut self, key: &Q) -> Option<&mut V> where Q: BorrowFrom<K> + Ord {
// temp_node is a Borrowck hack for having a mutable value outlive a loop iteration // temp_node is a Borrowck hack for having a mutable value outlive a loop iteration
let mut temp_node = &mut self.root; let mut temp_node = &mut self.root;
loop { loop {
@ -410,6 +420,9 @@ impl<K: Ord, V> BTreeMap<K, V> {
/// Removes a key from the map, returning the value at the key if the key /// Removes a key from the map, returning the value at the key if the key
/// was previously in the map. /// was previously in the map.
/// ///
/// The key may be any borrowed form of the map's key type, but the ordering
/// on the borrowed form *must* match the ordering on the key type.
///
/// # Example /// # Example
/// ///
/// ``` /// ```
@ -421,7 +434,7 @@ impl<K: Ord, V> BTreeMap<K, V> {
/// assert_eq!(map.remove(&1), None); /// assert_eq!(map.remove(&1), None);
/// ``` /// ```
#[unstable = "matches collection reform specification, waiting for dust to settle"] #[unstable = "matches collection reform specification, waiting for dust to settle"]
pub fn remove(&mut self, key: &K) -> Option<V> { pub fn remove<Sized? Q>(&mut self, key: &Q) -> Option<V> where Q: BorrowFrom<K> + Ord {
// See `swap` for a more thorough description of the stuff going on in here // See `swap` for a more thorough description of the stuff going on in here
let mut stack = stack::PartialSearchStack::new(self); let mut stack = stack::PartialSearchStack::new(self);
loop { loop {
@ -790,14 +803,18 @@ impl<K: Show, V: Show> Show for BTreeMap<K, V> {
} }
} }
impl<K: Ord, V> Index<K, V> for BTreeMap<K, V> { impl<K: Ord, Sized? Q, V> Index<Q, V> for BTreeMap<K, V>
fn index(&self, key: &K) -> &V { where Q: BorrowFrom<K> + Ord
{
fn index(&self, key: &Q) -> &V {
self.get(key).expect("no entry found for key") self.get(key).expect("no entry found for key")
} }
} }
impl<K: Ord, V> IndexMut<K, V> for BTreeMap<K, V> { impl<K: Ord, Sized? Q, V> IndexMut<Q, V> for BTreeMap<K, V>
fn index_mut(&mut self, key: &K) -> &mut V { where Q: BorrowFrom<K> + Ord
{
fn index_mut(&mut self, key: &Q) -> &mut V {
self.get_mut(key).expect("no entry found for key") self.get_mut(key).expect("no entry found for key")
} }
} }

View File

@ -19,6 +19,7 @@ use core::prelude::*;
use core::{slice, mem, ptr}; use core::{slice, mem, ptr};
use core::iter::Zip; use core::iter::Zip;
use core::borrow::BorrowFrom;
use vec; use vec;
use vec::Vec; use vec::Vec;
@ -47,7 +48,7 @@ pub struct Node<K, V> {
// theory, if we take full control of allocation like HashMap's RawTable does, // theory, if we take full control of allocation like HashMap's RawTable does,
// and restrict leaves to max size 256 (not unreasonable for a btree node) we can cut // and restrict leaves to max size 256 (not unreasonable for a btree node) we can cut
// this down to just (ptr, cap: u8, size: u8, is_leaf: bool). With generic // this down to just (ptr, cap: u8, size: u8, is_leaf: bool). With generic
// integer arguments, cap can even move into the the type, reducing this just to // integer arguments, cap can even move into the type, reducing this just to
// (ptr, size, is_leaf). This could also have cache benefits for very small nodes, as keys // (ptr, size, is_leaf). This could also have cache benefits for very small nodes, as keys
// could bleed into edges and vals. // could bleed into edges and vals.
// //
@ -73,19 +74,19 @@ impl<K: Ord, V> Node<K, V> {
/// Searches for the given key in the node. If it finds an exact match, /// Searches for the given key in the node. If it finds an exact match,
/// `Found` will be yielded with the matching index. If it doesn't find an exact match, /// `Found` will be yielded with the matching index. If it doesn't find an exact match,
/// `GoDown` will be yielded with the index of the subtree the key must lie in. /// `GoDown` will be yielded with the index of the subtree the key must lie in.
pub fn search(&self, key: &K) -> SearchResult { pub fn search<Sized? Q>(&self, key: &Q) -> SearchResult where Q: BorrowFrom<K> + Ord {
// FIXME(Gankro): Tune when to search linear or binary based on B (and maybe K/V). // FIXME(Gankro): Tune when to search linear or binary based on B (and maybe K/V).
// For the B configured as of this writing (B = 6), binary search was *significantly* // For the B configured as of this writing (B = 6), binary search was *significantly*
// worse for uints. // worse for uints.
self.search_linear(key) self.search_linear(key)
} }
fn search_linear(&self, key: &K) -> SearchResult { fn search_linear<Sized? Q>(&self, key: &Q) -> SearchResult where Q: BorrowFrom<K> + Ord {
for (i, k) in self.keys.iter().enumerate() { for (i, k) in self.keys.iter().enumerate() {
match k.cmp(key) { match key.cmp(BorrowFrom::borrow_from(k)) {
Less => {}, Greater => {},
Equal => return Found(i), Equal => return Found(i),
Greater => return GoDown(i), Less => return GoDown(i),
} }
} }
GoDown(self.len()) GoDown(self.len())

View File

@ -15,6 +15,7 @@ use core::prelude::*;
use btree_map::{BTreeMap, Keys, MoveEntries}; use btree_map::{BTreeMap, Keys, MoveEntries};
use std::hash::Hash; use std::hash::Hash;
use core::borrow::BorrowFrom;
use core::default::Default; use core::default::Default;
use core::{iter, fmt}; use core::{iter, fmt};
use core::iter::Peekable; use core::iter::Peekable;
@ -167,6 +168,10 @@ impl<T: Ord> BTreeSet<T> {
/// Returns `true` if the set contains a value. /// Returns `true` if the set contains a value.
/// ///
/// The value may be any borrowed form of the set's value type,
/// but the ordering on the borrowed form *must* match the
/// ordering on the value type.
///
/// # Example /// # Example
/// ///
/// ``` /// ```
@ -177,7 +182,7 @@ impl<T: Ord> BTreeSet<T> {
/// assert_eq!(set.contains(&4), false); /// assert_eq!(set.contains(&4), false);
/// ``` /// ```
#[unstable = "matches collection reform specification, waiting for dust to settle"] #[unstable = "matches collection reform specification, waiting for dust to settle"]
pub fn contains(&self, value: &T) -> bool { pub fn contains<Sized? Q>(&self, value: &Q) -> bool where Q: BorrowFrom<T> + Ord {
self.map.contains_key(value) self.map.contains_key(value)
} }
@ -291,6 +296,10 @@ impl<T: Ord> BTreeSet<T> {
/// Removes a value from the set. Returns `true` if the value was /// Removes a value from the set. Returns `true` if the value was
/// present in the set. /// present in the set.
/// ///
/// The value may be any borrowed form of the set's value type,
/// but the ordering on the borrowed form *must* match the
/// ordering on the value type.
///
/// # Example /// # Example
/// ///
/// ``` /// ```
@ -303,7 +312,7 @@ impl<T: Ord> BTreeSet<T> {
/// assert_eq!(set.remove(&2), false); /// assert_eq!(set.remove(&2), false);
/// ``` /// ```
#[unstable = "matches collection reform specification, waiting for dust to settle"] #[unstable = "matches collection reform specification, waiting for dust to settle"]
pub fn remove(&mut self, value: &T) -> bool { pub fn remove<Sized? Q>(&mut self, value: &Q) -> bool where Q: BorrowFrom<T> + Ord {
self.map.remove(value).is_some() self.map.remove(value).is_some()
} }
} }

View File

@ -89,6 +89,7 @@
use self::Direction::*; use self::Direction::*;
use alloc::boxed::Box; use alloc::boxed::Box;
use core::borrow::{BorrowFrom, BorrowFromMut};
use core::cmp; use core::cmp;
use core::kinds::Sized; use core::kinds::Sized;
use core::mem::size_of; use core::mem::size_of;
@ -647,6 +648,16 @@ impl<T> SliceAllocPrelude<T> for [T] {
} }
} }
#[unstable = "trait is unstable"]
impl<T> BorrowFrom<Vec<T>> for [T] {
fn borrow_from(owned: &Vec<T>) -> &[T] { owned[] }
}
#[unstable = "trait is unstable"]
impl<T> BorrowFromMut<Vec<T>> for [T] {
fn borrow_from_mut(owned: &mut Vec<T>) -> &mut [T] { owned[mut] }
}
/// Unsafe operations /// Unsafe operations
pub mod raw { pub mod raw {
pub use core::slice::raw::{buf_as_slice, mut_buf_as_slice}; pub use core::slice::raw::{buf_as_slice, mut_buf_as_slice};

View File

@ -54,7 +54,7 @@
pub use self::MaybeOwned::*; pub use self::MaybeOwned::*;
use self::RecompositionState::*; use self::RecompositionState::*;
use self::DecompositionType::*; use self::DecompositionType::*;
use core::borrow::BorrowFrom;
use core::default::Default; use core::default::Default;
use core::fmt; use core::fmt;
use core::cmp; use core::cmp;
@ -604,6 +604,11 @@ impl<'a> fmt::Show for MaybeOwned<'a> {
} }
} }
#[unstable = "trait is unstable"]
impl BorrowFrom<String> for str {
fn borrow_from(owned: &String) -> &str { owned[] }
}
/// Unsafe string operations. /// Unsafe string operations.
pub mod raw { pub mod raw {
pub use core::str::raw::{from_utf8, c_str_to_static_slice, slice_bytes}; pub use core::str::raw::{from_utf8, c_str_to_static_slice, slice_bytes};
@ -1258,13 +1263,13 @@ mod tests {
#[test] #[test]
fn test_slice_shift_char() { fn test_slice_shift_char() {
let data = "ประเทศไทย中"; let data = "ประเทศไทย中";
assert_eq!(data.slice_shift_char(), (Some('ป'), "ระเทศไทย中")); assert_eq!(data.slice_shift_char(), Some(('ป', "ระเทศไทย中")));
} }
#[test] #[test]
fn test_slice_shift_char_2() { fn test_slice_shift_char_2() {
let empty = ""; let empty = "";
assert_eq!(empty.slice_shift_char(), (None, "")); assert_eq!(empty.slice_shift_char(), None);
} }
#[test] #[test]

View File

@ -549,7 +549,7 @@ impl String {
/// ///
/// # Warning /// # Warning
/// ///
/// This is a O(n) operation as it requires copying every element in the /// This is an O(n) operation as it requires copying every element in the
/// buffer. /// buffer.
/// ///
/// # Panics /// # Panics
@ -586,7 +586,7 @@ impl String {
/// ///
/// # Warning /// # Warning
/// ///
/// This is a O(n) operation as it requires copying every element in the /// This is an O(n) operation as it requires copying every element in the
/// buffer. /// buffer.
/// ///
/// # Panics /// # Panics

View File

@ -11,6 +11,8 @@
use core::prelude::*; use core::prelude::*;
use alloc::boxed::Box; use alloc::boxed::Box;
use core::borrow::BorrowFrom;
use core::default::Default; use core::default::Default;
use core::fmt; use core::fmt;
use core::fmt::Show; use core::fmt::Show;
@ -188,16 +190,16 @@ impl<K: Ord, V> Default for TreeMap<K,V> {
fn default() -> TreeMap<K, V> { TreeMap::new() } fn default() -> TreeMap<K, V> { TreeMap::new() }
} }
impl<K: Ord, V> Index<K, V> for TreeMap<K, V> { impl<K: Ord, Sized? Q, V> Index<Q, V> for TreeMap<K, V> where Q: BorrowFrom<K> + Ord {
#[inline] #[inline]
fn index<'a>(&'a self, i: &K) -> &'a V { fn index<'a>(&'a self, i: &Q) -> &'a V {
self.get(i).expect("no entry found for key") self.get(i).expect("no entry found for key")
} }
} }
impl<K: Ord, V> IndexMut<K, V> for TreeMap<K, V> { impl<K: Ord, Sized? Q, V> IndexMut<Q, V> for TreeMap<K, V> where Q: BorrowFrom<K> + Ord {
#[inline] #[inline]
fn index_mut<'a>(&'a mut self, i: &K) -> &'a mut V { fn index_mut<'a>(&'a mut self, i: &Q) -> &'a mut V {
self.get_mut(i).expect("no entry found for key") self.get_mut(i).expect("no entry found for key")
} }
} }
@ -446,6 +448,9 @@ impl<K: Ord, V> TreeMap<K, V> {
/// Returns a reference to the value corresponding to the key. /// Returns a reference to the value corresponding to the key.
/// ///
/// The key may be any borrowed form of the map's key type, but the ordering
/// on the borrowed form *must* match the ordering on the key type.
///
/// # Example /// # Example
/// ///
/// ``` /// ```
@ -458,12 +463,17 @@ impl<K: Ord, V> TreeMap<K, V> {
/// ``` /// ```
#[inline] #[inline]
#[unstable = "matches collection reform specification, waiting for dust to settle"] #[unstable = "matches collection reform specification, waiting for dust to settle"]
pub fn get(&self, key: &K) -> Option<&V> { pub fn get<Sized? Q>(&self, key: &Q) -> Option<&V>
tree_find_with(&self.root, |k2| key.cmp(k2)) where Q: BorrowFrom<K> + Ord
{
tree_find_with(&self.root, |k2| key.cmp(BorrowFrom::borrow_from(k2)))
} }
/// Returns true if the map contains a value for the specified key. /// Returns true if the map contains a value for the specified key.
/// ///
/// The key may be any borrowed form of the map's key type, but the ordering
/// on the borrowed form *must* match the ordering on the key type.
///
/// # Example /// # Example
/// ///
/// ``` /// ```
@ -476,7 +486,9 @@ impl<K: Ord, V> TreeMap<K, V> {
/// ``` /// ```
#[inline] #[inline]
#[unstable = "matches collection reform specification, waiting for dust to settle"] #[unstable = "matches collection reform specification, waiting for dust to settle"]
pub fn contains_key(&self, key: &K) -> bool { pub fn contains_key<Sized? Q>(&self, key: &Q) -> bool
where Q: BorrowFrom<K> + Ord
{
self.get(key).is_some() self.get(key).is_some()
} }
@ -488,6 +500,9 @@ impl<K: Ord, V> TreeMap<K, V> {
/// Returns a mutable reference to the value corresponding to the key. /// Returns a mutable reference to the value corresponding to the key.
/// ///
/// The key may be any borrowed form of the map's key type, but the ordering
/// on the borrowed form *must* match the ordering on the key type.
///
/// # Example /// # Example
/// ///
/// ``` /// ```
@ -503,8 +518,10 @@ impl<K: Ord, V> TreeMap<K, V> {
/// ``` /// ```
#[inline] #[inline]
#[unstable = "matches collection reform specification, waiting for dust to settle"] #[unstable = "matches collection reform specification, waiting for dust to settle"]
pub fn get_mut(&mut self, key: &K) -> Option<&mut V> { pub fn get_mut<Sized? Q>(&mut self, key: &Q) -> Option<&mut V>
tree_find_with_mut(&mut self.root, |x| key.cmp(x)) where Q: BorrowFrom<K> + Ord
{
tree_find_with_mut(&mut self.root, |x| key.cmp(BorrowFrom::borrow_from(x)))
} }
/// Deprecated: Renamed to `insert`. /// Deprecated: Renamed to `insert`.
@ -545,6 +562,9 @@ impl<K: Ord, V> TreeMap<K, V> {
/// Removes a key from the map, returning the value at the key if the key /// Removes a key from the map, returning the value at the key if the key
/// was previously in the map. /// was previously in the map.
/// ///
/// The key may be any borrowed form of the map's key type, but the ordering
/// on the borrowed form *must* match the ordering on the key type.
///
/// # Example /// # Example
/// ///
/// ``` /// ```
@ -556,7 +576,9 @@ impl<K: Ord, V> TreeMap<K, V> {
/// assert_eq!(map.remove(&1), None); /// assert_eq!(map.remove(&1), None);
/// ``` /// ```
#[unstable = "matches collection reform specification, waiting for dust to settle"] #[unstable = "matches collection reform specification, waiting for dust to settle"]
pub fn remove(&mut self, key: &K) -> Option<V> { pub fn remove<Sized? Q>(&mut self, key: &Q) -> Option<V>
where Q: BorrowFrom<K> + Ord
{
let ret = remove(&mut self.root, key); let ret = remove(&mut self.root, key);
if ret.is_some() { self.length -= 1 } if ret.is_some() { self.length -= 1 }
ret ret
@ -589,6 +611,7 @@ impl<K, V> TreeMap<K, V> {
/// assert_eq!((*ua.unwrap()).as_slice(), "Curl-Rust/0.1"); /// assert_eq!((*ua.unwrap()).as_slice(), "Curl-Rust/0.1");
/// ``` /// ```
#[inline] #[inline]
#[experimental = "likely to be renamed, may be removed"]
pub fn find_with(&self, f:|&K| -> Ordering) -> Option<&V> { pub fn find_with(&self, f:|&K| -> Ordering) -> Option<&V> {
tree_find_with(&self.root, f) tree_find_with(&self.root, f)
} }
@ -613,6 +636,7 @@ impl<K, V> TreeMap<K, V> {
/// assert_eq!(t.get(&"User-Agent"), Some(&new_ua)); /// assert_eq!(t.get(&"User-Agent"), Some(&new_ua));
/// ``` /// ```
#[inline] #[inline]
#[experimental = "likely to be renamed, may be removed"]
pub fn find_with_mut<'a>(&'a mut self, f:|&K| -> Ordering) -> Option<&'a mut V> { pub fn find_with_mut<'a>(&'a mut self, f:|&K| -> Ordering) -> Option<&'a mut V> {
tree_find_with_mut(&mut self.root, f) tree_find_with_mut(&mut self.root, f)
} }
@ -1168,8 +1192,9 @@ fn insert<K: Ord, V>(node: &mut Option<Box<TreeNode<K, V>>>,
} }
} }
fn remove<K: Ord, V>(node: &mut Option<Box<TreeNode<K, V>>>, fn remove<K, Sized? Q, V>(node: &mut Option<Box<TreeNode<K, V>>>, key: &Q) -> Option<V>
key: &K) -> Option<V> { where K: Ord, Q: BorrowFrom<K> + Ord
{
fn heir_swap<K: Ord, V>(node: &mut Box<TreeNode<K, V>>, fn heir_swap<K: Ord, V>(node: &mut Box<TreeNode<K, V>>,
child: &mut Option<Box<TreeNode<K, V>>>) { child: &mut Option<Box<TreeNode<K, V>>>) {
// *could* be done without recursion, but it won't borrow check // *could* be done without recursion, but it won't borrow check
@ -1188,7 +1213,7 @@ fn remove<K: Ord, V>(node: &mut Option<Box<TreeNode<K, V>>>,
return None; // bottom of tree return None; // bottom of tree
} }
Some(ref mut save) => { Some(ref mut save) => {
let (ret, rebalance) = match key.cmp(&save.key) { let (ret, rebalance) = match key.cmp(BorrowFrom::borrow_from(&save.key)) {
Less => (remove(&mut save.left, key), true), Less => (remove(&mut save.left, key), true),
Greater => (remove(&mut save.right, key), true), Greater => (remove(&mut save.right, key), true),
Equal => { Equal => {
@ -1918,4 +1943,3 @@ mod bench {
bench_iter(b, 100000); bench_iter(b, 100000);
} }
} }

View File

@ -10,6 +10,7 @@
use core::prelude::*; use core::prelude::*;
use core::borrow::BorrowFrom;
use core::default::Default; use core::default::Default;
use core::fmt; use core::fmt;
use core::fmt::Show; use core::fmt::Show;
@ -396,6 +397,10 @@ impl<T: Ord> TreeSet<T> {
/// Returns `true` if the set contains a value. /// Returns `true` if the set contains a value.
/// ///
/// The value may be any borrowed form of the set's value type,
/// but the ordering on the borrowed form *must* match the
/// ordering on the value type.
///
/// # Example /// # Example
/// ///
/// ``` /// ```
@ -407,7 +412,9 @@ impl<T: Ord> TreeSet<T> {
/// ``` /// ```
#[inline] #[inline]
#[unstable = "matches collection reform specification, waiting for dust to settle"] #[unstable = "matches collection reform specification, waiting for dust to settle"]
pub fn contains(&self, value: &T) -> bool { pub fn contains<Sized? Q>(&self, value: &Q) -> bool
where Q: Ord + BorrowFrom<T>
{
self.map.contains_key(value) self.map.contains_key(value)
} }
@ -519,6 +526,10 @@ impl<T: Ord> TreeSet<T> {
/// Removes a value from the set. Returns `true` if the value was /// Removes a value from the set. Returns `true` if the value was
/// present in the set. /// present in the set.
/// ///
/// The value may be any borrowed form of the set's value type,
/// but the ordering on the borrowed form *must* match the
/// ordering on the value type.
///
/// # Example /// # Example
/// ///
/// ``` /// ```
@ -532,7 +543,11 @@ impl<T: Ord> TreeSet<T> {
/// ``` /// ```
#[inline] #[inline]
#[unstable = "matches collection reform specification, waiting for dust to settle"] #[unstable = "matches collection reform specification, waiting for dust to settle"]
pub fn remove(&mut self, value: &T) -> bool { self.map.remove(value).is_some() } pub fn remove<Sized? Q>(&mut self, value: &Q) -> bool
where Q: Ord + BorrowFrom<T>
{
self.map.remove(value).is_some()
}
} }
/// A lazy forward iterator over a set. /// A lazy forward iterator over a set.

View File

@ -1057,7 +1057,7 @@ impl<'a, T> VacantEntry<'a, T> {
search_stack.map.root.count = temp; search_stack.map.root.count = temp;
value_ref value_ref
} }
// Otherwise, find the predeccessor of the last stack node, and insert as normal. // Otherwise, find the predecessor of the last stack node, and insert as normal.
else { else {
match *search_stack.get_ref(old_length - 2) { match *search_stack.get_ref(old_length - 2) {
Internal(box ref mut parent) => { Internal(box ref mut parent) => {
@ -1741,7 +1741,7 @@ mod test {
// Update it to i^3 using the returned mutable reference. // Update it to i^3 using the returned mutable reference.
*inserted_val = i * i * i; *inserted_val = i * i * i;
}, },
_ => panic!("Non-existant key found.") _ => panic!("Non-existent key found.")
} }
assert_eq!(map.get(&i).unwrap(), &(i * i * i)); assert_eq!(map.get(&i).unwrap(), &(i * i * i));
} }

View File

@ -8,22 +8,36 @@
// option. This file may not be copied, modified, or distributed // option. This file may not be copied, modified, or distributed
// except according to those terms. // except according to those terms.
/*! //! Implementations of things like `Eq` for fixed-length arrays
* Implementations of things like `Eq` for fixed-length arrays //! up to a certain length. Eventually we should able to generalize
* up to a certain length. Eventually we should able to generalize //! to all lengths.
* to all lengths.
*/
#![stable]
#![experimental] // not yet reviewed #![experimental] // not yet reviewed
use cmp::*; use clone::Clone;
use option::{Option}; use cmp::{PartialEq, Eq, PartialOrd, Ord, Ordering};
use fmt;
use kinds::Copy;
use option::Option;
// macro for implementing n-ary tuple functions and operations // macro for implementing n-ary tuple functions and operations
macro_rules! array_impls { macro_rules! array_impls {
($($N:expr)+) => { ($($N:expr)+) => {
$( $(
#[unstable = "waiting for Clone to stabilize"]
impl<T:Copy> Clone for [T, ..$N] {
fn clone(&self) -> [T, ..$N] {
*self
}
}
#[unstable = "waiting for Show to stabilize"]
impl<T:fmt::Show> fmt::Show for [T, ..$N] {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::Show::fmt(&self[], f)
}
}
#[unstable = "waiting for PartialEq to stabilize"] #[unstable = "waiting for PartialEq to stabilize"]
impl<T:PartialEq> PartialEq for [T, ..$N] { impl<T:PartialEq> PartialEq for [T, ..$N] {
#[inline] #[inline]

127
src/libcore/borrow.rs Normal file
View File

@ -0,0 +1,127 @@
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
//! A module for working with borrowed data.
//!
//! # The `BorrowFrom` traits
//!
//! In general, there may be several ways to "borrow" a piece of data. The
//! typical ways of borrowing a type `T` are `&T` (a shared borrow) and `&mut T`
//! (a mutable borrow). But types like `Vec<T>` provide additional kinds of
//! borrows: the borrowed slices `&[T]` and `&mut [T]`.
//!
//! When writing generic code, it is often desirable to abstract over all ways
//! of borrowing data from a given type. That is the role of the `BorrowFrom`
//! trait: if `T: BorrowFrom<U>`, then `&T` can be borrowed from `&U`. A given
//! type can be borrowed as multiple different types. In particular, `Vec<T>:
//! BorrowFrom<Vec<T>>` and `[T]: BorrowFrom<Vec<T>>`.
//!
//! # The `ToOwned` trait
//!
//! Some types make it possible to go from borrowed to owned, usually by
//! implementing the `Clone` trait. But `Clone` works only for going from `&T`
//! to `T`. The `ToOwned` trait generalizes `Clone` to construct owned data
//! from any borrow of a given type.
//!
//! # The `Cow` (clone-on-write) type
//!
//! The type `Cow` is a smart pointer providing clone-on-write functionality: it
//! can enclose and provide immutable access to borrowed data, and clone the
//! data lazily when mutation or ownership is required. The type is designed to
//! work with general borrowed data via the `BorrowFrom` trait.
//!
//! `Cow` implements both `Deref` and `DerefMut`, which means that you can call
//! methods directly on the data it encloses. The first time a mutable reference
//! is required, the data will be cloned (via `to_owned`) if it is not
//! already owned.
#![unstable = "recently added as part of collections reform"]
use clone::Clone;
use kinds::Sized;
use ops::Deref;
use self::Cow::*;
/// A trait for borrowing data.
pub trait BorrowFrom<Sized? Owned> for Sized? {
/// Immutably borrow from an owned value.
fn borrow_from(owned: &Owned) -> &Self;
}
/// A trait for mutably borrowing data.
pub trait BorrowFromMut<Sized? Owned> for Sized? : BorrowFrom<Owned> {
/// Mutably borrow from an owned value.
fn borrow_from_mut(owned: &mut Owned) -> &mut Self;
}
impl<Sized? T> BorrowFrom<T> for T {
fn borrow_from(owned: &T) -> &T { owned }
}
impl<Sized? T> BorrowFromMut<T> for T {
fn borrow_from_mut(owned: &mut T) -> &mut T { owned }
}
impl BorrowFrom<&'static str> for str {
fn borrow_from<'a>(owned: &'a &'static str) -> &'a str { &**owned }
}
/// A generalization of Clone to borrowed data.
pub trait ToOwned<Owned> for Sized?: BorrowFrom<Owned> {
/// Create owned data from borrowed data, usually by copying.
fn to_owned(&self) -> Owned;
}
impl<T> ToOwned<T> for T where T: Clone {
fn to_owned(&self) -> T { self.clone() }
}
/// A clone-on-write smart pointer.
pub enum Cow<'a, T, B: 'a> where B: ToOwned<T> {
/// Borrowed data.
Borrowed(&'a B),
/// Owned data.
Owned(T)
}
impl<'a, T, B> Cow<'a, T, B> where B: ToOwned<T> {
/// Acquire a mutable reference to the owned form of the data.
///
/// Copies the data if it is not already owned.
pub fn to_mut(&mut self) -> &mut T {
match *self {
Borrowed(borrowed) => {
*self = Owned(borrowed.to_owned());
self.to_mut()
}
Owned(ref mut owned) => owned
}
}
/// Extract the owned data.
///
/// Copies the data if it is not already owned.
pub fn into_owned(self) -> T {
match self {
Borrowed(borrowed) => borrowed.to_owned(),
Owned(owned) => owned
}
}
}
impl<'a, T, B> Deref<B> for Cow<'a, T, B> where B: ToOwned<T> {
fn deref(&self) -> &B {
match *self {
Borrowed(borrowed) => borrowed,
Owned(ref owned) => BorrowFrom::borrow_from(owned)
}
}
}

View File

@ -23,6 +23,8 @@ the `clone` method.
#![unstable] #![unstable]
use kinds::Sized;
/// A common trait for cloning an object. /// A common trait for cloning an object.
pub trait Clone { pub trait Clone {
/// Returns a copy of the value. /// Returns a copy of the value.
@ -40,24 +42,12 @@ pub trait Clone {
} }
} }
impl<'a, T> Clone for &'a T { impl<'a, Sized? T> Clone for &'a T {
/// Return a shallow copy of the reference. /// Return a shallow copy of the reference.
#[inline] #[inline]
fn clone(&self) -> &'a T { *self } fn clone(&self) -> &'a T { *self }
} }
impl<'a, T> Clone for &'a [T] {
/// Return a shallow copy of the slice.
#[inline]
fn clone(&self) -> &'a [T] { *self }
}
impl<'a> Clone for &'a str {
/// Return a shallow copy of the slice.
#[inline]
fn clone(&self) -> &'a str { *self }
}
macro_rules! clone_impl( macro_rules! clone_impl(
($t:ty) => { ($t:ty) => {
impl Clone for $t { impl Clone for $t {

View File

@ -108,6 +108,7 @@ pub mod default;
pub mod any; pub mod any;
pub mod atomic; pub mod atomic;
pub mod bool; pub mod bool;
pub mod borrow;
pub mod cell; pub mod cell;
pub mod char; pub mod char;
pub mod panicking; pub mod panicking;

View File

@ -88,7 +88,7 @@ pub fn align_of_val<T>(_val: &T) -> uint {
/// Create a value initialized to zero. /// Create a value initialized to zero.
/// ///
/// This function is similar to allocating space for a a local variable and /// This function is similar to allocating space for a local variable and
/// zeroing it out (an unsafe operation). /// zeroing it out (an unsafe operation).
/// ///
/// Care must be taken when using this function, if the type `T` has a /// Care must be taken when using this function, if the type `T` has a

View File

@ -198,7 +198,7 @@ pub trait Int
/// ``` /// ```
fn swap_bytes(self) -> Self; fn swap_bytes(self) -> Self;
/// Convert a integer from big endian to the target's endianness. /// Convert an integer from big endian to the target's endianness.
/// ///
/// On big endian this is a no-op. On little endian the bytes are swapped. /// On big endian this is a no-op. On little endian the bytes are swapped.
/// ///
@ -220,7 +220,7 @@ pub trait Int
if cfg!(target_endian = "big") { x } else { x.swap_bytes() } if cfg!(target_endian = "big") { x } else { x.swap_bytes() }
} }
/// Convert a integer from little endian to the target's endianness. /// Convert an integer from little endian to the target's endianness.
/// ///
/// On little endian this is a no-op. On big endian the bytes are swapped. /// On little endian this is a no-op. On big endian the bytes are swapped.
/// ///
@ -1457,10 +1457,10 @@ macro_rules! from_str_radix_float_impl {
} }
let (is_positive, src) = match src.slice_shift_char() { let (is_positive, src) = match src.slice_shift_char() {
(None, _) => return None, None => return None,
(Some('-'), "") => return None, Some(('-', "")) => return None,
(Some('-'), src) => (false, src), Some(('-', src)) => (false, src),
(Some(_), _) => (true, src), Some((_, _)) => (true, src),
}; };
// The significand to accumulate // The significand to accumulate
@ -1563,10 +1563,10 @@ macro_rules! from_str_radix_float_impl {
// Parse the exponent as decimal integer // Parse the exponent as decimal integer
let src = src[offset..]; let src = src[offset..];
let (is_positive, exp) = match src.slice_shift_char() { let (is_positive, exp) = match src.slice_shift_char() {
(Some('-'), src) => (false, from_str::<uint>(src)), Some(('-', src)) => (false, from_str::<uint>(src)),
(Some('+'), src) => (true, from_str::<uint>(src)), Some(('+', src)) => (true, from_str::<uint>(src)),
(Some(_), _) => (true, from_str::<uint>(src)), Some((_, _)) => (true, from_str::<uint>(src)),
(None, _) => return None, None => return None,
}; };
match (is_positive, exp) { match (is_positive, exp) {
@ -1606,7 +1606,7 @@ macro_rules! from_str_radix_int_impl {
let is_signed_ty = (0 as $T) > Int::min_value(); let is_signed_ty = (0 as $T) > Int::min_value();
match src.slice_shift_char() { match src.slice_shift_char() {
(Some('-'), src) if is_signed_ty => { Some(('-', src)) if is_signed_ty => {
// The number is negative // The number is negative
let mut result = 0; let mut result = 0;
for c in src.chars() { for c in src.chars() {
@ -1625,7 +1625,7 @@ macro_rules! from_str_radix_int_impl {
} }
Some(result) Some(result)
}, },
(Some(_), _) => { Some((_, _)) => {
// The number is signed // The number is signed
let mut result = 0; let mut result = 0;
for c in src.chars() { for c in src.chars() {
@ -1644,7 +1644,7 @@ macro_rules! from_str_radix_int_impl {
} }
Some(result) Some(result)
}, },
(None, _) => None, None => None,
} }
} }
} }

View File

@ -638,7 +638,7 @@ shr_impl!(uint u8 u16 u32 u64 int i8 i16 i32 i64)
* ``` * ```
*/ */
#[lang="index"] #[lang="index"]
pub trait Index<Index, Sized? Result> for Sized? { pub trait Index<Sized? Index, Sized? Result> for Sized? {
/// The method for the indexing (`Foo[Bar]`) operation /// The method for the indexing (`Foo[Bar]`) operation
fn index<'a>(&'a self, index: &Index) -> &'a Result; fn index<'a>(&'a self, index: &Index) -> &'a Result;
} }
@ -669,7 +669,7 @@ pub trait Index<Index, Sized? Result> for Sized? {
* ``` * ```
*/ */
#[lang="index_mut"] #[lang="index_mut"]
pub trait IndexMut<Index, Result> for Sized? { pub trait IndexMut<Sized? Index, Result> for Sized? {
/// The method for the indexing (`Foo[Bar]`) operation /// The method for the indexing (`Foo[Bar]`) operation
fn index_mut<'a>(&'a mut self, index: &Index) -> &'a mut Result; fn index_mut<'a>(&'a mut self, index: &Index) -> &'a mut Result;
} }

View File

@ -1811,21 +1811,21 @@ pub trait StrPrelude for Sized? {
/// it. This does not allocate a new string; instead, it returns a /// it. This does not allocate a new string; instead, it returns a
/// slice that point one character beyond the character that was /// slice that point one character beyond the character that was
/// shifted. If the string does not contain any characters, /// shifted. If the string does not contain any characters,
/// a tuple of None and an empty string is returned instead. /// None is returned instead.
/// ///
/// # Example /// # Example
/// ///
/// ```rust /// ```rust
/// let s = "Löwe 老虎 Léopard"; /// let s = "Löwe 老虎 Léopard";
/// let (c, s1) = s.slice_shift_char(); /// let (c, s1) = s.slice_shift_char().unwrap();
/// assert_eq!(c, Some('L')); /// assert_eq!(c, 'L');
/// assert_eq!(s1, "öwe 老虎 Léopard"); /// assert_eq!(s1, "öwe 老虎 Léopard");
/// ///
/// let (c, s2) = s1.slice_shift_char(); /// let (c, s2) = s1.slice_shift_char().unwrap();
/// assert_eq!(c, Some('ö')); /// assert_eq!(c, 'ö');
/// assert_eq!(s2, "we 老虎 Léopard"); /// assert_eq!(s2, "we 老虎 Léopard");
/// ``` /// ```
fn slice_shift_char<'a>(&'a self) -> (Option<char>, &'a str); fn slice_shift_char<'a>(&'a self) -> Option<(char, &'a str)>;
/// Returns the byte offset of an inner slice relative to an enclosing outer slice. /// Returns the byte offset of an inner slice relative to an enclosing outer slice.
/// ///
@ -2197,13 +2197,13 @@ impl StrPrelude for str {
} }
#[inline] #[inline]
fn slice_shift_char(&self) -> (Option<char>, &str) { fn slice_shift_char(&self) -> Option<(char, &str)> {
if self.is_empty() { if self.is_empty() {
return (None, self); None
} else { } else {
let CharRange {ch, next} = self.char_range_at(0u); let CharRange {ch, next} = self.char_range_at(0u);
let next_s = unsafe { raw::slice_bytes(self, next, self.len()) }; let next_s = unsafe { raw::slice_bytes(self, next, self.len()) };
return (Some(ch), next_s); Some((ch, next_s))
} }
} }

View File

@ -60,10 +60,10 @@ pub fn render_to<W:Writer>(output: &mut W) {
} }
impl<'a> dot::Labeller<'a, Nd, Ed> for Edges { impl<'a> dot::Labeller<'a, Nd, Ed> for Edges {
fn graph_id(&'a self) -> dot::Id<'a> { dot::Id::new("example1") } fn graph_id(&'a self) -> dot::Id<'a> { dot::Id::new("example1").unwrap() }
fn node_id(&'a self, n: &Nd) -> dot::Id<'a> { fn node_id(&'a self, n: &Nd) -> dot::Id<'a> {
dot::Id::new(format!("N{}", *n)) dot::Id::new(format!("N{}", *n)).unwrap()
} }
} }
@ -163,9 +163,9 @@ pub fn render_to<W:Writer>(output: &mut W) {
} }
impl<'a> dot::Labeller<'a, Nd, Ed<'a>> for Graph { impl<'a> dot::Labeller<'a, Nd, Ed<'a>> for Graph {
fn graph_id(&'a self) -> dot::Id<'a> { dot::Id::new("example2") } fn graph_id(&'a self) -> dot::Id<'a> { dot::Id::new("example2").unwrap() }
fn node_id(&'a self, n: &Nd) -> dot::Id<'a> { fn node_id(&'a self, n: &Nd) -> dot::Id<'a> {
dot::Id::new(format!("N{}", n)) dot::Id::new(format!("N{}", n)).unwrap()
} }
fn node_label<'a>(&'a self, n: &Nd) -> dot::LabelText<'a> { fn node_label<'a>(&'a self, n: &Nd) -> dot::LabelText<'a> {
dot::LabelStr(str::Slice(self.nodes[*n].as_slice())) dot::LabelStr(str::Slice(self.nodes[*n].as_slice()))
@ -219,9 +219,9 @@ pub fn render_to<W:Writer>(output: &mut W) {
} }
impl<'a> dot::Labeller<'a, Nd<'a>, Ed<'a>> for Graph { impl<'a> dot::Labeller<'a, Nd<'a>, Ed<'a>> for Graph {
fn graph_id(&'a self) -> dot::Id<'a> { dot::Id::new("example3") } fn graph_id(&'a self) -> dot::Id<'a> { dot::Id::new("example3").unwrap() }
fn node_id(&'a self, n: &Nd<'a>) -> dot::Id<'a> { fn node_id(&'a self, n: &Nd<'a>) -> dot::Id<'a> {
dot::Id::new(format!("N{:u}", n.val0())) dot::Id::new(format!("N{:u}", n.val0())).unwrap()
} }
fn node_label<'a>(&'a self, n: &Nd<'a>) -> dot::LabelText<'a> { fn node_label<'a>(&'a self, n: &Nd<'a>) -> dot::LabelText<'a> {
let &(i, _) = n; let &(i, _) = n;
@ -354,14 +354,22 @@ impl<'a> Id<'a> {
/// defined by the DOT language. This function may change in the /// defined by the DOT language. This function may change in the
/// future to accept a broader subset, or the entirety, of DOT's /// future to accept a broader subset, or the entirety, of DOT's
/// `ID` format.) /// `ID` format.)
pub fn new<Name:str::IntoMaybeOwned<'a>>(name: Name) -> Id<'a> { ///
/// Passing an invalid string (containing spaces, brackets,
/// quotes, ...) will return an empty `Err` value.
pub fn new<Name:str::IntoMaybeOwned<'a>>(name: Name) -> Result<Id<'a>, ()> {
let name = name.into_maybe_owned(); let name = name.into_maybe_owned();
{ {
let mut chars = name.as_slice().chars(); let mut chars = name.as_slice().chars();
assert!(is_letter_or_underscore(chars.next().unwrap())); match chars.next() {
assert!(chars.all(is_constituent)); Some(c) if is_letter_or_underscore(c) => { ; },
_ => return Err(())
} }
return Id{ name: name }; if !chars.all(is_constituent) {
return Err(());
}
}
return Ok(Id{ name: name });
fn is_letter_or_underscore(c: char) -> bool { fn is_letter_or_underscore(c: char) -> bool {
in_range('a', c, 'z') || in_range('A', c, 'Z') || c == '_' in_range('a', c, 'z') || in_range('A', c, 'Z') || c == '_'
@ -627,12 +635,12 @@ mod tests {
} }
fn id_name<'a>(n: &Node) -> Id<'a> { fn id_name<'a>(n: &Node) -> Id<'a> {
Id::new(format!("N{:u}", *n)) Id::new(format!("N{:u}", *n)).unwrap()
} }
impl<'a> Labeller<'a, Node, &'a Edge> for LabelledGraph { impl<'a> Labeller<'a, Node, &'a Edge> for LabelledGraph {
fn graph_id(&'a self) -> Id<'a> { fn graph_id(&'a self) -> Id<'a> {
Id::new(self.name.as_slice()) Id::new(self.name.as_slice()).unwrap()
} }
fn node_id(&'a self, n: &Node) -> Id<'a> { fn node_id(&'a self, n: &Node) -> Id<'a> {
id_name(n) id_name(n)
@ -825,4 +833,22 @@ r#"digraph syntax_tree {
} }
"#); "#);
} }
#[test]
fn simple_id_construction() {
let id1 = Id::new("hello");
match id1 {
Ok(_) => {;},
Err(_) => panic!("'hello' is not a valid value for id anymore")
}
}
#[test]
fn badly_formatted_id() {
let id2 = Id::new("Weird { struct : ure } !!!");
match id2 {
Ok(_) => panic!("graphviz id suddenly allows spaces, brackets and stuff"),
Err(_) => {;}
}
}
} }

View File

@ -137,7 +137,7 @@
//! includes 'foo'. //! includes 'foo'.
//! * `info/f.o` turns on all info logging where the log message includes 'foo', //! * `info/f.o` turns on all info logging where the log message includes 'foo',
//! 'f1o', 'fao', etc. //! 'f1o', 'fao', etc.
//! * `hello=debug/foo*foo` turns on debug logging for 'hello' where the the log //! * `hello=debug/foo*foo` turns on debug logging for 'hello' where the log
//! message includes 'foofoo' or 'fofoo' or 'fooooooofoo', etc. //! message includes 'foofoo' or 'fofoo' or 'fooooooofoo', etc.
//! * `error,hello=warn/[0-9] scopes` turn on global error logging and also warn for //! * `error,hello=warn/[0-9] scopes` turn on global error logging and also warn for
//! hello. In both cases the log message must include a single digit number //! hello. In both cases the log message must include a single digit number

View File

@ -561,7 +561,7 @@ pub struct NoExpand<'t>(pub &'t str);
/// Replacer describes types that can be used to replace matches in a string. /// Replacer describes types that can be used to replace matches in a string.
pub trait Replacer { pub trait Replacer {
/// Returns a possibly owned string that is used to replace the match /// Returns a possibly owned string that is used to replace the match
/// corresponding the the `caps` capture group. /// corresponding to the `caps` capture group.
/// ///
/// The `'a` lifetime refers to the lifetime of a borrowed string when /// The `'a` lifetime refers to the lifetime of a borrowed string when
/// a new owned string isn't needed (e.g., for `NoExpand`). /// a new owned string isn't needed (e.g., for `NoExpand`).
@ -726,7 +726,7 @@ impl<'t> Captures<'t> {
match self.named { match self.named {
None => "", None => "",
Some(ref h) => { Some(ref h) => {
match h.find_equiv(name) { match h.get(name) {
None => "", None => "",
Some(i) => self.at(*i), Some(i) => self.at(*i),
} }

View File

@ -728,7 +728,9 @@ fn link_staticlib(sess: &Session, obj_filename: &Path, out_filename: &Path) {
if sess.target.target.options.morestack { if sess.target.target.options.morestack {
ab.add_native_library("morestack").unwrap(); ab.add_native_library("morestack").unwrap();
} }
if !sess.target.target.options.no_compiler_rt {
ab.add_native_library("compiler-rt").unwrap(); ab.add_native_library("compiler-rt").unwrap();
}
let crates = sess.cstore.get_used_crates(cstore::RequireStatic); let crates = sess.cstore.get_used_crates(cstore::RequireStatic);
let mut all_native_libs = vec![]; let mut all_native_libs = vec![];

View File

@ -143,5 +143,6 @@ register_diagnostics!(
E0164, E0164,
E0165, E0165,
E0166, E0166,
E0167 E0167,
E0168
) )

View File

@ -623,6 +623,7 @@ impl LintPass for UnusedAttributes {
"link", "link",
"link_name", "link_name",
"link_section", "link_section",
"linkage",
"no_builtins", "no_builtins",
"no_mangle", "no_mangle",
"no_split_stack", "no_split_stack",

View File

@ -165,7 +165,7 @@ impl LintStore {
} }
fn register_renamed(&mut self, old_name: &str, new_name: &str) { fn register_renamed(&mut self, old_name: &str, new_name: &str) {
let target = match self.by_name.find_equiv(new_name) { let target = match self.by_name.get(new_name) {
Some(&Id(lint_id)) => lint_id.clone(), Some(&Id(lint_id)) => lint_id.clone(),
_ => panic!("invalid lint renaming of {} to {}", old_name, new_name) _ => panic!("invalid lint renaming of {} to {}", old_name, new_name)
}; };
@ -259,7 +259,7 @@ impl LintStore {
fn find_lint(&self, lint_name: &str, sess: &Session, span: Option<Span>) fn find_lint(&self, lint_name: &str, sess: &Session, span: Option<Span>)
-> Option<LintId> -> Option<LintId>
{ {
match self.by_name.find_equiv(lint_name) { match self.by_name.get(lint_name) {
Some(&Id(lint_id)) => Some(lint_id), Some(&Id(lint_id)) => Some(lint_id),
Some(&Renamed(ref new_name, lint_id)) => { Some(&Renamed(ref new_name, lint_id)) => {
let warning = format!("lint {} has been renamed to {}", let warning = format!("lint {} has been renamed to {}",
@ -282,7 +282,7 @@ impl LintStore {
match self.lint_groups.iter().map(|(&x, pair)| (x, pair.ref0().clone())) match self.lint_groups.iter().map(|(&x, pair)| (x, pair.ref0().clone()))
.collect::<FnvHashMap<&'static str, .collect::<FnvHashMap<&'static str,
Vec<LintId>>>() Vec<LintId>>>()
.find_equiv(lint_name.as_slice()) { .get(lint_name.as_slice()) {
Some(v) => { Some(v) => {
v.iter() v.iter()
.map(|lint_id: &LintId| .map(|lint_id: &LintId|
@ -489,7 +489,7 @@ impl<'a, 'tcx> Context<'a, 'tcx> {
match self.lints.find_lint(lint_name.get(), &self.tcx.sess, Some(span)) { match self.lints.find_lint(lint_name.get(), &self.tcx.sess, Some(span)) {
Some(lint_id) => vec![(lint_id, level, span)], Some(lint_id) => vec![(lint_id, level, span)],
None => { None => {
match self.lints.lint_groups.find_equiv(lint_name.get()) { match self.lints.lint_groups.get(lint_name.get()) {
Some(&(ref v, _)) => v.iter() Some(&(ref v, _)) => v.iter()
.map(|lint_id: &LintId| .map(|lint_id: &LintId|
(*lint_id, level, span)) (*lint_id, level, span))

View File

@ -242,6 +242,8 @@ fn visit_item(e: &Env, i: &ast::Item) {
cstore::NativeFramework cstore::NativeFramework
} else if k.equiv(&("framework")) { } else if k.equiv(&("framework")) {
cstore::NativeFramework cstore::NativeFramework
} else if k.equiv(&("dylib")) {
cstore::NativeUnknown
} else { } else {
e.sess.span_err(m.span, e.sess.span_err(m.span,
format!("unknown kind: `{}`", format!("unknown kind: `{}`",
@ -321,7 +323,7 @@ fn existing_match(e: &Env, name: &str,
// `source` stores paths which are normalized which may be different // `source` stores paths which are normalized which may be different
// from the strings on the command line. // from the strings on the command line.
let source = e.sess.cstore.get_used_crate_source(cnum).unwrap(); let source = e.sess.cstore.get_used_crate_source(cnum).unwrap();
match e.sess.opts.externs.find_equiv(name) { match e.sess.opts.externs.get(name) {
Some(locs) => { Some(locs) => {
let found = locs.iter().any(|l| { let found = locs.iter().any(|l| {
let l = fs::realpath(&Path::new(l.as_slice())).ok(); let l = fs::realpath(&Path::new(l.as_slice())).ok();

View File

@ -298,7 +298,7 @@ fn item_path(item_doc: rbml::Doc) -> Vec<ast_map::PathElem> {
fn item_name(intr: &IdentInterner, item: rbml::Doc) -> ast::Name { fn item_name(intr: &IdentInterner, item: rbml::Doc) -> ast::Name {
let name = reader::get_doc(item, tag_paths_data_name); let name = reader::get_doc(item, tag_paths_data_name);
let string = name.as_str_slice(); let string = name.as_str_slice();
match intr.find_equiv(string) { match intr.find(string) {
None => token::intern(string), None => token::intern(string),
Some(val) => val, Some(val) => val,
} }
@ -1449,4 +1449,3 @@ pub fn is_associated_type(cdata: Cmd, id: ast::NodeId) -> bool {
Some(item) => item_sort(item) == 't', Some(item) => item_sort(item) == 't',
} }
} }

View File

@ -54,7 +54,7 @@ impl<'a> FileSearch<'a> {
debug!("filesearch: searching lib path"); debug!("filesearch: searching lib path");
let tlib_path = make_target_lib_path(self.sysroot, let tlib_path = make_target_lib_path(self.sysroot,
self.triple); self.triple);
if !visited_dirs.contains_equiv(tlib_path.as_vec()) { if !visited_dirs.contains(tlib_path.as_vec()) {
match f(&tlib_path) { match f(&tlib_path) {
FileMatches => found = true, FileMatches => found = true,
FileDoesntMatch => () FileDoesntMatch => ()
@ -69,9 +69,9 @@ impl<'a> FileSearch<'a> {
let tlib_path = make_rustpkg_lib_path( let tlib_path = make_rustpkg_lib_path(
self.sysroot, path, self.triple); self.sysroot, path, self.triple);
debug!("is {} in visited_dirs? {}", tlib_path.display(), debug!("is {} in visited_dirs? {}", tlib_path.display(),
visited_dirs.contains_equiv(&tlib_path.as_vec().to_vec())); visited_dirs.contains(&tlib_path.as_vec().to_vec()));
if !visited_dirs.contains_equiv(tlib_path.as_vec()) { if !visited_dirs.contains(tlib_path.as_vec()) {
visited_dirs.insert(tlib_path.as_vec().to_vec()); visited_dirs.insert(tlib_path.as_vec().to_vec());
// Don't keep searching the RUST_PATH if one match turns up -- // Don't keep searching the RUST_PATH if one match turns up --
// if we did, we'd get a "multiple matching crates" error // if we did, we'd get a "multiple matching crates" error

View File

@ -596,7 +596,7 @@ impl<'a> Context<'a> {
} }
fn find_commandline_library(&mut self) -> Option<Library> { fn find_commandline_library(&mut self) -> Option<Library> {
let locs = match self.sess.opts.externs.find_equiv(self.crate_name) { let locs = match self.sess.opts.externs.get(self.crate_name) {
Some(s) => s, Some(s) => s,
None => return None, None => return None,
}; };

View File

@ -50,10 +50,10 @@ fn replace_newline_with_backslash_l(s: String) -> String {
} }
impl<'a, 'ast> dot::Labeller<'a, Node<'a>, Edge<'a>> for LabelledCFG<'a, 'ast> { impl<'a, 'ast> dot::Labeller<'a, Node<'a>, Edge<'a>> for LabelledCFG<'a, 'ast> {
fn graph_id(&'a self) -> dot::Id<'a> { dot::Id::new(self.name.as_slice()) } fn graph_id(&'a self) -> dot::Id<'a> { dot::Id::new(self.name.as_slice()).unwrap() }
fn node_id(&'a self, &(i,_): &Node<'a>) -> dot::Id<'a> { fn node_id(&'a self, &(i,_): &Node<'a>) -> dot::Id<'a> {
dot::Id::new(format!("N{:u}", i.node_id())) dot::Id::new(format!("N{:u}", i.node_id())).unwrap()
} }
fn node_label(&'a self, &(i, n): &Node<'a>) -> dot::LabelText<'a> { fn node_label(&'a self, &(i, n): &Node<'a>) -> dot::LabelText<'a> {

View File

@ -132,7 +132,7 @@ impl<'a, 'v> Visitor<'v> for LanguageItemCollector<'a> {
fn visit_item(&mut self, item: &ast::Item) { fn visit_item(&mut self, item: &ast::Item) {
match extract(item.attrs.as_slice()) { match extract(item.attrs.as_slice()) {
Some(value) => { Some(value) => {
let item_index = self.item_refs.find_equiv(&value).map(|x| *x); let item_index = self.item_refs.get(value.get()).map(|x| *x);
match item_index { match item_index {
Some(item_index) => { Some(item_index) => {

View File

@ -79,14 +79,17 @@ impl<'v> Visitor<'v> for Annotator {
} }
} }
fn visit_fn(&mut self, fk: FnKind<'v>, fd: &'v FnDecl, fn visit_fn(&mut self, fk: FnKind<'v>, _: &'v FnDecl,
b: &'v Block, s: Span, _: NodeId) { _: &'v Block, _: Span, _: NodeId) {
match fk { match fk {
FkMethod(_, _, meth) => { FkMethod(_, _, meth) => {
self.annotate(meth.id, &meth.attrs, |v| visit::walk_fn(v, fk, fd, b, s)); // Methods are not already annotated, so we annotate it
self.annotate(meth.id, &meth.attrs, |_| {});
} }
_ => visit::walk_fn(self, fk, fd, b, s) _ => {}
} }
// Items defined in a function body have no reason to have
// a stability attribute, so we don't recurse.
} }
fn visit_trait_item(&mut self, t: &TraitItem) { fn visit_trait_item(&mut self, t: &TraitItem) {

View File

@ -353,7 +353,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
// matches this obligation, then we can assume that the // matches this obligation, then we can assume that the
// obligation is satisfied for now (still all other conditions // obligation is satisfied for now (still all other conditions
// must be met of course). One obvious case this comes up is // must be met of course). One obvious case this comes up is
// marker traits like `Send`. Think of a a linked list: // marker traits like `Send`. Think of a linked list:
// //
// struct List<T> { data: T, next: Option<Box<List<T>>> { // struct List<T> { data: T, next: Option<Box<List<T>>> {
// //

View File

@ -36,7 +36,7 @@ use driver::config::{NoDebugInfo, FullDebugInfo};
use driver::driver::{CrateAnalysis, CrateTranslation, ModuleTranslation}; use driver::driver::{CrateAnalysis, CrateTranslation, ModuleTranslation};
use driver::session::Session; use driver::session::Session;
use lint; use lint;
use llvm::{BasicBlockRef, ValueRef, Vector, get_param}; use llvm::{BasicBlockRef, Linkage, ValueRef, Vector, get_param};
use llvm; use llvm;
use metadata::{csearch, encoder, loader}; use metadata::{csearch, encoder, loader};
use middle::astencode; use middle::astencode;
@ -216,7 +216,7 @@ pub fn get_extern_fn(ccx: &CrateContext,
ty: Type, ty: Type,
output: ty::t) output: ty::t)
-> ValueRef { -> ValueRef {
match externs.find_equiv(name) { match externs.get(name) {
Some(n) => return *n, Some(n) => return *n,
None => {} None => {}
} }
@ -226,7 +226,7 @@ pub fn get_extern_fn(ccx: &CrateContext,
} }
fn get_extern_rust_fn(ccx: &CrateContext, fn_ty: ty::t, name: &str, did: ast::DefId) -> ValueRef { fn get_extern_rust_fn(ccx: &CrateContext, fn_ty: ty::t, name: &str, did: ast::DefId) -> ValueRef {
match ccx.externs().borrow().find_equiv(name) { match ccx.externs().borrow().get(name) {
Some(n) => return *n, Some(n) => return *n,
None => () None => ()
} }
@ -2137,6 +2137,32 @@ impl<'a, 'tcx, 'v> Visitor<'v> for TransItemVisitor<'a, 'tcx> {
} }
} }
pub fn llvm_linkage_by_name(name: &str) -> Option<Linkage> {
// Use the names from src/llvm/docs/LangRef.rst here. Most types are only
// applicable to variable declarations and may not really make sense for
// Rust code in the first place but whitelist them anyway and trust that
// the user knows what s/he's doing. Who knows, unanticipated use cases
// may pop up in the future.
//
// ghost, dllimport, dllexport and linkonce_odr_autohide are not supported
// and don't have to be, LLVM treats them as no-ops.
match name {
"appending" => Some(llvm::AppendingLinkage),
"available_externally" => Some(llvm::AvailableExternallyLinkage),
"common" => Some(llvm::CommonLinkage),
"extern_weak" => Some(llvm::ExternalWeakLinkage),
"external" => Some(llvm::ExternalLinkage),
"internal" => Some(llvm::InternalLinkage),
"linkonce" => Some(llvm::LinkOnceAnyLinkage),
"linkonce_odr" => Some(llvm::LinkOnceODRLinkage),
"private" => Some(llvm::PrivateLinkage),
"weak" => Some(llvm::WeakAnyLinkage),
"weak_odr" => Some(llvm::WeakODRLinkage),
_ => None,
}
}
/// Enum describing the origin of an LLVM `Value`, for linkage purposes. /// Enum describing the origin of an LLVM `Value`, for linkage purposes.
pub enum ValueOrigin { pub enum ValueOrigin {
/// The LLVM `Value` is in this context because the corresponding item was /// The LLVM `Value` is in this context because the corresponding item was
@ -2174,6 +2200,23 @@ pub fn update_linkage(ccx: &CrateContext,
OriginalTranslation => {}, OriginalTranslation => {},
} }
match id {
Some(id) => {
let item = ccx.tcx().map.get(id);
if let ast_map::NodeItem(i) = item {
if let Some(name) = attr::first_attr_value_str_by_name(i.attrs[], "linkage") {
if let Some(linkage) = llvm_linkage_by_name(name.get()) {
llvm::SetLinkage(llval, linkage);
} else {
ccx.sess().span_fatal(i.span, "invalid linkage specified");
}
return;
}
}
}
_ => {}
}
match id { match id {
Some(id) if ccx.reachable().contains(&id) => { Some(id) if ccx.reachable().contains(&id) => {
llvm::SetLinkage(llval, llvm::ExternalLinkage); llvm::SetLinkage(llval, llvm::ExternalLinkage);
@ -2983,7 +3026,7 @@ fn internalize_symbols(cx: &SharedCrateContext, reachable: &HashSet<String>) {
let name = CString::new(llvm::LLVMGetValueName(val), false); let name = CString::new(llvm::LLVMGetValueName(val), false);
if !declared.contains(&name) && if !declared.contains(&name) &&
!reachable.contains_equiv(name.as_str().unwrap()) { !reachable.contains(name.as_str().unwrap()) {
llvm::SetLinkage(val, llvm::InternalLinkage); llvm::SetLinkage(val, llvm::InternalLinkage);
} }
} }

View File

@ -1677,7 +1677,7 @@ fn declare_local(bcx: Block,
} }
fn file_metadata(cx: &CrateContext, full_path: &str) -> DIFile { fn file_metadata(cx: &CrateContext, full_path: &str) -> DIFile {
match debug_context(cx).created_files.borrow().find_equiv(full_path) { match debug_context(cx).created_files.borrow().get(full_path) {
Some(file_metadata) => return *file_metadata, Some(file_metadata) => return *file_metadata,
None => () None => ()
} }

View File

@ -10,10 +10,10 @@
use back::{link}; use back::{link};
use llvm::{ValueRef, CallConv, Linkage, get_param}; use llvm::{ValueRef, CallConv, get_param};
use llvm; use llvm;
use middle::weak_lang_items; use middle::weak_lang_items;
use middle::trans::base::push_ctxt; use middle::trans::base::{llvm_linkage_by_name, push_ctxt};
use middle::trans::base; use middle::trans::base;
use middle::trans::build::*; use middle::trans::build::*;
use middle::trans::cabi; use middle::trans::cabi;
@ -101,31 +101,6 @@ pub fn llvm_calling_convention(ccx: &CrateContext,
} }
} }
pub fn llvm_linkage_by_name(name: &str) -> Option<Linkage> {
// Use the names from src/llvm/docs/LangRef.rst here. Most types are only
// applicable to variable declarations and may not really make sense for
// Rust code in the first place but whitelist them anyway and trust that
// the user knows what s/he's doing. Who knows, unanticipated use cases
// may pop up in the future.
//
// ghost, dllimport, dllexport and linkonce_odr_autohide are not supported
// and don't have to be, LLVM treats them as no-ops.
match name {
"appending" => Some(llvm::AppendingLinkage),
"available_externally" => Some(llvm::AvailableExternallyLinkage),
"common" => Some(llvm::CommonLinkage),
"extern_weak" => Some(llvm::ExternalWeakLinkage),
"external" => Some(llvm::ExternalLinkage),
"internal" => Some(llvm::InternalLinkage),
"linkonce" => Some(llvm::LinkOnceAnyLinkage),
"linkonce_odr" => Some(llvm::LinkOnceODRLinkage),
"private" => Some(llvm::PrivateLinkage),
"weak" => Some(llvm::WeakAnyLinkage),
"weak_odr" => Some(llvm::WeakODRLinkage),
_ => None,
}
}
pub fn register_static(ccx: &CrateContext, pub fn register_static(ccx: &CrateContext,
foreign_item: &ast::ForeignItem) -> ValueRef { foreign_item: &ast::ForeignItem) -> ValueRef {
let ty = ty::node_id_to_type(ccx.tcx(), foreign_item.id); let ty = ty::node_id_to_type(ccx.tcx(), foreign_item.id);

View File

@ -336,7 +336,7 @@ impl TypeNames {
} }
pub fn find_type(&self, s: &str) -> Option<Type> { pub fn find_type(&self, s: &str) -> Option<Type> {
self.named_types.borrow().find_equiv(s).map(|x| Type::from_ref(*x)) self.named_types.borrow().get(s).map(|x| Type::from_ref(*x))
} }
pub fn type_to_string(&self, ty: Type) -> String { pub fn type_to_string(&self, ty: Type) -> String {

View File

@ -297,11 +297,25 @@ pub fn check_pat_struct(pcx: &pat_ctxt, pat: &ast::Pat,
let tcx = pcx.fcx.ccx.tcx; let tcx = pcx.fcx.ccx.tcx;
let def = tcx.def_map.borrow()[pat.id].clone(); let def = tcx.def_map.borrow()[pat.id].clone();
let (enum_def_id, variant_def_id) = match def {
def::DefTrait(_) => {
let name = pprust::path_to_string(path);
span_err!(tcx.sess, pat.span, E0168,
"use of trait `{}` in a struct pattern", name);
fcx.write_error(pat.id);
for field in fields.iter() {
check_pat(pcx, &*field.node.pat, ty::mk_err());
}
return;
},
_ => {
let def_type = ty::lookup_item_type(tcx, def.def_id()); let def_type = ty::lookup_item_type(tcx, def.def_id());
let (enum_def_id, variant_def_id) = match ty::get(def_type.ty).sty { match ty::get(def_type.ty).sty {
ty::ty_struct(struct_def_id, _) => ty::ty_struct(struct_def_id, _) =>
(struct_def_id, struct_def_id), (struct_def_id, struct_def_id),
ty::ty_enum(enum_def_id, _) if def == def::DefVariant(enum_def_id, def.def_id(), true) => ty::ty_enum(enum_def_id, _)
if def == def::DefVariant(enum_def_id, def.def_id(), true) =>
(enum_def_id, def.def_id()), (enum_def_id, def.def_id()),
_ => { _ => {
let name = pprust::path_to_string(path); let name = pprust::path_to_string(path);
@ -314,6 +328,8 @@ pub fn check_pat_struct(pcx: &pat_ctxt, pat: &ast::Pat,
} }
return; return;
} }
}
}
}; };
instantiate_path(pcx.fcx, path, ty::lookup_item_type(tcx, enum_def_id), instantiate_path(pcx.fcx, path, ty::lookup_item_type(tcx, enum_def_id),

View File

@ -2122,7 +2122,7 @@ impl<'a> fmt::Show for Sidebar<'a> {
fn block(w: &mut fmt::Formatter, short: &str, longty: &str, fn block(w: &mut fmt::Formatter, short: &str, longty: &str,
cur: &clean::Item, cx: &Context) -> fmt::Result { cur: &clean::Item, cx: &Context) -> fmt::Result {
let items = match cx.sidebar.find_equiv(short) { let items = match cx.sidebar.get(short) {
Some(items) => items.as_slice(), Some(items) => items.as_slice(),
None => return Ok(()) None => return Ok(())
}; };

View File

@ -901,7 +901,7 @@ impl Json {
/// Otherwise, returns None. /// Otherwise, returns None.
pub fn find<'a>(&'a self, key: &str) -> Option<&'a Json>{ pub fn find<'a>(&'a self, key: &str) -> Option<&'a Json>{
match self { match self {
&Object(ref map) => map.find_with(|s| key.cmp(s.as_slice())), &Object(ref map) => map.get(key),
_ => None _ => None
} }
} }
@ -926,7 +926,7 @@ impl Json {
pub fn search<'a>(&'a self, key: &str) -> Option<&'a Json> { pub fn search<'a>(&'a self, key: &str) -> Option<&'a Json> {
match self { match self {
&Object(ref map) => { &Object(ref map) => {
match map.find_with(|s| key.cmp(s.as_slice())) { match map.get(key) {
Some(json_value) => Some(json_value), Some(json_value) => Some(json_value),
None => { None => {
for (_, v) in map.iter() { for (_, v) in map.iter() {

View File

@ -14,6 +14,7 @@ pub use self::Entry::*;
use self::SearchResult::*; use self::SearchResult::*;
use self::VacantEntryState::*; use self::VacantEntryState::*;
use borrow::BorrowFrom;
use clone::Clone; use clone::Clone;
use cmp::{max, Eq, Equiv, PartialEq}; use cmp::{max, Eq, Equiv, PartialEq};
use default::Default; use default::Default;
@ -142,7 +143,7 @@ impl DefaultResizePolicy {
// about the size of rust executables. // about the size of rust executables.
// //
// Annotate exceedingly likely branches in `table::make_hash` // Annotate exceedingly likely branches in `table::make_hash`
// and `search_hashed_generic` to reduce instruction cache pressure // and `search_hashed` to reduce instruction cache pressure
// and mispredictions once it becomes possible (blocked on issue #11092). // and mispredictions once it becomes possible (blocked on issue #11092).
// //
// Shrinking the table could simply reallocate in place after moving buckets // Shrinking the table could simply reallocate in place after moving buckets
@ -286,7 +287,7 @@ pub struct HashMap<K, V, H = RandomSipHasher> {
} }
/// Search for a pre-hashed key. /// Search for a pre-hashed key.
fn search_hashed_generic<K, V, M: Deref<RawTable<K, V>>>(table: M, fn search_hashed<K, V, M: Deref<RawTable<K, V>>>(table: M,
hash: &SafeHash, hash: &SafeHash,
is_match: |&K| -> bool) is_match: |&K| -> bool)
-> SearchResult<K, V, M> { -> SearchResult<K, V, M> {
@ -325,11 +326,6 @@ fn search_hashed_generic<K, V, M: Deref<RawTable<K, V>>>(table: M,
TableRef(probe.into_table()) TableRef(probe.into_table())
} }
fn search_hashed<K: Eq, V, M: Deref<RawTable<K, V>>>(table: M, hash: &SafeHash, k: &K)
-> SearchResult<K, V, M> {
search_hashed_generic(table, hash, |k_| *k == *k_)
}
fn pop_internal<K, V>(starting_bucket: FullBucketMut<K, V>) -> (K, V) { fn pop_internal<K, V>(starting_bucket: FullBucketMut<K, V>) -> (K, V) {
let (empty, retkey, retval) = starting_bucket.take(); let (empty, retkey, retval) = starting_bucket.take();
let mut gap = match empty.gap_peek() { let mut gap = match empty.gap_peek() {
@ -432,26 +428,32 @@ impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> HashMap<K, V, H> {
fn search_equiv<'a, Sized? Q: Hash<S> + Equiv<K>>(&'a self, q: &Q) fn search_equiv<'a, Sized? Q: Hash<S> + Equiv<K>>(&'a self, q: &Q)
-> Option<FullBucketImm<'a, K, V>> { -> Option<FullBucketImm<'a, K, V>> {
let hash = self.make_hash(q); let hash = self.make_hash(q);
search_hashed_generic(&self.table, &hash, |k| q.equiv(k)).into_option() search_hashed(&self.table, &hash, |k| q.equiv(k)).into_option()
} }
fn search_equiv_mut<'a, Sized? Q: Hash<S> + Equiv<K>>(&'a mut self, q: &Q) fn search_equiv_mut<'a, Sized? Q: Hash<S> + Equiv<K>>(&'a mut self, q: &Q)
-> Option<FullBucketMut<'a, K, V>> { -> Option<FullBucketMut<'a, K, V>> {
let hash = self.make_hash(q); let hash = self.make_hash(q);
search_hashed_generic(&mut self.table, &hash, |k| q.equiv(k)).into_option() search_hashed(&mut self.table, &hash, |k| q.equiv(k)).into_option()
} }
/// Search for a key, yielding the index if it's found in the hashtable. /// Search for a key, yielding the index if it's found in the hashtable.
/// If you already have the hash for the key lying around, use /// If you already have the hash for the key lying around, use
/// search_hashed. /// search_hashed.
fn search<'a>(&'a self, k: &K) -> Option<FullBucketImm<'a, K, V>> { fn search<'a, Sized? Q>(&'a self, q: &Q) -> Option<FullBucketImm<'a, K, V>>
let hash = self.make_hash(k); where Q: BorrowFrom<K> + Eq + Hash<S>
search_hashed(&self.table, &hash, k).into_option() {
let hash = self.make_hash(q);
search_hashed(&self.table, &hash, |k| q.eq(BorrowFrom::borrow_from(k)))
.into_option()
} }
fn search_mut<'a>(&'a mut self, k: &K) -> Option<FullBucketMut<'a, K, V>> { fn search_mut<'a, Sized? Q>(&'a mut self, q: &Q) -> Option<FullBucketMut<'a, K, V>>
let hash = self.make_hash(k); where Q: BorrowFrom<K> + Eq + Hash<S>
search_hashed(&mut self.table, &hash, k).into_option() {
let hash = self.make_hash(q);
search_hashed(&mut self.table, &hash, |k| q.eq(BorrowFrom::borrow_from(k)))
.into_option()
} }
// The caller should ensure that invariants by Robin Hood Hashing hold. // The caller should ensure that invariants by Robin Hood Hashing hold.
@ -748,18 +750,14 @@ impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> HashMap<K, V, H> {
} }
} }
/// Return true if the map contains a value for the specified key, /// Deprecated: use `contains_key` and `BorrowFrom` instead.
/// using equivalence. #[deprecated = "use contains_key and BorrowFrom instead"]
///
/// See [pop_equiv](#method.pop_equiv) for an extended example.
pub fn contains_key_equiv<Sized? Q: Hash<S> + Equiv<K>>(&self, key: &Q) -> bool { pub fn contains_key_equiv<Sized? Q: Hash<S> + Equiv<K>>(&self, key: &Q) -> bool {
self.search_equiv(key).is_some() self.search_equiv(key).is_some()
} }
/// Return the value corresponding to the key in the map, using /// Deprecated: use `get` and `BorrowFrom` instead.
/// equivalence. #[deprecated = "use get and BorrowFrom instead"]
///
/// See [pop_equiv](#method.pop_equiv) for an extended example.
pub fn find_equiv<'a, Sized? Q: Hash<S> + Equiv<K>>(&'a self, k: &Q) -> Option<&'a V> { pub fn find_equiv<'a, Sized? Q: Hash<S> + Equiv<K>>(&'a self, k: &Q) -> Option<&'a V> {
match self.search_equiv(k) { match self.search_equiv(k) {
None => None, None => None,
@ -770,52 +768,8 @@ impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> HashMap<K, V, H> {
} }
} }
/// Remove an equivalent key from the map, returning the value at the /// Deprecated: use `remove` and `BorrowFrom` instead.
/// key if the key was previously in the map. #[deprecated = "use remove and BorrowFrom instead"]
///
/// # Example
///
/// This is a slightly silly example where we define the number's
/// parity as the equivalence class. It is important that the
/// values hash the same, which is why we implement `Hash`.
///
/// ```
/// use std::collections::HashMap;
/// use std::hash::Hash;
/// use std::hash::sip::SipState;
///
/// #[deriving(Eq, PartialEq)]
/// struct EvenOrOdd {
/// num: uint
/// };
///
/// impl Hash for EvenOrOdd {
/// fn hash(&self, state: &mut SipState) {
/// let parity = self.num % 2;
/// parity.hash(state);
/// }
/// }
///
/// impl Equiv<EvenOrOdd> for EvenOrOdd {
/// fn equiv(&self, other: &EvenOrOdd) -> bool {
/// self.num % 2 == other.num % 2
/// }
/// }
///
/// let mut map = HashMap::new();
/// map.insert(EvenOrOdd { num: 3 }, "foo");
///
/// assert!(map.contains_key_equiv(&EvenOrOdd { num: 1 }));
/// assert!(!map.contains_key_equiv(&EvenOrOdd { num: 4 }));
///
/// assert_eq!(map.find_equiv(&EvenOrOdd { num: 5 }), Some(&"foo"));
/// assert_eq!(map.find_equiv(&EvenOrOdd { num: 2 }), None);
///
/// assert_eq!(map.pop_equiv(&EvenOrOdd { num: 1 }), Some("foo"));
/// assert_eq!(map.pop_equiv(&EvenOrOdd { num: 2 }), None);
///
/// ```
#[experimental]
pub fn pop_equiv<Sized? Q:Hash<S> + Equiv<K>>(&mut self, k: &Q) -> Option<V> { pub fn pop_equiv<Sized? Q:Hash<S> + Equiv<K>>(&mut self, k: &Q) -> Option<V> {
if self.table.size() == 0 { if self.table.size() == 0 {
return None return None
@ -1036,6 +990,10 @@ impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> HashMap<K, V, H> {
/// Returns a reference to the value corresponding to the key. /// Returns a reference to the value corresponding to the key.
/// ///
/// The key may be any borrowed form of the map's key type, but
/// `Hash` and `Eq` on the borrowed form *must* match those for
/// the key type.
///
/// # Example /// # Example
/// ///
/// ``` /// ```
@ -1047,7 +1005,9 @@ impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> HashMap<K, V, H> {
/// assert_eq!(map.get(&2), None); /// assert_eq!(map.get(&2), None);
/// ``` /// ```
#[unstable = "matches collection reform specification, waiting for dust to settle"] #[unstable = "matches collection reform specification, waiting for dust to settle"]
pub fn get(&self, k: &K) -> Option<&V> { pub fn get<Sized? Q>(&self, k: &Q) -> Option<&V>
where Q: Hash<S> + Eq + BorrowFrom<K>
{
self.search(k).map(|bucket| { self.search(k).map(|bucket| {
let (_, v) = bucket.into_refs(); let (_, v) = bucket.into_refs();
v v
@ -1056,6 +1016,10 @@ impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> HashMap<K, V, H> {
/// Returns true if the map contains a value for the specified key. /// Returns true if the map contains a value for the specified key.
/// ///
/// The key may be any borrowed form of the map's key type, but
/// `Hash` and `Eq` on the borrowed form *must* match those for
/// the key type.
///
/// # Example /// # Example
/// ///
/// ``` /// ```
@ -1067,7 +1031,9 @@ impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> HashMap<K, V, H> {
/// assert_eq!(map.contains_key(&2), false); /// assert_eq!(map.contains_key(&2), false);
/// ``` /// ```
#[unstable = "matches collection reform specification, waiting for dust to settle"] #[unstable = "matches collection reform specification, waiting for dust to settle"]
pub fn contains_key(&self, k: &K) -> bool { pub fn contains_key<Sized? Q>(&self, k: &Q) -> bool
where Q: Hash<S> + Eq + BorrowFrom<K>
{
self.search(k).is_some() self.search(k).is_some()
} }
@ -1079,6 +1045,10 @@ impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> HashMap<K, V, H> {
/// Returns a mutable reference to the value corresponding to the key. /// Returns a mutable reference to the value corresponding to the key.
/// ///
/// The key may be any borrowed form of the map's key type, but
/// `Hash` and `Eq` on the borrowed form *must* match those for
/// the key type.
///
/// # Example /// # Example
/// ///
/// ``` /// ```
@ -1093,7 +1063,9 @@ impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> HashMap<K, V, H> {
/// assert_eq!(map[1], "b"); /// assert_eq!(map[1], "b");
/// ``` /// ```
#[unstable = "matches collection reform specification, waiting for dust to settle"] #[unstable = "matches collection reform specification, waiting for dust to settle"]
pub fn get_mut(&mut self, k: &K) -> Option<&mut V> { pub fn get_mut<Sized? Q>(&mut self, k: &Q) -> Option<&mut V>
where Q: Hash<S> + Eq + BorrowFrom<K>
{
match self.search_mut(k) { match self.search_mut(k) {
Some(bucket) => { Some(bucket) => {
let (_, v) = bucket.into_mut_refs(); let (_, v) = bucket.into_mut_refs();
@ -1147,6 +1119,10 @@ impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> HashMap<K, V, H> {
/// Removes a key from the map, returning the value at the key if the key /// Removes a key from the map, returning the value at the key if the key
/// was previously in the map. /// was previously in the map.
/// ///
/// The key may be any borrowed form of the map's key type, but
/// `Hash` and `Eq` on the borrowed form *must* match those for
/// the key type.
///
/// # Example /// # Example
/// ///
/// ``` /// ```
@ -1158,7 +1134,9 @@ impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> HashMap<K, V, H> {
/// assert_eq!(map.remove(&1), None); /// assert_eq!(map.remove(&1), None);
/// ``` /// ```
#[unstable = "matches collection reform specification, waiting for dust to settle"] #[unstable = "matches collection reform specification, waiting for dust to settle"]
pub fn remove(&mut self, k: &K) -> Option<V> { pub fn remove<Sized? Q>(&mut self, k: &Q) -> Option<V>
where Q: Hash<S> + Eq + BorrowFrom<K>
{
if self.table.size() == 0 { if self.table.size() == 0 {
return None return None
} }
@ -1271,16 +1249,20 @@ impl<K: Eq + Hash<S>, V, S, H: Hasher<S> + Default> Default for HashMap<K, V, H>
} }
} }
impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> Index<K, V> for HashMap<K, V, H> { impl<K: Hash<S> + Eq, Sized? Q, V, S, H: Hasher<S>> Index<Q, V> for HashMap<K, V, H>
where Q: BorrowFrom<K> + Hash<S> + Eq
{
#[inline] #[inline]
fn index<'a>(&'a self, index: &K) -> &'a V { fn index<'a>(&'a self, index: &Q) -> &'a V {
self.get(index).expect("no entry found for key") self.get(index).expect("no entry found for key")
} }
} }
impl<K: Eq + Hash<S>, V, S, H: Hasher<S>> IndexMut<K, V> for HashMap<K, V, H> { impl<K: Hash<S> + Eq, Sized? Q, V, S, H: Hasher<S>> IndexMut<Q, V> for HashMap<K, V, H>
where Q: BorrowFrom<K> + Hash<S> + Eq
{
#[inline] #[inline]
fn index_mut<'a>(&'a mut self, index: &K) -> &'a mut V { fn index_mut<'a>(&'a mut self, index: &Q) -> &'a mut V {
match self.get_mut(index) { match self.get_mut(index) {
Some(v) => v, Some(v) => v,
None => panic!("no entry found for key") None => panic!("no entry found for key")
@ -1962,11 +1944,11 @@ mod test_map {
m.insert("baz".to_string(), baz); m.insert("baz".to_string(), baz);
assert_eq!(m.find_equiv("foo"), Some(&foo)); assert_eq!(m.get("foo"), Some(&foo));
assert_eq!(m.find_equiv("bar"), Some(&bar)); assert_eq!(m.get("bar"), Some(&bar));
assert_eq!(m.find_equiv("baz"), Some(&baz)); assert_eq!(m.get("baz"), Some(&baz));
assert_eq!(m.find_equiv("qux"), None); assert_eq!(m.get("qux"), None);
} }
#[test] #[test]

View File

@ -10,6 +10,7 @@
// //
// ignore-lexer-test FIXME #15883 // ignore-lexer-test FIXME #15883
use borrow::BorrowFrom;
use cmp::{Eq, Equiv, PartialEq}; use cmp::{Eq, Equiv, PartialEq};
use core::kinds::Sized; use core::kinds::Sized;
use default::Default; use default::Default;
@ -184,47 +185,9 @@ impl<T: Eq + Hash<S>, S, H: Hasher<S>> HashSet<T, H> {
self.map.reserve(n) self.map.reserve(n)
} }
/// Returns true if the hash set contains a value equivalent to the /// Deprecated: use `contains` and `BorrowFrom`.
/// given query value. #[deprecated = "use contains and BorrowFrom"]
/// #[allow(deprecated)]
/// # Example
///
/// This is a slightly silly example where we define the number's
/// parity as the equivalance class. It is important that the
/// values hash the same, which is why we implement `Hash`.
///
/// ```
/// use std::collections::HashSet;
/// use std::hash::Hash;
/// use std::hash::sip::SipState;
///
/// #[deriving(Eq, PartialEq)]
/// struct EvenOrOdd {
/// num: uint
/// };
///
/// impl Hash for EvenOrOdd {
/// fn hash(&self, state: &mut SipState) {
/// let parity = self.num % 2;
/// parity.hash(state);
/// }
/// }
///
/// impl Equiv<EvenOrOdd> for EvenOrOdd {
/// fn equiv(&self, other: &EvenOrOdd) -> bool {
/// self.num % 2 == other.num % 2
/// }
/// }
///
/// let mut set = HashSet::new();
/// set.insert(EvenOrOdd { num: 3u });
///
/// assert!(set.contains_equiv(&EvenOrOdd { num: 3u }));
/// assert!(set.contains_equiv(&EvenOrOdd { num: 5u }));
/// assert!(!set.contains_equiv(&EvenOrOdd { num: 4u }));
/// assert!(!set.contains_equiv(&EvenOrOdd { num: 2u }));
///
/// ```
pub fn contains_equiv<Sized? Q: Hash<S> + Equiv<T>>(&self, value: &Q) -> bool { pub fn contains_equiv<Sized? Q: Hash<S> + Equiv<T>>(&self, value: &Q) -> bool {
self.map.contains_key_equiv(value) self.map.contains_key_equiv(value)
} }
@ -427,6 +390,10 @@ impl<T: Eq + Hash<S>, S, H: Hasher<S>> HashSet<T, H> {
/// Returns `true` if the set contains a value. /// Returns `true` if the set contains a value.
/// ///
/// The value may be any borrowed form of the set's value type, but
/// `Hash` and `Eq` on the borrowed form *must* match those for
/// the value type.
///
/// # Example /// # Example
/// ///
/// ``` /// ```
@ -437,7 +404,11 @@ impl<T: Eq + Hash<S>, S, H: Hasher<S>> HashSet<T, H> {
/// assert_eq!(set.contains(&4), false); /// assert_eq!(set.contains(&4), false);
/// ``` /// ```
#[unstable = "matches collection reform specification, waiting for dust to settle"] #[unstable = "matches collection reform specification, waiting for dust to settle"]
pub fn contains(&self, value: &T) -> bool { self.map.contains_key(value) } pub fn contains<Sized? Q>(&self, value: &Q) -> bool
where Q: BorrowFrom<T> + Hash<S> + Eq
{
self.map.contains_key(value)
}
/// Returns `true` if the set has no elements in common with `other`. /// Returns `true` if the set has no elements in common with `other`.
/// This is equivalent to checking for an empty intersection. /// This is equivalent to checking for an empty intersection.
@ -527,6 +498,10 @@ impl<T: Eq + Hash<S>, S, H: Hasher<S>> HashSet<T, H> {
/// Removes a value from the set. Returns `true` if the value was /// Removes a value from the set. Returns `true` if the value was
/// present in the set. /// present in the set.
/// ///
/// The value may be any borrowed form of the set's value type, but
/// `Hash` and `Eq` on the borrowed form *must* match those for
/// the value type.
///
/// # Example /// # Example
/// ///
/// ``` /// ```
@ -539,7 +514,11 @@ impl<T: Eq + Hash<S>, S, H: Hasher<S>> HashSet<T, H> {
/// assert_eq!(set.remove(&2), false); /// assert_eq!(set.remove(&2), false);
/// ``` /// ```
#[unstable = "matches collection reform specification, waiting for dust to settle"] #[unstable = "matches collection reform specification, waiting for dust to settle"]
pub fn remove(&mut self, value: &T) -> bool { self.map.remove(value).is_some() } pub fn remove<Sized? Q>(&mut self, value: &Q) -> bool
where Q: BorrowFrom<T> + Hash<S> + Eq
{
self.map.remove(value).is_some()
}
} }
impl<T: Eq + Hash<S>, S, H: Hasher<S>> PartialEq for HashSet<T, H> { impl<T: Eq + Hash<S>, S, H: Hasher<S>> PartialEq for HashSet<T, H> {

View File

@ -718,7 +718,7 @@ impl<'a, K, V> Iterator<RawBucket<K, V>> for RawBuckets<'a, K, V> {
} }
/// An iterator that moves out buckets in reverse order. It leaves the table /// An iterator that moves out buckets in reverse order. It leaves the table
/// in an an inconsistent state and should only be used for dropping /// in an inconsistent state and should only be used for dropping
/// the table's remaining entries. It's used in the implementation of Drop. /// the table's remaining entries. It's used in the implementation of Drop.
struct RevMoveBuckets<'a, K, V> { struct RevMoveBuckets<'a, K, V> {
raw: RawBucket<K, V>, raw: RawBucket<K, V>,

View File

@ -381,16 +381,8 @@ pub fn copy(from: &Path, to: &Path) -> IoResult<()> {
let mut reader = try!(File::open(from)); let mut reader = try!(File::open(from));
let mut writer = try!(File::create(to)); let mut writer = try!(File::create(to));
let mut buf = [0, ..io::DEFAULT_BUF_SIZE];
loop { try!(update_err(super::util::copy(&mut reader, &mut writer), from, to));
let amt = match reader.read(&mut buf) {
Ok(n) => n,
Err(ref e) if e.kind == io::EndOfFile => { break }
Err(e) => return update_err(Err(e), from, to)
};
try!(writer.write(buf[..amt]));
}
chmod(to, try!(update_err(from.stat(), from, to)).perm) chmod(to, try!(update_err(from.stat(), from, to)).perm)
} }

View File

@ -141,6 +141,7 @@ extern crate rustrt;
pub use core::any; pub use core::any;
pub use core::bool; pub use core::bool;
pub use core::borrow;
pub use core::cell; pub use core::cell;
pub use core::clone; pub use core::clone;
#[cfg(not(test))] pub use core::cmp; #[cfg(not(test))] pub use core::cmp;

View File

@ -81,7 +81,7 @@ const BUF_BYTES : uint = 2048u;
/// # Failure /// # Failure
/// ///
/// Fails if the current working directory value is invalid: /// Fails if the current working directory value is invalid:
/// Possibles cases: /// Possible cases:
/// ///
/// * Current directory does not exist. /// * Current directory does not exist.
/// * There are insufficient permissions to access the current directory. /// * There are insufficient permissions to access the current directory.

View File

@ -554,11 +554,4 @@ mod tests {
assert_eq!(format!("{:30}", Duration::days(1) + Duration::milliseconds(2345)), assert_eq!(format!("{:30}", Duration::days(1) + Duration::milliseconds(2345)),
"P1DT2.345S".to_string()); "P1DT2.345S".to_string());
} }
#[test]
fn span() {
use io::timer::sleep;
let dur = Duration::span(|| sleep(Duration::milliseconds(5)));
assert!(dur > Duration::milliseconds(1));
}
} }

View File

@ -20,6 +20,6 @@ impl Registry {
} }
pub fn find_description(&self, code: &str) -> Option<&'static str> { pub fn find_description(&self, code: &str) -> Option<&'static str> {
self.descriptions.find_equiv(code).map(|desc| *desc) self.descriptions.get(code).map(|desc| *desc)
} }
} }

View File

@ -97,8 +97,8 @@ pub fn expand_asm<'cx>(cx: &'cx mut ExtCtxt, sp: Span, tts: &[ast::TokenTree])
// cannot be shared with any other operand (usually when // cannot be shared with any other operand (usually when
// a register is clobbered early.) // a register is clobbered early.)
let output = match constraint.get().slice_shift_char() { let output = match constraint.get().slice_shift_char() {
(Some('='), _) => None, Some(('=', _)) => None,
(Some('+'), operand) => { Some(('+', operand)) => {
Some(token::intern_and_get_ident(format!( Some(token::intern_and_get_ident(format!(
"={}", "={}",
operand).as_slice())) operand).as_slice()))

View File

@ -144,7 +144,7 @@ fn parse_args(ecx: &mut ExtCtxt, sp: Span, allow_method: bool,
let name = interned_name.get(); let name = interned_name.get();
p.expect(&token::Eq); p.expect(&token::Eq);
let e = p.parse_expr(); let e = p.parse_expr();
match names.find_equiv(name) { match names.get(name) {
None => {} None => {}
Some(prev) => { Some(prev) => {
ecx.span_err(e.span, ecx.span_err(e.span,
@ -366,7 +366,7 @@ impl<'a, 'b> Context<'a, 'b> {
self.ecx.expr_path(path) self.ecx.expr_path(path)
} }
parse::CountIsName(n) => { parse::CountIsName(n) => {
let i = match self.name_positions.find_equiv(n) { let i = match self.name_positions.get(n) {
Some(&i) => i, Some(&i) => i,
None => 0, // error already emitted elsewhere None => 0, // error already emitted elsewhere
}; };
@ -410,7 +410,7 @@ impl<'a, 'b> Context<'a, 'b> {
// Named arguments are converted to positional arguments at // Named arguments are converted to positional arguments at
// the end of the list of arguments // the end of the list of arguments
parse::ArgumentNamed(n) => { parse::ArgumentNamed(n) => {
let i = match self.name_positions.find_equiv(n) { let i = match self.name_positions.get(n) {
Some(&i) => i, Some(&i) => i,
None => 0, // error already emitted elsewhere None => 0, // error already emitted elsewhere
}; };

View File

@ -182,6 +182,10 @@ impl<'a, 'v> Visitor<'v> for Context<'a> {
"`#[thread_local]` is an experimental feature, and does not \ "`#[thread_local]` is an experimental feature, and does not \
currently handle destructors. There is no corresponding \ currently handle destructors. There is no corresponding \
`#[task_local]` mapping to the task model"); `#[task_local]` mapping to the task model");
} else if attr.name().equiv(&("linkage")) {
self.gate_feature("linkage", i.span,
"the `linkage` attribute is experimental \
and not portable across platforms")
} }
} }
match i.node { match i.node {

View File

@ -1232,7 +1232,8 @@ impl<'a> Parser<'a> {
{ {
if self.eat(&token::Lt) { if self.eat(&token::Lt) {
if lifetime_defs.is_empty() { if lifetime_defs.is_empty() {
self.warn("deprecated syntax, use `for` keyword now"); self.warn("deprecated syntax; use the `for` keyword now \
(e.g. change `fn<'a>` to `for<'a> fn`)");
let lifetime_defs = self.parse_lifetime_defs(); let lifetime_defs = self.parse_lifetime_defs();
self.expect_gt(); self.expect_gt();
lifetime_defs lifetime_defs
@ -5178,7 +5179,15 @@ impl<'a> Parser<'a> {
if self.eat(&token::OpenDelim(token::Brace)) { if self.eat(&token::OpenDelim(token::Brace)) {
// Parse a struct variant. // Parse a struct variant.
all_nullary = false; all_nullary = false;
kind = StructVariantKind(self.parse_struct_def()); let start_span = self.span;
let struct_def = self.parse_struct_def();
if struct_def.fields.len() == 0 {
self.span_err(start_span,
format!("unit-like struct variant should be written \
without braces, as `{},`",
token::get_ident(ident)).as_slice());
}
kind = StructVariantKind(struct_def);
} else if self.token == token::OpenDelim(token::Paren) { } else if self.token == token::OpenDelim(token::Paren) {
all_nullary = false; all_nullary = false;
let arg_tys = self.parse_enum_variant_seq( let arg_tys = self.parse_enum_variant_seq(

View File

@ -1855,7 +1855,7 @@ impl<'a> State<'a> {
try!(self.commasep(Inconsistent, a.outputs.as_slice(), try!(self.commasep(Inconsistent, a.outputs.as_slice(),
|s, &(ref co, ref o, is_rw)| { |s, &(ref co, ref o, is_rw)| {
match co.get().slice_shift_char() { match co.get().slice_shift_char() {
(Some('='), operand) if is_rw => { Some(('=', operand)) if is_rw => {
try!(s.print_string(format!("+{}", operand).as_slice(), try!(s.print_string(format!("+{}", operand).as_slice(),
ast::CookedStr)) ast::CookedStr))
} }

View File

@ -14,9 +14,9 @@
use ast::Name; use ast::Name;
use std::borrow::BorrowFrom;
use std::collections::HashMap; use std::collections::HashMap;
use std::cell::RefCell; use std::cell::RefCell;
use std::cmp::Equiv;
use std::fmt; use std::fmt;
use std::hash::Hash; use std::hash::Hash;
use std::rc::Rc; use std::rc::Rc;
@ -75,9 +75,10 @@ impl<T: Eq + Hash + Clone + 'static> Interner<T> {
(*vect).len() (*vect).len()
} }
pub fn find_equiv<Sized? Q: Hash + Equiv<T>>(&self, val: &Q) -> Option<Name> { pub fn find<Sized? Q>(&self, val: &Q) -> Option<Name>
where Q: BorrowFrom<T> + Eq + Hash {
let map = self.map.borrow(); let map = self.map.borrow();
match (*map).find_equiv(val) { match (*map).get(val) {
Some(v) => Some(*v), Some(v) => Some(*v),
None => None, None => None,
} }
@ -117,6 +118,12 @@ impl fmt::Show for RcStr {
} }
} }
impl BorrowFrom<RcStr> for str {
fn borrow_from(owned: &RcStr) -> &str {
owned.string.as_slice()
}
}
impl RcStr { impl RcStr {
pub fn new(string: &str) -> RcStr { pub fn new(string: &str) -> RcStr {
RcStr { RcStr {
@ -149,7 +156,7 @@ impl StrInterner {
pub fn intern(&self, val: &str) -> Name { pub fn intern(&self, val: &str) -> Name {
let mut map = self.map.borrow_mut(); let mut map = self.map.borrow_mut();
match map.find_equiv(val) { match map.get(val) {
Some(&idx) => return idx, Some(&idx) => return idx,
None => (), None => (),
} }
@ -195,8 +202,9 @@ impl StrInterner {
self.vect.borrow().len() self.vect.borrow().len()
} }
pub fn find_equiv<Sized? Q:Hash + Equiv<RcStr>>(&self, val: &Q) -> Option<Name> { pub fn find<Sized? Q>(&self, val: &Q) -> Option<Name>
match (*self.map.borrow()).find_equiv(val) { where Q: BorrowFrom<RcStr> + Eq + Hash {
match (*self.map.borrow()).get(val) {
Some(v) => Some(*v), Some(v) => Some(*v),
None => None, None => None,
} }

View File

@ -78,7 +78,7 @@ impl<T: Writer+Send> Terminal<T> for TerminfoTerminal<T> {
if self.num_colors > color { if self.num_colors > color {
let s = expand(self.ti let s = expand(self.ti
.strings .strings
.find_equiv("setaf") .get("setaf")
.unwrap() .unwrap()
.as_slice(), .as_slice(),
&[Number(color as int)], &mut Variables::new()); &[Number(color as int)], &mut Variables::new());
@ -95,7 +95,7 @@ impl<T: Writer+Send> Terminal<T> for TerminfoTerminal<T> {
if self.num_colors > color { if self.num_colors > color {
let s = expand(self.ti let s = expand(self.ti
.strings .strings
.find_equiv("setab") .get("setab")
.unwrap() .unwrap()
.as_slice(), .as_slice(),
&[Number(color as int)], &mut Variables::new()); &[Number(color as int)], &mut Variables::new());
@ -113,7 +113,7 @@ impl<T: Writer+Send> Terminal<T> for TerminfoTerminal<T> {
attr::BackgroundColor(c) => self.bg(c), attr::BackgroundColor(c) => self.bg(c),
_ => { _ => {
let cap = cap_for_attr(attr); let cap = cap_for_attr(attr);
let parm = self.ti.strings.find_equiv(cap); let parm = self.ti.strings.get(cap);
if parm.is_some() { if parm.is_some() {
let s = expand(parm.unwrap().as_slice(), let s = expand(parm.unwrap().as_slice(),
&[], &[],
@ -135,19 +135,19 @@ impl<T: Writer+Send> Terminal<T> for TerminfoTerminal<T> {
} }
_ => { _ => {
let cap = cap_for_attr(attr); let cap = cap_for_attr(attr);
self.ti.strings.find_equiv(cap).is_some() self.ti.strings.get(cap).is_some()
} }
} }
} }
fn reset(&mut self) -> IoResult<()> { fn reset(&mut self) -> IoResult<()> {
let mut cap = self.ti.strings.find_equiv("sgr0"); let mut cap = self.ti.strings.get("sgr0");
if cap.is_none() { if cap.is_none() {
// are there any terminals that have color/attrs and not sgr0? // are there any terminals that have color/attrs and not sgr0?
// Try falling back to sgr, then op // Try falling back to sgr, then op
cap = self.ti.strings.find_equiv("sgr"); cap = self.ti.strings.get("sgr");
if cap.is_none() { if cap.is_none() {
cap = self.ti.strings.find_equiv("op"); cap = self.ti.strings.get("op");
} }
} }
let s = cap.map_or(Err("can't find terminfo capability `sgr0`".to_string()), |op| { let s = cap.map_or(Err("can't find terminfo capability `sgr0`".to_string()), |op| {
@ -202,9 +202,9 @@ impl<T: Writer+Send> TerminfoTerminal<T> {
} }
let inf = ti.unwrap(); let inf = ti.unwrap();
let nc = if inf.strings.find_equiv("setaf").is_some() let nc = if inf.strings.get("setaf").is_some()
&& inf.strings.find_equiv("setab").is_some() { && inf.strings.get("setab").is_some() {
inf.numbers.find_equiv("colors").map_or(0, |&n| n) inf.numbers.get("colors").map_or(0, |&n| n)
} else { 0 }; } else { 0 };
return Some(box TerminfoTerminal {out: out, return Some(box TerminfoTerminal {out: out,

View File

@ -76,7 +76,7 @@ fn sort_and_fmt(mm: &HashMap<Vec<u8> , uint>, total: uint) -> String {
// given a map, search for the frequency of a pattern // given a map, search for the frequency of a pattern
fn find(mm: &HashMap<Vec<u8> , uint>, key: String) -> uint { fn find(mm: &HashMap<Vec<u8> , uint>, key: String) -> uint {
let key = key.into_ascii().as_slice().to_lowercase().into_string(); let key = key.into_ascii().as_slice().to_lowercase().into_string();
match mm.find_equiv(key.as_bytes()) { match mm.get(key.as_bytes()) {
option::None => { return 0u; } option::None => { return 0u; }
option::Some(&num) => { return num; } option::Some(&num) => { return num; }
} }

View File

@ -0,0 +1,20 @@
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// aux-build:use_from_trait_xc.rs
extern crate use_from_trait_xc;
pub use use_from_trait_xc::Trait;
fn main() {
match () {
Trait { x: 42u } => () //~ ERROR use of trait `Trait` in a struct pattern
}
}

View File

@ -0,0 +1,15 @@
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#[linkage = "external"]
static foo: int = 0;
//~^ ERROR: the `linkage` attribute is experimental and not portable
fn main() {}

View File

@ -459,6 +459,20 @@ mod this_crate {
foo.trait_stable(); foo.trait_stable();
} }
#[deprecated]
fn test_fn_body() {
fn fn_in_body() {}
fn_in_body();
}
impl MethodTester {
#[deprecated]
fn test_method_body(&self) {
fn fn_in_body() {}
fn_in_body();
}
}
#[deprecated] #[deprecated]
pub trait DeprecatedTrait {} pub trait DeprecatedTrait {}

View File

@ -0,0 +1,13 @@
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
enum Foo {
Bar {} //~ ERROR unit-like struct variant should be written without braces, as `Bar,`
}

View File

@ -0,0 +1,8 @@
-include ../tools.mk
all:
$(CC) foo.c -c -o $(TMPDIR)/foo.o
$(AR) rcs $(TMPDIR)/libfoo.a $(TMPDIR)/foo.o
$(RUSTC) bar.rs -lfoo -L $(TMPDIR)
$(call RUN,bar) || exit 1

View File

@ -0,0 +1,25 @@
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![feature(linkage)]
#[no_mangle]
#[linkage = "external"]
static BAZ: i32 = 21;
extern {
fn what() -> i32;
}
fn main() {
unsafe {
assert_eq!(what(), BAZ);
}
}

View File

@ -0,0 +1,7 @@
#include <stdint.h>
extern int32_t BAZ;
int32_t what() {
return BAZ;
}

View File

@ -0,0 +1,26 @@
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
struct Str([u8]);
#[deriving(Clone)]
struct CharSplits<'a, Sep> {
string: &'a Str,
sep: Sep,
allow_trailing_empty: bool,
only_ascii: bool,
finished: bool,
}
fn clone(s: &Str) -> &Str {
Clone::clone(&s)
}
fn main() {}