]> git.lizzy.rs Git - rust.git/commitdiff
auto merge of #14293 : alexcrichton/rust/weak-lang-items, r=brson
authorbors <bors@rust-lang.org>
Wed, 21 May 2014 04:36:25 +0000 (21:36 -0700)
committerbors <bors@rust-lang.org>
Wed, 21 May 2014 04:36:25 +0000 (21:36 -0700)
This commit is part of the ongoing libstd facade efforts (cc #13851). The
compiler now recognizes some language items as "extern { fn foo(...); }" and
will automatically perform the following actions:

1. The foreign function has a pre-defined name.
2. The crate and downstream crates can only be built as rlibs until a crate
   defines the lang item itself.
3. The actual lang item has a pre-defined name.

This is essentially nicer compiler support for the hokey
core-depends-on-std-failure scheme today, but it is implemented the same way.
The details are a little more hidden under the covers.

In addition to failure, this commit promotes the eh_personality and
rust_stack_exhausted functions to official lang items. The compiler can generate
calls to these functions, causing linkage errors if they are left undefined. The
checking for these items is not as precise as it could be. Crates compiling with
`-Z no-landing-pads` will not need the eh_personality lang item, and crates
compiling with no split stacks won't need the stack exhausted lang item. For
ease, however, these items are checked for presence in all final outputs of the
compiler.

It is quite easy to define dummy versions of the functions necessary:

    #[lang = "stack_exhausted"]
    extern fn stack_exhausted() { /* ... */ }

    #[lang = "eh_personality"]
    extern fn eh_personality() { /* ... */ }

cc #11922, rust_stack_exhausted is now a lang item
cc #13851, libcollections is blocked on eh_personality becoming weak

30 files changed:
configure
mk/platform.mk
src/compiletest/common.rs
src/compiletest/compiletest.rs
src/compiletest/errors.rs
src/compiletest/runtest.rs
src/doc/rust.md
src/doc/tutorial.md
src/libcollections/bitv.rs
src/libcollections/dlist.rs
src/libcollections/priority_queue.rs
src/libcore/bool.rs
src/libcore/cell.rs
src/libcore/iter.rs
src/libcore/lib.rs
src/libcore/num/mod.rs
src/libcore/ops.rs
src/libcore/result.rs
src/librustc/middle/resolve.rs
src/librustc/middle/typeck/infer/region_inference/mod.rs
src/libstd/lib.rs
src/libstd/macros.rs
src/libstd/num/mod.rs
src/libsyntax/diagnostic.rs
src/libtest/lib.rs
src/test/compile-fail/issue-14254.rs [new file with mode: 0644]
src/test/compile-fail/regions-fn-subtyping-return-static.rs [new file with mode: 0644]
src/test/run-make/test-shard-completeness/Makefile [new file with mode: 0644]
src/test/run-make/test-shard-completeness/main.rs [new file with mode: 0644]
src/test/run-pass/issue-14254.rs [new file with mode: 0644]

index 3ab71f762f236e6c7baa7010af3de0b184a68a72..f4cac4cbe85ae261c13326cd90e7aeef28016d25 100755 (executable)
--- a/configure
+++ b/configure
@@ -223,6 +223,30 @@ opt() {
      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
@@ -621,7 +645,7 @@ then
             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
 
@@ -646,41 +670,101 @@ then
     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%/}
@@ -742,11 +826,6 @@ do
     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'`
@@ -961,7 +1040,7 @@ do
             ;;
         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"
@@ -991,6 +1070,16 @@ do
 
             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"
@@ -1073,7 +1162,6 @@ putvar CFG_PREFIX
 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
@@ -1084,7 +1172,7 @@ putvar CFG_DISABLE_INJECT_STD_VERSION
 
 # 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
index 76c9debba8016be85384c8257a7712b30f083526..ecc4c33d154841e80fceb022a67fafa549d3710e 100644 (file)
@@ -81,57 +81,27 @@ CFG_DEPEND_FLAGS = -MMD -MP -MT $(1) -MF $(1:%.o=%.d)
 
 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
@@ -173,9 +143,9 @@ CFG_LIB_NAME_i686-unknown-linux-gnu=lib$(1).so
 CFG_STATIC_LIB_NAME_i686-unknown-linux-gnu=lib$(1).a
 CFG_LIB_GLOB_i686-unknown-linux-gnu=lib$(1)-*.so
 CFG_LIB_DSYM_GLOB_i686-unknown-linux-gnu=lib$(1)-*.dylib.dSYM
-CFG_CFLAGS_i686-unknown-linux-gnu := -m32
-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
@@ -203,9 +173,9 @@ AR_arm-apple-darwin = $(shell xcrun -find -sdk iphoneos ar)
 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 :=
@@ -232,9 +202,9 @@ CFG_LIB_NAME_x86_64-apple-darwin=lib$(1).dylib
 CFG_STATIC_LIB_NAME_x86_64-apple-darwin=lib$(1).a
 CFG_LIB_GLOB_x86_64-apple-darwin=lib$(1)-*.dylib
 CFG_LIB_DSYM_GLOB_x86_64-apple-darwin=lib$(1)-*.dylib.dSYM
-CFG_CFLAGS_x86_64-apple-darwin := -m64 -arch x86_64
-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 :=
@@ -260,9 +230,9 @@ CFG_LIB_NAME_i686-apple-darwin=lib$(1).dylib
 CFG_STATIC_LIB_NAME_i686-apple-darwin=lib$(1).a
 CFG_LIB_GLOB_i686-apple-darwin=lib$(1)-*.dylib
 CFG_LIB_DSYM_GLOB_i686-apple-darwin=lib$(1)-*.dylib.dSYM
-CFG_CFLAGS_i686-apple-darwin := -m32 -arch i386
-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 :=
@@ -288,9 +258,9 @@ CFG_LIB_NAME_arm-linux-androideabi=lib$(1).so
 CFG_STATIC_LIB_NAME_arm-linux-androideabi=lib$(1).a
 CFG_LIB_GLOB_arm-linux-androideabi=lib$(1)-*.so
 CFG_LIB_DSYM_GLOB_arm-linux-androideabi=lib$(1)-*.dylib.dSYM
-CFG_CFLAGS_arm-linux-androideabi := -D__arm__ -DANDROID -D__ANDROID__
-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
@@ -319,9 +289,9 @@ CFG_LIB_NAME_arm-unknown-linux-gnueabihf=lib$(1).so
 CFG_STATIC_LIB_NAME_arm-unknown-linux-gnueabihf=lib$(1).a
 CFG_LIB_GLOB_arm-unknown-linux-gnueabihf=lib$(1)-*.so
 CFG_LIB_DSYM_GLOB_arm-unknown-linux-gnueabihf=lib$(1)-*.dylib.dSYM
-CFG_CFLAGS_arm-unknown-linux-gnueabihf := -D__arm__
-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
@@ -350,9 +320,9 @@ CFG_LIB_NAME_arm-unknown-linux-gnueabi=lib$(1).so
 CFG_STATIC_LIB_NAME_arm-unknown-linux-gnueabi=lib$(1).a
 CFG_LIB_GLOB_arm-unknown-linux-gnueabi=lib$(1)-*.so
 CFG_LIB_DSYM_GLOB_arm-unknown-linux-gnueabi=lib$(1)-*.dylib.dSYM
-CFG_CFLAGS_arm-unknown-linux-gnueabi := -D__arm__ -mfpu=vfp
-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
@@ -380,9 +350,9 @@ CFG_LIB_NAME_mips-unknown-linux-gnu=lib$(1).so
 CFG_STATIC_LIB_NAME_mips-unknown-linux-gnu=lib$(1).a
 CFG_LIB_GLOB_mips-unknown-linux-gnu=lib$(1)-*.so
 CFG_LIB_DSYM_GLOB_mips-unknown-linux-gnu=lib$(1)-*.dylib.dSYM
-CFG_CFLAGS_mips-unknown-linux-gnu := -mips32r2 -msoft-float -mabi=32 -mno-compact-eh
-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
@@ -409,9 +379,9 @@ CFG_LIB_NAME_i686-pc-mingw32=$(1).dll
 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 :=
@@ -438,9 +408,9 @@ CFG_LIB_NAME_i586-mingw32msvc=$(1).dll
 CFG_STATIC_LIB_NAME_i586-mingw32msvc=$(1).lib
 CFG_LIB_GLOB_i586-mingw32msvc=$(1)-*.dll
 CFG_LIB_DSYM_GLOB_i586-mingw32msvc=$(1)-*.dylib.dSYM
-CFG_CFLAGS_i586-mingw32msvc := -march=i586 -m32
-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 :=
@@ -469,9 +439,9 @@ CFG_LIB_NAME_i686-w64-mingw32=$(1).dll
 CFG_STATIC_LIB_NAME_i686-w64-mingw32=$(1).lib
 CFG_LIB_GLOB_i686-w64-mingw32=$(1)-*.dll
 CFG_LIB_DSYM_GLOB_i686-w64-mingw32=$(1)-*.dylib.dSYM
-CFG_CFLAGS_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 :=
@@ -499,9 +469,9 @@ CFG_LIB_NAME_x86_64-w64-mingw32=$(1).dll
 CFG_STATIC_LIB_NAME_x86_64-w64-mingw32=$(1).lib
 CFG_LIB_GLOB_x86_64-w64-mingw32=$(1)-*.dll
 CFG_LIB_DSYM_GLOB_x86_64-w64-mingw32=$(1)-*.dylib.dSYM
-CFG_CFLAGS_x86_64-w64-mingw32 := -m64 -D_WIN32_WINNT=0x0600
-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 :=
@@ -528,8 +498,8 @@ CFG_LIB_NAME_x86_64-unknown-freebsd=lib$(1).so
 CFG_STATIC_LIB_NAME_x86_64-unknown-freebsd=lib$(1).a
 CFG_LIB_GLOB_x86_64-unknown-freebsd=lib$(1)-*.so
 CFG_LIB_DSYM_GLOB_x86_64-unknown-freebsd=$(1)-*.dylib.dSYM
-CFG_CFLAGS_x86_64-unknown-freebsd := -I/usr/local/include
-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
index a7f693da6cceceff6948bd85f6055cb14cce2ba2..1c629e5a5fd071355b1259695d86cb1d5d9ec441 100644 (file)
@@ -1,4 +1,4 @@
-// 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.
 //
@@ -91,6 +91,9 @@ pub struct Config {
     // 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>,
 
@@ -144,5 +147,4 @@ pub struct Config {
 
     // Explain what's going on
     pub verbose: bool
-
 }
index 3fb354a786768250b688f9cad6e6089839766606..db9cf358a9b99db7e516c5dd29159ecf69ac832d 100644 (file)
@@ -1,4 +1,4 @@
-// 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.
 //
@@ -33,6 +33,7 @@
 use common::Config;
 use common::{Pretty, DebugInfoGdb, Codegen};
 use util::logv;
+use regex::Regex;
 
 pub mod procsrv;
 pub mod util;
@@ -147,6 +148,7 @@ fn opt_path(m: &getopts::Matches, nm: &str) -> Path {
                                        .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:
index 4e65115caa2bec6fcbeab9e8eee2cf9f563268a9..408206b16e998c3b51bb1146b9b83f6babde078e 100644 (file)
@@ -1,4 +1,4 @@
-// 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.
 //
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 use std::io::{BufferedReader, File};
+use regex::Regex;
 
 pub struct ExpectedError {
     pub line: uint,
@@ -16,61 +17,28 @@ pub struct ExpectedError {
     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,
+        })
+    })
 }
index cd00a949bf8487b77c69a25d6cbcabbb3e89c11a..8c2b34ff35d3706009fee35ee23635ecdd3db77e 100644 (file)
@@ -1,4 +1,4 @@
-// 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.
 //
@@ -79,7 +79,7 @@ fn run_cfail_test(config: &Config, props: &TestProps, testfile: &Path) {
 
     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 \
index 4986ad1ba99f55809a4d11b13bed018fd2ca909d..d686a02b2fe64c533a5283794c60221e0e97af1b 100644 (file)
@@ -848,11 +848,11 @@ extern crate foo = "some/where/rust-foo#foo:1.0"; // a full crate ID for externa
 ##### 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 ] * '}' ;
 ~~~~
 
@@ -1743,7 +1743,7 @@ import public items from their destination, not private items.
 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 &mdash; crates, modules and items &mdash; may have _attributes_
@@ -2943,7 +2943,7 @@ See [Break expressions](#break-expressions) and [Continue expressions](#continue
 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`,
@@ -2956,7 +2956,7 @@ but must enclose it.
 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*.
@@ -3027,11 +3027,11 @@ then any `else` block is executed.
 ### 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
@@ -3115,7 +3115,7 @@ let x: List<int> = Cons(10, box Cons(11, box Nil));
 
 match x {
     Cons(a, box Cons(b, _)) => {
-        process_pair(a,b);
+        process_pair(a, b);
     }
     Cons(10, _) => {
         process_ten();
@@ -3137,7 +3137,7 @@ using the `ref` keyword,
 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:
 
 ~~~~
@@ -3329,8 +3329,8 @@ order specified by the tuple type.
 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");
 ~~~~
index ad77b90e79b7023110ca784fc020158c4dc7b47b..4e3688a060d2138febd799b2afbaa0d01899b1ef 100644 (file)
@@ -2602,7 +2602,7 @@ fn main() {
 ~~~
 
 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
index 871584b669e75a079f7175104ade16ed5c8ffb53..e2934efa43b65b5e42df828a7363e60c1e058c0c 100644 (file)
@@ -486,17 +486,13 @@ pub fn any(&self) -> bool {
         !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 })
     }
 
     /**
index 3a797cc935461ac91ab8236eb5a8374f910bf015..58ced1beeed609f8569b398d02183b19102dba4c 100644 (file)
@@ -410,7 +410,7 @@ pub fn move_rev_iter(self) -> Rev<MoveItems<T>> {
     }
 }
 
-impl<T: Ord> DList<T> {
+impl<T: TotalOrd> DList<T> {
     /// Insert `elt` sorted in ascending order
     ///
     /// O(N)
index f9f4945efc789a876989a82ed171bebf72824297..2e8178cd931e555f9895f0baba3ea6aa468715d1 100644 (file)
@@ -22,31 +22,31 @@ pub struct PriorityQueue<T> {
     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() }
 
@@ -60,20 +60,23 @@ pub fn reserve(&mut self, n: uint) {
         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) {
@@ -84,26 +87,40 @@ 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 {
@@ -111,7 +128,7 @@ pub fn to_sorted_vec(self) -> Vec<T> {
             q.data.as_mut_slice().swap(0, end);
             q.siftdown_range(0, end)
         }
-        q.to_vec()
+        q.into_vec()
     }
 
     /// Create an empty PriorityQueue
@@ -197,7 +214,7 @@ fn next(&mut self) -> Option<(&'a T)> { self.iter.next() }
     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);
@@ -205,7 +222,7 @@ fn from_iter<Iter: Iterator<T>>(iter: Iter) -> PriorityQueue<T> {
     }
 }
 
-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();
 
@@ -241,8 +258,8 @@ fn test_top_and_pop() {
         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());
         }
     }
 
@@ -250,44 +267,44 @@ fn test_top_and_pop() {
     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]
@@ -308,24 +325,24 @@ fn test_push_pop() {
     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]
@@ -346,36 +363,21 @@ fn test_to_vec() {
     }
 
     #[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]
@@ -385,7 +387,7 @@ fn test_from_iter() {
         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);
         }
     }
 }
index 0f632f4d4d095c366820356c694d7789227c8da2..2a44d1417198b2f28bd933fd81da1b88d4db80a8 100644 (file)
 //! Implementations of the following traits:
 //!
 //! * `Not`
+//! * `BitAnd`
+//! * `BitOr`
+//! * `BitXor`
 //! * `Ord`
 //! * `TotalOrd`
 //! * `Eq`
+//! * `TotalEq`
 //! * `Default`
-//! * `Zero`
 //!
 //! A `to_bit` conversion function.
 
index d42ad49485f6dae9927a33e8df4c68afc394fe68..093b3f57047ca0f1118a1798511ad1daec8a0d88 100644 (file)
@@ -8,7 +8,157 @@
 // 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;
index d40701860f46eb09ed85117e205ef3fe0fec0623..9fc16b55631a4d5d15867b33e7033df4f656f33f 100644 (file)
@@ -2184,7 +2184,7 @@ pub mod order {
     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,
@@ -2195,7 +2195,7 @@ pub fn equals<A: TotalEq, T: Iterator<A>>(mut a: T, mut b: T) -> bool {
     }
 
     /// 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,
@@ -2210,7 +2210,7 @@ pub fn cmp<A: TotalOrd, T: Iterator<A>>(mut a: T, mut b: T) -> cmp::Ordering {
     }
 
     /// 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,
@@ -2221,7 +2221,7 @@ pub fn eq<A: Eq, T: Iterator<A>>(mut a: T, mut b: T) -> bool {
     }
 
     /// 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,
@@ -2232,7 +2232,7 @@ pub fn ne<A: Eq, T: Iterator<A>>(mut a: T, mut b: T) -> bool {
     }
 
     /// 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,
@@ -2244,7 +2244,7 @@ pub fn lt<A: Ord, T: Iterator<A>>(mut a: T, mut b: T) -> bool {
     }
 
     /// 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,
@@ -2256,7 +2256,7 @@ pub fn le<A: Ord, T: Iterator<A>>(mut a: T, mut b: T) -> bool {
     }
 
     /// 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,
@@ -2268,7 +2268,7 @@ pub fn gt<A: Ord, T: Iterator<A>>(mut a: T, mut b: T) -> bool {
     }
 
     /// 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,
@@ -2325,6 +2325,16 @@ fn test_lt() {
         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)]
index 05b314b6998478a998fad6e2fc6b947cb5474ec0..ffb9b676e7d4752c2811ae88d81443375cd758ad 100644 (file)
@@ -8,31 +8,42 @@
 // 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"]
index 47be5df67eabdb345c963e9cc58ccd9dfcaf8c39..03eca8b12b825c4631a406153f7d569078f7e5da 100644 (file)
@@ -11,7 +11,7 @@
 //! 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)]
 
@@ -97,7 +97,7 @@ pub trait One: Mul<Self, Self> {
 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.
@@ -108,15 +108,17 @@ pub trait Signed: Num + Neg<Self> {
 
     /// 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.
@@ -128,7 +130,7 @@ 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`
 #[inline(always)]
 pub fn abs<T: Signed>(value: T) -> T {
     value.abs()
@@ -145,15 +147,17 @@ pub fn abs_sub<T: Signed>(x: T, y: T) -> T {
 
 /// 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
index 4c31face2e3e28041b4e0bba624e145eaa0e94b8..1eab5c04469fc62c920471356017f40e38189e9b 100644 (file)
@@ -10,7 +10,7 @@
 
 /*!
  *
- * Traits representing built-in operators, useful for overloading
+ * Overloadable operators
  *
  * Implementing these traits allows you to get an effect similar to
  * overloading operators.
index 3237269e4a64fb0dbe8a22e9822055c327e4ae29..46f4427e8387e67074bfa9a0c49d9fa8a1cce5af 100644 (file)
@@ -508,12 +508,19 @@ pub fn unwrap_or(self, optb: T) -> T {
     /// 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> {
@@ -758,8 +765,8 @@ fn handler(msg: ~str) -> int {
         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]
@@ -774,6 +781,6 @@ fn handler(msg: ~str) -> int {
         }
 
         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);
     }
 }
index 87919c8a4f470d5d388180ebad376581fc0a78c9..cd3375799a3ca8b1f489043af98aaed9f4096c3c 100644 (file)
@@ -4891,6 +4891,25 @@ fn resolve_error(&self, span: Span, s: &str) {
     }
 
     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();
@@ -4918,27 +4937,29 @@ fn get_module(this: &mut Resolver, span: Span, ident_path: &[ast::Ident])
             }
         }
 
-        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<_>>();
@@ -4955,8 +4976,8 @@ fn get_module(this: &mut Resolver, span: Span, ident_path: &[ast::Ident])
                                 FromTrait(_) => unreachable!()
                             }
                         }
-                        Some(DefMethod(_, None)) => return Method,
-                        Some(DefMethod(_, _)) => return TraitMethod,
+                        Some(DefMethod(_, None)) if allowed == Everything => return Method,
+                        Some(DefMethod(_, Some(_))) => return TraitMethod,
                         _ => ()
                     }
                 }
index 297a29211478bfc9ed9e1fc7bb18d5cd8549e64c..24265d342eb411f574efbc89a70b4f4cd8f2de37 100644 (file)
@@ -299,6 +299,9 @@ pub fn make_subregion(&self,
                         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);
           }
index a45f8a83a249426cb9031f77ee9564ea4a62bbc7..a9ec9c1ddc5ac0ed5f5e819e909b5e24b6c6d52e 100644 (file)
@@ -16,9 +16,8 @@
 //!
 //! ## 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;
index 9d1fd230f5c044ab3adbed33abf031758d80e614..1c616bdcbbf7c774b5f09d2a61f6d2c0a31d87cc 100644 (file)
@@ -471,8 +471,9 @@ macro_rules! option_env( ($name:expr) => ({ /* compiler built-in */ }) )
     /// # 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 */ }) )
index 3178fcbd66fdb8958e423a352f41942b134f2e33..40167718236ef6798c7bebd0d0f76f93a63ed023 100644 (file)
@@ -11,7 +11,7 @@
 //! 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)]
 
index 1a07393f9fc80f3fce28a0ee88615ed1af4c1e5e..3eb6f40ba53c39250734040b1591ad9fe6b62b37 100644 (file)
@@ -232,8 +232,27 @@ fn print_maybe_styled(w: &mut EmitterWriter,
     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) => {
index 4681c02d78e13ea12b33dba100363fddac56830c..dc3a18b809510e2b61cc587c17a6504a8790c9a6 100644 (file)
@@ -32,7 +32,7 @@
        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;
@@ -83,7 +83,7 @@ pub mod test {
 // 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)
@@ -156,6 +156,19 @@ fn padding(&self) -> NamePadding {
     }
 }
 
+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
@@ -170,13 +183,14 @@ pub struct Bencher {
 
 // 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,
@@ -242,15 +256,9 @@ pub fn test_main(args: &[StrBuf], tests: Vec<TestDescAndFn> ) {
 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)
@@ -419,8 +427,15 @@ pub fn opt_shard(maybestr: Option<StrBuf>) -> Option<(uint,uint)> {
         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,
             }
         }
@@ -739,10 +754,9 @@ pub fn fmt_bench_samples(bs: &BenchSamples) -> StrBuf {
 }
 
 // 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),
@@ -778,6 +792,7 @@ fn callback<T: Writer>(event: &TestEvent,
             }
         }
     }
+
     let mut st = try!(ConsoleTestState::new(opts, None::<StdWriter>));
     fn len_if_padded(t: &TestDescAndFn) -> uint {
         match t.testfn.padding() {
@@ -933,9 +948,7 @@ fn get_concurrency() -> uint {
     }
 }
 
-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
@@ -973,7 +986,9 @@ fn filter(test: TestDescAndFn) -> Option<TestDescAndFn> {
         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()
         }
diff --git a/src/test/compile-fail/issue-14254.rs b/src/test/compile-fail/issue-14254.rs
new file mode 100644 (file)
index 0000000..8b7267a
--- /dev/null
@@ -0,0 +1,113 @@
+// 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`?
+    }
+}
diff --git a/src/test/compile-fail/regions-fn-subtyping-return-static.rs b/src/test/compile-fail/regions-fn-subtyping-return-static.rs
new file mode 100644 (file)
index 0000000..c03040f
--- /dev/null
@@ -0,0 +1,60 @@
+// 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() {
+}
diff --git a/src/test/run-make/test-shard-completeness/Makefile b/src/test/run-make/test-shard-completeness/Makefile
new file mode 100644 (file)
index 0000000..16ab12a
--- /dev/null
@@ -0,0 +1,7 @@
+-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"
diff --git a/src/test/run-make/test-shard-completeness/main.rs b/src/test/run-make/test-shard-completeness/main.rs
new file mode 100644 (file)
index 0000000..5eabd63
--- /dev/null
@@ -0,0 +1,16 @@
+// 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() { }
diff --git a/src/test/run-pass/issue-14254.rs b/src/test/run-pass/issue-14254.rs
new file mode 100644 (file)
index 0000000..a3ead0a
--- /dev/null
@@ -0,0 +1,100 @@
+// 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() {}