fi
}
+envopt() {
+ local NAME=$1
+ local V="CFG_${NAME}"
+ eval VV=\$$V
+
+ # If configure didn't set a value already, then check environment.
+ #
+ # (It is recommended that the configure script always check the
+ # environment before setting any values to envopt variables; see
+ # e.g. how CFG_CC is handled, where it first checks `-z "$CC"`,
+ # and issues msg if it ends up employing that provided value.)
+ if [ -z "$VV" ]
+ then
+ eval $V=\$$NAME
+ eval VV=\$$V
+ fi
+
+ # If script or environment provided a value, save it.
+ if [ ! -z "$VV" ]
+ then
+ putvar $V
+ fi
+}
+
msg "looking for configure programs"
need_cmd cmp
need_cmd mkdir
if !((chk_cc gcc clang && chk_cc g++ clang) ||
(chk_cc gcc gcc &&( chk_cc g++ g++ || chk g++ gcc))) then
err "the gcc and g++ in your path point to different compilers.
- Check which versions are in your path with cc --version and g++ --version.
+ Check which versions are in your path with gcc --version and g++ --version.
To resolve this problem, either fix your PATH or run configure with --enable-clang"
fi
esac
fi
-if [ ! -z "$CFG_ENABLE_CLANG" ]
+# Even when the user overrides the choice of CC, still try to detect
+# clang to disable some clang-specific warnings. We here draw a
+# distinction between:
+#
+# CFG_ENABLE_CLANG : passed --enable-clang, or host "requires" clang,
+# CFG_USING_CLANG : compiler (clang / gcc / $CC) looks like clang.
+#
+# This distinction is important because there are some safeguards we
+# would prefer to skip when merely CFG_USING_CLANG is set; but when
+# CFG_ENABLE_CLANG is set, that indicates that we are opting into
+# running such safeguards.
+
+if [ ! -z "$CC" ]
then
- if [ -z "$CFG_CLANG" ]
+ msg "skipping compiler inference steps; using provided CC=$CC"
+ CFG_CC="$CC"
+
+ CFG_OSX_CC_VERSION=$("$CFG_CC" --version 2>&1 | grep "clang")
+ if [ $? -eq 0 ]
then
- err "clang requested but not found"
+ step_msg "note, user-provided CC looks like clang; CC=$CC."
+ CFG_USING_CLANG=1
+ putvar CFG_USING_CLANG
fi
- CFG_CLANG_VERSION=$("$CFG_CLANG" \
- --version \
- | grep version \
- | sed 's/.*\(version .*\)/\1/; s/.*based on \(LLVM .*\))/\1/' \
- | cut -d ' ' -f 2)
-
- case $CFG_CLANG_VERSION in
- (3.0svn | 3.0 | 3.1* | 3.2* | 3.3* | 3.4* | 3.5* )
- step_msg "found ok version of CLANG: $CFG_CLANG_VERSION"
- CFG_C_COMPILER="clang"
- ;;
- (*)
- err "bad CLANG version: $CFG_CLANG_VERSION, need >=3.0svn"
- ;;
- esac
else
- CFG_C_COMPILER="gcc"
+ if [ ! -z "$CFG_ENABLE_CLANG" ]
+ then
+ if [ -z "$CFG_CLANG" ]
+ then
+ err "clang requested but not found"
+ fi
+ CFG_CC="$CFG_CLANG"
+ CFG_USING_CLANG=1
+ putvar CFG_USING_CLANG
+ else
+ CFG_CC="gcc"
+ fi
+fi
+
+if [ ! -z "$CFG_ENABLE_CLANG" ]
+then
+ if [ -z "$CC" ] || [[ $CC == *clang ]]
+ then
+ CFG_CLANG_VERSION=$($CFG_CC \
+ --version \
+ | grep version \
+ | sed 's/.*\(version .*\)/\1/; s/.*based on \(LLVM .*\))/\1/' \
+ | cut -d ' ' -f 2)
+
+ case $CFG_CLANG_VERSION in
+ (3.0svn | 3.0 | 3.1* | 3.2* | 3.3* | 3.4* | 3.5* )
+ step_msg "found ok version of CLANG: $CFG_CLANG_VERSION"
+ if [ -z "$CC" ]
+ then
+ CFG_CC="clang"
+ fi
+ ;;
+ (*)
+ err "bad CLANG version: $CFG_CLANG_VERSION, need >=3.0svn"
+ ;;
+ esac
+ else
+ msg "skipping CFG_ENABLE_CLANG version check; provided CC=$CC"
+ fi
fi
if [ ! -z "$CFG_ENABLE_CCACHE" ]
then
- if [ -z "$CFG_CCACHE" ]
+ if [ -z "$CC" ]
then
- err "ccache requested but not found"
+ if [ -z "$CFG_CCACHE" ]
+ then
+ err "ccache requested but not found"
+ fi
+
+ CFG_CC="ccache $CFG_CC"
fi
+fi
- CFG_C_COMPILER="ccache $CFG_C_COMPILER"
+if [ -z "$CC" -a -z "$CFG_ENABLE_CLANG" -a -z "$CFG_GCC" ]
+then
+ err "either clang or gcc is required"
fi
+# All safeguards based on $CFG_ENABLE_CLANG should occur before this
+# point in the script; after this point, script logic should inspect
+# $CFG_USING_CLANG rather than $CFG_ENABLE_CLANG.
+
+# Set CFG_{CC,CXX,CPP,CFLAGS,CXXFLAGS}
+envopt CC
+envopt CXX
+envopt CPP
+envopt CFLAGS
+envopt CXXFLAGS
+
# a little post-processing of various config values
CFG_PREFIX=${CFG_PREFIX%/}
CFG_MANDIR=${CFG_MANDIR%/}
esac
done
-if [ -z "$CFG_ENABLE_CLANG" -a -z "$CFG_GCC" ]
-then
- err "either clang or gcc is required"
-fi
-
if [ ! -z "$CFG_PERF" ]
then
HAVE_PERF_LOGFD=`$CFG_PERF stat --log-fd 2>&1 | grep 'unknown option'`
;;
esac
- case "$CFG_C_COMPILER" in
+ case "$CFG_CC" in
("ccache clang")
LLVM_CXX_32="ccache clang++ -m32 -Qunused-arguments"
LLVM_CC_32="ccache clang -m32 -Qunused-arguments"
LLVM_CXX_64="g++"
LLVM_CC_64="gcc"
+ ;;
+
+ (*)
+ msg "inferring LLVM_CXX/CC from CXX/CC = $CXX/$CC"
+ LLVM_CXX_32="$CXX -m32"
+ LLVM_CC_32="$CC -m32"
+
+ LLVM_CXX_64="$CXX"
+ LLVM_CC_64="$CC"
+ ;;
esac
LLVM_CFLAGS_32="-m32"
putvar CFG_BUILD
putvar CFG_HOST
putvar CFG_TARGET
-putvar CFG_C_COMPILER
putvar CFG_LIBDIR
putvar CFG_LIBDIR_RELATIVE
putvar CFG_DISABLE_MANAGE_SUBMODULES
# Avoid spurious warnings from clang by feeding it original source on
# ccache-miss rather than preprocessed input.
-if [ ! -z "$CFG_ENABLE_CCACHE" ] && [ ! -z "$CFG_ENABLE_CLANG" ]
+if [ ! -z "$CFG_ENABLE_CCACHE" ] && [ ! -z "$CFG_USING_CLANG" ]
then
CFG_CCACHE_CPP2=1
putvar CFG_CCACHE_CPP2
AR := ar
-CFG_INFO := $(info cfg: using $(CFG_C_COMPILER))
-ifeq ($(CFG_C_COMPILER),clang)
- # The -Qunused-arguments sidesteps spurious warnings from clang
- ifeq ($(origin CC),default)
- CC=clang -Qunused-arguments
- endif
- ifeq ($(origin CXX),default)
- CXX=clang++ -Qunused-arguments
- endif
- ifeq ($(origin CPP),default)
- CPP=clang -Qunused-arguments
- endif
-else
-ifeq ($(CFG_C_COMPILER),gcc)
- ifeq ($(origin CC),default)
- CC=gcc
- endif
- ifeq ($(origin CXX),default)
- CXX=g++
- endif
- ifeq ($(origin CPP),default)
- CPP=gcc
+define SET_FROM_CFG
+ ifdef CFG_$(1)
+ ifeq ($(origin $(1)),undefined)
+ $$(info cfg: using $(1)=$(CFG_$(1)) (CFG_$(1)))
+ $(1)=$(CFG_$(1))
+ endif
+ ifeq ($(origin $(1)),default)
+ $$(info cfg: using $(1)=$(CFG_$(1)) (CFG_$(1)))
+ $(1)=$(CFG_$(1))
+ endif
endif
-else
-ifeq ($(CFG_C_COMPILER),ccache clang)
+endef
+
+$(foreach cvar,CC CXX CPP CFLAGS CXXFLAGS CPPFLAGS,\
+ $(eval $(call SET_FROM_CFG,$(cvar))))
+
+ifeq ($(CFG_USING_CLANG),1)
# The -Qunused-arguments sidesteps spurious warnings from clang
- ifeq ($(origin CC),default)
- CC=ccache clang -Qunused-arguments
- endif
- ifeq ($(origin CXX),default)
- CXX=ccache clang++ -Qunused-arguments
- endif
- ifeq ($(origin CPP),default)
- CPP=ccache clang -Qunused-arguments
- endif
-else
-ifeq ($(CFG_C_COMPILER),ccache gcc)
- ifeq ($(origin CC),default)
- CC=ccache gcc
- endif
- ifeq ($(origin CXX),default)
- CXX=ccache g++
- endif
- ifeq ($(origin CPP),default)
- CPP=ccache gcc
- endif
-else
- CFG_ERR := $(error please try on a system with gcc or clang)
-endif
-endif
-endif
+ CFLAGS += -Qunused-arguments
+ CXXFLAGS += -Qunused-arguments
+ CPPFLAGS += -Qunused-arguments
endif
CFG_RLIB_GLOB=lib$(1)-*.rlib
CFG_STATIC_LIB_NAME_i686-unknown-linux-gnu=lib$(1).a
CFG_LIB_GLOB_i686-unknown-linux-gnu=lib$(1)-*.so
CFG_LIB_DSYM_GLOB_i686-unknown-linux-gnu=lib$(1)-*.dylib.dSYM
-CFG_CFLAGS_i686-unknown-linux-gnu := -m32
-CFG_GCCISH_CFLAGS_i686-unknown-linux-gnu := -Wall -Werror -g -fPIC -m32
-CFG_GCCISH_CXXFLAGS_i686-unknown-linux-gnu := -fno-rtti
+CFG_CFLAGS_i686-unknown-linux-gnu := -m32 $(CFLAGS)
+CFG_GCCISH_CFLAGS_i686-unknown-linux-gnu := -Wall -Werror -g -fPIC -m32 $(CFLAGS)
+CFG_GCCISH_CXXFLAGS_i686-unknown-linux-gnu := -fno-rtti $(CXXFLAGS)
CFG_GCCISH_LINK_FLAGS_i686-unknown-linux-gnu := -shared -fPIC -ldl -pthread -lrt -g -m32
CFG_GCCISH_DEF_FLAG_i686-unknown-linux-gnu := -Wl,--export-dynamic,--dynamic-list=
CFG_GCCISH_PRE_LIB_FLAGS_i686-unknown-linux-gnu := -Wl,-whole-archive
CFG_LIB_NAME_arm-apple-darwin = lib$(1).dylib
CFG_LIB_GLOB_arm-apple-darwin = lib$(1)-*.dylib
CFG_LIB_DSYM_GLOB_arm-apple-darwin = lib$(1)-*.dylib.dSYM
-CFG_CFLAGS_arm-apple-darwin := $(CFG_IOS_FLAGS)
-CFG_GCCISH_CFLAGS_arm-apple-darwin := -Wall -Werror -g -fPIC $(CFG_IOS_FLAGS)
-CFG_GCCISH_CXXFLAGS_arm-apple-darwin := -fno-rtti $(CFG_IOS_FLAGS)
+CFG_CFLAGS_arm-apple-darwin := $(CFG_IOS_FLAGS) $(CFLAGS)
+CFG_GCCISH_CFLAGS_arm-apple-darwin := -Wall -Werror -g -fPIC $(CFG_IOS_FLAGS) $(CFLAGS)
+CFG_GCCISH_CXXFLAGS_arm-apple-darwin := -fno-rtti $(CFG_IOS_FLAGS) $(CXXFLAGS)
CFG_GCCISH_LINK_FLAGS_arm-apple-darwin := -dynamiclib -lpthread -framework CoreServices -Wl,-no_compact_unwind
CFG_GCCISH_DEF_FLAG_arm-apple-darwin := -Wl,-exported_symbols_list,
CFG_GCCISH_PRE_LIB_FLAGS_arm-apple-darwin :=
CFG_STATIC_LIB_NAME_x86_64-apple-darwin=lib$(1).a
CFG_LIB_GLOB_x86_64-apple-darwin=lib$(1)-*.dylib
CFG_LIB_DSYM_GLOB_x86_64-apple-darwin=lib$(1)-*.dylib.dSYM
-CFG_CFLAGS_x86_64-apple-darwin := -m64 -arch x86_64
-CFG_GCCISH_CFLAGS_x86_64-apple-darwin := -Wall -Werror -g -fPIC -m64 -arch x86_64
-CFG_GCCISH_CXXFLAGS_x86_64-apple-darwin := -fno-rtti
+CFG_CFLAGS_x86_64-apple-darwin := -m64 -arch x86_64 $(CFLAGS)
+CFG_GCCISH_CFLAGS_x86_64-apple-darwin := -Wall -Werror -g -fPIC -m64 -arch x86_64 $(CFLAGS)
+CFG_GCCISH_CXXFLAGS_x86_64-apple-darwin := -fno-rtti $(CXXFLAGS)
CFG_GCCISH_LINK_FLAGS_x86_64-apple-darwin := -dynamiclib -pthread -framework CoreServices -m64
CFG_GCCISH_DEF_FLAG_x86_64-apple-darwin := -Wl,-exported_symbols_list,
CFG_GCCISH_PRE_LIB_FLAGS_x86_64-apple-darwin :=
CFG_STATIC_LIB_NAME_i686-apple-darwin=lib$(1).a
CFG_LIB_GLOB_i686-apple-darwin=lib$(1)-*.dylib
CFG_LIB_DSYM_GLOB_i686-apple-darwin=lib$(1)-*.dylib.dSYM
-CFG_CFLAGS_i686-apple-darwin := -m32 -arch i386
-CFG_GCCISH_CFLAGS_i686-apple-darwin := -Wall -Werror -g -fPIC -m32 -arch i386
-CFG_GCCISH_CXXFLAGS_i686-apple-darwin := -fno-rtti
+CFG_CFLAGS_i686-apple-darwin := -m32 -arch i386 $(CFLAGS)
+CFG_GCCISH_CFLAGS_i686-apple-darwin := -Wall -Werror -g -fPIC -m32 -arch i386 $(CFLAGS)
+CFG_GCCISH_CXXFLAGS_i686-apple-darwin := -fno-rtti $(CXXFLAGS)
CFG_GCCISH_LINK_FLAGS_i686-apple-darwin := -dynamiclib -pthread -framework CoreServices -m32
CFG_GCCISH_DEF_FLAG_i686-apple-darwin := -Wl,-exported_symbols_list,
CFG_GCCISH_PRE_LIB_FLAGS_i686-apple-darwin :=
CFG_STATIC_LIB_NAME_arm-linux-androideabi=lib$(1).a
CFG_LIB_GLOB_arm-linux-androideabi=lib$(1)-*.so
CFG_LIB_DSYM_GLOB_arm-linux-androideabi=lib$(1)-*.dylib.dSYM
-CFG_CFLAGS_arm-linux-androideabi := -D__arm__ -DANDROID -D__ANDROID__
-CFG_GCCISH_CFLAGS_arm-linux-androideabi := -Wall -g -fPIC -D__arm__ -DANDROID -D__ANDROID__
-CFG_GCCISH_CXXFLAGS_arm-linux-androideabi := -fno-rtti
+CFG_CFLAGS_arm-linux-androideabi := -D__arm__ -DANDROID -D__ANDROID__ $(CFLAGS)
+CFG_GCCISH_CFLAGS_arm-linux-androideabi := -Wall -g -fPIC -D__arm__ -DANDROID -D__ANDROID__ $(CFLAGS)
+CFG_GCCISH_CXXFLAGS_arm-linux-androideabi := -fno-rtti $(CXXFLAGS)
CFG_GCCISH_LINK_FLAGS_arm-linux-androideabi := -shared -fPIC -ldl -g -lm -lsupc++
CFG_GCCISH_DEF_FLAG_arm-linux-androideabi := -Wl,--export-dynamic,--dynamic-list=
CFG_GCCISH_PRE_LIB_FLAGS_arm-linux-androideabi := -Wl,-whole-archive
CFG_STATIC_LIB_NAME_arm-unknown-linux-gnueabihf=lib$(1).a
CFG_LIB_GLOB_arm-unknown-linux-gnueabihf=lib$(1)-*.so
CFG_LIB_DSYM_GLOB_arm-unknown-linux-gnueabihf=lib$(1)-*.dylib.dSYM
-CFG_CFLAGS_arm-unknown-linux-gnueabihf := -D__arm__
-CFG_GCCISH_CFLAGS_arm-unknown-linux-gnueabihf := -Wall -g -fPIC -D__arm__
-CFG_GCCISH_CXXFLAGS_arm-unknown-linux-gnueabihf := -fno-rtti
+CFG_CFLAGS_arm-unknown-linux-gnueabihf := -D__arm__ $(CFLAGS)
+CFG_GCCISH_CFLAGS_arm-unknown-linux-gnueabihf := -Wall -g -fPIC -D__arm__ $(CFLAGS)
+CFG_GCCISH_CXXFLAGS_arm-unknown-linux-gnueabihf := -fno-rtti $(CXXFLAGS)
CFG_GCCISH_LINK_FLAGS_arm-unknown-linux-gnueabihf := -shared -fPIC -g
CFG_GCCISH_DEF_FLAG_arm-unknown-linux-gnueabihf := -Wl,--export-dynamic,--dynamic-list=
CFG_GCCISH_PRE_LIB_FLAGS_arm-unknown-linux-gnueabihf := -Wl,-whole-archive
CFG_STATIC_LIB_NAME_arm-unknown-linux-gnueabi=lib$(1).a
CFG_LIB_GLOB_arm-unknown-linux-gnueabi=lib$(1)-*.so
CFG_LIB_DSYM_GLOB_arm-unknown-linux-gnueabi=lib$(1)-*.dylib.dSYM
-CFG_CFLAGS_arm-unknown-linux-gnueabi := -D__arm__ -mfpu=vfp
-CFG_GCCISH_CFLAGS_arm-unknown-linux-gnueabi := -Wall -g -fPIC -D__arm__ -mfpu=vfp
-CFG_GCCISH_CXXFLAGS_arm-unknown-linux-gnueabi := -fno-rtti
+CFG_CFLAGS_arm-unknown-linux-gnueabi := -D__arm__ -mfpu=vfp $(CFLAGS)
+CFG_GCCISH_CFLAGS_arm-unknown-linux-gnueabi := -Wall -g -fPIC -D__arm__ -mfpu=vfp $(CFLAGS)
+CFG_GCCISH_CXXFLAGS_arm-unknown-linux-gnueabi := -fno-rtti $(CXXFLAGS)
CFG_GCCISH_LINK_FLAGS_arm-unknown-linux-gnueabi := -shared -fPIC -g
CFG_GCCISH_DEF_FLAG_arm-unknown-linux-gnueabi := -Wl,--export-dynamic,--dynamic-list=
CFG_GCCISH_PRE_LIB_FLAGS_arm-unknown-linux-gnueabi := -Wl,-whole-archive
CFG_STATIC_LIB_NAME_mips-unknown-linux-gnu=lib$(1).a
CFG_LIB_GLOB_mips-unknown-linux-gnu=lib$(1)-*.so
CFG_LIB_DSYM_GLOB_mips-unknown-linux-gnu=lib$(1)-*.dylib.dSYM
-CFG_CFLAGS_mips-unknown-linux-gnu := -mips32r2 -msoft-float -mabi=32 -mno-compact-eh
-CFG_GCCISH_CFLAGS_mips-unknown-linux-gnu := -Wall -g -fPIC -mips32r2 -msoft-float -mabi=32 -mno-compact-eh
-CFG_GCCISH_CXXFLAGS_mips-unknown-linux-gnu := -fno-rtti
+CFG_CFLAGS_mips-unknown-linux-gnu := -mips32r2 -msoft-float -mabi=32 -mno-compact-eh $(CFLAGS)
+CFG_GCCISH_CFLAGS_mips-unknown-linux-gnu := -Wall -g -fPIC -mips32r2 -msoft-float -mabi=32 -mno-compact-eh $(CFLAGS)
+CFG_GCCISH_CXXFLAGS_mips-unknown-linux-gnu := -fno-rtti $(CXXFLAGS)
CFG_GCCISH_LINK_FLAGS_mips-unknown-linux-gnu := -shared -fPIC -g -mips32r2 -msoft-float -mabi=32
CFG_GCCISH_DEF_FLAG_mips-unknown-linux-gnu := -Wl,--export-dynamic,--dynamic-list=
CFG_GCCISH_PRE_LIB_FLAGS_mips-unknown-linux-gnu := -Wl,-whole-archive
CFG_STATIC_LIB_NAME_i686-pc-mingw32=$(1).lib
CFG_LIB_GLOB_i686-pc-mingw32=$(1)-*.dll
CFG_LIB_DSYM_GLOB_i686-pc-mingw32=$(1)-*.dylib.dSYM
-CFG_CFLAGS_mips-i686-pc-mingw32 := -m32 -march=i686 -D_WIN32_WINNT=0x0600
-CFG_GCCISH_CFLAGS_i686-pc-mingw32 := -Wall -Werror -g -m32 -march=i686 -D_WIN32_WINNT=0x0600 -I$(CFG_SRC_DIR)src/etc/mingw-fix-include
-CFG_GCCISH_CXXFLAGS_i686-pc-mingw32 := -fno-rtti
+CFG_CFLAGS_mips-i686-pc-mingw32 := -m32 -march=i686 -D_WIN32_WINNT=0x0600 $(CFLAGS)
+CFG_GCCISH_CFLAGS_i686-pc-mingw32 := -Wall -Werror -g -m32 -march=i686 -D_WIN32_WINNT=0x0600 -I$(CFG_SRC_DIR)src/etc/mingw-fix-include $(CFLAGS)
+CFG_GCCISH_CXXFLAGS_i686-pc-mingw32 := -fno-rtti $(CXXFLAGS)
CFG_GCCISH_LINK_FLAGS_i686-pc-mingw32 := -shared -fPIC -g -m32
CFG_GCCISH_DEF_FLAG_i686-pc-mingw32 :=
CFG_GCCISH_PRE_LIB_FLAGS_i686-pc-mingw32 :=
CFG_STATIC_LIB_NAME_i586-mingw32msvc=$(1).lib
CFG_LIB_GLOB_i586-mingw32msvc=$(1)-*.dll
CFG_LIB_DSYM_GLOB_i586-mingw32msvc=$(1)-*.dylib.dSYM
-CFG_CFLAGS_i586-mingw32msvc := -march=i586 -m32
-CFG_GCCISH_CFLAGS_i586-mingw32msvc := -Wall -Werror -g -march=i586 -m32
-CFG_GCCISH_CXXFLAGS_i586-mingw32msvc := -fno-rtti
+CFG_CFLAGS_i586-mingw32msvc := -march=i586 -m32 $(CFLAGS)
+CFG_GCCISH_CFLAGS_i586-mingw32msvc := -Wall -Werror -g -march=i586 -m32 $(CFLAGS)
+CFG_GCCISH_CXXFLAGS_i586-mingw32msvc := -fno-rtti $(CXXFLAGS)
CFG_GCCISH_LINK_FLAGS_i586-mingw32msvc := -shared -g -m32
CFG_GCCISH_DEF_FLAG_i586-mingw32msvc :=
CFG_GCCISH_PRE_LIB_FLAGS_i586-mingw32msvc :=
CFG_STATIC_LIB_NAME_i686-w64-mingw32=$(1).lib
CFG_LIB_GLOB_i686-w64-mingw32=$(1)-*.dll
CFG_LIB_DSYM_GLOB_i686-w64-mingw32=$(1)-*.dylib.dSYM
-CFG_CFLAGS_i586-w64-mingw32 := -march=i586 -m32 -D_WIN32_WINNT=0x0600
-CFG_GCCISH_CFLAGS_i686-w64-mingw32 := -Wall -Werror -g -m32 -D_WIN32_WINNT=0x0600
-CFG_GCCISH_CXXFLAGS_i686-w64-mingw32 := -fno-rtti
+CFG_CFLAGS_i586-w64-mingw32 := -march=i586 -m32 -D_WIN32_WINNT=0x0600 $(CFLAGS)
+CFG_GCCISH_CFLAGS_i686-w64-mingw32 := -Wall -Werror -g -m32 -D_WIN32_WINNT=0x0600 $(CFLAGS)
+CFG_GCCISH_CXXFLAGS_i686-w64-mingw32 := -fno-rtti $(CXXFLAGS)
CFG_GCCISH_LINK_FLAGS_i686-w64-mingw32 := -shared -g -m32
CFG_GCCISH_DEF_FLAG_i686-w64-mingw32 :=
CFG_GCCISH_PRE_LIB_FLAGS_i686-w64-mingw32 :=
CFG_STATIC_LIB_NAME_x86_64-w64-mingw32=$(1).lib
CFG_LIB_GLOB_x86_64-w64-mingw32=$(1)-*.dll
CFG_LIB_DSYM_GLOB_x86_64-w64-mingw32=$(1)-*.dylib.dSYM
-CFG_CFLAGS_x86_64-w64-mingw32 := -m64 -D_WIN32_WINNT=0x0600
-CFG_GCCISH_CFLAGS_x86_64-w64-mingw32 := -Wall -Werror -g -m64 -D_WIN32_WINNT=0x0600
-CFG_GCCISH_CXXFLAGS_x86_64-w64-mingw32 := -fno-rtti
+CFG_CFLAGS_x86_64-w64-mingw32 := -m64 -D_WIN32_WINNT=0x0600 $(CFLAGS)
+CFG_GCCISH_CFLAGS_x86_64-w64-mingw32 := -Wall -Werror -g -m64 -D_WIN32_WINNT=0x0600 $(CFLAGS)
+CFG_GCCISH_CXXFLAGS_x86_64-w64-mingw32 := -fno-rtti $(CXXFLAGS)
CFG_GCCISH_LINK_FLAGS_x86_64-w64-mingw32 := -shared -g -m64
CFG_GCCISH_DEF_FLAG_x86_64-w64-mingw32 :=
CFG_GCCISH_PRE_LIB_FLAGS_x86_64-w64-mingw32 :=
CFG_STATIC_LIB_NAME_x86_64-unknown-freebsd=lib$(1).a
CFG_LIB_GLOB_x86_64-unknown-freebsd=lib$(1)-*.so
CFG_LIB_DSYM_GLOB_x86_64-unknown-freebsd=$(1)-*.dylib.dSYM
-CFG_CFLAGS_x86_64-unknown-freebsd := -I/usr/local/include
-CFG_GCCISH_CFLAGS_x86_64-unknown-freebsd := -Wall -Werror -g -fPIC -I/usr/local/include
+CFG_CFLAGS_x86_64-unknown-freebsd := -I/usr/local/include $(CFLAGS)
+CFG_GCCISH_CFLAGS_x86_64-unknown-freebsd := -Wall -Werror -g -fPIC -I/usr/local/include $(CFLAGS)
CFG_GCCISH_LINK_FLAGS_x86_64-unknown-freebsd := -shared -fPIC -g -pthread -lrt
CFG_GCCISH_DEF_FLAG_x86_64-unknown-freebsd := -Wl,--export-dynamic,--dynamic-list=
CFG_GCCISH_PRE_LIB_FLAGS_x86_64-unknown-freebsd := -Wl,-whole-archive
-// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Only run tests that match this filter
pub filter: Option<Regex>,
+ // Precompiled regex for finding expected errors in cfail
+ pub cfail_regex: Regex,
+
// Write out a parseable log of tests that were run
pub logfile: Option<Path>,
// Explain what's going on
pub verbose: bool
-
}
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
use common::Config;
use common::{Pretty, DebugInfoGdb, Codegen};
use util::logv;
+use regex::Regex;
pub mod procsrv;
pub mod util;
.as_slice()).expect("invalid mode"),
run_ignored: matches.opt_present("ignored"),
filter: filter,
+ cfail_regex: Regex::new(errors::EXPECTED_PATTERN).unwrap(),
logfile: matches.opt_str("logfile").map(|s| Path::new(s)),
save_metrics: matches.opt_str("save-metrics").map(|s| Path::new(s)),
ratchet_metrics:
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// except according to those terms.
use std::io::{BufferedReader, File};
+use regex::Regex;
pub struct ExpectedError {
pub line: uint,
pub msg: StrBuf,
}
-// Load any test directives embedded in the file
-pub fn load_errors(testfile: &Path) -> Vec<ExpectedError> {
+pub static EXPECTED_PATTERN : &'static str = r"//~(?P<adjusts>\^*)\s*(?P<kind>\S*)\s*(?P<msg>.*)";
- let mut error_patterns = Vec::new();
+// Load any test directives embedded in the file
+pub fn load_errors(re: &Regex, testfile: &Path) -> Vec<ExpectedError> {
let mut rdr = BufferedReader::new(File::open(testfile).unwrap());
- let mut line_num = 1u;
- for ln in rdr.lines() {
- error_patterns.push_all_move(parse_expected(line_num,
- ln.unwrap().to_strbuf()));
- line_num += 1u;
- }
- return error_patterns;
-}
-
-fn parse_expected(line_num: uint, line: StrBuf) -> Vec<ExpectedError> {
- let line = line.as_slice().trim().to_strbuf();
- let error_tag = "//~".to_strbuf();
- let mut idx;
- match line.as_slice().find_str(error_tag.as_slice()) {
- None => return Vec::new(),
- Some(nn) => { idx = (nn as uint) + error_tag.len(); }
- }
-
- // "//~^^^ kind msg" denotes a message expected
- // three lines above current line:
- let mut adjust_line = 0u;
- let len = line.len();
- while idx < len && line.as_slice()[idx] == ('^' as u8) {
- adjust_line += 1u;
- idx += 1u;
- }
- // Extract kind:
- while idx < len && line.as_slice()[idx] == (' ' as u8) {
- idx += 1u;
- }
- let start_kind = idx;
- while idx < len && line.as_slice()[idx] != (' ' as u8) {
- idx += 1u;
- }
-
- let kind = line.as_slice().slice(start_kind, idx);
- let kind = kind.to_ascii().to_lower().into_str().to_strbuf();
-
- // Extract msg:
- while idx < len && line.as_slice()[idx] == (' ' as u8) {
- idx += 1u;
- }
- let msg = line.as_slice().slice(idx, len).to_strbuf();
-
- debug!("line={} kind={} msg={}", line_num - adjust_line, kind, msg);
+ rdr.lines().enumerate().filter_map(|(line_no, ln)| {
+ parse_expected(line_no + 1, ln.unwrap(), re)
+ }).collect()
+}
- return vec!(ExpectedError{
- line: line_num - adjust_line,
- kind: kind,
- msg: msg,
- });
+fn parse_expected(line_num: uint, line: &str, re: &Regex) -> Option<ExpectedError> {
+ re.captures(line).and_then(|caps| {
+ let adjusts = caps.name("adjusts").len();
+ let kind = caps.name("kind").to_ascii().to_lower().into_str().to_strbuf();
+ let msg = caps.name("msg").trim().to_strbuf();
+
+ debug!("line={} kind={} msg={}", line_num, kind, msg);
+ Some(ExpectedError {
+ line: line_num - adjusts,
+ kind: kind,
+ msg: msg,
+ })
+ })
}
-// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
check_correct_failure_status(&proc_res);
- let expected_errors = errors::load_errors(testfile);
+ let expected_errors = errors::load_errors(&config.cfail_regex, testfile);
if !expected_errors.is_empty() {
if !props.error_patterns.is_empty() {
fatal("both error pattern and expected errors \
##### Use declarations
~~~~ {.notrust .ebnf .gram}
-use_decl : "pub" ? "use" ident [ '=' path
- | "::" path_glob ] ;
+use_decl : "pub" ? "use" [ ident '=' path
+ | path_glob ] ;
-path_glob : ident [ "::" path_glob ] ?
- | '*'
+path_glob : ident [ "::" [ path_glob
+ | '*' ] ] ?
| '{' ident [ ',' ident ] * '}' ;
~~~~
attribute : '#' '!' ? '[' meta_item ']' ;
meta_item : ident [ '=' literal
| '(' meta_seq ')' ] ? ;
-meta_seq : meta_item [ ',' meta_seq ]* ;
+meta_seq : meta_item [ ',' meta_seq ] ? ;
~~~~
Static entities in Rust — crates, modules and items — may have _attributes_
break_expr : "break" [ lifetime ];
~~~~
-A `break` expression has an optional `label`.
+A `break` expression has an optional _label_.
If the label is absent, then executing a `break` expression immediately terminates the innermost loop enclosing it.
It is only permitted in the body of a loop.
If the label is present, then `break foo` terminates the loop with label `foo`,
continue_expr : "continue" [ lifetime ];
~~~~
-A `continue` expression has an optional `label`.
+A `continue` expression has an optional _label_.
If the label is absent,
then executing a `continue` expression immediately terminates the current iteration of the innermost loop enclosing it,
returning control to the loop *head*.
### Match expressions
~~~~ {.notrust .ebnf .gram}
-match_expr : "match" expr '{' match_arm [ '|' match_arm ] * '}' ;
+match_expr : "match" expr '{' match_arm * '}' ;
-match_arm : match_pat "=>" [ expr "," | '{' block '}' ] ;
+match_arm : attribute * match_pat "=>" [ expr "," | '{' block '}' ] ;
-match_pat : pat [ ".." pat ] ? [ "if" expr ] ;
+match_pat : pat [ '|' pat ] * [ "if" expr ] ? ;
~~~~
A `match` expression branches on a *pattern*. The exact form of matching that
match x {
Cons(a, box Cons(b, _)) => {
- process_pair(a,b);
+ process_pair(a, b);
}
Cons(10, _) => {
process_ten();
or to a mutable reference using `ref mut`.
Subpatterns can also be bound to variables by the use of the syntax
-`variable @ pattern`.
+`variable @ subpattern`.
For example:
~~~~
An example of a tuple type and its use:
~~~~
-type Pair<'a> = (int,&'a str);
-let p: Pair<'static> = (10,"hello");
+type Pair<'a> = (int, &'a str);
+let p: Pair<'static> = (10, "hello");
let (a, b) = p;
assert!(b != "world");
~~~~
~~~
The full list of derivable traits is `Eq`, `TotalEq`, `Ord`,
-`TotalOrd`, `Encodable` `Decodable`, `Clone`,
+`TotalOrd`, `Encodable`, `Decodable`, `Clone`,
`Hash`, `Rand`, `Default`, `Zero`, `FromPrimitive` and `Show`.
# Crates and the module system
!self.none()
}
- pub fn init_to_vec(&self, i: uint) -> uint {
- return if self.get(i) { 1 } else { 0 };
- }
-
/**
* Converts `self` to a vector of `uint` with the same length.
*
* Each `uint` in the resulting vector has either value `0u` or `1u`.
*/
pub fn to_vec(&self) -> Vec<uint> {
- Vec::from_fn(self.nbits, |x| self.init_to_vec(x))
+ Vec::from_fn(self.nbits, |i| if self.get(i) { 1 } else { 0 })
}
/**
}
}
-impl<T: Ord> DList<T> {
+impl<T: TotalOrd> DList<T> {
/// Insert `elt` sorted in ascending order
///
/// O(N)
data: Vec<T>,
}
-impl<T:Ord> Container for PriorityQueue<T> {
+impl<T: TotalOrd> Container for PriorityQueue<T> {
/// Returns the length of the queue
fn len(&self) -> uint { self.data.len() }
}
-impl<T:Ord> Mutable for PriorityQueue<T> {
+impl<T: TotalOrd> Mutable for PriorityQueue<T> {
/// Drop all items from the queue
fn clear(&mut self) { self.data.truncate(0) }
}
-impl<T:Ord> PriorityQueue<T> {
+impl<T: TotalOrd> PriorityQueue<T> {
/// An iterator visiting all values in underlying vector, in
/// arbitrary order.
pub fn iter<'a>(&'a self) -> Items<'a, T> {
Items { iter: self.data.iter() }
}
- /// Returns the greatest item in the queue - fails if empty
- pub fn top<'a>(&'a self) -> &'a T { self.data.get(0) }
-
- /// Returns the greatest item in the queue - None if empty
- pub fn maybe_top<'a>(&'a self) -> Option<&'a T> {
- if self.is_empty() { None } else { Some(self.top()) }
+ /// Returns the greatest item in a queue or None if it is empty
+ pub fn top<'a>(&'a self) -> Option<&'a T> {
+ if self.is_empty() { None } else { Some(self.data.get(0)) }
}
+ #[deprecated="renamed to `top`"]
+ pub fn maybe_top<'a>(&'a self) -> Option<&'a T> { self.top() }
+
/// Returns the number of elements the queue can hold without reallocating
pub fn capacity(&self) -> uint { self.data.capacity() }
self.data.reserve(n)
}
- /// Pop the greatest item from the queue - fails if empty
- pub fn pop(&mut self) -> T {
- let mut item = self.data.pop().unwrap();
- if !self.is_empty() {
- swap(&mut item, self.data.get_mut(0));
- self.siftdown(0);
+ /// Remove the greatest item from a queue and return it, or `None` if it is
+ /// empty.
+ pub fn pop(&mut self) -> Option<T> {
+ match self.data.pop() {
+ None => { None }
+ Some(mut item) => {
+ if !self.is_empty() {
+ swap(&mut item, self.data.get_mut(0));
+ self.siftdown(0);
+ }
+ Some(item)
+ }
}
- item
}
- /// Pop the greatest item from the queue - None if empty
- pub fn maybe_pop(&mut self) -> Option<T> {
- if self.is_empty() { None } else { Some(self.pop()) }
- }
+ #[deprecated="renamed to `pop`"]
+ pub fn maybe_pop(&mut self) -> Option<T> { self.pop() }
/// Push an item onto the queue
pub fn push(&mut self, item: T) {
/// Optimized version of a push followed by a pop
pub fn push_pop(&mut self, mut item: T) -> T {
- if !self.is_empty() && *self.top() > item {
+ if !self.is_empty() && *self.top().unwrap() > item {
swap(&mut item, self.data.get_mut(0));
self.siftdown(0);
}
item
}
- /// Optimized version of a pop followed by a push - fails if empty
- pub fn replace(&mut self, mut item: T) -> T {
- swap(&mut item, self.data.get_mut(0));
- self.siftdown(0);
- item
+ /// Optimized version of a pop followed by a push. The push is done
+ /// regardless of whether the queue is empty.
+ pub fn replace(&mut self, mut item: T) -> Option<T> {
+ if !self.is_empty() {
+ swap(&mut item, self.data.get_mut(0));
+ self.siftdown(0);
+ Some(item)
+ } else {
+ self.push(item);
+ None
+ }
}
+ #[allow(dead_code)]
+ #[deprecated="renamed to `into_vec`"]
+ fn to_vec(self) -> Vec<T> { self.into_vec() }
+
+ #[allow(dead_code)]
+ #[deprecated="renamed to `into_sorted_vec`"]
+ fn to_sorted_vec(self) -> Vec<T> { self.into_sorted_vec() }
+
/// Consume the PriorityQueue and return the underlying vector
- pub fn to_vec(self) -> Vec<T> { let PriorityQueue{data: v} = self; v }
+ pub fn into_vec(self) -> Vec<T> { let PriorityQueue{data: v} = self; v }
/// Consume the PriorityQueue and return a vector in sorted
/// (ascending) order
- pub fn to_sorted_vec(self) -> Vec<T> {
+ pub fn into_sorted_vec(self) -> Vec<T> {
let mut q = self;
let mut end = q.len();
while end > 1 {
q.data.as_mut_slice().swap(0, end);
q.siftdown_range(0, end)
}
- q.to_vec()
+ q.into_vec()
}
/// Create an empty PriorityQueue
fn size_hint(&self) -> (uint, Option<uint>) { self.iter.size_hint() }
}
-impl<T: Ord> FromIterator<T> for PriorityQueue<T> {
+impl<T: TotalOrd> FromIterator<T> for PriorityQueue<T> {
fn from_iter<Iter: Iterator<T>>(iter: Iter) -> PriorityQueue<T> {
let mut q = PriorityQueue::new();
q.extend(iter);
}
}
-impl<T: Ord> Extendable<T> for PriorityQueue<T> {
+impl<T: TotalOrd> Extendable<T> for PriorityQueue<T> {
fn extend<Iter: Iterator<T>>(&mut self, mut iter: Iter) {
let (lower, _) = iter.size_hint();
sorted.sort();
let mut heap = PriorityQueue::from_vec(data);
while !heap.is_empty() {
- assert_eq!(heap.top(), sorted.last().unwrap());
- assert_eq!(heap.pop(), sorted.pop().unwrap());
+ assert_eq!(heap.top().unwrap(), sorted.last().unwrap());
+ assert_eq!(heap.pop().unwrap(), sorted.pop().unwrap());
}
}
fn test_push() {
let mut heap = PriorityQueue::from_vec(vec!(2, 4, 9));
assert_eq!(heap.len(), 3);
- assert!(*heap.top() == 9);
+ assert!(*heap.top().unwrap() == 9);
heap.push(11);
assert_eq!(heap.len(), 4);
- assert!(*heap.top() == 11);
+ assert!(*heap.top().unwrap() == 11);
heap.push(5);
assert_eq!(heap.len(), 5);
- assert!(*heap.top() == 11);
+ assert!(*heap.top().unwrap() == 11);
heap.push(27);
assert_eq!(heap.len(), 6);
- assert!(*heap.top() == 27);
+ assert!(*heap.top().unwrap() == 27);
heap.push(3);
assert_eq!(heap.len(), 7);
- assert!(*heap.top() == 27);
+ assert!(*heap.top().unwrap() == 27);
heap.push(103);
assert_eq!(heap.len(), 8);
- assert!(*heap.top() == 103);
+ assert!(*heap.top().unwrap() == 103);
}
#[test]
fn test_push_unique() {
let mut heap = PriorityQueue::from_vec(vec!(box 2, box 4, box 9));
assert_eq!(heap.len(), 3);
- assert!(*heap.top() == box 9);
+ assert!(*heap.top().unwrap() == box 9);
heap.push(box 11);
assert_eq!(heap.len(), 4);
- assert!(*heap.top() == box 11);
+ assert!(*heap.top().unwrap() == box 11);
heap.push(box 5);
assert_eq!(heap.len(), 5);
- assert!(*heap.top() == box 11);
+ assert!(*heap.top().unwrap() == box 11);
heap.push(box 27);
assert_eq!(heap.len(), 6);
- assert!(*heap.top() == box 27);
+ assert!(*heap.top().unwrap() == box 27);
heap.push(box 3);
assert_eq!(heap.len(), 7);
- assert!(*heap.top() == box 27);
+ assert!(*heap.top().unwrap() == box 27);
heap.push(box 103);
assert_eq!(heap.len(), 8);
- assert!(*heap.top() == box 103);
+ assert!(*heap.top().unwrap() == box 103);
}
#[test]
fn test_replace() {
let mut heap = PriorityQueue::from_vec(vec!(5, 5, 2, 1, 3));
assert_eq!(heap.len(), 5);
- assert_eq!(heap.replace(6), 5);
+ assert_eq!(heap.replace(6).unwrap(), 5);
assert_eq!(heap.len(), 5);
- assert_eq!(heap.replace(0), 6);
+ assert_eq!(heap.replace(0).unwrap(), 6);
assert_eq!(heap.len(), 5);
- assert_eq!(heap.replace(4), 5);
+ assert_eq!(heap.replace(4).unwrap(), 5);
assert_eq!(heap.len(), 5);
- assert_eq!(heap.replace(1), 4);
+ assert_eq!(heap.replace(1).unwrap(), 4);
assert_eq!(heap.len(), 5);
}
fn check_to_vec(mut data: Vec<int>) {
let heap = PriorityQueue::from_vec(data.clone());
- let mut v = heap.clone().to_vec();
+ let mut v = heap.clone().into_vec();
v.sort();
data.sort();
assert_eq!(v, data);
- assert_eq!(heap.to_sorted_vec(), data);
+ assert_eq!(heap.into_sorted_vec(), data);
}
#[test]
}
#[test]
- #[should_fail]
fn test_empty_pop() {
let mut heap: PriorityQueue<int> = PriorityQueue::new();
- heap.pop();
- }
-
- #[test]
- fn test_empty_maybe_pop() {
- let mut heap: PriorityQueue<int> = PriorityQueue::new();
- assert!(heap.maybe_pop().is_none());
+ assert!(heap.pop().is_none());
}
#[test]
- #[should_fail]
fn test_empty_top() {
let empty: PriorityQueue<int> = PriorityQueue::new();
- empty.top();
- }
-
- #[test]
- fn test_empty_maybe_top() {
- let empty: PriorityQueue<int> = PriorityQueue::new();
- assert!(empty.maybe_top().is_none());
+ assert!(empty.top().is_none());
}
#[test]
- #[should_fail]
fn test_empty_replace() {
let mut heap: PriorityQueue<int> = PriorityQueue::new();
- heap.replace(5);
+ heap.replace(5).is_none();
}
#[test]
let mut q: PriorityQueue<uint> = xs.as_slice().iter().rev().map(|&x| x).collect();
for &x in xs.iter() {
- assert_eq!(q.pop(), x);
+ assert_eq!(q.pop().unwrap(), x);
}
}
}
//! Implementations of the following traits:
//!
//! * `Not`
+//! * `BitAnd`
+//! * `BitOr`
+//! * `BitXor`
//! * `Ord`
//! * `TotalOrd`
//! * `Eq`
+//! * `TotalEq`
//! * `Default`
-//! * `Zero`
//!
//! A `to_bit` conversion function.
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-//! Types that provide interior mutability.
+//! Sharable mutable containers.
+//!
+//! Values of the `Cell` and `RefCell` types may be mutated through
+//! shared references (i.e. the common `&T` type), whereas most Rust
+//! types can only be mutated through unique (`&mut T`) references. We
+//! say that `Cell` and `RefCell` provide *interior mutability*, in
+//! contrast with typical Rust types that exhibit *inherited
+//! mutability*.
+//!
+//! Cell types come in two flavors: `Cell` and `RefCell`. `Cell`
+//! provides `get` and `set` methods that change the
+//! interior value with a single method call. `Cell` though is only
+//! compatible with types that implement `Copy`. For other types,
+//! one must use the `RefCell` type, acquiring a write lock before
+//! mutating.
+//!
+//! `RefCell` uses Rust's lifetimes to implement *dynamic borrowing*,
+//! a process whereby one can claim temporary, exclusive, mutable
+//! access to the inner value. Borrows for `RefCell`s are tracked *at
+//! runtime*, unlike Rust's native reference types which are entirely
+//! tracked statically, at compile time. Because `RefCell` borrows are
+//! dynamic it is possible to attempt to borrow a value that is
+//! already mutably borrowed; when this happens it results in task
+//! failure.
+//!
+//! # When to choose interior mutability
+//!
+//! The more common inherited mutability, where one must have unique
+//! access to mutate a value, is one of the key language elements that
+//! enables Rust to reason strongly about pointer aliasing, statically
+//! preventing crash bugs. Because of that, inherited mutability is
+//! preferred, and interior mutability is something of a last
+//! resort. Since cell types enable mutation where it would otherwise
+//! be disallowed though, there are occassions when interior
+//! mutability might be appropriate, or even *must* be used, e.g.
+//!
+//! * Introducing inherited mutability roots to shared types.
+//! * Implementation details of logically-immutable methods.
+//! * Mutating implementations of `clone`.
+//!
+//! ## Introducing inherited mutability roots to shared types
+//!
+//! Shared smart pointer types, including `Rc` and `Arc`, provide
+//! containers that can be cloned and shared between multiple parties.
+//! Because the contained values may be multiply-aliased, they can
+//! only be borrowed as shared references, not mutable references.
+//! Without cells it would be impossible to mutate data inside of
+//! shared boxes at all!
+//!
+//! It's very common then to put a `RefCell` inside shared pointer
+//! types to reintroduce mutability:
+//!
+//! ```
+//! extern crate collections;
+//!
+//! use collections::HashMap;
+//! use std::cell::RefCell;
+//! use std::rc::Rc;
+//!
+//! fn main() {
+//! let shared_map: Rc<RefCell<_>> = Rc::new(RefCell::new(HashMap::new()));
+//! shared_map.borrow_mut().insert("africa", 92388);
+//! shared_map.borrow_mut().insert("kyoto", 11837);
+//! shared_map.borrow_mut().insert("piccadilly", 11826);
+//! shared_map.borrow_mut().insert("marbles", 38);
+//! }
+//! ```
+//!
+//! ## Implementation details of logically-immutable methods
+//!
+//! Occasionally it may be desirable not to expose in an API that
+//! there is mutation happening "under the hood". This may be because
+//! logically the operation is immutable, but e.g. caching forces the
+//! implementation to perform mutation; or because you must employ
+//! mutation to implement a trait method that was originally defined
+//! to take `&self`.
+//!
+//! ```
+//! extern crate collections;
+//!
+//! use collections::HashMap;
+//! use std::cell::RefCell;
+//!
+//! struct Graph {
+//! edges: HashMap<uint, uint>,
+//! span_tree_cache: RefCell<Option<Vec<(uint, uint)>>>
+//! }
+//!
+//! impl Graph {
+//! fn minimum_spanning_tree(&self) -> Vec<(uint, uint)> {
+//! // Create a new scope to contain the lifetime of the
+//! // dynamic borrow
+//! {
+//! // Take a reference to the inside of cache cell
+//! let mut cache = self.span_tree_cache.borrow_mut();
+//! if cache.is_some() {
+//! return cache.get_ref().clone();
+//! }
+//!
+//! let span_tree = self.calc_span_tree();
+//! *cache = Some(span_tree);
+//! }
+//!
+//! // Recursive call to return the just-cached value.
+//! // Note that if we had not let the previous borrow
+//! // of the cache fall out of scope then the subsequent
+//! // recursive borrow would cause a dynamic task failure.
+//! // This is the major hazard of using `RefCell`.
+//! self.minimum_spanning_tree()
+//! }
+//! # fn calc_span_tree(&self) -> Vec<(uint, uint)> { vec![] }
+//! }
+//! # fn main() { }
+//! ```
+//!
+//! ## Mutating implementations of `clone`
+//!
+//! This is simply a special - but common - case of the previous:
+//! hiding mutability for operations that appear to be immutable.
+//! The `clone` method is expected to not change the source value, and
+//! is declared to take `&self`, not `&mut self`. Therefore any
+//! mutation that happens in the `clone` method must use cell
+//! types. For example, `Rc` maintains its reference counts within a
+//! `Cell`.
+//!
+//! ```
+//! use std::cell::Cell;
+//!
+//! struct Rc<T> {
+//! ptr: *mut RcBox<T>
+//! }
+//!
+//! struct RcBox<T> {
+//! value: T,
+//! refcount: Cell<uint>
+//! }
+//!
+//! impl<T> Clone for Rc<T> {
+//! fn clone(&self) -> Rc<T> {
+//! unsafe {
+//! (*self.ptr).refcount.set((*self.ptr).refcount.get() + 1);
+//! Rc { ptr: self.ptr }
+//! }
+//! }
+//! }
+//! ```
+//!
+// FIXME: Explain difference between Cell and RefCell
+// FIXME: Downsides to interior mutability
+// FIXME: Can't be shared between threads. Dynamic borrows
+// FIXME: Relationship to Atomic types and RWLock
use clone::Clone;
use cmp::Eq;
use super::Iterator;
/// Compare `a` and `b` for equality using `TotalEq`
- pub fn equals<A: TotalEq, T: Iterator<A>>(mut a: T, mut b: T) -> bool {
+ pub fn equals<A: TotalEq, T: Iterator<A>, S: Iterator<A>>(mut a: T, mut b: S) -> bool {
loop {
match (a.next(), b.next()) {
(None, None) => return true,
}
/// Order `a` and `b` lexicographically using `TotalOrd`
- pub fn cmp<A: TotalOrd, T: Iterator<A>>(mut a: T, mut b: T) -> cmp::Ordering {
+ pub fn cmp<A: TotalOrd, T: Iterator<A>, S: Iterator<A>>(mut a: T, mut b: S) -> cmp::Ordering {
loop {
match (a.next(), b.next()) {
(None, None) => return cmp::Equal,
}
/// Compare `a` and `b` for equality (Using partial equality, `Eq`)
- pub fn eq<A: Eq, T: Iterator<A>>(mut a: T, mut b: T) -> bool {
+ pub fn eq<A: Eq, T: Iterator<A>, S: Iterator<A>>(mut a: T, mut b: S) -> bool {
loop {
match (a.next(), b.next()) {
(None, None) => return true,
}
/// Compare `a` and `b` for nonequality (Using partial equality, `Eq`)
- pub fn ne<A: Eq, T: Iterator<A>>(mut a: T, mut b: T) -> bool {
+ pub fn ne<A: Eq, T: Iterator<A>, S: Iterator<A>>(mut a: T, mut b: S) -> bool {
loop {
match (a.next(), b.next()) {
(None, None) => return false,
}
/// Return `a` < `b` lexicographically (Using partial order, `Ord`)
- pub fn lt<A: Ord, T: Iterator<A>>(mut a: T, mut b: T) -> bool {
+ pub fn lt<A: Ord, T: Iterator<A>, S: Iterator<A>>(mut a: T, mut b: S) -> bool {
loop {
match (a.next(), b.next()) {
(None, None) => return false,
}
/// Return `a` <= `b` lexicographically (Using partial order, `Ord`)
- pub fn le<A: Ord, T: Iterator<A>>(mut a: T, mut b: T) -> bool {
+ pub fn le<A: Ord, T: Iterator<A>, S: Iterator<A>>(mut a: T, mut b: S) -> bool {
loop {
match (a.next(), b.next()) {
(None, None) => return true,
}
/// Return `a` > `b` lexicographically (Using partial order, `Ord`)
- pub fn gt<A: Ord, T: Iterator<A>>(mut a: T, mut b: T) -> bool {
+ pub fn gt<A: Ord, T: Iterator<A>, S: Iterator<A>>(mut a: T, mut b: S) -> bool {
loop {
match (a.next(), b.next()) {
(None, None) => return false,
}
/// Return `a` >= `b` lexicographically (Using partial order, `Ord`)
- pub fn ge<A: Ord, T: Iterator<A>>(mut a: T, mut b: T) -> bool {
+ pub fn ge<A: Ord, T: Iterator<A>, S: Iterator<A>>(mut a: T, mut b: S) -> bool {
loop {
match (a.next(), b.next()) {
(None, None) => return true,
assert!(gt(c.iter(), b.iter()) == (c[0] > b[0]));
assert!(ge(c.iter(), b.iter()) == (c[0] >= b[0]));
}
+
+ #[test]
+ fn test_multi_iter() {
+ use slice::ImmutableVector;
+ use iter::DoubleEndedIterator;
+ let xs = [1i,2,3,4];
+ let ys = [4i,3,2,1];
+ assert!(eq(xs.iter(), ys.iter().rev()));
+ assert!(lt(xs.iter(), xs.iter().skip(2)));
+ }
}
#[cfg(test)]
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-//! The Rust core library
+//! The Rust Core Library
//!
-//! This library is meant to represent the core functionality of rust that is
-//! maximally portable to other platforms. To that extent, this library has no
-//! knowledge of things like allocation, threads, I/O, etc. This library is
-//! built on the assumption of a few existing symbols:
+//! The Rust Core Library is the dependency-free foundation of [The
+//! Rust Standard Library](../std/index.html). It is the portable glue
+//! between the language and its libraries, defining the intrinsic and
+//! primitive building blocks of all Rust code. It links to no
+//! upstream libraries, no system libraries, and no libc.
+//!
+//! The core library is *minimal*: it isn't even aware of heap allocation,
+//! nor does it provide concurrency or I/O. These things require
+//! platform integration, and this library is platform-agnostic.
+//!
+//! *It is not recommended to use the core library*. The stable
+//! functionality of libcore is reexported from the
+//! [standard library](../std/index.html). The composition of this library is
+//! subject to change over time; only the interface exposed through libstd is
+//! intended to be stable.
+//!
+//! # How to use the core library
+//!
+// FIXME: Fill me in with more detail when the interface settles
+//! This library is built on the assumption of a few existing symbols:
//!
//! * `memcpy`, `memcmp`, `memset` - These are core memory routines which are
//! often generated by LLVM. Additionally, this library can make explicit
-//! calls to these funcitons. Their signatures are the same as found in C.
+//! calls to these functions. Their signatures are the same as found in C.
//! These functions are often provided by the system libc, but can also be
//! provided by `librlibc` which is distributed with the standard rust
//! distribution.
//!
//! * `rust_begin_unwind` - This function takes three arguments, a
-//! `&fmt::Arguments`, a `&str`, and a `uint. These three arguments dictate
+//! `&fmt::Arguments`, a `&str`, and a `uint`. These three arguments dictate
//! the failure message, the file at which failure was invoked, and the line.
//! It is up to consumers of this core library to define this failure
//! function; it is only required to never return.
//!
-//! Currently, it is *not* recommended to use the core library. The stable
-//! functionality of libcore is exported directly into the
-//! [standard library](../std/index.html). The composition of this library is
-//! subject to change over time, only the interface exposed through libstd is
-//! intended to be stable.
#![crate_id = "core#0.11.0-pre"]
#![license = "MIT/ASL2"]
//! Numeric traits and functions for generic mathematics
//!
//! These are implemented for the primitive numeric types in `std::{u8, u16,
-//! u32, u64, uint, i8, i16, i32, i64, int, f32, f64, float}`.
+//! u32, u64, uint, i8, i16, i32, i64, int, f32, f64}`.
#![allow(missing_doc)]
pub trait Signed: Num + Neg<Self> {
/// Computes the absolute value.
///
- /// For float, f32, and f64, `NaN` will be returned if the number is `NaN`.
+ /// For `f32` and `f64`, `NaN` will be returned if the number is `NaN`.
fn abs(&self) -> Self;
/// The positive difference of two numbers.
/// Returns the sign of the number.
///
- /// For `float`, `f32`, `f64`:
- /// * `1.0` if the number is positive, `+0.0` or `INFINITY`
- /// * `-1.0` if the number is negative, `-0.0` or `NEG_INFINITY`
- /// * `NaN` if the number is `NaN`
+ /// For `f32` and `f64`:
+ ///
+ /// * `1.0` if the number is positive, `+0.0` or `INFINITY`
+ /// * `-1.0` if the number is negative, `-0.0` or `NEG_INFINITY`
+ /// * `NaN` if the number is `NaN`
///
/// For `int`:
- /// * `0` if the number is zero
- /// * `1` if the number is positive
- /// * `-1` if the number is negative
+ ///
+ /// * `0` if the number is zero
+ /// * `1` if the number is positive
+ /// * `-1` if the number is negative
fn signum(&self) -> Self;
/// Returns true if the number is positive and false if the number is zero or negative.
/// Computes the absolute value.
///
-/// For float, f32, and f64, `NaN` will be returned if the number is `NaN`
+/// For `f32` and `f64`, `NaN` will be returned if the number is `NaN`
#[inline(always)]
pub fn abs<T: Signed>(value: T) -> T {
value.abs()
/// Returns the sign of the number.
///
-/// For float, f32, f64:
-/// - `1.0` if the number is positive, `+0.0` or `INFINITY`
-/// - `-1.0` if the number is negative, `-0.0` or `NEG_INFINITY`
-/// - `NAN` if the number is `NAN`
+/// For `f32` and `f64`:
+///
+/// * `1.0` if the number is positive, `+0.0` or `INFINITY`
+/// * `-1.0` if the number is negative, `-0.0` or `NEG_INFINITY`
+/// * `NaN` if the number is `NaN`
///
/// For int:
-/// - `0` if the number is zero
-/// - `1` if the number is positive
-/// - `-1` if the number is negative
+///
+/// * `0` if the number is zero
+/// * `1` if the number is positive
+/// * `-1` if the number is negative
#[inline(always)] pub fn signum<T: Signed>(value: T) -> T { value.signum() }
/// A trait for values which cannot be negative
/*!
*
- * Traits representing built-in operators, useful for overloading
+ * Overloadable operators
*
* Implementing these traits allows you to get an effect similar to
* overloading operators.
/// Unwraps a result, yielding the content of an `Ok`.
/// If the value is an `Err` then it calls `op` with its value.
#[inline]
- pub fn unwrap_or_handle(self, op: |E| -> T) -> T {
+ pub fn unwrap_or_else(self, op: |E| -> T) -> T {
match self {
Ok(t) => t,
Err(e) => op(e)
}
}
+
+ /// Deprecated name for `unwrap_or_else()`.
+ #[deprecated = "replaced by .unwrap_or_else()"]
+ #[inline]
+ pub fn unwrap_or_handle(self, op: |E| -> T) -> T {
+ self.unwrap_or_else(op)
+ }
}
impl<T, E: Show> Result<T, E> {
let ok: Result<int, ~str> = Ok(100);
let ok_err: Result<int, ~str> = Err("I got this.".to_owned());
- assert_eq!(ok.unwrap_or_handle(handler), 100);
- assert_eq!(ok_err.unwrap_or_handle(handler), 50);
+ assert_eq!(ok.unwrap_or_else(handler), 100);
+ assert_eq!(ok_err.unwrap_or_else(handler), 50);
}
#[test]
}
let bad_err: Result<int, ~str> = Err("Unrecoverable mess.".to_owned());
- let _ : int = bad_err.unwrap_or_handle(handler);
+ let _ : int = bad_err.unwrap_or_else(handler);
}
}
}
fn find_fallback_in_self_type(&mut self, name: Name) -> FallbackSuggestion {
+ #[deriving(Eq)]
+ enum FallbackChecks {
+ Everything,
+ OnlyTraitAndStatics
+ }
+
+ fn extract_path_and_node_id(t: &Ty, allow: FallbackChecks)
+ -> Option<(Path, NodeId, FallbackChecks)> {
+ match t.node {
+ TyPath(ref path, _, node_id) => Some((path.clone(), node_id, allow)),
+ TyPtr(mut_ty) => extract_path_and_node_id(mut_ty.ty, OnlyTraitAndStatics),
+ TyRptr(_, mut_ty) => extract_path_and_node_id(mut_ty.ty, allow),
+ // This doesn't handle the remaining `Ty` variants as they are not
+ // that commonly the self_type, it might be interesting to provide
+ // support for those in future.
+ _ => None,
+ }
+ }
+
fn get_module(this: &mut Resolver, span: Span, ident_path: &[ast::Ident])
-> Option<Rc<Module>> {
let root = this.current_module.clone();
}
}
- let (path, node_id) = match self.current_self_type {
- Some(ref ty) => match ty.node {
- TyPath(ref path, _, node_id) => (path.clone(), node_id),
- _ => unreachable!(),
+ let (path, node_id, allowed) = match self.current_self_type {
+ Some(ref ty) => match extract_path_and_node_id(ty, Everything) {
+ Some(x) => x,
+ None => return NoSuggestion,
},
None => return NoSuggestion,
};
- // Look for a field with the same name in the current self_type.
- match self.def_map.borrow().find(&node_id) {
- Some(&DefTy(did))
- | Some(&DefStruct(did))
- | Some(&DefVariant(_, did, _)) => match self.structs.find(&did) {
- None => {}
- Some(fields) => {
- if fields.iter().any(|&field_name| name == field_name) {
- return Field;
+ if allowed == Everything {
+ // Look for a field with the same name in the current self_type.
+ match self.def_map.borrow().find(&node_id) {
+ Some(&DefTy(did))
+ | Some(&DefStruct(did))
+ | Some(&DefVariant(_, did, _)) => match self.structs.find(&did) {
+ None => {}
+ Some(fields) => {
+ if fields.iter().any(|&field_name| name == field_name) {
+ return Field;
+ }
}
- }
- },
- _ => {} // Self type didn't resolve properly
+ },
+ _ => {} // Self type didn't resolve properly
+ }
}
let ident_path = path.segments.iter().map(|seg| seg.identifier).collect::<Vec<_>>();
FromTrait(_) => unreachable!()
}
}
- Some(DefMethod(_, None)) => return Method,
- Some(DefMethod(_, _)) => return TraitMethod,
+ Some(DefMethod(_, None)) if allowed == Everything => return Method,
+ Some(DefMethod(_, Some(_))) => return TraitMethod,
_ => ()
}
}
sub.repr(self.tcx),
sup.repr(self.tcx)));
}
+ (_, ReStatic) => {
+ // all regions are subregions of static, so we can ignore this
+ }
(ReInfer(ReVar(sub_id)), ReInfer(ReVar(sup_id))) => {
self.add_constraint(ConstrainVarSubVar(sub_id, sup_id), origin);
}
//!
//! ## Intrinsic types and operations
//!
-//! The [`ptr`](../core/ptr/index.html), [`mem`](../core/mem/index.html),
-//! and [`cast`](../core/cast/index.html) modules deal with unsafe pointers,
-//! memory manipulation, and coercion.
+//! The [`ptr`](../core/ptr/index.html) and [`mem`](../core/mem/index.html)
+//! modules deal with unsafe pointers and memory manipulation.
//! [`kinds`](../core/kinds/index.html) defines the special built-in traits,
//! and [`raw`](../core/raw/index.html) the runtime representation of Rust types.
//! These are some of the lowest-level building blocks of Rust
#[cfg(test)] pub use realstd::cmp;
#[cfg(test)] pub use realstd::ty;
-#[cfg(not(test))] pub use core::cmp;
-#[cfg(not(test))] pub use core::kinds;
-#[cfg(not(test))] pub use core::ops;
-#[cfg(not(test))] pub use core::ty;
+
+// NB: These reexports are in the order they should be listed in rustdoc
pub use core::any;
pub use core::bool;
pub use core::cell;
pub use core::char;
pub use core::clone;
+#[cfg(not(test))] pub use core::cmp;
pub use core::container;
pub use core::default;
pub use core::intrinsics;
pub use core::iter;
+#[cfg(not(test))] pub use core::kinds;
pub use core::mem;
+#[cfg(not(test))] pub use core::ops;
pub use core::ptr;
pub use core::raw;
pub use core::tuple;
+#[cfg(not(test))] pub use core::ty;
pub use core::result;
pub use alloc::owned;
/// # Example
///
/// ```
- /// let rust = bytes!("r", 'u', "st");
+ /// let rust = bytes!("r", 'u', "st", 255);
/// assert_eq!(rust[1], 'u' as u8);
+ /// assert_eq!(rust[5], 255);
/// ```
#[macro_export]
macro_rules! bytes( ($($e:expr),*) => ({ /* compiler built-in */ }) )
//! Numeric traits and functions for generic mathematics
//!
//! These are implemented for the primitive numeric types in `std::{u8, u16,
-//! u32, u64, uint, i8, i16, i32, i64, int, f32, f64, float}`.
+//! u32, u64, uint, i8, i16, i32, i64, int, f32, f64}`.
#![allow(missing_doc)]
match w.dst {
Terminal(ref mut t) => {
try!(t.attr(color));
- try!(t.write_str(msg));
- try!(t.reset());
+ // If `msg` ends in a newline, we need to reset the color before
+ // the newline. We're making the assumption that we end up writing
+ // to a `LineBufferedWriter`, which means that emitting the reset
+ // after the newline ends up buffering the reset until we print
+ // another line or exit. Buffering the reset is a problem if we're
+ // sharing the terminal with any other programs (e.g. other rustc
+ // instances via `make -jN`).
+ //
+ // Note that if `msg` contains any internal newlines, this will
+ // result in the `LineBufferedWriter` flushing twice instead of
+ // once, which still leaves the opportunity for interleaved output
+ // to be miscolored. We assume this is rare enough that we don't
+ // have to worry about it.
+ if msg.ends_with("\n") {
+ try!(t.write_str(msg.slice_to(msg.len()-1)));
+ try!(t.reset());
+ try!(t.write_str("\n"));
+ } else {
+ try!(t.write_str(msg));
+ try!(t.reset());
+ }
Ok(())
}
Raw(ref mut w) => {
html_favicon_url = "http://www.rust-lang.org/favicon.ico",
html_root_url = "http://static.rust-lang.org/doc/master")]
-#![feature(asm, macro_rules)]
+#![feature(asm, macro_rules, phase)]
#![deny(deprecated_owned_vector)]
extern crate collections;
// colons. This way if some test runner wants to arrange the tests
// hierarchically it may.
-#[deriving(Clone)]
+#[deriving(Clone, Eq, TotalEq, Hash)]
pub enum TestName {
StaticTestName(&'static str),
DynTestName(StrBuf)
}
}
+impl fmt::Show for TestFn {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ f.write(match *self {
+ StaticTestFn(..) => "StaticTestFn(..)",
+ StaticBenchFn(..) => "StaticBenchFn(..)",
+ StaticMetricFn(..) => "StaticMetricFn(..)",
+ DynTestFn(..) => "DynTestFn(..)",
+ DynMetricFn(..) => "DynMetricFn(..)",
+ DynBenchFn(..) => "DynBenchFn(..)"
+ }.as_bytes())
+ }
+}
+
/// Manager of the benchmarking runs.
///
/// This is feed into functions marked with `#[bench]` to allow for
// The definition of a single test. A test runner will run a list of
// these.
-#[deriving(Clone)]
+#[deriving(Clone, Show, Eq, TotalEq, Hash)]
pub struct TestDesc {
pub name: TestName,
pub ignore: bool,
pub should_fail: bool,
}
+#[deriving(Show)]
pub struct TestDescAndFn {
pub desc: TestDesc,
pub testfn: TestFn,
pub fn test_main_static(args: &[StrBuf], tests: &[TestDescAndFn]) {
let owned_tests = tests.iter().map(|t| {
match t.testfn {
- StaticTestFn(f) =>
- TestDescAndFn { testfn: StaticTestFn(f), desc: t.desc.clone() },
-
- StaticBenchFn(f) =>
- TestDescAndFn { testfn: StaticBenchFn(f), desc: t.desc.clone() },
-
- _ => {
- fail!("non-static tests passed to test::test_main_static");
- }
+ StaticTestFn(f) => TestDescAndFn { testfn: StaticTestFn(f), desc: t.desc.clone() },
+ StaticBenchFn(f) => TestDescAndFn { testfn: StaticBenchFn(f), desc: t.desc.clone() },
+ _ => fail!("non-static tests passed to test::test_main_static")
}
}).collect();
test_main(args, owned_tests)
None => None,
Some(s) => {
let mut it = s.as_slice().split('.');
- match (it.next().and_then(from_str), it.next().and_then(from_str), it.next()) {
- (Some(a), Some(b), None) => Some((a, b)),
+ match (it.next().and_then(from_str::<uint>), it.next().and_then(from_str::<uint>),
+ it.next()) {
+ (Some(a), Some(b), None) => {
+ if a <= 0 || a > b {
+ fail!("tried to run shard {a}.{b}, but {a} is out of bounds \
+ (should be between 1 and {b}", a=a, b=b)
+ }
+ Some((a, b))
+ }
_ => None,
}
}
}
// A simple console test runner
-pub fn run_tests_console(opts: &TestOpts,
- tests: Vec<TestDescAndFn> ) -> io::IoResult<bool> {
- fn callback<T: Writer>(event: &TestEvent,
- st: &mut ConsoleTestState<T>) -> io::IoResult<()> {
+pub fn run_tests_console(opts: &TestOpts, tests: Vec<TestDescAndFn> ) -> io::IoResult<bool> {
+
+ fn callback<T: Writer>(event: &TestEvent, st: &mut ConsoleTestState<T>) -> io::IoResult<()> {
match (*event).clone() {
TeFiltered(ref filtered_tests) => st.write_run_start(filtered_tests.len()),
TeWait(ref test, padding) => st.write_test_start(test, padding),
}
}
}
+
let mut st = try!(ConsoleTestState::new(opts, None::<StdWriter>));
fn len_if_padded(t: &TestDescAndFn) -> uint {
match t.testfn.padding() {
}
}
-pub fn filter_tests(
- opts: &TestOpts,
- tests: Vec<TestDescAndFn> ) -> Vec<TestDescAndFn> {
+pub fn filter_tests(opts: &TestOpts, tests: Vec<TestDescAndFn>) -> Vec<TestDescAndFn> {
let mut filtered = tests;
// Remove tests that don't match the test filter
None => filtered,
Some((a,b)) => {
filtered.move_iter().enumerate()
- .filter(|&(i,_)| i % b == a)
+ // note: using a - 1 so that the valid shards, for example, are
+ // 1.2 and 2.2 instead of 0.2 and 1.2
+ .filter(|&(i,_)| i % b == (a - 1))
.map(|(_,t)| t)
.collect()
}
--- /dev/null
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+trait Foo {
+ fn bar(&self);
+ fn baz(&self) { }
+ fn bah(_: Option<Self>) { }
+}
+
+struct BarTy {
+ x : int,
+ y : f64,
+}
+
+impl BarTy {
+ fn a() {}
+ fn b(&self) {}
+}
+
+impl Foo for *BarTy {
+ fn bar(&self) {
+ baz();
+ //~^ ERROR: unresolved name `baz`. Did you mean to call `self.baz`?
+ a;
+ //~^ ERROR: unresolved name `a`. Did you mean to call `BarTy::a`?
+ }
+}
+
+impl<'a> Foo for &'a BarTy {
+ fn bar(&self) {
+ baz();
+ //~^ ERROR: unresolved name `baz`. Did you mean to call `self.baz`?
+ x;
+ //~^ ERROR: unresolved name `x`. Did you mean `self.x`?
+ y;
+ //~^ ERROR: unresolved name `y`. Did you mean `self.y`?
+ a;
+ //~^ ERROR: unresolved name `a`. Did you mean to call `BarTy::a`?
+ bah;
+ //~^ ERROR: unresolved name `bah`. Did you mean to call `Foo::bah`?
+ b;
+ //~^ ERROR: unresolved name `b`. Did you mean to call `self.b`?
+ }
+}
+
+impl<'a> Foo for &'a mut BarTy {
+ fn bar(&self) {
+ baz();
+ //~^ ERROR: unresolved name `baz`. Did you mean to call `self.baz`?
+ x;
+ //~^ ERROR: unresolved name `x`. Did you mean `self.x`?
+ y;
+ //~^ ERROR: unresolved name `y`. Did you mean `self.y`?
+ a;
+ //~^ ERROR: unresolved name `a`. Did you mean to call `BarTy::a`?
+ bah;
+ //~^ ERROR: unresolved name `bah`. Did you mean to call `Foo::bah`?
+ b;
+ //~^ ERROR: unresolved name `b`. Did you mean to call `self.b`?
+ }
+}
+
+impl Foo for Box<BarTy> {
+ fn bar(&self) {
+ baz();
+ //~^ ERROR: unresolved name `baz`. Did you mean to call `self.baz`?
+ bah;
+ //~^ ERROR: unresolved name `bah`. Did you mean to call `Foo::bah`?
+ }
+}
+
+impl Foo for *int {
+ fn bar(&self) {
+ baz();
+ //~^ ERROR: unresolved name `baz`. Did you mean to call `self.baz`?
+ bah;
+ //~^ ERROR: unresolved name `bah`. Did you mean to call `Foo::bah`?
+ }
+}
+
+impl<'a> Foo for &'a int {
+ fn bar(&self) {
+ baz();
+ //~^ ERROR: unresolved name `baz`. Did you mean to call `self.baz`?
+ bah;
+ //~^ ERROR: unresolved name `bah`. Did you mean to call `Foo::bah`?
+ }
+}
+
+impl<'a> Foo for &'a mut int {
+ fn bar(&self) {
+ baz();
+ //~^ ERROR: unresolved name `baz`. Did you mean to call `self.baz`?
+ bah;
+ //~^ ERROR: unresolved name `bah`. Did you mean to call `Foo::bah`?
+ }
+}
+
+impl Foo for Box<int> {
+ fn bar(&self) {
+ baz();
+ //~^ ERROR: unresolved name `baz`. Did you mean to call `self.baz`?
+ bah;
+ //~^ ERROR: unresolved name `bah`. Did you mean to call `Foo::bah`?
+ }
+}
--- /dev/null
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// In this fn, the type `F` is a function that takes a reference to a
+// struct and returns another reference with the same lifetime.
+//
+// Meanwhile, the bare fn `foo` takes a reference to a struct with
+// *ANY* lifetime and returns a reference with the 'static lifetime.
+// This can safely be considered to be an instance of `F` because all
+// lifetimes are sublifetimes of 'static.
+
+#![allow(dead_code)]
+#![allow(unused_variable)]
+
+struct S;
+
+// Given 'cx, return 'cx
+type F = fn<'cx>(&'cx S) -> &'cx S;
+fn want_F(f: F) { }
+
+// Given anything, return 'static
+type G = fn<'cx>(&'cx S) -> &'static S;
+fn want_G(f: G) { }
+
+// Should meet both.
+fn foo(x: &S) -> &'static S {
+ fail!()
+}
+
+// Should meet both.
+fn bar<'a,'b>(x: &'a S) -> &'b S {
+ fail!()
+}
+
+// Meets F, but not G.
+fn baz<'a>(x: &'a S) -> &'a S {
+ fail!()
+}
+
+fn supply_F() {
+ want_F(foo);
+ want_F(bar);
+ want_F(baz);
+}
+
+fn supply_G() {
+ want_G(foo);
+ want_G(bar);
+ want_G(baz); //~ ERROR expected concrete lifetime
+}
+
+pub fn main() {
+}
--- /dev/null
+-include ../tools.mk
+
+all:
+ # Running all the shards should hit every test
+ $(RUSTC) --test main.rs
+ $(call RUN,main) --test-shard 1.2 | grep "test_1 ... ok"
+ $(call RUN,main) --test-shard 2.2 | grep "test_2 ... ok"
--- /dev/null
+// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![crate_type = "lib"]
+
+#[test]
+fn test_1() { }
+#[test]
+fn test_2() { }
--- /dev/null
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+trait Foo {
+ fn bar(&self);
+ fn baz(&self) { }
+ fn bah(_: Option<Self>) { }
+}
+
+struct BarTy {
+ x : int,
+ y : f64,
+}
+
+impl BarTy {
+ fn a() {}
+ fn b(&self) {}
+}
+
+// If these fail, it's necessary to update middle::resolve and the cfail tests.
+impl Foo for *BarTy {
+ fn bar(&self) {
+ self.baz();
+ BarTy::a();
+ Foo::bah(None::<*BarTy>);
+ }
+}
+
+// If these fail, it's necessary to update middle::resolve and the cfail tests.
+impl<'a> Foo for &'a BarTy {
+ fn bar(&self) {
+ self.baz();
+ self.x;
+ self.y;
+ BarTy::a();
+ Foo::bah(None::<&BarTy>);
+ self.b();
+ }
+}
+
+// If these fail, it's necessary to update middle::resolve and the cfail tests.
+impl<'a> Foo for &'a mut BarTy {
+ fn bar(&self) {
+ self.baz();
+ self.x;
+ self.y;
+ BarTy::a();
+ Foo::bah(None::<&mut BarTy>);
+ self.b();
+ }
+}
+
+// If these fail, it's necessary to update middle::resolve and the cfail tests.
+impl Foo for Box<BarTy> {
+ fn bar(&self) {
+ self.baz();
+ Foo::bah(None::<Box<BarTy>>);
+ }
+}
+
+// If these fail, it's necessary to update middle::resolve and the cfail tests.
+impl Foo for *int {
+ fn bar(&self) {
+ self.baz();
+ Foo::bah(None::<*int>);
+ }
+}
+
+// If these fail, it's necessary to update middle::resolve and the cfail tests.
+impl<'a> Foo for &'a int {
+ fn bar(&self) {
+ self.baz();
+ Foo::bah(None::<&int>);
+ }
+}
+
+// If these fail, it's necessary to update middle::resolve and the cfail tests.
+impl<'a> Foo for &'a mut int {
+ fn bar(&self) {
+ self.baz();
+ Foo::bah(None::<&mut int>);
+ }
+}
+
+// If these fail, it's necessary to update middle::resolve and the cfail tests.
+impl Foo for Box<int> {
+ fn bar(&self) {
+ self.baz();
+ Foo::bah(None::<Box<int>>);
+ }
+}
+
+fn main() {}