]> git.lizzy.rs Git - rust.git/commitdiff
rollup merge of #21075: iKevinY/intro-changes
authorAlex Crichton <alex@alexcrichton.com>
Thu, 15 Jan 2015 22:11:41 +0000 (14:11 -0800)
committerAlex Crichton <alex@alexcrichton.com>
Thu, 15 Jan 2015 22:11:41 +0000 (14:11 -0800)
- Make punctuation/formatting consistent with the changes made to *The Rust Programming Language* in #20782.
- Use title casing for "Safety and Speed" section.
- Reword some phrases to improve clarity.

339 files changed:
Makefile.in
README.md
configure
mk/cfg/aarch64-apple-ios.mk
mk/cfg/armv7-apple-ios.mk
mk/cfg/armv7s-apple-ios.mk
mk/cfg/i386-apple-ios.mk
mk/cfg/powerpc-unknown-linux-gnu.mk [new file with mode: 0644]
mk/cfg/x86_64-apple-ios.mk
mk/main.mk
mk/platform.mk
mk/prepare.mk
src/compiletest/runtest.rs
src/doc/intro.md
src/doc/not_found.md
src/doc/reference.md
src/doc/rustdoc.md
src/doc/trpl/README.md
src/doc/trpl/SUMMARY.md
src/doc/trpl/arrays-vectors-and-slices.md
src/doc/trpl/closures.md
src/doc/trpl/comments.md
src/doc/trpl/compound-data-types.md
src/doc/trpl/crates-and-modules.md
src/doc/trpl/error-handling.md
src/doc/trpl/ffi.md
src/doc/trpl/functions.md
src/doc/trpl/guessing-game.md
src/doc/trpl/hello-world.md
src/doc/trpl/if.md
src/doc/trpl/looping.md
src/doc/trpl/macros.md
src/doc/trpl/ownership.md
src/doc/trpl/plugins.md
src/doc/trpl/pointers.md
src/doc/trpl/tasks.md [deleted file]
src/doc/trpl/testing.md
src/doc/trpl/threads.md [new file with mode: 0644]
src/doc/trpl/unsafe.md
src/doc/trpl/variable-bindings.md
src/etc/emacs/rust-mode.el
src/etc/vim/syntax/rust.vim
src/liballoc/arc.rs
src/liballoc/heap.rs
src/libcollections/bit.rs
src/libcollections/btree/map.rs
src/libcollections/slice.rs
src/libcollections/str.rs
src/libcollections/string.rs
src/libcollections/vec.rs
src/libcore/atomic.rs
src/libcore/finally.rs
src/libcore/fmt/float.rs
src/libcore/fmt/mod.rs
src/libcore/iter.rs
src/libcore/lib.rs
src/libcore/ops.rs
src/libcore/slice.rs
src/libcore/str/mod.rs
src/libcoretest/atomic.rs
src/libcoretest/char.rs
src/libcoretest/iter.rs
src/libcoretest/mem.rs
src/libfmt_macros/lib.rs
src/liblibc/lib.rs
src/librand/lib.rs
src/librbml/io.rs
src/librustc/README.txt
src/librustc/lib.rs
src/librustc/lint/builtin.rs
src/librustc/metadata/csearch.rs
src/librustc/metadata/decoder.rs
src/librustc/metadata/filesearch.rs
src/librustc/middle/cfg/construct.rs
src/librustc/middle/check_const.rs
src/librustc/middle/check_match.rs
src/librustc/middle/check_static.rs
src/librustc/middle/check_static_recursion.rs
src/librustc/middle/const_eval.rs
src/librustc/middle/effect.rs
src/librustc/middle/expr_use_visitor.rs
src/librustc/middle/infer/mod.rs
src/librustc/middle/liveness.rs
src/librustc/middle/mem_categorization.rs
src/librustc/middle/privacy.rs
src/librustc/middle/reachable.rs
src/librustc/middle/recursion_limit.rs
src/librustc/middle/subst.rs
src/librustc/middle/traits/error_reporting.rs
src/librustc/middle/traits/mod.rs
src/librustc/middle/traits/select.rs
src/librustc/middle/traits/util.rs
src/librustc/middle/ty.rs
src/librustc/middle/ty_fold.rs
src/librustc/plugin/registry.rs
src/librustc/session/mod.rs
src/librustc/session/search_paths.rs
src/librustc/util/ppaux.rs
src/librustc_back/sha2.rs
src/librustc_back/svh.rs
src/librustc_back/target/apple_ios_base.rs
src/librustc_back/target/mod.rs
src/librustc_back/target/powerpc_unknown_linux_gnu.rs [new file with mode: 0644]
src/librustc_back/target/x86_64_apple_darwin.rs
src/librustc_back/target/x86_64_pc_windows_gnu.rs
src/librustc_back/target/x86_64_unknown_dragonfly.rs
src/librustc_back/target/x86_64_unknown_freebsd.rs
src/librustc_back/target/x86_64_unknown_linux_gnu.rs
src/librustc_driver/driver.rs
src/librustc_driver/lib.rs
src/librustc_driver/pretty.rs
src/librustc_llvm/lib.rs
src/librustc_resolve/lib.rs
src/librustc_trans/back/lto.rs
src/librustc_trans/back/write.rs
src/librustc_trans/save/mod.rs
src/librustc_trans/save/recorder.rs
src/librustc_trans/trans/_match.rs
src/librustc_trans/trans/asm.rs
src/librustc_trans/trans/base.rs
src/librustc_trans/trans/builder.rs
src/librustc_trans/trans/cabi.rs
src/librustc_trans/trans/cabi_powerpc.rs [new file with mode: 0644]
src/librustc_trans/trans/callee.rs
src/librustc_trans/trans/consts.rs
src/librustc_trans/trans/debuginfo.rs
src/librustc_trans/trans/expr.rs
src/librustc_trans/trans/meth.rs
src/librustc_trans/trans/mod.rs
src/librustc_trans/trans/monomorphize.rs
src/librustc_typeck/astconv.rs
src/librustc_typeck/check/_match.rs
src/librustc_typeck/check/callee.rs
src/librustc_typeck/check/closure.rs
src/librustc_typeck/check/compare_method.rs [new file with mode: 0644]
src/librustc_typeck/check/mod.rs
src/librustc_typeck/lib.rs
src/librustdoc/clean/inline.rs
src/librustdoc/clean/mod.rs
src/librustdoc/core.rs
src/librustdoc/html/format.rs
src/librustdoc/html/markdown.rs
src/librustdoc/html/static/playpen.js
src/librustdoc/lib.rs
src/librustdoc/markdown.rs
src/librustdoc/test.rs
src/libserialize/json.rs
src/libstd/collections/hash/map.rs
src/libstd/collections/hash/set.rs
src/libstd/collections/hash/table.rs
src/libstd/io/buffered.rs
src/libstd/io/comm_adapters.rs
src/libstd/io/fs.rs
src/libstd/io/mem.rs
src/libstd/io/mod.rs
src/libstd/io/net/ip.rs
src/libstd/io/test.rs
src/libstd/io/util.rs
src/libstd/lib.rs
src/libstd/os.rs
src/libstd/path/mod.rs
src/libstd/path/posix.rs
src/libstd/path/windows.rs
src/libstd/rand/mod.rs
src/libstd/rand/os.rs
src/libstd/rt/backtrace.rs
src/libstd/rt/libunwind.rs
src/libstd/rt/unwind.rs
src/libstd/rt/util.rs
src/libstd/sync/condvar.rs
src/libstd/sync/mpsc/oneshot.rs
src/libstd/sync/mpsc/shared.rs
src/libstd/sync/mpsc/spsc_queue.rs
src/libstd/sync/mpsc/stream.rs
src/libstd/sync/mpsc/sync.rs
src/libstd/sync/once.rs
src/libstd/sys/common/stack.rs
src/libstd/sys/common/thread_local.rs
src/libstd/sys/unix/c.rs
src/libstd/sys/unix/stack_overflow.rs
src/libstd/sys/unix/sync.rs
src/libstd/sys/unix/thread.rs
src/libstd/sys/unix/timer.rs
src/libstd/sys/windows/condvar.rs
src/libstd/sys/windows/mutex.rs
src/libstd/sys/windows/os.rs
src/libstd/sys/windows/sync.rs
src/libsyntax/ast.rs
src/libsyntax/ast_map/mod.rs
src/libsyntax/codemap.rs
src/libsyntax/diagnostic.rs
src/libsyntax/ext/base.rs
src/libsyntax/ext/deriving/generic/mod.rs
src/libsyntax/ext/expand.rs
src/libsyntax/feature_gate.rs
src/libsyntax/fold.rs
src/libsyntax/parse/parser.rs
src/libsyntax/print/pprust.rs
src/libsyntax/visit.rs
src/libtest/lib.rs
src/rt/arch/aarch64/morestack.S
src/rt/arch/powerpc/morestack.S [new file with mode: 0644]
src/rt/arch/powerpc/record_sp.S [new file with mode: 0644]
src/rustbook/build.rs
src/rustbook/css.rs
src/rustbook/javascript.rs [new file with mode: 0644]
src/rustbook/main.rs
src/rustllvm/llvm-auto-clean-trigger
src/test/auxiliary/issue-17718.rs
src/test/auxiliary/macro_crate_test.rs
src/test/bench/shootout-fasta-redux.rs
src/test/bench/shootout-threadring.rs
src/test/compile-fail/array-not-vector.rs
src/test/compile-fail/associated-types-eq-3.rs
src/test/compile-fail/associated-types-path-2.rs
src/test/compile-fail/bad-const-type.rs
src/test/compile-fail/block-must-not-have-result-do.rs
src/test/compile-fail/block-must-not-have-result-res.rs
src/test/compile-fail/block-must-not-have-result-while.rs
src/test/compile-fail/coercion-slice.rs
src/test/compile-fail/const-cast-different-types.rs
src/test/compile-fail/cross-borrow-trait.rs
src/test/compile-fail/destructure-trait-ref.rs
src/test/compile-fail/dst-bad-assign.rs
src/test/compile-fail/dst-bad-coerce1.rs
src/test/compile-fail/dst-bad-coerce4.rs
src/test/compile-fail/explicit-self-lifetime-mismatch.rs
src/test/compile-fail/fn-item-type.rs
src/test/compile-fail/fn-trait-formatting.rs
src/test/compile-fail/fully-qualified-type-name1.rs
src/test/compile-fail/fully-qualified-type-name2.rs
src/test/compile-fail/fully-qualified-type-name4.rs
src/test/compile-fail/generic-type-params-name-repr.rs
src/test/compile-fail/if-branch-types.rs
src/test/compile-fail/if-without-else-result.rs
src/test/compile-fail/integer-literal-suffix-inference.rs
src/test/compile-fail/integral-variable-unification-error.rs
src/test/compile-fail/issue-10176.rs
src/test/compile-fail/issue-11319.rs
src/test/compile-fail/issue-11771.rs
src/test/compile-fail/issue-12997-2.rs
src/test/compile-fail/issue-13058.rs
src/test/compile-fail/issue-13359.rs
src/test/compile-fail/issue-13466.rs
src/test/compile-fail/issue-13482-2.rs
src/test/compile-fail/issue-13482.rs
src/test/compile-fail/issue-13624.rs
src/test/compile-fail/issue-14091.rs
src/test/compile-fail/issue-14541.rs
src/test/compile-fail/issue-14845.rs
src/test/compile-fail/issue-14853.rs
src/test/compile-fail/issue-15783.rs
src/test/compile-fail/issue-15896.rs
src/test/compile-fail/issue-16338.rs
src/test/compile-fail/issue-16401.rs
src/test/compile-fail/issue-17033.rs
src/test/compile-fail/issue-17283.rs
src/test/compile-fail/issue-17740.rs
src/test/compile-fail/issue-17905.rs
src/test/compile-fail/issue-19991.rs
src/test/compile-fail/issue-2611-4.rs
src/test/compile-fail/issue-2951.rs
src/test/compile-fail/issue-3477.rs
src/test/compile-fail/issue-3563.rs
src/test/compile-fail/issue-3680.rs
src/test/compile-fail/issue-4201.rs
src/test/compile-fail/issue-4517.rs
src/test/compile-fail/issue-4968.rs
src/test/compile-fail/issue-5100.rs
src/test/compile-fail/issue-5358-1.rs
src/test/compile-fail/issue-5500.rs
src/test/compile-fail/issue-7061.rs
src/test/compile-fail/issue-7092.rs
src/test/compile-fail/issue-7867.rs
src/test/compile-fail/issue-8761.rs
src/test/compile-fail/match-struct.rs
src/test/compile-fail/match-vec-mismatch-2.rs
src/test/compile-fail/method-self-arg-1.rs
src/test/compile-fail/mut-pattern-mismatched.rs
src/test/compile-fail/no-type-for-node-ice.rs [new file with mode: 0644]
src/test/compile-fail/noexporttypeexe.rs
src/test/compile-fail/occurs-check-2.rs
src/test/compile-fail/occurs-check.rs
src/test/compile-fail/on-unimplemented-bad-anno.rs [new file with mode: 0644]
src/test/compile-fail/on-unimplemented.rs [new file with mode: 0644]
src/test/compile-fail/pattern-error-continue.rs
src/test/compile-fail/pptypedef.rs
src/test/compile-fail/ptr-coercion.rs
src/test/compile-fail/regions-bound-missing-bound-in-impl.rs
src/test/compile-fail/regions-bounds.rs
src/test/compile-fail/regions-early-bound-error-method.rs
src/test/compile-fail/regions-early-bound-error.rs
src/test/compile-fail/regions-fn-subtyping-return-static.rs
src/test/compile-fail/regions-infer-paramd-indirect.rs
src/test/compile-fail/repeat_count.rs
src/test/compile-fail/shift-various-bad-types.rs
src/test/compile-fail/slightly-nice-generic-literal-messages.rs
src/test/compile-fail/std-uncopyable-atomics.rs
src/test/compile-fail/struct-base-wrong-type.rs
src/test/compile-fail/structure-constructor-type-mismatch.rs
src/test/compile-fail/suppressed-error.rs
src/test/compile-fail/tag-that-dare-not-speak-its-name.rs
src/test/compile-fail/terr-in-field.rs
src/test/compile-fail/terr-sorts.rs
src/test/compile-fail/trait-bounds-cant-coerce.rs
src/test/compile-fail/trait-bounds-impl-comparison-1.rs
src/test/compile-fail/trait-bounds-impl-comparison-2.rs
src/test/compile-fail/tuple-arity-mismatch.rs
src/test/compile-fail/tutorial-suffix-inference-test.rs
src/test/compile-fail/type-mismatch-multiple.rs
src/test/compile-fail/type-parameter-names.rs
src/test/compile-fail/type-params-in-different-spaces-1.rs
src/test/compile-fail/typeck_type_placeholder_mismatch.rs
src/test/compile-fail/ufcs-explicit-self-bad.rs
src/test/compile-fail/ufcs-qpath-missing-params.rs [new file with mode: 0644]
src/test/compile-fail/ufcs-qpath-self-mismatch.rs [new file with mode: 0644]
src/test/compile-fail/variadic-ffi.rs
src/test/compile-fail/wrong-mul-method-signature.rs
src/test/debuginfo/associated_types.rs [new file with mode: 0644]
src/test/run-make/issue-19371/foo.rs
src/test/run-pass-fulldeps/macro-crate.rs
src/test/run-pass/associated-types-enum-field-named.rs [new file with mode: 0644]
src/test/run-pass/associated-types-enum-field-numbered.rs [new file with mode: 0644]
src/test/run-pass/associated-types-projection-in-where-clause.rs [new file with mode: 0644]
src/test/run-pass/associated-types-struct-field-named.rs [new file with mode: 0644]
src/test/run-pass/associated-types-struct-field-numbered.rs [new file with mode: 0644]
src/test/run-pass/backtrace.rs
src/test/run-pass/coerce-expect-unsized.rs
src/test/run-pass/coerce-unify-return.rs [new file with mode: 0644]
src/test/run-pass/const-polymorphic-paths.rs
src/test/run-pass/issue-17503.rs
src/test/run-pass/issue-17718.rs
src/test/run-pass/issue-20575.rs [new file with mode: 0644]
src/test/run-pass/issue-8898.rs
src/test/run-pass/slice-2.rs
src/test/run-pass/tcp-accept-stress.rs
src/test/run-pass/trait-false-ambiguity-where-clause-builtin-bound.rs [new file with mode: 0644]
src/test/run-pass/vector-sort-panic-safe.rs
src/test/run-pass/where-clause-bounds-inconsistency.rs [new file with mode: 0644]

index a2394101f3a72f8a30a7cc952bd712289165fba9..63c5742a540d404c0502a38326fceb06e47da22a 100644 (file)
 #     make check-stage1-std RUST_TEST_TASKS=1
 #
 # This is hardly all there is to know of The Rust Build System's
-# mysteries. The tale continues on the wiki[1][2].
+# mysteries. The tale continues on the wiki[1].
 #
-# [1]: https://github.com/rust-lang/rust/wiki/Note-getting-started-developing-Rust
-# [2]: https://github.com/rust-lang/rust/wiki/Note-testsuite
+# [1]: https://github.com/rust-lang/rust/wiki/Note-testsuite
 #
 # If you really feel like getting your hands dirty, then:
 #
index e858e91773b9288e6df572d205f419ac067963c1..147d2e9d2f44aa1c377bd06a1757616d7a3840bf 100644 (file)
--- a/README.md
+++ b/README.md
@@ -58,16 +58,23 @@ documentation.
 
 ### Building on Windows
 
-To easily build on windows we can use [MSYS2](http://sourceforge.net/projects/msys2/):
+To easily build on windows we can use [MSYS2](http://msys2.github.io/):
 
 1. Grab the latest MSYS2 installer and go through the installer.
 2. Now from the MSYS2 terminal we want to install the mingw64 toolchain and the other
    tools we need.
 
-        $ pacman -S mingw-w64-i686-toolchain
-        $ pacman -S base-devel
+```bash
+# choose one based on platform
+$ pacman -S mingw-w64-i686-toolchain
+$ pacman -S mingw-w64-x86_64-toolchain
 
-3. With that now start `mingw32_shell.bat` from where you installed MSYS2 (i.e. `C:\msys`).
+$ pacman -S base-devel
+```
+
+3. With that now start `mingw32_shell.bat` or `mingw64_shell.bat`
+   from where you installed MSYS2 (i.e. `C:\msys`). Which one you
+   choose depends on if you want 32 or 64 bit Rust.
 4. From there just navigate to where you have Rust's source code, configure and build it:
 
         $ ./configure
index d0b99b12fd90d080b054bb9ffb0d32ca648363f2..86ed88c8d06315e87247b8f4c8106d6b7d32df90 100755 (executable)
--- a/configure
+++ b/configure
@@ -448,6 +448,10 @@ case $CFG_CPUTYPE in
         CFG_CPUTYPE=aarch64
         ;;
 
+    powerpc)
+        CFG_CPUTYPE=powerpc
+        ;;
+
     x86_64 | x86-64 | x64 | amd64)
         CFG_CPUTYPE=x86_64
         ;;
@@ -1004,7 +1008,7 @@ do
     make_dir $t/rt/jemalloc
     for i in                                          \
       isaac sync test \
-      arch/i386 arch/x86_64 arch/arm arch/aarch64 arch/mips
+      arch/i386 arch/x86_64 arch/arm arch/aarch64 arch/mips arch/powerpc
     do
       make_dir $t/rt/stage$s/$i
     done
@@ -1169,7 +1173,7 @@ do
 
         msg "configuring LLVM for $gnu_t"
 
-        LLVM_TARGETS="--enable-targets=x86,x86_64,arm,aarch64,mips"
+        LLVM_TARGETS="--enable-targets=x86,x86_64,arm,aarch64,mips,powerpc"
         LLVM_BUILD="--build=$gnu_t"
         LLVM_HOST="--host=$gnu_t"
         LLVM_TARGET="--target=$gnu_t"
index cbd889669ab22921885a17b870acaf0fd7b9d6ad..0219ab960579bb81239b8df362a522c7e4615834 100644 (file)
@@ -11,7 +11,7 @@ AR_aarch64-apple-ios = $(shell xcrun -find -sdk iphoneos ar)
 endif
 CFG_LIB_NAME_aarch64-apple-ios = lib$(1).a
 CFG_LIB_GLOB_aarch64-apple-ios = lib$(1)-*.a
-CFG_LIB_SKIP_INSTALL_aarch64-apple-ios = 1 #lib$(1)-*.a
+CFG_INSTALL_ONLY_RLIB_aarch64-apple-ios = 1
 CFG_STATIC_LIB_NAME_aarch64-apple-ios=lib$(1).a
 CFG_LIB_DSYM_GLOB_aarch64-apple-ios = lib$(1)-*.a.dSYM
 CFG_CFLAGS_aarch64-apple-ios := $(CFG_IOS_SDK_FLAGS_aarch64-apple-ios)
index 23686c41f2b19ccfc7063d74d1ec5b942ae3f1b1..aee4e64addfc1834040be1717ca8379d63ea781f 100644 (file)
@@ -11,7 +11,7 @@ AR_armv7-apple-ios = $(shell xcrun -find -sdk iphoneos ar)
 endif
 CFG_LIB_NAME_armv7-apple-ios = lib$(1).a
 CFG_LIB_GLOB_armv7-apple-ios = lib$(1)-*.a
-CFG_LIB_SKIP_INSTALL_armv7-apple-ios = 1 #lib$(1)-*.a
+CFG_INSTALL_ONLY_RLIB_armv7-apple-ios = 1
 CFG_STATIC_LIB_NAME_armv7-apple-ios=lib$(1).a
 CFG_LIB_DSYM_GLOB_armv7-apple-ios = lib$(1)-*.a.dSYM
 CFG_JEMALLOC_CFLAGS_armv7-apple-ios := -arch armv7 -mfpu=vfp3 $(CFG_IOS_SDK_FLAGS_armv7-apple-ios)
index ccb7f014159ff9e8a55bc6acbb35c26652e0a58d..7540bd44de878211e1b540e05465c8d1c23358e4 100644 (file)
@@ -11,7 +11,7 @@ AR_armv7s-apple-ios = $(shell xcrun -find -sdk iphoneos ar)
 endif
 CFG_LIB_NAME_armv7s-apple-ios = lib$(1).a
 CFG_LIB_GLOB_armv7s-apple-ios = lib$(1)-*.a
-CFG_LIB_SKIP_INSTALL_armv7s-apple-ios = 1 #lib$(1)-*.a
+CFG_INSTALL_ONLY_RLIB_armv7s-apple-ios = 1
 CFG_STATIC_LIB_NAME_armv7s-apple-ios=lib$(1).a
 CFG_LIB_DSYM_GLOB_armv7s-apple-ios = lib$(1)-*.a.dSYM
 CFG_JEMALLOC_CFLAGS_armv7s-apple-ios := -arch armv7s -mfpu=vfp4 $(CFG_IOS_SDK_FLAGS_armv7s-apple-ios)
index 5007c0617c5a988cbfdf032ef33984edf01e045d..e84bf49d4079a39830b28f95f958e3caf1bc4c21 100644 (file)
@@ -11,6 +11,7 @@ AR_i386-apple-ios = $(shell xcrun -find -sdk iphonesimulator ar)
 endif
 CFG_LIB_NAME_i386-apple-ios = lib$(1).a
 CFG_LIB_GLOB_i386-apple-ios = lib$(1)-*.dylib
+CFG_INSTALL_ONLY_RLIB_i386-apple-ios = 1
 CFG_STATIC_LIB_NAME_i386-apple-ios=lib$(1).a
 CFG_LIB_DSYM_GLOB_i386-apple-ios = lib$(1)-*.dylib.dSYM
 CFG_GCCISH_CFLAGS_i386-apple-ios := -Wall -Werror -g -fPIC -m32 $(CFG_IOSSIM_FLAGS_i386-apple-ios)
diff --git a/mk/cfg/powerpc-unknown-linux-gnu.mk b/mk/cfg/powerpc-unknown-linux-gnu.mk
new file mode 100644 (file)
index 0000000..fd37bd6
--- /dev/null
@@ -0,0 +1,28 @@
+# powerpc-unknown-linux-gnu configuration
+CROSS_PREFIX_powerpc-unknown-linux-gnu=powerpc-linux-gnu-
+CC_powerpc-unknown-linux-gnu=$(CC)
+CXX_powerpc-unknown-linux-gnu=$(CXX)
+CPP_powerpc-unknown-linux-gnu=$(CPP)
+AR_powerpc-unknown-linux-gnu=$(AR)
+CFG_LIB_NAME_powerpc-unknown-linux-gnu=lib$(1).so
+CFG_STATIC_LIB_NAME_powerpc-unknown-linux-gnu=lib$(1).a
+CFG_LIB_GLOB_powerpc-unknown-linux-gnu=lib$(1)-*.so
+CFG_LIB_DSYM_GLOB_powerpc-unknown-linux-gnu=lib$(1)-*.dylib.dSYM
+CFG_CFLAGS_powerpc-unknown-linux-gnu := -m32 $(CFLAGS)
+CFG_GCCISH_CFLAGS_powerpc-unknown-linux-gnu := -Wall -Werror -g -fPIC -m32 $(CFLAGS)
+CFG_GCCISH_CXXFLAGS_powerpc-unknown-linux-gnu := -fno-rtti $(CXXFLAGS)
+CFG_GCCISH_LINK_FLAGS_powerpc-unknown-linux-gnu := -shared -fPIC -ldl -pthread  -lrt -g -m32
+CFG_GCCISH_DEF_FLAG_powerpc-unknown-linux-gnu := -Wl,--export-dynamic,--dynamic-list=
+CFG_GCCISH_PRE_LIB_FLAGS_powerpc-unknown-linux-gnu := -Wl,-whole-archive
+CFG_GCCISH_POST_LIB_FLAGS_powerpc-unknown-linux-gnu := -Wl,-no-whole-archive
+CFG_DEF_SUFFIX_powerpc-unknown-linux-gnu := .linux.def
+CFG_LLC_FLAGS_powerpc-unknown-linux-gnu :=
+CFG_INSTALL_NAME_powerpc-unknown-linux-gnu =
+CFG_EXE_SUFFIX_powerpc-unknown-linux-gnu =
+CFG_WINDOWSY_powerpc-unknown-linux-gnu :=
+CFG_UNIXY_powerpc-unknown-linux-gnu := 1
+CFG_PATH_MUNGE_powerpc-unknown-linux-gnu := true
+CFG_LDPATH_powerpc-unknown-linux-gnu :=
+CFG_RUN_powerpc-unknown-linux-gnu=$(2)
+CFG_RUN_TARG_powerpc-unknown-linux-gnu=$(call CFG_RUN_powerpc-unknown-linux-gnu,,$(2))
+CFG_GNU_TRIPLE_powerpc-unknown-linux-gnu := powerpc-unknown-linux-gnu
index 69070ec4fad4d5e57843074cd9477bb4c9f9ddee..b3f05a895a49fe0f65c912ac9997a59270fb1744 100644 (file)
@@ -11,7 +11,7 @@ AR_x86_64-apple-ios = $(shell xcrun -find -sdk iphonesimulator ar)
 endif
 CFG_LIB_NAME_x86_64-apple-ios = lib$(1).a
 CFG_LIB_GLOB_x86_64-apple-ios = lib$(1)-*.a
-CFG_LIB_SKIP_INSTALL_x86_64-apple-ios = 1 #lib$(1)-*.a
+CFG_INSTALL_ONLY_RLIB_x86_64-apple-ios = 1
 CFG_STATIC_LIB_NAME_x86_64-apple-ios=lib$(1).a
 CFG_LIB_DSYM_GLOB_x86_64-apple-ios = lib$(1)-*.a.dSYM
 CFG_CFLAGS_x86_64-apple-ios := $(CFG_IOSSIM_FLAGS_x86_64-apple-ios)
index ba6baa3fefef7a3bba9a455213f2fae28ec80a74..334647d04023f04082f6e7cdba65979da8ceb936 100644 (file)
@@ -263,7 +263,7 @@ endif
 ######################################################################
 
 # FIXME: x86-ism
-LLVM_COMPONENTS=x86 arm aarch64 mips ipo bitreader bitwriter linker asmparser mcjit \
+LLVM_COMPONENTS=x86 arm aarch64 mips powerpc ipo bitreader bitwriter linker asmparser mcjit \
                 interpreter instrumentation
 
 # Only build these LLVM tools
index 50bf51b20de18f4bfb87d66c43ed00d3744366b1..78c1057c2fe524ca28a19e6d9164c0f1d08ab771 100644 (file)
@@ -177,7 +177,7 @@ define CFG_MAKE_TOOLCHAIN
         $$(CFG_GCCISH_DEF_FLAG_$(1))$$(3) $$(2) \
         $$(call CFG_INSTALL_NAME_$(1),$$(4))
 
-  ifeq ($$(findstring $(HOST_$(1)),arm aarch64 mips mipsel),)
+  ifeq ($$(findstring $(HOST_$(1)),arm aarch64 mips mipsel powerpc),)
 
   # We're using llvm-mc as our assembler because it supports
   # .cfi pseudo-ops on mac
@@ -189,7 +189,7 @@ define CFG_MAKE_TOOLCHAIN
                     -o=$$(1)
   else
 
-  # For the ARM, AARCH64 and MIPS crosses, use the toolchain assembler
+  # For the ARM, AARCH64, MIPS and POWER crosses, use the toolchain assembler
   # FIXME: We should be able to use the LLVM assembler
   CFG_ASSEMBLE_$(1)=$$(CC_$(1)) $$(CFG_GCCISH_CFLAGS_$(1)) \
                    $$(CFG_DEPEND_FLAGS) $$(2) -c -o $$(1)
index 6a5daeb690941f98097570ce3676e24bc101a67c..f1c4aa65f5ffe5943b302698eda17ebdd7697bcc 100644 (file)
@@ -134,7 +134,7 @@ prepare-target-$(2)-host-$(3)-$(1)-$(4): prepare-maybe-clean-$(4) \
         $$(if $$(findstring $(3), $$(PREPARE_HOST)), \
           $$(call PREPARE_DIR,$$(PREPARE_WORKING_DEST_LIB_DIR)) \
           $$(foreach crate,$$(TARGET_CRATES), \
-           $$(if $$(findstring 1, $$(ONLY_RLIB_$$(crate))),, \
+           $$(if $$(or $$(findstring 1, $$(ONLY_RLIB_$$(crate))),$$(findstring 1,$$(CFG_INSTALL_ONLY_RLIB_$(2)))),, \
               $$(call PREPARE_LIB,$$(call CFG_LIB_GLOB_$(2),$$(crate)))) \
             $$(call PREPARE_LIB,$$(call CFG_RLIB_GLOB,$$(crate)))) \
           $$(if $$(findstring $(2),$$(CFG_HOST)), \
index 5de93c52029226503abbeee5d715f139e36057ca..5579479c5e5aca5df77ebf0b2edf4fa9e3f1249d 100644 (file)
@@ -966,6 +966,16 @@ fn prefix_matches( line : &str, prefix : &str ) -> bool {
         line.starts_with( prefix )
     }
 
+    // A multi-line error will have followup lines which will always
+    // start with one of these strings.
+    fn continuation( line: &str) -> bool {
+        line.starts_with(" expected") ||
+        line.starts_with("    found") ||
+        //                1234
+        // Should have 4 spaces: see issue 18946
+        line.starts_with("(")
+    }
+
     // Scan and extract our error/warning messages,
     // which look like:
     //    filename:line1:col1: line2:col2: *error:* msg
@@ -981,7 +991,7 @@ fn prefix_matches( line : &str, prefix : &str ) -> bool {
                        ee.kind,
                        ee.msg,
                        line);
-                if prefix_matches(line, prefixes[i].as_slice()) &&
+                if (prefix_matches(line, prefixes[i].as_slice()) || continuation(line)) &&
                     line.contains(ee.kind.as_slice()) &&
                     line.contains(ee.msg.as_slice()) {
                     found_flags[i] = true;
index f244119f322ebd04b2e26b7336c85d0ba6d3ca7d..d93b680ae6de704cb83fd73394475fb1681b88e8 100644 (file)
@@ -106,9 +106,9 @@ use semver::Version;
 
 fn main() {
     assert!(Version::parse("1.2.3") == Ok(Version {
-        major: 1u,
-        minor: 2u,
-        patch: 3u,
+        major: 1u64,
+        minor: 2u64,
+        patch: 3u64,
         pre: vec!(),
         build: vec!(),
     }));
@@ -392,20 +392,21 @@ Here's an example of a concurrent Rust program:
 use std::thread::Thread;
 
 fn main() {
-    for _ in range(0u, 10u) {
-        Thread::spawn(move || {
+    let guards: Vec<_> = (0..10).map(|_| {
+        Thread::scoped(|| {
             println!("Hello, world!");
-        });
-    }
+        })
+    }).collect();
 }
 ```
 
-This program creates ten threads, who all print `Hello, world!`. The
-`spawn` function takes one argument, a closure, indicated by the
-double bars `||`. (The `move` keyword indicates that the closure takes
-ownership of any data it uses; we'll have more on the significance of
-this shortly.) This closure is executed in a new thread created by
-`spawn`.
+This program creates ten threads, which all print `Hello, world!`. The `scoped`
+function takes one argument, a closure, indicated by the double bars `||`. This
+closure is executed in a new thread created by `scoped`. The method is called
+`scoped` because it returns a 'join guard', which will automatically join the
+child thread when it goes out of scope. Because we `collect` these guards into
+a `Vec<T>`, and that vector goes out of scope at the end of our program, our
+program will wait for every thread to finish before finishing.
 
 One common form of problem in concurrent programs is a *data race*.
 This occurs when two different threads attempt to access the same
index bd4d959109716e354d97227bda0b38a5958d1f30..c746c5773dd0907ce8fea7c97a69e47c66de178f 100644 (file)
@@ -12,6 +12,7 @@ Looks like you've taken a wrong turn.
 Some things that might be helpful to you though:
 
 ## Search
+
 * <form action="https://duckduckgo.com/">
     <input type="text" id="site-search" name="q" size="80"></input>
     <input type="submit" value="Search DuckDuckGo">
@@ -19,10 +20,12 @@ Some things that might be helpful to you though:
 * Rust doc search: <span id="core-search"></span>
 
 ## Reference
+
 * [The Rust official site](http://rust-lang.org)
-* [The Rust reference](http://doc.rust-lang.org/reference.html) (* [PDF](http://doc.rust-lang.org/reference.pdf))
+* [The Rust reference](http://doc.rust-lang.org/reference.html)
 
 ## Docs
+
 * [The standard library](http://doc.rust-lang.org/std/)
 
 <script>
index 2486466c8696d464d36cddefcd3a16db2b0d9950..435566ae1831ffdbadfc997b783b5d2c8c77f17b 100644 (file)
@@ -603,7 +603,7 @@ mod b {
 ```
 
 * Paths starting with the keyword `super` begin resolution relative to the
-  parent module. Each further identifier must resolve to an item
+  parent module. Each further identifier must resolve to an item.
 
 ```rust
 mod a {
@@ -985,7 +985,7 @@ top of [modules](#modules) and [blocks](#blocks).
 
 Use declarations support a number of convenient shortcuts:
 
-* Rebinding the target name as a new local name, using the syntax `use p::q::r as x;`.
+* Rebinding the target name as a new local name, using the syntax `use p::q::r as x;`
 * Simultaneously binding a list of paths differing only in their final element,
   using the glob-like brace syntax `use a::b::{c,d,e,f};`
 * Binding all paths matching a given prefix, using the asterisk wildcard syntax
@@ -1091,7 +1091,7 @@ set of *input* [*slots*](#memory-slots) as parameters, through which the caller
 passes arguments into the function, and an *output* [*slot*](#memory-slots)
 through which the function passes results back to the caller.
 
-A function may also be copied into a first class *value*, in which case the
+A function may also be copied into a first-class *value*, in which case the
 value has the corresponding [*function type*](#function-types), and can be used
 otherwise exactly as a function item (with a minor additional cost of calling
 the function indirectly).
@@ -1224,7 +1224,7 @@ the guarantee that these issues are never caused by safe code.
   * A value other than `false` (0) or `true` (1) in a `bool`
   * A discriminant in an `enum` not included in the type definition
   * A value in a `char` which is a surrogate or above `char::MAX`
-  * non-UTF-8 byte sequences in a `str`
+  * Non-UTF-8 byte sequences in a `str`
 * Unwinding into Rust from foreign code or unwinding from Rust into foreign
   code. Rust's failure system is not compatible with exception handling in
   other languages. Unwinding must be caught and handled at FFI boundaries.
@@ -1827,7 +1827,7 @@ accesses in two cases:
 
 These two cases are surprisingly powerful for creating module hierarchies
 exposing public APIs while hiding internal implementation details. To help
-explain, here's a few use cases and what they would entail.
+explain, here's a few use cases and what they would entail:
 
 * A library developer needs to expose functionality to crates which link
   against their library. As a consequence of the first case, this means that
@@ -1858,7 +1858,7 @@ import/expression is only valid if the destination is in the current visibility
 scope.
 
 Here's an example of a program which exemplifies the three cases outlined
-above.
+above:
 
 ```
 // This module is private, meaning that no external crate can access this
@@ -2117,6 +2117,13 @@ macro scope.
   destructors from being run twice. Destructors might be run multiple times on
   the same object with this attribute.
 - `doc` - Doc comments such as `/// foo` are equivalent to `#[doc = "foo"]`.
+- `rustc_on_unimplemented` - Write a custom note to be shown along with the error
+   when the trait is found to be unimplemented on a type.
+   You may use format arguments like `{T}`, `{A}` to correspond to the
+   types at the point of use corresponding to the type parameters of the
+   trait of the same name. `{Self}` will be replaced with the type that is supposed
+   to implement the trait but doesn't. To use this, the `on_unimplemented` feature gate
+   must be enabled.
 
 ### Conditional compilation
 
@@ -2163,7 +2170,7 @@ arbitrarily complex configurations through nesting.
 The following configurations must be defined by the implementation:
 
 * `target_arch = "..."`. Target CPU architecture, such as `"x86"`, `"x86_64"`
-  `"mips"`, `"arm"`, or `"aarch64"`.
+  `"mips"`, `"powerpc"`, `"arm"`, or `"aarch64"`.
 * `target_endian = "..."`. Endianness of the target CPU, either `"little"` or
   `"big"`.
 * `target_family = "..."`. Operating system family of the target, e. g.
@@ -2213,7 +2220,7 @@ mod m1 {
 ```
 
 This example shows how one can use `allow` and `warn` to toggle a particular
-check on and off.
+check on and off:
 
 ```{.ignore}
 #[warn(missing_docs)]
@@ -2235,7 +2242,7 @@ mod m2{
 ```
 
 This example shows how one can use `forbid` to disallow uses of `allow` for
-that lint check.
+that lint check:
 
 ```{.ignore}
 #[forbid(missing_docs)]
@@ -2318,9 +2325,9 @@ These language items are traits:
 * `ord`
   : Elements have a partial ordering.
 * `deref`
-  : `*` can be applied, yielding a reference to another type
+  : `*` can be applied, yielding a reference to another type.
 * `deref_mut`
-  : `*` can be applied, yielding a mutable reference to another type
+  : `*` can be applied, yielding a mutable reference to another type.
 
 These are functions:
 
@@ -2341,7 +2348,7 @@ These are functions:
 * `type_id`
   : The type returned by the `type_id` intrinsic.
 * `unsafe`
-  : A type whose contents can be mutated through an immutable reference
+  : A type whose contents can be mutated through an immutable reference.
 
 #### Marker types
 
@@ -2350,11 +2357,11 @@ These types help drive the compiler's analysis
 * `begin_unwind`
   : ___Needs filling in___
 * `no_copy_bound`
-  : This type does not implement "copy", even if eligible
+  : This type does not implement "copy", even if eligible.
 * `no_send_bound`
-  : This type does not implement "send", even if eligible
+  : This type does not implement "send", even if eligible.
 * `no_sync_bound`
-  : This type does not implement "sync", even if eligible
+  : This type does not implement "sync", even if eligible.
 * `eh_personality`
   : ___Needs filling in___
 * `exchange_free`
@@ -2376,11 +2383,11 @@ These types help drive the compiler's analysis
 * `iterator`
   : ___Needs filling in___
 * `contravariant_lifetime`
-  : The lifetime parameter should be considered contravariant
+  : The lifetime parameter should be considered contravariant.
 * `covariant_lifetime`
-  : The lifetime parameter should be considered covariant
+  : The lifetime parameter should be considered covariant.
 * `invariant_lifetime`
-  : The lifetime parameter should be considered invariant
+  : The lifetime parameter should be considered invariant.
 * `malloc`
   : Allocate memory on the managed heap.
 * `owned_box`
@@ -2390,11 +2397,11 @@ These types help drive the compiler's analysis
 * `start`
   : ___Needs filling in___
 * `contravariant_type`
-  : The type parameter should be considered contravariant
+  : The type parameter should be considered contravariant.
 * `covariant_type`
-  : The type parameter should be considered covariant
+  : The type parameter should be considered covariant.
 * `invariant_type`
-  : The type parameter should be considered invariant
+  : The type parameter should be considered invariant.
 * `ty_desc`
   : ___Needs filling in___
 
@@ -2425,15 +2432,15 @@ There are three different types of inline attributes:
 * `#[inline(always)]` asks the compiler to always perform an inline expansion.
 * `#[inline(never)]` asks the compiler to never perform an inline expansion.
 
-### Deriving
+### Derive
 
-The `deriving` attribute allows certain traits to be automatically implemented
+The `derive` attribute allows certain traits to be automatically implemented
 for data structures. For example, the following will create an `impl` for the
 `PartialEq` and `Clone` traits for `Foo`, the type parameter `T` will be given
 the `PartialEq` or `Clone` constraints for the appropriate `impl`:
 
 ```
-#[deriving(PartialEq, Clone)]
+#[derive(PartialEq, Clone)]
 struct Foo<T> {
     a: int,
     b: T
@@ -2455,7 +2462,7 @@ impl<T: PartialEq> PartialEq for Foo<T> {
 }
 ```
 
-Supported traits for `deriving` are:
+Supported traits for `derive` are:
 
 * Comparison traits: `PartialEq`, `Eq`, `PartialOrd`, `Ord`.
 * Serialization: `Encodable`, `Decodable`. These require `serialize`.
@@ -2921,13 +2928,13 @@ automatically dereferenced to make the field access possible.
 ```{.ebnf .gram}
 array_expr : '[' "mut" ? vec_elems? ']' ;
 
-array_elems : [expr [',' expr]*] | [expr ',' ".." expr] ;
+array_elems : [expr [',' expr]*] | [expr ';' expr] ;
 ```
 
 An [array](#array,-and-slice-types) _expression_ is written by enclosing zero
 or more comma-separated expressions of uniform type in square brackets.
 
-In the `[expr ',' ".." expr]` form, the expression after the `".."` must be a
+In the `[expr ';' expr]` form, the expression after the `';'` must be a
 constant expression that can be evaluated at compile time, such as a
 [literal](#literals) or a [static item](#static-items).
 
@@ -2960,8 +2967,8 @@ _panicked state_.
 
 ### Unary operator expressions
 
-Rust defines six symbolic unary operators. They are all written as prefix
-operators, before the expression they apply to.
+Rust defines three unary operators. They are all written as prefix operators,
+before the expression they apply to.
 
 * `-`
   : Negation. May only be applied to numeric types.
@@ -2979,13 +2986,6 @@ operators, before the expression they apply to.
   : Logical negation. On the boolean type, this flips between `true` and
     `false`. On integer types, this inverts the individual bits in the
     two's complement representation of the value.
-* `box`
-  : [Boxing](#pointer-types) operators. Allocate a box to hold the value they
-    are applied to, and store the value in it. `box` creates a box.
-* `&`
-  : Borrow operator. Returns a reference, pointing to its operand. The operand
-    of a borrow is statically proven to outlive the resulting pointer. If the
-    borrow-checker cannot prove this, it is a compilation error.
 
 ### Binary operator expressions
 
@@ -3219,11 +3219,11 @@ the simplest and least-expensive form (analogous to a ```|| { }``` expression),
 the lambda expression captures its environment by reference, effectively
 borrowing pointers to all outer variables mentioned inside the function.
 Alternately, the compiler may infer that a lambda expression should copy or
-move values (depending on their type.) from the environment into the lambda
+move values (depending on their type) from the environment into the lambda
 expression's captured environment.
 
 In this example, we define a function `ten_times` that takes a higher-order
-function argument, and call it with a lambda expression as an argument.
+function argument, and call it with a lambda expression as an argument:
 
 ```
 fn ten_times<F>(f: F) where F: Fn(int) {
@@ -3661,14 +3661,14 @@ within an object along with one byte past the end.
 The types `char` and `str` hold textual data.
 
 A value of type `char` is a [Unicode scalar value](
-http://www.unicode.org/glossary/#unicode_scalar_value) (ie. a code point that
+http://www.unicode.org/glossary/#unicode_scalar_value) (i.e. a code point that
 is not a surrogate), represented as a 32-bit unsigned word in the 0x0000 to
 0xD7FF or 0xE000 to 0x10FFFF range. A `[char]` array is effectively an UCS-4 /
 UTF-32 string.
 
 A value of type `str` is a Unicode string, represented as an array of 8-bit
 unsigned bytes holding a sequence of UTF-8 codepoints. Since `str` is of
-unknown size, it is not a _first class_ type, but can only be instantiated
+unknown size, it is not a _first-class_ type, but can only be instantiated
 through a pointer type, such as `&str` or `String`.
 
 ### Tuple types
@@ -3698,7 +3698,7 @@ assert!(b != "world");
 
 Rust has two different types for a list of items:
 
-* `[T ..N]`, an 'array'
+* `[T; N]`, an 'array'.
 * `&[T]`, a 'slice'.
 
 An array has a fixed size, and can be allocated on either the stack or the
@@ -3710,9 +3710,9 @@ to, it borrows it.
 An example of each kind:
 
 ```{rust}
-let vec: Vec<int>  = vec![1, 2, 3];
-let arr: [int; 3] = [1, 2, 3];
-let s: &[int]      = vec.as_slice();
+let vec: Vec<i32> = vec![1, 2, 3];
+let arr: [i32; 3] = [1, 2, 3];
+let s: &[i32] = vec.as_slice();
 ```
 
 As you can see, the `vec!` macro allows you to create a `Vec<T>` easily. The
@@ -3798,7 +3798,7 @@ enum List<T> {
     Cons(T, Box<List<T>>)
 }
 
-let a: List<int> = List::Cons(7, Box::new(List::Cons(13, Box::new(List::Nil))));
+let a: List<i32> = List::Cons(7, Box::new(List::Cons(13, Box::new(List::Nil))));
 ```
 
 ### Pointer types
index 054552559dbec077fb5a1fd4533b3f0d40b83efb..0b686eb76dbfb2d5dcf1eba88d965d1c2b069cc7 100644 (file)
@@ -198,7 +198,7 @@ Rustdoc also supplies some extra sugar for helping with some tedious
 documentation examples. If a line is prefixed with `# `, then the line
 will not show up in the HTML documentation, but it will be used when
 testing the code block (NB. the space after the `#` is required, so
-that one can still write things like `#[deriving(Eq)]`).
+that one can still write things like `#[derive(Eq)]`).
 
 ~~~md
 ```
@@ -217,6 +217,35 @@ spawn(move || { fib(200); })
 The documentation online would look like `spawn(move || { fib(200); })`, but when
 testing this code, the `fib` function will be included (so it can compile).
 
+Rustdoc will automatically add a `main()` wrapper around your code, and in the right
+place. For example:
+
+```
+/// ```
+/// use std::rc::Rc;
+///
+/// let five = Rc::new(5);
+/// ```
+# fn foo() {}
+```
+
+This will end up testing:
+
+```
+fn main() {
+    use std::rc::Rc;
+    let five = Rc::new(5);
+}
+```
+
+Here's the full algorithm:
+
+1. Given a code block, if it does not contain `fn main`, it is wrapped in `fn main() { your_code }`
+2. Given that result, if it contains no `extern crate` directives but it also
+   contains the name of the crate being tested, then `extern crate <name>` is
+   injected at the top.
+3. Some common `allow` attributes are added for documentation examples at the top.
+
 ## Running tests (advanced)
 
 Running tests often requires some special configuration to filter tests, find
index 67fcb94326c409ff3853adbde3dda5043dda84da..eb9e2b24ac900e0d7f1090cc7697c057111bec19 100644 (file)
@@ -8,7 +8,7 @@ memory safe without using garbage collection.
 "The Rust Programming Language" is split into three sections, which you can
 navigate through the menu on the left.
 
-## Basics
+<h2 class="section-header"><a href="basic.html">Basics</a></h2>
 
 This section is a linear introduction to the basic syntax and semantics of
 Rust. It has individual sections on each part of Rust's syntax, and culminates
@@ -17,7 +17,7 @@ in a small project: a guessing game.
 After reading "Basics," you will have a good foundation to learn more about
 Rust, and can write very simple programs.
 
-## Intermediate
+<h2 class="section-header"><a href="intermediate.html">Intermediate</a></h2>
 
 This section contains individual chapters, which are self-contained. They focus
 on specific topics, and can be read in any order.
@@ -25,7 +25,7 @@ on specific topics, and can be read in any order.
 After reading "Intermediate," you will have a solid understanding of Rust,
 and will be able to understand most Rust code and write more complex programs.
 
-## Advanced
+<h2 class="section-header"><a href="advanced.html">Advanced</a></h2>
 
 In a similar fashion to "Intermediate," this section is full of individual,
 deep-dive chapters, which stand alone and can be read in any order. These
index 1a61c6d216b68054cda09231b979b8cfe7bdaa1b..aab03add905bb2f691b58f25cf40b147b7f67656 100644 (file)
@@ -26,7 +26,7 @@
     * [Iterators](iterators.md)
     * [Generics](generics.md)
     * [Traits](traits.md)
-    * [Tasks](tasks.md)
+    * [Threads](threads.md)
     * [Error Handling](error-handling.md)
 * [III: Advanced Topics](advanced.md)
     * [FFI](ffi.md)
index 11ced4b9f3c1d130a81180a8902fadb1495cd7cc..e7ac55bfbd30d4ccb26792f059054f8a4f1d0a2f 100644 (file)
@@ -82,7 +82,7 @@ arrays:
 
 ```{rust}
 let a = [0, 1, 2, 3, 4];
-let middle = a.slice(1, 4);     // A slice of a: just the elements [1,2,3]
+let middle = &a[1..4];     // A slice of a: just the elements 1, 2, and 3
 
 for e in middle.iter() {
     println!("{}", e);          // Prints 1, 2, 3
@@ -94,6 +94,6 @@ backed by arrays. Slices have type `&[T]`, which we'll talk about when we cover
 generics.
 
 We have now learned all of the most basic Rust concepts. We're ready to start
-building our guessing game, we just need to know one last thing: how to get
-input from the keyboard. You can't have a guessing game without the ability to
-guess!
+building ourselves a guessing game, we just need to know one last thing: how to
+get input from the keyboard. You can't have a guessing game without the ability
+to guess!
index cec9c1e7cf7dde178417ae75bfea51885f7f2e2c..5b49df92fe39691a60213e05e7f7f2f8cabe48c2 100644 (file)
@@ -110,25 +110,27 @@ passing two variables: one is an i32, and one is a function."
 Next, let's look at how `twice` is defined:
 
 ```{rust,ignore}
-fn twice(x: i32, f: |i32| -> i32) -> i32 {
+fn twice<F: Fn(i32) -> i32>(x: i32, f: F) -> i32 {
 ```
 
 `twice` takes two arguments, `x` and `f`. That's why we called it with two
 arguments. `x` is an `i32`, we've done that a ton of times. `f` is a function,
-though, and that function takes an `i32` and returns an `i32`. Notice
-how the `|i32| -> i32` syntax looks a lot like our definition of `square`
-above, if we added the return type in:
-
-```{rust}
-let square = |&: x: i32| -> i32 { x * x };
-//           |i32|       -> i32
-```
-
-This function takes an `i32` and returns an `i32`.
+though, and that function takes an `i32` and returns an `i32`. This is
+what the requirement `Fn(i32) -> i32` for the type parameter `F` says.
+You might ask yourself: why do we need to introduce a type parameter here?
+That is because in Rust each closure has its own unique type.
+So, not only do closures with different signatures have different types,
+but different closures with the *same* signature have *different* types!
+You can think of it this way: the behaviour of a closure is part of its type.
+And since we want to support many different closures that all take
+an `i32` and return an `i32` we introduced a type parameter that is able
+to represent all these closures. 
 
 This is the most complicated function signature we've seen yet! Give it a read
 a few times until you can see how it works. It takes a teeny bit of practice, and
-then it's easy.
+then it's easy. The good news is that this kind of passing a closure around
+can be very efficient. With all the type information available at compile-time
+the compiler can do wonders.
 
 Finally, `twice` returns an `i32` as well.
 
index fe7acaab5fc70ad56b86fa30cf4169d1dfb7ca2c..3c211b007cf9057b0a9f688794eba3f1fc17e795 100644 (file)
@@ -40,7 +40,8 @@ fn hello(name: &str) {
 ```
 
 When writing doc comments, adding sections for any arguments, return values,
-and providing some examples of usage is very, very helpful.
+and providing some examples of usage is very, very helpful. Don't worry about
+the `&str`, we'll get to it soon.
 
 You can use the [`rustdoc`](../rustdoc.html) tool to generate HTML documentation
 from these doc comments.
index 31d330b40222f212ee8bafaccb4354dff78b046a..5ad9fcd41f554f0052a788801ca03f94be2a06df 100644 (file)
@@ -23,10 +23,10 @@ let x: (i32, &str) = (1, "hello");
 As you can see, the type of a tuple looks just like the tuple, but with each
 position having a type name rather than the value. Careful readers will also
 note that tuples are heterogeneous: we have an `i32` and a `&str` in this tuple.
-You haven't seen `&str` as a type before, and we'll discuss the details of
-strings later. In systems programming languages, strings are a bit more complex
-than in other languages. For now, just read `&str` as a *string slice*, and
-we'll learn more soon.
+You have briefly seen `&str` used as a type before, and we'll discuss the
+details of strings later. In systems programming languages, strings are a bit
+more complex than in other languages. For now, just read `&str` as a *string
+slice*, and we'll learn more soon.
 
 You can access the fields in a tuple through a *destructuring let*. Here's
 an example:
@@ -182,7 +182,7 @@ and with a struct, we have actual names.
 
 There _is_ one case when a tuple struct is very useful, though, and that's a
 tuple struct with only one element. We call this a *newtype*, because it lets
-you create a new type that's a synonym for another one:
+you create a new type that's similar to another one:
 
 ```{rust}
 struct Inches(i32);
@@ -194,7 +194,8 @@ println!("length is {} inches", integer_length);
 ```
 
 As you can see here, you can extract the inner integer type through a
-destructuring `let`.
+destructuring `let`, as we discussed previously in 'tuples.' In this case, the
+`let Inches(integer_length)` assigns `10` to `integer_length`.
 
 ## Enums
 
index c179a263b35ed446031b477d2701c8e421d2b04c..c12090e2a614cee32f71c9c4a7f3e6c47edb1abf 100644 (file)
@@ -256,7 +256,7 @@ fn goodbye() -> String {
 }
 ```
 
-(This is "Sayoonara", if you're curious.)
+(This is "Sayōnara", if you're curious.)
 
 Now that we have our some functionality in our crate, let's try to use it from
 another crate.
@@ -559,7 +559,7 @@ Also, note that we `pub use`d before we declared our `mod`s. Rust requires that
 This will build and run:
 
 ```bash
-$ cargo build
+$ cargo run
    Compiling phrases v0.0.1 (file:///home/you/projects/phrases)
      Running `target/phrases`
 Hello in English: Hello!
index 6c444b741c5de36346af356eab69010b869db233..4b1c92239aed348f633b8837f571b4a6da5565a1 100644 (file)
@@ -1,6 +1,6 @@
 % Error Handling in Rust
 
-> The best-laid plans of mice and men
+> The best-laid plans of mice and men  
 > Often go awry
 >
 > "Tae a Moose", Robert Burns
@@ -181,7 +181,7 @@ errors that can occur.
 # Non-recoverable errors with `panic!`
 
 In the case of an error that is unexpected and not recoverable, the `panic!`
-macro will induce a panic. This will crash the current task, and give an error:
+macro will induce a panic. This will crash the current thread, and give an error:
 
 ```{rust,ignore}
 panic!("boom");
@@ -190,7 +190,7 @@ panic!("boom");
 gives
 
 ```text
-task '<main>' panicked at 'boom', hello.rs:2
+thread '<main>' panicked at 'boom', hello.rs:2
 ```
 
 when you run it.
index a65325af7be3db9532474e8a52ada8efed1975b0..e398ebe64db0bf059fe31c5940bbcf9f61a2c1bc 100644 (file)
@@ -166,12 +166,12 @@ GitHub](https://github.com/thestinger/rust-snappy).
 
 # Stack management
 
-Rust tasks by default run on a *large stack*. This is actually implemented as a
+Rust threads by default run on a *large stack*. This is actually implemented as a
 reserving a large segment of the address space and then lazily mapping in pages
 as they are needed. When calling an external C function, the code is invoked on
 the same stack as the rust stack. This means that there is no extra
 stack-switching mechanism in place because it is assumed that the large stack
-for the rust task is plenty for the C function to have.
+for the rust thread is plenty for the C function to have.
 
 A planned future improvement (not yet implemented at the time of this writing)
 is to have a guard page at the end of every rust stack. No rust function will
@@ -184,8 +184,8 @@ For normal external function usage, this all means that there shouldn't be any
 need for any extra effort on a user's perspective. The C stack naturally
 interleaves with the rust stack, and it's "large enough" for both to
 interoperate. If, however, it is determined that a larger stack is necessary,
-there are appropriate functions in the task spawning API to control the size of
-the stack of the task which is spawned.
+there are appropriate functions in the thread spawning API to control the size of
+the stack of the thread which is spawned.
 
 # Destructors
 
@@ -320,8 +320,7 @@ In the previously given examples the callbacks are invoked as a direct reaction
 to a function call to the external C library.
 The control over the current thread is switched from Rust to C to Rust for the
 execution of the callback, but in the end the callback is executed on the
-same thread (and Rust task) that lead called the function which triggered
-the callback.
+same thread that called the function which triggered the callback.
 
 Things get more complicated when the external library spawns its own threads
 and invokes callbacks from there.
@@ -329,7 +328,7 @@ In these cases access to Rust data structures inside the callbacks is
 especially unsafe and proper synchronization mechanisms must be used.
 Besides classical synchronization mechanisms like mutexes, one possibility in
 Rust is to use channels (in `std::comm`) to forward data from the C thread
-that invoked the callback into a Rust task.
+that invoked the callback into a Rust thread.
 
 If an asynchronous callback targets a special object in the Rust address space
 it is also absolutely necessary that no more callbacks are performed by the
index 2e32fdfa7947f0b976401e9c5a7e1225a36ead99..6980663651a4a27a30a4032b27e0747b46b14de0 100644 (file)
@@ -59,7 +59,7 @@ Unlike `let`, you _must_ declare the types of function arguments. This does
 not work:
 
 ```{ignore}
-fn print_number(x, y) {
+fn print_sum(x, y) {
     println!("x is: {}", x + y);
 }
 ```
@@ -67,7 +67,7 @@ fn print_number(x, y) {
 You get this error:
 
 ```text
-hello.rs:5:18: 5:19 error: expected `:` but found `,`
+hello.rs:5:18: 5:19 expected one of `!`, `:`, or `@`, found `)`
 hello.rs:5 fn print_number(x, y) {
 ```
 
index 16bd1e347b7c85c839848a130fa9016e197e11d5..474e7db6942e1e260d817a7fce8d13dc083a1e63 100644 (file)
@@ -239,7 +239,7 @@ use std::rand;
 fn main() {
     println!("Guess the number!");
 
-    let secret_number = (rand::random::<uint>() % 100u) + 1u;
+    let secret_number = (rand::random::<u32>() % 100) + 1;
 
     println!("The secret number is: {}", secret_number);
 
@@ -283,7 +283,7 @@ use std::cmp::Ordering;
 fn main() {
     println!("Guess the number!");
 
-    let secret_number = (rand::random::<uint>() % 100u) + 1u;
+    let secret_number = (rand::random::<u32>() % 100) + 1;
 
     println!("The secret number is: {}", secret_number);
 
@@ -318,7 +318,7 @@ $ cargo build
 src/main.rs:20:15: 20:20 error: mismatched types: expected `i32` but found `collections::string::String` (expected i32 but found struct collections::string::String)
 src/main.rs:20     match cmp(input, secret_number) {
                              ^~~~~
-src/main.rs:20:22: 20:35 error: mismatched types: expected `i32` but found `uint` (expected i32 but found uint)
+src/main.rs:20:22: 20:35 error: mismatched types: expected `i32` but found `u32` (expected i32 but found u32)
 src/main.rs:20     match cmp(input, secret_number) {
                                     ^~~~~~~~~~~~~
 error: aborting due to 2 previous errors
@@ -328,7 +328,7 @@ This often happens when writing Rust programs, and is one of Rust's greatest
 strengths. You try out some code, see if it compiles, and Rust tells you that
 you've done something wrong. In this case, our `cmp` function works on integers,
 but we've given it unsigned integers. In this case, the fix is easy, because
-we wrote the `cmp` function! Let's change it to take `uint`s:
+we wrote the `cmp` function! Let's change it to take `u32`s:
 
 ```{rust,ignore}
 use std::io;
@@ -338,7 +338,7 @@ use std::cmp::Ordering;
 fn main() {
     println!("Guess the number!");
 
-    let secret_number = (rand::random::<uint>() % 100u) + 1u;
+    let secret_number = (rand::random::<u32>() % 100) + 1;
 
     println!("The secret number is: {}", secret_number);
 
@@ -358,7 +358,7 @@ fn main() {
     }
 }
 
-fn cmp(a: uint, b: uint) -> Ordering {
+fn cmp(a: u32, b: u32) -> Ordering {
     if a < b { Ordering::Less }
     else if a > b { Ordering::Greater }
     else { Ordering::Equal }
@@ -370,13 +370,13 @@ And try compiling again:
 ```bash
 $ cargo build
    Compiling guessing_game v0.0.1 (file:///home/you/projects/guessing_game)
-src/main.rs:20:15: 20:20 error: mismatched types: expected `uint` but found `collections::string::String` (expected uint but found struct collections::string::String)
+src/main.rs:20:15: 20:20 error: mismatched types: expected `u32` but found `collections::string::String` (expected u32 but found struct collections::string::String)
 src/main.rs:20     match cmp(input, secret_number) {
                              ^~~~~
 error: aborting due to previous error
 ```
 
-This error is similar to the last one: we expected to get a `uint`, but we got
+This error is similar to the last one: we expected to get a `u32`, but we got
 a `String` instead! That's because our `input` variable is coming from the
 standard input, and you can guess anything. Try it:
 
@@ -393,14 +393,14 @@ Oops! Also, you'll note that we just ran our program even though it didn't compi
 This works because the older version we did successfully compile was still lying
 around. Gotta be careful!
 
-Anyway, we have a `String`, but we need a `uint`. What to do? Well, there's
+Anyway, we have a `String`, but we need a `u32`. What to do? Well, there's
 a function for that:
 
 ```{rust,ignore}
 let input = io::stdin().read_line()
                        .ok()
                        .expect("Failed to read line");
-let input_num: Option<uint> = input.parse();
+let input_num: Option<u32> = input.parse();
 ```
 
 The `parse` function takes in a `&str` value and converts it into something.
@@ -408,22 +408,22 @@ We tell it what kind of something with a type hint. Remember our type hint with
 `random()`? It looked like this:
 
 ```{rust,ignore}
-rand::random::<uint>();
+rand::random::<u32>();
 ```
 
 There's an alternate way of providing a hint too, and that's declaring the type
 in a `let`:
 
 ```{rust,ignore}
-let x: uint = rand::random();
+let x: u32 = rand::random();
 ```
 
-In this case, we say `x` is a `uint` explicitly, so Rust is able to properly
+In this case, we say `x` is a `u32` explicitly, so Rust is able to properly
 tell `random()` what to generate. In a similar fashion, both of these work:
 
 ```{rust,ignore}
-let input_num = "5".parse::<uint>();         // input_num: Option<uint>
-let input_num: Option<uint> = "5".parse();   // input_num: Option<uint>
+let input_num = "5".parse::<u32>();         // input_num: Option<u32>
+let input_num: Option<u32> = "5".parse();   // input_num: Option<u32>
 ```
 
 Anyway, with us now converting our input to a number, our code looks like this:
@@ -436,7 +436,7 @@ use std::cmp::Ordering;
 fn main() {
     println!("Guess the number!");
 
-    let secret_number = (rand::random::<uint>() % 100u) + 1u;
+    let secret_number = (rand::random::<u32>() % 100) + 1;
 
     println!("The secret number is: {}", secret_number);
 
@@ -445,7 +445,7 @@ fn main() {
     let input = io::stdin().read_line()
                            .ok()
                            .expect("Failed to read line");
-    let input_num: Option<uint> = input.parse();
+    let input_num: Option<u32> = input.parse();
 
     println!("You guessed: {}", input_num);
 
@@ -456,7 +456,7 @@ fn main() {
     }
 }
 
-fn cmp(a: uint, b: uint) -> Ordering {
+fn cmp(a: u32, b: u32) -> Ordering {
     if a < b { Ordering::Less }
     else if a > b { Ordering::Greater }
     else { Ordering::Equal }
@@ -468,13 +468,13 @@ Let's try it out!
 ```bash
 $ cargo build
    Compiling guessing_game v0.0.1 (file:///home/you/projects/guessing_game)
-src/main.rs:22:15: 22:24 error: mismatched types: expected `uint` but found `core::option::Option<uint>` (expected uint but found enum core::option::Option)
+src/main.rs:22:15: 22:24 error: mismatched types: expected `u32` but found `core::option::Option<u32>` (expected u32 but found enum core::option::Option)
 src/main.rs:22     match cmp(input_num, secret_number) {
                              ^~~~~~~~~
 error: aborting due to previous error
 ```
 
-Oh yeah! Our `input_num` has the type `Option<uint>`, rather than `uint`. We
+Oh yeah! Our `input_num` has the type `Option<u32>`, rather than `u32`. We
 need to unwrap the Option. If you remember from before, `match` is a great way
 to do that. Try this code:
 
@@ -486,7 +486,7 @@ use std::cmp::Ordering;
 fn main() {
     println!("Guess the number!");
 
-    let secret_number = (rand::random::<uint>() % 100u) + 1u;
+    let secret_number = (rand::random::<u32>() % 100) + 1;
 
     println!("The secret number is: {}", secret_number);
 
@@ -495,7 +495,7 @@ fn main() {
     let input = io::stdin().read_line()
                            .ok()
                            .expect("Failed to read line");
-    let input_num: Option<uint> = input.parse();
+    let input_num: Option<u32> = input.parse();
 
     let num = match input_num {
         Some(num) => num,
@@ -515,14 +515,14 @@ fn main() {
     }
 }
 
-fn cmp(a: uint, b: uint) -> Ordering {
+fn cmp(a: u32, b: u32) -> Ordering {
     if a < b { Ordering::Less }
     else if a > b { Ordering::Greater }
     else { Ordering::Equal }
 }
 ```
 
-We use a `match` to either give us the `uint` inside of the `Option`, or else
+We use a `match` to either give us the `u32` inside of the `Option`, or else
 print an error message and return. Let's give this a shot:
 
 ```bash
@@ -553,7 +553,7 @@ use std::cmp::Ordering;
 fn main() {
     println!("Guess the number!");
 
-    let secret_number = (rand::random::<uint>() % 100u) + 1u;
+    let secret_number = (rand::random::<u32>() % 100) + 1;
 
     println!("The secret number is: {}", secret_number);
 
@@ -562,7 +562,7 @@ fn main() {
     let input = io::stdin().read_line()
                            .ok()
                            .expect("Failed to read line");
-    let input_num: Option<uint> = input.trim().parse();
+    let input_num: Option<u32> = input.trim().parse();
 
     let num = match input_num {
         Some(num) => num,
@@ -582,7 +582,7 @@ fn main() {
     }
 }
 
-fn cmp(a: uint, b: uint) -> Ordering {
+fn cmp(a: u32, b: u32) -> Ordering {
     if a < b { Ordering::Less }
     else if a > b { Ordering::Greater }
     else { Ordering::Equal }
@@ -627,7 +627,7 @@ use std::cmp::Ordering;
 fn main() {
     println!("Guess the number!");
 
-    let secret_number = (rand::random::<uint>() % 100u) + 1u;
+    let secret_number = (rand::random::<u32>() % 100) + 1;
 
     println!("The secret number is: {}", secret_number);
 
@@ -638,7 +638,7 @@ fn main() {
         let input = io::stdin().read_line()
                                .ok()
                                .expect("Failed to read line");
-        let input_num: Option<uint> = input.trim().parse();
+        let input_num: Option<u32> = input.trim().parse();
 
         let num = match input_num {
             Some(num) => num,
@@ -659,7 +659,7 @@ fn main() {
     }
 }
 
-fn cmp(a: uint, b: uint) -> Ordering {
+fn cmp(a: u32, b: u32) -> Ordering {
     if a < b { Ordering::Less }
     else if a > b { Ordering::Greater }
     else { Ordering::Equal }
@@ -703,7 +703,7 @@ use std::cmp::Ordering;
 fn main() {
     println!("Guess the number!");
 
-    let secret_number = (rand::random::<uint>() % 100u) + 1u;
+    let secret_number = (rand::random::<u32>() % 100) + 1;
 
     println!("The secret number is: {}", secret_number);
 
@@ -714,7 +714,7 @@ fn main() {
         let input = io::stdin().read_line()
                                .ok()
                                .expect("Failed to read line");
-        let input_num: Option<uint> = input.trim().parse();
+        let input_num: Option<u32> = input.trim().parse();
 
         let num = match input_num {
             Some(num) => num,
@@ -738,7 +738,7 @@ fn main() {
     }
 }
 
-fn cmp(a: uint, b: uint) -> Ordering {
+fn cmp(a: u32, b: u32) -> Ordering {
     if a < b { Ordering::Less }
     else if a > b { Ordering::Greater }
     else { Ordering::Equal }
@@ -759,7 +759,7 @@ use std::cmp::Ordering;
 fn main() {
     println!("Guess the number!");
 
-    let secret_number = (rand::random::<uint>() % 100u) + 1u;
+    let secret_number = (rand::random::<u32>() % 100) + 1;
 
     println!("The secret number is: {}", secret_number);
 
@@ -770,7 +770,7 @@ fn main() {
         let input = io::stdin().read_line()
                                .ok()
                                .expect("Failed to read line");
-        let input_num: Option<uint> = input.trim().parse();
+        let input_num: Option<u32> = input.trim().parse();
 
         let num = match input_num {
             Some(num) => num,
@@ -794,7 +794,7 @@ fn main() {
     }
 }
 
-fn cmp(a: uint, b: uint) -> Ordering {
+fn cmp(a: u32, b: u32) -> Ordering {
     if a < b { Ordering::Less }
     else if a > b { Ordering::Greater }
     else { Ordering::Equal }
@@ -838,7 +838,7 @@ use std::cmp::Ordering;
 fn main() {
     println!("Guess the number!");
 
-    let secret_number = (rand::random::<uint>() % 100u) + 1u;
+    let secret_number = (rand::random::<u32>() % 100) + 1;
 
     loop {
 
@@ -847,7 +847,7 @@ fn main() {
         let input = io::stdin().read_line()
                                .ok()
                                .expect("Failed to read line");
-        let input_num: Option<uint> = input.trim().parse();
+        let input_num: Option<u32> = input.trim().parse();
 
         let num = match input_num {
             Some(num) => num,
@@ -871,7 +871,7 @@ fn main() {
     }
 }
 
-fn cmp(a: uint, b: uint) -> Ordering {
+fn cmp(a: u32, b: u32) -> Ordering {
     if a < b { Ordering::Less }
     else if a > b { Ordering::Greater }
     else { Ordering::Equal }
index 3cb14df1210a9af07524bdbb1921441a5c055326..640f0109b0697d841c0bed2d53a89d0014c612ca 100644 (file)
@@ -71,8 +71,8 @@ These lines define a *function* in Rust. The `main` function is special:
 it's the beginning of every Rust program. The first line says "I'm declaring a
 function named `main`, which takes no arguments and returns nothing." If there
 were arguments, they would go inside the parentheses (`(` and `)`), and because
-we aren't returning anything from this function, we've dropped that notation
-entirely.  We'll get to it later.
+we aren't returning anything from this function, we can omit the return type
+entirely. We'll get to it later.
 
 You'll also note that the function is wrapped in curly braces (`{` and `}`).
 Rust requires these around all function bodies. It is also considered good
index 8c9d89652b6676986eef2b0a4ac2bc008af486fb..ea1da167458ab4e17b61e286fddbb5accdebfb0a 100644 (file)
@@ -126,7 +126,7 @@ let y: i32 = if x == 5 { 10; } else { 15; };
 Note the semicolons after the 10 and 15. Rust will give us the following error:
 
 ```text
-error: mismatched types: expected `i32` but found `()` (expected i32 but found ())
+error: mismatched types: expected `i32`, found `()` (expected i32, found ())
 ```
 
 We expected an integer, but we got `()`. `()` is pronounced *unit*, and is a
index f54084a7fb9d3a679615100987c4e899ffaa1acb..2985477085e948278d18832aed30935857960bbd 100644 (file)
@@ -18,7 +18,7 @@ for (x = 0; x < 10; x++) {
 Instead, it looks like this:
 
 ```{rust}
-for x in range(0, 10) {
+for x in 0..10 {
     println!("{}", x); // x: i32
 }
 ```
@@ -38,7 +38,7 @@ valid for the loop body. Once the body is over, the next value is fetched from
 the iterator, and we loop another time. When there are no more values, the
 `for` loop is over.
 
-In our example, `range` is a function that takes a start and an end position,
+In our example, `0..10` is an expression that takes a start and an end position,
 and gives an iterator over those values. The upper bound is exclusive, though,
 so our loop will print `0` through `9`, not `10`.
 
@@ -54,7 +54,7 @@ The other kind of looping construct in Rust is the `while` loop. It looks like
 this:
 
 ```{rust}
-let mut x = 5u;       // mut x: uint
+let mut x = 5u32;       // mut x: u32
 let mut done = false; // mut done: bool
 
 while !done {
@@ -91,7 +91,7 @@ can do with safety and code generation, so you should always prefer
 Let's take a look at that `while` loop we had earlier:
 
 ```{rust}
-let mut x = 5u;
+let mut x = 5u32;
 let mut done = false;
 
 while !done {
@@ -108,7 +108,7 @@ modifying iteration: `break` and `continue`.
 In this case, we can write the loop in a better way with `break`:
 
 ```{rust}
-let mut x = 5u;
+let mut x = 5u32;
 
 loop {
     x += x - 3;
@@ -123,7 +123,7 @@ We now loop forever with `loop` and use `break` to break out early.
 iteration. This will only print the odd numbers:
 
 ```{rust}
-for x in range(0, 10) {
+for x in 0..10 {
     if x % 2 == 0 { continue; }
 
     println!("{}", x);
index c73fbefb2a4019352bfb7104ecfcc11c38049a92..0bc49365921c056b2e4eb58b731d8b4fbf5f1b6c 100644 (file)
@@ -42,7 +42,7 @@ the pattern in the above code:
 # let input_1 = T::SpecialA(0);
 # let input_2 = T::SpecialA(0);
 macro_rules! early_return {
-    ($inp:expr, $sp:path) => ( // invoke it like `(input_5 SpecialE)`
+    ($inp:expr, $sp:path) => ( // invoke it like `(input_5, SpecialE)`
         match $inp {
             $sp(x) => { return x; }
             _ => {}
@@ -59,7 +59,7 @@ early_return!(input_2, T::SpecialB);
 ~~~~
 
 Macros are defined in pattern-matching style: in the above example, the text
-`($inp:expr $sp:ident)` that appears on the left-hand side of the `=>` is the
+`($inp:expr, $sp:path)` that appears on the left-hand side of the `=>` is the
 *macro invocation syntax*, a pattern denoting how to write a call to the
 macro. The text on the right-hand side of the `=>`, beginning with `match
 $inp`, is the *macro transcription syntax*: what the macro expands to.
@@ -74,6 +74,8 @@ conforms to the following rules:
 2. `$` has special meaning (described below).
 3. The `()`s, `[]`s, and `{}`s it contains must balance. For example, `([)` is
 forbidden.
+4. Some arguments can be followed only by a limited set of separators, to
+avoid ambiguity (described below).
 
 Otherwise, the invocation syntax is free-form.
 
@@ -86,7 +88,8 @@ To take a fragment of Rust code as an argument, write `$` followed by a name
   `foo`.)
 * `expr` (an expression. Examples: `2 + 2`; `if true then { 1 } else { 2 }`;
   `f(42)`.)
-* `ty` (a type. Examples: `int`, `Vec<(char, String)>`, `&T`.)
+* `ty` (a type. Examples: `i32`, `Vec<(char, String)>`, `&T`.)
+* `path` (a path to struct or enum variant. Example: `T::SpecialA`)
 * `pat` (a pattern, usually appearing in a `match` or on the left-hand side of
   a declaration. Examples: `Some(t)`; `(17, 'a')`; `_`.)
 * `block` (a sequence of actions. Example: `{ log(error, "hi"); return 12; }`)
@@ -97,6 +100,12 @@ rules of tokenization apply,
 So `($x:ident -> (($e:expr)))`, though excessively fancy, would designate a macro
 that could be invoked like: `my_macro!(i->(( 2+2 )))`.
 
+To avoid ambiguity, macro invocation syntax must conform to the following rules:
+* `expr` must be followed by `=>`, `,` or `;`.
+* `ty` and `path` must be followed by `=>`, `,`, `:`, `=`, `>` or `as`.
+* `pat` must be followed by `=>`, `,` or `=`.
+* `ident` and `block` can be followed by any token.
+
 ## Invocation location
 
 A macro invocation may take the place of (and therefore expand to) an
index 946d0eee7df5ceea5de5d477eb55b2e622dde8a5..011746cf5b11799266927450c787111e970ad9c6 100644 (file)
@@ -81,15 +81,14 @@ therefore deallocates the memory for you. Here's the equivalent example in
 Rust:
 
 ```rust
-# use std::boxed::Box;
 {
-    let x = Box::new(5i);
+    let x = Box::new(5);
 }
 ```
 
-The `Box::new` function creates a `Box<T>` (specifically `Box<int>` in this
+The `Box::new` function creates a `Box<T>` (specifically `Box<i32>` in this
 case) by allocating a small segment of memory on the heap with enough space to
-fit an `int`. But where in the code is the box deallocated? We said before that
+fit an `i32`. But where in the code is the box deallocated? We said before that
 we must have a deallocation for each allocation. Rust handles this for you. It
 knows that our handle, `x`, is the owning reference to our box. Rust knows that
 `x` will go out of scope at the end of the block, and so it inserts a call to
@@ -101,14 +100,13 @@ This is pretty straightforward, but what happens when we want to pass our box
 to a function? Let's look at some code:
 
 ```rust
-# use std::boxed::Box;
 fn main() {
-    let x = Box::new(5i);
+    let x = Box::new(5);
 
     add_one(x);
 }
 
-fn add_one(mut num: Box<int>) {
+fn add_one(mut num: Box<i32>) {
     *num += 1;
 }
 ```
@@ -117,16 +115,15 @@ This code works, but it's not ideal. For example, let's add one more line of
 code, where we print out the value of `x`:
 
 ```{rust,ignore}
-# use std::boxed::Box;
 fn main() {
-    let x = Box::new(5i);
+    let x = Box::new(5);
 
     add_one(x);
 
     println!("{}", x);
 }
 
-fn add_one(mut num: Box<int>) {
+fn add_one(mut num: Box<i32>) {
     *num += 1;
 }
 ```
@@ -151,16 +148,15 @@ To fix this, we can have `add_one` give ownership back when it's done with the
 box:
 
 ```rust
-# use std::boxed::Box;
 fn main() {
-    let x = Box::new(5i);
+    let x = Box::new(5);
 
     let y = add_one(x);
 
     println!("{}", y);
 }
 
-fn add_one(mut num: Box<int>) -> Box<int> {
+fn add_one(mut num: Box<i32>) -> Box<i32> {
     *num += 1;
 
     num
@@ -179,7 +175,7 @@ to something another handle owns. It's called *borrowing*, and it's done with
 Here's the current state of our `add_one` function:
 
 ```rust
-fn add_one(mut num: Box<int>) -> Box<int> {
+fn add_one(mut num: Box<i32>) -> Box<i32> {
     *num += 1;
 
     num
@@ -199,14 +195,34 @@ period. This is also called *borrowing*. Here's a version of `add_one` which
 borrows its argument rather than taking ownership:
 
 ```rust
-fn add_one(num: &mut int) {
+fn add_one(num: &mut i32) {
     *num += 1;
 }
 ```
 
-This function borrows an `int` from its caller, and then increments it. When
+This function borrows an `i32` from its caller, and then increments it. When
 the function is over, and `num` goes out of scope, the borrow is over.
 
+We have to change our `main` a bit too:
+
+```rust
+fn main() {
+    let mut x = 5;
+
+    add_one(&mut x);
+
+    println!("{}", x);
+}
+
+fn add_one(num: &mut i32) {
+    *num += 1;
+}
+```
+
+We don't need to assign the result of `add_one()` anymore, because it doesn't
+return anything anymore. This is because we're not passing ownership back,
+since we just borrow, not take ownership.
+
 # Lifetimes
 
 Lending out a reference to a resource that someone else owns can be
@@ -225,10 +241,10 @@ To fix this, we have to make sure that step four never happens after step
 three. The ownership system in Rust does this through a concept called
 *lifetimes*, which describe the scope that a reference is valid for.
 
-Let's look at that function which borrows an `int` again:
+Remember the function that borrowed an `i32`? Let's look at it again.
 
 ```rust
-fn add_one(num: &int) -> int {
+fn add_one(num: &i32) -> i32 {
     *num + 1
 }
 ```
@@ -239,7 +255,7 @@ cover the others later. Without eliding the lifetimes, `add_one` looks like
 this:
 
 ```rust
-fn add_one<'a>(num: &'a int) -> int {
+fn add_one<'a>(num: &'a i32) -> i32 {
     *num + 1
 }
 ```
@@ -262,22 +278,22 @@ fn add_two<'a, 'b>(...)
 Then in our parameter list, we use the lifetimes we've named:
 
 ```{rust,ignore}
-...(num: &'a int) -> ...
+...(num: &'a i32) -> ...
 ```
 
-If you compare `&int` to `&'a int`, they're the same, it's just that the
-lifetime `'a` has snuck in between the `&` and the `int`. We read `&int` as "a
-reference to an int" and `&'a int` as "a reference to an int with the lifetime 'a.'"
+If you compare `&i32` to `&'a i32`, they're the same, it's just that the
+lifetime `'a` has snuck in between the `&` and the `i32`. We read `&i32` as "a
+reference to an i32" and `&'a i32` as "a reference to an i32 with the lifetime 'a.'"
 
 Why do lifetimes matter? Well, for example, here's some code:
 
 ```rust
 struct Foo<'a> {
-    x: &'a int,
+    x: &'a i32,
 }
 
 fn main() {
-    let y = &5i; // this is the same as `let _y = 5; let y = &_y;
+    let y = &5; // this is the same as `let _y = 5; let y = &_y;
     let f = Foo { x: y };
 
     println!("{}", f.x);
@@ -288,7 +304,7 @@ As you can see, `struct`s can also have lifetimes. In a similar way to functions
 
 ```{rust}
 struct Foo<'a> {
-# x: &'a int,
+# x: &'a i32,
 # }
 ```
 
@@ -296,12 +312,12 @@ declares a lifetime, and
 
 ```rust
 # struct Foo<'a> {
-x: &'a int,
+x: &'a i32,
 # }
 ```
 
 uses it. So why do we need a lifetime here? We need to ensure that any reference
-to a `Foo` cannot outlive the reference to an `int` it contains.
+to a `Foo` cannot outlive the reference to an `i32` it contains.
 
 ## Thinking in scopes
 
@@ -310,7 +326,7 @@ valid for. For example:
 
 ```rust
 fn main() {
-    let y = &5i;    // -+ y goes into scope
+    let y = &5;    // -+ y goes into scope
                     //  |
     // stuff        //  |
                     //  |
@@ -321,11 +337,11 @@ Adding in our `Foo`:
 
 ```rust
 struct Foo<'a> {
-    x: &'a int,
+    x: &'a i32,
 }
 
 fn main() {
-    let y = &5i;          // -+ y goes into scope
+    let y = &5;          // -+ y goes into scope
     let f = Foo { x: y }; // -+ f goes into scope
     // stuff              //  |
                           //  |
@@ -337,14 +353,14 @@ This code won't work:
 
 ```{rust,ignore}
 struct Foo<'a> {
-    x: &'a int,
+    x: &'a i32,
 }
 
 fn main() {
     let x;                    // -+ x goes into scope
                               //  |
     {                         //  |
-        let y = &5i;          // ---+ y goes into scope
+        let y = &5;          // ---+ y goes into scope
         let f = Foo { x: y }; // ---+ f goes into scope
         x = &f.x;             //  | | error here
     }                         // ---+ f and y go out of scope
@@ -375,12 +391,12 @@ alive: they are baked into the data segment of the final binary. Another
 example are globals:
 
 ```rust
-static FOO: int = 5i;
-let x: &'static int = &FOO;
+static FOO: i32 = 5;
+let x: &'static i32 = &FOO;
 ```
 
-This adds an `int` to the data segment of the binary, and FOO is a reference to
-it.
+This adds an `i32` to the data segment of the binary, and `FOO` is a reference
+to it.
 
 # Shared Ownership
 
@@ -395,7 +411,7 @@ struct Car {
 }
 
 struct Wheel {
-    size: int,
+    size: i32,
     owner: Car,
 }
 
@@ -431,7 +447,7 @@ struct Car {
 }
 
 struct Wheel {
-    size: int,
+    size: i32,
     owner: Rc<Car>,
 }
 
@@ -504,15 +520,15 @@ what the elided lifetimes are expand to:
 fn print(s: &str);                                      // elided
 fn print<'a>(s: &'a str);                               // expanded
 
-fn debug(lvl: uint, s: &str);                           // elided
-fn debug<'a>(lvl: uint, s: &'a str);                    // expanded
+fn debug(lvl: u32, s: &str);                           // elided
+fn debug<'a>(lvl: u32, s: &'a str);                    // expanded
 
 // In the preceeding example, `lvl` doesn't need a lifetime because it's not a
 // reference (`&`). Only things relating to references (such as a `struct`
 // which contains a reference) need lifetimes.
 
-fn substr(s: &str, until: uint) -> &str;                // elided
-fn substr<'a>(s: &'a str, until: uint) -> &'a str;      // expanded
+fn substr(s: &str, until: u32) -> &str;                // elided
+fn substr<'a>(s: &'a str, until: u32) -> &'a str;      // expanded
 
 fn get_str() -> &str;                                   // ILLEGAL, no inputs
 
index 2fc361ca1b2841eaae1809c65d7aec3392ba9e49..4cd39d407a243b184c80fa590cbf0dba2a84ef78 100644 (file)
@@ -126,7 +126,7 @@ The advantages over a simple `fn(&str) -> uint` are:
   a way to define new literal syntax for any data type.
 
 In addition to procedural macros, you can define new
-[`deriving`](../reference.html#deriving)-like attributes and other kinds of
+[`derive`](../reference.html#derive)-like attributes and other kinds of
 extensions.  See
 [`Registry::register_syntax_extension`](../rustc/plugin/registry/struct.Registry.html#method.register_syntax_extension)
 and the [`SyntaxExtension`
index 63c16ef191e06787cda71640225ed97c20bc4336..0c72e5c404cc9e30328067dc9d02333e1c641523 100644 (file)
@@ -721,11 +721,10 @@ fn main() {
 This gives you flexibility without sacrificing performance.
 
 You may think that this gives us terrible performance: return a value and then
-immediately box it up ?! Isn't that the worst of both worlds? Rust is smarter
-than that. There is no copy in this code. `main` allocates enough room for the
-`box`, passes a pointer to that memory into `foo` as `x`, and then `foo` writes
-the value straight into that pointer. This writes the return value directly into
-the allocated box.
+immediately box it up ?! Isn't this pattern the worst of both worlds? Rust is
+smarter than that. There is no copy in this code. `main` allocates enough room
+for the `box`, passes a pointer to that memory into `foo` as `x`, and then
+`foo` writes the value straight into the `Box<T>`.
 
 This is important enough that it bears repeating: pointers are not for
 optimizing returning values from your code. Allow the caller to choose how they
diff --git a/src/doc/trpl/tasks.md b/src/doc/trpl/tasks.md
deleted file mode 100644 (file)
index 4c6a7f1..0000000
+++ /dev/null
@@ -1,384 +0,0 @@
-% The Rust Threads and Communication Guide
-
-**NOTE** This guide is badly out of date and needs to be rewritten.
-
-# Introduction
-
-Rust provides safe concurrent abstractions through a number of core library
-primitives. This guide will describe the concurrency model in Rust, how it
-relates to the Rust type system, and introduce the fundamental library
-abstractions for constructing concurrent programs.
-
-Threads provide failure isolation and recovery. When a fatal error occurs in Rust
-code as a result of an explicit call to `panic!()`, an assertion failure, or
-another invalid operation, the runtime system destroys the entire thread. Unlike
-in languages such as Java and C++, there is no way to `catch` an exception.
-Instead, threads may monitor each other to see if they panic.
-
-Threads use Rust's type system to provide strong memory safety guarantees.  In
-particular, the type system guarantees that threads cannot induce a data race
-from shared mutable state.
-
-# Basics
-
-At its simplest, creating a thread is a matter of calling the `spawn` function
-with a closure argument. `spawn` executes the closure in the new thread.
-
-```{rust,ignore}
-# use std::thread::spawn;
-
-// Print something profound in a different thread using a named function
-fn print_message() { println!("I am running in a different thread!"); }
-spawn(print_message);
-
-// Alternatively, use a `move ||` expression instead of a named function.
-// `||` expressions evaluate to an unnamed closure. The `move` keyword
-// indicates that the closure should take ownership of any variables it
-// touches.
-spawn(move || println!("I am also running in a different thread!"));
-```
-
-In Rust, a thread is not a concept that appears in the language semantics.
-Instead, Rust's type system provides all the tools necessary to implement safe
-concurrency: particularly, ownership. The language leaves the implementation
-details to the standard library.
-
-The `spawn` function has the type signature: `fn
-spawn<F:FnOnce()+Send>(f: F)`.  This indicates that it takes as
-argument a closure (of type `F`) that it will run exactly once. This
-closure is limited to capturing `Send`-able data from its environment
-(that is, data which is deeply owned). Limiting the closure to `Send`
-ensures that `spawn` can safely move the entire closure and all its
-associated state into an entirely different thread for execution.
-
-```{rust,ignore}
-# use std::thread::spawn;
-# fn generate_thread_number() -> int { 0 }
-// Generate some state locally
-let child_thread_number = generate_thread_number();
-
-spawn(move || {
-    // Capture it in the remote thread. The `move` keyword indicates
-    // that this closure should move `child_thread_number` into its
-    // environment, rather than capturing a reference into the
-    // enclosing stack frame.
-    println!("I am child number {}", child_thread_number);
-});
-```
-
-## Communication
-
-Now that we have spawned a new thread, it would be nice if we could communicate
-with it. For this, we use *channels*. A channel is simply a pair of endpoints:
-one for sending messages and another for receiving messages.
-
-The simplest way to create a channel is to use the `channel` function to create a
-`(Sender, Receiver)` pair. In Rust parlance, a *sender* is a sending endpoint
-of a channel, and a *receiver* is the receiving endpoint. Consider the following
-example of calculating two results concurrently:
-
-```{rust,ignore}
-# use std::thread::spawn;
-
-let (tx, rx): (Sender<int>, Receiver<int>) = channel();
-
-spawn(move || {
-    let result = some_expensive_computation();
-    tx.send(result);
-});
-
-some_other_expensive_computation();
-let result = rx.recv();
-# fn some_expensive_computation() -> int { 42 }
-# fn some_other_expensive_computation() {}
-```
-
-Let's examine this example in detail. First, the `let` statement creates a
-stream for sending and receiving integers (the left-hand side of the `let`,
-`(tx, rx)`, is an example of a destructuring let: the pattern separates a tuple
-into its component parts).
-
-```{rust,ignore}
-let (tx, rx): (Sender<int>, Receiver<int>) = channel();
-```
-
-The child thread will use the sender to send data to the parent thread, which will
-wait to receive the data on the receiver. The next statement spawns the child
-thread.
-
-```{rust,ignore}
-# use std::thread::spawn;
-# fn some_expensive_computation() -> int { 42 }
-# let (tx, rx) = channel();
-spawn(move || {
-    let result = some_expensive_computation();
-    tx.send(result);
-});
-```
-
-Notice that the creation of the thread closure transfers `tx` to the child thread
-implicitly: the closure captures `tx` in its environment. Both `Sender` and
-`Receiver` are sendable types and may be captured into threads or otherwise
-transferred between them. In the example, the child thread runs an expensive
-computation, then sends the result over the captured channel.
-
-Finally, the parent continues with some other expensive computation, then waits
-for the child's result to arrive on the receiver:
-
-```{rust,ignore}
-# fn some_other_expensive_computation() {}
-# let (tx, rx) = channel::<int>();
-# tx.send(0);
-some_other_expensive_computation();
-let result = rx.recv();
-```
-
-The `Sender` and `Receiver` pair created by `channel` enables efficient
-communication between a single sender and a single receiver, but multiple
-senders cannot use a single `Sender` value, and multiple receivers cannot use a
-single `Receiver` value.  What if our example needed to compute multiple
-results across a number of threads? The following program is ill-typed:
-
-```{rust,ignore}
-# fn some_expensive_computation() -> int { 42 }
-let (tx, rx) = channel();
-
-spawn(move || {
-    tx.send(some_expensive_computation());
-});
-
-// ERROR! The previous spawn statement already owns the sender,
-// so the compiler will not allow it to be captured again
-spawn(move || {
-    tx.send(some_expensive_computation());
-});
-```
-
-Instead we can clone the `tx`, which allows for multiple senders.
-
-```{rust,ignore}
-let (tx, rx) = channel();
-
-for init_val in range(0u, 3) {
-    // Create a new channel handle to distribute to the child thread
-    let child_tx = tx.clone();
-    spawn(move || {
-        child_tx.send(some_expensive_computation(init_val));
-    });
-}
-
-let result = rx.recv() + rx.recv() + rx.recv();
-# fn some_expensive_computation(_i: uint) -> int { 42 }
-```
-
-Cloning a `Sender` produces a new handle to the same channel, allowing multiple
-threads to send data to a single receiver. It upgrades the channel internally in
-order to allow this functionality, which means that channels that are not
-cloned can avoid the overhead required to handle multiple senders. But this
-fact has no bearing on the channel's usage: the upgrade is transparent.
-
-Note that the above cloning example is somewhat contrived since you could also
-simply use three `Sender` pairs, but it serves to illustrate the point. For
-reference, written with multiple streams, it might look like the example below.
-
-```{rust,ignore}
-# use std::thread::spawn;
-
-// Create a vector of ports, one for each child thread
-let rxs = Vec::from_fn(3, |init_val| {
-    let (tx, rx) = channel();
-    spawn(move || {
-        tx.send(some_expensive_computation(init_val));
-    });
-    rx
-});
-
-// Wait on each port, accumulating the results
-let result = rxs.iter().fold(0, |accum, rx| accum + rx.recv() );
-# fn some_expensive_computation(_i: uint) -> int { 42 }
-```
-
-## Backgrounding computations: Futures
-
-With `sync::Future`, rust has a mechanism for requesting a computation and
-getting the result later.
-
-The basic example below illustrates this.
-
-```{rust,ignore}
-# #![allow(deprecated)]
-use std::sync::Future;
-
-# fn main() {
-# fn make_a_sandwich() {};
-fn fib(n: u64) -> u64 {
-    // lengthy computation returning an uint
-    12586269025
-}
-
-let mut delayed_fib = Future::spawn(move || fib(50));
-make_a_sandwich();
-println!("fib(50) = {}", delayed_fib.get())
-# }
-```
-
-The call to `future::spawn` immediately returns a `future` object regardless of
-how long it takes to run `fib(50)`. You can then make yourself a sandwich while
-the computation of `fib` is running. The result of the execution of the method
-is obtained by calling `get` on the future. This call will block until the
-value is available (*i.e.* the computation is complete). Note that the future
-needs to be mutable so that it can save the result for next time `get` is
-called.
-
-Here is another example showing how futures allow you to background
-computations. The workload will be distributed on the available cores.
-
-```{rust,ignore}
-# #![allow(deprecated)]
-# use std::num::Float;
-# use std::sync::Future;
-fn partial_sum(start: uint) -> f64 {
-    let mut local_sum = 0f64;
-    for num in range(start*100000, (start+1)*100000) {
-        local_sum += (num as f64 + 1.0).powf(-2.0);
-    }
-    local_sum
-}
-
-fn main() {
-    let mut futures = Vec::from_fn(200, |ind| Future::spawn(move || partial_sum(ind)));
-
-    let mut final_res = 0f64;
-    for ft in futures.iter_mut()  {
-        final_res += ft.get();
-    }
-    println!("π^2/6 is not far from : {}", final_res);
-}
-```
-
-## Sharing without copying: Arc
-
-To share data between threads, a first approach would be to only use channel as
-we have seen previously. A copy of the data to share would then be made for
-each thread. In some cases, this would add up to a significant amount of wasted
-memory and would require copying the same data more than necessary.
-
-To tackle this issue, one can use an Atomically Reference Counted wrapper
-(`Arc`) as implemented in the `sync` library of Rust. With an Arc, the data
-will no longer be copied for each thread. The Arc acts as a reference to the
-shared data and only this reference is shared and cloned.
-
-Here is a small example showing how to use Arcs. We wish to run concurrently
-several computations on a single large vector of floats. Each thread needs the
-full vector to perform its duty.
-
-```{rust,ignore}
-use std::num::Float;
-use std::rand;
-use std::sync::Arc;
-
-fn pnorm(nums: &[f64], p: uint) -> f64 {
-    nums.iter().fold(0.0, |a, b| a + b.powf(p as f64)).powf(1.0 / (p as f64))
-}
-
-fn main() {
-    let numbers = Vec::from_fn(1000000, |_| rand::random::<f64>());
-    let numbers_arc = Arc::new(numbers);
-
-    for num in range(1u, 10) {
-        let thread_numbers = numbers_arc.clone();
-
-        spawn(move || {
-            println!("{}-norm = {}", num, pnorm(thread_numbers.as_slice(), num));
-        });
-    }
-}
-```
-
-The function `pnorm` performs a simple computation on the vector (it computes
-the sum of its items at the power given as argument and takes the inverse power
-of this value). The Arc on the vector is created by the line:
-
-```{rust,ignore}
-# use std::rand;
-# use std::sync::Arc;
-# fn main() {
-# let numbers = Vec::from_fn(1000000, |_| rand::random::<f64>());
-let numbers_arc = Arc::new(numbers);
-# }
-```
-
-and a clone is captured for each thread via a procedure. This only copies
-the wrapper and not its contents. Within the thread's procedure, the captured
-Arc reference can be used as a shared reference to the underlying vector as
-if it were local.
-
-```{rust,ignore}
-# use std::rand;
-# use std::sync::Arc;
-# fn pnorm(nums: &[f64], p: uint) -> f64 { 4.0 }
-# fn main() {
-# let numbers=Vec::from_fn(1000000, |_| rand::random::<f64>());
-# let numbers_arc = Arc::new(numbers);
-# let num = 4;
-let thread_numbers = numbers_arc.clone();
-spawn(move || {
-    // Capture thread_numbers and use it as if it was the underlying vector
-    println!("{}-norm = {}", num, pnorm(thread_numbers.as_slice(), num));
-});
-# }
-```
-
-# Handling thread panics
-
-Rust has a built-in mechanism for raising exceptions. The `panic!()` macro
-(which can also be written with an error string as an argument: `panic!(
-~reason)`) and the `assert!` construct (which effectively calls `panic!()` if a
-boolean expression is false) are both ways to raise exceptions. When a thread
-raises an exception, the thread unwinds its stack—running destructors and
-freeing memory along the way—and then exits. Unlike exceptions in C++,
-exceptions in Rust are unrecoverable within a single thread: once a thread panics,
-there is no way to "catch" the exception.
-
-While it isn't possible for a thread to recover from panicking, threads may notify
-each other if they panic. The simplest way of handling a panic is with the
-`try` function, which is similar to `spawn`, but immediately blocks and waits
-for the child thread to finish. `try` returns a value of type
-`Result<T, Box<Any + Send>>`. `Result` is an `enum` type with two variants:
-`Ok` and `Err`. In this case, because the type arguments to `Result` are `int`
-and `()`, callers can pattern-match on a result to check whether it's an `Ok`
-result with an `int` field (representing a successful result) or an `Err` result
-(representing termination with an error).
-
-```{rust,ignore}
-# use std::thread::Thread;
-# fn some_condition() -> bool { false }
-# fn calculate_result() -> int { 0 }
-let result: Result<int, Box<std::any::Any + Send>> = Thread::spawn(move || {
-    if some_condition() {
-        calculate_result()
-    } else {
-        panic!("oops!");
-    }
-}).join();
-assert!(result.is_err());
-```
-
-Unlike `spawn`, the function spawned using `try` may return a value, which
-`try` will dutifully propagate back to the caller in a [`Result`] enum. If the
-child thread terminates successfully, `try` will return an `Ok` result; if the
-child thread panics, `try` will return an `Error` result.
-
-[`Result`]: ../std/result/index.html
-
-> *Note:* A panicked thread does not currently produce a useful error
-> value (`try` always returns `Err(())`). In the
-> future, it may be possible for threads to intercept the value passed to
-> `panic!()`.
-
-But not all panics are created equal. In some cases you might need to abort
-the entire program (perhaps you're writing an assert which, if it trips,
-indicates an unrecoverable logic error); in other cases you might want to
-contain the panic at a certain boundary (perhaps a small piece of input from
-the outside world, which you happen to be processing in parallel, is malformed
-such that the processing thread cannot proceed).
index 66da6395a5e09ae3b040a28b1dc5a8bc3ae64324..aefc7d7aa3d3ce09622e8ed9e40ac69adfa1126e 100644 (file)
@@ -96,7 +96,7 @@ test it_works ... FAILED
 failures:
 
 ---- it_works stdout ----
-        task 'it_works' panicked at 'assertion failed: false', /home/steve/tmp/adder/src/lib.rs:3
+        thread 'it_works' panicked at 'assertion failed: false', /home/steve/tmp/adder/src/lib.rs:3
 
 
 
@@ -105,7 +105,7 @@ failures:
 
 test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured
 
-task '<main>' panicked at 'Some tests failed', /home/steve/src/rust/src/libtest/lib.rs:247
+thread '<main>' panicked at 'Some tests failed', /home/steve/src/rust/src/libtest/lib.rs:247
 ```
 
 Rust indicates that our test failed:
@@ -254,7 +254,6 @@ a large module, and so this is a common use of the `glob` feature. Let's change
 our `src/lib.rs` to make use of it:
 
 ```{rust,ignore}
-#![feature(globs)]
 
 pub fn add_two(a: i32) -> i32 {
     a + 2
@@ -271,8 +270,7 @@ mod tests {
 }
 ```
 
-Note the `feature` attribute, as well as the different `use` line. Now we run
-our tests:
+Note the different `use` line. Now we run our tests:
 
 ```bash
 $ cargo test
@@ -370,8 +368,6 @@ with examples:
 //! assert_eq!(4, adder::add_two(2));
 //! ```
 
-#![feature(globs)]
-
 /// This function adds two to its argument.
 ///
 /// # Examples
@@ -440,8 +436,6 @@ Rust also supports benchmark tests, which can test the performance of your
 code. Let's make our `src/lib.rs` look like this (comments elided):
 
 ```{rust,ignore}
-#![feature(globs)]
-
 extern crate test;
 
 pub fn add_two(a: i32) -> i32 {
diff --git a/src/doc/trpl/threads.md b/src/doc/trpl/threads.md
new file mode 100644 (file)
index 0000000..4c6a7f1
--- /dev/null
@@ -0,0 +1,384 @@
+% The Rust Threads and Communication Guide
+
+**NOTE** This guide is badly out of date and needs to be rewritten.
+
+# Introduction
+
+Rust provides safe concurrent abstractions through a number of core library
+primitives. This guide will describe the concurrency model in Rust, how it
+relates to the Rust type system, and introduce the fundamental library
+abstractions for constructing concurrent programs.
+
+Threads provide failure isolation and recovery. When a fatal error occurs in Rust
+code as a result of an explicit call to `panic!()`, an assertion failure, or
+another invalid operation, the runtime system destroys the entire thread. Unlike
+in languages such as Java and C++, there is no way to `catch` an exception.
+Instead, threads may monitor each other to see if they panic.
+
+Threads use Rust's type system to provide strong memory safety guarantees.  In
+particular, the type system guarantees that threads cannot induce a data race
+from shared mutable state.
+
+# Basics
+
+At its simplest, creating a thread is a matter of calling the `spawn` function
+with a closure argument. `spawn` executes the closure in the new thread.
+
+```{rust,ignore}
+# use std::thread::spawn;
+
+// Print something profound in a different thread using a named function
+fn print_message() { println!("I am running in a different thread!"); }
+spawn(print_message);
+
+// Alternatively, use a `move ||` expression instead of a named function.
+// `||` expressions evaluate to an unnamed closure. The `move` keyword
+// indicates that the closure should take ownership of any variables it
+// touches.
+spawn(move || println!("I am also running in a different thread!"));
+```
+
+In Rust, a thread is not a concept that appears in the language semantics.
+Instead, Rust's type system provides all the tools necessary to implement safe
+concurrency: particularly, ownership. The language leaves the implementation
+details to the standard library.
+
+The `spawn` function has the type signature: `fn
+spawn<F:FnOnce()+Send>(f: F)`.  This indicates that it takes as
+argument a closure (of type `F`) that it will run exactly once. This
+closure is limited to capturing `Send`-able data from its environment
+(that is, data which is deeply owned). Limiting the closure to `Send`
+ensures that `spawn` can safely move the entire closure and all its
+associated state into an entirely different thread for execution.
+
+```{rust,ignore}
+# use std::thread::spawn;
+# fn generate_thread_number() -> int { 0 }
+// Generate some state locally
+let child_thread_number = generate_thread_number();
+
+spawn(move || {
+    // Capture it in the remote thread. The `move` keyword indicates
+    // that this closure should move `child_thread_number` into its
+    // environment, rather than capturing a reference into the
+    // enclosing stack frame.
+    println!("I am child number {}", child_thread_number);
+});
+```
+
+## Communication
+
+Now that we have spawned a new thread, it would be nice if we could communicate
+with it. For this, we use *channels*. A channel is simply a pair of endpoints:
+one for sending messages and another for receiving messages.
+
+The simplest way to create a channel is to use the `channel` function to create a
+`(Sender, Receiver)` pair. In Rust parlance, a *sender* is a sending endpoint
+of a channel, and a *receiver* is the receiving endpoint. Consider the following
+example of calculating two results concurrently:
+
+```{rust,ignore}
+# use std::thread::spawn;
+
+let (tx, rx): (Sender<int>, Receiver<int>) = channel();
+
+spawn(move || {
+    let result = some_expensive_computation();
+    tx.send(result);
+});
+
+some_other_expensive_computation();
+let result = rx.recv();
+# fn some_expensive_computation() -> int { 42 }
+# fn some_other_expensive_computation() {}
+```
+
+Let's examine this example in detail. First, the `let` statement creates a
+stream for sending and receiving integers (the left-hand side of the `let`,
+`(tx, rx)`, is an example of a destructuring let: the pattern separates a tuple
+into its component parts).
+
+```{rust,ignore}
+let (tx, rx): (Sender<int>, Receiver<int>) = channel();
+```
+
+The child thread will use the sender to send data to the parent thread, which will
+wait to receive the data on the receiver. The next statement spawns the child
+thread.
+
+```{rust,ignore}
+# use std::thread::spawn;
+# fn some_expensive_computation() -> int { 42 }
+# let (tx, rx) = channel();
+spawn(move || {
+    let result = some_expensive_computation();
+    tx.send(result);
+});
+```
+
+Notice that the creation of the thread closure transfers `tx` to the child thread
+implicitly: the closure captures `tx` in its environment. Both `Sender` and
+`Receiver` are sendable types and may be captured into threads or otherwise
+transferred between them. In the example, the child thread runs an expensive
+computation, then sends the result over the captured channel.
+
+Finally, the parent continues with some other expensive computation, then waits
+for the child's result to arrive on the receiver:
+
+```{rust,ignore}
+# fn some_other_expensive_computation() {}
+# let (tx, rx) = channel::<int>();
+# tx.send(0);
+some_other_expensive_computation();
+let result = rx.recv();
+```
+
+The `Sender` and `Receiver` pair created by `channel` enables efficient
+communication between a single sender and a single receiver, but multiple
+senders cannot use a single `Sender` value, and multiple receivers cannot use a
+single `Receiver` value.  What if our example needed to compute multiple
+results across a number of threads? The following program is ill-typed:
+
+```{rust,ignore}
+# fn some_expensive_computation() -> int { 42 }
+let (tx, rx) = channel();
+
+spawn(move || {
+    tx.send(some_expensive_computation());
+});
+
+// ERROR! The previous spawn statement already owns the sender,
+// so the compiler will not allow it to be captured again
+spawn(move || {
+    tx.send(some_expensive_computation());
+});
+```
+
+Instead we can clone the `tx`, which allows for multiple senders.
+
+```{rust,ignore}
+let (tx, rx) = channel();
+
+for init_val in range(0u, 3) {
+    // Create a new channel handle to distribute to the child thread
+    let child_tx = tx.clone();
+    spawn(move || {
+        child_tx.send(some_expensive_computation(init_val));
+    });
+}
+
+let result = rx.recv() + rx.recv() + rx.recv();
+# fn some_expensive_computation(_i: uint) -> int { 42 }
+```
+
+Cloning a `Sender` produces a new handle to the same channel, allowing multiple
+threads to send data to a single receiver. It upgrades the channel internally in
+order to allow this functionality, which means that channels that are not
+cloned can avoid the overhead required to handle multiple senders. But this
+fact has no bearing on the channel's usage: the upgrade is transparent.
+
+Note that the above cloning example is somewhat contrived since you could also
+simply use three `Sender` pairs, but it serves to illustrate the point. For
+reference, written with multiple streams, it might look like the example below.
+
+```{rust,ignore}
+# use std::thread::spawn;
+
+// Create a vector of ports, one for each child thread
+let rxs = Vec::from_fn(3, |init_val| {
+    let (tx, rx) = channel();
+    spawn(move || {
+        tx.send(some_expensive_computation(init_val));
+    });
+    rx
+});
+
+// Wait on each port, accumulating the results
+let result = rxs.iter().fold(0, |accum, rx| accum + rx.recv() );
+# fn some_expensive_computation(_i: uint) -> int { 42 }
+```
+
+## Backgrounding computations: Futures
+
+With `sync::Future`, rust has a mechanism for requesting a computation and
+getting the result later.
+
+The basic example below illustrates this.
+
+```{rust,ignore}
+# #![allow(deprecated)]
+use std::sync::Future;
+
+# fn main() {
+# fn make_a_sandwich() {};
+fn fib(n: u64) -> u64 {
+    // lengthy computation returning an uint
+    12586269025
+}
+
+let mut delayed_fib = Future::spawn(move || fib(50));
+make_a_sandwich();
+println!("fib(50) = {}", delayed_fib.get())
+# }
+```
+
+The call to `future::spawn` immediately returns a `future` object regardless of
+how long it takes to run `fib(50)`. You can then make yourself a sandwich while
+the computation of `fib` is running. The result of the execution of the method
+is obtained by calling `get` on the future. This call will block until the
+value is available (*i.e.* the computation is complete). Note that the future
+needs to be mutable so that it can save the result for next time `get` is
+called.
+
+Here is another example showing how futures allow you to background
+computations. The workload will be distributed on the available cores.
+
+```{rust,ignore}
+# #![allow(deprecated)]
+# use std::num::Float;
+# use std::sync::Future;
+fn partial_sum(start: uint) -> f64 {
+    let mut local_sum = 0f64;
+    for num in range(start*100000, (start+1)*100000) {
+        local_sum += (num as f64 + 1.0).powf(-2.0);
+    }
+    local_sum
+}
+
+fn main() {
+    let mut futures = Vec::from_fn(200, |ind| Future::spawn(move || partial_sum(ind)));
+
+    let mut final_res = 0f64;
+    for ft in futures.iter_mut()  {
+        final_res += ft.get();
+    }
+    println!("π^2/6 is not far from : {}", final_res);
+}
+```
+
+## Sharing without copying: Arc
+
+To share data between threads, a first approach would be to only use channel as
+we have seen previously. A copy of the data to share would then be made for
+each thread. In some cases, this would add up to a significant amount of wasted
+memory and would require copying the same data more than necessary.
+
+To tackle this issue, one can use an Atomically Reference Counted wrapper
+(`Arc`) as implemented in the `sync` library of Rust. With an Arc, the data
+will no longer be copied for each thread. The Arc acts as a reference to the
+shared data and only this reference is shared and cloned.
+
+Here is a small example showing how to use Arcs. We wish to run concurrently
+several computations on a single large vector of floats. Each thread needs the
+full vector to perform its duty.
+
+```{rust,ignore}
+use std::num::Float;
+use std::rand;
+use std::sync::Arc;
+
+fn pnorm(nums: &[f64], p: uint) -> f64 {
+    nums.iter().fold(0.0, |a, b| a + b.powf(p as f64)).powf(1.0 / (p as f64))
+}
+
+fn main() {
+    let numbers = Vec::from_fn(1000000, |_| rand::random::<f64>());
+    let numbers_arc = Arc::new(numbers);
+
+    for num in range(1u, 10) {
+        let thread_numbers = numbers_arc.clone();
+
+        spawn(move || {
+            println!("{}-norm = {}", num, pnorm(thread_numbers.as_slice(), num));
+        });
+    }
+}
+```
+
+The function `pnorm` performs a simple computation on the vector (it computes
+the sum of its items at the power given as argument and takes the inverse power
+of this value). The Arc on the vector is created by the line:
+
+```{rust,ignore}
+# use std::rand;
+# use std::sync::Arc;
+# fn main() {
+# let numbers = Vec::from_fn(1000000, |_| rand::random::<f64>());
+let numbers_arc = Arc::new(numbers);
+# }
+```
+
+and a clone is captured for each thread via a procedure. This only copies
+the wrapper and not its contents. Within the thread's procedure, the captured
+Arc reference can be used as a shared reference to the underlying vector as
+if it were local.
+
+```{rust,ignore}
+# use std::rand;
+# use std::sync::Arc;
+# fn pnorm(nums: &[f64], p: uint) -> f64 { 4.0 }
+# fn main() {
+# let numbers=Vec::from_fn(1000000, |_| rand::random::<f64>());
+# let numbers_arc = Arc::new(numbers);
+# let num = 4;
+let thread_numbers = numbers_arc.clone();
+spawn(move || {
+    // Capture thread_numbers and use it as if it was the underlying vector
+    println!("{}-norm = {}", num, pnorm(thread_numbers.as_slice(), num));
+});
+# }
+```
+
+# Handling thread panics
+
+Rust has a built-in mechanism for raising exceptions. The `panic!()` macro
+(which can also be written with an error string as an argument: `panic!(
+~reason)`) and the `assert!` construct (which effectively calls `panic!()` if a
+boolean expression is false) are both ways to raise exceptions. When a thread
+raises an exception, the thread unwinds its stack—running destructors and
+freeing memory along the way—and then exits. Unlike exceptions in C++,
+exceptions in Rust are unrecoverable within a single thread: once a thread panics,
+there is no way to "catch" the exception.
+
+While it isn't possible for a thread to recover from panicking, threads may notify
+each other if they panic. The simplest way of handling a panic is with the
+`try` function, which is similar to `spawn`, but immediately blocks and waits
+for the child thread to finish. `try` returns a value of type
+`Result<T, Box<Any + Send>>`. `Result` is an `enum` type with two variants:
+`Ok` and `Err`. In this case, because the type arguments to `Result` are `int`
+and `()`, callers can pattern-match on a result to check whether it's an `Ok`
+result with an `int` field (representing a successful result) or an `Err` result
+(representing termination with an error).
+
+```{rust,ignore}
+# use std::thread::Thread;
+# fn some_condition() -> bool { false }
+# fn calculate_result() -> int { 0 }
+let result: Result<int, Box<std::any::Any + Send>> = Thread::spawn(move || {
+    if some_condition() {
+        calculate_result()
+    } else {
+        panic!("oops!");
+    }
+}).join();
+assert!(result.is_err());
+```
+
+Unlike `spawn`, the function spawned using `try` may return a value, which
+`try` will dutifully propagate back to the caller in a [`Result`] enum. If the
+child thread terminates successfully, `try` will return an `Ok` result; if the
+child thread panics, `try` will return an `Error` result.
+
+[`Result`]: ../std/result/index.html
+
+> *Note:* A panicked thread does not currently produce a useful error
+> value (`try` always returns `Err(())`). In the
+> future, it may be possible for threads to intercept the value passed to
+> `panic!()`.
+
+But not all panics are created equal. In some cases you might need to abort
+the entire program (perhaps you're writing an assert which, if it trips,
+indicates an unrecoverable logic error); in other cases you might want to
+contain the panic at a certain boundary (perhaps a small piece of input from
+the outside world, which you happen to be processing in parallel, is malformed
+such that the processing thread cannot proceed).
index 38427875a6230562663777cfcd690b6a481f6e0a..554ad0daae61cd742ffe753671b1a23187fe5456 100644 (file)
@@ -182,7 +182,7 @@ code:
 - implement the `Drop` for resource clean-up via a destructor, and use
   RAII (Resource Acquisition Is Initialization). This reduces the need
   for any manual memory management by users, and automatically ensures
-  that clean-up is always run, even when the task panics.
+  that clean-up is always run, even when the thread panics.
 - ensure that any data stored behind a raw pointer is destroyed at the
   appropriate time.
 
@@ -499,7 +499,7 @@ library, but without it you must define your own.
 The first of these three functions, `stack_exhausted`, is invoked whenever stack
 overflow is detected.  This function has a number of restrictions about how it
 can be called and what it must do, but if the stack limit register is not being
-maintained then a task always has an "infinite stack" and this function
+maintained then a thread always has an "infinite stack" and this function
 shouldn't get triggered.
 
 The second of these three functions, `eh_personality`, is used by the
@@ -530,7 +530,6 @@ vectors provided from C, using idiomatic Rust practices.
 
 ```
 #![no_std]
-#![feature(globs)]
 #![feature(lang_items)]
 
 # extern crate libc;
index aa99caa731fe3a755bd75b4c84f2c64cef0c79df..e57fc7a120653aa29507b477b04eabefd34c895b 100644 (file)
@@ -89,25 +89,7 @@ what you need, so it's not verboten.
 
 Let's get back to bindings. Rust variable bindings have one more aspect that
 differs from other languages: bindings are required to be initialized with a
-value before you're allowed to use them. If we try...
-
-```{ignore}
-let x;
-```
-
-...we'll get an error:
-
-```text
-src/main.rs:2:9: 2:10 error: cannot determine a type for this local variable: unconstrained type
-src/main.rs:2     let x;
-                      ^
-```
-
-Giving it a type will compile, though:
-
-```{rust}
-let x: i32;
-```
+value before you're allowed to use them.
 
 Let's try it out. Change your `src/main.rs` file to look like this:
 
index 661dc21e2dc5dc8b708cef2e9c615d1ac97e45c7..f25a59015fcdbeaf1b6320382c118039d86a40d2 100644 (file)
     (modify-syntax-entry ?\" "\"" table)
     (modify-syntax-entry ?\\ "\\" table)
 
+    ;; mark _ as a word constituent so that identifiers
+    ;; such as xyz_type don't cause type to be highlighted
+    ;; as a keyword
+    (modify-syntax-entry ?_ "w" table)
+
     ;; Comments
     (modify-syntax-entry ?/  ". 124b" table)
     (modify-syntax-entry ?*  ". 23"   table)
index 678cb3e160234cb81b5fb4a1de169efe9271c68d..a37b7b6d57dbfe0e129c91fa01a7b621b7d63131 100644 (file)
@@ -59,7 +59,7 @@ syn match rustMacroVariable "$\w\+"
 syn keyword   rustReservedKeyword alignof be do offsetof priv pure sizeof typeof unsized yield abstract final override macro
 
 " Built-in types {{{2
-syn keyword   rustType        int isize uint usize float char bool u8 u16 u32 u64 f32
+syn keyword   rustType        isize usize float char bool u8 u16 u32 u64 f32
 syn keyword   rustType        f64 i8 i16 i32 i64 str Self
 
 " Things from the prelude (src/libstd/prelude.rs) {{{2
@@ -95,8 +95,6 @@ syn keyword rustTrait Vec
 syn keyword rustTrait Path GenericPath
 " FIXME: remove when I/O reform lands
 syn keyword rustTrait Buffer Writer Reader Seek BufferPrelude
-" FIXME: remove when range syntax lands
-syn keyword rustFunction range
 
 " Other syntax {{{2
 syn keyword   rustSelf        self
@@ -139,10 +137,10 @@ syn region    rustAttribute   start="#!\?\[" end="\]" contains=rustString,rustDe
 syn region    rustDerive      start="derive(" end=")" contained contains=rustTrait
 
 " Number literals
-syn match     rustDecNumber   display "\<[0-9][0-9_]*\%([iu]\%(8\|16\|32\|64\)\=\)\="
-syn match     rustHexNumber   display "\<0x[a-fA-F0-9_]\+\%([iu]\%(8\|16\|32\|64\)\=\)\="
-syn match     rustOctNumber   display "\<0o[0-7_]\+\%([iu]\%(8\|16\|32\|64\)\=\)\="
-syn match     rustBinNumber   display "\<0b[01_]\+\%([iu]\%(8\|16\|32\|64\)\=\)\="
+syn match     rustDecNumber   display "\<[0-9][0-9_]*\%([iu]\%(s\|8\|16\|32\|64\)\)\="
+syn match     rustHexNumber   display "\<0x[a-fA-F0-9_]\+\%([iu]\%(s\|8\|16\|32\|64\)\)\="
+syn match     rustOctNumber   display "\<0o[0-7_]\+\%([iu]\%(s\|8\|16\|32\|64\)\)\="
+syn match     rustBinNumber   display "\<0b[01_]\+\%([iu]\%(s\|8\|16\|32\|64\)\)\="
 
 " Special case for numbers of the form "1." which are float literals, unless followed by
 " an identifier, which makes them integer literals with a method call or field access,
index 290dd21d666a40a36775edd0b882646848fa7bd6..c0cd034abfa4a414f71e7e91849d5e055b98978d 100644 (file)
@@ -137,8 +137,8 @@ unsafe impl<T: Sync + Send> Send for Weak<T> { }
 unsafe impl<T: Sync + Send> Sync for Weak<T> { }
 
 struct ArcInner<T> {
-    strong: atomic::AtomicUint,
-    weak: atomic::AtomicUint,
+    strong: atomic::AtomicUsize,
+    weak: atomic::AtomicUsize,
     data: T,
 }
 
@@ -161,8 +161,8 @@ pub fn new(data: T) -> Arc<T> {
         // Start the weak pointer count as 1 which is the weak pointer that's
         // held by all the strong pointers (kinda), see std/rc.rs for more info
         let x = box ArcInner {
-            strong: atomic::AtomicUint::new(1),
-            weak: atomic::AtomicUint::new(1),
+            strong: atomic::AtomicUsize::new(1),
+            weak: atomic::AtomicUsize::new(1),
             data: data,
         };
         Arc { _ptr: unsafe { NonZero::new(mem::transmute(x)) } }
@@ -619,7 +619,7 @@ mod tests {
     use super::{Arc, Weak, weak_count, strong_count};
     use std::sync::Mutex;
 
-    struct Canary(*mut atomic::AtomicUint);
+    struct Canary(*mut atomic::AtomicUsize);
 
     impl Drop for Canary
     {
@@ -743,16 +743,16 @@ struct Cycle {
 
     #[test]
     fn drop_arc() {
-        let mut canary = atomic::AtomicUint::new(0);
-        let x = Arc::new(Canary(&mut canary as *mut atomic::AtomicUint));
+        let mut canary = atomic::AtomicUsize::new(0);
+        let x = Arc::new(Canary(&mut canary as *mut atomic::AtomicUsize));
         drop(x);
         assert!(canary.load(Acquire) == 1);
     }
 
     #[test]
     fn drop_arc_weak() {
-        let mut canary = atomic::AtomicUint::new(0);
-        let arc = Arc::new(Canary(&mut canary as *mut atomic::AtomicUint));
+        let mut canary = atomic::AtomicUsize::new(0);
+        let arc = Arc::new(Canary(&mut canary as *mut atomic::AtomicUsize));
         let arc_weak = arc.downgrade();
         assert!(canary.load(Acquire) == 0);
         drop(arc);
index 02933c763efe5f56997f72c2fd6feeb91d68fa59..b7bc1b4764614ac50e6f9fd32384e812ca1bbc2e 100644 (file)
@@ -119,7 +119,8 @@ unsafe fn exchange_free(ptr: *mut u8, old_size: uint, align: uint) {
           not(feature = "external_crate"),
           any(target_arch = "arm",
               target_arch = "mips",
-              target_arch = "mipsel")))]
+              target_arch = "mipsel",
+              target_arch = "powerpc")))]
 const MIN_ALIGN: uint = 8;
 #[cfg(all(not(feature = "external_funcs"),
           not(feature = "external_crate"),
index c1b34c52fcc154c260de01340982ea77f4083b4c..82e5af67ae31649e8cc0b0693a870c5c5671b3ee 100644 (file)
@@ -2526,7 +2526,7 @@ fn bench_uint_small(b: &mut Bencher) {
             for _ in range(0u, 100) {
                 bitv |= 1 << ((r.next_u32() as uint) % u32::BITS);
             }
-            black_box(&bitv)
+            black_box(&bitv);
         });
     }
 
@@ -2538,7 +2538,7 @@ fn bench_bitv_set_big_fixed(b: &mut Bencher) {
             for _ in range(0u, 100) {
                 bitv.set((r.next_u32() as uint) % BENCH_BITS, true);
             }
-            black_box(&bitv)
+            black_box(&bitv);
         });
     }
 
index 3e1533dd35f598aad43903e14b74774627c0af14..6c3767b011158403bed037a173487c8a129a97b7 100644 (file)
@@ -1422,7 +1422,6 @@ pub fn entry<'a>(&'a mut self, mut key: K) -> Entry<'a, K, V> {
 #[cfg(test)]
 mod test {
     use prelude::*;
-    use std::borrow::BorrowFrom;
 
     use super::{BTreeMap, Occupied, Vacant};
 
index 9a1f22ef7a643067ae4314c9fe77fbbf01c21775..4812ecc2c0b754b7a3a83b58dd1f43446271b495 100644 (file)
@@ -1631,7 +1631,7 @@ fn test_slice() {
     #[test]
     fn test_slice_from() {
         let vec: &[int] = &[1, 2, 3, 4];
-        assert_eq!(&vec[0..], vec);
+        assert_eq!(&vec[], vec);
         let b: &[int] = &[3, 4];
         assert_eq!(&vec[2..], b);
         let b: &[int] = &[];
@@ -1641,11 +1641,11 @@ fn test_slice_from() {
     #[test]
     fn test_slice_to() {
         let vec: &[int] = &[1, 2, 3, 4];
-        assert_eq!(&vec[0..4], vec);
+        assert_eq!(&vec[..4], vec);
         let b: &[int] = &[1, 2];
-        assert_eq!(&vec[0..2], b);
+        assert_eq!(&vec[..2], b);
         let b: &[int] = &[];
-        assert_eq!(&vec[0..0], b);
+        assert_eq!(&vec[..0], b);
     }
 
 
@@ -2538,7 +2538,7 @@ fn test_mut_split_at() {
             let (left, right) = values.split_at_mut(2);
             {
                 let left: &[_] = left;
-                assert!(left[0..left.len()] == [1, 2][]);
+                assert!(left[..left.len()] == [1, 2][]);
             }
             for p in left.iter_mut() {
                 *p += 1;
@@ -2546,7 +2546,7 @@ fn test_mut_split_at() {
 
             {
                 let right: &[_] = right;
-                assert!(right[0..right.len()] == [3, 4, 5][]);
+                assert!(right[..right.len()] == [3, 4, 5][]);
             }
             for p in right.iter_mut() {
                 *p += 2;
index ccf654ac0a048a93860f585977c52e2830a15cf5..f7668930660b0203481894aaeb05ff408d0e8210 100644 (file)
@@ -807,7 +807,7 @@ fn slice_from(&self, begin: uint) -> &str {
     /// out of bounds.
     ///
     /// See also `slice`, `slice_from` and `slice_chars`.
-    #[unstable = "use slice notation [0..a] instead"]
+    #[unstable = "use slice notation [..a] instead"]
     fn slice_to(&self, end: uint) -> &str {
         core_str::StrExt::slice_to(&self[], end)
     }
@@ -2841,7 +2841,7 @@ fn char_iterator_for(b: &mut Bencher) {
         let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb";
 
         b.iter(|| {
-            for ch in s.chars() { black_box(ch) }
+            for ch in s.chars() { black_box(ch); }
         });
     }
 
@@ -2869,7 +2869,7 @@ fn char_iterator_rev_for(b: &mut Bencher) {
         let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb";
 
         b.iter(|| {
-            for ch in s.chars().rev() { black_box(ch) }
+            for ch in s.chars().rev() { black_box(ch); }
         });
     }
 
index e30e7e8600dcbc773117078d6957ee077c71c9ea..c845d86ca0fe78dc043a8131b3da0d13b1bbfa09 100644 (file)
@@ -168,7 +168,7 @@ fn safe_get(xs: &[u8], i: uint, total: uint) -> u8 {
 
         if i > 0 {
             unsafe {
-                res.as_mut_vec().push_all(&v[0..i])
+                res.as_mut_vec().push_all(&v[..i])
             };
         }
 
index 47afc78bc1213b13ab8496085fa33e660e4ec5a3..8f6c343205d6c7086a4aed00244d0b8d23bc94f8 100644 (file)
@@ -1511,6 +1511,9 @@ pub struct IntoIter<T> {
     end: *const T
 }
 
+unsafe impl<T: Send> Send for IntoIter<T> { }
+unsafe impl<T: Sync> Sync for IntoIter<T> { }
+
 impl<T> IntoIter<T> {
     #[inline]
     /// Drops all items that have not yet been moved and returns the empty vector.
@@ -2199,7 +2202,7 @@ fn test_map_in_place_zero_sized() {
 
     #[test]
     fn test_map_in_place_zero_drop_count() {
-        use std::sync::atomic::{AtomicUint, Ordering, ATOMIC_UINT_INIT};
+        use std::sync::atomic::{AtomicUsize, Ordering, ATOMIC_USIZE_INIT};
 
         #[derive(Clone, PartialEq, Show)]
         struct Nothing;
@@ -2213,7 +2216,7 @@ fn drop(&mut self) {
             }
         }
         const NUM_ELEMENTS: uint = 2;
-        static DROP_COUNTER: AtomicUint = ATOMIC_UINT_INIT;
+        static DROP_COUNTER: AtomicUsize = ATOMIC_USIZE_INIT;
 
         let v = repeat(Nothing).take(NUM_ELEMENTS).collect::<Vec<_>>();
 
index e740a9292528cfc0a8d7ac8c0d8f66ffba64b59e..aa93d9ed8379230e1eb5dc9c7baa4d3ae962a772 100644 (file)
@@ -15,7 +15,7 @@
 //! types.
 //!
 //! This module defines atomic versions of a select number of primitive
-//! types, including `AtomicBool`, `AtomicInt`, `AtomicUint`, and `AtomicOption`.
+//! types, including `AtomicBool`, `AtomicIsize`, `AtomicUsize`, and `AtomicOption`.
 //! Atomic types present operations that, when used correctly, synchronize
 //! updates between threads.
 //!
 //!
 //! ```
 //! use std::sync::Arc;
-//! use std::sync::atomic::{AtomicUint, Ordering};
+//! use std::sync::atomic::{AtomicUsize, Ordering};
 //! use std::thread::Thread;
 //!
 //! fn main() {
-//!     let spinlock = Arc::new(AtomicUint::new(1));
+//!     let spinlock = Arc::new(AtomicUsize::new(1));
 //!
 //!     let spinlock_clone = spinlock.clone();
 //!     Thread::spawn(move|| {
@@ -60,9 +60,9 @@
 //! Keep a global count of live tasks:
 //!
 //! ```
-//! use std::sync::atomic::{AtomicUint, Ordering, ATOMIC_UINT_INIT};
+//! use std::sync::atomic::{AtomicUsize, Ordering, ATOMIC_USIZE_INIT};
 //!
-//! static GLOBAL_TASK_COUNT: AtomicUint = ATOMIC_UINT_INIT;
+//! static GLOBAL_TASK_COUNT: AtomicUsize = ATOMIC_USIZE_INIT;
 //!
 //! let old_task_count = GLOBAL_TASK_COUNT.fetch_add(1, Ordering::SeqCst);
 //! println!("live tasks: {}", old_task_count + 1);
 /// A boolean type which can be safely shared between threads.
 #[stable]
 pub struct AtomicBool {
-    v: UnsafeCell<uint>,
+    v: UnsafeCell<usize>,
 }
 
 unsafe impl Sync for AtomicBool {}
 
 /// A signed integer type which can be safely shared between threads.
-#[unstable = "awaiting int/uint conventions, may be renamed"]
-pub struct AtomicInt {
-    v: UnsafeCell<int>,
+#[stable]
+pub struct AtomicIsize {
+    v: UnsafeCell<isize>,
 }
 
-unsafe impl Sync for AtomicInt {}
+unsafe impl Sync for AtomicIsize {}
 
 /// An unsigned integer type which can be safely shared between threads.
-#[unstable = "awaiting int/uint conventions, may be renamed"]
-pub struct AtomicUint {
-    v: UnsafeCell<uint>,
+#[stable]
+pub struct AtomicUsize {
+    v: UnsafeCell<usize>,
 }
 
-unsafe impl Sync for AtomicUint {}
+unsafe impl Sync for AtomicUsize {}
 
 /// A raw pointer type which can be safely shared between threads.
 #[stable]
 pub struct AtomicPtr<T> {
-    p: UnsafeCell<uint>,
+    p: UnsafeCell<usize>,
 }
 
 unsafe impl<T> Sync for AtomicPtr<T> {}
@@ -149,17 +149,17 @@ pub enum Ordering {
 #[stable]
 pub const ATOMIC_BOOL_INIT: AtomicBool =
         AtomicBool { v: UnsafeCell { value: 0 } };
-/// An `AtomicInt` initialized to `0`.
-#[unstable = "awaiting int/uint conventions, may be renamed"]
-pub const ATOMIC_INT_INIT: AtomicInt =
-        AtomicInt { v: UnsafeCell { value: 0 } };
-/// An `AtomicUint` initialized to `0`.
-#[unstable = "awaiting int/uint conventions, may be renamed"]
-pub const ATOMIC_UINT_INIT: AtomicUint =
-        AtomicUint { v: UnsafeCell { value: 0, } };
+/// An `AtomicIsize` initialized to `0`.
+#[stable]
+pub const ATOMIC_ISIZE_INIT: AtomicIsize =
+        AtomicIsize { v: UnsafeCell { value: 0 } };
+/// An `AtomicUsize` initialized to `0`.
+#[stable]
+pub const ATOMIC_USIZE_INIT: AtomicUsize =
+        AtomicUsize { v: UnsafeCell { value: 0, } };
 
 // NB: Needs to be -1 (0b11111111...) to make fetch_nand work correctly
-const UINT_TRUE: uint = -1;
+const UINT_TRUE: usize = -1;
 
 impl AtomicBool {
     /// Creates a new `AtomicBool`.
@@ -199,7 +199,7 @@ pub fn new(v: bool) -> AtomicBool {
     #[inline]
     #[stable]
     pub fn load(&self, order: Ordering) -> bool {
-        unsafe { atomic_load(self.v.get() as *const uint, order) > 0 }
+        unsafe { atomic_load(self.v.get() as *const usize, order) > 0 }
     }
 
     /// Stores a value into the bool.
@@ -323,7 +323,7 @@ pub fn fetch_and(&self, val: bool, order: Ordering) -> bool {
     ///
     /// let foo = AtomicBool::new(true);
     /// assert_eq!(true, foo.fetch_nand(true, Ordering::SeqCst));
-    /// assert_eq!(0, foo.load(Ordering::SeqCst) as int);
+    /// assert_eq!(0, foo.load(Ordering::SeqCst) as usize);
     /// assert_eq!(false, foo.load(Ordering::SeqCst));
     ///
     /// let foo = AtomicBool::new(false);
@@ -403,23 +403,23 @@ pub fn fetch_xor(&self, val: bool, order: Ordering) -> bool {
     }
 }
 
-#[unstable = "awaiting int/uint conventions, types may change"]
-impl AtomicInt {
-    /// Creates a new `AtomicInt`.
+#[stable]
+impl AtomicIsize {
+    /// Creates a new `AtomicIsize`.
     ///
     /// # Examples
     ///
     /// ```
-    /// use std::sync::atomic::AtomicInt;
+    /// use std::sync::atomic::AtomicIsize;
     ///
-    /// let atomic_forty_two  = AtomicInt::new(42);
+    /// let atomic_forty_two  = AtomicIsize::new(42);
     /// ```
     #[inline]
-    pub fn new(v: int) -> AtomicInt {
-        AtomicInt {v: UnsafeCell::new(v)}
+    pub fn new(v: isize) -> AtomicIsize {
+        AtomicIsize {v: UnsafeCell::new(v)}
     }
 
-    /// Loads a value from the int.
+    /// Loads a value from the isize.
     ///
     /// `load` takes an `Ordering` argument which describes the memory ordering of this operation.
     ///
@@ -430,58 +430,58 @@ pub fn new(v: int) -> AtomicInt {
     /// # Examples
     ///
     /// ```
-    /// use std::sync::atomic::{AtomicInt, Ordering};
+    /// use std::sync::atomic::{AtomicIsize, Ordering};
     ///
-    /// let some_int = AtomicInt::new(5);
+    /// let some_isize = AtomicIsize::new(5);
     ///
-    /// let value = some_int.load(Ordering::Relaxed);
+    /// let value = some_isize.load(Ordering::Relaxed);
     /// ```
     #[inline]
-    pub fn load(&self, order: Ordering) -> int {
-        unsafe { atomic_load(self.v.get() as *const int, order) }
+    pub fn load(&self, order: Ordering) -> isize {
+        unsafe { atomic_load(self.v.get() as *const isize, order) }
     }
 
-    /// Stores a value into the int.
+    /// Stores a value into the isize.
     ///
     /// `store` takes an `Ordering` argument which describes the memory ordering of this operation.
     ///
     /// # Examples
     ///
     /// ```
-    /// use std::sync::atomic::{AtomicInt, Ordering};
+    /// use std::sync::atomic::{AtomicIsize, Ordering};
     ///
-    /// let some_int = AtomicInt::new(5);
+    /// let some_isize = AtomicIsize::new(5);
     ///
-    /// some_int.store(10, Ordering::Relaxed);
+    /// some_isize.store(10, Ordering::Relaxed);
     /// ```
     ///
     /// # Panics
     ///
     /// Panics if `order` is `Acquire` or `AcqRel`.
     #[inline]
-    pub fn store(&self, val: int, order: Ordering) {
+    pub fn store(&self, val: isize, order: Ordering) {
         unsafe { atomic_store(self.v.get(), val, order); }
     }
 
-    /// Stores a value into the int, returning the old value.
+    /// Stores a value into the isize, returning the old value.
     ///
     /// `swap` takes an `Ordering` argument which describes the memory ordering of this operation.
     ///
     /// # Examples
     ///
     /// ```
-    /// use std::sync::atomic::{AtomicInt, Ordering};
+    /// use std::sync::atomic::{AtomicIsize, Ordering};
     ///
-    /// let some_int = AtomicInt::new(5);
+    /// let some_isize = AtomicIsize::new(5);
     ///
-    /// let value = some_int.swap(10, Ordering::Relaxed);
+    /// let value = some_isize.swap(10, Ordering::Relaxed);
     /// ```
     #[inline]
-    pub fn swap(&self, val: int, order: Ordering) -> int {
+    pub fn swap(&self, val: isize, order: Ordering) -> isize {
         unsafe { atomic_swap(self.v.get(), val, order) }
     }
 
-    /// Stores a value into the int if the current value is the same as the expected value.
+    /// Stores a value into the isize if the current value is the same as the expected value.
     ///
     /// If the return value is equal to `old` then the value was updated.
     ///
@@ -491,112 +491,112 @@ pub fn swap(&self, val: int, order: Ordering) -> int {
     /// # Examples
     ///
     /// ```
-    /// use std::sync::atomic::{AtomicInt, Ordering};
+    /// use std::sync::atomic::{AtomicIsize, Ordering};
     ///
-    /// let some_int = AtomicInt::new(5);
+    /// let some_isize = AtomicIsize::new(5);
     ///
-    /// let value = some_int.compare_and_swap(5, 10, Ordering::Relaxed);
+    /// let value = some_isize.compare_and_swap(5, 10, Ordering::Relaxed);
     /// ```
     #[inline]
-    pub fn compare_and_swap(&self, old: int, new: int, order: Ordering) -> int {
+    pub fn compare_and_swap(&self, old: isize, new: isize, order: Ordering) -> isize {
         unsafe { atomic_compare_and_swap(self.v.get(), old, new, order) }
     }
 
-    /// Add an int to the current value, returning the previous value.
+    /// Add an isize to the current value, returning the previous value.
     ///
     /// # Examples
     ///
     /// ```
-    /// use std::sync::atomic::{AtomicInt, Ordering};
+    /// use std::sync::atomic::{AtomicIsize, Ordering};
     ///
-    /// let foo = AtomicInt::new(0);
+    /// let foo = AtomicIsize::new(0);
     /// assert_eq!(0, foo.fetch_add(10, Ordering::SeqCst));
     /// assert_eq!(10, foo.load(Ordering::SeqCst));
     /// ```
     #[inline]
-    pub fn fetch_add(&self, val: int, order: Ordering) -> int {
+    pub fn fetch_add(&self, val: isize, order: Ordering) -> isize {
         unsafe { atomic_add(self.v.get(), val, order) }
     }
 
-    /// Subtract an int from the current value, returning the previous value.
+    /// Subtract an isize from the current value, returning the previous value.
     ///
     /// # Examples
     ///
     /// ```
-    /// use std::sync::atomic::{AtomicInt, Ordering};
+    /// use std::sync::atomic::{AtomicIsize, Ordering};
     ///
-    /// let foo = AtomicInt::new(0);
+    /// let foo = AtomicIsize::new(0);
     /// assert_eq!(0, foo.fetch_sub(10, Ordering::SeqCst));
     /// assert_eq!(-10, foo.load(Ordering::SeqCst));
     /// ```
     #[inline]
-    pub fn fetch_sub(&self, val: int, order: Ordering) -> int {
+    pub fn fetch_sub(&self, val: isize, order: Ordering) -> isize {
         unsafe { atomic_sub(self.v.get(), val, order) }
     }
 
-    /// Bitwise and with the current int, returning the previous value.
+    /// Bitwise and with the current isize, returning the previous value.
     ///
     /// # Examples
     ///
     /// ```
-    /// use std::sync::atomic::{AtomicInt, Ordering};
+    /// use std::sync::atomic::{AtomicIsize, Ordering};
     ///
-    /// let foo = AtomicInt::new(0b101101);
+    /// let foo = AtomicIsize::new(0b101101);
     /// assert_eq!(0b101101, foo.fetch_and(0b110011, Ordering::SeqCst));
     /// assert_eq!(0b100001, foo.load(Ordering::SeqCst));
     #[inline]
-    pub fn fetch_and(&self, val: int, order: Ordering) -> int {
+    pub fn fetch_and(&self, val: isize, order: Ordering) -> isize {
         unsafe { atomic_and(self.v.get(), val, order) }
     }
 
-    /// Bitwise or with the current int, returning the previous value.
+    /// Bitwise or with the current isize, returning the previous value.
     ///
     /// # Examples
     ///
     /// ```
-    /// use std::sync::atomic::{AtomicInt, Ordering};
+    /// use std::sync::atomic::{AtomicIsize, Ordering};
     ///
-    /// let foo = AtomicInt::new(0b101101);
+    /// let foo = AtomicIsize::new(0b101101);
     /// assert_eq!(0b101101, foo.fetch_or(0b110011, Ordering::SeqCst));
     /// assert_eq!(0b111111, foo.load(Ordering::SeqCst));
     #[inline]
-    pub fn fetch_or(&self, val: int, order: Ordering) -> int {
+    pub fn fetch_or(&self, val: isize, order: Ordering) -> isize {
         unsafe { atomic_or(self.v.get(), val, order) }
     }
 
-    /// Bitwise xor with the current int, returning the previous value.
+    /// Bitwise xor with the current isize, returning the previous value.
     ///
     /// # Examples
     ///
     /// ```
-    /// use std::sync::atomic::{AtomicInt, Ordering};
+    /// use std::sync::atomic::{AtomicIsize, Ordering};
     ///
-    /// let foo = AtomicInt::new(0b101101);
+    /// let foo = AtomicIsize::new(0b101101);
     /// assert_eq!(0b101101, foo.fetch_xor(0b110011, Ordering::SeqCst));
     /// assert_eq!(0b011110, foo.load(Ordering::SeqCst));
     #[inline]
-    pub fn fetch_xor(&self, val: int, order: Ordering) -> int {
+    pub fn fetch_xor(&self, val: isize, order: Ordering) -> isize {
         unsafe { atomic_xor(self.v.get(), val, order) }
     }
 }
 
-#[unstable = "awaiting int/uint conventions, types may change"]
-impl AtomicUint {
-    /// Creates a new `AtomicUint`.
+#[stable]
+impl AtomicUsize {
+    /// Creates a new `AtomicUsize`.
     ///
     /// # Examples
     ///
     /// ```
-    /// use std::sync::atomic::AtomicUint;
+    /// use std::sync::atomic::AtomicUsize;
     ///
-    /// let atomic_forty_two = AtomicUint::new(42u);
+    /// let atomic_forty_two = AtomicUsize::new(42u);
     /// ```
     #[inline]
-    pub fn new(v: uint) -> AtomicUint {
-        AtomicUint { v: UnsafeCell::new(v) }
+    pub fn new(v: usize) -> AtomicUsize {
+        AtomicUsize { v: UnsafeCell::new(v) }
     }
 
-    /// Loads a value from the uint.
+    /// Loads a value from the usize.
     ///
     /// `load` takes an `Ordering` argument which describes the memory ordering of this operation.
     ///
@@ -607,58 +607,58 @@ pub fn new(v: uint) -> AtomicUint {
     /// # Examples
     ///
     /// ```
-    /// use std::sync::atomic::{AtomicUint, Ordering};
+    /// use std::sync::atomic::{AtomicUsize, Ordering};
     ///
-    /// let some_uint = AtomicUint::new(5);
+    /// let some_usize = AtomicUsize::new(5);
     ///
-    /// let value = some_uint.load(Ordering::Relaxed);
+    /// let value = some_usize.load(Ordering::Relaxed);
     /// ```
     #[inline]
-    pub fn load(&self, order: Ordering) -> uint {
-        unsafe { atomic_load(self.v.get() as *const uint, order) }
+    pub fn load(&self, order: Ordering) -> usize {
+        unsafe { atomic_load(self.v.get() as *const usize, order) }
     }
 
-    /// Stores a value into the uint.
+    /// Stores a value into the usize.
     ///
     /// `store` takes an `Ordering` argument which describes the memory ordering of this operation.
     ///
     /// # Examples
     ///
     /// ```
-    /// use std::sync::atomic::{AtomicUint, Ordering};
+    /// use std::sync::atomic::{AtomicUsize, Ordering};
     ///
-    /// let some_uint = AtomicUint::new(5);
+    /// let some_usize = AtomicUsize::new(5);
     ///
-    /// some_uint.store(10, Ordering::Relaxed);
+    /// some_usize.store(10, Ordering::Relaxed);
     /// ```
     ///
     /// # Panics
     ///
     /// Panics if `order` is `Acquire` or `AcqRel`.
     #[inline]
-    pub fn store(&self, val: uint, order: Ordering) {
+    pub fn store(&self, val: usize, order: Ordering) {
         unsafe { atomic_store(self.v.get(), val, order); }
     }
 
-    /// Stores a value into the uint, returning the old value.
+    /// Stores a value into the usize, returning the old value.
     ///
     /// `swap` takes an `Ordering` argument which describes the memory ordering of this operation.
     ///
     /// # Examples
     ///
     /// ```
-    /// use std::sync::atomic::{AtomicUint, Ordering};
+    /// use std::sync::atomic::{AtomicUsize, Ordering};
     ///
-    /// let some_uint = AtomicUint::new(5);
+    /// let some_usize= AtomicUsize::new(5);
     ///
-    /// let value = some_uint.swap(10, Ordering::Relaxed);
+    /// let value = some_usize.swap(10, Ordering::Relaxed);
     /// ```
     #[inline]
-    pub fn swap(&self, val: uint, order: Ordering) -> uint {
+    pub fn swap(&self, val: usize, order: Ordering) -> usize {
         unsafe { atomic_swap(self.v.get(), val, order) }
     }
 
-    /// Stores a value into the uint if the current value is the same as the expected value.
+    /// Stores a value into the usize if the current value is the same as the expected value.
     ///
     /// If the return value is equal to `old` then the value was updated.
     ///
@@ -668,91 +668,91 @@ pub fn swap(&self, val: uint, order: Ordering) -> uint {
     /// # Examples
     ///
     /// ```
-    /// use std::sync::atomic::{AtomicUint, Ordering};
+    /// use std::sync::atomic::{AtomicUsize, Ordering};
     ///
-    /// let some_uint = AtomicUint::new(5);
+    /// let some_usize = AtomicUsize::new(5);
     ///
-    /// let value = some_uint.compare_and_swap(5, 10, Ordering::Relaxed);
+    /// let value = some_usize.compare_and_swap(5, 10, Ordering::Relaxed);
     /// ```
     #[inline]
-    pub fn compare_and_swap(&self, old: uint, new: uint, order: Ordering) -> uint {
+    pub fn compare_and_swap(&self, old: usize, new: usize, order: Ordering) -> usize {
         unsafe { atomic_compare_and_swap(self.v.get(), old, new, order) }
     }
 
-    /// Add to the current uint, returning the previous value.
+    /// Add to the current usize, returning the previous value.
     ///
     /// # Examples
     ///
     /// ```
-    /// use std::sync::atomic::{AtomicUint, Ordering};
+    /// use std::sync::atomic::{AtomicUsize, Ordering};
     ///
-    /// let foo = AtomicUint::new(0);
+    /// let foo = AtomicUsize::new(0);
     /// assert_eq!(0, foo.fetch_add(10, Ordering::SeqCst));
     /// assert_eq!(10, foo.load(Ordering::SeqCst));
     /// ```
     #[inline]
-    pub fn fetch_add(&self, val: uint, order: Ordering) -> uint {
+    pub fn fetch_add(&self, val: usize, order: Ordering) -> usize {
         unsafe { atomic_add(self.v.get(), val, order) }
     }
 
-    /// Subtract from the current uint, returning the previous value.
+    /// Subtract from the current usize, returning the previous value.
     ///
     /// # Examples
     ///
     /// ```
-    /// use std::sync::atomic::{AtomicUint, Ordering};
+    /// use std::sync::atomic::{AtomicUsize, Ordering};
     ///
-    /// let foo = AtomicUint::new(10);
+    /// let foo = AtomicUsize::new(10);
     /// assert_eq!(10, foo.fetch_sub(10, Ordering::SeqCst));
     /// assert_eq!(0, foo.load(Ordering::SeqCst));
     /// ```
     #[inline]
-    pub fn fetch_sub(&self, val: uint, order: Ordering) -> uint {
+    pub fn fetch_sub(&self, val: usize, order: Ordering) -> usize {
         unsafe { atomic_sub(self.v.get(), val, order) }
     }
 
-    /// Bitwise and with the current uint, returning the previous value.
+    /// Bitwise and with the current usize, returning the previous value.
     ///
     /// # Examples
     ///
     /// ```
-    /// use std::sync::atomic::{AtomicUint, Ordering};
+    /// use std::sync::atomic::{AtomicUsize, Ordering};
     ///
-    /// let foo = AtomicUint::new(0b101101);
+    /// let foo = AtomicUsize::new(0b101101);
     /// assert_eq!(0b101101, foo.fetch_and(0b110011, Ordering::SeqCst));
     /// assert_eq!(0b100001, foo.load(Ordering::SeqCst));
     #[inline]
-    pub fn fetch_and(&self, val: uint, order: Ordering) -> uint {
+    pub fn fetch_and(&self, val: usize, order: Ordering) -> usize {
         unsafe { atomic_and(self.v.get(), val, order) }
     }
 
-    /// Bitwise or with the current uint, returning the previous value.
+    /// Bitwise or with the current usize, returning the previous value.
     ///
     /// # Examples
     ///
     /// ```
-    /// use std::sync::atomic::{AtomicUint, Ordering};
+    /// use std::sync::atomic::{AtomicUsize, Ordering};
     ///
-    /// let foo = AtomicUint::new(0b101101);
+    /// let foo = AtomicUsize::new(0b101101);
     /// assert_eq!(0b101101, foo.fetch_or(0b110011, Ordering::SeqCst));
     /// assert_eq!(0b111111, foo.load(Ordering::SeqCst));
     #[inline]
-    pub fn fetch_or(&self, val: uint, order: Ordering) -> uint {
+    pub fn fetch_or(&self, val: usize, order: Ordering) -> usize {
         unsafe { atomic_or(self.v.get(), val, order) }
     }
 
-    /// Bitwise xor with the current uint, returning the previous value.
+    /// Bitwise xor with the current usize, returning the previous value.
     ///
     /// # Examples
     ///
     /// ```
-    /// use std::sync::atomic::{AtomicUint, Ordering};
+    /// use std::sync::atomic::{AtomicUsize, Ordering};
     ///
-    /// let foo = AtomicUint::new(0b101101);
+    /// let foo = AtomicUsize::new(0b101101);
     /// assert_eq!(0b101101, foo.fetch_xor(0b110011, Ordering::SeqCst));
     /// assert_eq!(0b011110, foo.load(Ordering::SeqCst));
     #[inline]
-    pub fn fetch_xor(&self, val: uint, order: Ordering) -> uint {
+    pub fn fetch_xor(&self, val: usize, order: Ordering) -> usize {
         unsafe { atomic_xor(self.v.get(), val, order) }
     }
 }
@@ -771,7 +771,7 @@ impl<T> AtomicPtr<T> {
     #[inline]
     #[stable]
     pub fn new(p: *mut T) -> AtomicPtr<T> {
-        AtomicPtr { p: UnsafeCell::new(p as uint) }
+        AtomicPtr { p: UnsafeCell::new(p as usize) }
     }
 
     /// Loads a value from the pointer.
@@ -823,7 +823,7 @@ pub fn load(&self, order: Ordering) -> *mut T {
     #[inline]
     #[stable]
     pub fn store(&self, ptr: *mut T, order: Ordering) {
-        unsafe { atomic_store(self.p.get(), ptr as uint, order); }
+        unsafe { atomic_store(self.p.get(), ptr as usize, order); }
     }
 
     /// Stores a value into the pointer, returning the old value.
@@ -845,7 +845,7 @@ pub fn store(&self, ptr: *mut T, order: Ordering) {
     #[inline]
     #[stable]
     pub fn swap(&self, ptr: *mut T, order: Ordering) -> *mut T {
-        unsafe { atomic_swap(self.p.get(), ptr as uint, order) as *mut T }
+        unsafe { atomic_swap(self.p.get(), ptr as usize, order) as *mut T }
     }
 
     /// Stores a value into the pointer if the current value is the same as the expected value.
@@ -872,8 +872,8 @@ pub fn swap(&self, ptr: *mut T, order: Ordering) -> *mut T {
     #[stable]
     pub fn compare_and_swap(&self, old: *mut T, new: *mut T, order: Ordering) -> *mut T {
         unsafe {
-            atomic_compare_and_swap(self.p.get(), old as uint,
-                                    new as uint, order) as *mut T
+            atomic_compare_and_swap(self.p.get(), old as usize,
+                                    new as usize, order) as *mut T
         }
     }
 }
@@ -1035,3 +1035,134 @@ pub fn fence(order: Ordering) {
         }
     }
 }
+
+#[deprecated="renamed to AtomicIsize"]
+#[allow(missing_docs)]
+pub struct AtomicInt {
+    v: UnsafeCell<int>,
+}
+
+unsafe impl Sync for AtomicInt {}
+
+#[deprecated="renamed to AtomicUsize"]
+#[allow(missing_docs)]
+pub struct AtomicUint {
+    v: UnsafeCell<uint>,
+}
+
+unsafe impl Sync for AtomicUint {}
+
+#[deprecated="use ATOMIC_ISIZE_INIT instead"]
+#[allow(missing_docs, deprecated)]
+pub const ATOMIC_INT_INIT: AtomicInt =
+        AtomicInt { v: UnsafeCell { value: 0 } };
+#[deprecated="use ATOMIC_USIZE_INIT instead"]
+#[allow(missing_docs, deprecated)]
+pub const ATOMIC_UINT_INIT: AtomicUint =
+        AtomicUint { v: UnsafeCell { value: 0, } };
+
+#[allow(missing_docs, deprecated)]
+impl AtomicInt {
+    #[inline]
+    pub fn new(v: int) -> AtomicInt {
+        AtomicInt {v: UnsafeCell::new(v)}
+    }
+
+    #[inline]
+    pub fn load(&self, order: Ordering) -> int {
+        unsafe { atomic_load(self.v.get() as *const int, order) }
+    }
+
+    #[inline]
+    pub fn store(&self, val: int, order: Ordering) {
+        unsafe { atomic_store(self.v.get(), val, order); }
+    }
+
+    #[inline]
+    pub fn swap(&self, val: int, order: Ordering) -> int {
+        unsafe { atomic_swap(self.v.get(), val, order) }
+    }
+
+    #[inline]
+    pub fn compare_and_swap(&self, old: int, new: int, order: Ordering) -> int {
+        unsafe { atomic_compare_and_swap(self.v.get(), old, new, order) }
+    }
+
+    #[inline]
+    pub fn fetch_add(&self, val: int, order: Ordering) -> int {
+        unsafe { atomic_add(self.v.get(), val, order) }
+    }
+
+    #[inline]
+    pub fn fetch_sub(&self, val: int, order: Ordering) -> int {
+        unsafe { atomic_sub(self.v.get(), val, order) }
+    }
+
+    #[inline]
+    pub fn fetch_and(&self, val: int, order: Ordering) -> int {
+        unsafe { atomic_and(self.v.get(), val, order) }
+    }
+
+    #[inline]
+    pub fn fetch_or(&self, val: int, order: Ordering) -> int {
+        unsafe { atomic_or(self.v.get(), val, order) }
+    }
+
+    #[inline]
+    pub fn fetch_xor(&self, val: int, order: Ordering) -> int {
+        unsafe { atomic_xor(self.v.get(), val, order) }
+    }
+}
+
+#[allow(missing_docs, deprecated)]
+impl AtomicUint {
+    #[inline]
+    pub fn new(v: uint) -> AtomicUint {
+        AtomicUint { v: UnsafeCell::new(v) }
+    }
+
+    #[inline]
+    pub fn load(&self, order: Ordering) -> uint {
+        unsafe { atomic_load(self.v.get() as *const uint, order) }
+    }
+
+    #[inline]
+    pub fn store(&self, val: uint, order: Ordering) {
+        unsafe { atomic_store(self.v.get(), val, order); }
+    }
+
+    #[inline]
+    pub fn swap(&self, val: uint, order: Ordering) -> uint {
+        unsafe { atomic_swap(self.v.get(), val, order) }
+    }
+
+    #[inline]
+    pub fn compare_and_swap(&self, old: uint, new: uint, order: Ordering) -> uint {
+        unsafe { atomic_compare_and_swap(self.v.get(), old, new, order) }
+    }
+
+    #[inline]
+    pub fn fetch_add(&self, val: uint, order: Ordering) -> uint {
+        unsafe { atomic_add(self.v.get(), val, order) }
+    }
+
+    #[inline]
+    pub fn fetch_sub(&self, val: uint, order: Ordering) -> uint {
+        unsafe { atomic_sub(self.v.get(), val, order) }
+    }
+
+    #[inline]
+    pub fn fetch_and(&self, val: uint, order: Ordering) -> uint {
+        unsafe { atomic_and(self.v.get(), val, order) }
+    }
+
+    #[inline]
+    pub fn fetch_or(&self, val: uint, order: Ordering) -> uint {
+        unsafe { atomic_or(self.v.get(), val, order) }
+    }
+
+    #[inline]
+    pub fn fetch_xor(&self, val: uint, order: Ordering) -> uint {
+        unsafe { atomic_xor(self.v.get(), val, order) }
+    }
+}
index a21ec892dd77a64abfc60a564c3268f04ecb6a1c..4c2a2ff1086039c2c3f4c39a28aef8b9c2a53024 100644 (file)
 //! # }
 //! ```
 
-#![unstable]
+#![deprecated = "It is unclear if this module is more robust than implementing \
+                 Drop on a custom type, and this module is being removed with no \
+                 replacement. Use a custom Drop implementation to regain existing \
+                 functionality."]
+#![allow(deprecated)]
 
 use ops::{Drop, FnMut, FnOnce};
 
index 0ffcb014c2877f558f6b9e4dc6f41e6b894fa416..f1b9ebe6d905d13e6271094fe4bd61126aaff854 100644 (file)
@@ -332,5 +332,5 @@ fn write_str(&mut self, s: &str) -> fmt::Result {
         }
     }
 
-    f(unsafe { str::from_utf8_unchecked(&buf[0..end]) })
+    f(unsafe { str::from_utf8_unchecked(&buf[..end]) })
 }
index a0ec9e5f151c2c2eaf28a2e357b646413e1a0ab2..20ac3e28c973ecb65f439556f9a491462fdb14c6 100644 (file)
@@ -449,7 +449,7 @@ pub fn pad_integral(&mut self,
             for c in sign.into_iter() {
                 let mut b = [0; 4];
                 let n = c.encode_utf8(&mut b).unwrap_or(0);
-                let b = unsafe { str::from_utf8_unchecked(&b[0..n]) };
+                let b = unsafe { str::from_utf8_unchecked(&b[..n]) };
                 try!(f.buf.write_str(b));
             }
             if prefixed { f.buf.write_str(prefix) }
@@ -692,7 +692,7 @@ impl String for char {
     fn fmt(&self, f: &mut Formatter) -> Result {
         let mut utf8 = [0u8; 4];
         let amt = self.encode_utf8(&mut utf8).unwrap_or(0);
-        let s: &str = unsafe { mem::transmute(&utf8[0..amt]) };
+        let s: &str = unsafe { mem::transmute(&utf8[..amt]) };
         String::fmt(s, f)
     }
 }
index 849080e8a828390d7e8f0daf0df0ee9f8bf38342..5ed77852ad0a1e1ee6a6a232848dfdfa4392b8ba 100644 (file)
@@ -101,6 +101,8 @@ fn size_hint(&self) -> (uint, Option<uint>) { (0, None) }
 
 /// Conversion from an `Iterator`
 #[stable]
+#[rustc_on_unimplemented="a collection of type `{Self}` cannot be \
+                          built from an iterator over elements of type `{A}`"]
 pub trait FromIterator<A> {
     /// Build a container with elements from an external iterator.
     fn from_iter<T: Iterator<Item=A>>(iterator: T) -> Self;
index 28f8cf588bea9a1a408876d308837a45b3e9bdd4..78e8a2a9e9164be4bf34700c3ec630231a328202 100644 (file)
@@ -63,6 +63,7 @@
 #![feature(simd, unsafe_destructor, slicing_syntax)]
 #![feature(unboxed_closures)]
 #![allow(unknown_features)] #![feature(int_uint)]
+#![feature(on_unimplemented)]
 #![deny(missing_docs)]
 
 #[macro_use]
index ab956587d8248045d0d680322c530dbd5e1a3869..e7eb307689fbe88bd670e380da13d28a8ac728c1 100644 (file)
@@ -706,20 +706,45 @@ pub trait Shl<RHS> {
 }
 
 macro_rules! shl_impl {
-    ($($t:ty)*) => ($(
+    ($t:ty, $f:ty) => (
         #[stable]
-        impl Shl<uint> for $t {
+        impl Shl<$f> for $t {
             type Output = $t;
 
             #[inline]
-            fn shl(self, other: uint) -> $t {
+            fn shl(self, other: $f) -> $t {
                 self << other
             }
         }
+    )
+}
+
+// SNAP 9e4e524e0
+#[cfg(not(stage0))]
+macro_rules! shl_impl_all {
+    ($($t:ty)*) => ($(
+        shl_impl! { $t, u8 }
+        shl_impl! { $t, u16 }
+        shl_impl! { $t, u32 }
+        shl_impl! { $t, u64 }
+        shl_impl! { $t, usize }
+
+        shl_impl! { $t, i8 }
+        shl_impl! { $t, i16 }
+        shl_impl! { $t, i32 }
+        shl_impl! { $t, i64 }
+        shl_impl! { $t, isize }
     )*)
 }
 
-shl_impl! { uint u8 u16 u32 u64 int i8 i16 i32 i64 }
+#[cfg(stage0)]
+macro_rules! shl_impl_all {
+    ($($t:ty)*) => ($(
+        shl_impl! { $t, usize }
+    )*)
+}
+
+shl_impl_all! { u8 u16 u32 u64 usize i8 i16 i32 i64 isize }
 
 /// The `Shr` trait is used to specify the functionality of `>>`.
 ///
@@ -761,17 +786,44 @@ pub trait Shr<RHS> {
 }
 
 macro_rules! shr_impl {
-    ($($t:ty)*) => ($(
-        impl Shr<uint> for $t {
+    ($t:ty, $f:ty) => (
+        impl Shr<$f> for $t {
             type Output = $t;
 
             #[inline]
-            fn shr(self, other: uint) -> $t { self >> other }
+            fn shr(self, other: $f) -> $t {
+                self >> other
+            }
         }
+    )
+}
+
+// SNAP 9e4e524e0
+#[cfg(not(stage0))]
+macro_rules! shr_impl_all {
+    ($($t:ty)*) => ($(
+        shr_impl! { $t, u8 }
+        shr_impl! { $t, u16 }
+        shr_impl! { $t, u32 }
+        shr_impl! { $t, u64 }
+        shr_impl! { $t, usize }
+
+        shr_impl! { $t, i8 }
+        shr_impl! { $t, i16 }
+        shr_impl! { $t, i32 }
+        shr_impl! { $t, i64 }
+        shr_impl! { $t, isize }
+    )*)
+}
+
+#[cfg(stage0)]
+macro_rules! shr_impl_all {
+    ($($t:ty)*) => ($(
+        shr_impl! { $t, usize }
     )*)
 }
 
-shr_impl! { uint u8 u16 u32 u64 int i8 i16 i32 i64 }
+shr_impl_all! { u8 u16 u32 u64 usize i8 i16 i32 i64 isize }
 
 /// The `Index` trait is used to specify the functionality of indexing operations
 /// like `arr[idx]` when used in an immutable context.
index 7e47c5257a344942cfab44a2f0465dce27712f5f..22da168911daad66f84a6bc6a731408cfbae17c0 100644 (file)
@@ -159,7 +159,7 @@ fn slice_to(&self, end: uint) -> &[T] {
 
     #[inline]
     fn split_at(&self, mid: uint) -> (&[T], &[T]) {
-        (&self[0..mid], &self[mid..])
+        (&self[..mid], &self[mid..])
     }
 
     #[inline]
@@ -240,7 +240,7 @@ fn tail(&self) -> &[T] { &self[1..] }
 
     #[inline]
     fn init(&self) -> &[T] {
-        &self[0..(self.len() - 1)]
+        &self[..(self.len() - 1)]
     }
 
     #[inline]
@@ -443,7 +443,7 @@ fn contains(&self, x: &T) -> bool where T: PartialEq {
     #[inline]
     fn starts_with(&self, needle: &[T]) -> bool where T: PartialEq {
         let n = needle.len();
-        self.len() >= n && needle == &self[0..n]
+        self.len() >= n && needle == &self[..n]
     }
 
     #[inline]
@@ -972,7 +972,7 @@ fn next(&mut self) -> Option<&'a [T]> {
         match self.v.iter().position(|x| (self.pred)(x)) {
             None => self.finish(),
             Some(idx) => {
-                let ret = Some(&self.v[0..idx]);
+                let ret = Some(&self.v[..idx]);
                 self.v = &self.v[(idx + 1)..];
                 ret
             }
@@ -999,7 +999,7 @@ fn next_back(&mut self) -> Option<&'a [T]> {
             None => self.finish(),
             Some(idx) => {
                 let ret = Some(&self.v[(idx + 1)..]);
-                self.v = &self.v[0..idx];
+                self.v = &self.v[..idx];
                 ret
             }
         }
@@ -1195,7 +1195,7 @@ fn next(&mut self) -> Option<&'a [T]> {
         if self.size > self.v.len() {
             None
         } else {
-            let ret = Some(&self.v[0..self.size]);
+            let ret = Some(&self.v[..self.size]);
             self.v = &self.v[1..];
             ret
         }
index 94ee9b7dcf6adaa639e931f9888a88b3546c3e5e..d9cf6dc086d9972099544924198cdf313333f096 100644 (file)
@@ -701,10 +701,10 @@ fn new(needle: &[u8]) -> TwoWaySearcher {
         //
         // What's going on is we have some critical factorization (u, v) of the
         // needle, and we want to determine whether u is a suffix of
-        // &v[0..period]. If it is, we use "Algorithm CP1". Otherwise we use
+        // &v[..period]. If it is, we use "Algorithm CP1". Otherwise we use
         // "Algorithm CP2", which is optimized for when the period of the needle
         // is large.
-        if &needle[0..crit_pos] == &needle[period.. period + crit_pos] {
+        if &needle[..crit_pos] == &needle[period.. period + crit_pos] {
             TwoWaySearcher {
                 crit_pos: crit_pos,
                 period: period,
@@ -1412,7 +1412,7 @@ unsafe fn slice_unchecked(&self, begin: uint, end: uint) -> &str {
     #[inline]
     fn starts_with(&self, needle: &str) -> bool {
         let n = needle.len();
-        self.len() >= n && needle.as_bytes() == &self.as_bytes()[0..n]
+        self.len() >= n && needle.as_bytes() == &self.as_bytes()[..n]
     }
 
     #[inline]
index f8e943ec9f651a9bef01e5e5c2388dc6b24beabb..8e3c7f4595a48cafe2865ecbdafbf6b389b2c461 100644 (file)
@@ -30,49 +30,49 @@ fn bool_and() {
 
 #[test]
 fn uint_and() {
-    let x = AtomicUint::new(0xf731);
+    let x = AtomicUsize::new(0xf731);
     assert_eq!(x.fetch_and(0x137f, SeqCst), 0xf731);
     assert_eq!(x.load(SeqCst), 0xf731 & 0x137f);
 }
 
 #[test]
 fn uint_or() {
-    let x = AtomicUint::new(0xf731);
+    let x = AtomicUsize::new(0xf731);
     assert_eq!(x.fetch_or(0x137f, SeqCst), 0xf731);
     assert_eq!(x.load(SeqCst), 0xf731 | 0x137f);
 }
 
 #[test]
 fn uint_xor() {
-    let x = AtomicUint::new(0xf731);
+    let x = AtomicUsize::new(0xf731);
     assert_eq!(x.fetch_xor(0x137f, SeqCst), 0xf731);
     assert_eq!(x.load(SeqCst), 0xf731 ^ 0x137f);
 }
 
 #[test]
 fn int_and() {
-    let x = AtomicInt::new(0xf731);
+    let x = AtomicIsize::new(0xf731);
     assert_eq!(x.fetch_and(0x137f, SeqCst), 0xf731);
     assert_eq!(x.load(SeqCst), 0xf731 & 0x137f);
 }
 
 #[test]
 fn int_or() {
-    let x = AtomicInt::new(0xf731);
+    let x = AtomicIsize::new(0xf731);
     assert_eq!(x.fetch_or(0x137f, SeqCst), 0xf731);
     assert_eq!(x.load(SeqCst), 0xf731 | 0x137f);
 }
 
 #[test]
 fn int_xor() {
-    let x = AtomicInt::new(0xf731);
+    let x = AtomicIsize::new(0xf731);
     assert_eq!(x.fetch_xor(0x137f, SeqCst), 0xf731);
     assert_eq!(x.load(SeqCst), 0xf731 ^ 0x137f);
 }
 
 static S_BOOL : AtomicBool = ATOMIC_BOOL_INIT;
-static S_INT  : AtomicInt  = ATOMIC_INT_INIT;
-static S_UINT : AtomicUint = ATOMIC_UINT_INIT;
+static S_INT  : AtomicIsize  = ATOMIC_ISIZE_INIT;
+static S_UINT : AtomicUsize = ATOMIC_USIZE_INIT;
 
 #[test]
 fn static_init() {
index 7b6b4f848085e75a49d2c578e83b9662a3c50aa0..2e29b1c41c418f1fb098735d3df6ee353e942d3a 100644 (file)
@@ -167,7 +167,7 @@ fn test_encode_utf8() {
     fn check(input: char, expect: &[u8]) {
         let mut buf = [0u8; 4];
         let n = input.encode_utf8(buf.as_mut_slice()).unwrap_or(0);
-        assert_eq!(&buf[0..n], expect);
+        assert_eq!(&buf[..n], expect);
     }
 
     check('x', &[0x78]);
@@ -181,7 +181,7 @@ fn test_encode_utf16() {
     fn check(input: char, expect: &[u16]) {
         let mut buf = [0u16; 2];
         let n = input.encode_utf16(buf.as_mut_slice()).unwrap_or(0);
-        assert_eq!(&buf[0..n], expect);
+        assert_eq!(&buf[..n], expect);
     }
 
     check('x', &[0x0078]);
index 61266a926494458f62bfffdbac6b964cbcffac83..26819bf92098631a86ba05c2940d201fe1a6e996 100644 (file)
@@ -288,7 +288,7 @@ fn test_iterator_len() {
     let v: &[_] = &[0i, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
     assert_eq!(v[..4].iter().count(), 4);
     assert_eq!(v[..10].iter().count(), 10);
-    assert_eq!(v[0..0].iter().count(), 0);
+    assert_eq!(v[..0].iter().count(), 0);
 }
 
 #[test]
@@ -296,31 +296,31 @@ fn test_iterator_sum() {
     let v: &[_] = &[0i, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
     assert_eq!(v[..4].iter().map(|&x| x).sum(), 6);
     assert_eq!(v.iter().map(|&x| x).sum(), 55);
-    assert_eq!(v[0..0].iter().map(|&x| x).sum(), 0);
+    assert_eq!(v[..0].iter().map(|&x| x).sum(), 0);
 }
 
 #[test]
 fn test_iterator_product() {
     let v: &[_] = &[0i, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
-    assert_eq!(v[0..4].iter().map(|&x| x).product(), 0);
+    assert_eq!(v[..4].iter().map(|&x| x).product(), 0);
     assert_eq!(v[1..5].iter().map(|&x| x).product(), 24);
-    assert_eq!(v[0..0].iter().map(|&x| x).product(), 1);
+    assert_eq!(v[..0].iter().map(|&x| x).product(), 1);
 }
 
 #[test]
 fn test_iterator_max() {
     let v: &[_] = &[0i, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
-    assert_eq!(v[0..4].iter().map(|&x| x).max(), Some(3));
+    assert_eq!(v[..4].iter().map(|&x| x).max(), Some(3));
     assert_eq!(v.iter().map(|&x| x).max(), Some(10));
-    assert_eq!(v[0..0].iter().map(|&x| x).max(), None);
+    assert_eq!(v[..0].iter().map(|&x| x).max(), None);
 }
 
 #[test]
 fn test_iterator_min() {
     let v: &[_] = &[0i, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
-    assert_eq!(v[0..4].iter().map(|&x| x).min(), Some(0));
+    assert_eq!(v[..4].iter().map(|&x| x).min(), Some(0));
     assert_eq!(v.iter().map(|&x| x).min(), Some(0));
-    assert_eq!(v[0..0].iter().map(|&x| x).min(), None);
+    assert_eq!(v[..0].iter().map(|&x| x).min(), None);
 }
 
 #[test]
@@ -373,7 +373,7 @@ fn test_all() {
     assert!(v.iter().all(|&x| x < 10));
     assert!(!v.iter().all(|&x| x % 2 == 0));
     assert!(!v.iter().all(|&x| x > 100));
-    assert!(v[0..0].iter().all(|_| panic!()));
+    assert!(v[..0].iter().all(|_| panic!()));
 }
 
 #[test]
@@ -382,7 +382,7 @@ fn test_any() {
     assert!(v.iter().any(|&x| x < 10));
     assert!(v.iter().any(|&x| x % 2 == 0));
     assert!(!v.iter().any(|&x| x > 100));
-    assert!(!v[0..0].iter().any(|_| panic!()));
+    assert!(!v[..0].iter().any(|_| panic!()));
 }
 
 #[test]
index 96b50e8bccbad0c62c067522ee8a93a68ff781b9..3dc209e6fcb247fe41760e4da303dc7bb8899aad 100644 (file)
@@ -19,18 +19,14 @@ fn size_of_basic() {
 }
 
 #[test]
-#[cfg(any(target_arch = "x86",
-          target_arch = "arm",
-          target_arch = "mips",
-          target_arch = "mipsel"))]
+#[cfg(target_pointer_width = "32")]
 fn size_of_32() {
     assert_eq!(size_of::<uint>(), 4u);
     assert_eq!(size_of::<*const uint>(), 4u);
 }
 
 #[test]
-#[cfg(any(target_arch = "x86_64",
-          target_arch = "aarch64"))]
+#[cfg(target_pointer_width = "64")]
 fn size_of_64() {
     assert_eq!(size_of::<uint>(), 8u);
     assert_eq!(size_of::<*const uint>(), 8u);
@@ -52,18 +48,14 @@ fn align_of_basic() {
 }
 
 #[test]
-#[cfg(any(target_arch = "x86",
-          target_arch = "arm",
-          target_arch = "mips",
-          target_arch = "mipsel"))]
+#[cfg(target_pointer_width = "32")]
 fn align_of_32() {
     assert_eq!(align_of::<uint>(), 4u);
     assert_eq!(align_of::<*const uint>(), 4u);
 }
 
 #[test]
-#[cfg(any(target_arch = "x86_64",
-          target_arch = "aarch64"))]
+#[cfg(target_pointer_width = "64")]
 fn align_of_64() {
     assert_eq!(align_of::<uint>(), 8u);
     assert_eq!(align_of::<*const uint>(), 8u);
index 70ad8d28d271ff727f6841c3f2fd8a8e63d60e53..85944ccc5517c1c855152e0e10c12c0c2eb641b6 100644 (file)
@@ -286,7 +286,7 @@ fn format(&mut self) -> FormatSpec<'a> {
             flags: 0,
             precision: CountImplied,
             width: CountImplied,
-            ty: &self.input[0..0],
+            ty: &self.input[..0],
         };
         if !self.consume(':') { return spec }
 
@@ -395,7 +395,7 @@ fn word(&mut self) -> &'a str {
                 self.cur.next();
                 pos
             }
-            Some(..) | None => { return &self.input[0..0]; }
+            Some(..) | None => { return &self.input[..0]; }
         };
         let mut end;
         loop {
index c866deafee4569a84bb99985e4a760f27d9391e3..deab0cabfbe5195bfce29fbb75be076cdb0b4c55 100644 (file)
@@ -497,7 +497,8 @@ pub mod bsd44 {
         #[cfg(any(target_arch = "x86",
                   target_arch = "arm",
                   target_arch = "mips",
-                  target_arch = "mipsel"))]
+                  target_arch = "mipsel",
+                  target_arch = "powerpc"))]
         pub mod arch {
             pub mod c95 {
                 pub type c_char = i8;
@@ -528,7 +529,8 @@ pub mod c99 {
             }
             #[cfg(any(target_arch = "x86",
                       target_arch = "mips",
-                      target_arch = "mipsel"))]
+                      target_arch = "mipsel",
+                      target_arch = "powerpc"))]
             pub mod posix88 {
                 pub type off_t = i32;
                 pub type dev_t = u64;
@@ -642,7 +644,9 @@ pub mod posix01 {
                     pub __size: [u32; 9]
                 }
             }
-            #[cfg(any(target_arch = "mips", target_arch = "mipsel"))]
+            #[cfg(any(target_arch = "mips",
+                      target_arch = "mipsel",
+                      target_arch = "powerpc"))]
             pub mod posix01 {
                 use types::os::arch::c95::{c_long, c_ulong, time_t};
                 use types::os::arch::posix88::{gid_t, ino_t};
@@ -2697,7 +2701,9 @@ pub mod posix88 {
             pub const EHWPOISON: c_int = 133;
         }
 
-        #[cfg(any(target_arch = "mips", target_arch = "mipsel"))]
+        #[cfg(any(target_arch = "mips",
+                  target_arch = "mipsel",
+                  target_arch = "powerpc"))]
         pub mod posix88 {
             use types::os::arch::c95::c_int;
             use types::common::c95::c_void;
@@ -2982,7 +2988,8 @@ pub mod posix01 {
             #[cfg(all(target_os = "linux",
                       any(target_arch = "mips",
                           target_arch = "mipsel",
-                          target_arch = "aarch64")))]
+                          target_arch = "aarch64",
+                          target_arch = "powerpc")))]
             pub const PTHREAD_STACK_MIN: size_t = 131072;
 
             pub const CLOCK_REALTIME: c_int = 0;
@@ -3040,7 +3047,9 @@ pub mod bsd44 {
             pub const SHUT_WR: c_int = 1;
             pub const SHUT_RDWR: c_int = 2;
         }
-        #[cfg(any(target_arch = "mips", target_arch = "mipsel"))]
+        #[cfg(any(target_arch = "mips",
+                  target_arch = "mipsel",
+                  target_arch = "powerpc"))]
         pub mod bsd44 {
             use types::os::arch::c95::c_int;
 
@@ -3115,7 +3124,9 @@ pub mod extra {
             pub const MAP_NONBLOCK : c_int = 0x010000;
             pub const MAP_STACK : c_int = 0x020000;
         }
-        #[cfg(any(target_arch = "mips", target_arch = "mipsel"))]
+        #[cfg(any(target_arch = "mips",
+                  target_arch = "mipsel",
+                  target_arch = "powerpc"))]
         pub mod extra {
             use types::os::arch::c95::c_int;
 
index 4d605253ab06474c6671c4cdd8f416e45d373099..8430ee81c321462a6ee025850b8ce739a0b8bcff 100644 (file)
@@ -270,8 +270,7 @@ fn gen_ascii_chars<'a>(&'a mut self) -> AsciiGenerator<'a, Self> {
     /// let choices = [1i, 2, 4, 8, 16, 32];
     /// let mut rng = thread_rng();
     /// println!("{:?}", rng.choose(&choices));
-    /// # // uncomment when slicing syntax is stable
-    /// //assert_eq!(rng.choose(&choices[0..0]), None);
+    /// assert_eq!(rng.choose(&choices[..0]), None);
     /// ```
     fn choose<'a, T>(&mut self, values: &'a [T]) -> Option<&'a T> {
         if values.is_empty() {
index bdc00d7db97fe8e22da8b66d50826f459683b3ea..f39860c8695c96c8c629513fe4138b19f219e656 100644 (file)
@@ -95,7 +95,7 @@ fn write(&mut self, buf: &[u8]) -> IoResult<()> {
             // there (left), and what will be appended on the end (right)
             let cap = self.buf.len() - self.pos;
             let (left, right) = if cap <= buf.len() {
-                (&buf[0..cap], &buf[cap..])
+                (&buf[..cap], &buf[cap..])
             } else {
                 let result: (_, &[_]) = (buf, &[]);
                 result
index e79ee7fa6477bea68a32eb3ccb28bb6baf965fab..697dddca74fb1291182e8c326b1633a02f43be40 100644 (file)
@@ -68,7 +68,7 @@ util     - ubiquitous types and helper functions
 lib      - bindings to LLVM
 
 The entry-point for the compiler is main() in the librustc_trans
-crate. But the 
+crate.
 
 The 3 central data structures:
 ------------------------------
index fb7c5296d020e38ac637f6e7cc9ffbd0f5d2a59e..b79f19413ef924dec6e35e598821236f61f1293a 100644 (file)
 
 extern crate arena;
 extern crate flate;
+extern crate fmt_macros;
 extern crate getopts;
 extern crate graphviz;
 extern crate libc;
+extern crate regex;
 extern crate rustc_llvm;
 extern crate rustc_back;
 extern crate serialize;
index 620b8f277dddcd95a5a7959a96b6c31699d91d24..59808b302f47dff362678a63eb41cf1b073fffbf 100644 (file)
@@ -666,6 +666,7 @@ fn check_attribute(&mut self, cx: &Context, attr: &ast::Attribute) {
             "must_use",
             "stable",
             "unstable",
+            "rustc_on_unimplemented",
 
             // FIXME: #19470 this shouldn't be needed forever
             "old_orphan_check",
@@ -773,9 +774,8 @@ fn check_stmt(&mut self, cx: &Context, s: &ast::Stmt) {
                         warned |= check_must_use(cx, &it.attrs[], s.span);
                     }
                 } else {
-                    csearch::get_item_attrs(&cx.sess().cstore, did, |attrs| {
-                        warned |= check_must_use(cx, &attrs[], s.span);
-                    });
+                    let attrs = csearch::get_item_attrs(&cx.sess().cstore, did);
+                    warned |= check_must_use(cx, &attrs[], s.span);
                 }
             }
             _ => {}
@@ -1731,7 +1731,7 @@ fn check_expr(&mut self, cx: &Context, e: &ast::Expr) {
         let mut span = e.span;
 
         let id = match e.node {
-            ast::ExprPath(..) | ast::ExprStruct(..) => {
+            ast::ExprPath(..) | ast::ExprQPath(..) | ast::ExprStruct(..) => {
                 match cx.tcx.def_map.borrow().get(&e.id) {
                     Some(&def) => def.def_id(),
                     None => return
index cfff7c9935bc8ddefd18986be22f2710964d550c..0bbd11bea0a48e0daaee8a8e5b8da9b0fdef911b 100644 (file)
@@ -203,13 +203,11 @@ pub fn get_methods_if_impl(cstore: &cstore::CStore,
     decoder::get_methods_if_impl(cstore.intr.clone(), &*cdata, def.node)
 }
 
-pub fn get_item_attrs<F>(cstore: &cstore::CStore,
-                         def_id: ast::DefId,
-                         f: F) where
-    F: FnOnce(Vec<ast::Attribute>),
-{
+pub fn get_item_attrs(cstore: &cstore::CStore,
+                      def_id: ast::DefId)
+                      -> Vec<ast::Attribute> {
     let cdata = cstore.get_crate_data(def_id.krate);
-    decoder::get_item_attrs(&*cdata, def_id.node, f)
+    decoder::get_item_attrs(&*cdata, def_id.node)
 }
 
 pub fn get_struct_fields(cstore: &cstore::CStore,
index 5ac8f908bf1642360d3e4f2ab461786eb573fefe..dfbff7156886d42ce45f9e15eac2a02c8de51bd1 100644 (file)
@@ -1025,18 +1025,16 @@ pub fn get_tuple_struct_definition_if_ctor(cdata: Cmd,
     ret
 }
 
-pub fn get_item_attrs<F>(cdata: Cmd,
-                         orig_node_id: ast::NodeId,
-                         f: F) where
-    F: FnOnce(Vec<ast::Attribute>),
-{
+pub fn get_item_attrs(cdata: Cmd,
+                      orig_node_id: ast::NodeId)
+                      -> Vec<ast::Attribute> {
     // The attributes for a tuple struct are attached to the definition, not the ctor;
     // we assume that someone passing in a tuple struct ctor is actually wanting to
     // look at the definition
     let node_id = get_tuple_struct_definition_if_ctor(cdata, orig_node_id);
     let node_id = node_id.map(|x| x.node).unwrap_or(orig_node_id);
     let item = lookup_item(node_id, cdata.data());
-    f(get_attributes(item));
+    get_attributes(item)
 }
 
 pub fn get_struct_field_attrs(cdata: Cmd) -> HashMap<ast::NodeId, Vec<ast::Attribute>> {
index e8160487e16f73f1a7c36048a4e57c82498e4984..193b14174c7abc3890e14ead41568ca871491ce6 100644 (file)
@@ -54,7 +54,7 @@ pub fn for_each_lib_search_path<F>(&self, mut f: F) where
 
         debug!("filesearch: searching lib path");
         let tlib_path = make_target_lib_path(self.sysroot,
-                                    self.triple);
+                                             self.triple);
         if !visited_dirs.contains(tlib_path.as_vec()) {
             match f(&tlib_path) {
                 FileMatches => found = true,
index b601ea59486ce6ee32e67218530700b0c20e75f4..07b520e5865b233b28e666d4b9dcfe1d32b7d118 100644 (file)
@@ -495,7 +495,8 @@ fn expr(&mut self, expr: &ast::Expr, pred: CFGIndex) -> CFGIndex {
             ast::ExprMac(..) |
             ast::ExprClosure(..) |
             ast::ExprLit(..) |
-            ast::ExprPath(..) => {
+            ast::ExprPath(..) |
+            ast::ExprQPath(..) => {
                 self.straightline(expr, pred, None::<ast::Expr>.iter())
             }
         }
index 621d7274b3f7c01a41c3c386ab8c1c3cf4623c5d..202020a9033ed9ced58f1411ddf0573dbcf9ef5a 100644 (file)
@@ -111,7 +111,7 @@ fn check_expr(v: &mut CheckCrateVisitor, e: &ast::Expr) {
                            expression");
             }
         }
-        ast::ExprPath(_) => {
+        ast::ExprPath(_) | ast::ExprQPath(_) => {
             match v.tcx.def_map.borrow()[e.id] {
                 DefStatic(..) | DefConst(..) |
                 DefFn(..) | DefStaticMethod(..) | DefMethod(..) |
index 43f39a67f5c41b1d78b34b74a602d0965c2d9f40..a1a90395b3b783306c08c7a9f488348694a53a58 100644 (file)
@@ -926,7 +926,7 @@ pub fn specialize<'a>(cx: &MatchCheckCtxt, r: &[&'a Pat],
         }
     };
     head.map(|mut head| {
-        head.push_all(&r[0..col]);
+        head.push_all(&r[..col]);
         head.push_all(&r[(col + 1)..]);
         head
     })
index 154272d2deb41caefec580c198a041ed889d8cbe..026aa3c5ccf837d710b72c5db398759c010aa9c1 100644 (file)
@@ -228,7 +228,7 @@ fn visit_expr(&mut self, e: &ast::Expr) {
                           "{} are not allowed to have custom pointers",
                           self.msg());
             }
-            ast::ExprPath(..) => {
+            ast::ExprPath(_) | ast::ExprQPath(_) => {
                 match ty::resolve_expr(self.tcx, e) {
                     def::DefStatic(..) if self.mode == InConstant => {
                         let msg = "constants cannot refer to other statics, \
index e2a0738def180dd2c47a28e5968c7d14a21bb511..86a58dae45aa4c96676b6df893f1a8a2ba46a0c5 100644 (file)
@@ -93,7 +93,7 @@ fn visit_item(&mut self, it: &ast::Item) {
 
     fn visit_expr(&mut self, e: &ast::Expr) {
         match e.node {
-            ast::ExprPath(..) => {
+            ast::ExprPath(_) | ast::ExprQPath(_) => {
                 match self.def_map.borrow().get(&e.id) {
                     Some(&DefStatic(def_id, _)) |
                     Some(&DefConst(def_id)) if
index 52352e920ce36a3922683413684780e822e951d9..c998d178c22459b8c91a898ab4544370eed060d4 100644 (file)
@@ -244,7 +244,7 @@ fn classify(&mut self, e: &Expr) -> constness {
 
             // FIXME: (#3728) we can probably do something CCI-ish
             // surrounding nonlocal constants. But we don't yet.
-            ast::ExprPath(_) => self.lookup_constness(e),
+            ast::ExprPath(_) | ast::ExprQPath(_) => self.lookup_constness(e),
 
             ast::ExprRepeat(..) => general_const,
 
@@ -356,6 +356,13 @@ pub fn const_expr_to_pat(tcx: &ty::ctxt, expr: &Expr) -> P<ast::Pat> {
             }
         }
 
+        ast::ExprQPath(_) => {
+            match lookup_const(tcx, expr) {
+                Some(actual) => return const_expr_to_pat(tcx, actual),
+                _ => unreachable!()
+            }
+        }
+
         _ => ast::PatLit(P(expr.clone()))
     };
     P(ast::Pat { id: expr.id, node: pat, span: expr.span })
@@ -542,7 +549,7 @@ macro_rules! define_casts {
                 ty::ty_float(ast::TyF64) => (f64, const_float, f64)
             }))
       }
-      ast::ExprPath(_) => {
+      ast::ExprPath(_) | ast::ExprQPath(_) => {
           match lookup_const(tcx, e) {
               Some(actual_e) => eval_const_expr_partial(tcx, &*actual_e),
               None => Err("non-constant path in constant expr".to_string())
index f7eea6e5cb7c9cc45da7be1b13ae6c291afd87a2..abb8f35f662b5e07604f03d873a7d0861a8b9c99 100644 (file)
@@ -175,7 +175,7 @@ fn visit_expr(&mut self, expr: &ast::Expr) {
             ast::ExprInlineAsm(..) => {
                 self.require_unsafe(expr.span, "use of inline assembly");
             }
-            ast::ExprPath(..) => {
+            ast::ExprPath(_) | ast::ExprQPath(_) => {
                 if let def::DefStatic(_, true) = ty::resolve_expr(self.tcx, expr) {
                     self.require_unsafe(expr.span, "use of mutable static");
                 }
index e5eb439d42c75a3fa6f20bb8b22e8bab50cc7059..a5f2dc398e9e2fddb71b4a1ff81811a591a65d3d 100644 (file)
@@ -424,7 +424,7 @@ pub fn walk_expr(&mut self, expr: &ast::Expr) {
                 self.walk_expr(&**subexpr)
             }
 
-            ast::ExprPath(..) => { }
+            ast::ExprPath(_) | ast::ExprQPath(_) => { }
 
             ast::ExprUnary(ast::UnDeref, ref base) => {      // *base
                 if !self.walk_overloaded_operator(expr, &**base, Vec::new(), PassArgs::ByRef) {
index ab1c41f69683eb074ecb8dd5a9eaa857bdebd84a..8fd44f144e1ea577fc30a832bef7d1b9addb4282 100644 (file)
@@ -613,6 +613,39 @@ pub fn commit_if_ok<T, E, F>(&self, f: F) -> Result<T, E> where
         self.commit_unconditionally(move || self.try(move |_| f()))
     }
 
+    /// Execute `f` and commit only the region bindings if successful.
+    /// The function f must be very careful not to leak any non-region
+    /// variables that get created.
+    pub fn commit_regions_if_ok<T, E, F>(&self, f: F) -> Result<T, E> where
+        F: FnOnce() -> Result<T, E>
+    {
+        debug!("commit_regions_if_ok()");
+        let CombinedSnapshot { type_snapshot,
+                               int_snapshot,
+                               float_snapshot,
+                               region_vars_snapshot } = self.start_snapshot();
+
+        let r = self.try(move |_| f());
+
+        // Roll back any non-region bindings - they should be resolved
+        // inside `f`, with, e.g. `resolve_type_vars_if_possible`.
+        self.type_variables
+            .borrow_mut()
+            .rollback_to(type_snapshot);
+        self.int_unification_table
+            .borrow_mut()
+            .rollback_to(int_snapshot);
+        self.float_unification_table
+            .borrow_mut()
+            .rollback_to(float_snapshot);
+
+        // Commit region vars that may escape through resolved types.
+        self.region_vars
+            .commit(region_vars_snapshot);
+
+        r
+    }
+
     /// Execute `f`, unroll bindings on panic
     pub fn try<T, E, F>(&self, f: F) -> Result<T, E> where
         F: FnOnce(&CombinedSnapshot) -> Result<T, E>
index 1b1dca004228eafb3d9e6074f254ae19b7128b15..6b9e5b2ceea3a6d4ba40df2e5724cc09717f9430 100644 (file)
@@ -447,7 +447,7 @@ fn visit_arm(ir: &mut IrMaps, arm: &ast::Arm) {
 fn visit_expr(ir: &mut IrMaps, expr: &Expr) {
     match expr.node {
       // live nodes required for uses or definitions of variables:
-      ast::ExprPath(_) => {
+      ast::ExprPath(_) | ast::ExprQPath(_) => {
         let def = ir.tcx.def_map.borrow()[expr.id].clone();
         debug!("expr {}: path that leads to {:?}", expr.id, def);
         if let DefLocal(..) = def {
@@ -960,7 +960,7 @@ fn propagate_through_expr(&mut self, expr: &Expr, succ: LiveNode)
         match expr.node {
           // Interesting cases with control flow or which gen/kill
 
-          ast::ExprPath(_) => {
+          ast::ExprPath(_) | ast::ExprQPath(_) => {
               self.access_path(expr, succ, ACC_READ | ACC_USE)
           }
 
@@ -1289,7 +1289,7 @@ fn propagate_through_lvalue_components(&mut self,
         // just ignore such cases and treat them as reads.
 
         match expr.node {
-            ast::ExprPath(_) => succ,
+            ast::ExprPath(_) | ast::ExprQPath(_) => succ,
             ast::ExprField(ref e, _) => self.propagate_through_expr(&**e, succ),
             ast::ExprTupField(ref e, _) => self.propagate_through_expr(&**e, succ),
             _ => self.propagate_through_expr(expr, succ)
@@ -1300,7 +1300,9 @@ fn propagate_through_lvalue_components(&mut self,
     fn write_lvalue(&mut self, expr: &Expr, succ: LiveNode, acc: uint)
                     -> LiveNode {
         match expr.node {
-          ast::ExprPath(_) => self.access_path(expr, succ, acc),
+          ast::ExprPath(_) | ast::ExprQPath(_) => {
+              self.access_path(expr, succ, acc)
+          }
 
           // We do not track other lvalues, so just propagate through
           // to their subcomponents.  Also, it may happen that
@@ -1492,7 +1494,7 @@ fn check_expr(this: &mut Liveness, expr: &Expr) {
       ast::ExprBlock(..) | ast::ExprMac(..) | ast::ExprAddrOf(..) |
       ast::ExprStruct(..) | ast::ExprRepeat(..) | ast::ExprParen(..) |
       ast::ExprClosure(..) | ast::ExprPath(..) | ast::ExprBox(..) |
-      ast::ExprRange(..) => {
+      ast::ExprRange(..) | ast::ExprQPath(..) => {
         visit::walk_expr(this, expr);
       }
       ast::ExprIfLet(..) => {
@@ -1583,7 +1585,7 @@ fn check_ret(&self,
 
     fn check_lvalue(&mut self, expr: &Expr) {
         match expr.node {
-            ast::ExprPath(_) => {
+            ast::ExprPath(_) | ast::ExprQPath(_) => {
                 if let DefLocal(nid) = self.ir.tcx.def_map.borrow()[expr.id].clone() {
                     // Assignment to an immutable variable or argument: only legal
                     // if there is no later assignment. If this local is actually
index 51ec75284326c4f76f9b790ef99b19cc654b76a4..90fe6b4991138d3fd8b45072efd8cf63f228be30 100644 (file)
@@ -520,7 +520,7 @@ pub fn cat_expr_unadjusted(&self, expr: &ast::Expr) -> McResult<cmt<'tcx>> {
             }
           }
 
-          ast::ExprPath(_) => {
+          ast::ExprPath(_) | ast::ExprQPath(_) => {
             let def = (*self.tcx().def_map.borrow())[expr.id];
             self.cat_def(expr.id, expr.span, expr_ty, def)
           }
index aa37c2fe348b586c178e121114ac47d79b41d027..b92870cfa42b0d181ce1e8f3be12771646bd588e 100644 (file)
@@ -920,7 +920,7 @@ fn visit_expr(&mut self, expr: &ast::Expr) {
                                                             struct type?!"),
                 }
             }
-            ast::ExprPath(..) => {
+            ast::ExprPath(_) | ast::ExprQPath(_) => {
                 let guard = |&: did: ast::DefId| {
                     let fields = ty::lookup_struct_fields(self.tcx, did);
                     let any_priv = fields.iter().any(|f| {
index 906607ddc5ba14e77e205064b5f67a2425fb914c..b7e6da8c5f63aa29664cbaa9e7bfcd4a53fd20f4 100644 (file)
@@ -104,7 +104,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for ReachableContext<'a, 'tcx> {
     fn visit_expr(&mut self, expr: &ast::Expr) {
 
         match expr.node {
-            ast::ExprPath(_) => {
+            ast::ExprPath(_) | ast::ExprQPath(_) => {
                 let def = match self.tcx.def_map.borrow().get(&expr.id) {
                     Some(&def) => def,
                     None => {
index a6a6703353cd1ca12911f72ea3b6fb101eab43c8..017641bd3b71aeb6cbf4f6fbe75412c9fc2c6e4d 100644 (file)
@@ -12,7 +12,7 @@
 //
 // There are various parts of the compiler that must impose arbitrary limits
 // on how deeply they recurse to prevent stack overflow. Users can override
-// this via an attribute on the crate like `#![recursion_limit(22)]`. This pass
+// this via an attribute on the crate like `#![recursion_limit="22"]`. This pass
 // just peeks and looks for that attribute.
 
 use session::Session;
@@ -34,6 +34,6 @@ pub fn update_recursion_limit(sess: &Session, krate: &ast::Crate) {
         }
 
         sess.span_err(attr.span, "malformed recursion limit attribute, \
-                                  expected #![recursion_limit(\"N\")]");
+                                  expected #![recursion_limit=\"N\"]");
     }
 }
index 9ac6b8a86b68b10585fb191f64ca5552f3cb181a..9ad2dd499cc9deb56b69154a4213847f3167d72d 100644 (file)
@@ -19,7 +19,7 @@
 
 use std::fmt;
 use std::slice::Iter;
-use std::vec::Vec;
+use std::vec::{Vec, IntoIter};
 use syntax::codemap::{Span, DUMMY_SP};
 
 ///////////////////////////////////////////////////////////////////////////
@@ -397,6 +397,10 @@ pub fn iter<'a>(&'a self) -> Iter<'a,T> {
         self.content.iter()
     }
 
+    pub fn into_iter(self) -> IntoIter<T> {
+        self.content.into_iter()
+    }
+
     pub fn iter_enumerated<'a>(&'a self) -> EnumeratedItems<'a,T> {
         EnumeratedItems::new(self)
     }
index 02c913a9e81ae34991cb6405824558085ee6a936..6d0e60ec495a7bee25ea3fe8249befef125adf29 100644 (file)
     SelectionError,
 };
 
+use fmt_macros::{Parser, Piece, Position};
 use middle::infer::InferCtxt;
-use middle::ty::{self, AsPredicate, ReferencesError, ToPolyTraitRef};
-use syntax::codemap::Span;
+use middle::ty::{self, AsPredicate, ReferencesError, ToPolyTraitRef, TraitRef};
+use std::collections::HashMap;
+use syntax::codemap::{DUMMY_SP, Span};
+use syntax::attr::{AttributeMethods, AttrMetaMethods};
 use util::ppaux::{Repr, UserString};
 
 pub fn report_fulfillment_errors<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
@@ -62,6 +65,83 @@ pub fn report_projection_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
     }
 }
 
+fn report_on_unimplemented<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
+                                     trait_ref: &TraitRef<'tcx>,
+                                     span: Span) -> Option<String> {
+    let def_id = trait_ref.def_id;
+    let mut report = None;
+    for item in ty::get_attrs(infcx.tcx, def_id).iter() {
+        if item.check_name("rustc_on_unimplemented") {
+            let err_sp = if item.meta().span == DUMMY_SP {
+                span
+            } else {
+                item.meta().span
+            };
+            let def = ty::lookup_trait_def(infcx.tcx, def_id);
+            let trait_str = def.trait_ref.user_string(infcx.tcx);
+            if let Some(ref istring) = item.value_str() {
+                let mut generic_map = def.generics.types.iter_enumerated()
+                                         .map(|(param, i, gen)| {
+                                               (gen.name.as_str().to_string(),
+                                                trait_ref.substs.types.get(param, i)
+                                                         .user_string(infcx.tcx))
+                                              }).collect::<HashMap<String, String>>();
+                generic_map.insert("Self".to_string(),
+                                   trait_ref.self_ty().user_string(infcx.tcx));
+                let parser = Parser::new(istring.get());
+                let mut errored = false;
+                let err: String = parser.filter_map(|p| {
+                    match p {
+                        Piece::String(s) => Some(s),
+                        Piece::NextArgument(a) => match a.position {
+                            Position::ArgumentNamed(s) => match generic_map.get(s) {
+                                Some(val) => Some(val.as_slice()),
+                                None => {
+                                    infcx.tcx.sess
+                                         .span_err(err_sp,
+                                                   format!("the #[rustc_on_unimplemented] \
+                                                            attribute on \
+                                                            trait definition for {} refers to \
+                                                            non-existent type parameter {}",
+                                                           trait_str, s)
+                                                   .as_slice());
+                                    errored = true;
+                                    None
+                                }
+                            },
+                            _ => {
+                                infcx.tcx.sess
+                                     .span_err(err_sp,
+                                               format!("the #[rustc_on_unimplemented] \
+                                                        attribute on \
+                                                        trait definition for {} must have named \
+                                                        format arguments, \
+                                                        eg `#[rustc_on_unimplemented = \
+                                                        \"foo {{T}}\"]`",
+                                                       trait_str).as_slice());
+                                errored = true;
+                                None
+                            }
+                        }
+                    }
+                }).collect();
+                // Report only if the format string checks out
+                if !errored {
+                    report = Some(err);
+                }
+            } else {
+                infcx.tcx.sess.span_err(err_sp,
+                                        format!("the #[rustc_on_unimplemented] attribute on \
+                                                 trait definition for {} must have a value, \
+                                                 eg `#[rustc_on_unimplemented = \"foo\"]`",
+                                                 trait_str).as_slice());
+            }
+            break;
+        }
+    }
+    report
+}
+
 pub fn report_selection_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
                                         obligation: &PredicateObligation<'tcx>,
                                         error: &SelectionError<'tcx>)
@@ -81,58 +161,80 @@ pub fn report_selection_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
 
             note_obligation_cause(infcx, obligation);
         }
-        SelectionError::Unimplemented => {
-            match obligation.predicate {
-                ty::Predicate::Trait(ref trait_predicate) => {
-                    let trait_predicate =
-                        infcx.resolve_type_vars_if_possible(trait_predicate);
-                    if !trait_predicate.references_error() {
-                        let trait_ref = trait_predicate.to_poly_trait_ref();
-                        infcx.tcx.sess.span_err(
-                            obligation.cause.span,
-                            format!(
-                                "the trait `{}` is not implemented for the type `{}`",
-                                trait_ref.user_string(infcx.tcx),
-                                trait_ref.self_ty().user_string(infcx.tcx)).as_slice());
-                    }
-                }
 
-                ty::Predicate::Equate(ref predicate) => {
-                    let predicate = infcx.resolve_type_vars_if_possible(predicate);
-                    let err = infcx.equality_predicate(obligation.cause.span,
-                                                             &predicate).unwrap_err();
+        SelectionError::Unimplemented => {
+            match &obligation.cause.code {
+                &ObligationCauseCode::CompareImplMethodObligation => {
                     infcx.tcx.sess.span_err(
                         obligation.cause.span,
                         format!(
-                            "the requirement `{}` is not satisfied (`{}`)",
-                            predicate.user_string(infcx.tcx),
-                            ty::type_err_to_str(infcx.tcx, &err)).as_slice());
+                            "the requirement `{}` appears on the impl \
+                            method but not on the corresponding trait method",
+                            obligation.predicate.user_string(infcx.tcx)).as_slice());
                 }
+                _ => {
+                    match obligation.predicate {
+                        ty::Predicate::Trait(ref trait_predicate) => {
+                            let trait_predicate =
+                                infcx.resolve_type_vars_if_possible(trait_predicate);
 
-                ty::Predicate::RegionOutlives(ref predicate) => {
-                    let predicate = infcx.resolve_type_vars_if_possible(predicate);
-                    let err = infcx.region_outlives_predicate(obligation.cause.span,
-                                                              &predicate).unwrap_err();
-                    infcx.tcx.sess.span_err(
-                        obligation.cause.span,
-                        format!(
-                            "the requirement `{}` is not satisfied (`{}`)",
-                            predicate.user_string(infcx.tcx),
-                            ty::type_err_to_str(infcx.tcx, &err)).as_slice());
-                }
+                            if !trait_predicate.references_error() {
+                                let trait_ref = trait_predicate.to_poly_trait_ref();
+                                infcx.tcx.sess.span_err(
+                                    obligation.cause.span,
+                                    format!(
+                                        "the trait `{}` is not implemented for the type `{}`",
+                                        trait_ref.user_string(infcx.tcx),
+                                        trait_ref.self_ty().user_string(infcx.tcx)).as_slice());
+                                // Check if it has a custom "#[rustc_on_unimplemented]"
+                                // error message, report with that message if it does
+                                let custom_note = report_on_unimplemented(infcx, &*trait_ref.0,
+                                                                          obligation.cause.span);
+                                if let Some(s) = custom_note {
+                                    infcx.tcx.sess.span_note(obligation.cause.span,
+                                                             s.as_slice());
+                                }
+                            }
+                        }
 
-                ty::Predicate::Projection(..) |
-                ty::Predicate::TypeOutlives(..) => {
-                    let predicate =
-                        infcx.resolve_type_vars_if_possible(&obligation.predicate);
-                    infcx.tcx.sess.span_err(
-                        obligation.cause.span,
-                        format!(
-                            "the requirement `{}` is not satisfied",
-                            predicate.user_string(infcx.tcx)).as_slice());
+                        ty::Predicate::Equate(ref predicate) => {
+                            let predicate = infcx.resolve_type_vars_if_possible(predicate);
+                            let err = infcx.equality_predicate(obligation.cause.span,
+                                                               &predicate).unwrap_err();
+                            infcx.tcx.sess.span_err(
+                                obligation.cause.span,
+                                format!(
+                                    "the requirement `{}` is not satisfied (`{}`)",
+                                    predicate.user_string(infcx.tcx),
+                                    ty::type_err_to_str(infcx.tcx, &err)).as_slice());
+                        }
+
+                        ty::Predicate::RegionOutlives(ref predicate) => {
+                            let predicate = infcx.resolve_type_vars_if_possible(predicate);
+                            let err = infcx.region_outlives_predicate(obligation.cause.span,
+                                                                      &predicate).unwrap_err();
+                            infcx.tcx.sess.span_err(
+                                obligation.cause.span,
+                                format!(
+                                    "the requirement `{}` is not satisfied (`{}`)",
+                                    predicate.user_string(infcx.tcx),
+                                    ty::type_err_to_str(infcx.tcx, &err)).as_slice());
+                        }
+
+                        ty::Predicate::Projection(..) | ty::Predicate::TypeOutlives(..) => {
+                                let predicate =
+                                    infcx.resolve_type_vars_if_possible(&obligation.predicate);
+                                infcx.tcx.sess.span_err(
+                                    obligation.cause.span,
+                                    format!(
+                                        "the requirement `{}` is not satisfied",
+                                        predicate.user_string(infcx.tcx)).as_slice());
+                        }
+                    }
                 }
             }
         }
+
         OutputTypeParameterMismatch(ref expected_trait_ref, ref actual_trait_ref, ref e) => {
             let expected_trait_ref = infcx.resolve_type_vars_if_possible(&*expected_trait_ref);
             let actual_trait_ref = infcx.resolve_type_vars_if_possible(&*actual_trait_ref);
@@ -141,12 +243,12 @@ pub fn report_selection_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
                     obligation.cause.span,
                     format!(
                         "type mismatch: the type `{}` implements the trait `{}`, \
-                         but the trait `{}` is required ({})",
+                        but the trait `{}` is required ({})",
                         expected_trait_ref.self_ty().user_string(infcx.tcx),
                         expected_trait_ref.user_string(infcx.tcx),
                         actual_trait_ref.user_string(infcx.tcx),
                         ty::type_err_to_str(infcx.tcx, e)).as_slice());
-                note_obligation_cause(infcx, obligation);
+                    note_obligation_cause(infcx, obligation);
             }
         }
     }
@@ -242,7 +344,7 @@ fn note_obligation_cause<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
 }
 
 fn note_obligation_cause_code<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
-                                        _predicate: &ty::Predicate<'tcx>,
+                                        predicate: &ty::Predicate<'tcx>,
                                         cause_span: Span,
                                         cause_code: &ObligationCauseCode<'tcx>)
 {
@@ -329,6 +431,12 @@ fn note_obligation_cause_code<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
             let parent_predicate = parent_trait_ref.as_predicate();
             note_obligation_cause_code(infcx, &parent_predicate, cause_span, &*data.parent_code);
         }
+        ObligationCauseCode::CompareImplMethodObligation => {
+            span_note!(tcx.sess, cause_span,
+                      "the requirement `{}` appears on the impl method\
+                      but not on the corresponding trait method",
+                      predicate.user_string(infcx.tcx));
+        }
     }
 }
 
index 3ef6694ce31c76f3793920dae07c55b44b47c02a..425765edf870c5c30cd56a007ca2d2a3d7e639c6 100644 (file)
@@ -121,9 +121,12 @@ pub enum ObligationCauseCode<'tcx> {
     // static items must have `Sync` type
     SharedStatic,
 
+
     BuiltinDerivedObligation(DerivedObligationCause<'tcx>),
 
     ImplDerivedObligation(DerivedObligationCause<'tcx>),
+
+    CompareImplMethodObligation,
 }
 
 #[derive(Clone)]
@@ -218,8 +221,10 @@ pub enum Vtable<'tcx, N> {
     VtableImpl(VtableImplData<'tcx, N>),
 
     /// Successful resolution to an obligation provided by the caller
-    /// for some type parameter.
-    VtableParam,
+    /// for some type parameter. The `Vec<N>` represents the
+    /// obligations incurred from normalizing the where-clause (if
+    /// any).
+    VtableParam(Vec<N>),
 
     /// Virtual calls through an object
     VtableObject(VtableObjectData<'tcx>),
@@ -443,7 +448,7 @@ pub fn iter_nested(&self) -> Iter<N> {
             VtableImpl(ref i) => i.iter_nested(),
             VtableFnPointer(..) => (&[]).iter(),
             VtableUnboxedClosure(..) => (&[]).iter(),
-            VtableParam => (&[]).iter(),
+            VtableParam(ref n) => n.iter(),
             VtableObject(_) => (&[]).iter(),
             VtableBuiltin(ref i) => i.iter_nested(),
         }
@@ -454,7 +459,7 @@ pub fn map_nested<M, F>(&self, op: F) -> Vtable<'tcx, M> where F: FnMut(&N) -> M
             VtableImpl(ref i) => VtableImpl(i.map_nested(op)),
             VtableFnPointer(ref sig) => VtableFnPointer((*sig).clone()),
             VtableUnboxedClosure(d, ref s) => VtableUnboxedClosure(d, s.clone()),
-            VtableParam => VtableParam,
+            VtableParam(ref n) => VtableParam(n.iter().map(op).collect()),
             VtableObject(ref p) => VtableObject(p.clone()),
             VtableBuiltin(ref b) => VtableBuiltin(b.map_nested(op)),
         }
@@ -467,7 +472,7 @@ pub fn map_move_nested<M, F>(self, op: F) -> Vtable<'tcx, M> where
             VtableImpl(i) => VtableImpl(i.map_move_nested(op)),
             VtableFnPointer(sig) => VtableFnPointer(sig),
             VtableUnboxedClosure(d, s) => VtableUnboxedClosure(d, s),
-            VtableParam => VtableParam,
+            VtableParam(n) => VtableParam(n.into_iter().map(op).collect()),
             VtableObject(p) => VtableObject(p),
             VtableBuiltin(no) => VtableBuiltin(no.map_move_nested(op)),
         }
index d6302976b9f111d21864e84eef0cf1c7ccffedb4..a38814580f54cb38922082b4b12412c598e02d17 100644 (file)
@@ -747,7 +747,7 @@ fn assemble_candidates<'o>(&mut self,
         }
 
         self.assemble_candidates_from_projected_tys(obligation, &mut candidates);
-        try!(self.assemble_candidates_from_caller_bounds(obligation, &mut candidates));
+        try!(self.assemble_candidates_from_caller_bounds(stack, &mut candidates));
         debug!("candidate list size: {}", candidates.vec.len());
         Ok(candidates)
     }
@@ -884,13 +884,13 @@ fn match_projection(&mut self,
     /// supplied to find out whether it is listed among them.
     ///
     /// Never affects inference environment.
-    fn assemble_candidates_from_caller_bounds(&mut self,
-                                              obligation: &TraitObligation<'tcx>,
-                                              candidates: &mut SelectionCandidateSet<'tcx>)
-                                              -> Result<(),SelectionError<'tcx>>
+    fn assemble_candidates_from_caller_bounds<'o>(&mut self,
+                                                  stack: &TraitObligationStack<'o, 'tcx>,
+                                                  candidates: &mut SelectionCandidateSet<'tcx>)
+                                                  -> Result<(),SelectionError<'tcx>>
     {
         debug!("assemble_candidates_from_caller_bounds({})",
-               obligation.repr(self.tcx()));
+               stack.obligation.repr(self.tcx()));
 
         let caller_trait_refs: Vec<_> =
             self.param_env().caller_bounds.predicates.iter()
@@ -903,8 +903,7 @@ fn assemble_candidates_from_caller_bounds(&mut self,
 
         let matching_bounds =
             all_bounds.filter(
-                |bound| self.infcx.probe(
-                    |_| self.match_poly_trait_ref(obligation, bound.clone())).is_ok());
+                |bound| self.evaluate_where_clause(stack, bound.clone()).may_apply());
 
         let param_candidates =
             matching_bounds.map(|bound| ParamCandidate(bound));
@@ -914,6 +913,23 @@ fn assemble_candidates_from_caller_bounds(&mut self,
         Ok(())
     }
 
+    fn evaluate_where_clause<'o>(&mut self,
+                                 stack: &TraitObligationStack<'o, 'tcx>,
+                                 where_clause_trait_ref: ty::PolyTraitRef<'tcx>)
+                                 -> EvaluationResult<'tcx>
+    {
+        self.infcx().probe(move |_| {
+            match self.match_where_clause_trait_ref(stack.obligation, where_clause_trait_ref) {
+                Ok(obligations) => {
+                    self.evaluate_predicates_recursively(Some(stack), obligations.iter())
+                }
+                Err(()) => {
+                    EvaluatedToErr(Unimplemented)
+                }
+            }
+        })
+    }
+
     /// Check for the artificial impl that the compiler will create for an obligation like `X :
     /// FnMut<..>` where `X` is an unboxed closure type.
     ///
@@ -1140,6 +1156,10 @@ fn candidate_should_be_dropped_in_favor_of<'o>(&mut self,
                                                    candidate_j: &SelectionCandidate<'tcx>)
                                                    -> bool
     {
+        if candidate_i == candidate_j {
+            return true;
+        }
+
         match (candidate_i, candidate_j) {
             (&ImplCandidate(impl_def_id), &ParamCandidate(ref bound)) => {
                 debug!("Considering whether to drop param {} in favor of impl {}",
@@ -1166,6 +1186,14 @@ fn candidate_should_be_dropped_in_favor_of<'o>(&mut self,
                         .is_ok()
                 })
             }
+            (&BuiltinCandidate(_), &ParamCandidate(_)) => {
+                // If we have a where-clause like `Option<K> : Send`,
+                // then we wind up in a situation where there is a
+                // default rule (`Option<K>:Send if K:Send) and the
+                // where-clause that both seem applicable. Just take
+                // the where-clause in that case.
+                true
+            }
             (&ProjectionCandidate, &ParamCandidate(_)) => {
                 // FIXME(#20297) -- this gives where clauses precedent
                 // over projections. Really these are just two means
@@ -1179,8 +1207,27 @@ fn candidate_should_be_dropped_in_favor_of<'o>(&mut self,
                 // the where clauses are in scope.
                 true
             }
+            (&ParamCandidate(ref bound1), &ParamCandidate(ref bound2)) => {
+                self.infcx.probe(|_| {
+                    let bound1 =
+                        project::normalize_with_depth(self,
+                                                      stack.obligation.cause.clone(),
+                                                      stack.obligation.recursion_depth+1,
+                                                      bound1);
+                    let bound2 =
+                        project::normalize_with_depth(self,
+                                                      stack.obligation.cause.clone(),
+                                                      stack.obligation.recursion_depth+1,
+                                                      bound2);
+                    let origin =
+                        infer::RelateOutputImplTypes(stack.obligation.cause.span);
+                    self.infcx
+                        .sub_poly_trait_refs(false, origin, bound1.value, bound2.value)
+                        .is_ok()
+                })
+            }
             _ => {
-                *candidate_i == *candidate_j
+                false
             }
         }
     }
@@ -1548,8 +1595,8 @@ fn confirm_candidate(&mut self,
             }
 
             ParamCandidate(param) => {
-                self.confirm_param_candidate(obligation, param);
-                Ok(VtableParam)
+                let obligations = self.confirm_param_candidate(obligation, param);
+                Ok(VtableParam(obligations))
             }
 
             ImplCandidate(impl_def_id) => {
@@ -1576,7 +1623,7 @@ fn confirm_candidate(&mut self,
 
             ProjectionCandidate => {
                 self.confirm_projection_candidate(obligation);
-                Ok(VtableParam)
+                Ok(VtableParam(Vec::new()))
             }
         }
     }
@@ -1597,6 +1644,7 @@ fn confirm_projection_candidate(&mut self,
     fn confirm_param_candidate(&mut self,
                                obligation: &TraitObligation<'tcx>,
                                param: ty::PolyTraitRef<'tcx>)
+                               -> Vec<PredicateObligation<'tcx>>
     {
         debug!("confirm_param_candidate({},{})",
                obligation.repr(self.tcx()),
@@ -1606,11 +1654,9 @@ fn confirm_param_candidate(&mut self,
         // where-clause trait-ref could be unified with the obligation
         // trait-ref. Repeat that unification now without any
         // transactional boundary; it should not fail.
-        match self.confirm_poly_trait_refs(obligation.cause.clone(),
-                                           obligation.predicate.to_poly_trait_ref(),
-                                           param.clone()) {
-            Ok(()) => { }
-            Err(_) => {
+        match self.match_where_clause_trait_ref(obligation, param.clone()) {
+            Ok(obligations) => obligations,
+            Err(()) => {
                 self.tcx().sess.bug(
                     format!("Where clause `{}` was applicable to `{}` but now is not",
                             param.repr(self.tcx()),
@@ -2037,19 +2083,43 @@ fn fast_reject_trait_refs(&mut self,
             })
     }
 
+    /// Normalize `where_clause_trait_ref` and try to match it against
+    /// `obligation`.  If successful, return any predicates that
+    /// result from the normalization. Normalization is necessary
+    /// because where-clauses are stored in the parameter environment
+    /// unnormalized.
+    fn match_where_clause_trait_ref(&mut self,
+                                    obligation: &TraitObligation<'tcx>,
+                                    where_clause_trait_ref: ty::PolyTraitRef<'tcx>)
+                                    -> Result<Vec<PredicateObligation<'tcx>>,()>
+    {
+        let where_clause_trait_ref =
+            project::normalize_with_depth(self,
+                                          obligation.cause.clone(),
+                                          obligation.recursion_depth+1,
+                                          &where_clause_trait_ref);
+
+        let () =
+            try!(self.match_poly_trait_ref(obligation, where_clause_trait_ref.value.clone()));
+
+        Ok(where_clause_trait_ref.obligations)
+    }
+
+    /// Returns `Ok` if `poly_trait_ref` being true implies that the
+    /// obligation is satisfied.
     fn match_poly_trait_ref(&mut self,
                             obligation: &TraitObligation<'tcx>,
-                            where_clause_trait_ref: ty::PolyTraitRef<'tcx>)
+                            poly_trait_ref: ty::PolyTraitRef<'tcx>)
                             -> Result<(),()>
     {
-        debug!("match_poly_trait_ref: obligation={} where_clause_trait_ref={}",
+        debug!("match_poly_trait_ref: obligation={} poly_trait_ref={}",
                obligation.repr(self.tcx()),
-               where_clause_trait_ref.repr(self.tcx()));
+               poly_trait_ref.repr(self.tcx()));
 
         let origin = infer::RelateOutputImplTypes(obligation.cause.span);
         match self.infcx.sub_poly_trait_refs(false,
                                              origin,
-                                             where_clause_trait_ref,
+                                             poly_trait_ref,
                                              obligation.predicate.to_poly_trait_ref()) {
             Ok(()) => Ok(()),
             Err(_) => Err(()),
index 272447027afd8f6d56e4269d44962e2560731274..fe8362223e3cd7393b333f4df5cf97af56ec1017 100644 (file)
@@ -380,8 +380,9 @@ fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
                 format!("VtableObject({})",
                         d.repr(tcx)),
 
-            super::VtableParam =>
-                format!("VtableParam"),
+            super::VtableParam(ref n) =>
+                format!("VtableParam({})",
+                        n.repr(tcx)),
 
             super::VtableBuiltin(ref d) =>
                 d.repr(tcx)
index ef86e67de1606af77d7c0e3397fb7309412f1f0f..525fe86cf24e6a710e712b7fd359d49bbcb42169 100644 (file)
@@ -68,7 +68,7 @@
 use util::nodemap::{FnvHashMap};
 
 use arena::TypedArena;
-use std::borrow::BorrowFrom;
+use std::borrow::{BorrowFrom, Cow};
 use std::cell::{Cell, RefCell};
 use std::cmp::{self, Ordering};
 use std::fmt::{self, Show};
@@ -76,6 +76,7 @@
 use std::mem;
 use std::ops;
 use std::rc::Rc;
+use std::vec::CowVec;
 use collections::enum_set::{EnumSet, CLike};
 use std::collections::{HashMap, HashSet};
 use syntax::abi;
@@ -1890,7 +1891,7 @@ pub fn def_id(&self) -> ast::DefId {
 /// normal trait predicate (`T : TraitRef<...>`) and one of these
 /// predicates. Form #2 is a broader form in that it also permits
 /// equality between arbitrary types. Processing an instance of Form
-/// #2 eventually yields one of these `ProjectionPredicate`
+/// \#2 eventually yields one of these `ProjectionPredicate`
 /// instances to normalize the LHS.
 #[derive(Clone, PartialEq, Eq, Hash, Show)]
 pub struct ProjectionPredicate<'tcx> {
@@ -4514,7 +4515,7 @@ pub fn expr_kind(tcx: &ctxt, expr: &ast::Expr) -> ExprKind {
     }
 
     match expr.node {
-        ast::ExprPath(..) => {
+        ast::ExprPath(_) | ast::ExprQPath(_) => {
             match resolve_expr(tcx, expr) {
                 def::DefVariant(tid, vid, _) => {
                     let variant_info = enum_variant_with_id(tcx, tid, vid);
@@ -4702,7 +4703,7 @@ pub fn ty_sort_string<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> String {
         }
         ty_tup(ref tys) if tys.is_empty() => ::util::ppaux::ty_to_string(cx, ty),
 
-        ty_enum(id, _) => format!("enum {}", item_path_str(cx, id)),
+        ty_enum(id, _) => format!("enum `{}`", item_path_str(cx, id)),
         ty_uniq(_) => "box".to_string(),
         ty_vec(_, Some(n)) => format!("array of {} elements", n),
         ty_vec(_, None) => "slice".to_string(),
@@ -4714,7 +4715,7 @@ pub fn ty_sort_string<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> String {
             format!("trait {}", item_path_str(cx, inner.principal_def_id()))
         }
         ty_struct(id, _) => {
-            format!("struct {}", item_path_str(cx, id))
+            format!("struct `{}`", item_path_str(cx, id))
         }
         ty_unboxed_closure(..) => "closure".to_string(),
         ty_tup(_) => "tuple".to_string(),
@@ -5555,40 +5556,20 @@ pub fn predicates<'tcx>(
     vec
 }
 
-/// Iterate over attributes of a definition.
-// (This should really be an iterator, but that would require csearch and
-// decoder to use iterators instead of higher-order functions.)
-pub fn each_attr<F>(tcx: &ctxt, did: DefId, mut f: F) -> bool where
-    F: FnMut(&ast::Attribute) -> bool,
-{
+/// Get the attributes of a definition.
+pub fn get_attrs<'tcx>(tcx: &'tcx ctxt, did: DefId)
+                       -> CowVec<'tcx, ast::Attribute> {
     if is_local(did) {
         let item = tcx.map.expect_item(did.node);
-        item.attrs.iter().all(|attr| f(attr))
+        Cow::Borrowed(&item.attrs[])
     } else {
-        info!("getting foreign attrs");
-        let mut cont = true;
-        csearch::get_item_attrs(&tcx.sess.cstore, did, |attrs| {
-            if cont {
-                cont = attrs.iter().all(|attr| f(attr));
-            }
-        });
-        info!("done");
-        cont
+        Cow::Owned(csearch::get_item_attrs(&tcx.sess.cstore, did))
     }
 }
 
 /// Determine whether an item is annotated with an attribute
 pub fn has_attr(tcx: &ctxt, did: DefId, attr: &str) -> bool {
-    let mut found = false;
-    each_attr(tcx, did, |item| {
-        if item.check_name(attr) {
-            found = true;
-            false
-        } else {
-            true
-        }
-    });
-    found
+    get_attrs(tcx, did).iter().any(|item| item.check_name(attr))
 }
 
 /// Determine whether an item is annotated with `#[repr(packed)]`
@@ -5605,13 +5586,9 @@ pub fn lookup_simd(tcx: &ctxt, did: DefId) -> bool {
 pub fn lookup_repr_hints(tcx: &ctxt, did: DefId) -> Rc<Vec<attr::ReprAttr>> {
     memoized(&tcx.repr_hint_cache, did, |did: DefId| {
         Rc::new(if did.krate == LOCAL_CRATE {
-            let mut acc = Vec::new();
-            ty::each_attr(tcx, did, |meta| {
-                acc.extend(attr::find_repr_attrs(tcx.sess.diagnostic(),
-                                                 meta).into_iter());
-                true
-            });
-            acc
+            get_attrs(tcx, did).iter().flat_map(|meta| {
+                attr::find_repr_attrs(tcx.sess.diagnostic(), meta).into_iter()
+            }).collect()
         } else {
             csearch::get_repr_attrs(&tcx.sess.cstore, did)
         })
@@ -7364,3 +7341,15 @@ fn repr(&self, tcx: &ctxt<'tcx>) -> String {
                 self.mt.repr(tcx))
     }
 }
+
+impl<'a, 'tcx> Repr<'tcx> for ParameterEnvironment<'a, 'tcx> {
+    fn repr(&self, tcx: &ctxt<'tcx>) -> String {
+        format!("ParameterEnvironment(\
+            free_substs={}, \
+            implicit_region_bound={}, \
+            caller_bounds={})",
+            self.free_substs.repr(tcx),
+            self.implicit_region_bound.repr(tcx),
+            self.caller_bounds.repr(tcx))
+        }
+    }
index b81a4ed2f58ff79f76a0f197111056e75346a64d..37886b4a1e1f670681be6705676362901d458074 100644 (file)
@@ -514,7 +514,7 @@ fn fold_with<F:TypeFolder<'tcx>>(&self, folder: &mut F) -> traits::Vtable<'tcx,
             traits::VtableFnPointer(ref d) => {
                 traits::VtableFnPointer(d.fold_with(folder))
             }
-            traits::VtableParam => traits::VtableParam,
+            traits::VtableParam(ref n) => traits::VtableParam(n.fold_with(folder)),
             traits::VtableBuiltin(ref d) => traits::VtableBuiltin(d.fold_with(folder)),
             traits::VtableObject(ref d) => traits::VtableObject(d.fold_with(folder)),
         }
@@ -564,6 +564,18 @@ fn fold_with<F:TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::UnboxedClosureUpv
     }
 }
 
+impl<'a, 'tcx> TypeFoldable<'tcx> for ty::ParameterEnvironment<'a, 'tcx> where 'tcx: 'a {
+    fn fold_with<F:TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::ParameterEnvironment<'a, 'tcx> {
+        ty::ParameterEnvironment {
+            tcx: self.tcx,
+            free_substs: self.free_substs.fold_with(folder),
+            implicit_region_bound: self.implicit_region_bound.fold_with(folder),
+            caller_bounds: self.caller_bounds.fold_with(folder),
+            selection_cache: traits::SelectionCache::new(),
+        }
+    }
+}
+
 ///////////////////////////////////////////////////////////////////////////
 // "super" routines: these are the default implementations for TypeFolder.
 //
index feec97f02da55dd204399f7bdf39066605298934..f6fb1c2d41928ad57cabd02a69f56cf9842474ff 100644 (file)
@@ -14,7 +14,7 @@
 use session::Session;
 
 use syntax::ext::base::{SyntaxExtension, NamedSyntaxExtension, NormalTT};
-use syntax::ext::base::{IdentTT, Decorator, Modifier, MacroRulesTT};
+use syntax::ext::base::{IdentTT, Decorator, Modifier, MultiModifier, MacroRulesTT};
 use syntax::ext::base::{MacroExpanderFn};
 use syntax::codemap::Span;
 use syntax::parse::token;
@@ -82,7 +82,7 @@ pub fn register_syntax_extension(&mut self, name: ast::Name, extension: SyntaxEx
             IdentTT(ext, _) => IdentTT(ext, Some(self.krate_span)),
             Decorator(ext) => Decorator(ext),
             Modifier(ext) => Modifier(ext),
-
+            MultiModifier(ext) => MultiModifier(ext),
             MacroRulesTT => {
                 self.sess.err("plugin tried to register a new MacroRulesTT");
                 return;
index 26d5a9daf89b04bdfa62ec9b3ca52bcb92168623..27acc39c77863304291884edd0c70a4709556795 100644 (file)
@@ -15,6 +15,8 @@
 use session::search_paths::PathKind;
 use util::nodemap::NodeMap;
 
+use regex::Regex;
+
 use syntax::ast::NodeId;
 use syntax::codemap::Span;
 use syntax::diagnostic::{self, Emitter};
@@ -71,7 +73,58 @@ pub fn fatal(&self, msg: &str) -> ! {
         self.diagnostic().handler().fatal(msg)
     }
     pub fn span_err(&self, sp: Span, msg: &str) {
-        self.diagnostic().span_err(sp, msg)
+        // Conditions for enabling multi-line errors:
+        if !msg.contains("mismatched types") &&
+           !msg.contains("type mismatch resolving") &&
+           !msg.contains("if and else have incompatible types") &&
+           !msg.contains("if may be missing an else clause") &&
+           !msg.contains("match arms have incompatible types") &&
+           !msg.contains("structure constructor specifies a structure of type") {
+            return self.diagnostic().span_err(sp, msg);
+        }
+
+        let first  = Regex::new(r"[( ]expected").unwrap();
+        let second = Regex::new(r" found").unwrap();
+        let third  = Regex::new(
+                     r"\((values differ|lifetime|cyclic type of infinite size)").unwrap();
+
+        let mut new_msg = String::new();
+        let mut head = 0u;
+
+        // Insert `\n` before expected and found.
+        for (pos1, pos2) in first.find_iter(msg).zip(
+                            second.find_iter(msg)) {
+            new_msg = new_msg +
+            // A `(` may be preceded by a space and it should be trimmed
+                      msg[head..pos1.0].trim_right() + // prefix
+                      "\n" +                           // insert before first
+                      &msg[pos1.0..pos1.1] +           // insert what first matched
+                      &msg[pos1.1..pos2.0] +           // between matches
+                      "\n   " +                        // insert before second
+            //           123
+            // `expected` is 3 char longer than `found`. To align the types, `found` gets
+            // 3 spaces prepended.
+                      &msg[pos2.0..pos2.1];            // insert what second matched
+
+            head = pos2.1;
+        }
+
+        let mut tail = &msg[head..];
+        // Insert `\n` before any remaining messages which match.
+        for pos in third.find_iter(tail).take(1) {
+            // The end of the message may just be wrapped in `()` without `expected`/`found`.
+            // Push this also to a new line and add the final tail after.
+            new_msg = new_msg +
+            // `(` is usually preceded by a space and should be trimmed.
+                      tail[..pos.0].trim_right() + // prefix
+                      "\n" +                       // insert before paren
+                      &tail[pos.0..];              // append the tail
+
+            tail = "";
+        }
+
+        new_msg.push_str(tail);
+        self.diagnostic().span_err(sp, &new_msg[])
     }
     pub fn span_err_with_code(&self, sp: Span, msg: &str, code: &str) {
         self.diagnostic().span_err_with_code(sp, msg, code)
index 9bff54352179ec0c0d4785539a63b68825bbe986..0cd501ca05fcdf4ec1792e7a93e7f19401b110df 100644 (file)
@@ -10,7 +10,7 @@
 
 use std::slice;
 
-#[derive(Clone)]
+#[derive(Clone, Show)]
 pub struct SearchPaths {
     paths: Vec<(PathKind, Path)>,
 }
@@ -20,7 +20,7 @@ pub struct Iter<'a> {
     iter: slice::Iter<'a, (PathKind, Path)>,
 }
 
-#[derive(Eq, PartialEq, Clone, Copy)]
+#[derive(Eq, PartialEq, Clone, Copy, Show)]
 pub enum PathKind {
     Native,
     Crate,
index 559ec533baa9eca1ed0a67d7bbca462541c5ad9f..1a1ad899d4e82bd281b1f53fe8801ce007ff9399 100644 (file)
@@ -542,7 +542,7 @@ pub fn parameterized<'tcx>(cx: &ctxt<'tcx>,
         0
     };
 
-    for t in tps[0..(tps.len() - num_defaults)].iter() {
+    for t in tps[..(tps.len() - num_defaults)].iter() {
         strs.push(ty_to_string(cx, *t))
     }
 
index ac5662f534c86c4fa229ac14eb590f679b6348af..e376ac50dcdf5ebd1055e6892a1409d1d257bdaf 100644 (file)
@@ -140,7 +140,7 @@ fn input<F>(&mut self, input: &[u8], mut func: F) where
             if input.len() >= buffer_remaining {
                     copy_memory(
                         self.buffer.slice_mut(self.buffer_idx, size),
-                        &input[0..buffer_remaining]);
+                        &input[..buffer_remaining]);
                 self.buffer_idx = 0;
                 func(&self.buffer);
                 i += buffer_remaining;
@@ -188,7 +188,7 @@ fn next<'s>(&'s mut self, len: uint) -> &'s mut [u8] {
     fn full_buffer<'s>(&'s mut self) -> &'s [u8] {
         assert!(self.buffer_idx == 64);
         self.buffer_idx = 0;
-        return &self.buffer[0..64];
+        return &self.buffer[..64];
     }
 
     fn position(&self) -> uint { self.buffer_idx }
index 4e260da2e4dedd3ff176f35473410da6b1894f28..789a87bbcdafcd63a2f1aca5e8d2df7739e00223 100644 (file)
@@ -252,6 +252,7 @@ pub enum SawExprComponent<'a> {
         SawExprIndex,
         SawExprRange,
         SawExprPath,
+        SawExprQPath,
         SawExprAddrOf(ast::Mutability),
         SawExprRet,
         SawExprInlineAsm(&'a ast::InlineAsm),
@@ -285,6 +286,7 @@ fn saw_expr<'a>(node: &'a Expr_) -> SawExprComponent<'a> {
             ExprIndex(..)            => SawExprIndex,
             ExprRange(..)            => SawExprRange,
             ExprPath(..)             => SawExprPath,
+            ExprQPath(..)            => SawExprQPath,
             ExprAddrOf(m, _)         => SawExprAddrOf(m),
             ExprBreak(id)            => SawExprBreak(id.map(content)),
             ExprAgain(id)            => SawExprAgain(id.map(content)),
index f9dcb4fb81230b7dc82711602c757352f99f0ce2..ac133cabc3b8c128b19e4f7b3b743690083376b7 100644 (file)
@@ -14,6 +14,7 @@
 use self::Arch::*;
 
 #[allow(non_camel_case_types)]
+#[derive(Copy)]
 pub enum Arch {
     Armv7,
     Armv7s,
@@ -70,8 +71,16 @@ fn pre_link_args(arch: Arch) -> Vec<String> {
          "-Wl,-syslibroot".to_string(), get_sdk_root(sdk_name)]
 }
 
+fn target_cpu(arch: Arch) -> String {
+    match arch {
+        X86_64 => "x86-64",
+        _ => "generic",
+    }.to_string()
+}
+
 pub fn opts(arch: Arch) -> TargetOptions {
     TargetOptions {
+        cpu: target_cpu(arch),
         dynamic_linking: false,
         executables: true,
         // Although there is an experimental implementation of LLVM which
index 57e2744ae9bf8c467e33c47e5d4dc5c67e9d8915..f8eabb4375fb3b83bfa2015f48f96a9b2419341b 100644 (file)
@@ -72,6 +72,7 @@
 mod i686_unknown_linux_gnu;
 mod mips_unknown_linux_gnu;
 mod mipsel_unknown_linux_gnu;
+mod powerpc_unknown_linux_gnu;
 mod x86_64_apple_darwin;
 mod x86_64_apple_ios;
 mod x86_64_pc_windows_gnu;
@@ -95,7 +96,7 @@ pub struct Target {
     /// OS name to use for conditional compilation.
     pub target_os: String,
     /// Architecture to use for ABI considerations. Valid options: "x86", "x86_64", "arm",
-    /// "aarch64", and "mips". "mips" includes "mipsel".
+    /// "aarch64", "mips", and "powerpc". "mips" includes "mipsel".
     pub arch: String,
     /// Optional settings with defaults.
     pub options: TargetOptions,
@@ -339,6 +340,7 @@ macro_rules! load_specific {
             i686_unknown_linux_gnu,
             mips_unknown_linux_gnu,
             mipsel_unknown_linux_gnu,
+            powerpc_unknown_linux_gnu,
             arm_linux_androideabi,
             arm_unknown_linux_gnueabi,
             arm_unknown_linux_gnueabihf,
diff --git a/src/librustc_back/target/powerpc_unknown_linux_gnu.rs b/src/librustc_back/target/powerpc_unknown_linux_gnu.rs
new file mode 100644 (file)
index 0000000..5e0b7bc
--- /dev/null
@@ -0,0 +1,26 @@
+// 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.
+
+use target::Target;
+
+pub fn target() -> Target {
+    let mut base = super::linux_base::opts();
+    base.pre_link_args.push("-m32".to_string());
+
+    Target {
+        data_layout: "E-S8-p:32:32-f64:32:64-i64:32:64-f80:32:32-n8:16:32".to_string(),
+        llvm_target: "powerpc-unknown-linux-gnu".to_string(),
+        target_endian: "big".to_string(),
+        target_pointer_width: "32".to_string(),
+        arch: "powerpc".to_string(),
+        target_os: "linux".to_string(),
+        options: base,
+    }
+}
index 0ebd3bd321583aa17186ae3f55cf6d84899a4019..f2abfd4564c7ddd615b2fd20ddbcd68828384e50 100644 (file)
@@ -12,6 +12,7 @@
 
 pub fn target() -> Target {
     let mut base = super::apple_base::opts();
+    base.cpu = "x86-64".to_string();
     base.eliminate_frame_pointer = false;
     base.pre_link_args.push("-m64".to_string());
 
index 9e1294a89625fbc5ef112acfc95be0a0ec3baeef..6b3054656fe9f1fbe49f2536f7895350db7e2da3 100644 (file)
@@ -12,6 +12,7 @@
 
 pub fn target() -> Target {
     let mut base = super::windows_base::opts();
+    base.cpu = "x86-64".to_string();
     // On Win64 unwinding is handled by the OS, so we can link libgcc statically.
     base.pre_link_args.push("-static-libgcc".to_string());
     base.pre_link_args.push("-m64".to_string());
index 6635306b0e193b57376664139c316d59c580c30d..676aaecc2fc7db4f16c92cff2c2ef88cc8355379 100644 (file)
@@ -12,6 +12,7 @@
 
 pub fn target() -> Target {
     let mut base = super::dragonfly_base::opts();
+    base.cpu = "x86-64".to_string();
     base.pre_link_args.push("-m64".to_string());
 
     Target {
index 2aba2b8defbdc1385043851fc3c34c4d1b85c6dd..3275cb07b5abc3a7b7021d784e79d109d8c9a6e5 100644 (file)
@@ -12,6 +12,7 @@
 
 pub fn target() -> Target {
     let mut base = super::freebsd_base::opts();
+    base.cpu = "x86-64".to_string();
     base.pre_link_args.push("-m64".to_string());
 
     Target {
index d7a6df3a8b0beddd8be12612ed074e3e385d6328..49c4ad4aea99f60ef8894d188dc265881dd5cef8 100644 (file)
@@ -12,6 +12,7 @@
 
 pub fn target() -> Target {
     let mut base = super::linux_base::opts();
+    base.cpu = "x86-64".to_string();
     base.pre_link_args.push("-m64".to_string());
 
     Target {
index c2af4315b06a2c7bbb80e8c821aec3644bb2edea..f35f8ab1b40f5cb741392bf2cb3b0390b0e1f0aa 100644 (file)
@@ -24,7 +24,6 @@
 use rustc_resolve as resolve;
 use rustc_trans::back::link;
 use rustc_trans::back::write;
-use rustc_trans::save;
 use rustc_trans::trans;
 use rustc_typeck as typeck;
 
@@ -47,23 +46,43 @@ pub fn compile_input(sess: Session,
                      input: &Input,
                      outdir: &Option<Path>,
                      output: &Option<Path>,
-                     addl_plugins: Option<Vec<String>>) {
+                     addl_plugins: Option<Vec<String>>,
+                     control: CompileController) {
+    macro_rules! controller_entry_point{($point: ident, $make_state: expr) => ({
+        {
+            let state = $make_state;
+            (control.$point.callback)(state);
+        }
+        if control.$point.stop {
+            return;
+        }
+    })}
+
     // We need nested scopes here, because the intermediate results can keep
     // large chunks of memory alive and we want to free them as soon as
     // possible to keep the peak memory usage low
     let (outputs, trans, sess) = {
         let (outputs, expanded_crate, id) = {
             let krate = phase_1_parse_input(&sess, cfg, input);
-            if stop_after_phase_1(&sess) { return; }
+
+            controller_entry_point!(after_parse,
+                                    CompileState::state_after_parse(input,
+                                                                    &sess,
+                                                                    outdir,
+                                                                    &krate));
+
             let outputs = build_output_filenames(input,
                                                  outdir,
                                                  output,
                                                  &krate.attrs[],
                                                  &sess);
-            let id = link::find_crate_name(Some(&sess), &krate.attrs[],
+            let id = link::find_crate_name(Some(&sess),
+                                           &krate.attrs[],
                                            input);
             let expanded_crate
-                = match phase_2_configure_and_expand(&sess, krate, &id[],
+                = match phase_2_configure_and_expand(&sess,
+                                                     krate,
+                                                     &id[],
                                                      addl_plugins) {
                     None => return,
                     Some(k) => k
@@ -72,23 +91,37 @@ pub fn compile_input(sess: Session,
             (outputs, expanded_crate, id)
         };
 
+        controller_entry_point!(after_expand,
+                                CompileState::state_after_expand(input,
+                                                                 &sess,
+                                                                 outdir,
+                                                                 &expanded_crate,
+                                                                 &id[]));
+
         let mut forest = ast_map::Forest::new(expanded_crate);
         let ast_map = assign_node_ids_and_map(&sess, &mut forest);
 
         write_out_deps(&sess, input, &outputs, &id[]);
 
-        if stop_after_phase_2(&sess) { return; }
-
         let arenas = ty::CtxtArenas::new();
-        let analysis = phase_3_run_analysis_passes(sess, ast_map, &arenas, id);
-        phase_save_analysis(&analysis.ty_cx.sess, analysis.ty_cx.map.krate(), &analysis, outdir);
+        let analysis = phase_3_run_analysis_passes(sess,
+                                                   ast_map,
+                                                   &arenas,
+                                                   id,
+                                                   control.make_glob_map);
+
+        controller_entry_point!(after_analysis,
+                                CompileState::state_after_analysis(input,
+                                                                   &analysis.ty_cx.sess,
+                                                                   outdir,
+                                                                   analysis.ty_cx.map.krate(),
+                                                                   &analysis,
+                                                                   &analysis.ty_cx));
 
         if log_enabled!(::log::INFO) {
             println!("Pre-trans");
             analysis.ty_cx.print_debug_stats();
         }
-
-        if stop_after_phase_3(&analysis.ty_cx.sess) { return; }
         let (tcx, trans) = phase_4_translate_to_llvm(analysis);
 
         if log_enabled!(::log::INFO) {
@@ -102,7 +135,13 @@ pub fn compile_input(sess: Session,
         (outputs, trans, tcx.sess)
     };
     phase_5_run_llvm_passes(&sess, &trans, &outputs);
-    if stop_after_phase_5(&sess) { return; }
+
+    controller_entry_point!(after_llvm,
+                            CompileState::state_after_llvm(input,
+                                                           &sess,
+                                                           outdir,
+                                                           &trans));
+
     phase_6_link_output(&sess, &trans, &outputs);
 }
 
@@ -120,6 +159,146 @@ pub fn source_name(input: &Input) -> String {
     }
 }
 
+/// CompileController is used to customise compilation, it allows compilation to
+/// be stopped and/or to call arbitrary code at various points in compilation.
+/// It also allows for various flags to be set to influence what information gets
+/// colelcted during compilation.
+///
+/// This is a somewhat higher level controller than a Session - the Session
+/// controls what happens in each phase, whereas the CompileController controls
+/// whether a phase is run at all and whether other code (from outside the
+/// the compiler) is run between phases.
+///
+/// Note that if compilation is set to stop and a callback is provided for a
+/// given entry point, the callback is called before compilation is stopped.
+///
+/// Expect more entry points to be added in the future.
+pub struct CompileController<'a> {
+    pub after_parse: PhaseController<'a>,
+    pub after_expand: PhaseController<'a>,
+    pub after_analysis: PhaseController<'a>,
+    pub after_llvm: PhaseController<'a>,
+
+    pub make_glob_map: resolve::MakeGlobMap,
+}
+
+impl<'a> CompileController<'a> {
+    pub fn basic() -> CompileController<'a> {
+        CompileController {
+            after_parse: PhaseController::basic(),
+            after_expand: PhaseController::basic(),
+            after_analysis: PhaseController::basic(),
+            after_llvm: PhaseController::basic(),
+            make_glob_map: resolve::MakeGlobMap::No,
+        }
+    }
+}
+
+pub struct PhaseController<'a> {
+    pub stop: bool,
+    pub callback: Box<Fn(CompileState) -> () + 'a>,
+}
+
+impl<'a> PhaseController<'a> {
+    pub fn basic() -> PhaseController<'a> {
+        PhaseController {
+            stop: false,
+            callback: box |&: _| {},
+        }
+    }
+}
+
+/// State that is passed to a callback. What state is available depends on when
+/// during compilation the callback is made. See the various constructor methods
+/// (`state_*`) in the impl to see which data is provided for any given entry point.
+pub struct CompileState<'a, 'ast: 'a, 'tcx: 'a> {
+    pub input: &'a Input,
+    pub session: &'a Session,
+    pub cfg: Option<&'a ast::CrateConfig>,
+    pub krate: Option<&'a ast::Crate>,
+    pub crate_name: Option<&'a str>,
+    pub output_filenames: Option<&'a OutputFilenames>,
+    pub out_dir: Option<&'a Path>,
+    pub expanded_crate: Option<&'a ast::Crate>,
+    pub ast_map: Option<&'a ast_map::Map<'ast>>,
+    pub analysis: Option<&'a ty::CrateAnalysis<'tcx>>,
+    pub tcx: Option<&'a ty::ctxt<'tcx>>,
+    pub trans: Option<&'a trans::CrateTranslation>,
+}
+
+impl<'a, 'ast, 'tcx> CompileState<'a, 'ast, 'tcx> {
+    fn empty(input: &'a Input,
+             session: &'a Session,
+             out_dir: &'a Option<Path>)
+             -> CompileState<'a, 'ast, 'tcx> {
+        CompileState {
+            input: input,
+            session: session,
+            out_dir: out_dir.as_ref(),
+            cfg: None,
+            krate: None,
+            crate_name: None,
+            output_filenames: None,
+            expanded_crate: None,
+            ast_map: None,
+            analysis: None,
+            tcx: None,
+            trans: None,
+        }
+    }
+
+    fn state_after_parse(input: &'a Input,
+                         session: &'a Session,
+                         out_dir: &'a Option<Path>,
+                         krate: &'a ast::Crate)
+                         -> CompileState<'a, 'ast, 'tcx> {
+        CompileState {
+            krate: Some(krate),
+            .. CompileState::empty(input, session, out_dir)
+        }
+    }
+
+    fn state_after_expand(input: &'a Input,
+                          session: &'a Session,
+                          out_dir: &'a Option<Path>,
+                          expanded_crate: &'a ast::Crate,
+                          crate_name: &'a str)
+                          -> CompileState<'a, 'ast, 'tcx> {
+        CompileState {
+            crate_name: Some(crate_name),
+            expanded_crate: Some(expanded_crate),
+            .. CompileState::empty(input, session, out_dir)
+        }
+    }
+
+    fn state_after_analysis(input: &'a Input,
+                            session: &'a Session,
+                            out_dir: &'a Option<Path>,
+                            krate: &'a ast::Crate,
+                            analysis: &'a ty::CrateAnalysis<'tcx>,
+                            tcx: &'a ty::ctxt<'tcx>)
+                            -> CompileState<'a, 'ast, 'tcx> {
+        CompileState {
+            analysis: Some(analysis),
+            tcx: Some(tcx),
+            krate: Some(krate),
+            .. CompileState::empty(input, session, out_dir)
+        }
+    }
+
+
+    fn state_after_llvm(input: &'a Input,
+                        session: &'a Session,
+                        out_dir: &'a Option<Path>,
+                        trans: &'a trans::CrateTranslation)
+                        -> CompileState<'a, 'ast, 'tcx> {
+        CompileState {
+            trans: Some(trans),
+            .. CompileState::empty(input, session, out_dir)
+        }
+    }
+}
+
 pub fn phase_1_parse_input(sess: &Session, cfg: ast::CrateConfig, input: &Input)
     -> ast::Crate {
     // These may be left in an incoherent state after a previous compile.
@@ -347,7 +526,9 @@ fn new_id(&self, old_id: ast::NodeId) -> ast::NodeId {
 pub fn phase_3_run_analysis_passes<'tcx>(sess: Session,
                                          ast_map: ast_map::Map<'tcx>,
                                          arenas: &'tcx ty::CtxtArenas<'tcx>,
-                                         name: String) -> ty::CrateAnalysis<'tcx> {
+                                         name: String,
+                                         make_glob_map: resolve::MakeGlobMap)
+                                         -> ty::CrateAnalysis<'tcx> {
     let time_passes = sess.time_passes();
     let krate = ast_map.krate();
 
@@ -357,11 +538,6 @@ pub fn phase_3_run_analysis_passes<'tcx>(sess: Session,
     let lang_items = time(time_passes, "language item collection", (), |_|
                           middle::lang_items::collect_language_items(krate, &sess));
 
-    let make_glob_map = if save_analysis(&sess) {
-        resolve::MakeGlobMap::Yes
-    } else {
-        resolve::MakeGlobMap::No
-    };
     let resolve::CrateMap {
         def_map,
         freevars,
@@ -483,21 +659,6 @@ pub fn phase_3_run_analysis_passes<'tcx>(sess: Session,
     }
 }
 
-fn save_analysis(sess: &Session) -> bool {
-    sess.opts.debugging_opts.save_analysis
-}
-
-pub fn phase_save_analysis(sess: &Session,
-                           krate: &ast::Crate,
-                           analysis: &ty::CrateAnalysis,
-                           odir: &Option<Path>) {
-    if !save_analysis(sess) {
-        return;
-    }
-    time(sess.time_passes(), "save analysis", krate, |krate|
-         save::process_crate(sess, krate, analysis, odir));
-}
-
 /// Run the translation phase to LLVM, after which the AST and analysis can
 /// be discarded.
 pub fn phase_4_translate_to_llvm<'tcx>(analysis: ty::CrateAnalysis<'tcx>)
@@ -559,41 +720,6 @@ pub fn phase_6_link_output(sess: &Session,
     os::setenv("PATH", old_path);
 }
 
-pub fn stop_after_phase_3(sess: &Session) -> bool {
-   if sess.opts.no_trans {
-        debug!("invoked with --no-trans, returning early from compile_input");
-        return true;
-    }
-    return false;
-}
-
-pub fn stop_after_phase_1(sess: &Session) -> bool {
-    if sess.opts.parse_only {
-        debug!("invoked with --parse-only, returning early from compile_input");
-        return true;
-    }
-    if sess.opts.show_span.is_some() {
-        return true;
-    }
-    return sess.opts.debugging_opts.ast_json_noexpand;
-}
-
-pub fn stop_after_phase_2(sess: &Session) -> bool {
-    if sess.opts.no_analysis {
-        debug!("invoked with --no-analysis, returning early from compile_input");
-        return true;
-    }
-    return sess.opts.debugging_opts.ast_json;
-}
-
-pub fn stop_after_phase_5(sess: &Session) -> bool {
-    if !sess.opts.output_types.iter().any(|&i| i == config::OutputTypeExe) {
-        debug!("not building executable, returning early from compile_input");
-        return true;
-    }
-    return false;
-}
-
 fn escape_dep_filename(filename: &str) -> String {
     // Apparently clang and gcc *only* escape spaces:
     // http://llvm.org/klaus/clang/commit/9d50634cfc268ecc9a7250226dd5ca0e945240d4
index 9122a34a79362db703a50e00742593d09d37f6e5..6893c4d72f7ded94ec5461abea8a107babd8a66c 100644 (file)
 
 pub use syntax::diagnostic;
 
+use driver::CompileController;
+
+use rustc_resolve as resolve;
 use rustc_trans::back::link;
+use rustc_trans::save;
 use rustc::session::{config, Session, build_session};
 use rustc::session::config::{Input, PrintRequest, UnstableFeatures};
 use rustc::lint::Lint;
@@ -56,6 +60,7 @@
 use rustc::metadata;
 use rustc::metadata::creader::CrateOrString::Str;
 use rustc::DIAGNOSTICS;
+use rustc::util::common::time;
 
 use std::cmp::Ordering::Equal;
 use std::io;
@@ -181,14 +186,50 @@ fn run_compiler(args: &[String]) {
                 list_metadata(&sess, &(*ifile), &mut stdout).unwrap();
             }
             Input::Str(_) => {
-                early_error("can not list metadata for stdin");
+                early_error("cannot list metadata for stdin");
             }
         }
         return;
     }
 
     let plugins = sess.opts.debugging_opts.extra_plugins.clone();
-    driver::compile_input(sess, cfg, &input, &odir, &ofile, Some(plugins));
+    let control = build_controller(&sess);
+    driver::compile_input(sess, cfg, &input, &odir, &ofile, Some(plugins), control);
+}
+
+fn build_controller<'a>(sess: &Session) -> CompileController<'a> {
+    let mut control = CompileController::basic();
+
+    if sess.opts.parse_only ||
+       sess.opts.show_span.is_some() ||
+       sess.opts.debugging_opts.ast_json_noexpand {
+        control.after_parse.stop = true;
+    }
+
+    if sess.opts.no_analysis || sess.opts.debugging_opts.ast_json {
+        control.after_expand.stop = true;
+    }
+
+    if sess.opts.no_trans {
+        control.after_analysis.stop = true;
+    }
+
+    if !sess.opts.output_types.iter().any(|&i| i == config::OutputTypeExe) {
+        control.after_llvm.stop = true;
+    }
+
+    if sess.opts.debugging_opts.save_analysis {
+        control.after_analysis.callback = box |state| {
+            time(state.session.time_passes(), "save analysis", state.krate.unwrap(), |krate|
+                 save::process_crate(state.session,
+                                     krate,
+                                     state.analysis.unwrap(),
+                                     state.out_dir));
+        };
+        control.make_glob_map = resolve::MakeGlobMap::Yes;
+    }
+
+    control
 }
 
 pub fn get_unstable_features_setting() -> UnstableFeatures {
index 1765c80f9437b45b28807545f10e62f8e5f46a7a..6429c5f59856e2394f23cf6ac85a489defb1d003 100644 (file)
@@ -27,6 +27,7 @@
 use rustc::util::ppaux;
 use rustc_borrowck as borrowck;
 use rustc_borrowck::graphviz as borrowck_dot;
+use rustc_resolve as resolve;
 
 use syntax::ast;
 use syntax::ast_map::{self, blocks, NodePrinter};
@@ -133,7 +134,11 @@ fn call_with_pp_support<'tcx, A, B, F>(&self,
             }
             PpmTyped => {
                 let ast_map = ast_map.expect("--pretty=typed missing ast_map");
-                let analysis = driver::phase_3_run_analysis_passes(sess, ast_map, arenas, id);
+                let analysis = driver::phase_3_run_analysis_passes(sess,
+                                                                   ast_map,
+                                                                   arenas,
+                                                                   id,
+                                                                   resolve::MakeGlobMap::No);
                 let annotation = TypedAnnotation { analysis: analysis };
                 f(&annotation, payload)
             }
@@ -603,7 +608,11 @@ pub fn pretty_print_input(sess: Session,
             match code {
                 Some(code) => {
                     let variants = gather_flowgraph_variants(&sess);
-                    let analysis = driver::phase_3_run_analysis_passes(sess, ast_map, &arenas, id);
+                    let analysis = driver::phase_3_run_analysis_passes(sess,
+                                                                       ast_map,
+                                                                       &arenas,
+                                                                       id,
+                                                                       resolve::MakeGlobMap::No);
                     print_flowgraph(variants, analysis, code, out)
                 }
                 None => {
index a4f9b1f98d4c969cbc1bec5cae04130ad0e5a89c..3edb1ec48a023f00117ff00615ae6efc23a19bea 100644 (file)
@@ -1974,6 +1974,11 @@ pub fn LLVMDIBuilderCreateNameSpace(Builder: DIBuilderRef,
     pub fn LLVMInitializeMipsTargetMC();
     pub fn LLVMInitializeMipsAsmPrinter();
     pub fn LLVMInitializeMipsAsmParser();
+    pub fn LLVMInitializePowerPCTargetInfo();
+    pub fn LLVMInitializePowerPCTarget();
+    pub fn LLVMInitializePowerPCTargetMC();
+    pub fn LLVMInitializePowerPCAsmPrinter();
+    pub fn LLVMInitializePowerPCAsmParser();
 
     pub fn LLVMRustAddPass(PM: PassManagerRef, Pass: *const c_char) -> bool;
     pub fn LLVMRustCreateTargetMachine(Triple: *const c_char,
@@ -2249,6 +2254,12 @@ pub unsafe fn static_link_hack_this_sucks() {
     LLVMInitializeMipsAsmPrinter();
     LLVMInitializeMipsAsmParser();
 
+    LLVMInitializePowerPCTargetInfo();
+    LLVMInitializePowerPCTarget();
+    LLVMInitializePowerPCTargetMC();
+    LLVMInitializePowerPCAsmPrinter();
+    LLVMInitializePowerPCAsmParser();
+
     LLVMRustSetLLVMOptions(0 as c_int,
                                        0 as *const _);
 
index ea6ecfbb92b4f2f3a90b685eaf48a0b56406a23f..7743a437858d2e97d3b4a350b8d81dfc7a750d4a 100644 (file)
@@ -61,7 +61,7 @@
 use syntax::ast::{Arm, BindByRef, BindByValue, BindingMode, Block, Crate, CrateNum};
 use syntax::ast::{DefId, Expr, ExprAgain, ExprBreak, ExprField};
 use syntax::ast::{ExprClosure, ExprForLoop, ExprLoop, ExprWhile, ExprMethodCall};
-use syntax::ast::{ExprPath, ExprStruct, FnDecl};
+use syntax::ast::{ExprPath, ExprQPath, ExprStruct, FnDecl};
 use syntax::ast::{ForeignItemFn, ForeignItemStatic, Generics};
 use syntax::ast::{Ident, ImplItem, Item, ItemConst, ItemEnum, ItemFn};
 use syntax::ast::{ItemForeignMod, ItemImpl, ItemMac, ItemMod, ItemStatic};
@@ -2081,7 +2081,7 @@ fn resolve_module_path(&mut self,
                                             // idx +- 1 to account for the
                                             // colons on either side
                                             &mpath[(idx + 1)..],
-                                            &mpath[0..(idx - 1)]);
+                                            &mpath[..(idx - 1)]);
                         return Failed(Some((span, msg)));
                     },
                     None => {
@@ -3169,7 +3169,7 @@ fn resolve_trait_reference(&mut self,
                     TraitImplementation        => "implement",
                     TraitDerivation            => "derive",
                     TraitObject                => "reference",
-                    TraitQPath                 => "extract an associated type from",
+                    TraitQPath                 => "extract an associated item from",
                 };
 
                 let msg = format!("attempt to {} a nonexistent trait `{}`", usage_str, path_str);
@@ -3565,31 +3565,17 @@ fn resolve_type(&mut self, ty: &Ty) {
                     }
                 }
 
-                match result_def {
-                    None => {
-                        match self.resolve_path(ty.id, path, TypeNS, true) {
-                            Some(def) => {
-                                debug!("(resolving type) resolved `{:?}` to \
-                                        type {:?}",
-                                       token::get_ident(path.segments.last().unwrap() .identifier),
-                                       def);
-                                result_def = Some(def);
-                            }
-                            None => {
-                                result_def = None;
-                            }
-                        }
-                    }
-                    Some(_) => {}   // Continue.
+                if let None = result_def {
+                    result_def = self.resolve_path(ty.id, path, TypeNS, true);
                 }
 
                 match result_def {
                     Some(def) => {
                         // Write the result into the def map.
                         debug!("(resolving type) writing resolution for `{}` \
-                                (id {})",
+                                (id {}) = {:?}",
                                self.path_names_to_string(path),
-                               path_id);
+                               path_id, def);
                         self.record_def(path_id, def);
                     }
                     None => {
@@ -3609,6 +3595,12 @@ fn resolve_type(&mut self, ty: &Ty) {
             TyQPath(ref qpath) => {
                 self.resolve_type(&*qpath.self_type);
                 self.resolve_trait_reference(ty.id, &*qpath.trait_ref, TraitQPath);
+                for ty in qpath.item_path.parameters.types().into_iter() {
+                    self.resolve_type(&**ty);
+                }
+                for binding in qpath.item_path.parameters.bindings().into_iter() {
+                    self.resolve_type(&*binding.ty);
+                }
             }
 
             TyPolyTraitRef(ref bounds) => {
@@ -4400,15 +4392,25 @@ fn resolve_expr(&mut self, expr: &Expr) {
             // The interpretation of paths depends on whether the path has
             // multiple elements in it or not.
 
-            ExprPath(ref path) => {
+            ExprPath(_) | ExprQPath(_) => {
+                let mut path_from_qpath;
+                let path = match expr.node {
+                    ExprPath(ref path) => path,
+                    ExprQPath(ref qpath) => {
+                        self.resolve_type(&*qpath.self_type);
+                        self.resolve_trait_reference(expr.id, &*qpath.trait_ref, TraitQPath);
+                        path_from_qpath = qpath.trait_ref.path.clone();
+                        path_from_qpath.segments.push(qpath.item_path.clone());
+                        &path_from_qpath
+                    }
+                    _ => unreachable!()
+                };
                 // This is a local path in the value namespace. Walk through
                 // scopes looking for it.
-
-                let path_name = self.path_names_to_string(path);
-
                 match self.resolve_path(expr.id, path, ValueNS, true) {
                     // Check if struct variant
                     Some((DefVariant(_, _, true), _)) => {
+                        let path_name = self.path_names_to_string(path);
                         self.resolve_error(expr.span,
                                 format!("`{}` is a struct variant name, but \
                                          this expression \
@@ -4423,7 +4425,7 @@ fn resolve_expr(&mut self, expr: &Expr) {
                     Some(def) => {
                         // Write the result into the def map.
                         debug!("(resolving expr) resolved `{}`",
-                               path_name);
+                               self.path_names_to_string(path));
 
                         self.record_def(expr.id, def);
                     }
@@ -4432,6 +4434,7 @@ fn resolve_expr(&mut self, expr: &Expr) {
                         // (The pattern matching def_tys where the id is in self.structs
                         // matches on regular structs while excluding tuple- and enum-like
                         // structs, which wouldn't result in this error.)
+                        let path_name = self.path_names_to_string(path);
                         match self.with_no_errors(|this|
                             this.resolve_path(expr.id, path, TypeNS, false)) {
                             Some((DefTy(struct_id, _), _))
index b6a6b526faccd5662c67e25225f84863673c5853..d7148bdaa1fe8a56a0629b26443fa78b77bab30c 100644 (file)
@@ -186,7 +186,7 @@ pub fn run(sess: &session::Session, llmod: ModuleRef,
 fn is_versioned_bytecode_format(bc: &[u8]) -> bool {
     let magic_id_byte_count = link::RLIB_BYTECODE_OBJECT_MAGIC.len();
     return bc.len() > magic_id_byte_count &&
-           &bc[0..magic_id_byte_count] == link::RLIB_BYTECODE_OBJECT_MAGIC;
+           &bc[..magic_id_byte_count] == link::RLIB_BYTECODE_OBJECT_MAGIC;
 }
 
 fn extract_bytecode_format_version(bc: &[u8]) -> u32 {
index c818dda7581bd02aa32c737e21c5b7bada86f067..aa51b0c5ee24805ed20c327d30ad40d15a643041 100644 (file)
@@ -1039,6 +1039,12 @@ unsafe fn configure_llvm(sess: &Session) {
         llvm::LLVMInitializeMipsAsmPrinter();
         llvm::LLVMInitializeMipsAsmParser();
 
+        llvm::LLVMInitializePowerPCTargetInfo();
+        llvm::LLVMInitializePowerPCTarget();
+        llvm::LLVMInitializePowerPCTargetMC();
+        llvm::LLVMInitializePowerPCAsmPrinter();
+        llvm::LLVMInitializePowerPCAsmParser();
+
         llvm::LLVMRustSetLLVMOptions(llvm_args.len() as c_int,
                                      llvm_args.as_ptr());
     });
index eb163ed7406f25597654631f13b9bfe80fb5fbea..f2a67029170b756df54a1f049aa44ff60783fe71 100644 (file)
@@ -186,7 +186,7 @@ fn write_sub_path_trait_truncated(&mut self, path: &ast::Path) {
         if len <= 2 {
             return;
         }
-        let sub_paths = &sub_paths[0..(len-2)];
+        let sub_paths = &sub_paths[..(len-2)];
         for &(ref span, ref qualname) in sub_paths.iter() {
             self.fmt.sub_mod_ref_str(path.span,
                                      *span,
@@ -767,7 +767,7 @@ fn process_path(&mut self,
                     span: Span,
                     path: &ast::Path,
                     ref_kind: Option<recorder::Row>) {
-        if generated_code(path.span) {
+        if generated_code(span) {
             return
         }
 
@@ -1307,9 +1307,15 @@ fn visit_expr(&mut self, ex: &ast::Expr) {
                 visit::walk_expr(self, ex);
             },
             ast::ExprPath(ref path) => {
-                self.process_path(ex.id, ex.span, path, None);
+                self.process_path(ex.id, path.span, path, None);
                 visit::walk_path(self, path);
             }
+            ast::ExprQPath(ref qpath) => {
+                let mut path = qpath.trait_ref.path.clone();
+                path.segments.push(qpath.item_path.clone());
+                self.process_path(ex.id, ex.span, &path, None);
+                visit::walk_qpath(self, ex.span, &**qpath);
+            }
             ast::ExprStruct(ref path, ref fields, ref base) =>
                 self.process_struct_lit(ex, path, fields, base),
             ast::ExprMethodCall(_, _, ref args) => self.process_method_call(ex, args),
@@ -1439,7 +1445,7 @@ fn visit_arm(&mut self, arm: &ast::Arm) {
                                           "")
                 }
                 def::DefVariant(..) => {
-                    paths_to_process.push((id, p.span, p.clone(), Some(ref_kind)))
+                    paths_to_process.push((id, p.clone(), Some(ref_kind)))
                 }
                 // FIXME(nrc) what are these doing here?
                 def::DefStatic(_, _) => {}
@@ -1448,8 +1454,8 @@ fn visit_arm(&mut self, arm: &ast::Arm) {
                             *def)
             }
         }
-        for &(id, span, ref path, ref_kind) in paths_to_process.iter() {
-            self.process_path(id, span, path, ref_kind);
+        for &(id, ref path, ref_kind) in paths_to_process.iter() {
+            self.process_path(id, path.span, path, ref_kind);
         }
         self.collecting = false;
         self.collected_paths.clear();
@@ -1505,7 +1511,7 @@ fn visit_local(&mut self, l: &ast::Local) {
 pub fn process_crate(sess: &Session,
                      krate: &ast::Crate,
                      analysis: &ty::CrateAnalysis,
-                     odir: &Option<Path>) {
+                     odir: Option<&Path>) {
     if generated_code(krate.span) {
         return;
     }
@@ -1524,8 +1530,8 @@ pub fn process_crate(sess: &Session,
     // find a path to dump our data to
     let mut root_path = match os::getenv("DXR_RUST_TEMP_FOLDER") {
         Some(val) => Path::new(val),
-        None => match *odir {
-            Some(ref val) => val.join("dxr"),
+        None => match odir {
+            Some(val) => val.join("dxr"),
             None => Path::new("dxr-temp"),
         },
     };
index 23598751c08d73c724f0947d6bd0c312bc361723..11f8fbbaf11bfb50168268a38fc3c3f4c98d7b92 100644 (file)
@@ -166,7 +166,7 @@ pub fn make_values_str(&self,
         let values = values.iter().map(|s| {
             // Never take more than 1020 chars
             if s.len() > 1020 {
-                &s[0..1020]
+                &s[..1020]
             } else {
                 &s[]
             }
index fc19a582db2f5d070381891f816ee0bd699eb874..b01604bd397532af2bf893c8caab5890ac287df1 100644 (file)
@@ -471,7 +471,7 @@ fn enter_default<'a, 'p, 'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
     // Collect all of the matches that can match against anything.
     enter_match(bcx, dm, m, col, val, |pats| {
         if pat_is_binding_or_wild(dm, &*pats[col]) {
-            let mut r = pats[0..col].to_vec();
+            let mut r = pats[..col].to_vec();
             r.push_all(&pats[(col + 1)..]);
             Some(r)
         } else {
@@ -1235,7 +1235,7 @@ pub fn trans_match<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
 /// Checks whether the binding in `discr` is assigned to anywhere in the expression `body`
 fn is_discr_reassigned(bcx: Block, discr: &ast::Expr, body: &ast::Expr) -> bool {
     let (vid, field) = match discr.node {
-        ast::ExprPath(..) => match bcx.def(discr.id) {
+        ast::ExprPath(_) | ast::ExprQPath(_) => match bcx.def(discr.id) {
             def::DefLocal(vid) | def::DefUpvar(vid, _, _) => (vid, None),
             _ => return false
         },
index 9b6fa32405ffb9c2247318779d675967f65a67a2..05abd3ff5577d7b211a0a59a2ded4b493aeccf8f 100644 (file)
@@ -161,10 +161,7 @@ pub fn trans_inline_asm<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, ia: &ast::InlineAsm)
 // Default per-arch clobbers
 // Basically what clang does
 
-#[cfg(any(target_arch = "arm",
-          target_arch = "aarch64",
-          target_arch = "mips",
-          target_arch = "mipsel"))]
+#[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))]
 fn get_clobbers() -> String {
     "".to_string()
 }
index ea98d6bb74e9504b502c5f41e8aff2424aede395..28558c5a204f1cd174e51497688bdd4d428a425d 100644 (file)
@@ -248,9 +248,8 @@ fn get_extern_rust_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, fn_ty: Ty<'tcx>,
 
     let f = decl_rust_fn(ccx, fn_ty, name);
 
-    csearch::get_item_attrs(&ccx.sess().cstore, did, |attrs| {
-        set_llvm_fn_attrs(ccx, &attrs[], f)
-    });
+    let attrs = csearch::get_item_attrs(&ccx.sess().cstore, did);
+    set_llvm_fn_attrs(ccx, &attrs[], f);
 
     ccx.externs().borrow_mut().insert(name.to_string(), f);
     f
@@ -353,12 +352,11 @@ pub fn get_extern_const<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, did: ast::DefId,
         // don't do this then linker errors can be generated where the linker
         // complains that one object files has a thread local version of the
         // symbol and another one doesn't.
-        ty::each_attr(ccx.tcx(), did, |attr| {
+        for attr in ty::get_attrs(ccx.tcx(), did).iter() {
             if attr.check_name("thread_local") {
                 llvm::set_thread_local(c, true);
             }
-            true
-        });
+        }
         ccx.externs().borrow_mut().insert(name.to_string(), c);
         return c;
     }
@@ -702,9 +700,8 @@ fn iter_variant<'blk, 'tcx, F>(cx: Block<'blk, 'tcx>,
         let mut cx = cx;
 
         for (i, &arg) in variant.args.iter().enumerate() {
-            cx = (*f)(cx,
-                   adt::trans_field_ptr(cx, repr, av, variant.disr_val, i),
-                   arg.subst(tcx, substs));
+            let arg = monomorphize::apply_param_substs(tcx, substs, &arg);
+            cx = f(cx, adt::trans_field_ptr(cx, repr, av, variant.disr_val, i), arg);
         }
         return cx;
     }
index b80088e4690c966024257b8584535db71a0ad824..75194e3d21fcb57ac29602db0ed39d9e803159b3 100644 (file)
@@ -552,7 +552,7 @@ pub fn gepi(&self, base: ValueRef, ixs: &[uint]) -> ValueRef {
             for (small_vec_e, &ix) in small_vec.iter_mut().zip(ixs.iter()) {
                 *small_vec_e = C_i32(self.ccx, ix as i32);
             }
-            self.inbounds_gep(base, &small_vec[0..ixs.len()])
+            self.inbounds_gep(base, &small_vec[..ixs.len()])
         } else {
             let v = ixs.iter().map(|i| C_i32(self.ccx, *i as i32)).collect::<Vec<ValueRef>>();
             self.count_insn("gepi");
index f7ffbb95feb3b43699a5002d526f6e1546a45d87..7abcdd07cc5da6a0ea6bb4827ce190ddcbe54969 100644 (file)
@@ -18,6 +18,7 @@
 use trans::cabi_x86_win64;
 use trans::cabi_arm;
 use trans::cabi_aarch64;
+use trans::cabi_powerpc;
 use trans::cabi_mips;
 use trans::type_::Type;
 
@@ -125,6 +126,7 @@ pub fn compute_abi_info(ccx: &CrateContext,
             cabi_arm::compute_abi_info(ccx, atys, rty, ret_def, flavor)
         },
         "mips" => cabi_mips::compute_abi_info(ccx, atys, rty, ret_def),
+        "powerpc" => cabi_powerpc::compute_abi_info(ccx, atys, rty, ret_def),
         a => ccx.sess().fatal(&format!("unrecognized arch \"{}\" in target specification", a)
                               []),
     }
diff --git a/src/librustc_trans/trans/cabi_powerpc.rs b/src/librustc_trans/trans/cabi_powerpc.rs
new file mode 100644 (file)
index 0000000..9fc67e1
--- /dev/null
@@ -0,0 +1,183 @@
+// Copyright 2014-2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use libc::c_uint;
+use llvm;
+use llvm::{Integer, Pointer, Float, Double, Struct, Array};
+use llvm::{StructRetAttribute, ZExtAttribute};
+use trans::cabi::{FnType, ArgType};
+use trans::context::CrateContext;
+use trans::type_::Type;
+
+use std::cmp;
+
+fn align_up_to(off: uint, a: uint) -> uint {
+    return (off + a - 1u) / a * a;
+}
+
+fn align(off: uint, ty: Type) -> uint {
+    let a = ty_align(ty);
+    return align_up_to(off, a);
+}
+
+fn ty_align(ty: Type) -> uint {
+    match ty.kind() {
+        Integer => {
+            unsafe {
+                ((llvm::LLVMGetIntTypeWidth(ty.to_ref()) as uint) + 7) / 8
+            }
+        }
+        Pointer => 4,
+        Float => 4,
+        Double => 8,
+        Struct => {
+          if ty.is_packed() {
+            1
+          } else {
+            let str_tys = ty.field_types();
+            str_tys.iter().fold(1, |a, t| cmp::max(a, ty_align(*t)))
+          }
+        }
+        Array => {
+            let elt = ty.element_type();
+            ty_align(elt)
+        }
+        _ => panic!("ty_size: unhandled type")
+    }
+}
+
+fn ty_size(ty: Type) -> uint {
+    match ty.kind() {
+        Integer => {
+            unsafe {
+                ((llvm::LLVMGetIntTypeWidth(ty.to_ref()) as uint) + 7) / 8
+            }
+        }
+        Pointer => 4,
+        Float => 4,
+        Double => 8,
+        Struct => {
+            if ty.is_packed() {
+                let str_tys = ty.field_types();
+                str_tys.iter().fold(0, |s, t| s + ty_size(*t))
+            } else {
+                let str_tys = ty.field_types();
+                let size = str_tys.iter().fold(0, |s, t| align(s, *t) + ty_size(*t));
+                align(size, ty)
+            }
+        }
+        Array => {
+            let len = ty.array_length();
+            let elt = ty.element_type();
+            let eltsz = ty_size(elt);
+            len * eltsz
+        }
+        _ => panic!("ty_size: unhandled type")
+    }
+}
+
+fn classify_ret_ty(ccx: &CrateContext, ty: Type) -> ArgType {
+    if is_reg_ty(ty) {
+        let attr = if ty == Type::i1(ccx) { Some(ZExtAttribute) } else { None };
+        ArgType::direct(ty, None, None, attr)
+    } else {
+        ArgType::indirect(ty, Some(StructRetAttribute))
+    }
+}
+
+fn classify_arg_ty(ccx: &CrateContext, ty: Type, offset: &mut uint) -> ArgType {
+    let orig_offset = *offset;
+    let size = ty_size(ty) * 8;
+    let mut align = ty_align(ty);
+
+    align = cmp::min(cmp::max(align, 4), 8);
+    *offset = align_up_to(*offset, align);
+    *offset += align_up_to(size, align * 8) / 8;
+
+    if is_reg_ty(ty) {
+        let attr = if ty == Type::i1(ccx) { Some(ZExtAttribute) } else { None };
+        ArgType::direct(ty, None, None, attr)
+    } else {
+        ArgType::direct(
+            ty,
+            Some(struct_ty(ccx, ty)),
+            padding_ty(ccx, align, orig_offset),
+            None
+        )
+    }
+}
+
+fn is_reg_ty(ty: Type) -> bool {
+    return match ty.kind() {
+        Integer
+        | Pointer
+        | Float
+        | Double => true,
+        _ => false
+    };
+}
+
+fn padding_ty(ccx: &CrateContext, align: uint, offset: uint) -> Option<Type> {
+    if ((align - 1 ) & offset) > 0 {
+        Some(Type::i32(ccx))
+    } else {
+        None
+    }
+}
+
+fn coerce_to_int(ccx: &CrateContext, size: uint) -> Vec<Type> {
+    let int_ty = Type::i32(ccx);
+    let mut args = Vec::new();
+
+    let mut n = size / 32;
+    while n > 0 {
+        args.push(int_ty);
+        n -= 1;
+    }
+
+    let r = size % 32;
+    if r > 0 {
+        unsafe {
+            args.push(Type::from_ref(llvm::LLVMIntTypeInContext(ccx.llcx(), r as c_uint)));
+        }
+    }
+
+    args
+}
+
+fn struct_ty(ccx: &CrateContext, ty: Type) -> Type {
+    let size = ty_size(ty) * 8;
+    Type::struct_(ccx, coerce_to_int(ccx, size).as_slice(), false)
+}
+
+pub fn compute_abi_info(ccx: &CrateContext,
+                        atys: &[Type],
+                        rty: Type,
+                        ret_def: bool) -> FnType {
+    let ret_ty = if ret_def {
+        classify_ret_ty(ccx, rty)
+    } else {
+        ArgType::direct(Type::void(ccx), None, None, None)
+    };
+
+    let sret = ret_ty.is_indirect();
+    let mut arg_tys = Vec::new();
+    let mut offset = if sret { 4 } else { 0 };
+
+    for aty in atys.iter() {
+        let ty = classify_arg_ty(ccx, *aty, &mut offset);
+        arg_tys.push(ty);
+    };
+
+    return FnType {
+        arg_tys: arg_tys,
+        ret_ty: ret_ty,
+    };
+}
index 6196f9e5eab65eff401594f9cfad0699ecfd9378..11006f37531d2b5ebcb90ddfa27c0379b5bcf782 100644 (file)
@@ -91,8 +91,11 @@ fn trans<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, expr: &ast::Expr)
     debug!("callee::trans(expr={})", expr.repr(bcx.tcx()));
 
     // pick out special kinds of expressions that can be called:
-    if let ast::ExprPath(_) = expr.node {
-        return trans_def(bcx, bcx.def(expr.id), expr);
+    match expr.node {
+        ast::ExprPath(_) | ast::ExprQPath(_) => {
+            return trans_def(bcx, bcx.def(expr.id), expr);
+        }
+        _ => {}
     }
 
     // any other expressions are closures:
index 00b97286de36780519e0471448cce156cb580991..29cf9f72ef8e88e6d6f06ce974ece47a272b5428 100644 (file)
@@ -600,7 +600,7 @@ fn const_expr_unadjusted(cx: &CrateContext, e: &ast::Expr) -> ValueRef {
                 C_array(llunitty, &vs[])
             }
           }
-          ast::ExprPath(_) => {
+          ast::ExprPath(_) | ast::ExprQPath(_) => {
             let def = cx.tcx().def_map.borrow()[e.id];
             match def {
                 def::DefFn(..) | def::DefStaticMethod(..) | def::DefMethod(..) => {
index 2f58baab7fca944327b5e073538c0e9150431f62..d5416ae0631fcde6dc36d96865031a0d1e4002bf 100644 (file)
@@ -323,26 +323,28 @@ fn get_unique_type_id_as_string(&self, unique_type_id: UniqueTypeId) -> Rc<Strin
     fn get_unique_type_id_of_type<'a>(&mut self, cx: &CrateContext<'a, 'tcx>,
                                       type_: Ty<'tcx>) -> UniqueTypeId {
 
-        // basic type           -> {:name of the type:}
-        // tuple                -> {tuple_(:param-uid:)*}
-        // struct               -> {struct_:svh: / :node-id:_<(:param-uid:),*> }
-        // enum                 -> {enum_:svh: / :node-id:_<(:param-uid:),*> }
-        // enum variant         -> {variant_:variant-name:_:enum-uid:}
-        // reference (&)        -> {& :pointee-uid:}
-        // mut reference (&mut) -> {&mut :pointee-uid:}
-        // ptr (*)              -> {* :pointee-uid:}
-        // mut ptr (*mut)       -> {*mut :pointee-uid:}
-        // unique ptr (~)       -> {~ :pointee-uid:}
-        // @-ptr (@)            -> {@ :pointee-uid:}
-        // sized vec ([T; x])   -> {[:size:] :element-uid:}
-        // unsized vec ([T])    -> {[] :element-uid:}
-        // trait (T)            -> {trait_:svh: / :node-id:_<(:param-uid:),*> }
-        // closure              -> {<unsafe_> <once_> :store-sigil: |(:param-uid:),* <,_...>| -> \
-        //                             :return-type-uid: : (:bounds:)*}
-        // function             -> {<unsafe_> <abi_> fn( (:param-uid:)* <,_...> ) -> \
-        //                             :return-type-uid:}
-        // unique vec box (~[]) -> {HEAP_VEC_BOX<:pointee-uid:>}
-        // gc box               -> {GC_BOX<:pointee-uid:>}
+        // basic type               -> {:name of the type:}
+        // tuple                    -> {tuple_(:param-uid:)*}
+        // struct                   -> {struct_:svh: / :node-id:_<(:param-uid:),*> }
+        // enum                     -> {enum_:svh: / :node-id:_<(:param-uid:),*> }
+        // enum variant             -> {variant_:variant-name:_:enum-uid:}
+        // reference (&)            -> {& :pointee-uid:}
+        // mut reference (&mut)     -> {&mut :pointee-uid:}
+        // ptr (*)                  -> {* :pointee-uid:}
+        // mut ptr (*mut)           -> {*mut :pointee-uid:}
+        // unique ptr (~)           -> {~ :pointee-uid:}
+        // @-ptr (@)                -> {@ :pointee-uid:}
+        // sized vec ([T; x])       -> {[:size:] :element-uid:}
+        // unsized vec ([T])        -> {[] :element-uid:}
+        // trait (T)                -> {trait_:svh: / :node-id:_<(:param-uid:),*> }
+        // closure                  -> {<unsafe_> <once_> :store-sigil:
+        //                                  |(:param-uid:),* <,_...>| -> \
+        //                                  :return-type-uid: : (:bounds:)*}
+        // function                 -> {<unsafe_> <abi_> fn( (:param-uid:)* <,_...> ) -> \
+        //                                  :return-type-uid:}
+        // unique vec box (~[])     -> {HEAP_VEC_BOX<:pointee-uid:>}
+        // gc box                   -> {GC_BOX<:pointee-uid:>}
+        // projection (<T as U>::V) -> {<:ty-uid: as :trait-uid:> :: :name-uid: }
 
         match self.type_to_unique_id.get(&type_).cloned() {
             Some(unique_type_id) => return unique_type_id,
@@ -435,6 +437,25 @@ fn get_unique_type_id_of_type<'a>(&mut self, cx: &CrateContext<'a, 'tcx>,
                                        principal.substs,
                                        &mut unique_type_id);
             },
+            ty::ty_projection(ref projection) => {
+                unique_type_id.push_str("<");
+
+                let self_ty = projection.trait_ref.self_ty();
+                let self_type_id = self.get_unique_type_id_of_type(cx, self_ty);
+                let self_type_id = self.get_unique_type_id_as_string(self_type_id);
+                unique_type_id.push_str(&self_type_id[]);
+
+                unique_type_id.push_str(" as ");
+
+                from_def_id_and_substs(self,
+                                       cx,
+                                       projection.trait_ref.def_id,
+                                       projection.trait_ref.substs,
+                                       &mut unique_type_id);
+
+                unique_type_id.push_str(">::");
+                unique_type_id.push_str(token::get_name(projection.item_name).get());
+            },
             ty::ty_bare_fn(_, &ty::BareFnTy{ unsafety, abi, ref sig } ) => {
                 if unsafety == ast::Unsafety::Unsafe {
                     unique_type_id.push_str("unsafe ");
@@ -478,7 +499,10 @@ fn get_unique_type_id_of_type<'a>(&mut self, cx: &CrateContext<'a, 'tcx>,
                                                         closure_ty,
                                                         &mut unique_type_id);
             },
-            _ => {
+            ty::ty_err |
+            ty::ty_infer(_) |
+            ty::ty_open(_) |
+            ty::ty_param(_) => {
                 cx.sess().bug(&format!("get_unique_type_id_of_type() - unexpected type: {}, {:?}",
                                       &ppaux::ty_to_string(cx.tcx(), type_)[],
                                       type_.sty)[])
@@ -962,7 +986,7 @@ pub fn create_captured_var_metadata<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
 
     let variable_access = IndirectVariable {
         alloca: env_pointer,
-        address_operations: &address_operations[0..address_op_count]
+        address_operations: &address_operations[..address_op_count]
     };
 
     declare_local(bcx,
@@ -3502,7 +3526,8 @@ fn walk_expr(cx: &CrateContext,
             ast::ExprLit(_)   |
             ast::ExprBreak(_) |
             ast::ExprAgain(_) |
-            ast::ExprPath(_)  => {}
+            ast::ExprPath(_)  |
+            ast::ExprQPath(_) => {}
 
             ast::ExprCast(ref sub_exp, _)     |
             ast::ExprAddrOf(_, ref sub_exp)  |
@@ -3855,10 +3880,22 @@ fn push_debuginfo_type_name<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
         ty::ty_unboxed_closure(..) => {
             output.push_str("closure");
         }
+        ty::ty_projection(ref projection) => {
+            output.push_str("<");
+            let self_ty = projection.trait_ref.self_ty();
+            push_debuginfo_type_name(cx, self_ty, true, output);
+
+            output.push_str(" as ");
+
+            push_item_name(cx, projection.trait_ref.def_id, false, output);
+            push_type_params(cx, projection.trait_ref.substs, output);
+
+            output.push_str(">::");
+            output.push_str(token::get_name(projection.item_name).get());
+        }
         ty::ty_err |
         ty::ty_infer(_) |
         ty::ty_open(_) |
-        ty::ty_projection(..) |
         ty::ty_param(_) => {
             cx.sess().bug(&format!("debuginfo: Trying to create type name for \
                 unexpected type: {}", ppaux::ty_to_string(cx.tcx(), t))[]);
index ac50445be2f9b41adea0427d9c49b003b83bad36..0e921d8e5228373e3bd407c91e86bb0c61760567 100644 (file)
@@ -564,7 +564,7 @@ fn trans_datum_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
         ast::ExprParen(ref e) => {
             trans(bcx, &**e)
         }
-        ast::ExprPath(_) => {
+        ast::ExprPath(_) | ast::ExprQPath(_) => {
             trans_def(bcx, expr, bcx.def(expr.id))
         }
         ast::ExprField(ref base, ident) => {
@@ -997,7 +997,7 @@ fn trans_rvalue_dps_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
         ast::ExprParen(ref e) => {
             trans_into(bcx, &**e, dest)
         }
-        ast::ExprPath(_) => {
+        ast::ExprPath(_) | ast::ExprQPath(_) => {
             trans_def_dps_unadjusted(bcx, expr, bcx.def(expr.id), dest)
         }
         ast::ExprIf(ref cond, ref thn, ref els) => {
index 7ac062108f3fb2c2f14d141ab2c07fadbdb19e89..493df366d2ae69c6e82a27e2892566b7f60bb3de 100644 (file)
@@ -736,7 +736,7 @@ pub fn get_vtable<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                     format!("cannot get vtable for an object type: {}",
                             data.repr(bcx.tcx())).as_slice());
             }
-            traits::VtableParam => {
+            traits::VtableParam(..) => {
                 bcx.sess().bug(
                     &format!("resolved vtable for {} to bad vtable {} in trans",
                             trait_ref.repr(bcx.tcx()),
index 42134789546958bbb3d2a47d835bfc0e6126a4bc..91c6c9a13a362107520277bb890299fa24dcdaff 100644 (file)
@@ -45,6 +45,7 @@
 mod cabi_arm;
 mod cabi_aarch64;
 mod cabi_mips;
+mod cabi_powerpc;
 mod foreign;
 mod intrinsic;
 mod debuginfo;
index 93076260349abd5c81aee5d5801823a800ec4a2d..f52e7c0ec94c09122aef2551bffbeff53cdfe72e 100644 (file)
@@ -274,6 +274,7 @@ pub fn monomorphic_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
         ast_map::NodeArg(..) |
         ast_map::NodeBlock(..) |
         ast_map::NodePat(..) |
+        ast_map::NodeViewItem(..) |
         ast_map::NodeLocal(..) => {
             ccx.sess().bug(&format!("can't monomorphize a {:?}",
                                    map_node)[])
index 45e05c12713bfbc78401aed51c413ca6721c5ef9..27d31a3a2f7288674a4e9a2ae1d174981232e580 100644 (file)
@@ -1001,9 +1001,12 @@ fn qpath_to_ty<'tcx>(this: &AstConv<'tcx>,
 
     debug!("qpath_to_ty: trait_ref={}", trait_ref.repr(this.tcx()));
 
+    // `<T as Trait>::U<V>` shouldn't parse right now.
+    assert!(qpath.item_path.parameters.is_empty());
+
     return this.projected_ty(ast_ty.span,
                              trait_ref,
-                             qpath.item_name.name);
+                             qpath.item_path.identifier.name);
 }
 
 // Parses the programmer's textual representation of a type into our
index cacf9bb19d20faeabcedd73894b7b4ebe8bd7256..47346592c86bb859220ba8186d4470cf6002952b 100644 (file)
@@ -467,7 +467,7 @@ pub fn check_pat_struct<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, pat: &ast::Pat,
     };
 
     instantiate_path(pcx.fcx, path, ty::lookup_item_type(tcx, enum_def_id),
-                     def, pat.span, pat.id);
+                     None, def, pat.span, pat.id);
 
     let pat_ty = fcx.node_ty(pat.id);
     demand::eqtype(fcx, pat.span, expected, pat_ty);
@@ -505,7 +505,7 @@ pub fn check_pat_enum<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, pat: &ast::Pat,
     } else {
         ctor_scheme
     };
-    instantiate_path(pcx.fcx, path, path_scheme, def, pat.span, pat.id);
+    instantiate_path(pcx.fcx, path, path_scheme, None, def, pat.span, pat.id);
 
     let pat_ty = fcx.node_ty(pat.id);
     demand::eqtype(fcx, pat.span, expected, pat_ty);
@@ -619,6 +619,8 @@ pub fn check_struct_pat_fields<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
             }
         };
 
+        let field_type = pcx.fcx.normalize_associated_types_in(span, &field_type);
+
         check_pat(pcx, &*field.pat, field_type);
     }
 
index 19a88dfc553b68159675280fc4f9195c8e54f5a7..d851206f384e316ab116e1ad7a208a12220939e9 100644 (file)
@@ -14,6 +14,8 @@
 use super::check_expr;
 use super::check_method_argument_types;
 use super::err_args;
+use super::Expectation;
+use super::expected_types_for_fn_args;
 use super::FnCtxt;
 use super::LvaluePreference;
 use super::method;
@@ -65,7 +67,8 @@ pub fn check_legal_trait_for_method_call(ccx: &CrateCtxt, span: Span, trait_id:
 pub fn check_call<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                             call_expr: &ast::Expr,
                             callee_expr: &ast::Expr,
-                            arg_exprs: &[P<ast::Expr>])
+                            arg_exprs: &[P<ast::Expr>],
+                            expected: Expectation<'tcx>)
 {
     check_expr(fcx, callee_expr);
     let original_callee_ty = fcx.expr_ty(callee_expr);
@@ -84,15 +87,15 @@ pub fn check_call<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
     match result {
         None => {
             // this will report an error since original_callee_ty is not a fn
-            confirm_builtin_call(fcx, call_expr, original_callee_ty, arg_exprs);
+            confirm_builtin_call(fcx, call_expr, original_callee_ty, arg_exprs, expected);
         }
 
         Some(CallStep::Builtin) => {
-            confirm_builtin_call(fcx, call_expr, callee_ty, arg_exprs);
+            confirm_builtin_call(fcx, call_expr, callee_ty, arg_exprs, expected);
         }
 
         Some(CallStep::Overloaded(method_callee)) => {
-            confirm_overloaded_call(fcx, call_expr, arg_exprs, method_callee);
+            confirm_overloaded_call(fcx, call_expr, arg_exprs, method_callee, expected);
         }
     }
 }
@@ -153,7 +156,8 @@ fn try_overloaded_call_step<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
 fn confirm_builtin_call<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
                                  call_expr: &ast::Expr,
                                  callee_ty: Ty<'tcx>,
-                                 arg_exprs: &[P<ast::Expr>])
+                                 arg_exprs: &[P<ast::Expr>],
+                                 expected: Expectation<'tcx>)
 {
     let error_fn_sig;
 
@@ -192,11 +196,16 @@ fn confirm_builtin_call<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
         fcx.normalize_associated_types_in(call_expr.span, &fn_sig);
 
     // Call the generic checker.
-    let arg_exprs: Vec<_> = arg_exprs.iter().collect(); // for some weird reason we take &[&P<...>].
+    let expected_arg_tys = expected_types_for_fn_args(fcx,
+                                                      call_expr.span,
+                                                      expected,
+                                                      fn_sig.output,
+                                                      fn_sig.inputs.as_slice());
     check_argument_types(fcx,
                          call_expr.span,
                          fn_sig.inputs.as_slice(),
-                         arg_exprs.as_slice(),
+                         &expected_arg_tys[],
+                         arg_exprs,
                          AutorefArgs::No,
                          fn_sig.variadic,
                          TupleArgumentsFlag::DontTupleArguments);
@@ -207,16 +216,17 @@ fn confirm_builtin_call<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
 fn confirm_overloaded_call<'a,'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                                     call_expr: &ast::Expr,
                                     arg_exprs: &[P<ast::Expr>],
-                                    method_callee: ty::MethodCallee<'tcx>)
+                                    method_callee: ty::MethodCallee<'tcx>,
+                                    expected: Expectation<'tcx>)
 {
-    let arg_exprs: Vec<_> = arg_exprs.iter().collect(); // for some weird reason we take &[&P<...>].
     let output_type = check_method_argument_types(fcx,
                                                   call_expr.span,
                                                   method_callee.ty,
                                                   call_expr,
-                                                  arg_exprs.as_slice(),
+                                                  arg_exprs,
                                                   AutorefArgs::No,
-                                                  TupleArgumentsFlag::TupleArguments);
+                                                  TupleArgumentsFlag::TupleArguments,
+                                                  expected);
     let method_call = ty::MethodCall::expr(call_expr.id);
     fcx.inh.method_map.borrow_mut().insert(method_call, method_callee);
     write_call(fcx, call_expr, output_type);
index 0079115756993771f4a5cb7b26f1db59b1779f23..bfe43086aab10205a38022dc89129dfce5712fb1 100644 (file)
@@ -33,7 +33,7 @@ pub fn check_expr_closure<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
            expr.repr(fcx.tcx()),
            expected.repr(fcx.tcx()));
 
-    let expected_sig_and_kind = expected.map_to_option(fcx, |ty| {
+    let expected_sig_and_kind = expected.to_option(fcx).and_then(|ty| {
         deduce_unboxed_closure_expectations_from_expected_type(fcx, ty)
     });
 
diff --git a/src/librustc_typeck/check/compare_method.rs b/src/librustc_typeck/check/compare_method.rs
new file mode 100644 (file)
index 0000000..27d4b20
--- /dev/null
@@ -0,0 +1,413 @@
+// 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.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use middle::infer;
+use middle::traits;
+use middle::ty::{self};
+use middle::subst::{self, Subst, Substs, VecPerParamSpace};
+use util::ppaux::{self, Repr};
+
+use syntax::ast;
+use syntax::codemap::{Span};
+use syntax::parse::token;
+
+use super::assoc;
+
+/// Checks that a method from an impl conforms to the signature of
+/// the same method as declared in the trait.
+///
+/// # Parameters
+///
+/// - impl_m: type of the method we are checking
+/// - impl_m_span: span to use for reporting errors
+/// - impl_m_body_id: id of the method body
+/// - trait_m: the method in the trait
+/// - impl_trait_ref: the TraitRef corresponding to the trait implementation
+
+pub fn compare_impl_method<'tcx>(tcx: &ty::ctxt<'tcx>,
+                                 impl_m: &ty::Method<'tcx>,
+                                 impl_m_span: Span,
+                                 impl_m_body_id: ast::NodeId,
+                                 trait_m: &ty::Method<'tcx>,
+                                 impl_trait_ref: &ty::TraitRef<'tcx>) {
+    debug!("compare_impl_method(impl_trait_ref={})",
+           impl_trait_ref.repr(tcx));
+
+    debug!("compare_impl_method: impl_trait_ref (liberated) = {}",
+           impl_trait_ref.repr(tcx));
+
+    let infcx = infer::new_infer_ctxt(tcx);
+    let mut fulfillment_cx = traits::FulfillmentContext::new();
+
+    let trait_to_impl_substs = &impl_trait_ref.substs;
+
+    // Try to give more informative error messages about self typing
+    // mismatches.  Note that any mismatch will also be detected
+    // below, where we construct a canonical function type that
+    // includes the self parameter as a normal parameter.  It's just
+    // that the error messages you get out of this code are a bit more
+    // inscrutable, particularly for cases where one method has no
+    // self.
+    match (&trait_m.explicit_self, &impl_m.explicit_self) {
+        (&ty::StaticExplicitSelfCategory,
+         &ty::StaticExplicitSelfCategory) => {}
+        (&ty::StaticExplicitSelfCategory, _) => {
+            tcx.sess.span_err(
+                impl_m_span,
+                format!("method `{}` has a `{}` declaration in the impl, \
+                        but not in the trait",
+                        token::get_name(trait_m.name),
+                        ppaux::explicit_self_category_to_str(
+                            &impl_m.explicit_self)).as_slice());
+            return;
+        }
+        (_, &ty::StaticExplicitSelfCategory) => {
+            tcx.sess.span_err(
+                impl_m_span,
+                format!("method `{}` has a `{}` declaration in the trait, \
+                        but not in the impl",
+                        token::get_name(trait_m.name),
+                        ppaux::explicit_self_category_to_str(
+                            &trait_m.explicit_self)).as_slice());
+            return;
+        }
+        _ => {
+            // Let the type checker catch other errors below
+        }
+    }
+
+    let num_impl_m_type_params = impl_m.generics.types.len(subst::FnSpace);
+    let num_trait_m_type_params = trait_m.generics.types.len(subst::FnSpace);
+    if num_impl_m_type_params != num_trait_m_type_params {
+        span_err!(tcx.sess, impl_m_span, E0049,
+            "method `{}` has {} type parameter{} \
+             but its trait declaration has {} type parameter{}",
+            token::get_name(trait_m.name),
+            num_impl_m_type_params,
+            if num_impl_m_type_params == 1 {""} else {"s"},
+            num_trait_m_type_params,
+            if num_trait_m_type_params == 1 {""} else {"s"});
+        return;
+    }
+
+    if impl_m.fty.sig.0.inputs.len() != trait_m.fty.sig.0.inputs.len() {
+        span_err!(tcx.sess, impl_m_span, E0050,
+            "method `{}` has {} parameter{} \
+             but the declaration in trait `{}` has {}",
+            token::get_name(trait_m.name),
+            impl_m.fty.sig.0.inputs.len(),
+            if impl_m.fty.sig.0.inputs.len() == 1 {""} else {"s"},
+            ty::item_path_str(tcx, trait_m.def_id),
+            trait_m.fty.sig.0.inputs.len());
+        return;
+    }
+
+    // This code is best explained by example. Consider a trait:
+    //
+    //     trait Trait<'t,T> {
+    //          fn method<'a,M>(t: &'t T, m: &'a M) -> Self;
+    //     }
+    //
+    // And an impl:
+    //
+    //     impl<'i, 'j, U> Trait<'j, &'i U> for Foo {
+    //          fn method<'b,N>(t: &'j &'i U, m: &'b N) -> Foo;
+    //     }
+    //
+    // We wish to decide if those two method types are compatible.
+    //
+    // We start out with trait_to_impl_substs, that maps the trait
+    // type parameters to impl type parameters. This is taken from the
+    // impl trait reference:
+    //
+    //     trait_to_impl_substs = {'t => 'j, T => &'i U, Self => Foo}
+    //
+    // We create a mapping `dummy_substs` that maps from the impl type
+    // parameters to fresh types and regions. For type parameters,
+    // this is the identity transform, but we could as well use any
+    // skolemized types. For regions, we convert from bound to free
+    // regions (Note: but only early-bound regions, i.e., those
+    // declared on the impl or used in type parameter bounds).
+    //
+    //     impl_to_skol_substs = {'i => 'i0, U => U0, N => N0 }
+    //
+    // Now we can apply skol_substs to the type of the impl method
+    // to yield a new function type in terms of our fresh, skolemized
+    // types:
+    //
+    //     <'b> fn(t: &'i0 U0, m: &'b) -> Foo
+    //
+    // We now want to extract and substitute the type of the *trait*
+    // method and compare it. To do so, we must create a compound
+    // substitution by combining trait_to_impl_substs and
+    // impl_to_skol_substs, and also adding a mapping for the method
+    // type parameters. We extend the mapping to also include
+    // the method parameters.
+    //
+    //     trait_to_skol_substs = { T => &'i0 U0, Self => Foo, M => N0 }
+    //
+    // Applying this to the trait method type yields:
+    //
+    //     <'a> fn(t: &'i0 U0, m: &'a) -> Foo
+    //
+    // This type is also the same but the name of the bound region ('a
+    // vs 'b).  However, the normal subtyping rules on fn types handle
+    // this kind of equivalency just fine.
+    //
+    // We now use these subsititions to ensure that all declared bounds are
+    // satisfied by the implementation's method.
+    //
+    // We do this by creating a parameter environment which contains a
+    // substition corresponding to impl_to_skol_substs. We then build
+    // trait_to_skol_substs and use it to convert the predicates contained
+    // in the trait_m.generics to the skolemized form.
+    //
+    // Finally we register each of these predicates as an obligation in
+    // a fresh FulfillmentCtxt, and invoke select_all_or_error.
+
+    // Create a parameter environment that represents the implementation's
+    // method.
+    let impl_param_env =
+        ty::ParameterEnvironment::for_item(tcx, impl_m.def_id.node);
+
+    // Create mapping from impl to skolemized.
+    let impl_to_skol_substs = &impl_param_env.free_substs;
+
+    // Create mapping from trait to skolemized.
+    let trait_to_skol_substs =
+        trait_to_impl_substs
+        .subst(tcx, impl_to_skol_substs)
+        .with_method(impl_to_skol_substs.types.get_slice(subst::FnSpace).to_vec(),
+                     impl_to_skol_substs.regions().get_slice(subst::FnSpace).to_vec());
+    debug!("compare_impl_method: trait_to_skol_substs={}",
+           trait_to_skol_substs.repr(tcx));
+
+    // Check region bounds. FIXME(@jroesch) refactor this away when removing
+    // ParamBounds.
+    if !check_region_bounds_on_impl_method(tcx,
+                                           impl_m_span,
+                                           impl_m,
+                                           &trait_m.generics,
+                                           &impl_m.generics,
+                                           &trait_to_skol_substs,
+                                           impl_to_skol_substs) {
+        return;
+    }
+
+    // Create obligations for each predicate declared by the impl
+    // definition in the context of the trait's parameter
+    // environment. We can't just use `impl_env.caller_bounds`,
+    // however, because we want to replace all late-bound regions with
+    // region variables.
+    let impl_bounds =
+        impl_m.generics.to_bounds(tcx, impl_to_skol_substs);
+
+    let (impl_bounds, _) =
+        infcx.replace_late_bound_regions_with_fresh_var(
+            impl_m_span,
+            infer::HigherRankedType,
+            &ty::Binder(impl_bounds));
+    debug!("compare_impl_method: impl_bounds={}",
+           impl_bounds.repr(tcx));
+
+    // // Normalize the associated types in the impl_bounds.
+    // let traits::Normalized { value: impl_bounds, .. } =
+    //     traits::normalize(&mut selcx, normalize_cause.clone(), &impl_bounds);
+
+    // Normalize the associated types in the trait_bounds.
+    let trait_bounds = trait_m.generics.to_bounds(tcx, &trait_to_skol_substs);
+    // let traits::Normalized { value: trait_bounds, .. } =
+    //     traits::normalize(&mut selcx, normalize_cause, &trait_bounds);
+
+    // Obtain the predicate split predicate sets for each.
+    let trait_pred = trait_bounds.predicates.split();
+    let impl_pred = impl_bounds.predicates.split();
+
+    // This is the only tricky bit of the new way we check implementation methods
+    // We need to build a set of predicates where only the FnSpace bounds
+    // are from the trait and we assume all other bounds from the implementation
+    // to be previously satisfied.
+    //
+    // We then register the obligations from the impl_m and check to see
+    // if all constraints hold.
+    let hybrid_preds = VecPerParamSpace::new(
+        impl_pred.types,
+        impl_pred.selfs,
+        trait_pred.fns
+    );
+
+    // Construct trait parameter environment and then shift it into the skolemized viewpoint.
+    let mut trait_param_env = impl_param_env.clone();
+    // The key step here is to update the caller_bounds's predicates to be
+    // the new hybrid bounds we computed.
+    trait_param_env.caller_bounds.predicates = hybrid_preds;
+
+    debug!("compare_impl_method: trait_bounds={}",
+        trait_param_env.caller_bounds.repr(tcx));
+
+    let mut selcx = traits::SelectionContext::new(&infcx, &trait_param_env);
+
+    let normalize_cause =
+        traits::ObligationCause::misc(impl_m_span, impl_m_body_id);
+
+    for predicate in impl_pred.fns.into_iter() {
+        let traits::Normalized { value: predicate, .. } =
+            traits::normalize(&mut selcx, normalize_cause.clone(), &predicate);
+
+        let cause = traits::ObligationCause {
+            span: impl_m_span,
+            body_id: impl_m_body_id,
+            code: traits::ObligationCauseCode::CompareImplMethodObligation
+        };
+
+        fulfillment_cx.register_predicate_obligation(
+            &infcx,
+            traits::Obligation::new(cause, predicate));
+    }
+
+    // We now need to check that the signature of the impl method is
+    // compatible with that of the trait method. We do this by
+    // checking that `impl_fty <: trait_fty`.
+    //
+    // FIXME. Unfortunately, this doesn't quite work right now because
+    // associated type normalization is not integrated into subtype
+    // checks. For the comparison to be valid, we need to
+    // normalize the associated types in the impl/trait methods
+    // first. However, because function types bind regions, just
+    // calling `normalize_associated_types_in` would have no effect on
+    // any associated types appearing in the fn arguments or return
+    // type.
+
+    // Compute skolemized form of impl and trait method tys.
+    let impl_fty = ty::mk_bare_fn(tcx, None, tcx.mk_bare_fn(impl_m.fty.clone()));
+    let impl_fty = impl_fty.subst(tcx, impl_to_skol_substs);
+    let trait_fty = ty::mk_bare_fn(tcx, None, tcx.mk_bare_fn(trait_m.fty.clone()));
+    let trait_fty = trait_fty.subst(tcx, &trait_to_skol_substs);
+
+    let err = infcx.try(|snapshot| {
+        let origin = infer::MethodCompatCheck(impl_m_span);
+
+        let (impl_sig, _) =
+            infcx.replace_late_bound_regions_with_fresh_var(impl_m_span,
+                                                            infer::HigherRankedType,
+                                                            &impl_m.fty.sig);
+        let impl_sig =
+            impl_sig.subst(tcx, impl_to_skol_substs);
+        let impl_sig =
+            assoc::normalize_associated_types_in(&infcx,
+                                                 &impl_param_env,
+                                                 &mut fulfillment_cx,
+                                                 impl_m_span,
+                                                 impl_m_body_id,
+                                                 &impl_sig);
+        let impl_fty =
+            ty::mk_bare_fn(tcx,
+                           None,
+                           tcx.mk_bare_fn(ty::BareFnTy { unsafety: impl_m.fty.unsafety,
+                                                         abi: impl_m.fty.abi,
+                                                         sig: ty::Binder(impl_sig) }));
+        debug!("compare_impl_method: impl_fty={}",
+               impl_fty.repr(tcx));
+
+        let (trait_sig, skol_map) =
+            infcx.skolemize_late_bound_regions(&trait_m.fty.sig, snapshot);
+        let trait_sig =
+            trait_sig.subst(tcx, &trait_to_skol_substs);
+        let trait_sig =
+            assoc::normalize_associated_types_in(&infcx,
+                                                 &impl_param_env,
+                                                 &mut fulfillment_cx,
+                                                 impl_m_span,
+                                                 impl_m_body_id,
+                                                 &trait_sig);
+        let trait_fty =
+            ty::mk_bare_fn(tcx,
+                           None,
+                           tcx.mk_bare_fn(ty::BareFnTy { unsafety: trait_m.fty.unsafety,
+                                                         abi: trait_m.fty.abi,
+                                                         sig: ty::Binder(trait_sig) }));
+
+        debug!("compare_impl_method: trait_fty={}",
+               trait_fty.repr(tcx));
+
+        try!(infer::mk_subty(&infcx, false, origin, impl_fty, trait_fty));
+
+        infcx.leak_check(&skol_map, snapshot)
+    });
+
+    match err {
+        Ok(()) => { }
+        Err(terr) => {
+            debug!("checking trait method for compatibility: impl ty {}, trait ty {}",
+                   impl_fty.repr(tcx),
+                   trait_fty.repr(tcx));
+            span_err!(tcx.sess, impl_m_span, E0053,
+                      "method `{}` has an incompatible type for trait: {}",
+                      token::get_name(trait_m.name),
+                      ty::type_err_to_str(tcx, &terr));
+            return;
+        }
+    }
+
+    // Check that all obligations are satisfied by the implementation's
+    // version.
+    match fulfillment_cx.select_all_or_error(&infcx, &trait_param_env) {
+        Err(ref errors) => { traits::report_fulfillment_errors(&infcx, errors) }
+        Ok(_) => {}
+    }
+
+    // Finally, resolve all regions. This catches wily misuses of lifetime
+    // parameters.
+    infcx.resolve_regions_and_report_errors(impl_m_body_id);
+
+    fn check_region_bounds_on_impl_method<'tcx>(tcx: &ty::ctxt<'tcx>,
+                                                span: Span,
+                                                impl_m: &ty::Method<'tcx>,
+                                                trait_generics: &ty::Generics<'tcx>,
+                                                impl_generics: &ty::Generics<'tcx>,
+                                                trait_to_skol_substs: &Substs<'tcx>,
+                                                impl_to_skol_substs: &Substs<'tcx>)
+                                                -> bool
+    {
+
+        let trait_params = trait_generics.regions.get_slice(subst::FnSpace);
+        let impl_params = impl_generics.regions.get_slice(subst::FnSpace);
+
+        debug!("check_region_bounds_on_impl_method: \
+               trait_generics={} \
+               impl_generics={} \
+               trait_to_skol_substs={} \
+               impl_to_skol_substs={}",
+               trait_generics.repr(tcx),
+               impl_generics.repr(tcx),
+               trait_to_skol_substs.repr(tcx),
+               impl_to_skol_substs.repr(tcx));
+
+        // Must have same number of early-bound lifetime parameters.
+        // Unfortunately, if the user screws up the bounds, then this
+        // will change classification between early and late.  E.g.,
+        // if in trait we have `<'a,'b:'a>`, and in impl we just have
+        // `<'a,'b>`, then we have 2 early-bound lifetime parameters
+        // in trait but 0 in the impl. But if we report "expected 2
+        // but found 0" it's confusing, because it looks like there
+        // are zero. Since I don't quite know how to phrase things at
+        // the moment, give a kind of vague error message.
+        if trait_params.len() != impl_params.len() {
+            tcx.sess.span_err(
+                span,
+                &format!("lifetime parameters or bounds on method `{}` do \
+                         not match the trait declaration",
+                         token::get_name(impl_m.name))[]);
+            return false;
+        }
+
+        return true;
+    }
+}
index 1d184131dede3c017b35d279018f1a922db35200..e4c333a0e1ea593a96f2591ff651c4d6401b63e0 100644 (file)
 
 pub use self::LvaluePreference::*;
 pub use self::Expectation::*;
+pub use self::compare_method::compare_impl_method;
 use self::IsBinopAssignment::*;
 use self::TupleArgumentsFlag::*;
 
 use astconv::{self, ast_region_to_region, ast_ty_to_ty, AstConv};
 use check::_match::pat_ctxt;
+use fmt_macros::{Parser, Piece, Position};
 use middle::{const_eval, def};
 use middle::infer;
 use middle::lang_items::IteratorItem;
 use middle::lang_items::TypeIdLangItem;
 use lint;
 use util::common::{block_query, indenter, loop_query};
-use util::ppaux::{self, UserString, Repr};
+use util::ppaux::{self, Repr};
 use util::nodemap::{DefIdMap, FnvHashMap, NodeMap};
 
 use std::cell::{Cell, Ref, RefCell};
 use std::mem::replace;
 use std::rc::Rc;
 use std::iter::repeat;
+use std::slice;
 use syntax::{self, abi, attr};
+use syntax::attr::AttrMetaMethods;
 use syntax::ast::{self, ProvidedMethod, RequiredMethod, TypeTraitItem, DefId};
 use syntax::ast_util::{self, local_def, PostExpansionMethod};
 use syntax::codemap::{self, Span};
 pub mod wf;
 mod closure;
 mod callee;
+mod compare_method;
 
-/// Fields that are part of a `FnCtxt` which are inherited by
 /// closures defined within the function.  For example:
 ///
 ///     fn foo() {
@@ -726,7 +730,8 @@ pub fn check_item(ccx: &CrateCtxt, it: &ast::Item) {
         }
 
       }
-      ast::ItemTrait(_, _, _, ref trait_methods) => {
+      ast::ItemTrait(_, ref generics, _, ref trait_methods) => {
+        check_trait_on_unimplemented(ccx, generics, it);
         let trait_def = ty::lookup_trait_def(ccx.tcx, local_def(it.id));
         for trait_method in trait_methods.iter() {
             match *trait_method {
@@ -776,6 +781,51 @@ pub fn check_item(ccx: &CrateCtxt, it: &ast::Item) {
     }
 }
 
+fn check_trait_on_unimplemented<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
+                               generics: &ast::Generics,
+                               item: &ast::Item) {
+    if let Some(ref attr) = item.attrs.iter().find(|&: a| {
+        a.check_name("rustc_on_unimplemented")
+    }) {
+        if let Some(ref istring) = attr.value_str() {
+            let mut parser = Parser::new(istring.get());
+            let types = generics.ty_params.as_slice();
+            for token in parser {
+                match token {
+                    Piece::String(_) => (), // Normal string, no need to check it
+                    Piece::NextArgument(a) => match a.position {
+                        // `{Self}` is allowed
+                        Position::ArgumentNamed(s) if s == "Self" => (),
+                        // So is `{A}` if A is a type parameter
+                        Position::ArgumentNamed(s) => match types.iter().find(|t| {
+                            t.ident.as_str() == s
+                        }) {
+                            Some(_) => (),
+                            None => {
+                                ccx.tcx.sess.span_err(attr.span,
+                                                 format!("there is no type parameter \
+                                                          {} on trait {}",
+                                                           s, item.ident.as_str())
+                                            .as_slice());
+                            }
+                        },
+                        // `{:1}` and `{}` are not to be used
+                        Position::ArgumentIs(_) | Position::ArgumentNext => {
+                            ccx.tcx.sess.span_err(attr.span,
+                                                  "only named substitution \
+                                                   parameters are allowed");
+                        }
+                    }
+                }
+            }
+        } else {
+            ccx.tcx.sess.span_err(attr.span,
+                                  "this attribute must have a value, \
+                                   eg `#[rustc_on_unimplemented = \"foo\"]`")
+        }
+    }
+}
+
 /// Type checks a method body.
 ///
 /// # Parameters
@@ -944,503 +994,6 @@ trait `{}`",
     }
 }
 
-/// Checks that a method from an impl conforms to the signature of
-/// the same method as declared in the trait.
-///
-/// # Parameters
-///
-/// - impl_generics: the generics declared on the impl itself (not the method!)
-/// - impl_m: type of the method we are checking
-/// - impl_m_span: span to use for reporting errors
-/// - impl_m_body_id: id of the method body
-/// - trait_m: the method in the trait
-/// - trait_to_impl_substs: the substitutions used on the type of the trait
-fn compare_impl_method<'tcx>(tcx: &ty::ctxt<'tcx>,
-                             impl_m: &ty::Method<'tcx>,
-                             impl_m_span: Span,
-                             impl_m_body_id: ast::NodeId,
-                             trait_m: &ty::Method<'tcx>,
-                             impl_trait_ref: &ty::TraitRef<'tcx>) {
-    debug!("compare_impl_method(impl_trait_ref={})",
-           impl_trait_ref.repr(tcx));
-
-    debug!("impl_trait_ref (liberated) = {}",
-           impl_trait_ref.repr(tcx));
-
-    let infcx = infer::new_infer_ctxt(tcx);
-    let mut fulfillment_cx = traits::FulfillmentContext::new();
-
-    let trait_to_impl_substs = &impl_trait_ref.substs;
-
-    // Try to give more informative error messages about self typing
-    // mismatches.  Note that any mismatch will also be detected
-    // below, where we construct a canonical function type that
-    // includes the self parameter as a normal parameter.  It's just
-    // that the error messages you get out of this code are a bit more
-    // inscrutable, particularly for cases where one method has no
-    // self.
-    match (&trait_m.explicit_self, &impl_m.explicit_self) {
-        (&ty::StaticExplicitSelfCategory,
-         &ty::StaticExplicitSelfCategory) => {}
-        (&ty::StaticExplicitSelfCategory, _) => {
-            tcx.sess.span_err(
-                impl_m_span,
-                &format!("method `{}` has a `{}` declaration in the impl, \
-                        but not in the trait",
-                        token::get_name(trait_m.name),
-                        ppaux::explicit_self_category_to_str(
-                            &impl_m.explicit_self))[]);
-            return;
-        }
-        (_, &ty::StaticExplicitSelfCategory) => {
-            tcx.sess.span_err(
-                impl_m_span,
-                &format!("method `{}` has a `{}` declaration in the trait, \
-                        but not in the impl",
-                        token::get_name(trait_m.name),
-                        ppaux::explicit_self_category_to_str(
-                            &trait_m.explicit_self))[]);
-            return;
-        }
-        _ => {
-            // Let the type checker catch other errors below
-        }
-    }
-
-    let num_impl_m_type_params = impl_m.generics.types.len(subst::FnSpace);
-    let num_trait_m_type_params = trait_m.generics.types.len(subst::FnSpace);
-    if num_impl_m_type_params != num_trait_m_type_params {
-        span_err!(tcx.sess, impl_m_span, E0049,
-            "method `{}` has {} type parameter{} \
-             but its trait declaration has {} type parameter{}",
-            token::get_name(trait_m.name),
-            num_impl_m_type_params,
-            if num_impl_m_type_params == 1 {""} else {"s"},
-            num_trait_m_type_params,
-            if num_trait_m_type_params == 1 {""} else {"s"});
-        return;
-    }
-
-    if impl_m.fty.sig.0.inputs.len() != trait_m.fty.sig.0.inputs.len() {
-        span_err!(tcx.sess, impl_m_span, E0050,
-            "method `{}` has {} parameter{} \
-             but the declaration in trait `{}` has {}",
-            token::get_name(trait_m.name),
-            impl_m.fty.sig.0.inputs.len(),
-            if impl_m.fty.sig.0.inputs.len() == 1 {""} else {"s"},
-            ty::item_path_str(tcx, trait_m.def_id),
-            trait_m.fty.sig.0.inputs.len());
-        return;
-    }
-
-    // This code is best explained by example. Consider a trait:
-    //
-    //     trait Trait<'t,T> {
-    //          fn method<'a,M>(t: &'t T, m: &'a M) -> Self;
-    //     }
-    //
-    // And an impl:
-    //
-    //     impl<'i, 'j, U> Trait<'j, &'i U> for Foo {
-    //          fn method<'b,N>(t: &'j &'i U, m: &'b N) -> Foo;
-    //     }
-    //
-    // We wish to decide if those two method types are compatible.
-    //
-    // We start out with trait_to_impl_substs, that maps the trait
-    // type parameters to impl type parameters. This is taken from the
-    // impl trait reference:
-    //
-    //     trait_to_impl_substs = {'t => 'j, T => &'i U, Self => Foo}
-    //
-    // We create a mapping `dummy_substs` that maps from the impl type
-    // parameters to fresh types and regions. For type parameters,
-    // this is the identity transform, but we could as well use any
-    // skolemized types. For regions, we convert from bound to free
-    // regions (Note: but only early-bound regions, i.e., those
-    // declared on the impl or used in type parameter bounds).
-    //
-    //     impl_to_skol_substs = {'i => 'i0, U => U0, N => N0 }
-    //
-    // Now we can apply skol_substs to the type of the impl method
-    // to yield a new function type in terms of our fresh, skolemized
-    // types:
-    //
-    //     <'b> fn(t: &'i0 U0, m: &'b) -> Foo
-    //
-    // We now want to extract and substitute the type of the *trait*
-    // method and compare it. To do so, we must create a compound
-    // substitution by combining trait_to_impl_substs and
-    // impl_to_skol_substs, and also adding a mapping for the method
-    // type parameters. We extend the mapping to also include
-    // the method parameters.
-    //
-    //     trait_to_skol_substs = { T => &'i0 U0, Self => Foo, M => N0 }
-    //
-    // Applying this to the trait method type yields:
-    //
-    //     <'a> fn(t: &'i0 U0, m: &'a) -> Foo
-    //
-    // This type is also the same but the name of the bound region ('a
-    // vs 'b).  However, the normal subtyping rules on fn types handle
-    // this kind of equivalency just fine.
-
-    // Create mapping from impl to skolemized.
-    let impl_param_env = ty::construct_parameter_environment(tcx, &impl_m.generics, impl_m_body_id);
-    let impl_to_skol_substs = &impl_param_env.free_substs;
-
-    // Create mapping from trait to skolemized.
-    let trait_to_skol_substs =
-        trait_to_impl_substs
-        .subst(tcx, impl_to_skol_substs)
-        .with_method(impl_to_skol_substs.types.get_slice(subst::FnSpace).to_vec(),
-                     impl_to_skol_substs.regions().get_slice(subst::FnSpace).to_vec());
-
-    // Check region bounds.
-    if !check_region_bounds_on_impl_method(tcx,
-                                           impl_m_span,
-                                           impl_m,
-                                           &trait_m.generics,
-                                           &impl_m.generics,
-                                           &trait_to_skol_substs,
-                                           impl_to_skol_substs) {
-        return;
-    }
-
-    // Check bounds. Note that the bounds from the impl may reference
-    // late-bound regions declared on the impl, so liberate those.
-    // This requires two artificial binding scopes -- one for the impl,
-    // and one for the method.
-    //
-    // An example would be:
-    //
-    //     trait Foo<T> { fn method<U:Bound<T>>() { ... } }
-    //
-    //     impl<'a> Foo<&'a T> for &'a U {
-    //         fn method<U:Bound<&'a T>>() { ... }
-    //     }
-    //
-    // Here, the region parameter `'a` is late-bound, so in the bound
-    // `Bound<&'a T>`, the lifetime `'a` will be late-bound with a
-    // depth of 3 (it is nested within 3 binders: the impl, method,
-    // and trait-ref itself). So when we do the liberation, we have
-    // two introduce two `ty::Binder` scopes, one for the impl and one
-    // the method.
-    //
-    // The only late-bounded regions that can possibly appear here are
-    // from the impl, not the method. This is because region
-    // parameters declared on the method which appear in a type bound
-    // would be early bound. On the trait side, there can be no
-    // late-bound lifetimes because trait definitions do not introduce
-    // a late region binder.
-    let trait_bounds =
-        trait_m.generics.types.get_slice(subst::FnSpace).iter()
-        .map(|trait_param_def| &trait_param_def.bounds);
-    let impl_bounds =
-        impl_m.generics.types.get_slice(subst::FnSpace).iter()
-        .map(|impl_param_def| &impl_param_def.bounds);
-    for (i, (trait_param_bounds, impl_param_bounds)) in
-        trait_bounds.zip(impl_bounds).enumerate()
-    {
-        // Check that the impl does not require any builtin-bounds
-        // that the trait does not guarantee:
-        let extra_bounds =
-            impl_param_bounds.builtin_bounds -
-            trait_param_bounds.builtin_bounds;
-        if !extra_bounds.is_empty() {
-            span_err!(tcx.sess, impl_m_span, E0051,
-                "in method `{}`, type parameter {} requires `{}`, \
-                 which is not required by the corresponding type parameter \
-                 in the trait declaration",
-                token::get_name(trait_m.name),
-                i,
-                extra_bounds.user_string(tcx));
-           return;
-        }
-
-        // Check that the trait bounds of the trait imply the bounds of its
-        // implementation.
-        //
-        // FIXME(pcwalton): We could be laxer here regarding sub- and super-
-        // traits, but I doubt that'll be wanted often, so meh.
-        for impl_trait_bound in impl_param_bounds.trait_bounds.iter() {
-            debug!("compare_impl_method(): impl-trait-bound subst");
-            let impl_trait_bound =
-                impl_trait_bound.subst(tcx, impl_to_skol_substs);
-
-            // There may be late-bound regions from the impl in the
-            // impl's bound, so "liberate" those. Note that the
-            // trait_to_skol_substs is derived from the impl's
-            // trait-ref, and the late-bound regions appearing there
-            // have already been liberated, so the result should match
-            // up.
-
-            let found_match_in_trait =
-                trait_param_bounds.trait_bounds.iter().any(|trait_bound| {
-                    debug!("compare_impl_method(): trait-bound subst");
-                    let trait_bound =
-                        trait_bound.subst(tcx, &trait_to_skol_substs);
-                    infer::mk_sub_poly_trait_refs(&infcx,
-                                                  true,
-                                                  infer::Misc(impl_m_span),
-                                                  trait_bound,
-                                                  impl_trait_bound.clone()).is_ok()
-                });
-
-            if !found_match_in_trait {
-                span_err!(tcx.sess, impl_m_span, E0052,
-                          "in method `{}`, type parameter {} requires bound `{}`, which is not \
-                           required by the corresponding type parameter in the trait declaration",
-                          token::get_name(trait_m.name),
-                          i,
-                          impl_trait_bound.user_string(tcx));
-            }
-        }
-    }
-
-    // We now need to check that the signature of the impl method is
-    // compatible with that of the trait method. We do this by
-    // checking that `impl_fty <: trait_fty`.
-    //
-    // FIXME. Unfortunately, this doesn't quite work right now because
-    // associated type normalization is not integrated into subtype
-    // checks. For the comparison to be valid, we need to
-    // normalize the associated types in the impl/trait methods
-    // first. However, because function types bind regions, just
-    // calling `normalize_associated_types_in` would have no effect on
-    // any associated types appearing in the fn arguments or return
-    // type.
-
-
-    // Compute skolemized form of impl and trait method tys.
-    let impl_fty = ty::mk_bare_fn(tcx, None, tcx.mk_bare_fn(impl_m.fty.clone()));
-    let impl_fty = impl_fty.subst(tcx, impl_to_skol_substs);
-    let trait_fty = ty::mk_bare_fn(tcx, None, tcx.mk_bare_fn(trait_m.fty.clone()));
-    let trait_fty = trait_fty.subst(tcx, &trait_to_skol_substs);
-
-    let err = infcx.try(|snapshot| {
-        let origin = infer::MethodCompatCheck(impl_m_span);
-
-        let (impl_sig, _) =
-            infcx.replace_late_bound_regions_with_fresh_var(impl_m_span,
-                                                            infer::HigherRankedType,
-                                                            &impl_m.fty.sig);
-        let impl_sig =
-            impl_sig.subst(tcx, impl_to_skol_substs);
-        let impl_sig =
-            assoc::normalize_associated_types_in(&infcx,
-                                                 &impl_param_env,
-                                                 &mut fulfillment_cx,
-                                                 impl_m_span,
-                                                 impl_m_body_id,
-                                                 &impl_sig);
-        let impl_fty =
-            ty::mk_bare_fn(tcx,
-                           None,
-                           tcx.mk_bare_fn(ty::BareFnTy { unsafety: impl_m.fty.unsafety,
-                                                         abi: impl_m.fty.abi,
-                                                         sig: ty::Binder(impl_sig) }));
-        debug!("compare_impl_method: impl_fty={}",
-               impl_fty.repr(tcx));
-
-        let (trait_sig, skol_map) =
-            infcx.skolemize_late_bound_regions(&trait_m.fty.sig, snapshot);
-        let trait_sig =
-            trait_sig.subst(tcx, &trait_to_skol_substs);
-        let trait_sig =
-            assoc::normalize_associated_types_in(&infcx,
-                                                 &impl_param_env,
-                                                 &mut fulfillment_cx,
-                                                 impl_m_span,
-                                                 impl_m_body_id,
-                                                 &trait_sig);
-        let trait_fty =
-            ty::mk_bare_fn(tcx,
-                           None,
-                           tcx.mk_bare_fn(ty::BareFnTy { unsafety: trait_m.fty.unsafety,
-                                                         abi: trait_m.fty.abi,
-                                                         sig: ty::Binder(trait_sig) }));
-
-        debug!("compare_impl_method: trait_fty={}",
-               trait_fty.repr(tcx));
-
-        try!(infer::mk_subty(&infcx, false, origin, impl_fty, trait_fty));
-
-        infcx.leak_check(&skol_map, snapshot)
-    });
-
-    match err {
-        Ok(()) => { }
-        Err(terr) => {
-            debug!("checking trait method for compatibility: impl ty {}, trait ty {}",
-                   impl_fty.repr(tcx),
-                   trait_fty.repr(tcx));
-            span_err!(tcx.sess, impl_m_span, E0053,
-                      "method `{}` has an incompatible type for trait: {}",
-                      token::get_name(trait_m.name),
-                      ty::type_err_to_str(tcx, &terr));
-            return;
-        }
-    }
-
-    // Run the fulfillment context to completion to accommodate any
-    // associated type normalizations that may have occurred.
-    match fulfillment_cx.select_all_or_error(&infcx, &impl_param_env) {
-        Ok(()) => { }
-        Err(errors) => {
-            traits::report_fulfillment_errors(&infcx, &errors);
-        }
-    }
-
-    // Finally, resolve all regions. This catches wily misuses of lifetime
-    // parameters.
-    infcx.resolve_regions_and_report_errors(impl_m_body_id);
-
-    /// Check that region bounds on impl method are the same as those on the trait. In principle,
-    /// it could be ok for there to be fewer region bounds on the impl method, but this leads to an
-    /// annoying corner case that is painful to handle (described below), so for now we can just
-    /// forbid it.
-    ///
-    /// Example (see `src/test/compile-fail/regions-bound-missing-bound-in-impl.rs`):
-    ///
-    /// ```
-    /// trait Foo<'a> {
-    ///     fn method1<'b>();
-    ///     fn method2<'b:'a>();
-    /// }
-    ///
-    /// impl<'a> Foo<'a> for ... {
-    ///     fn method1<'b:'a>() { .. case 1, definitely bad .. }
-    ///     fn method2<'b>() { .. case 2, could be ok .. }
-    /// }
-    /// ```
-    ///
-    /// The "definitely bad" case is case #1. Here, the impl adds an extra constraint not present
-    /// in the trait.
-    ///
-    /// The "maybe bad" case is case #2. Here, the impl adds an extra constraint not present in the
-    /// trait. We could in principle allow this, but it interacts in a complex way with early/late
-    /// bound resolution of lifetimes. Basically the presence or absence of a lifetime bound
-    /// affects whether the lifetime is early/late bound, and right now the code breaks if the
-    /// trait has an early bound lifetime parameter and the method does not.
-    fn check_region_bounds_on_impl_method<'tcx>(tcx: &ty::ctxt<'tcx>,
-                                                span: Span,
-                                                impl_m: &ty::Method<'tcx>,
-                                                trait_generics: &ty::Generics<'tcx>,
-                                                impl_generics: &ty::Generics<'tcx>,
-                                                trait_to_skol_substs: &Substs<'tcx>,
-                                                impl_to_skol_substs: &Substs<'tcx>)
-                                                -> bool
-    {
-
-        let trait_params = trait_generics.regions.get_slice(subst::FnSpace);
-        let impl_params = impl_generics.regions.get_slice(subst::FnSpace);
-
-        debug!("check_region_bounds_on_impl_method: \
-               trait_generics={} \
-               impl_generics={} \
-               trait_to_skol_substs={} \
-               impl_to_skol_substs={}",
-               trait_generics.repr(tcx),
-               impl_generics.repr(tcx),
-               trait_to_skol_substs.repr(tcx),
-               impl_to_skol_substs.repr(tcx));
-
-        // Must have same number of early-bound lifetime parameters.
-        // Unfortunately, if the user screws up the bounds, then this
-        // will change classification between early and late.  E.g.,
-        // if in trait we have `<'a,'b:'a>`, and in impl we just have
-        // `<'a,'b>`, then we have 2 early-bound lifetime parameters
-        // in trait but 0 in the impl. But if we report "expected 2
-        // but found 0" it's confusing, because it looks like there
-        // are zero. Since I don't quite know how to phrase things at
-        // the moment, give a kind of vague error message.
-        if trait_params.len() != impl_params.len() {
-            tcx.sess.span_err(
-                span,
-                &format!("lifetime parameters or bounds on method `{}` do \
-                         not match the trait declaration",
-                        token::get_name(impl_m.name))[]);
-            return false;
-        }
-
-        // Each parameter `'a:'b+'c+'d` in trait should have the same
-        // set of bounds in the impl, after subst.
-        for (trait_param, impl_param) in
-            trait_params.iter().zip(
-                impl_params.iter())
-        {
-            let trait_bounds =
-                trait_param.bounds.subst(tcx, trait_to_skol_substs);
-            let impl_bounds =
-                impl_param.bounds.subst(tcx, impl_to_skol_substs);
-
-            debug!("check_region_bounds_on_impl_method: \
-                   trait_param={} \
-                   impl_param={} \
-                   trait_bounds={} \
-                   impl_bounds={}",
-                   trait_param.repr(tcx),
-                   impl_param.repr(tcx),
-                   trait_bounds.repr(tcx),
-                   impl_bounds.repr(tcx));
-
-            // Collect the set of bounds present in trait but not in
-            // impl.
-            let missing: Vec<ty::Region> =
-                trait_bounds.iter()
-                .filter(|&b| !impl_bounds.contains(b))
-                .map(|&b| b)
-                .collect();
-
-            // Collect set present in impl but not in trait.
-            let extra: Vec<ty::Region> =
-                impl_bounds.iter()
-                .filter(|&b| !trait_bounds.contains(b))
-                .map(|&b| b)
-                .collect();
-
-            debug!("missing={} extra={}",
-                   missing.repr(tcx), extra.repr(tcx));
-
-            let err = if missing.len() != 0 || extra.len() != 0 {
-                tcx.sess.span_err(
-                    span,
-                    &format!(
-                        "the lifetime parameter `{}` declared in the impl \
-                         has a distinct set of bounds \
-                         from its counterpart `{}` \
-                         declared in the trait",
-                        impl_param.name.user_string(tcx),
-                        trait_param.name.user_string(tcx))[]);
-                true
-            } else {
-                false
-            };
-
-            if missing.len() != 0 {
-                tcx.sess.span_note(
-                    span,
-                    &format!("the impl is missing the following bounds: `{}`",
-                            missing.user_string(tcx))[]);
-            }
-
-            if extra.len() != 0 {
-                tcx.sess.span_note(
-                    span,
-                    &format!("the impl has the following extra bounds: `{}`",
-                            extra.user_string(tcx))[]);
-            }
-
-            if err {
-                return false;
-            }
-        }
-
-        return true;
-    }
-}
-
 fn check_cast(fcx: &FnCtxt,
               cast_expr: &ast::Expr,
               e: &ast::Expr,
@@ -2097,6 +1650,7 @@ pub fn adjust_expr_ty(&self,
     pub fn node_ty(&self, id: ast::NodeId) -> Ty<'tcx> {
         match self.inh.node_types.borrow().get(&id) {
             Some(&t) => t,
+            None if self.err_count_since_creation() != 0 => self.tcx().types.err,
             None => {
                 self.tcx().sess.bug(
                     &format!("no type for node {}: {} in fcx {}",
@@ -2239,6 +1793,34 @@ pub fn add_obligations_for_parameters(&self,
 
         obligations.map_move(|o| self.register_predicate(o));
     }
+
+    // Only for fields! Returns <none> for methods>
+    // Indifferent to privacy flags
+    pub fn lookup_field_ty(&self,
+                           span: Span,
+                           class_id: ast::DefId,
+                           items: &[ty::field_ty],
+                           fieldname: ast::Name,
+                           substs: &subst::Substs<'tcx>)
+                           -> Option<Ty<'tcx>>
+    {
+        let o_field = items.iter().find(|f| f.name == fieldname);
+        o_field.map(|f| ty::lookup_field_type(self.tcx(), class_id, f.id, substs))
+               .map(|t| self.normalize_associated_types_in(span, &t))
+    }
+
+    pub fn lookup_tup_field_ty(&self,
+                               span: Span,
+                               class_id: ast::DefId,
+                               items: &[ty::field_ty],
+                               idx: uint,
+                               substs: &subst::Substs<'tcx>)
+                               -> Option<Ty<'tcx>>
+    {
+        let o_field = if idx < items.len() { Some(&items[idx]) } else { None };
+        o_field.map(|f| ty::lookup_field_type(self.tcx(), class_id, f.id, substs))
+               .map(|t| self.normalize_associated_types_in(span, &t))
+    }
 }
 
 impl<'a, 'tcx> RegionScope for FnCtxt<'a, 'tcx> {
@@ -2558,7 +2140,8 @@ fn lookup_method_for_for_loop<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                                                   iterator_expr,
                                                   &[],
                                                   AutorefArgs::No,
-                                                  DontTupleArguments);
+                                                  DontTupleArguments,
+                                                  NoExpectation);
 
     match method {
         Some(method) => {
@@ -2598,9 +2181,10 @@ fn check_method_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                                          sp: Span,
                                          method_fn_ty: Ty<'tcx>,
                                          callee_expr: &ast::Expr,
-                                         args_no_rcvr: &[&P<ast::Expr>],
+                                         args_no_rcvr: &[P<ast::Expr>],
                                          autoref_args: AutorefArgs,
-                                         tuple_arguments: TupleArgumentsFlag)
+                                         tuple_arguments: TupleArgumentsFlag,
+                                         expected: Expectation<'tcx>)
                                          -> ty::FnOutput<'tcx> {
     if ty::type_is_error(method_fn_ty) {
         let err_inputs = err_args(fcx.tcx(), args_no_rcvr.len());
@@ -2613,6 +2197,7 @@ fn check_method_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
         check_argument_types(fcx,
                              sp,
                              &err_inputs[],
+                             &[],
                              args_no_rcvr,
                              autoref_args,
                              false,
@@ -2622,9 +2207,15 @@ fn check_method_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
         match method_fn_ty.sty {
             ty::ty_bare_fn(_, ref fty) => {
                 // HACK(eddyb) ignore self in the definition (see above).
+                let expected_arg_tys = expected_types_for_fn_args(fcx,
+                                                                  sp,
+                                                                  expected,
+                                                                  fty.sig.0.output,
+                                                                  &fty.sig.0.inputs[1..]);
                 check_argument_types(fcx,
                                      sp,
-                                     fty.sig.0.inputs.slice_from(1),
+                                     &fty.sig.0.inputs[1..],
+                                     &expected_arg_tys[],
                                      args_no_rcvr,
                                      autoref_args,
                                      fty.sig.0.variadic,
@@ -2644,7 +2235,8 @@ fn check_method_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
 fn check_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                                   sp: Span,
                                   fn_inputs: &[Ty<'tcx>],
-                                  args: &[&P<ast::Expr>],
+                                  expected_arg_tys: &[Ty<'tcx>],
+                                  args: &[P<ast::Expr>],
                                   autoref_args: AutorefArgs,
                                   variadic: bool,
                                   tuple_arguments: TupleArgumentsFlag) {
@@ -2658,6 +2250,7 @@ fn check_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
         1
     };
 
+    let mut expected_arg_tys = expected_arg_tys;
     let expected_arg_count = fn_inputs.len();
     let formal_tys = if tuple_arguments == TupleArguments {
         let tuple_type = structurally_resolved_type(fcx, sp, fn_inputs[0]);
@@ -2670,8 +2263,16 @@ fn check_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                         if arg_types.len() == 1 {""} else {"s"},
                         args.len(),
                         if args.len() == 1 {" was"} else {"s were"});
+                    expected_arg_tys = &[][];
                     err_args(fcx.tcx(), args.len())
                 } else {
+                    expected_arg_tys = match expected_arg_tys.get(0) {
+                        Some(&ty) => match ty.sty {
+                            ty::ty_tup(ref tys) => &**tys,
+                            _ => &[]
+                        },
+                        None => &[]
+                    };
                     (*arg_types).clone()
                 }
             }
@@ -2679,14 +2280,15 @@ fn check_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                 span_err!(tcx.sess, sp, E0059,
                     "cannot use call notation; the first type parameter \
                      for the function trait is neither a tuple nor unit");
+                expected_arg_tys = &[][];
                 err_args(fcx.tcx(), args.len())
             }
         }
     } else if expected_arg_count == supplied_arg_count {
-        fn_inputs.iter().map(|a| *a).collect()
+        fn_inputs.to_vec()
     } else if variadic {
         if supplied_arg_count >= expected_arg_count {
-            fn_inputs.iter().map(|a| *a).collect()
+            fn_inputs.to_vec()
         } else {
             span_err!(tcx.sess, sp, E0060,
                 "this function takes at least {} parameter{} \
@@ -2695,6 +2297,7 @@ fn check_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                 if expected_arg_count == 1 {""} else {"s"},
                 supplied_arg_count,
                 if supplied_arg_count == 1 {" was"} else {"s were"});
+            expected_arg_tys = &[][];
             err_args(fcx.tcx(), supplied_arg_count)
         }
     } else {
@@ -2704,6 +2307,7 @@ fn check_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
             if expected_arg_count == 1 {""} else {"s"},
             supplied_arg_count,
             if supplied_arg_count == 1 {" was"} else {"s were"});
+        expected_arg_tys = &[][];
         err_args(fcx.tcx(), supplied_arg_count)
     };
 
@@ -2767,7 +2371,25 @@ fn check_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                     AutorefArgs::No => {}
                 }
 
-                check_expr_coercable_to_type(fcx, &***arg, formal_ty);
+                // The special-cased logic below has three functions:
+                // 1. Provide as good of an expected type as possible.
+                let expected = expected_arg_tys.get(i).map(|&ty| {
+                    Expectation::rvalue_hint(ty)
+                });
+
+                check_expr_with_unifier(fcx, &**arg,
+                                        expected.unwrap_or(ExpectHasType(formal_ty)),
+                                        NoPreference, || {
+                    // 2. Coerce to the most detailed type that could be coerced
+                    //    to, which is `expected_ty` if `rvalue_hint` returns an
+                    //    `ExprHasType(expected_ty)`, or the `formal_ty` otherwise.
+                    let coerce_ty = expected.and_then(|e| e.only_has_type(fcx));
+                    demand::coerce(fcx, arg.span, coerce_ty.unwrap_or(formal_ty), &**arg);
+
+                    // 3. Relate the expected type and the formal one,
+                    //    if the expected type was used for the coercion.
+                    coerce_ty.map(|ty| demand::suptype(fcx, arg.span, formal_ty, ty));
+                });
             }
         }
     }
@@ -2776,12 +2398,12 @@ fn check_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
     // arguments which we skipped above.
     if variadic {
         for arg in args.iter().skip(expected_arg_count) {
-            check_expr(fcx, &***arg);
+            check_expr(fcx, &**arg);
 
             // There are a few types which get autopromoted when passed via varargs
             // in C but we just error out instead and require explicit casts.
             let arg_ty = structurally_resolved_type(fcx, arg.span,
-                                                    fcx.expr_ty(&***arg));
+                                                    fcx.expr_ty(&**arg));
             match arg_ty.sty {
                 ty::ty_float(ast::TyF32) => {
                     fcx.type_error_message(arg.span,
@@ -2844,7 +2466,7 @@ fn check_lit<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
         ast::LitInt(_, ast::SignedIntLit(t, _)) => ty::mk_mach_int(tcx, t),
         ast::LitInt(_, ast::UnsignedIntLit(t)) => ty::mk_mach_uint(tcx, t),
         ast::LitInt(_, ast::UnsuffixedIntLit(_)) => {
-            let opt_ty = expected.map_to_option(fcx, |ty| {
+            let opt_ty = expected.to_option(fcx).and_then(|ty| {
                 match ty.sty {
                     ty::ty_int(_) | ty::ty_uint(_) => Some(ty),
                     ty::ty_char => Some(tcx.types.u8),
@@ -2858,7 +2480,7 @@ fn check_lit<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
         }
         ast::LitFloat(_, t) => ty::mk_mach_float(tcx, t),
         ast::LitFloatUnsuffixed(_) => {
-            let opt_ty = expected.map_to_option(fcx, |ty| {
+            let opt_ty = expected.to_option(fcx).and_then(|ty| {
                 match ty.sty {
                     ty::ty_float(_) => Some(ty),
                     _ => None
@@ -2953,30 +2575,6 @@ pub fn impl_self_ty<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
     TypeAndSubsts { substs: substs, ty: substd_ty }
 }
 
-// Only for fields! Returns <none> for methods>
-// Indifferent to privacy flags
-pub fn lookup_field_ty<'tcx>(tcx: &ty::ctxt<'tcx>,
-                             class_id: ast::DefId,
-                             items: &[ty::field_ty],
-                             fieldname: ast::Name,
-                             substs: &subst::Substs<'tcx>)
-                             -> Option<Ty<'tcx>> {
-
-    let o_field = items.iter().find(|f| f.name == fieldname);
-    o_field.map(|f| ty::lookup_field_type(tcx, class_id, f.id, substs))
-}
-
-pub fn lookup_tup_field_ty<'tcx>(tcx: &ty::ctxt<'tcx>,
-                                 class_id: ast::DefId,
-                                 items: &[ty::field_ty],
-                                 idx: uint,
-                                 substs: &subst::Substs<'tcx>)
-                                 -> Option<Ty<'tcx>> {
-
-    let o_field = if idx < items.len() { Some(&items[idx]) } else { None };
-    o_field.map(|f| ty::lookup_field_type(tcx, class_id, f.id, substs))
-}
-
 // Controls whether the arguments are automatically referenced. This is useful
 // for overloaded binary and unary operators.
 #[derive(Copy, PartialEq)]
@@ -3007,6 +2605,45 @@ enum TupleArgumentsFlag {
     TupleArguments,
 }
 
+/// Unifies the return type with the expected type early, for more coercions
+/// and forward type information on the argument expressions.
+fn expected_types_for_fn_args<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
+                                        call_span: Span,
+                                        expected_ret: Expectation<'tcx>,
+                                        formal_ret: ty::FnOutput<'tcx>,
+                                        formal_args: &[Ty<'tcx>])
+                                        -> Vec<Ty<'tcx>> {
+    let expected_args = expected_ret.only_has_type(fcx).and_then(|ret_ty| {
+        if let ty::FnConverging(formal_ret_ty) = formal_ret {
+            fcx.infcx().commit_regions_if_ok(|| {
+                // Attempt to apply a subtyping relationship between the formal
+                // return type (likely containing type variables if the function
+                // is polymorphic) and the expected return type.
+                // No argument expectations are produced if unification fails.
+                let origin = infer::Misc(call_span);
+                let ures = fcx.infcx().sub_types(false, origin, formal_ret_ty, ret_ty);
+                // FIXME(#15760) can't use try! here, FromError doesn't default
+                // to identity so the resulting type is not constrained.
+                if let Err(e) = ures {
+                    return Err(e);
+                }
+
+                // Record all the argument types, with the substitutions
+                // produced from the above subtyping unification.
+                Ok(formal_args.iter().map(|ty| {
+                    fcx.infcx().resolve_type_vars_if_possible(ty)
+                }).collect())
+            }).ok()
+        } else {
+            None
+        }
+    }).unwrap_or(vec![]);
+    debug!("expected_types_for_fn_args(formal={} -> {}, expected={} -> {})",
+           formal_args.repr(fcx.tcx()), formal_ret.repr(fcx.tcx()),
+           expected_args.repr(fcx.tcx()), expected_ret.repr(fcx.tcx()));
+    expected_args
+}
+
 /// Invariant:
 /// If an expression has any sub-expressions that result in a type error,
 /// inspecting that expression's type with `ty::type_is_error` will return
@@ -3028,12 +2665,13 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
            expr.repr(fcx.tcx()), expected.repr(fcx.tcx()));
 
     // Checks a method call.
-    fn check_method_call(fcx: &FnCtxt,
-                         expr: &ast::Expr,
-                         method_name: ast::SpannedIdent,
-                         args: &[P<ast::Expr>],
-                         tps: &[P<ast::Ty>],
-                         lvalue_pref: LvaluePreference) {
+    fn check_method_call<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
+                                   expr: &ast::Expr,
+                                   method_name: ast::SpannedIdent,
+                                   args: &[P<ast::Expr>],
+                                   tps: &[P<ast::Ty>],
+                                   expected: Expectation<'tcx>,
+                                   lvalue_pref: LvaluePreference) {
         let rcvr = &*args[0];
         check_expr_with_lvalue_pref(fcx, &*rcvr, lvalue_pref);
 
@@ -3064,14 +2702,14 @@ fn check_method_call(fcx: &FnCtxt,
         };
 
         // Call the generic checker.
-        let args: Vec<_> = args[1..].iter().map(|x| x).collect();
         let ret_ty = check_method_argument_types(fcx,
                                                  method_name.span,
                                                  fn_ty,
                                                  expr,
-                                                 args.as_slice(),
+                                                 &args[1..],
                                                  AutorefArgs::No,
-                                                 DontTupleArguments);
+                                                 DontTupleArguments,
+                                                 expected);
 
         write_call(fcx, expr, ret_ty);
     }
@@ -3167,8 +2805,8 @@ fn lookup_op_method<'a, 'tcx, F>(fcx: &'a FnCtxt<'a, 'tcx>,
             None => None
         };
         let args = match rhs {
-            Some(rhs) => vec![rhs],
-            None => vec![]
+            Some(rhs) => slice::ref_slice(rhs),
+            None => &[][]
         };
         match method {
             Some(method) => {
@@ -3177,12 +2815,13 @@ fn lookup_op_method<'a, 'tcx, F>(fcx: &'a FnCtxt<'a, 'tcx>,
                 let method_call = ::middle::ty::MethodCall::expr(op_ex.id);
                 fcx.inh.method_map.borrow_mut().insert(method_call, method);
                 match check_method_argument_types(fcx,
-                                            op_ex.span,
-                                            method_ty,
-                                            op_ex,
-                                            args.as_slice(),
-                                            autoref_args,
-                                            DontTupleArguments) {
+                                                  op_ex.span,
+                                                  method_ty,
+                                                  op_ex,
+                                                  args,
+                                                  autoref_args,
+                                                  DontTupleArguments,
+                                                  NoExpectation) {
                     ty::FnConverging(result_type) => result_type,
                     ty::FnDiverging => fcx.tcx().types.err
                 }
@@ -3196,9 +2835,10 @@ fn lookup_op_method<'a, 'tcx, F>(fcx: &'a FnCtxt<'a, 'tcx>,
                                             op_ex.span,
                                             expected_ty,
                                             op_ex,
-                                            args.as_slice(),
+                                            args,
                                             autoref_args,
-                                            DontTupleArguments);
+                                            DontTupleArguments,
+                                            NoExpectation);
                 fcx.tcx().types.err
             }
         }
@@ -3398,8 +3038,8 @@ fn check_field(fcx: &FnCtxt,
                     ty::ty_struct(base_id, substs) => {
                         debug!("struct named {}", ppaux::ty_to_string(tcx, base_t));
                         let fields = ty::lookup_struct_fields(tcx, base_id);
-                        lookup_field_ty(tcx, base_id, &fields[],
-                                        field.node.name, &(*substs))
+                        fcx.lookup_field_ty(expr.span, base_id, &fields[],
+                                            field.node.name, &(*substs))
                     }
                     _ => None
                 }
@@ -3461,8 +3101,8 @@ fn check_tup_field(fcx: &FnCtxt,
                         if tuple_like {
                             debug!("tuple struct named {}", ppaux::ty_to_string(tcx, base_t));
                             let fields = ty::lookup_struct_fields(tcx, base_id);
-                            lookup_tup_field_ty(tcx, base_id, &fields[],
-                                                idx.node, &(*substs))
+                            fcx.lookup_tup_field_ty(expr.span, base_id, &fields[],
+                                                    idx.node, &(*substs))
                         } else {
                             None
                         }
@@ -3761,7 +3401,7 @@ fn check_struct_fields_on_error(fcx: &FnCtxt,
         }
       }
       ast::ExprUnary(unop, ref oprnd) => {
-        let expected_inner = expected.map(fcx, |ty| {
+        let expected_inner = expected.to_option(fcx).map_or(NoExpectation, |ty| {
             match unop {
                 ast::UnUniq => match ty.sty {
                     ty::ty_uniq(ty) => {
@@ -3851,8 +3491,7 @@ fn check_struct_fields_on_error(fcx: &FnCtxt,
         fcx.write_ty(id, oprnd_t);
       }
       ast::ExprAddrOf(mutbl, ref oprnd) => {
-        let expected = expected.only_has_type();
-        let hint = expected.map(fcx, |ty| {
+        let hint = expected.only_has_type(fcx).map_or(NoExpectation, |ty| {
             match ty.sty {
                 ty::ty_rptr(_, ref mt) | ty::ty_ptr(ref mt) => {
                     if ty::expr_is_lval(fcx.tcx(), &**oprnd) {
@@ -3914,10 +3553,25 @@ fn check_struct_fields_on_error(fcx: &FnCtxt,
         };
         fcx.write_ty(id, oprnd_t);
       }
-      ast::ExprPath(ref pth) => {
-          let defn = lookup_def(fcx, pth.span, id);
+      ast::ExprPath(ref path) => {
+          let defn = lookup_def(fcx, path.span, id);
           let pty = type_scheme_for_def(fcx, expr.span, defn);
-          instantiate_path(fcx, pth, pty, defn, expr.span, expr.id);
+          instantiate_path(fcx, path, pty, None, defn, expr.span, expr.id);
+
+          // We always require that the type provided as the value for
+          // a type parameter outlives the moment of instantiation.
+          constrain_path_type_parameters(fcx, expr);
+      }
+      ast::ExprQPath(ref qpath) => {
+          // Require explicit type params for the trait.
+          let self_ty = fcx.to_ty(&*qpath.self_type);
+          astconv::instantiate_trait_ref(fcx, fcx, &*qpath.trait_ref, Some(self_ty), None);
+
+          let defn = lookup_def(fcx, expr.span, id);
+          let pty = type_scheme_for_def(fcx, expr.span, defn);
+          let mut path = qpath.trait_ref.path.clone();
+          path.segments.push(qpath.item_path.clone());
+          instantiate_path(fcx, &path, pty, Some(self_ty), defn, expr.span, expr.id);
 
           // We always require that the type provided as the value for
           // a type parameter outlives the moment of instantiation.
@@ -4046,10 +3700,10 @@ fn check_struct_fields_on_error(fcx: &FnCtxt,
         fcx.write_ty(id, fcx.node_ty(b.id));
       }
       ast::ExprCall(ref callee, ref args) => {
-          callee::check_call(fcx, expr, &**callee, args.as_slice());
+          callee::check_call(fcx, expr, &**callee, &args[], expected);
       }
       ast::ExprMethodCall(ident, ref tps, ref args) => {
-        check_method_call(fcx, expr, ident, args.as_slice(), tps.as_slice(), lvalue_pref);
+        check_method_call(fcx, expr, ident, &args[], &tps[], expected, lvalue_pref);
         let arg_tys = args.iter().map(|a| fcx.expr_ty(&**a));
         let  args_err = arg_tys.fold(false,
              |rest_err, a| {
@@ -4065,7 +3719,7 @@ fn check_struct_fields_on_error(fcx: &FnCtxt,
         check_cast(fcx, expr, &**e, &**t);
       }
       ast::ExprVec(ref args) => {
-        let uty = expected.map_to_option(fcx, |uty| {
+        let uty = expected.to_option(fcx).and_then(|uty| {
             match uty.sty {
                 ty::ty_vec(ty, _) => Some(ty),
                 _ => None
@@ -4134,8 +3788,7 @@ fn check_struct_fields_on_error(fcx: &FnCtxt,
         }
       }
       ast::ExprTup(ref elts) => {
-        let expected = expected.only_has_type();
-        let flds = expected.map_to_option(fcx, |ty| {
+        let flds = expected.only_has_type(fcx).and_then(|ty| {
             match ty.sty {
                 ty::ty_tup(ref flds) => Some(&flds[]),
                 _ => None
@@ -4428,13 +4081,6 @@ fn rvalue_hint(ty: Ty<'tcx>) -> Expectation<'tcx> {
         }
     }
 
-    fn only_has_type(self) -> Expectation<'tcx> {
-        match self {
-            ExpectHasType(t) => ExpectHasType(t),
-            _ => NoExpectation
-        }
-    }
-
     // Resolves `expected` by a single level if it is a variable. If
     // there is no expected type or resolution is not possible (e.g.,
     // no constraints yet present), just returns `None`.
@@ -4458,25 +4104,19 @@ fn resolve<'a>(self, fcx: &FnCtxt<'a, 'tcx>) -> Expectation<'tcx> {
         }
     }
 
-    fn map<'a, F>(self, fcx: &FnCtxt<'a, 'tcx>, unpack: F) -> Expectation<'tcx> where
-        F: FnOnce(Ty<'tcx>) -> Expectation<'tcx>
-    {
+    fn to_option<'a>(self, fcx: &FnCtxt<'a, 'tcx>) -> Option<Ty<'tcx>> {
         match self.resolve(fcx) {
-            NoExpectation => NoExpectation,
+            NoExpectation => None,
             ExpectCastableToType(ty) |
             ExpectHasType(ty) |
-            ExpectRvalueLikeUnsized(ty) => unpack(ty),
+            ExpectRvalueLikeUnsized(ty) => Some(ty),
         }
     }
 
-    fn map_to_option<'a, O, F>(self, fcx: &FnCtxt<'a, 'tcx>, unpack: F) -> Option<O> where
-        F: FnOnce(Ty<'tcx>) -> Option<O>,
-    {
+    fn only_has_type<'a>(self, fcx: &FnCtxt<'a, 'tcx>) -> Option<Ty<'tcx>> {
         match self.resolve(fcx) {
-            NoExpectation => None,
-            ExpectCastableToType(ty) |
-            ExpectHasType(ty) |
-            ExpectRvalueLikeUnsized(ty) => unpack(ty),
+            ExpectHasType(ty) => Some(ty),
+            _ => None
         }
     }
 }
@@ -4994,6 +4634,7 @@ pub fn type_scheme_for_def<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
 pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                                   path: &ast::Path,
                                   type_scheme: TypeScheme<'tcx>,
+                                  opt_self_ty: Option<Ty<'tcx>>,
                                   def: def::Def,
                                   span: Span,
                                   node_id: ast::NodeId) {
@@ -5151,6 +4792,11 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
             }
         }
     }
+    if let Some(self_ty) = opt_self_ty {
+        // `<T as Trait>::foo` shouldn't have resolved to a `Self`-less item.
+        assert_eq!(type_defs.len(subst::SelfSpace), 1);
+        substs.types.push(subst::SelfSpace, self_ty);
+    }
 
     // Now we have to compare the types that the user *actually*
     // provided against the types that were *expected*. If the user
index f15d53290e761de75895711b9640575c564f29bc..68b152dee233b4ea86be313adcf9076049d2e6f8 100644 (file)
@@ -84,6 +84,7 @@
 #[macro_use] extern crate syntax;
 
 extern crate arena;
+extern crate fmt_macros;
 extern crate rustc;
 
 pub use rustc::lint;
index 3e2474468adb696c8edc83717f67794a538c0973..ccaefadc1fcd963e281e00a6e788792df3f8df60 100644 (file)
@@ -126,13 +126,8 @@ fn try_inline_def(cx: &DocContext, tcx: &ty::ctxt,
 
 pub fn load_attrs(cx: &DocContext, tcx: &ty::ctxt,
                   did: ast::DefId) -> Vec<clean::Attribute> {
-    let mut attrs = Vec::new();
-    csearch::get_item_attrs(&tcx.sess.cstore, did, |v| {
-        attrs.extend(v.into_iter().map(|a| {
-            a.clean(cx)
-        }));
-    });
-    attrs
+    let attrs = csearch::get_item_attrs(&tcx.sess.cstore, did);
+    attrs.into_iter().map(|a| a.clean(cx)).collect()
 }
 
 /// Record an external fully qualified name in the external_paths cache.
index a44c73e8c4120f91d9b986673e6a68273003faf8..8dc3adad3b27a010feae9758f61c427960daaf76 100644 (file)
@@ -104,6 +104,12 @@ fn clean(&self, cx: &DocContext) -> Option<U> {
     }
 }
 
+impl<T, U> Clean<U> for ty::Binder<T> where T: Clean<U> {
+    fn clean(&self, cx: &DocContext) -> U {
+        self.0.clean(cx)
+    }
+}
+
 impl<T: Clean<U>, U> Clean<Vec<U>> for syntax::owned_slice::OwnedSlice<T> {
     fn clean(&self, cx: &DocContext) -> Vec<U> {
         self.iter().map(|x| x.clean(cx)).collect()
@@ -498,22 +504,28 @@ fn clean(&self, cx: &DocContext) -> TyParamBound {
     }
 }
 
-impl<'tcx> Clean<Vec<TyParamBound>> for ty::ExistentialBounds<'tcx> {
-    fn clean(&self, cx: &DocContext) -> Vec<TyParamBound> {
-        let mut vec = vec![];
-        self.region_bound.clean(cx).map(|b| vec.push(RegionBound(b)));
+impl<'tcx> Clean<(Vec<TyParamBound>, Vec<TypeBinding>)> for ty::ExistentialBounds<'tcx> {
+    fn clean(&self, cx: &DocContext) -> (Vec<TyParamBound>, Vec<TypeBinding>) {
+        let mut tp_bounds = vec![];
+        self.region_bound.clean(cx).map(|b| tp_bounds.push(RegionBound(b)));
         for bb in self.builtin_bounds.iter() {
-            vec.push(bb.clean(cx));
+            tp_bounds.push(bb.clean(cx));
         }
 
-        // FIXME(#20299) -- should do something with projection bounds
+        let mut bindings = vec![];
+        for &ty::Binder(ref pb) in self.projection_bounds.iter() {
+            bindings.push(TypeBinding {
+                name: pb.projection_ty.item_name.clean(cx),
+                ty: pb.ty.clean(cx)
+            });
+        }
 
-        vec
+        (tp_bounds, bindings)
     }
 }
 
 fn external_path_params(cx: &DocContext, trait_did: Option<ast::DefId>,
-                        substs: &subst::Substs) -> PathParameters {
+                        bindings: Vec<TypeBinding>, substs: &subst::Substs) -> PathParameters {
     use rustc::middle::ty::sty;
     let lifetimes = substs.regions().get_slice(subst::TypeSpace)
                     .iter()
@@ -531,7 +543,7 @@ fn external_path_params(cx: &DocContext, trait_did: Option<ast::DefId>,
                     return PathParameters::AngleBracketed {
                         lifetimes: lifetimes,
                         types: types.clean(cx),
-                        bindings: vec![]
+                        bindings: bindings
                     }
                 }
             };
@@ -548,7 +560,7 @@ fn external_path_params(cx: &DocContext, trait_did: Option<ast::DefId>,
             PathParameters::AngleBracketed {
                 lifetimes: lifetimes,
                 types: types.clean(cx),
-                bindings: vec![] // FIXME(#20646)
+                bindings: bindings
             }
         }
     }
@@ -557,12 +569,12 @@ fn external_path_params(cx: &DocContext, trait_did: Option<ast::DefId>,
 // trait_did should be set to a trait's DefId if called on a TraitRef, in order to sugar
 // from Fn<(A, B,), C> to Fn(A, B) -> C
 fn external_path(cx: &DocContext, name: &str, trait_did: Option<ast::DefId>,
-                 substs: &subst::Substs) -> Path {
+                 bindings: Vec<TypeBinding>, substs: &subst::Substs) -> Path {
     Path {
         global: false,
         segments: vec![PathSegment {
             name: name.to_string(),
-            params: external_path_params(cx, trait_did, substs)
+            params: external_path_params(cx, trait_did, bindings, substs)
         }],
     }
 }
@@ -577,16 +589,16 @@ fn clean(&self, cx: &DocContext) -> TyParamBound {
         let (did, path) = match *self {
             ty::BoundSend =>
                 (tcx.lang_items.send_trait().unwrap(),
-                 external_path(cx, "Send", None, &empty)),
+                 external_path(cx, "Send", None, vec![], &empty)),
             ty::BoundSized =>
                 (tcx.lang_items.sized_trait().unwrap(),
-                 external_path(cx, "Sized", None, &empty)),
+                 external_path(cx, "Sized", None, vec![], &empty)),
             ty::BoundCopy =>
                 (tcx.lang_items.copy_trait().unwrap(),
-                 external_path(cx, "Copy", None, &empty)),
+                 external_path(cx, "Copy", None, vec![], &empty)),
             ty::BoundSync =>
                 (tcx.lang_items.sync_trait().unwrap(),
-                 external_path(cx, "Sync", None, &empty)),
+                 external_path(cx, "Sync", None, vec![], &empty)),
         };
         let fqn = csearch::get_item_path(tcx, did);
         let fqn = fqn.into_iter().map(|i| i.to_string()).collect();
@@ -603,12 +615,6 @@ fn clean(&self, cx: &DocContext) -> TyParamBound {
     }
 }
 
-impl<'tcx> Clean<TyParamBound> for ty::PolyTraitRef<'tcx> {
-    fn clean(&self, cx: &DocContext) -> TyParamBound {
-        self.0.clean(cx)
-    }
-}
-
 impl<'tcx> Clean<TyParamBound> for ty::TraitRef<'tcx> {
     fn clean(&self, cx: &DocContext) -> TyParamBound {
         let tcx = match cx.tcx_opt() {
@@ -619,7 +625,7 @@ fn clean(&self, cx: &DocContext) -> TyParamBound {
         let fqn = fqn.into_iter().map(|i| i.to_string())
                      .collect::<Vec<String>>();
         let path = external_path(cx, fqn.last().unwrap().as_slice(),
-                                 Some(self.def_id), self.substs);
+                                 Some(self.def_id), vec![], self.substs);
         cx.external_paths.borrow_mut().as_mut().unwrap().insert(self.def_id,
                                                             (fqn, TypeTrait));
 
@@ -730,8 +736,7 @@ fn clean(&self, cx: &DocContext) -> Option<Lifetime> {
 pub enum WherePredicate {
     BoundPredicate { ty: Type, bounds: Vec<TyParamBound> },
     RegionPredicate { lifetime: Lifetime, bounds: Vec<Lifetime>},
-    // FIXME (#20041)
-    EqPredicate
+    EqPredicate { lhs: Type, rhs: Type }
 }
 
 impl Clean<WherePredicate> for ast::WherePredicate {
@@ -752,12 +757,89 @@ fn clean(&self, cx: &DocContext) -> WherePredicate {
             }
 
             ast::WherePredicate::EqPredicate(_) => {
-                WherePredicate::EqPredicate
+                unimplemented!() // FIXME(#20041)
             }
         }
     }
 }
 
+impl<'a> Clean<WherePredicate> for ty::Predicate<'a> {
+    fn clean(&self, cx: &DocContext) -> WherePredicate {
+        use rustc::middle::ty::Predicate;
+
+        match *self {
+            Predicate::Trait(ref pred) => pred.clean(cx),
+            Predicate::Equate(ref pred) => pred.clean(cx),
+            Predicate::RegionOutlives(ref pred) => pred.clean(cx),
+            Predicate::TypeOutlives(ref pred) => pred.clean(cx),
+            Predicate::Projection(ref pred) => pred.clean(cx)
+        }
+    }
+}
+
+impl<'a> Clean<WherePredicate> for ty::TraitPredicate<'a> {
+    fn clean(&self, cx: &DocContext) -> WherePredicate {
+        WherePredicate::BoundPredicate {
+            ty: self.trait_ref.substs.self_ty().clean(cx).unwrap(),
+            bounds: vec![self.trait_ref.clean(cx)]
+        }
+    }
+}
+
+impl<'tcx> Clean<WherePredicate> for ty::EquatePredicate<'tcx> {
+    fn clean(&self, cx: &DocContext) -> WherePredicate {
+        let ty::EquatePredicate(ref lhs, ref rhs) = *self;
+        WherePredicate::EqPredicate {
+            lhs: lhs.clean(cx),
+            rhs: rhs.clean(cx)
+        }
+    }
+}
+
+impl Clean<WherePredicate> for ty::OutlivesPredicate<ty::Region, ty::Region> {
+    fn clean(&self, cx: &DocContext) -> WherePredicate {
+        let ty::OutlivesPredicate(ref a, ref b) = *self;
+        WherePredicate::RegionPredicate {
+            lifetime: a.clean(cx).unwrap(),
+            bounds: vec![b.clean(cx).unwrap()]
+        }
+    }
+}
+
+impl<'tcx> Clean<WherePredicate> for ty::OutlivesPredicate<ty::Ty<'tcx>, ty::Region> {
+    fn clean(&self, cx: &DocContext) -> WherePredicate {
+        let ty::OutlivesPredicate(ref ty, ref lt) = *self;
+
+        WherePredicate::BoundPredicate {
+            ty: ty.clean(cx),
+            bounds: vec![TyParamBound::RegionBound(lt.clean(cx).unwrap())]
+        }
+    }
+}
+
+impl<'tcx> Clean<WherePredicate> for ty::ProjectionPredicate<'tcx> {
+    fn clean(&self, cx: &DocContext) -> WherePredicate {
+        WherePredicate::EqPredicate {
+            lhs: self.projection_ty.clean(cx),
+            rhs: self.ty.clean(cx)
+        }
+    }
+}
+
+impl<'tcx> Clean<Type> for ty::ProjectionTy<'tcx> {
+    fn clean(&self, cx: &DocContext) -> Type {
+        let trait_ = match self.trait_ref.clean(cx) {
+            TyParamBound::TraitBound(t, _) => t.trait_,
+            TyParamBound::RegionBound(_) => panic!("cleaning a trait got a region??"),
+        };
+        Type::QPath {
+            name: self.item_name.clean(cx),
+            self_type: box self.trait_ref.self_ty().clean(cx),
+            trait_: box trait_
+        }
+    }
+}
+
 // maybe use a Generic enum and use ~[Generic]?
 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Show)]
 pub struct Generics {
@@ -778,11 +860,80 @@ fn clean(&self, cx: &DocContext) -> Generics {
 
 impl<'a, 'tcx> Clean<Generics> for (&'a ty::Generics<'tcx>, subst::ParamSpace) {
     fn clean(&self, cx: &DocContext) -> Generics {
-        let (me, space) = *self;
+        use std::collections::HashSet;
+        use syntax::ast::TraitBoundModifier as TBM;
+        use self::WherePredicate as WP;
+
+        fn has_sized_bound(bounds: &[TyParamBound], cx: &DocContext) -> bool {
+            if let Some(tcx) = cx.tcx_opt() {
+                let sized_did = match tcx.lang_items.sized_trait() {
+                    Some(did) => did,
+                    None => return false
+                };
+                for bound in bounds.iter() {
+                    if let TyParamBound::TraitBound(PolyTrait {
+                        trait_: Type::ResolvedPath { did, .. }, ..
+                    }, TBM::None) = *bound {
+                        if did == sized_did {
+                            return true
+                        }
+                    }
+                }
+            }
+            false
+        }
+
+        let (gens, space) = *self;
+        // Bounds in the type_params and lifetimes fields are repeated in the predicates
+        // field (see rustc_typeck::collect::ty_generics), so remove them.
+        let stripped_typarams = gens.types.get_slice(space).iter().map(|tp| {
+            let mut stp = tp.clone();
+            stp.bounds = ty::ParamBounds::empty();
+            stp.clean(cx)
+        }).collect::<Vec<_>>();
+        let stripped_lifetimes = gens.regions.get_slice(space).iter().map(|rp| {
+            let mut srp = rp.clone();
+            srp.bounds = Vec::new();
+            srp.clean(cx)
+        }).collect::<Vec<_>>();
+
+        let where_predicates = gens.predicates.get_slice(space).to_vec().clean(cx);
+        // Type parameters have a Sized bound by default unless removed with ?Sized.
+        // Scan through the predicates and mark any type parameter with a Sized
+        // bound, removing the bounds as we find them.
+        let mut sized_params = HashSet::new();
+        let mut where_predicates = where_predicates.into_iter().filter_map(|pred| {
+            if let WP::BoundPredicate { ty: Type::Generic(ref g), ref bounds } = pred {
+                if has_sized_bound(&**bounds, cx) {
+                    sized_params.insert(g.clone());
+                    return None
+                }
+            }
+            Some(pred)
+        }).collect::<Vec<_>>();
+        // Finally, run through the type parameters again and insert a ?Sized unbound for
+        // any we didn't find to be Sized.
+        for tp in stripped_typarams.iter() {
+            if !sized_params.contains(&tp.name) {
+                let mut sized_bound = ty::BuiltinBound::BoundSized.clean(cx);
+                if let TyParamBound::TraitBound(_, ref mut tbm) = sized_bound {
+                    *tbm = TBM::Maybe
+                };
+                where_predicates.push(WP::BoundPredicate {
+                    ty: Type::Generic(tp.name.clone()),
+                    bounds: vec![sized_bound]
+                })
+            }
+        }
+
+        // It would be nice to collect all of the bounds on a type and recombine
+        // them if possible, to avoid e.g. `where T: Foo, T: Bar, T: Sized, T: 'a`
+        // and instead see `where T: Foo + Bar + Sized + 'a`
+
         Generics {
-            type_params: me.types.get_slice(space).to_vec().clean(cx),
-            lifetimes: me.regions.get_slice(space).to_vec().clean(cx),
-            where_predicates: vec![]
+            type_params: stripped_typarams,
+            lifetimes: stripped_lifetimes,
+            where_predicates: where_predicates
         }
     }
 }
@@ -910,27 +1061,6 @@ fn clean(&self, cx: &DocContext) -> Item {
     }
 }
 
-#[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Show)]
-pub struct ClosureDecl {
-    pub lifetimes: Vec<Lifetime>,
-    pub decl: FnDecl,
-    pub onceness: ast::Onceness,
-    pub unsafety: ast::Unsafety,
-    pub bounds: Vec<TyParamBound>,
-}
-
-impl Clean<ClosureDecl> for ast::ClosureTy {
-    fn clean(&self, cx: &DocContext) -> ClosureDecl {
-        ClosureDecl {
-            lifetimes: self.lifetimes.clean(cx),
-            decl: self.decl.clean(cx),
-            onceness: self.onceness,
-            unsafety: self.unsafety,
-            bounds: self.bounds.clean(cx)
-        }
-    }
-}
-
 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Show)]
 pub struct FnDecl {
     pub inputs: Arguments,
@@ -1207,8 +1337,6 @@ pub enum Type {
     Generic(String),
     /// Primitives are just the fixed-size numeric types (plus int/uint/float), and char.
     Primitive(PrimitiveType),
-    Closure(Box<ClosureDecl>),
-    Proc(Box<ClosureDecl>),
     /// extern "ABI" fn
     BareFunction(Box<BareFunctionDecl>),
     Tuple(Vec<Type>),
@@ -1436,7 +1564,7 @@ fn clean(&self, cx: &DocContext) -> Type {
                     _ => TypeEnum,
                 };
                 let path = external_path(cx, fqn.last().unwrap().to_string().as_slice(),
-                                         None, substs);
+                                         None, vec![], substs);
                 cx.external_paths.borrow_mut().as_mut().unwrap().insert(did, (fqn, kind));
                 ResolvedPath {
                     path: path,
@@ -1448,12 +1576,13 @@ fn clean(&self, cx: &DocContext) -> Type {
                 let did = principal.def_id();
                 let fqn = csearch::get_item_path(cx.tcx(), did);
                 let fqn: Vec<_> = fqn.into_iter().map(|i| i.to_string()).collect();
+                let (typarams, bindings) = bounds.clean(cx);
                 let path = external_path(cx, fqn.last().unwrap().to_string().as_slice(),
-                                         Some(did), principal.substs());
+                                         Some(did), bindings, principal.substs());
                 cx.external_paths.borrow_mut().as_mut().unwrap().insert(did, (fqn, TypeTrait));
                 ResolvedPath {
                     path: path,
-                    typarams: Some(bounds.clean(cx)),
+                    typarams: Some(typarams),
                     did: did,
                 }
             }
@@ -1485,7 +1614,7 @@ fn clean(&self, cx: &DocContext) -> Type {
 impl Clean<Type> for ast::QPath {
     fn clean(&self, cx: &DocContext) -> Type {
         Type::QPath {
-            name: self.item_name.clean(cx),
+            name: self.item_path.identifier.clean(cx),
             self_type: box self.self_type.clean(cx),
             trait_: box self.trait_ref.clean(cx)
         }
index 4885bd373eb1dfd74e57fa43062be708ec013d0f..5bef0195874b64616b8742ddb929847034a50558 100644 (file)
@@ -16,6 +16,7 @@
 use rustc::middle::{privacy, ty};
 use rustc::lint;
 use rustc_trans::back::link;
+use rustc_resolve as resolve;
 
 use syntax::{ast, ast_map, codemap, diagnostic};
 
@@ -126,7 +127,11 @@ pub fn run_core(search_paths: SearchPaths, cfgs: Vec<String>, externs: Externs,
     let arenas = ty::CtxtArenas::new();
     let ty::CrateAnalysis {
         exported_items, public_items, ty_cx, ..
-    } = driver::phase_3_run_analysis_passes(sess, ast_map, &arenas, name);
+    } = driver::phase_3_run_analysis_passes(sess,
+                                            ast_map,
+                                            &arenas,
+                                            name,
+                                            resolve::MakeGlobMap::No);
 
     let ctxt = DocContext {
         krate: ty_cx.map.krate(),
index 00f7c570b5d09f5b96c3d61eef0b213060ad561b..d13936b2168658f80472d625bacabfde1bcc6a9f 100644 (file)
@@ -153,8 +153,8 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                         try!(write!(f, "{}", lifetime));
                     }
                 }
-                &clean::WherePredicate::EqPredicate => {
-                    unimplemented!()
+                &clean::WherePredicate::EqPredicate { ref lhs, ref rhs } => {
+                    try!(write!(f, "{} == {}", lhs, rhs));
                 }
             }
         }
@@ -332,7 +332,7 @@ fn path<F, G>(w: &mut fmt::Formatter,
         match rel_root {
             Some(root) => {
                 let mut root = String::from_str(root.as_slice());
-                for seg in path.segments[0..amt].iter() {
+                for seg in path.segments[..amt].iter() {
                     if "super" == seg.name ||
                             "self" == seg.name {
                         try!(write!(w, "{}::", seg.name));
@@ -347,7 +347,7 @@ fn path<F, G>(w: &mut fmt::Formatter,
                 }
             }
             None => {
-                for seg in path.segments[0..amt].iter() {
+                for seg in path.segments[..amt].iter() {
                     try!(write!(w, "{}::", seg.name));
                 }
             }
@@ -465,61 +465,6 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
             }
             clean::Infer => write!(f, "_"),
             clean::Primitive(prim) => primitive_link(f, prim, prim.to_string()),
-            clean::Closure(ref decl) => {
-                write!(f, "{style}{lifetimes}|{args}|{bounds}{arrow}",
-                       style = UnsafetySpace(decl.unsafety),
-                       lifetimes = if decl.lifetimes.len() == 0 {
-                           "".to_string()
-                       } else {
-                           format!("for &lt;{}&gt;",
-                                   CommaSep(decl.lifetimes.as_slice()))
-                       },
-                       args = decl.decl.inputs,
-                       arrow = decl.decl.output,
-                       bounds = {
-                           let mut ret = String::new();
-                           for bound in decl.bounds.iter() {
-                                match *bound {
-                                    clean::RegionBound(..) => {}
-                                    clean::TraitBound(ref t, modifier) => {
-                                        if ret.len() == 0 {
-                                            ret.push_str(": ");
-                                        } else {
-                                            ret.push_str(" + ");
-                                        }
-                                        if modifier == ast::TraitBoundModifier::Maybe {
-                                            ret.push_str("?");
-                                        }
-                                        ret.push_str(format!("{}",
-                                                             *t).as_slice());
-                                    }
-                                }
-                           }
-                           ret
-                       })
-            }
-            clean::Proc(ref decl) => {
-                write!(f, "{style}{lifetimes}proc({args}){bounds}{arrow}",
-                       style = UnsafetySpace(decl.unsafety),
-                       lifetimes = if decl.lifetimes.len() == 0 {
-                           "".to_string()
-                       } else {
-                           format!("for &lt;{}&gt;",
-                                   CommaSep(decl.lifetimes.as_slice()))
-                       },
-                       args = decl.decl.inputs,
-                       bounds = if decl.bounds.len() == 0 {
-                           "".to_string()
-                       } else {
-                           let m = decl.bounds
-                                           .iter()
-                                           .map(|s| s.to_string());
-                           format!(
-                               ": {}",
-                               m.collect::<Vec<String>>().connect(" + "))
-                       },
-                       arrow = decl.decl.output)
-            }
             clean::BareFunction(ref decl) => {
                 write!(f, "{}{}fn{}{}",
                        UnsafetySpace(decl.unsafety),
index a063191a12fd6c505715954910808de554da3220..0dbd13b4616bb36bf91f6d8ed1dde08202eb5cbd 100644 (file)
@@ -30,7 +30,7 @@
 use libc;
 use std::ascii::AsciiExt;
 use std::ffi::CString;
-use std::cell::{RefCell, Cell};
+use std::cell::RefCell;
 use std::collections::HashMap;
 use std::fmt;
 use std::slice;
@@ -155,7 +155,6 @@ fn stripped_filtered_line<'a>(s: &'a str) -> Option<&'a str> {
 thread_local!(static USED_HEADER_MAP: RefCell<HashMap<String, uint>> = {
     RefCell::new(HashMap::new())
 });
-thread_local!(static TEST_IDX: Cell<uint> = Cell::new(0));
 
 thread_local!(pub static PLAYGROUND_KRATE: RefCell<Option<Option<String>>> = {
     RefCell::new(None)
@@ -195,26 +194,19 @@ pub fn render(w: &mut fmt::Formatter, s: &str, print_toc: bool) -> fmt::Result {
             if rendered { return }
             PLAYGROUND_KRATE.with(|krate| {
                 let mut s = String::new();
-                let id = krate.borrow().as_ref().map(|krate| {
-                    let idx = TEST_IDX.with(|slot| {
-                        let i = slot.get();
-                        slot.set(i + 1);
-                        i
-                    });
-
+                krate.borrow().as_ref().map(|krate| {
                     let test = origtext.lines().map(|l| {
                         stripped_filtered_line(l).unwrap_or(l)
                     }).collect::<Vec<&str>>().connect("\n");
                     let krate = krate.as_ref().map(|s| s.as_slice());
                     let test = test::maketest(test.as_slice(), krate, false, false);
-                    s.push_str(format!("<span id='rust-example-raw-{}' \
-                                         class='rusttest'>{}</span>",
-                                       idx, Escape(test.as_slice())).as_slice());
-                    format!("rust-example-rendered-{}", idx)
+                    s.push_str(format!("<span class='rusttest'>{}</span>",
+                                         Escape(test.as_slice())).as_slice());
                 });
-                let id = id.as_ref().map(|a| a.as_slice());
-                s.push_str(highlight::highlight(text.as_slice(), None, id)
-                                     .as_slice());
+                s.push_str(highlight::highlight(text.as_slice(),
+                                                None,
+                                                Some("rust-example-rendered"))
+                             .as_slice());
                 let output = CString::from_vec(s.into_bytes());
                 hoedown_buffer_puts(ob, output.as_ptr());
             })
@@ -432,7 +424,6 @@ fn parse(string: &str) -> LangString {
 /// previous state (if any).
 pub fn reset_headers() {
     USED_HEADER_MAP.with(|s| s.borrow_mut().clear());
-    TEST_IDX.with(|s| s.set(0));
 }
 
 impl<'a> fmt::String for Markdown<'a> {
index f7d6b872940a439b00131f812fe1efa10d9dd590..687f764f02077a10cc0df749585984d9e08030b7 100644 (file)
 (function() {
     if (window.playgroundUrl) {
         $('pre.rust').hover(function() {
-            if (!$(this).attr('id')) { return; }
-            var id = '#' + $(this).attr('id').replace('rendered', 'raw');
             var a = $('<a>').text('⇱').attr('class', 'test-arrow');
-            var code = $(id).text();
+            var code = $(this).siblings(".rusttest").text();
             a.attr('href', window.playgroundUrl + '?code=' +
                            encodeURIComponent(code));
             a.attr('target', '_blank');
index 6d5df3d777d8677f125c09cadb994a0537496003..e6eed4806338bc53c37221ab9ef03c417a6c6fac 100644 (file)
@@ -27,6 +27,7 @@
 extern crate rustc;
 extern crate rustc_trans;
 extern crate rustc_driver;
+extern crate rustc_resolve;
 extern crate serialize;
 extern crate syntax;
 extern crate "test" as testing;
index ab9c4ef942230bcc7a94ee0203085c42aeb4fc95..dc98a56eb1a4e7c1ed598ed393f9d099d44c6e60 100644 (file)
@@ -91,6 +91,7 @@ pub fn render(input: &str, mut output: Path, matches: &getopts::Matches,
 <html lang="en">
 <head>
     <meta charset="utf-8">
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
     <meta name="generator" content="rustdoc">
     <title>{title}</title>
 
index 38ce73895466567809d7eabc9f462d4edacace83..9b8d220acc394010804fd72461591585a055ec20 100644 (file)
@@ -123,7 +123,6 @@ fn runtest(test: &str, cratename: &str, libs: SearchPaths,
         search_paths: libs,
         crate_types: vec!(config::CrateTypeExecutable),
         output_types: vec!(config::OutputTypeExe),
-        no_trans: no_run,
         externs: externs,
         cg: config::CodegenOptions {
             prefer_dynamic: true,
@@ -170,14 +169,18 @@ fn runtest(test: &str, cratename: &str, libs: SearchPaths,
         diagnostic::mk_span_handler(diagnostic_handler, codemap);
 
     let sess = session::build_session_(sessopts,
-                                      None,
-                                      span_diagnostic_handler);
+                                       None,
+                                       span_diagnostic_handler);
 
     let outdir = TempDir::new("rustdoctest").ok().expect("rustdoc needs a tempdir");
     let out = Some(outdir.path().clone());
     let cfg = config::build_configuration(&sess);
     let libdir = sess.target_filesearch(PathKind::All).get_lib_path();
-    driver::compile_input(sess, cfg, &input, &out, &None, None);
+    let mut control = driver::CompileController::basic();
+    if no_run {
+        control.after_analysis.stop = true;
+    }
+    driver::compile_input(sess, cfg, &input, &out, &None, None, control);
 
     if no_run { return }
 
index 62acef2ca1cc75476f1cc27a13200f0784988b33..41499b5ae0efed34bafe3b29191c5db904c957f0 100644 (file)
@@ -401,7 +401,7 @@ fn escape_str(wr: &mut fmt::Writer, v: &str) -> fmt::Result {
 fn escape_char(writer: &mut fmt::Writer, v: char) -> fmt::Result {
     let mut buf = [0; 4];
     let n = v.encode_utf8(&mut buf).unwrap();
-    let buf = unsafe { str::from_utf8_unchecked(&buf[0..n]) };
+    let buf = unsafe { str::from_utf8_unchecked(&buf[..n]) };
     escape_str(writer, buf)
 }
 
@@ -414,7 +414,7 @@ fn spaces(wr: &mut fmt::Writer, mut n: uint) -> fmt::Result {
     }
 
     if n > 0 {
-        wr.write_str(&BUF[0..n])
+        wr.write_str(&BUF[..n])
     } else {
         Ok(())
     }
index c3bdfbb12d88d46a1e97c7cca365389a0a82d818..80ae3076df37a6ca7fd882e2347afdae4fff5d0b 100644 (file)
@@ -20,7 +20,7 @@
 use default::Default;
 use fmt::{self, Show};
 use hash::{self, Hash, SipHasher};
-use iter::{self, Iterator, IteratorExt, FromIterator, Extend, Map};
+use iter::{self, Iterator, ExactSizeIterator, IteratorExt, FromIterator, Extend, Map};
 use marker::Sized;
 use mem::{self, replace};
 use num::{Int, UnsignedInt};
@@ -1384,7 +1384,11 @@ impl<'a, K, V> Iterator for Iter<'a, K, V> {
     type Item = (&'a K, &'a V);
 
     #[inline] fn next(&mut self) -> Option<(&'a K, &'a V)> { self.inner.next() }
-    #[inline] fn size_hint(&self) -> (uint, Option<uint>) { self.inner.size_hint() }
+    #[inline] fn size_hint(&self) -> (usize, Option<usize>) { self.inner.size_hint() }
+}
+#[stable]
+impl<'a, K, V> ExactSizeIterator for Iter<'a, K, V> {
+    #[inline] fn len(&self) -> usize { self.inner.len() }
 }
 
 #[stable]
@@ -1392,7 +1396,11 @@ impl<'a, K, V> Iterator for IterMut<'a, K, V> {
     type Item = (&'a K, &'a mut V);
 
     #[inline] fn next(&mut self) -> Option<(&'a K, &'a mut V)> { self.inner.next() }
-    #[inline] fn size_hint(&self) -> (uint, Option<uint>) { self.inner.size_hint() }
+    #[inline] fn size_hint(&self) -> (usize, Option<usize>) { self.inner.size_hint() }
+}
+#[stable]
+impl<'a, K, V> ExactSizeIterator for IterMut<'a, K, V> {
+    #[inline] fn len(&self) -> usize { self.inner.len() }
 }
 
 #[stable]
@@ -1400,7 +1408,11 @@ impl<K, V> Iterator for IntoIter<K, V> {
     type Item = (K, V);
 
     #[inline] fn next(&mut self) -> Option<(K, V)> { self.inner.next() }
-    #[inline] fn size_hint(&self) -> (uint, Option<uint>) { self.inner.size_hint() }
+    #[inline] fn size_hint(&self) -> (usize, Option<usize>) { self.inner.size_hint() }
+}
+#[stable]
+impl<K, V> ExactSizeIterator for IntoIter<K, V> {
+    #[inline] fn len(&self) -> usize { self.inner.len() }
 }
 
 #[stable]
@@ -1408,7 +1420,11 @@ impl<'a, K, V> Iterator for Keys<'a, K, V> {
     type Item = &'a K;
 
     #[inline] fn next(&mut self) -> Option<(&'a K)> { self.inner.next() }
-    #[inline] fn size_hint(&self) -> (uint, Option<uint>) { self.inner.size_hint() }
+    #[inline] fn size_hint(&self) -> (usize, Option<usize>) { self.inner.size_hint() }
+}
+#[stable]
+impl<'a, K, V> ExactSizeIterator for Keys<'a, K, V> {
+    #[inline] fn len(&self) -> usize { self.inner.len() }
 }
 
 #[stable]
@@ -1416,21 +1432,23 @@ impl<'a, K, V> Iterator for Values<'a, K, V> {
     type Item = &'a V;
 
     #[inline] fn next(&mut self) -> Option<(&'a V)> { self.inner.next() }
-    #[inline] fn size_hint(&self) -> (uint, Option<uint>) { self.inner.size_hint() }
+    #[inline] fn size_hint(&self) -> (usize, Option<usize>) { self.inner.size_hint() }
+}
+#[stable]
+impl<'a, K, V> ExactSizeIterator for Values<'a, K, V> {
+    #[inline] fn len(&self) -> usize { self.inner.len() }
 }
 
 #[stable]
-impl<'a, K: 'a, V: 'a> Iterator for Drain<'a, K, V> {
+impl<'a, K, V> Iterator for Drain<'a, K, V> {
     type Item = (K, V);
 
-    #[inline]
-    fn next(&mut self) -> Option<(K, V)> {
-        self.inner.next()
-    }
-    #[inline]
-    fn size_hint(&self) -> (uint, Option<uint>) {
-        self.inner.size_hint()
-    }
+    #[inline] fn next(&mut self) -> Option<(K, V)> { self.inner.next() }
+    #[inline] fn size_hint(&self) -> (usize, Option<usize>) { self.inner.size_hint() }
+}
+#[stable]
+impl<'a, K, V> ExactSizeIterator for Drain<'a, K, V> {
+    #[inline] fn len(&self) -> usize { self.inner.len() }
 }
 
 #[unstable = "matches collection reform v2 specification, waiting for dust to settle"]
@@ -2135,6 +2153,19 @@ fn test_size_hint() {
         assert_eq!(iter.size_hint(), (3, Some(3)));
     }
 
+    #[test]
+    fn test_iter_len() {
+        let xs = [(1i, 1i), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6)];
+
+        let map: HashMap<int, int> = xs.iter().map(|&x| x).collect();
+
+        let mut iter = map.iter();
+
+        for _ in iter.by_ref().take(3) {}
+
+        assert_eq!(iter.len(), 3);
+    }
+
     #[test]
     fn test_mut_size_hint() {
         let xs = [(1i, 1i), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6)];
@@ -2148,6 +2179,19 @@ fn test_mut_size_hint() {
         assert_eq!(iter.size_hint(), (3, Some(3)));
     }
 
+    #[test]
+    fn test_iter_mut_len() {
+        let xs = [(1i, 1i), (2, 2), (3, 3), (4, 4), (5, 5), (6, 6)];
+
+        let mut map: HashMap<int, int> = xs.iter().map(|&x| x).collect();
+
+        let mut iter = map.iter_mut();
+
+        for _ in iter.by_ref().take(3) {}
+
+        assert_eq!(iter.len(), 3);
+    }
+
     #[test]
     fn test_index() {
         let mut map: HashMap<int, int> = HashMap::new();
index 4003d3addf13949f74b415521b188f9b6edd587e..1293f45161d78c2e25bb6bb2af76387710491502 100644 (file)
@@ -18,7 +18,7 @@
 use fmt::Show;
 use fmt;
 use hash::{self, Hash};
-use iter::{Iterator, IteratorExt, FromIterator, Map, Chain, Extend};
+use iter::{Iterator, ExactSizeIterator, IteratorExt, FromIterator, Map, Chain, Extend};
 use ops::{BitOr, BitAnd, BitXor, Sub};
 use option::Option::{Some, None, self};
 
@@ -837,7 +837,11 @@ impl<'a, K> Iterator for Iter<'a, K> {
     type Item = &'a K;
 
     fn next(&mut self) -> Option<&'a K> { self.iter.next() }
-    fn size_hint(&self) -> (uint, Option<uint>) { self.iter.size_hint() }
+    fn size_hint(&self) -> (usize, Option<usize>) { self.iter.size_hint() }
+}
+#[stable]
+impl<'a, K> ExactSizeIterator for Iter<'a, K> {
+    fn len(&self) -> usize { self.iter.len() }
 }
 
 #[stable]
@@ -845,15 +849,23 @@ impl<K> Iterator for IntoIter<K> {
     type Item = K;
 
     fn next(&mut self) -> Option<K> { self.iter.next() }
-    fn size_hint(&self) -> (uint, Option<uint>) { self.iter.size_hint() }
+    fn size_hint(&self) -> (usize, Option<usize>) { self.iter.size_hint() }
+}
+#[stable]
+impl<K> ExactSizeIterator for IntoIter<K> {
+    fn len(&self) -> usize { self.iter.len() }
 }
 
 #[stable]
-impl<'a, K: 'a> Iterator for Drain<'a, K> {
+impl<'a, K> Iterator for Drain<'a, K> {
     type Item = K;
 
     fn next(&mut self) -> Option<K> { self.iter.next() }
-    fn size_hint(&self) -> (uint, Option<uint>) { self.iter.size_hint() }
+    fn size_hint(&self) -> (usize, Option<usize>) { self.iter.size_hint() }
+}
+#[stable]
+impl<'a, K> ExactSizeIterator for Drain<'a, K> {
+    fn len(&self) -> usize { self.iter.len() }
 }
 
 #[stable]
@@ -875,7 +887,7 @@ fn next(&mut self) -> Option<&'a T> {
         }
     }
 
-    fn size_hint(&self) -> (uint, Option<uint>) {
+    fn size_hint(&self) -> (usize, Option<usize>) {
         let (_, upper) = self.iter.size_hint();
         (0, upper)
     }
@@ -900,7 +912,7 @@ fn next(&mut self) -> Option<&'a T> {
         }
     }
 
-    fn size_hint(&self) -> (uint, Option<uint>) {
+    fn size_hint(&self) -> (usize, Option<usize>) {
         let (_, upper) = self.iter.size_hint();
         (0, upper)
     }
@@ -915,7 +927,7 @@ impl<'a, T, S, H> Iterator for SymmetricDifference<'a, T, S>
     type Item = &'a T;
 
     fn next(&mut self) -> Option<&'a T> { self.iter.next() }
-    fn size_hint(&self) -> (uint, Option<uint>) { self.iter.size_hint() }
+    fn size_hint(&self) -> (usize, Option<usize>) { self.iter.size_hint() }
 }
 
 #[stable]
@@ -927,7 +939,7 @@ impl<'a, T, S, H> Iterator for Union<'a, T, S>
     type Item = &'a T;
 
     fn next(&mut self) -> Option<&'a T> { self.iter.next() }
-    fn size_hint(&self) -> (uint, Option<uint>) { self.iter.size_hint() }
+    fn size_hint(&self) -> (usize, Option<usize>) { self.iter.size_hint() }
 }
 
 #[cfg(test)]
index 456f3763b39162d523fe1ab646715fa6c1a2ded7..f28b95dbe95c4b64a605e434116c432693ae5aa2 100644 (file)
@@ -15,7 +15,7 @@
 use clone::Clone;
 use cmp;
 use hash::{Hash, Hasher};
-use iter::{Iterator, count};
+use iter::{Iterator, ExactSizeIterator, count};
 use marker::{Copy, Sized, self};
 use mem::{min_align_of, size_of};
 use mem;
@@ -838,10 +838,13 @@ fn next(&mut self) -> Option<(&'a K, &'a V)> {
         })
     }
 
-    fn size_hint(&self) -> (uint, Option<uint>) {
+    fn size_hint(&self) -> (usize, Option<usize>) {
         (self.elems_left, Some(self.elems_left))
     }
 }
+impl<'a, K, V> ExactSizeIterator for Iter<'a, K, V> {
+    fn len(&self) -> usize { self.elems_left }
+}
 
 impl<'a, K, V> Iterator for IterMut<'a, K, V> {
     type Item = (&'a K, &'a mut V);
@@ -856,10 +859,13 @@ fn next(&mut self) -> Option<(&'a K, &'a mut V)> {
         })
     }
 
-    fn size_hint(&self) -> (uint, Option<uint>) {
+    fn size_hint(&self) -> (usize, Option<usize>) {
         (self.elems_left, Some(self.elems_left))
     }
 }
+impl<'a, K, V> ExactSizeIterator for IterMut<'a, K, V> {
+    fn len(&self) -> usize { self.elems_left }
+}
 
 impl<K, V> Iterator for IntoIter<K, V> {
     type Item = (SafeHash, K, V);
@@ -879,13 +885,16 @@ fn next(&mut self) -> Option<(SafeHash, K, V)> {
         })
     }
 
-    fn size_hint(&self) -> (uint, Option<uint>) {
+    fn size_hint(&self) -> (usize, Option<usize>) {
         let size = self.table.size();
         (size, Some(size))
     }
 }
+impl<K, V> ExactSizeIterator for IntoIter<K, V> {
+    fn len(&self) -> usize { self.table.size() }
+}
 
-impl<'a, K: 'a, V: 'a> Iterator for Drain<'a, K, V> {
+impl<'a, K, V> Iterator for Drain<'a, K, V> {
     type Item = (SafeHash, K, V);
 
     #[inline]
@@ -904,11 +913,14 @@ fn next(&mut self) -> Option<(SafeHash, K, V)> {
         })
     }
 
-    fn size_hint(&self) -> (uint, Option<uint>) {
+    fn size_hint(&self) -> (usize, Option<usize>) {
         let size = self.table.size();
         (size, Some(size))
     }
 }
+impl<'a, K, V> ExactSizeIterator for Drain<'a, K, V> {
+    fn len(&self) -> usize { self.table.size() }
+}
 
 #[unsafe_destructor]
 impl<'a, K: 'a, V: 'a> Drop for Drain<'a, K, V> {
index 36def48b88b324d633453d236b624874bf1e895d..8c38bc009cc63058aeaf82fffb54a18eed15cd1d 100644 (file)
@@ -15,7 +15,7 @@
 use cmp;
 use fmt;
 use io::{Reader, Writer, Stream, Buffer, DEFAULT_BUF_SIZE, IoResult};
-use iter::{IteratorExt, ExactSizeIterator};
+use iter::{IteratorExt, ExactSizeIterator, repeat};
 use ops::Drop;
 use option::Option;
 use option::Option::{Some, None};
@@ -62,17 +62,11 @@ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
 impl<R: Reader> BufferedReader<R> {
     /// Creates a new `BufferedReader` with the specified buffer capacity
     pub fn with_capacity(cap: uint, inner: R) -> BufferedReader<R> {
-        // It's *much* faster to create an uninitialized buffer than it is to
-        // fill everything in with 0. This buffer is entirely an implementation
-        // detail and is never exposed, so we're safe to not initialize
-        // everything up-front. This allows creation of BufferedReader instances
-        // to be very cheap (large mallocs are not nearly as expensive as large
-        // callocs).
-        let mut buf = Vec::with_capacity(cap);
-        unsafe { buf.set_len(cap); }
         BufferedReader {
             inner: inner,
-            buf: buf,
+            // We can't use the same trick here as we do for BufferedWriter,
+            // since this memory is visible to the inner Reader.
+            buf: repeat(0).take(cap).collect(),
             pos: 0,
             cap: 0,
         }
@@ -122,7 +116,7 @@ fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> {
         let nread = {
             let available = try!(self.fill_buf());
             let nread = cmp::min(available.len(), buf.len());
-            slice::bytes::copy_memory(buf, &available[0..nread]);
+            slice::bytes::copy_memory(buf, &available[..nread]);
             nread
         };
         self.pos += nread;
@@ -166,7 +160,12 @@ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
 impl<W: Writer> BufferedWriter<W> {
     /// Creates a new `BufferedWriter` with the specified buffer capacity
     pub fn with_capacity(cap: uint, inner: W) -> BufferedWriter<W> {
-        // See comments in BufferedReader for why this uses unsafe code.
+        // It's *much* faster to create an uninitialized buffer than it is to
+        // fill everything in with 0. This buffer is entirely an implementation
+        // detail and is never exposed, so we're safe to not initialize
+        // everything up-front. This allows creation of BufferedWriter instances
+        // to be very cheap (large mallocs are not nearly as expensive as large
+        // callocs).
         let mut buf = Vec::with_capacity(cap);
         unsafe { buf.set_len(cap); }
         BufferedWriter {
@@ -183,7 +182,7 @@ pub fn new(inner: W) -> BufferedWriter<W> {
 
     fn flush_buf(&mut self) -> IoResult<()> {
         if self.pos != 0 {
-            let ret = self.inner.as_mut().unwrap().write(&self.buf[0..self.pos]);
+            let ret = self.inner.as_mut().unwrap().write(&self.buf[..self.pos]);
             self.pos = 0;
             ret
         } else {
@@ -282,7 +281,7 @@ impl<W: Writer> Writer for LineBufferedWriter<W> {
     fn write(&mut self, buf: &[u8]) -> IoResult<()> {
         match buf.iter().rposition(|&b| b == b'\n') {
             Some(i) => {
-                try!(self.inner.write(&buf[0..(i + 1)]));
+                try!(self.inner.write(&buf[..(i + 1)]));
                 try!(self.inner.flush());
                 try!(self.inner.write(&buf[(i + 1)..]));
                 Ok(())
index b578f4d5adcba81f5f84491abf8b60fa54256414..4b0014c68f7a84289cd17be9d6ff93a986b031e3 100644 (file)
@@ -90,7 +90,7 @@ fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> {
                 Some(src) => {
                     let dst = buf.slice_from_mut(num_read);
                     let count = cmp::min(src.len(), dst.len());
-                    bytes::copy_memory(dst, &src[0..count]);
+                    bytes::copy_memory(dst, &src[..count]);
                     count
                 },
                 None => 0,
index dbccc81c4cc72ea45a5fa218c43de82d4453259a..64406d88253a775305fb03749efe875c3c4d0bb9 100644 (file)
@@ -889,7 +889,7 @@ fn file_test_io_smoke_test() {
             let mut read_buf = [0; 1028];
             let read_str = match check!(read_stream.read(&mut read_buf)) {
                 -1|0 => panic!("shouldn't happen"),
-                n => str::from_utf8(&read_buf[0..n]).unwrap().to_string()
+                n => str::from_utf8(&read_buf[..n]).unwrap().to_string()
             };
             assert_eq!(read_str.as_slice(), message);
         }
index c5e289398e0466bc5faa2fa9a2f5da4feb8b516a..ee05a9e55964eb527421eca7707422f55d73b18e 100644 (file)
@@ -204,7 +204,7 @@ fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> {
 
         let write_len = min(buf.len(), self.len());
         {
-            let input = &self[0..write_len];
+            let input = &self[..write_len];
             let output = buf.slice_to_mut(write_len);
             slice::bytes::copy_memory(output, input);
         }
@@ -286,7 +286,7 @@ fn write(&mut self, src: &[u8]) -> IoResult<()> {
 
             Ok(())
         } else {
-            slice::bytes::copy_memory(dst, &src[0..dst_len]);
+            slice::bytes::copy_memory(dst, &src[..dst_len]);
 
             self.pos += dst_len;
 
@@ -498,7 +498,7 @@ fn test_mem_reader() {
         assert_eq!(buf, b);
         assert_eq!(reader.read(&mut buf), Ok(3));
         let b: &[_] = &[5, 6, 7];
-        assert_eq!(&buf[0..3], b);
+        assert_eq!(&buf[..3], b);
         assert!(reader.read(&mut buf).is_err());
         let mut reader = MemReader::new(vec!(0, 1, 2, 3, 4, 5, 6, 7));
         assert_eq!(reader.read_until(3).unwrap(), vec!(0, 1, 2, 3));
@@ -524,7 +524,7 @@ fn test_slice_reader() {
         assert_eq!(buf.as_slice(), b);
         assert_eq!(reader.read(&mut buf), Ok(3));
         let b: &[_] = &[5, 6, 7];
-        assert_eq!(&buf[0..3], b);
+        assert_eq!(&buf[..3], b);
         assert!(reader.read(&mut buf).is_err());
         let mut reader = &mut in_buf.as_slice();
         assert_eq!(reader.read_until(3).unwrap(), vec!(0, 1, 2, 3));
@@ -551,7 +551,7 @@ fn test_buf_reader() {
         assert_eq!(buf, b);
         assert_eq!(reader.read(&mut buf), Ok(3));
         let b: &[_] = &[5, 6, 7];
-        assert_eq!(&buf[0..3], b);
+        assert_eq!(&buf[..3], b);
         assert!(reader.read(&mut buf).is_err());
         let mut reader = BufReader::new(in_buf.as_slice());
         assert_eq!(reader.read_until(3).unwrap(), vec!(0, 1, 2, 3));
index 3968dda2a82026051a4687abf6a487314a63fa1b..bab4dafd090bdfc40ec6f90f5c2072744d16835d 100644 (file)
@@ -1069,7 +1069,7 @@ fn write_line(&mut self, s: &str) -> IoResult<()> {
     fn write_char(&mut self, c: char) -> IoResult<()> {
         let mut buf = [0u8; 4];
         let n = c.encode_utf8(buf.as_mut_slice()).unwrap_or(0);
-        self.write(&buf[0..n])
+        self.write(&buf[..n])
     }
 
     /// Write the result of passing n through `int::to_str_bytes`.
@@ -1454,7 +1454,7 @@ fn read_until(&mut self, byte: u8) -> IoResult<Vec<u8>> {
                 };
                 match available.iter().position(|&b| b == byte) {
                     Some(i) => {
-                        res.push_all(&available[0..(i + 1)]);
+                        res.push_all(&available[..(i + 1)]);
                         used = i + 1;
                         break
                     }
@@ -1493,7 +1493,7 @@ fn read_char(&mut self) -> IoResult<char> {
                 }
             }
         }
-        match str::from_utf8(&buf[0..width]).ok() {
+        match str::from_utf8(&buf[..width]).ok() {
             Some(s) => Ok(s.char_at(0)),
             None => Err(standard_error(InvalidInput))
         }
index d09afea94dcc1023827c4157f49062bd69e04195..adc122ff44741114d1337442addff67b03560714 100644 (file)
@@ -313,7 +313,7 @@ fn ipv6_addr_from_head_tail(head: &[u16], tail: &[u16]) -> IpAddr {
 
         let mut tail = [0u16; 8];
         let (tail_size, _) = read_groups(self, &mut tail, 8 - head_size);
-        Some(ipv6_addr_from_head_tail(&head[0..head_size], &tail[0..tail_size]))
+        Some(ipv6_addr_from_head_tail(&head[..head_size], &tail[..tail_size]))
     }
 
     fn read_ipv6_addr(&mut self) -> Option<IpAddr> {
index 67c14dc2dc12de381fc4f380070446f95e5c855f..6de466eb20bfc9a51f3471700256b5cc5308e665 100644 (file)
 use libc;
 use os;
 use std::io::net::ip::*;
-use sync::atomic::{AtomicUint, ATOMIC_UINT_INIT, Ordering};
+use sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering};
 
 /// Get a port number, starting at 9600, for use in tests
 pub fn next_test_port() -> u16 {
-    static NEXT_OFFSET: AtomicUint = ATOMIC_UINT_INIT;
+    static NEXT_OFFSET: AtomicUsize = ATOMIC_USIZE_INIT;
     base_port() + NEXT_OFFSET.fetch_add(1, Ordering::Relaxed) as u16
 }
 
 // iOS has a pretty long tmpdir path which causes pipe creation
 // to like: invalid argument: path must be smaller than SUN_LEN
 fn next_test_unix_socket() -> String {
-    static COUNT: AtomicUint = ATOMIC_UINT_INIT;
+    static COUNT: AtomicUsize = ATOMIC_USIZE_INIT;
     // base port and pid are an attempt to be unique between multiple
     // test-runners of different configurations running on one
     // buildbot, the count is to be unique within this executable.
index ac7fb3f9cdb4a40ef8ed65b7711d55cebf31dd1f..adfd88644ccec6e4ec35c57efdd17c836e7b2e9c 100644 (file)
@@ -60,7 +60,7 @@ fn read(&mut self, buf: &mut [u8]) -> io::IoResult<uint> {
 impl<R: Buffer> Buffer for LimitReader<R> {
     fn fill_buf<'a>(&'a mut self) -> io::IoResult<&'a [u8]> {
         let amt = try!(self.inner.fill_buf());
-        let buf = &amt[0..cmp::min(amt.len(), self.limit)];
+        let buf = &amt[..cmp::min(amt.len(), self.limit)];
         if buf.len() == 0 {
             Err(io::standard_error(io::EndOfFile))
         } else {
@@ -223,7 +223,7 @@ pub fn into_inner(self) -> (R, W) {
 impl<R: Reader, W: Writer> Reader for TeeReader<R, W> {
     fn read(&mut self, buf: &mut [u8]) -> io::IoResult<uint> {
         self.reader.read(buf).and_then(|len| {
-            self.writer.write(&mut buf[0..len]).map(|()| len)
+            self.writer.write(&mut buf[..len]).map(|()| len)
         })
     }
 }
@@ -237,7 +237,7 @@ pub fn copy<R: Reader, W: Writer>(r: &mut R, w: &mut W) -> io::IoResult<()> {
             Err(ref e) if e.kind == io::EndOfFile => return Ok(()),
             Err(e) => return Err(e),
         };
-        try!(w.write(&buf[0..len]));
+        try!(w.write(&buf[..len]));
     }
 }
 
index e15e611adc08cfc8aacc743886e77656773e1f83..03d9030b02517733b41c2e219847d8e62015760d 100644 (file)
@@ -73,7 +73,7 @@
 //!
 //! ## Concurrency, I/O, and the runtime
 //!
-//! The [`task`](task/index.html) module contains Rust's threading abstractions,
+//! The [`thread`](thread/index.html) module contains Rust's threading abstractions,
 //! while [`comm`](comm/index.html) contains the channel types for message
 //! passing. [`sync`](sync/index.html) contains further, primitive, shared
 //! memory types, including [`atomic`](sync/atomic/index.html).
index 6e3949b9e22d0efe26678e21fd01935bcc920214..fc0c838a3f11800418dce248a4c98c951be7f81c 100644 (file)
@@ -54,7 +54,7 @@
 use slice::{AsSlice, SliceExt};
 use str::{Str, StrExt};
 use string::{String, ToString};
-use sync::atomic::{AtomicInt, ATOMIC_INT_INIT, Ordering};
+use sync::atomic::{AtomicIsize, ATOMIC_ISIZE_INIT, Ordering};
 use vec::Vec;
 
 #[cfg(unix)] use ffi::{self, CString};
@@ -590,7 +590,7 @@ pub fn last_os_error() -> String {
     error_string(errno() as uint)
 }
 
-static EXIT_STATUS: AtomicInt = ATOMIC_INT_INIT;
+static EXIT_STATUS: AtomicIsize = ATOMIC_ISIZE_INIT;
 
 /// Sets the process exit code
 ///
@@ -1422,6 +1422,11 @@ mod arch_consts {
     pub const ARCH: &'static str = "mipsel";
 }
 
+#[cfg(target_arch = "powerpc")]
+mod arch_consts {
+    pub const ARCH: &'static str = "powerpc";
+}
+
 #[cfg(test)]
 mod tests {
     use prelude::v1::*;
index 1ec7b6b3edcbbd4c351c0d4b4eb1870246314ef2..541f1e7714070584dd0bf49046af9d6a9dba55a0 100644 (file)
@@ -352,7 +352,7 @@ fn filestem<'a>(&'a self) -> Option<&'a [u8]> {
                 match name.rposition_elem(&dot) {
                     None | Some(0) => name,
                     Some(1) if name == b".." => name,
-                    Some(pos) => &name[0..pos]
+                    Some(pos) => &name[..pos]
                 }
             })
         }
@@ -475,7 +475,7 @@ fn set_extension<T: BytesContainer>(&mut self, extension: T) {
             let extlen = extension.container_as_bytes().len();
             match (name.rposition_elem(&dot), extlen) {
                 (None, 0) | (Some(0), 0) => None,
-                (Some(idx), 0) => Some(name[0..idx].to_vec()),
+                (Some(idx), 0) => Some(name[..idx].to_vec()),
                 (idx, extlen) => {
                     let idx = match idx {
                         None | Some(0) => name.len(),
@@ -484,7 +484,7 @@ fn set_extension<T: BytesContainer>(&mut self, extension: T) {
 
                     let mut v;
                     v = Vec::with_capacity(idx + extlen + 1);
-                    v.push_all(&name[0..idx]);
+                    v.push_all(&name[..idx]);
                     v.push(dot);
                     v.push_all(extension.container_as_bytes());
                     Some(v)
index 293696d5ccada853d2393f525e3460527d3fa89e..aab64639ab5903865a180c74dc2715d88e71e10d 100644 (file)
@@ -136,7 +136,7 @@ unsafe fn set_filename_unchecked<T: BytesContainer>(&mut self, filename: T) {
             }
             Some(idx) => {
                 let mut v = Vec::with_capacity(idx + 1 + filename.len());
-                v.push_all(&self.repr[0..(idx+1)]);
+                v.push_all(&self.repr[..(idx+1)]);
                 v.push_all(filename);
                 // FIXME: this is slow
                 self.repr = Path::normalize(v.as_slice());
@@ -177,9 +177,9 @@ fn dirname<'a>(&'a self) -> &'a [u8] {
         match self.sepidx {
             None if b".." == self.repr => self.repr.as_slice(),
             None => dot_static,
-            Some(0) => &self.repr[0..1],
+            Some(0) => &self.repr[..1],
             Some(idx) if &self.repr[(idx+1)..] == b".." => self.repr.as_slice(),
-            Some(idx) => &self.repr[0..idx]
+            Some(idx) => &self.repr[..idx]
         }
     }
 
index 2a1f1794e49e7c059342940d02c006b9f17fffd7..3cff1c67be3684ed07c810d4ec69f17ff9eabaa9 100644 (file)
@@ -180,20 +180,20 @@ unsafe fn set_filename_unchecked<T: BytesContainer>(&mut self, filename: T) {
             }
             Some((_,idxa,end)) if &self.repr[idxa..end] == ".." => {
                 let mut s = String::with_capacity(end + 1 + filename.len());
-                s.push_str(&self.repr[0..end]);
+                s.push_str(&self.repr[..end]);
                 s.push(SEP);
                 s.push_str(filename);
                 self.update_normalized(&s[]);
             }
             Some((idxb,idxa,_)) if self.prefix == Some(DiskPrefix) && idxa == self.prefix_len() => {
                 let mut s = String::with_capacity(idxb + filename.len());
-                s.push_str(&self.repr[0..idxb]);
+                s.push_str(&self.repr[..idxb]);
                 s.push_str(filename);
                 self.update_normalized(&s[]);
             }
             Some((idxb,_,_)) => {
                 let mut s = String::with_capacity(idxb + 1 + filename.len());
-                s.push_str(&self.repr[0..idxb]);
+                s.push_str(&self.repr[..idxb]);
                 s.push(SEP);
                 s.push_str(filename);
                 self.update_normalized(&s[]);
@@ -350,13 +350,13 @@ fn dirname_str<'a>(&'a self) -> Option<&'a str> {
             Some((idxb,_,end)) if &self.repr[idxb..end] == "\\" => {
                 &self.repr[]
             }
-            Some((0,idxa,_)) => &self.repr[0..idxa],
+            Some((0,idxa,_)) => &self.repr[..idxa],
             Some((idxb,idxa,_)) => {
                 match self.prefix {
                     Some(DiskPrefix) | Some(VerbatimDiskPrefix) if idxb == self.prefix_len() => {
-                        &self.repr[0..idxa]
+                        &self.repr[..idxa]
                     }
-                    _ => &self.repr[0..idxb]
+                    _ => &self.repr[..idxb]
                 }
             }
         })
@@ -428,15 +428,15 @@ fn root_path(&self) -> Option<Path> {
         if self.prefix.is_some() {
             Some(Path::new(match self.prefix {
                 Some(DiskPrefix) if self.is_absolute() => {
-                    &self.repr[0..(self.prefix_len()+1)]
+                    &self.repr[..(self.prefix_len()+1)]
                 }
                 Some(VerbatimDiskPrefix) => {
-                    &self.repr[0..(self.prefix_len()+1)]
+                    &self.repr[..(self.prefix_len()+1)]
                 }
-                _ => &self.repr[0..self.prefix_len()]
+                _ => &self.repr[..self.prefix_len()]
             }))
         } else if is_vol_relative(self) {
-            Some(Path::new(&self.repr[0..1]))
+            Some(Path::new(&self.repr[..1]))
         } else {
             None
         }
@@ -683,7 +683,7 @@ fn equiv_prefix(&self, other: &Path) -> bool {
             }
             (None, None) => true,
             (a, b) if a == b => {
-                &s_repr[0..self.prefix_len()] == &o_repr[0..other.prefix_len()]
+                &s_repr[..self.prefix_len()] == &o_repr[..other.prefix_len()]
             }
             _ => false
         }
@@ -737,7 +737,7 @@ fn normalize__(s: &str, prefix: Option<PathPrefix>) -> Option<String> {
                         match prefix.unwrap() {
                             DiskPrefix => {
                                 let len = prefix_len(prefix) + is_abs as uint;
-                                let mut s = String::from_str(&s[0..len]);
+                                let mut s = String::from_str(&s[..len]);
                                 unsafe {
                                     let v = s.as_mut_vec();
                                     v[0] = (*v)[0].to_ascii_uppercase();
@@ -752,7 +752,7 @@ fn normalize__(s: &str, prefix: Option<PathPrefix>) -> Option<String> {
                             }
                             VerbatimDiskPrefix => {
                                 let len = prefix_len(prefix) + is_abs as uint;
-                                let mut s = String::from_str(&s[0..len]);
+                                let mut s = String::from_str(&s[..len]);
                                 unsafe {
                                     let v = s.as_mut_vec();
                                     v[4] = (*v)[4].to_ascii_uppercase();
@@ -762,14 +762,14 @@ fn normalize__(s: &str, prefix: Option<PathPrefix>) -> Option<String> {
                             _ => {
                                 let plen = prefix_len(prefix);
                                 if s.len() > plen {
-                                    Some(String::from_str(&s[0..plen]))
+                                    Some(String::from_str(&s[..plen]))
                                 } else { None }
                             }
                         }
                     } else if is_abs && comps.is_empty() {
                         Some(repeat(SEP).take(1).collect())
                     } else {
-                        let prefix_ = &s[0..prefix_len(prefix)];
+                        let prefix_ = &s[..prefix_len(prefix)];
                         let n = prefix_.len() +
                                 if is_abs { comps.len() } else { comps.len() - 1} +
                                 comps.iter().map(|v| v.len()).sum();
@@ -780,7 +780,7 @@ fn normalize__(s: &str, prefix: Option<PathPrefix>) -> Option<String> {
                                 s.push(':');
                             }
                             Some(VerbatimDiskPrefix) => {
-                                s.push_str(&prefix_[0..4]);
+                                s.push_str(&prefix_[..4]);
                                 s.push(prefix_.as_bytes()[4].to_ascii_uppercase() as char);
                                 s.push_str(&prefix_[5..]);
                             }
@@ -813,7 +813,7 @@ fn normalize__(s: &str, prefix: Option<PathPrefix>) -> Option<String> {
 
     fn update_sepidx(&mut self) {
         let s = if self.has_nonsemantic_trailing_slash() {
-                    &self.repr[0..(self.repr.len()-1)]
+                    &self.repr[..(self.repr.len()-1)]
                 } else { &self.repr[] };
         let sep_test: fn(char) -> bool = if !prefix_is_verbatim(self.prefix) {
             is_sep
index 60d490982db7ea284bb0c250c3a14baddff309c4..8130a6c82ec3e8c0fdae0f11b19f12c568e77692 100644 (file)
@@ -374,9 +374,13 @@ fn fill_bytes(&mut self, bytes: &mut [u8]) {
 /// `random()` can generate various types of random things, and so may require
 /// type hinting to generate the specific type you want.
 ///
+/// This function uses the thread local random number generator. This means
+/// that if you're calling `random()` in a loop, caching the generator can
+/// increase performance. An example is shown below.
+///
 /// # Examples
 ///
-/// ```rust
+/// ```
 /// use std::rand;
 ///
 /// let x = rand::random();
@@ -389,6 +393,27 @@ fn fill_bytes(&mut self, bytes: &mut [u8]) {
 ///     println!("Better lucky than good!");
 /// }
 /// ```
+///
+/// Caching the thread local random number generator:
+///
+/// ```
+/// use std::rand;
+/// use std::rand::Rng;
+///
+/// let mut v = vec![1, 2, 3];
+///
+/// for x in v.iter_mut() {
+///     *x = rand::random()
+/// }
+///
+/// // would be faster as
+///
+/// let mut rng = rand::thread_rng();
+///
+/// for x in v.iter_mut() {
+///     *x = rng.gen();
+/// }
+/// ```
 #[inline]
 pub fn random<T: Rand>() -> T {
     thread_rng().gen()
index 18d40ecd3ebe54f6e1003f1627f236a7f4790703..68ba7e1dd29e6716ab313ae576dc141df0bfc1ff 100644 (file)
@@ -32,7 +32,8 @@ mod imp {
               any(target_arch = "x86_64",
                   target_arch = "x86",
                   target_arch = "arm",
-                  target_arch = "aarch64")))]
+                  target_arch = "aarch64",
+                  target_arch = "powerpc")))]
     fn getrandom(buf: &mut [u8]) -> libc::c_long {
         extern "C" {
             fn syscall(number: libc::c_long, ...) -> libc::c_long;
@@ -44,6 +45,8 @@ fn getrandom(buf: &mut [u8]) -> libc::c_long {
         const NR_GETRANDOM: libc::c_long = 355;
         #[cfg(any(target_arch = "arm", target_arch = "aarch64"))]
         const NR_GETRANDOM: libc::c_long = 384;
+        #[cfg(target_arch = "powerpc")]
+        const NR_GETRANDOM: libc::c_long = 384;
 
         unsafe {
             syscall(NR_GETRANDOM, buf.as_mut_ptr(), buf.len(), 0u)
@@ -54,7 +57,8 @@ fn getrandom(buf: &mut [u8]) -> libc::c_long {
                   any(target_arch = "x86_64",
                       target_arch = "x86",
                       target_arch = "arm",
-                      target_arch = "aarch64"))))]
+                      target_arch = "aarch64",
+                      target_arch = "powerpc"))))]
     fn getrandom(_buf: &mut [u8]) -> libc::c_long { -1 }
 
     fn getrandom_fill_bytes(v: &mut [u8]) {
@@ -91,7 +95,8 @@ fn getrandom_next_u64() -> u64 {
               any(target_arch = "x86_64",
                   target_arch = "x86",
                   target_arch = "arm",
-                  target_arch = "aarch64")))]
+                  target_arch = "aarch64",
+                  target_arch = "powerpc")))]
     fn is_getrandom_available() -> bool {
         use sync::atomic::{AtomicBool, ATOMIC_BOOL_INIT, Ordering};
 
@@ -119,7 +124,8 @@ fn is_getrandom_available() -> bool {
                   any(target_arch = "x86_64",
                       target_arch = "x86",
                       target_arch = "arm",
-                      target_arch = "aarch64"))))]
+                      target_arch = "aarch64",
+                      target_arch = "powerpc"))))]
     fn is_getrandom_available() -> bool { false }
 
     /// A random number generator that retrieves randomness straight from
index bb0b6fe804bea4e676c0520cee80d4539c8b95e6..f2d66e1a4d765ea91545e740f35ec77305c65cd4 100644 (file)
@@ -22,7 +22,7 @@
 // For now logging is turned off by default, and this function checks to see
 // whether the magical environment variable is present to see if it's turned on.
 pub fn log_enabled() -> bool {
-    static ENABLED: atomic::AtomicInt = atomic::ATOMIC_INT_INIT;
+    static ENABLED: atomic::AtomicIsize = atomic::ATOMIC_ISIZE_INIT;
     match ENABLED.load(Ordering::SeqCst) {
         1 => return false,
         2 => return true,
index 7cc39d7d972485977c23d9e3870f6b5b2bdd48fe..dd9923307d6f0e788421a685573833f64b5cecfc 100644 (file)
@@ -81,6 +81,9 @@ pub enum _Unwind_Reason_Code {
 #[cfg(any(target_arch = "mips", target_arch = "mipsel"))]
 pub const unwinder_private_data_size: uint = 2;
 
+#[cfg(target_arch = "powerpc")]
+pub const unwinder_private_data_size: uint = 2;
+
 #[repr(C)]
 pub struct _Unwind_Exception {
     pub exception_class: _Unwind_Exception_Class,
index 4cd0b29688a708c1af3f67689a992b39c4f3e995..73b8f104c23691659f7bc484afbc6b66f29c7252 100644 (file)
@@ -83,16 +83,16 @@ struct Exception {
 //
 // For more information, see below.
 const MAX_CALLBACKS: uint = 16;
-static CALLBACKS: [atomic::AtomicUint; MAX_CALLBACKS] =
-        [atomic::ATOMIC_UINT_INIT, atomic::ATOMIC_UINT_INIT,
-         atomic::ATOMIC_UINT_INIT, atomic::ATOMIC_UINT_INIT,
-         atomic::ATOMIC_UINT_INIT, atomic::ATOMIC_UINT_INIT,
-         atomic::ATOMIC_UINT_INIT, atomic::ATOMIC_UINT_INIT,
-         atomic::ATOMIC_UINT_INIT, atomic::ATOMIC_UINT_INIT,
-         atomic::ATOMIC_UINT_INIT, atomic::ATOMIC_UINT_INIT,
-         atomic::ATOMIC_UINT_INIT, atomic::ATOMIC_UINT_INIT,
-         atomic::ATOMIC_UINT_INIT, atomic::ATOMIC_UINT_INIT];
-static CALLBACK_CNT: atomic::AtomicUint = atomic::ATOMIC_UINT_INIT;
+static CALLBACKS: [atomic::AtomicUsize; MAX_CALLBACKS] =
+        [atomic::ATOMIC_USIZE_INIT, atomic::ATOMIC_USIZE_INIT,
+         atomic::ATOMIC_USIZE_INIT, atomic::ATOMIC_USIZE_INIT,
+         atomic::ATOMIC_USIZE_INIT, atomic::ATOMIC_USIZE_INIT,
+         atomic::ATOMIC_USIZE_INIT, atomic::ATOMIC_USIZE_INIT,
+         atomic::ATOMIC_USIZE_INIT, atomic::ATOMIC_USIZE_INIT,
+         atomic::ATOMIC_USIZE_INIT, atomic::ATOMIC_USIZE_INIT,
+         atomic::ATOMIC_USIZE_INIT, atomic::ATOMIC_USIZE_INIT,
+         atomic::ATOMIC_USIZE_INIT, atomic::ATOMIC_USIZE_INIT];
+static CALLBACK_CNT: atomic::AtomicUsize = atomic::ATOMIC_USIZE_INIT;
 
 thread_local! { static PANICKING: Cell<bool> = Cell::new(false) }
 
@@ -544,7 +544,7 @@ fn begin_unwind_inner(msg: Box<Any + Send>, file_line: &(&'static str, uint)) ->
     // MAX_CALLBACKS, so we're sure to clamp it as necessary.
     let callbacks = {
         let amt = CALLBACK_CNT.load(Ordering::SeqCst);
-        &CALLBACKS[0..cmp::min(amt, MAX_CALLBACKS)]
+        &CALLBACKS[..cmp::min(amt, MAX_CALLBACKS)]
     };
     for cb in callbacks.iter() {
         match cb.load(Ordering::SeqCst) {
index c076f0a7c6ca026f494c1e26a10cab7b49cc076a..235cedcda524442959179eb13ace211a741b4b06 100644 (file)
@@ -46,7 +46,7 @@ pub fn limit_thread_creation_due_to_osx_and_valgrind() -> bool {
 }
 
 pub fn min_stack() -> uint {
-    static MIN: atomic::AtomicUint = atomic::ATOMIC_UINT_INIT;
+    static MIN: atomic::AtomicUsize = atomic::ATOMIC_USIZE_INIT;
     match MIN.load(Ordering::SeqCst) {
         0 => {}
         n => return n - 1,
@@ -131,7 +131,7 @@ struct BufWriter<'a> {
     impl<'a> fmt::Writer for BufWriter<'a> {
         fn write_str(&mut self, bytes: &str) -> fmt::Result {
             let left = self.buf.slice_from_mut(self.pos);
-            let to_write = &bytes.as_bytes()[0..cmp::min(bytes.len(), left.len())];
+            let to_write = &bytes.as_bytes()[..cmp::min(bytes.len(), left.len())];
             slice::bytes::copy_memory(left, to_write);
             self.pos += to_write.len();
             Ok(())
@@ -142,58 +142,8 @@ fn write_str(&mut self, bytes: &str) -> fmt::Result {
     let mut msg = [0u8; 512];
     let mut w = BufWriter { buf: &mut msg, pos: 0 };
     let _ = write!(&mut w, "{}", args);
-    let msg = str::from_utf8(&w.buf[0..w.pos]).unwrap_or("aborted");
+    let msg = str::from_utf8(&w.buf[..w.pos]).unwrap_or("aborted");
     let msg = if msg.is_empty() {"aborted"} else {msg};
-
-    // Give some context to the message
-    let hash = msg.bytes().fold(0, |accum, val| accum + (val as uint) );
-    let quote = match hash % 10 {
-        0 => "
-It was from the artists and poets that the pertinent answers came, and I
-know that panic would have broken loose had they been able to compare notes.
-As it was, lacking their original letters, I half suspected the compiler of
-having asked leading questions, or of having edited the correspondence in
-corroboration of what he had latently resolved to see.",
-        1 => "
-There are not many persons who know what wonders are opened to them in the
-stories and visions of their youth; for when as children we listen and dream,
-we think but half-formed thoughts, and when as men we try to remember, we are
-dulled and prosaic with the poison of life. But some of us awake in the night
-with strange phantasms of enchanted hills and gardens, of fountains that sing
-in the sun, of golden cliffs overhanging murmuring seas, of plains that stretch
-down to sleeping cities of bronze and stone, and of shadowy companies of heroes
-that ride caparisoned white horses along the edges of thick forests; and then
-we know that we have looked back through the ivory gates into that world of
-wonder which was ours before we were wise and unhappy.",
-        2 => "
-Instead of the poems I had hoped for, there came only a shuddering blackness
-and ineffable loneliness; and I saw at last a fearful truth which no one had
-ever dared to breathe before — the unwhisperable secret of secrets — The fact
-that this city of stone and stridor is not a sentient perpetuation of Old New
-York as London is of Old London and Paris of Old Paris, but that it is in fact
-quite dead, its sprawling body imperfectly embalmed and infested with queer
-animate things which have nothing to do with it as it was in life.",
-        3 => "
-The ocean ate the last of the land and poured into the smoking gulf, thereby
-giving up all it had ever conquered. From the new-flooded lands it flowed
-again, uncovering death and decay; and from its ancient and immemorial bed it
-trickled loathsomely, uncovering nighted secrets of the years when Time was
-young and the gods unborn. Above the waves rose weedy remembered spires. The
-moon laid pale lilies of light on dead London, and Paris stood up from its damp
-grave to be sanctified with star-dust. Then rose spires and monoliths that were
-weedy but not remembered; terrible spires and monoliths of lands that men never
-knew were lands...",
-        4 => "
-There was a night when winds from unknown spaces whirled us irresistibly into
-limitless vacuum beyond all thought and entity. Perceptions of the most
-maddeningly untransmissible sort thronged upon us; perceptions of infinity
-which at the time convulsed us with joy, yet which are now partly lost to my
-memory and partly incapable of presentation to others.",
-        _ => "You've met with a terrible fate, haven't you?"
-    };
-    rterrln!("{}", "");
-    rterrln!("{}", quote);
-    rterrln!("{}", "");
     rterrln!("fatal runtime error: {}", msg);
     unsafe { intrinsics::abort(); }
 }
index 3c0ae71255dbe39632a8485ee04836e793bf832d..bcd5f56a353792790e6467a5835e0987a03ba63a 100644 (file)
@@ -10,7 +10,7 @@
 
 use prelude::v1::*;
 
-use sync::atomic::{AtomicUint, Ordering, ATOMIC_UINT_INIT};
+use sync::atomic::{AtomicUsize, Ordering, ATOMIC_USIZE_INIT};
 use sync::poison::{self, LockResult};
 use sys_common::condvar as sys;
 use sys_common::mutex as sys_mutex;
@@ -78,7 +78,7 @@ unsafe impl Sync for Condvar {}
 #[unstable = "may be merged with Condvar in the future"]
 pub struct StaticCondvar {
     inner: sys::Condvar,
-    mutex: AtomicUint,
+    mutex: AtomicUsize,
 }
 
 unsafe impl Send for StaticCondvar {}
@@ -88,7 +88,7 @@ unsafe impl Sync for StaticCondvar {}
 #[unstable = "may be merged with Condvar in the future"]
 pub const CONDVAR_INIT: StaticCondvar = StaticCondvar {
     inner: sys::CONDVAR_INIT,
-    mutex: ATOMIC_UINT_INIT,
+    mutex: ATOMIC_USIZE_INIT,
 };
 
 impl Condvar {
@@ -99,7 +99,7 @@ pub fn new() -> Condvar {
         Condvar {
             inner: box StaticCondvar {
                 inner: unsafe { sys::Condvar::new() },
-                mutex: AtomicUint::new(0),
+                mutex: AtomicUsize::new(0),
             }
         }
     }
index 5c2331d0f2e9306b97762cfe5e48fc4ddb4aef6a..ca667e65e30cc50b06868872b867761f9e22054d 100644 (file)
@@ -42,7 +42,7 @@
 use sync::mpsc::Receiver;
 use sync::mpsc::blocking::{self, SignalToken};
 use core::mem;
-use sync::atomic::{AtomicUint, Ordering};
+use sync::atomic::{AtomicUsize, Ordering};
 
 // Various states you can find a port in.
 const EMPTY: uint = 0;          // initial state: no data, no blocked reciever
@@ -56,7 +56,7 @@
 
 pub struct Packet<T> {
     // Internal state of the chan/port pair (stores the blocked task as well)
-    state: AtomicUint,
+    state: AtomicUsize,
     // One-shot data slot location
     data: Option<T>,
     // when used for the second time, a oneshot channel must be upgraded, and
@@ -93,7 +93,7 @@ pub fn new() -> Packet<T> {
         Packet {
             data: None,
             upgrade: NothingSent,
-            state: AtomicUint::new(EMPTY),
+            state: AtomicUsize::new(EMPTY),
         }
     }
 
index 4295d116aed91a48fc571a2d85ebcbffacbe06c0..c97af4c6bca3611355140f7f8ec60ef8950e2890 100644 (file)
@@ -25,7 +25,7 @@
 use core::cmp;
 use core::int;
 
-use sync::atomic::{AtomicUint, AtomicInt, AtomicBool, Ordering};
+use sync::atomic::{AtomicUsize, AtomicIsize, AtomicBool, Ordering};
 use sync::mpsc::blocking::{self, SignalToken};
 use sync::mpsc::mpsc_queue as mpsc;
 use sync::mpsc::select::StartResult::*;
 
 pub struct Packet<T> {
     queue: mpsc::Queue<T>,
-    cnt: AtomicInt, // How many items are on this channel
+    cnt: AtomicIsize, // How many items are on this channel
     steals: int, // How many times has a port received without blocking?
-    to_wake: AtomicUint, // SignalToken for wake up
+    to_wake: AtomicUsize, // SignalToken for wake up
 
     // The number of channels which are currently using this packet.
-    channels: AtomicInt,
+    channels: AtomicIsize,
 
     // See the discussion in Port::drop and the channel send methods for what
     // these are used for
     port_dropped: AtomicBool,
-    sender_drain: AtomicInt,
+    sender_drain: AtomicIsize,
 
     // this lock protects various portions of this implementation during
     // select()
@@ -70,12 +70,12 @@ impl<T: Send> Packet<T> {
     pub fn new() -> Packet<T> {
         let p = Packet {
             queue: mpsc::Queue::new(),
-            cnt: AtomicInt::new(0),
+            cnt: AtomicIsize::new(0),
             steals: 0,
-            to_wake: AtomicUint::new(0),
-            channels: AtomicInt::new(2),
+            to_wake: AtomicUsize::new(0),
+            channels: AtomicIsize::new(2),
             port_dropped: AtomicBool::new(false),
-            sender_drain: AtomicInt::new(0),
+            sender_drain: AtomicIsize::new(0),
             select_lock: Mutex::new(()),
         };
         return p;
index 46c69f6f5478927b2713374b10d4a1e276af509e..34fd6bb70dc9a94fb840a5aa6e1de187fcac757c 100644 (file)
@@ -41,7 +41,7 @@
 use core::mem;
 use core::cell::UnsafeCell;
 
-use sync::atomic::{AtomicPtr, AtomicUint, Ordering};
+use sync::atomic::{AtomicPtr, AtomicUsize, Ordering};
 
 // Node within the linked list queue of messages to send
 struct Node<T> {
@@ -69,8 +69,8 @@ pub struct Queue<T> {
     // Cache maintenance fields. Additions and subtractions are stored
     // separately in order to allow them to use nonatomic addition/subtraction.
     cache_bound: uint,
-    cache_additions: AtomicUint,
-    cache_subtractions: AtomicUint,
+    cache_additions: AtomicUsize,
+    cache_subtractions: AtomicUsize,
 }
 
 unsafe impl<T: Send> Send for Queue<T> { }
@@ -117,8 +117,8 @@ pub unsafe fn new(bound: uint) -> Queue<T> {
             first: UnsafeCell::new(n1),
             tail_copy: UnsafeCell::new(n1),
             cache_bound: bound,
-            cache_additions: AtomicUint::new(0),
-            cache_subtractions: AtomicUint::new(0),
+            cache_additions: AtomicUsize::new(0),
+            cache_subtractions: AtomicUsize::new(0),
         }
     }
 
index f4b20c7b74235613c9334d974a7636a183e89c16..a03add8c5325517286ff9a8f6162c3c2ecf6a078 100644 (file)
@@ -28,7 +28,7 @@
 use core::int;
 use thread::Thread;
 
-use sync::atomic::{AtomicInt, AtomicUint, Ordering, AtomicBool};
+use sync::atomic::{AtomicIsize, AtomicUsize, Ordering, AtomicBool};
 use sync::mpsc::Receiver;
 use sync::mpsc::blocking::{self, SignalToken};
 use sync::mpsc::spsc_queue as spsc;
@@ -42,9 +42,9 @@
 pub struct Packet<T> {
     queue: spsc::Queue<Message<T>>, // internal queue for all message
 
-    cnt: AtomicInt, // How many items are on this channel
+    cnt: AtomicIsize, // How many items are on this channel
     steals: int, // How many times has a port received without blocking?
-    to_wake: AtomicUint, // SignalToken for the blocked thread to wake up
+    to_wake: AtomicUsize, // SignalToken for the blocked thread to wake up
 
     port_dropped: AtomicBool, // flag if the channel has been destroyed.
 }
@@ -79,9 +79,9 @@ pub fn new() -> Packet<T> {
         Packet {
             queue: unsafe { spsc::Queue::new(128) },
 
-            cnt: AtomicInt::new(0),
+            cnt: AtomicIsize::new(0),
             steals: 0,
-            to_wake: AtomicUint::new(0),
+            to_wake: AtomicUsize::new(0),
 
             port_dropped: AtomicBool::new(false),
         }
index b2cc807eb111d51879b19067a357de57ce01b462..30304dffb75a52557db36710d0cb95b60db7c0e7 100644 (file)
@@ -41,7 +41,7 @@
 use vec::Vec;
 use core::mem;
 
-use sync::atomic::{Ordering, AtomicUint};
+use sync::atomic::{Ordering, AtomicUsize};
 use sync::mpsc::blocking::{self, WaitToken, SignalToken};
 use sync::mpsc::select::StartResult::{self, Installed, Abort};
 use sync::{Mutex, MutexGuard};
@@ -49,7 +49,7 @@
 pub struct Packet<T> {
     /// Only field outside of the mutex. Just done for kicks, but mainly because
     /// the other shared channel already had the code implemented
-    channels: AtomicUint,
+    channels: AtomicUsize,
 
     lock: Mutex<State<T>>,
 }
@@ -138,7 +138,7 @@ fn wakeup<T>(token: SignalToken, guard: MutexGuard<State<T>>) {
 impl<T: Send> Packet<T> {
     pub fn new(cap: uint) -> Packet<T> {
         Packet {
-            channels: AtomicUint::new(1),
+            channels: AtomicUsize::new(1),
             lock: Mutex::new(State {
                 disconnected: false,
                 blocker: NoneBlocked,
index 3bf2ae277e0df10f89913db4e0f48e4f14c6374f..6231a91833d47a3c9d0f604ad24ac30c46e8fcbd 100644 (file)
@@ -17,7 +17,7 @@
 use marker::Sync;
 use mem::drop;
 use ops::FnOnce;
-use sync::atomic::{AtomicInt, Ordering, ATOMIC_INT_INIT};
+use sync::atomic::{AtomicIsize, Ordering, ATOMIC_ISIZE_INIT};
 use sync::{StaticMutex, MUTEX_INIT};
 
 /// A synchronization primitive which can be used to run a one-time global
@@ -39,8 +39,8 @@
 #[stable]
 pub struct Once {
     mutex: StaticMutex,
-    cnt: AtomicInt,
-    lock_cnt: AtomicInt,
+    cnt: AtomicIsize,
+    lock_cnt: AtomicIsize,
 }
 
 unsafe impl Sync for Once {}
@@ -49,8 +49,8 @@ unsafe impl Sync for Once {}
 #[stable]
 pub const ONCE_INIT: Once = Once {
     mutex: MUTEX_INIT,
-    cnt: ATOMIC_INT_INIT,
-    lock_cnt: ATOMIC_INT_INIT,
+    cnt: ATOMIC_ISIZE_INIT,
+    lock_cnt: ATOMIC_ISIZE_INIT,
 };
 
 impl Once {
index ce5ab67ae613c5c66e099aa5407127b210b010ef..88bb9395cf122e9fe15c1a8790798bd26ccdf90f 100644 (file)
@@ -231,6 +231,12 @@ unsafe fn target_record_sp_limit(limit: uint) {
     unsafe fn target_record_sp_limit(_: uint) {
     }
 
+    // powerpc - FIXME(POWERPC): missing...
+    #[cfg(target_arch = "powerpc")]
+    unsafe fn target_record_sp_limit(_: uint) {
+    }
+
+
     // iOS segmented stack is disabled for now, see related notes
     #[cfg(all(target_arch = "arm", target_os = "ios"))] #[inline(always)]
     unsafe fn target_record_sp_limit(_: uint) {
@@ -326,6 +332,12 @@ unsafe fn target_get_sp_limit() -> uint {
         1024
     }
 
+    // powepc - FIXME(POWERPC): missing...
+    #[cfg(target_arch = "powerpc")]
+    unsafe fn target_get_sp_limit() -> uint {
+        1024
+    }
+
     // iOS doesn't support segmented stacks yet. This function might
     // be called by runtime though so it is unsafe to mark it as
     // unreachable, let's return a fixed constant.
index e9af796c6745c9e24599c9301528c53a336c5dd2..edd16e0c0629e3f5a50a8c7424b153a9dc979374 100644 (file)
@@ -58,7 +58,7 @@
 
 use prelude::v1::*;
 
-use sync::atomic::{self, AtomicUint, Ordering};
+use sync::atomic::{self, AtomicUsize, Ordering};
 use sync::{Mutex, Once, ONCE_INIT};
 
 use sys::thread_local as imp;
@@ -97,7 +97,7 @@ pub struct StaticKey {
 
 /// Inner contents of `StaticKey`, created by the `INIT_INNER` constant.
 pub struct StaticKeyInner {
-    key: AtomicUint,
+    key: AtomicUsize,
 }
 
 /// A type for a safely managed OS-based TLS slot.
@@ -137,7 +137,7 @@ pub struct Key {
 ///
 /// This value allows specific configuration of the destructor for a TLS key.
 pub const INIT_INNER: StaticKeyInner = StaticKeyInner {
-    key: atomic::ATOMIC_UINT_INIT,
+    key: atomic::ATOMIC_USIZE_INIT,
 };
 
 static INIT_KEYS: Once = ONCE_INIT;
index 1d523ed6eddace4426c7c710070d4d58892a18c9..fed700cc9d52a93805118d240fb0f8c3793a1860 100644 (file)
@@ -33,7 +33,9 @@
           target_os = "android"))]
 pub const FIONBIO: libc::c_ulong = 0x5421;
 #[cfg(all(target_os = "linux",
-          any(target_arch = "mips", target_arch = "mipsel")))]
+          any(target_arch = "mips",
+              target_arch = "mipsel",
+              target_arch = "powerpc")))]
 pub const FIONBIO: libc::c_ulong = 0x667e;
 
 #[cfg(any(target_os = "macos",
@@ -49,7 +51,9 @@
           target_os = "android"))]
 pub const FIOCLEX: libc::c_ulong = 0x5451;
 #[cfg(all(target_os = "linux",
-          any(target_arch = "mips", target_arch = "mipsel")))]
+          any(target_arch = "mips",
+              target_arch = "mipsel",
+              target_arch = "powerpc")))]
 pub const FIOCLEX: libc::c_ulong = 0x6601;
 
 #[cfg(any(target_os = "macos",
@@ -182,7 +186,9 @@ pub struct sigset_t {
 }
 
 #[cfg(all(target_os = "linux",
-          any(target_arch = "mips", target_arch = "mipsel")))]
+          any(target_arch = "mips",
+              target_arch = "mipsel",
+              target_arch = "powerpc")))]
 mod signal {
     use libc;
 
index 48a51813ba4ab5a44f3b55f8ca77444322eda640..45680f52e73d12c54607780c132ef70cff277c19 100644 (file)
@@ -150,6 +150,7 @@ pub unsafe fn drop_handler(handler: &mut Handler) {
               all(target_os = "linux", target_arch = "aarch64"),
               all(target_os = "linux", target_arch = "mips"), // may not match
               all(target_os = "linux", target_arch = "mipsel"), // may not match
+              all(target_os = "linux", target_arch = "powerpc"), // may not match
               target_os = "android"))] // may not match
     mod signal {
         use libc;
index fbbdee1009d5b7adefe5eaf716df9b5b12817f42..c1e3fc88794eb1751dcd22368914819fb6d0ff4b 100644 (file)
@@ -126,7 +126,8 @@ mod os {
     #[cfg(any(target_arch = "x86",
               target_arch = "arm",
               target_arch = "mips",
-              target_arch = "mipsel"))]
+              target_arch = "mipsel",
+              target_arch = "powerpc"))]
     const __SIZEOF_PTHREAD_MUTEX_T: uint = 24 - 8;
     #[cfg(target_arch = "aarch64")]
     const __SIZEOF_PTHREAD_MUTEX_T: uint = 48 - 8;
@@ -136,7 +137,8 @@ mod os {
               target_arch = "arm",
               target_arch = "aarch64",
               target_arch = "mips",
-              target_arch = "mipsel"))]
+              target_arch = "mipsel",
+              target_arch = "powerpc"))]
     const __SIZEOF_PTHREAD_COND_T: uint = 48 - 8;
 
     #[cfg(any(target_arch = "x86_64",
@@ -146,7 +148,8 @@ mod os {
     #[cfg(any(target_arch = "x86",
               target_arch = "arm",
               target_arch = "mips",
-              target_arch = "mipsel"))]
+              target_arch = "mipsel",
+              target_arch = "powerpc"))]
     const __SIZEOF_PTHREAD_RWLOCK_T: uint = 32 - 8;
 
     #[repr(C)]
index 2416b64f98f43ededa4cf99af04cd81db2063146..ac51b68795fbeb04e3b9b8f69b6374b1c4cbb1b5 100644 (file)
@@ -93,7 +93,19 @@ pub unsafe fn init() {
 
         PAGE_SIZE = psize as uint;
 
-        let stackaddr = get_stack_start();
+        let mut stackaddr = get_stack_start();
+
+        // Ensure stackaddr is page aligned! A parent process might
+        // have reset RLIMIT_STACK to be non-page aligned. The
+        // pthread_attr_getstack() reports the usable stack area
+        // stackaddr < stackaddr + stacksize, so if stackaddr is not
+        // page-aligned, calculate the fix such that stackaddr <
+        // new_page_aligned_stackaddr < stackaddr + stacksize
+        let remainder = (stackaddr as usize) % (PAGE_SIZE as usize);
+        if remainder != 0 {
+            stackaddr = ((stackaddr as usize) + (PAGE_SIZE as usize) - remainder)
+                as *mut libc::c_void;
+        }
 
         // Rellocate the last page of the stack.
         // This ensures SIGBUS will be raised on
index 62f3242a2062580360ee277bc83ce9be8cf97767..c0c231a9e7303788e74337aedbc4ab60c864cb72 100644 (file)
@@ -211,7 +211,7 @@ pub fn new() -> IoResult<Timer> {
         // instead of ()
         HELPER.boot(|| {}, helper);
 
-        static ID: atomic::AtomicUint = atomic::ATOMIC_UINT_INIT;
+        static ID: atomic::AtomicUsize = atomic::ATOMIC_USIZE_INIT;
         let id = ID.fetch_add(1, Ordering::Relaxed);
         Ok(Timer {
             id: id,
index 291a8024cfccec76080f25deccdac04b98463501..db8038006fd6a81451a3783951609bddb7f8719f 100644 (file)
@@ -27,16 +27,18 @@ pub unsafe fn new() -> Condvar { CONDVAR_INIT }
 
     #[inline]
     pub unsafe fn wait(&self, mutex: &Mutex) {
-        let r = ffi::SleepConditionVariableCS(self.inner.get(),
-                                              mutex::raw(mutex),
-                                              libc::INFINITE);
+        let r = ffi::SleepConditionVariableSRW(self.inner.get(),
+                                               mutex::raw(mutex),
+                                               libc::INFINITE,
+                                               0);
         debug_assert!(r != 0);
     }
 
     pub unsafe fn wait_timeout(&self, mutex: &Mutex, dur: Duration) -> bool {
-        let r = ffi::SleepConditionVariableCS(self.inner.get(),
-                                              mutex::raw(mutex),
-                                              dur.num_milliseconds() as DWORD);
+        let r = ffi::SleepConditionVariableSRW(self.inner.get(),
+                                               mutex::raw(mutex),
+                                               dur.num_milliseconds() as DWORD,
+                                               0);
         if r == 0 {
             const ERROR_TIMEOUT: DWORD = 0x5B4;
             debug_assert_eq!(os::errno() as uint, ERROR_TIMEOUT as uint);
index 1def99a374198d544c9e09131e8578485ef7b933..828ad795ed3b4eaa3871fb0d4c415fa79e714cab 100644 (file)
@@ -8,73 +8,51 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use prelude::v1::*;
-
-use sync::atomic::{AtomicUint, ATOMIC_UINT_INIT, Ordering};
-use alloc::{self, heap};
-
-use libc::DWORD;
+use marker::Sync;
+use cell::UnsafeCell;
 use sys::sync as ffi;
 
-const SPIN_COUNT: DWORD = 4000;
+pub struct Mutex { inner: UnsafeCell<ffi::SRWLOCK> }
 
-pub struct Mutex { inner: AtomicUint }
-
-pub const MUTEX_INIT: Mutex = Mutex { inner: ATOMIC_UINT_INIT };
+pub const MUTEX_INIT: Mutex = Mutex {
+    inner: UnsafeCell { value: ffi::SRWLOCK_INIT }
+};
 
 unsafe impl Sync for Mutex {}
 
 #[inline]
-pub unsafe fn raw(m: &Mutex) -> ffi::LPCRITICAL_SECTION {
-    m.get()
+pub unsafe fn raw(m: &Mutex) -> ffi::PSRWLOCK {
+    m.inner.get()
 }
 
+// So you might be asking why we're using SRWLock instead of CriticalSection?
+//
+// 1. SRWLock is several times faster than CriticalSection according to benchmarks performed on both
+// Windows 8 and Windows 7.
+//
+// 2. CriticalSection allows recursive locking while SRWLock deadlocks. The Unix implementation
+// deadlocks so consistency is preferred. See #19962 for more details.
+//
+// 3. While CriticalSection is fair and SRWLock is not, the current Rust policy is there there are
+// no guarantees of fairness.
+
 impl Mutex {
     #[inline]
-    pub unsafe fn new() -> Mutex {
-        Mutex { inner: AtomicUint::new(init_lock() as uint) }
-    }
+    pub unsafe fn new() -> Mutex { MUTEX_INIT }
     #[inline]
     pub unsafe fn lock(&self) {
-        ffi::EnterCriticalSection(self.get())
+        ffi::AcquireSRWLockExclusive(self.inner.get())
     }
     #[inline]
     pub unsafe fn try_lock(&self) -> bool {
-        ffi::TryEnterCriticalSection(self.get()) != 0
+        ffi::TryAcquireSRWLockExclusive(self.inner.get()) != 0
     }
     #[inline]
     pub unsafe fn unlock(&self) {
-        ffi::LeaveCriticalSection(self.get())
+        ffi::ReleaseSRWLockExclusive(self.inner.get())
     }
+    #[inline]
     pub unsafe fn destroy(&self) {
-        let lock = self.inner.swap(0, Ordering::SeqCst);
-        if lock != 0 { free_lock(lock as ffi::LPCRITICAL_SECTION) }
-    }
-
-    unsafe fn get(&self) -> ffi::LPCRITICAL_SECTION {
-        match self.inner.load(Ordering::SeqCst) {
-            0 => {}
-            n => return n as ffi::LPCRITICAL_SECTION
-        }
-        let lock = init_lock();
-        match self.inner.compare_and_swap(0, lock as uint, Ordering::SeqCst) {
-            0 => return lock as ffi::LPCRITICAL_SECTION,
-            _ => {}
-        }
-        free_lock(lock);
-        return self.inner.load(Ordering::SeqCst) as ffi::LPCRITICAL_SECTION;
+        // ...
     }
 }
-
-unsafe fn init_lock() -> ffi::LPCRITICAL_SECTION {
-    let block = heap::allocate(ffi::CRITICAL_SECTION_SIZE, 8)
-                        as ffi::LPCRITICAL_SECTION;
-    if block.is_null() { alloc::oom() }
-    ffi::InitializeCriticalSectionAndSpinCount(block, SPIN_COUNT);
-    return block;
-}
-
-unsafe fn free_lock(h: ffi::LPCRITICAL_SECTION) {
-    ffi::DeleteCriticalSection(h);
-    heap::deallocate(h as *mut _, ffi::CRITICAL_SECTION_SIZE, 8);
-}
index 064633f321c19b1ed4689258eacb60f9ff4f5e65..4540068133bd796a7e734df0cbddef4c0ac03264 100644 (file)
@@ -36,7 +36,7 @@
 pub fn truncate_utf16_at_nul<'a>(v: &'a [u16]) -> &'a [u16] {
     match v.iter().position(|c| *c == 0) {
         // don't include the 0
-        Some(i) => &v[0..i],
+        Some(i) => &v[..i],
         None => v
     }
 }
index cbca47912b511642ab309ddd1ca451ce7c7496bb..d60646b7db915cdd9e568619adf8d017b598bc6e 100644 (file)
@@ -8,17 +8,12 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use libc::{BOOL, DWORD, c_void, LPVOID};
+use libc::{BOOL, DWORD, c_void, LPVOID, c_ulong};
 use libc::types::os::arch::extra::BOOLEAN;
 
-pub type LPCRITICAL_SECTION = *mut c_void;
-pub type LPCONDITION_VARIABLE = *mut CONDITION_VARIABLE;
-pub type LPSRWLOCK = *mut SRWLOCK;
-
-#[cfg(target_arch = "x86")]
-pub const CRITICAL_SECTION_SIZE: uint = 24;
-#[cfg(target_arch = "x86_64")]
-pub const CRITICAL_SECTION_SIZE: uint = 40;
+pub type PCONDITION_VARIABLE = *mut CONDITION_VARIABLE;
+pub type PSRWLOCK = *mut SRWLOCK;
+pub type ULONG = c_ulong;
 
 #[repr(C)]
 pub struct CONDITION_VARIABLE { pub ptr: LPVOID }
@@ -31,28 +26,19 @@ pub struct SRWLOCK { pub ptr: LPVOID }
 pub const SRWLOCK_INIT: SRWLOCK = SRWLOCK { ptr: 0 as *mut _ };
 
 extern "system" {
-    // critical sections
-    pub fn InitializeCriticalSectionAndSpinCount(
-                    lpCriticalSection: LPCRITICAL_SECTION,
-                    dwSpinCount: DWORD) -> BOOL;
-    pub fn DeleteCriticalSection(lpCriticalSection: LPCRITICAL_SECTION);
-    pub fn EnterCriticalSection(lpCriticalSection: LPCRITICAL_SECTION);
-    pub fn LeaveCriticalSection(lpCriticalSection: LPCRITICAL_SECTION);
-    pub fn TryEnterCriticalSection(lpCriticalSection: LPCRITICAL_SECTION) -> BOOL;
-
     // condition variables
-    pub fn SleepConditionVariableCS(ConditionVariable: LPCONDITION_VARIABLE,
-                                    CriticalSection: LPCRITICAL_SECTION,
-                                    dwMilliseconds: DWORD) -> BOOL;
-    pub fn WakeConditionVariable(ConditionVariable: LPCONDITION_VARIABLE);
-    pub fn WakeAllConditionVariable(ConditionVariable: LPCONDITION_VARIABLE);
+    pub fn SleepConditionVariableSRW(ConditionVariable: PCONDITION_VARIABLE,
+                                     SRWLock: PSRWLOCK,
+                                     dwMilliseconds: DWORD,
+                                     Flags: ULONG) -> BOOL;
+    pub fn WakeConditionVariable(ConditionVariable: PCONDITION_VARIABLE);
+    pub fn WakeAllConditionVariable(ConditionVariable: PCONDITION_VARIABLE);
 
     // slim rwlocks
-    pub fn AcquireSRWLockExclusive(SRWLock: LPSRWLOCK);
-    pub fn AcquireSRWLockShared(SRWLock: LPSRWLOCK);
-    pub fn ReleaseSRWLockExclusive(SRWLock: LPSRWLOCK);
-    pub fn ReleaseSRWLockShared(SRWLock: LPSRWLOCK);
-    pub fn TryAcquireSRWLockExclusive(SRWLock: LPSRWLOCK) -> BOOLEAN;
-    pub fn TryAcquireSRWLockShared(SRWLock: LPSRWLOCK) -> BOOLEAN;
+    pub fn AcquireSRWLockExclusive(SRWLock: PSRWLOCK);
+    pub fn AcquireSRWLockShared(SRWLock: PSRWLOCK);
+    pub fn ReleaseSRWLockExclusive(SRWLock: PSRWLOCK);
+    pub fn ReleaseSRWLockShared(SRWLock: PSRWLOCK);
+    pub fn TryAcquireSRWLockExclusive(SRWLock: PSRWLOCK) -> BOOLEAN;
+    pub fn TryAcquireSRWLockShared(SRWLock: PSRWLOCK) -> BOOLEAN;
 }
-
index 630f7768885de6ec6097834c0b90a2a312398f6f..0ea429116b0bb86308ee7532ce1a8304016139ed 100644 (file)
@@ -747,6 +747,8 @@ pub enum Expr_ {
     /// Variable reference, possibly containing `::` and/or
     /// type parameters, e.g. foo::bar::<baz>
     ExprPath(Path),
+    /// A "qualified path", e.g. `<Vec<T> as SomeTrait>::SomeType`
+    ExprQPath(P<QPath>),
 
     ExprAddrOf(Mutability, P<Expr>),
     ExprBreak(Option<Ident>),
@@ -771,12 +773,12 @@ pub enum Expr_ {
 ///
 ///     <Vec<T> as SomeTrait>::SomeAssociatedItem
 ///      ^~~~~     ^~~~~~~~~   ^~~~~~~~~~~~~~~~~~
-///      self_type  trait_name  item_name
+///      self_type  trait_name  item_path
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show)]
 pub struct QPath {
     pub self_type: P<Ty>,
     pub trait_ref: P<TraitRef>,
-    pub item_name: Ident, // FIXME(#20301) -- should use Name
+    pub item_path: PathSegment,
 }
 
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show, Copy)]
@@ -955,7 +957,7 @@ pub fn get_span(&self) -> Span {
 pub enum Mac_ {
     // NB: the additional ident for a macro_rules-style macro is actually
     // stored in the enclosing item. Oog.
-    MacInvocTT(Path, Vec<TokenTree> , SyntaxContext),   // new macro-invocation
+    MacInvocTT(Path, Vec<TokenTree>, SyntaxContext),   // new macro-invocation
 }
 
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show, Copy)]
@@ -1528,6 +1530,19 @@ pub struct ViewItem {
     pub span: Span,
 }
 
+impl ViewItem {
+    pub fn id(&self) -> NodeId {
+        match self.node {
+            ViewItemExternCrate(_, _, id) => id,
+            ViewItemUse(ref vp) => match vp.node {
+                ViewPathSimple(_, _, id) => id,
+                ViewPathGlob(_, id) => id,
+                ViewPathList(_, _, id) => id,
+            }
+        }
+    }
+}
+
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Show)]
 pub enum ViewItem_ {
     /// Ident: name used to refer to this crate in the code
index 3ef572791752bfd7420ed17ec5b4622cda88ba45..f462a730d3aa0458099a48775522042328642d8c 100644 (file)
@@ -107,6 +107,7 @@ pub fn path_to_string<PI: Iterator<Item=PathElem>>(path: PI) -> String {
 #[derive(Copy, Show)]
 pub enum Node<'ast> {
     NodeItem(&'ast Item),
+    NodeViewItem(&'ast ViewItem),
     NodeForeignItem(&'ast ForeignItem),
     NodeTraitItem(&'ast TraitItem),
     NodeImplItem(&'ast ImplItem),
@@ -133,6 +134,7 @@ enum MapEntry<'ast> {
 
     /// All the node types, with a parent ID.
     EntryItem(NodeId, &'ast Item),
+    EntryViewItem(NodeId, &'ast ViewItem),
     EntryForeignItem(NodeId, &'ast ForeignItem),
     EntryTraitItem(NodeId, &'ast TraitItem),
     EntryImplItem(NodeId, &'ast ImplItem),
@@ -167,6 +169,7 @@ impl<'ast> MapEntry<'ast> {
     fn from_node(p: NodeId, node: Node<'ast>) -> MapEntry<'ast> {
         match node {
             NodeItem(n) => EntryItem(p, n),
+            NodeViewItem(n) => EntryViewItem(p, n),
             NodeForeignItem(n) => EntryForeignItem(p, n),
             NodeTraitItem(n) => EntryTraitItem(p, n),
             NodeImplItem(n) => EntryImplItem(p, n),
@@ -185,6 +188,7 @@ fn from_node(p: NodeId, node: Node<'ast>) -> MapEntry<'ast> {
     fn parent(self) -> Option<NodeId> {
         Some(match self {
             EntryItem(id, _) => id,
+            EntryViewItem(id, _) => id,
             EntryForeignItem(id, _) => id,
             EntryTraitItem(id, _) => id,
             EntryImplItem(id, _) => id,
@@ -204,6 +208,7 @@ fn parent(self) -> Option<NodeId> {
     fn to_node(self) -> Option<Node<'ast>> {
         Some(match self {
             EntryItem(_, n) => NodeItem(n),
+            EntryViewItem(_, n) => NodeViewItem(n),
             EntryForeignItem(_, n) => NodeForeignItem(n),
             EntryTraitItem(_, n) => NodeTraitItem(n),
             EntryImplItem(_, n) => NodeImplItem(n),
@@ -336,6 +341,13 @@ pub fn expect_item(&self, id: NodeId) -> &'ast Item {
         }
     }
 
+    pub fn expect_view_item(&self, id: NodeId) -> &'ast ViewItem {
+        match self.find(id) {
+            Some(NodeViewItem(view_item)) => view_item,
+            _ => panic!("expected view item, found {}", self.node_to_string(id))
+        }
+    }
+
     pub fn expect_struct(&self, id: NodeId) -> &'ast StructDef {
         match self.find(id) {
             Some(NodeItem(i)) => {
@@ -513,7 +525,7 @@ pub fn nodes_matching_suffix<'a>(&'a self, parts: &'a [String])
         NodesMatchingSuffix {
             map: self,
             item_name: parts.last().unwrap(),
-            in_which: &parts[0..(parts.len() - 1)],
+            in_which: &parts[..(parts.len() - 1)],
             idx: 0,
         }
     }
@@ -521,6 +533,7 @@ pub fn nodes_matching_suffix<'a>(&'a self, parts: &'a [String])
     pub fn opt_span(&self, id: NodeId) -> Option<Span> {
         let sp = match self.find(id) {
             Some(NodeItem(item)) => item.span,
+            Some(NodeViewItem(item)) => item.span,
             Some(NodeForeignItem(foreign_item)) => foreign_item.span,
             Some(NodeTraitItem(trait_method)) => {
                 match *trait_method {
@@ -813,6 +826,11 @@ fn visit_item(&mut self, i: &'ast Item) {
         self.parent = parent;
     }
 
+    fn visit_view_item(&mut self, item: &'ast ViewItem) {
+        self.insert(item.id(), NodeViewItem(item));
+        visit::walk_view_item(self, item);
+    }
+
     fn visit_pat(&mut self, pat: &'ast Pat) {
         self.insert(pat.id, match pat.node {
             // Note: this is at least *potentially* a pattern...
@@ -1018,6 +1036,7 @@ impl<'a> NodePrinter for pprust::State<'a> {
     fn print_node(&mut self, node: &Node) -> IoResult<()> {
         match *node {
             NodeItem(a)        => self.print_item(&*a),
+            NodeViewItem(a)    => self.print_view_item(&*a),
             NodeForeignItem(a) => self.print_foreign_item(&*a),
             NodeTraitItem(a)   => self.print_trait_method(&*a),
             NodeImplItem(a)    => self.print_impl_item(&*a),
@@ -1060,6 +1079,9 @@ fn node_id_to_string(map: &Map, id: NodeId, include_id: bool) -> String {
             };
             format!("{} {}{}", item_str, path_str, id_str)
         }
+        Some(NodeViewItem(item)) => {
+            format!("view item {}{}", pprust::view_item_to_string(&*item), id_str)
+        }
         Some(NodeForeignItem(item)) => {
             let path_str = map.path_to_str_with_ident(id, item.ident);
             format!("foreign item {}{}", path_str, id_str)
index 9a422e17bb4dee49fa7c36e5aed96c5239fcc05e..bf26687deededc5f370d1b2050e3d6470f5c66c0 100644 (file)
@@ -313,7 +313,7 @@ pub fn get_line(&self, line_number: uint) -> Option<String> {
             let begin = begin.to_uint();
             let slice = &self.src[begin..];
             match slice.find('\n') {
-                Some(e) => &slice[0..e],
+                Some(e) => &slice[..e],
                 None => slice
             }.to_string()
         })
index 3f81dac2b0d6224afcc608e887690a65ad140e1a..dfef52872608fcc03a82adffd30ef5e0837d746e 100644 (file)
@@ -277,7 +277,7 @@ fn print_maybe_styled(w: &mut EmitterWriter,
             // 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[0..(msg.len()-1)]));
+                try!(t.write_str(&msg[..(msg.len()-1)]));
                 try!(t.reset());
                 try!(t.write_str("\n"));
             } else {
index 9b9d8a9ceb395bf7cf0024fe3ceb17030de165f7..f2498abfa6a593439e4cef48e71fae7e3aeab59c 100644 (file)
@@ -73,6 +73,108 @@ fn expand(&self,
     }
 }
 
+#[derive(Show,Clone)]
+pub enum Annotatable {
+    Item(P<ast::Item>),
+    TraitItem(ast::TraitItem),
+    ImplItem(ast::ImplItem),
+}
+
+impl Annotatable {
+    pub fn attrs(&self) -> &[ast::Attribute] {
+        match *self {
+            Annotatable::Item(ref i) => &i.attrs[],
+            Annotatable::TraitItem(ref i) => match *i {
+                ast::TraitItem::RequiredMethod(ref tm) => &tm.attrs[],
+                ast::TraitItem::ProvidedMethod(ref m) => &m.attrs[],
+                ast::TraitItem::TypeTraitItem(ref at) => &at.attrs[],
+            },
+            Annotatable::ImplItem(ref i) => match *i {
+                ast::ImplItem::MethodImplItem(ref m) => &m.attrs[],
+                ast::ImplItem::TypeImplItem(ref t) => &t.attrs[],
+            }
+        }
+    }
+
+    pub fn fold_attrs(self, attrs: Vec<ast::Attribute>) -> Annotatable {
+        match self {
+            Annotatable::Item(i) => Annotatable::Item(P(ast::Item {
+                attrs: attrs,
+                ..(*i).clone()
+            })),
+            Annotatable::TraitItem(i) => match i {
+                ast::TraitItem::RequiredMethod(tm) => Annotatable::TraitItem(
+                    ast::TraitItem::RequiredMethod(
+                        ast::TypeMethod { attrs: attrs, ..tm })),
+                ast::TraitItem::ProvidedMethod(m) => Annotatable::TraitItem(
+                    ast::TraitItem::ProvidedMethod(P(
+                        ast::Method { attrs: attrs, ..(*m).clone() }))),
+                ast::TraitItem::TypeTraitItem(at) => Annotatable::TraitItem(
+                    ast::TraitItem::TypeTraitItem(P(
+                        ast::AssociatedType { attrs: attrs, ..(*at).clone() }))),
+            },
+            Annotatable::ImplItem(i) => match i {
+                ast::ImplItem::MethodImplItem(m) => Annotatable::ImplItem(
+                    ast::ImplItem::MethodImplItem(P(
+                        ast::Method { attrs: attrs, ..(*m).clone() }))),
+                ast::ImplItem::TypeImplItem(t) => Annotatable::ImplItem(
+                    ast::ImplItem::TypeImplItem(P(
+                        ast::Typedef { attrs: attrs, ..(*t).clone() }))),
+            }
+        }
+    }
+
+    pub fn expect_item(self) -> P<ast::Item> {
+        match self {
+            Annotatable::Item(i) => i,
+            _ => panic!("expected Item")
+        }
+    }
+
+    pub fn expect_trait_item(self) -> ast::TraitItem {
+        match self {
+            Annotatable::TraitItem(i) => i,
+            _ => panic!("expected Item")
+        }
+    }
+
+    pub fn expect_impl_item(self) -> ast::ImplItem {
+        match self {
+            Annotatable::ImplItem(i) => i,
+            _ => panic!("expected Item")
+        }
+    }
+}
+
+// A more flexible ItemModifier (ItemModifier should go away, eventually, FIXME).
+// meta_item is the annotation, item is the item being modified, parent_item
+// is the impl or trait item is declared in if item is part of such a thing.
+// FIXME Decorators should follow the same pattern too.
+pub trait MultiItemModifier {
+    fn expand(&self,
+              ecx: &mut ExtCtxt,
+              span: Span,
+              meta_item: &ast::MetaItem,
+              item: Annotatable)
+              -> Annotatable;
+}
+
+impl<F> MultiItemModifier for F
+    where F: Fn(&mut ExtCtxt,
+                Span,
+                &ast::MetaItem,
+                Annotatable) -> Annotatable
+{
+    fn expand(&self,
+              ecx: &mut ExtCtxt,
+              span: Span,
+              meta_item: &ast::MetaItem,
+              item: Annotatable)
+              -> Annotatable {
+        (*self)(ecx, span, meta_item, item)
+    }
+}
+
 /// Represents a thing that maps token trees to Macro Results
 pub trait TTMacroExpander {
     fn expand<'cx>(&self,
@@ -299,6 +401,10 @@ pub enum SyntaxExtension {
     /// in-place.
     Modifier(Box<ItemModifier + 'static>),
 
+    /// A syntax extension that is attached to an item and modifies it
+    /// in-place. More flexible version than Modifier.
+    MultiModifier(Box<MultiItemModifier + 'static>),
+
     /// A normal, function-like syntax extension.
     ///
     /// `bytes!` is a `NormalTT`.
index e6b6f7bbd49c3d0f09d99bd7fcfd5d7fad69cce2..161b27d7abb597e3245c9cb7b0b0c38e476c1bb2 100644 (file)
 //!   (e.g. `Option<T>`), the parameters are automatically given the
 //!   current trait as a bound. (This includes separate type parameters
 //!   and lifetimes for methods.)
-//! - Additional bounds on the type parameters, e.g. the `Ord` instance
-//!   requires an explicit `PartialEq` bound at the
-//!   moment. (`TraitDef.additional_bounds`)
-//!
-//! Unsupported: FIXME #6257: calling methods on reference fields,
-//! e.g. derive Eq/Ord/Clone don't work on `struct A(&int)`,
-//! because of how the auto-dereferencing happens.
+//! - Additional bounds on the type parameters (`TraitDef.additional_bounds`)
 //!
 //! The most important thing for implementers is the `Substructure` and
 //! `SubstructureFields` objects. The latter groups 5 possibilities of the
 //! enums (one for each variant). For empty struct and empty enum
 //! variants, it is represented as a count of 0.
 //!
+//! # "`cs`" functions
+//!
+//! The `cs_...` functions ("combine substructure) are designed to
+//! make life easier by providing some pre-made recipes for common
+//! tasks; mostly calling the function being derived on all the
+//! arguments and then combining them back together in some way (or
+//! letting the user chose that). They are not meant to be the only
+//! way to handle the structures that this code creates.
+//!
 //! # Examples
 //!
 //! The following simplified `PartialEq` is used for in-code examples:
 //! When generating the `expr` for the `A` impl, the `SubstructureFields` is
 //!
 //! ```{.text}
-//! Struct(~[FieldInfo {
+//! Struct(vec![FieldInfo {
 //!            span: <span of x>
 //!            name: Some(<ident of x>),
 //!            self_: <expr for &self.x>,
-//!            other: ~[<expr for &other.x]
+//!            other: vec![<expr for &other.x]
 //!          }])
 //! ```
 //!
 //! For the `B` impl, called with `B(a)` and `B(b)`,
 //!
 //! ```{.text}
-//! Struct(~[FieldInfo {
+//! Struct(vec![FieldInfo {
 //!           span: <span of `int`>,
 //!           name: None,
-//!           <expr for &a>
-//!           ~[<expr for &b>]
+//!           self_: <expr for &a>
+//!           other: vec![<expr for &b>]
 //!          }])
 //! ```
 //!
 //!
 //! ```{.text}
 //! EnumMatching(0, <ast::Variant for C0>,
-//!              ~[FieldInfo {
+//!              vec![FieldInfo {
 //!                 span: <span of int>
 //!                 name: None,
 //!                 self_: <expr for &a>,
-//!                 other: ~[<expr for &b>]
+//!                 other: vec![<expr for &b>]
 //!               }])
 //! ```
 //!
 //!
 //! ```{.text}
 //! EnumMatching(1, <ast::Variant for C1>,
-//!              ~[FieldInfo {
+//!              vec![FieldInfo {
 //!                 span: <span of x>
 //!                 name: Some(<ident of x>),
 //!                 self_: <expr for &self.x>,
-//!                 other: ~[<expr for &other.x>]
+//!                 other: vec![<expr for &other.x>]
 //!                }])
 //! ```
 //!
 //!
 //! ```{.text}
 //! EnumNonMatchingCollapsed(
-//!     ~[<ident of self>, <ident of __arg_1>],
+//!     vec![<ident of self>, <ident of __arg_1>],
 //!     &[<ast::Variant for C0>, <ast::Variant for C1>],
 //!     &[<ident for self index value>, <ident of __arg_1 index value>])
 //! ```
 //!
 //! ## Static
 //!
-//! A static method on the above would result in,
+//! A static method on the types above would result in,
 //!
 //! ```{.text}
-//! StaticStruct(<ast::StructDef of A>, Named(~[(<ident of x>, <span of x>)]))
+//! StaticStruct(<ast::StructDef of A>, Named(vec![(<ident of x>, <span of x>)]))
 //!
-//! StaticStruct(<ast::StructDef of B>, Unnamed(~[<span of x>]))
+//! StaticStruct(<ast::StructDef of B>, Unnamed(vec![<span of x>]))
 //!
-//! StaticEnum(<ast::EnumDef of C>, ~[(<ident of C0>, <span of C0>, Unnamed(~[<span of int>])),
-//!                                   (<ident of C1>, <span of C1>,
-//!                                    Named(~[(<ident of x>, <span of x>)]))])
+//! StaticEnum(<ast::EnumDef of C>,
+//!            vec![(<ident of C0>, <span of C0>, Unnamed(vec![<span of int>])),
+//!                 (<ident of C1>, <span of C1>, Named(vec![(<ident of x>, <span of x>)]))])
 //! ```
 
 pub use self::StaticFields::*;
@@ -1378,8 +1381,8 @@ pub fn cs_fold<F>(use_foldl: bool,
 /// process the collected results. i.e.
 ///
 /// ```
-/// f(cx, span, ~[self_1.method(__arg_1_1, __arg_2_1),
-///              self_2.method(__arg_1_2, __arg_2_2)])
+/// f(cx, span, vec![self_1.method(__arg_1_1, __arg_2_1),
+///                  self_2.method(__arg_1_2, __arg_2_2)])
 /// ```
 #[inline]
 pub fn cs_same_method<F>(f: F,
index 9ef996ac3179b15e4acb483cd13579b1709b2311..c95bdeefd454046f39e6d5548c9c5bf10c5d3b83 100644 (file)
@@ -395,81 +395,15 @@ pub fn expand_item(it: P<ast::Item>, fld: &mut MacroExpander)
                    -> SmallVector<P<ast::Item>> {
     let it = expand_item_modifiers(it, fld);
 
-    let mut decorator_items = SmallVector::zero();
-    let mut new_attrs = Vec::new();
-    for attr in it.attrs.iter() {
-        let mname = attr.name();
-
-        match fld.cx.syntax_env.find(&intern(mname.get())) {
-            Some(rc) => match *rc {
-                Decorator(ref dec) => {
-                    attr::mark_used(attr);
-
-                    fld.cx.bt_push(ExpnInfo {
-                        call_site: attr.span,
-                        callee: NameAndSpan {
-                            name: mname.get().to_string(),
-                            format: MacroAttribute,
-                            span: None
-                        }
-                    });
-
-                    // we'd ideally decorator_items.push_all(expand_item(item, fld)),
-                    // but that double-mut-borrows fld
-                    let mut items: SmallVector<P<ast::Item>> = SmallVector::zero();
-                    dec.expand(fld.cx, attr.span, &*attr.node.value, &*it,
-                               box |&mut : item| items.push(item));
-                    decorator_items.extend(items.into_iter()
-                        .flat_map(|item| expand_item(item, fld).into_iter()));
-
-                    fld.cx.bt_pop();
-                }
-                _ => new_attrs.push((*attr).clone()),
-            },
-            _ => new_attrs.push((*attr).clone()),
-        }
-    }
-
-    let mut new_items = match it.node {
-        ast::ItemMac(..) => expand_item_mac(it, fld),
-        ast::ItemMod(_) | ast::ItemForeignMod(_) => {
-            let valid_ident =
-                it.ident.name != parse::token::special_idents::invalid.name;
-
-            if valid_ident {
-                fld.cx.mod_push(it.ident);
-            }
-            let macro_use = contains_macro_use(fld, &new_attrs[]);
-            let result = with_exts_frame!(fld.cx.syntax_env,
-                                          macro_use,
-                                          noop_fold_item(it, fld));
-            if valid_ident {
-                fld.cx.mod_pop();
-            }
-            result
-        },
-        _ => {
-            let it = P(ast::Item {
-                attrs: new_attrs,
-                ..(*it).clone()
-            });
-            noop_fold_item(it, fld)
-        }
-    };
-
-    new_items.push_all(decorator_items);
-    new_items
+    expand_annotatable(Annotatable::Item(it), fld)
+        .into_iter().map(|i| i.expect_item()).collect()
 }
 
 fn expand_item_modifiers(mut it: P<ast::Item>, fld: &mut MacroExpander)
                          -> P<ast::Item> {
     // partition the attributes into ItemModifiers and others
-    let (modifiers, other_attrs): (Vec<_>, _) = it.attrs.iter().cloned().partition(|attr| {
-        match fld.cx.syntax_env.find(&intern(attr.name().get())) {
-            Some(rc) => match *rc { Modifier(_) => true, _ => false },
-            _ => false
-        }
-    });
+    let (modifiers, other_attrs) = modifiers(&it.attrs, fld);
+
     // update the attrs, leave everything else alone. Is this mutation really a good idea?
     it = P(ast::Item {
         attrs: other_attrs,
@@ -477,7 +411,8 @@ fn expand_item_modifiers(mut it: P<ast::Item>, fld: &mut MacroExpander)
     });
 
     if modifiers.is_empty() {
-        return it;
+        let it = expand_item_multi_modifier(Annotatable::Item(it), fld);
+        return it.expect_item();
     }
 
     for attr in modifiers.iter() {
@@ -504,7 +439,12 @@ fn expand_item_modifiers(mut it: P<ast::Item>, fld: &mut MacroExpander)
         }
     }
 
-    // expansion may have added new ItemModifiers
+    // Expansion may have added new ItemModifiers.
+    // It is possible, that an item modifier could expand to a multi-modifier or
+    // vice versa. In this case we will expand all modifiers before multi-modifiers,
+    // which might give an odd ordering. However, I think it is unlikely that the
+    // two kinds will be mixed, and I old-style multi-modifiers should be deprecated
+    // anyway.
     expand_item_modifiers(it, fld)
 }
 
@@ -1029,6 +969,196 @@ fn fold_mac(&mut self, mac: ast::Mac) -> ast::Mac {
     }
 }
 
+fn expand_annotatable(a: Annotatable,
+                      fld: &mut MacroExpander)
+                      -> SmallVector<Annotatable> {
+    let a = expand_item_multi_modifier(a, fld);
+
+    let mut decorator_items = SmallVector::zero();
+    let mut new_attrs = Vec::new();
+    for attr in a.attrs().iter() {
+        let mname = attr.name();
+
+        match fld.cx.syntax_env.find(&intern(mname.get())) {
+            Some(rc) => match *rc {
+                Decorator(ref dec) => {
+                    let it = match a {
+                        Annotatable::Item(ref it) => it,
+                        // ItemDecorators are only implemented for Items.
+                        _ => break,
+                    };
+
+                    attr::mark_used(attr);
+
+                    fld.cx.bt_push(ExpnInfo {
+                        call_site: attr.span,
+                        callee: NameAndSpan {
+                            name: mname.get().to_string(),
+                            format: MacroAttribute,
+                            span: None
+                        }
+                    });
+
+                    // we'd ideally decorator_items.push_all(expand_item(item, fld)),
+                    // but that double-mut-borrows fld
+                    let mut items: SmallVector<P<ast::Item>> = SmallVector::zero();
+                    dec.expand(fld.cx, attr.span, &*attr.node.value, &**it,
+                               box |&mut: item| items.push(item));
+                    decorator_items.extend(items.into_iter()
+                        .flat_map(|item| expand_item(item, fld).into_iter()));
+
+                    fld.cx.bt_pop();
+                }
+                _ => new_attrs.push((*attr).clone()),
+            },
+            _ => new_attrs.push((*attr).clone()),
+        }
+    }
+
+    let mut new_items: SmallVector<Annotatable> = match a {
+        Annotatable::Item(it) => match it.node {
+            ast::ItemMac(..) => {
+                expand_item_mac(it, fld).into_iter().map(|i| Annotatable::Item(i)).collect()
+            }
+            ast::ItemMod(_) | ast::ItemForeignMod(_) => {
+                let valid_ident =
+                    it.ident.name != parse::token::special_idents::invalid.name;
+
+                if valid_ident {
+                    fld.cx.mod_push(it.ident);
+                }
+                let macro_use = contains_macro_use(fld, &new_attrs[]);
+                let result = with_exts_frame!(fld.cx.syntax_env,
+                                              macro_use,
+                                              noop_fold_item(it, fld));
+                if valid_ident {
+                    fld.cx.mod_pop();
+                }
+                result.into_iter().map(|i| Annotatable::Item(i)).collect()
+            },
+            _ => {
+                let it = P(ast::Item {
+                    attrs: new_attrs,
+                    ..(*it).clone()
+                });
+                noop_fold_item(it, fld).into_iter().map(|i| Annotatable::Item(i)).collect()
+            }
+        },
+        Annotatable::TraitItem(it) => match it {
+            ast::TraitItem::ProvidedMethod(m) => {
+                expand_method(m, fld).into_iter().map(|m|
+                    Annotatable::TraitItem(ast::TraitItem::ProvidedMethod(m))).collect()
+            }
+            ast::TraitItem::RequiredMethod(m) => {
+                SmallVector::one(Annotatable::TraitItem(
+                    ast::TraitItem::RequiredMethod(fld.fold_type_method(m))))
+            }
+            ast::TraitItem::TypeTraitItem(t) => {
+                SmallVector::one(Annotatable::TraitItem(
+                    ast::TraitItem::TypeTraitItem(P(fld.fold_associated_type((*t).clone())))))
+            }
+        },
+        Annotatable::ImplItem(it) => match it {
+            ast::ImplItem::MethodImplItem(m) => {
+                expand_method(m, fld).into_iter().map(|m|
+                    Annotatable::ImplItem(ast::ImplItem::MethodImplItem(m))).collect()
+            }
+            ast::ImplItem::TypeImplItem(t) => {
+                SmallVector::one(Annotatable::ImplItem(
+                    ast::ImplItem::TypeImplItem(P(fld.fold_typedef((*t).clone())))))
+            }
+        }
+    };
+
+    new_items.push_all(decorator_items.into_iter().map(|i| Annotatable::Item(i)).collect());
+    new_items
+}
+
+fn expand_trait_item(i: ast::TraitItem,
+                     fld: &mut MacroExpander)
+                     -> SmallVector<ast::TraitItem> {
+    expand_annotatable(Annotatable::TraitItem(i), fld)
+        .into_iter().map(|i| i.expect_trait_item()).collect()
+
+}
+
+fn expand_impl_item(i: ast::ImplItem,
+                    fld: &mut MacroExpander)
+                    -> SmallVector<ast::ImplItem> {
+    expand_annotatable(Annotatable::ImplItem(i), fld)
+        .into_iter().map(|i| i.expect_impl_item()).collect()
+}
+
+// partition the attributes into ItemModifiers and others
+fn modifiers(attrs: &Vec<ast::Attribute>,
+             fld: &MacroExpander)
+             -> (Vec<ast::Attribute>, Vec<ast::Attribute>) {
+    attrs.iter().cloned().partition(|attr| {
+        match fld.cx.syntax_env.find(&intern(attr.name().get())) {
+            Some(rc) => match *rc {
+                Modifier(_) => true,
+                _ => false
+            },
+            _ => false
+        }
+    })
+}
+
+// partition the attributes into MultiModifiers and others
+fn multi_modifiers(attrs: &[ast::Attribute],
+                   fld: &MacroExpander)
+                   -> (Vec<ast::Attribute>, Vec<ast::Attribute>) {
+    attrs.iter().cloned().partition(|attr| {
+        match fld.cx.syntax_env.find(&intern(attr.name().get())) {
+            Some(rc) => match *rc {
+                MultiModifier(_) => true,
+                _ => false
+            },
+            _ => false
+        }
+    })
+}
+
+fn expand_item_multi_modifier(mut it: Annotatable,
+                              fld: &mut MacroExpander)
+                              -> Annotatable {
+    let (modifiers, other_attrs) = multi_modifiers(it.attrs(), fld);
+
+    // Update the attrs, leave everything else alone. Is this mutation really a good idea?
+    it = it.fold_attrs(other_attrs);
+
+    if modifiers.is_empty() {
+        return it
+    }
+
+    for attr in modifiers.iter() {
+        let mname = attr.name();
+
+        match fld.cx.syntax_env.find(&intern(mname.get())) {
+            Some(rc) => match *rc {
+                MultiModifier(ref mac) => {
+                    attr::mark_used(attr);
+                    fld.cx.bt_push(ExpnInfo {
+                        call_site: attr.span,
+                        callee: NameAndSpan {
+                            name: mname.get().to_string(),
+                            format: MacroAttribute,
+                            span: None,
+                        }
+                    });
+                    it = mac.expand(fld.cx, attr.span, &*attr.node.value, it);
+                    fld.cx.bt_pop();
+                }
+                _ => unreachable!()
+            },
+            _ => unreachable!()
+        }
+    }
+
+    // Expansion may have added new ItemModifiers.
+    expand_item_multi_modifier(it, fld)
+}
+
 // expand a method
 fn expand_method(m: P<ast::Method>, fld: &mut MacroExpander) -> SmallVector<P<ast::Method>> {
     m.and_then(|m| match m.node {
@@ -1042,7 +1172,7 @@ fn expand_method(m: P<ast::Method>, fld: &mut MacroExpander) -> SmallVector<P<as
                       vis) => {
             let id = fld.new_id(m.id);
             let (rewritten_fn_decl, rewritten_body)
-                = expand_and_rename_fn_decl_and_block(decl,body,fld);
+                = expand_and_rename_fn_decl_and_block(decl, body, fld);
             SmallVector::one(P(ast::Method {
                     attrs: m.attrs.move_map(|a| fld.fold_attribute(a)),
                     id: id,
@@ -1147,6 +1277,14 @@ fn fold_arm(&mut self, arm: ast::Arm) -> ast::Arm {
         expand_arm(arm, self)
     }
 
+    fn fold_trait_item(&mut self, i: ast::TraitItem) -> SmallVector<ast::TraitItem> {
+        expand_trait_item(i, self)
+    }
+
+    fn fold_impl_item(&mut self, i: ast::ImplItem) -> SmallVector<ast::ImplItem> {
+        expand_impl_item(i, self)
+    }
+
     fn fold_method(&mut self, method: P<ast::Method>) -> SmallVector<P<ast::Method>> {
         expand_method(method, self)
     }
index 8175c0a9eecf4805d88fd571467b3c241a4a359f..8929bbe0232edc7bf78a6404f8204cbdfb83cd13 100644 (file)
@@ -71,6 +71,7 @@
     ("visible_private_types", Active),
     ("slicing_syntax", Active),
     ("box_syntax", Active),
+    ("on_unimplemented", Active),
 
     ("if_let", Accepted),
     ("while_let", Accepted),
@@ -249,6 +250,10 @@ fn visit_item(&mut self, i: &ast::Item) {
                 self.gate_feature("linkage", i.span,
                                   "the `linkage` attribute is experimental \
                                    and not portable across platforms")
+            } else if attr.name() == "rustc_on_unimplemented" {
+                self.gate_feature("on_unimplemented", i.span,
+                                  "the `#[rustc_on_unimplemented]` attribute \
+                                  is an experimental feature")
             }
         }
         match i.node {
index c45a4005339baea337116a1494daf44e2da0d048..16c29c9b5eb33a4bc206baf8b39b477c3fb09064 100644 (file)
@@ -102,6 +102,14 @@ fn fold_item_underscore(&mut self, i: Item_) -> Item_ {
         noop_fold_item_underscore(i, self)
     }
 
+    fn fold_trait_item(&mut self, i: TraitItem) -> SmallVector<TraitItem> {
+        noop_fold_trait_item(i, self)
+    }
+
+    fn fold_impl_item(&mut self, i: ImplItem) -> SmallVector<ImplItem> {
+        noop_fold_impl_item(i, self)
+    }
+
     fn fold_fn_decl(&mut self, d: P<FnDecl>) -> P<FnDecl> {
         noop_fold_fn_decl(d, self)
     }
@@ -454,7 +462,10 @@ pub fn noop_fold_qpath<T: Folder>(qpath: P<QPath>, fld: &mut T) -> P<QPath> {
         QPath {
             self_type: fld.fold_ty(qpath.self_type),
             trait_ref: qpath.trait_ref.map(|tr| fld.fold_trait_ref(tr)),
-            item_name: fld.fold_ident(qpath.item_name),
+            item_path: PathSegment {
+                identifier: fld.fold_ident(qpath.item_path.identifier),
+                parameters: fld.fold_path_parameters(qpath.item_path.parameters),
+            }
         }
     })
 }
@@ -1004,21 +1015,9 @@ pub fn noop_fold_item_underscore<T: Folder>(i: Item_, folder: &mut T) -> Item_ {
             ItemStruct(struct_def, folder.fold_generics(generics))
         }
         ItemImpl(unsafety, polarity, generics, ifce, ty, impl_items) => {
-            let mut new_impl_items = Vec::new();
-            for impl_item in impl_items.iter() {
-                match *impl_item {
-                    MethodImplItem(ref x) => {
-                        for method in folder.fold_method((*x).clone())
-                                            .into_iter() {
-                            new_impl_items.push(MethodImplItem(method))
-                        }
-                    }
-                    TypeImplItem(ref t) => {
-                        new_impl_items.push(TypeImplItem(
-                                P(folder.fold_typedef((**t).clone()))));
-                    }
-                }
-            }
+            let new_impl_items = impl_items.into_iter().flat_map(|item| {
+                folder.fold_impl_item(item).into_iter()
+            }).collect();
             let ifce = match ifce {
                 None => None,
                 Some(ref trait_ref) => {
@@ -1032,43 +1031,50 @@ pub fn noop_fold_item_underscore<T: Folder>(i: Item_, folder: &mut T) -> Item_ {
                      folder.fold_ty(ty),
                      new_impl_items)
         }
-        ItemTrait(unsafety, generics, bounds, methods) => {
+        ItemTrait(unsafety, generics, bounds, items) => {
             let bounds = folder.fold_bounds(bounds);
-            let methods = methods.into_iter().flat_map(|method| {
-                let r = match method {
-                    RequiredMethod(m) => {
-                            SmallVector::one(RequiredMethod(
-                                    folder.fold_type_method(m)))
-                                .into_iter()
-                    }
-                    ProvidedMethod(method) => {
-                        // the awkward collect/iter idiom here is because
-                        // even though an iter and a map satisfy the same
-                        // trait bound, they're not actually the same type, so
-                        // the method arms don't unify.
-                        let methods: SmallVector<ast::TraitItem> =
-                            folder.fold_method(method).into_iter()
-                            .map(|m| ProvidedMethod(m)).collect();
-                        methods.into_iter()
-                    }
-                    TypeTraitItem(at) => {
-                        SmallVector::one(TypeTraitItem(P(
-                                    folder.fold_associated_type(
-                                        (*at).clone()))))
-                            .into_iter()
-                    }
-                };
-                r
+            let items = items.into_iter().flat_map(|item| {
+                folder.fold_trait_item(item).into_iter()
             }).collect();
             ItemTrait(unsafety,
                       folder.fold_generics(generics),
                       bounds,
-                      methods)
+                      items)
         }
         ItemMac(m) => ItemMac(folder.fold_mac(m)),
     }
 }
 
+pub fn noop_fold_trait_item<T: Folder>(i: TraitItem, folder: &mut T) -> SmallVector<TraitItem> {
+    match i {
+        RequiredMethod(m) => {
+                SmallVector::one(RequiredMethod(
+                        folder.fold_type_method(m)))
+        }
+        ProvidedMethod(method) => {
+            folder.fold_method(method).into_iter()
+                .map(|m| ProvidedMethod(m)).collect()
+        }
+        TypeTraitItem(at) => {
+            SmallVector::one(TypeTraitItem(P(
+                        folder.fold_associated_type(
+                            (*at).clone()))))
+        }
+    }
+}
+
+pub fn noop_fold_impl_item<T: Folder>(i: ImplItem, folder: &mut T) -> SmallVector<ImplItem> {
+    match i {
+        MethodImplItem(ref x) => {
+            folder.fold_method((*x).clone()).into_iter().map(|m| MethodImplItem(m)).collect()
+        }
+        TypeImplItem(ref t) => {
+            SmallVector::one(TypeImplItem(
+                    P(folder.fold_typedef((**t).clone()))))
+        }
+    }
+}
+
 pub fn noop_fold_type_method<T: Folder>(m: TypeMethod, fld: &mut T) -> TypeMethod {
     let TypeMethod {
         id,
@@ -1381,6 +1387,7 @@ pub fn noop_fold_expr<T: Folder>(Expr {id, node, span}: Expr, folder: &mut T) ->
                           e2.map(|x| folder.fold_expr(x)))
             }
             ExprPath(pth) => ExprPath(folder.fold_path(pth)),
+            ExprQPath(qpath) => ExprQPath(folder.fold_qpath(qpath)),
             ExprBreak(opt_ident) => ExprBreak(opt_ident.map(|x| folder.fold_ident(x))),
             ExprAgain(opt_ident) => ExprAgain(opt_ident.map(|x| folder.fold_ident(x))),
             ExprRet(e) => ExprRet(e.map(|x| folder.fold_expr(x))),
index 33f9e35d8b7af76280b126d49ac8c12bf8006202..543b746849955d4f83558acaa07c848043f1f6ec 100644 (file)
@@ -25,7 +25,7 @@
 use ast::{ExprBreak, ExprCall, ExprCast};
 use ast::{ExprField, ExprTupField, ExprClosure, ExprIf, ExprIfLet, ExprIndex};
 use ast::{ExprLit, ExprLoop, ExprMac, ExprRange};
-use ast::{ExprMethodCall, ExprParen, ExprPath};
+use ast::{ExprMethodCall, ExprParen, ExprPath, ExprQPath};
 use ast::{ExprRepeat, ExprRet, ExprStruct, ExprTup, ExprUnary};
 use ast::{ExprVec, ExprWhile, ExprWhileLet, ExprForLoop, Field, FnDecl};
 use ast::{FnUnboxedClosureKind, FnMutUnboxedClosureKind};
@@ -1573,7 +1573,10 @@ pub fn parse_ty(&mut self) -> P<Ty> {
             TyQPath(P(QPath {
                 self_type: self_type,
                 trait_ref: P(trait_ref),
-                item_name: item_name,
+                item_path: ast::PathSegment {
+                    identifier: item_name,
+                    parameters: ast::PathParameters::none()
+                }
             }))
         } else if self.check(&token::ModSep) ||
                   self.token.is_ident() ||
@@ -1894,11 +1897,7 @@ pub fn parse_path_segments_with_colons(&mut self) -> Vec<ast::PathSegment> {
             if !self.eat(&token::ModSep) {
                 segments.push(ast::PathSegment {
                     identifier: identifier,
-                    parameters: ast::AngleBracketedParameters(ast::AngleBracketedParameterData {
-                        lifetimes: Vec::new(),
-                        types: OwnedSlice::empty(),
-                        bindings: OwnedSlice::empty(),
-                    })
+                    parameters: ast::PathParameters::none()
                 });
                 return segments;
             }
@@ -2253,6 +2252,37 @@ pub fn parse_bottom_expr(&mut self) -> P<Expr> {
                 hi = self.last_span.hi;
             }
             _ => {
+                if self.eat_lt() {
+                    // QUALIFIED PATH `<TYPE as TRAIT_REF>::item::<'a, T>`
+                    let self_type = self.parse_ty_sum();
+                    self.expect_keyword(keywords::As);
+                    let trait_ref = self.parse_trait_ref();
+                    self.expect(&token::Gt);
+                    self.expect(&token::ModSep);
+                    let item_name = self.parse_ident();
+                    let parameters = if self.eat(&token::ModSep) {
+                        self.expect_lt();
+                        // Consumed `item::<`, go look for types
+                        let (lifetimes, types, bindings) =
+                            self.parse_generic_values_after_lt();
+                        ast::AngleBracketedParameters(ast::AngleBracketedParameterData {
+                            lifetimes: lifetimes,
+                            types: OwnedSlice::from_vec(types),
+                            bindings: OwnedSlice::from_vec(bindings),
+                        })
+                    } else {
+                        ast::PathParameters::none()
+                    };
+                    let hi = self.span.hi;
+                    return self.mk_expr(lo, hi, ExprQPath(P(QPath {
+                        self_type: self_type,
+                        trait_ref: P(trait_ref),
+                        item_path: ast::PathSegment {
+                            identifier: item_name,
+                            parameters: parameters
+                        }
+                    })));
+                }
                 if self.eat_keyword(keywords::Move) {
                     return self.parse_lambda_expr(CaptureByValue);
                 }
index 9b6f8e6002d8aa894b2502a7a818d752be75fae0..ec6672d22a97a3dd9ba1b3f704c043ba99c0c16f 100644 (file)
@@ -727,14 +727,7 @@ pub fn print_type(&mut self, ty: &ast::Ty) -> IoResult<()> {
                 try!(self.print_bounds("", &bounds[]));
             }
             ast::TyQPath(ref qpath) => {
-                try!(word(&mut self.s, "<"));
-                try!(self.print_type(&*qpath.self_type));
-                try!(space(&mut self.s));
-                try!(self.word_space("as"));
-                try!(self.print_trait_ref(&*qpath.trait_ref));
-                try!(word(&mut self.s, ">"));
-                try!(word(&mut self.s, "::"));
-                try!(self.print_ident(qpath.item_name));
+                try!(self.print_qpath(&**qpath, false))
             }
             ast::TyFixedLengthVec(ref ty, ref v) => {
                 try!(word(&mut self.s, "["));
@@ -1749,6 +1742,7 @@ pub fn print_expr(&mut self, expr: &ast::Expr) -> IoResult<()> {
                 }
             }
             ast::ExprPath(ref path) => try!(self.print_path(path, true)),
+            ast::ExprQPath(ref qpath) => try!(self.print_qpath(&**qpath, true)),
             ast::ExprBreak(opt_ident) => {
                 try!(word(&mut self.s, "break"));
                 try!(space(&mut self.s));
@@ -1933,6 +1927,22 @@ fn print_path(&mut self,
         Ok(())
     }
 
+    fn print_qpath(&mut self,
+                   qpath: &ast::QPath,
+                   colons_before_params: bool)
+                   -> IoResult<()>
+    {
+        try!(word(&mut self.s, "<"));
+        try!(self.print_type(&*qpath.self_type));
+        try!(space(&mut self.s));
+        try!(self.word_space("as"));
+        try!(self.print_trait_ref(&*qpath.trait_ref));
+        try!(word(&mut self.s, ">"));
+        try!(word(&mut self.s, "::"));
+        try!(self.print_ident(qpath.item_path.identifier));
+        self.print_path_parameters(&qpath.item_path.parameters, colons_before_params)
+    }
+
     fn print_path_parameters(&mut self,
                              parameters: &ast::PathParameters,
                              colons_before_params: bool)
index 3f91304dcc5f21c528b2cfcdcee0c570109f10de..7778b4fa34aa1e7c19c258dbba2f10ec30c0cf0b 100644 (file)
@@ -126,6 +126,9 @@ fn visit_mac(&mut self, _mac: &'v Mac) {
     fn visit_path(&mut self, path: &'v Path, _id: ast::NodeId) {
         walk_path(self, path)
     }
+    fn visit_qpath(&mut self, qpath_span: Span, qpath: &'v QPath) {
+        walk_qpath(self, qpath_span, qpath)
+    }
     fn visit_path_segment(&mut self, path_span: Span, path_segment: &'v PathSegment) {
         walk_path_segment(self, path_span, path_segment)
     }
@@ -419,9 +422,7 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty) {
             walk_ty_param_bounds_helper(visitor, bounds);
         }
         TyQPath(ref qpath) => {
-            visitor.visit_ty(&*qpath.self_type);
-            visitor.visit_trait_ref(&*qpath.trait_ref);
-            visitor.visit_ident(typ.span, qpath.item_name);
+            visitor.visit_qpath(typ.span, &**qpath);
         }
         TyFixedLengthVec(ref ty, ref expression) => {
             visitor.visit_ty(&**ty);
@@ -450,6 +451,14 @@ pub fn walk_path<'v, V: Visitor<'v>>(visitor: &mut V, path: &'v Path) {
     }
 }
 
+pub fn walk_qpath<'v, V: Visitor<'v>>(visitor: &mut V,
+                                      qpath_span: Span,
+                                      qpath: &'v QPath) {
+    visitor.visit_ty(&*qpath.self_type);
+    visitor.visit_trait_ref(&*qpath.trait_ref);
+    visitor.visit_path_segment(qpath_span, &qpath.item_path);
+}
+
 pub fn walk_path_segment<'v, V: Visitor<'v>>(visitor: &mut V,
                                              path_span: Span,
                                              segment: &'v PathSegment) {
@@ -881,6 +890,9 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) {
         ExprPath(ref path) => {
             visitor.visit_path(path, expression.id)
         }
+        ExprQPath(ref qpath) => {
+            visitor.visit_qpath(expression.span, &**qpath)
+        }
         ExprBreak(_) | ExprAgain(_) => {}
         ExprRet(ref optional_expression) => {
             walk_expr_opt(visitor, optional_expression)
index c4cb53d6cb7b6e19cf557c613cc756d794ba0ac3..c00246598c303c94bdccd58287bf86b3f30ca02f 100644 (file)
@@ -1332,10 +1332,11 @@ pub fn ratchet(&self, p: &Path, pct: Option<f64>) -> (MetricDiff, bool) {
 /// elimination.
 ///
 /// This function is a no-op, and does not even read from `dummy`.
-pub fn black_box<T>(dummy: T) {
+pub fn black_box<T>(dummy: T) -> T {
     // we need to "use" the argument in some way LLVM can't
     // introspect.
     unsafe {asm!("" : : "r"(&dummy))}
+    dummy
 }
 
 
index 772b84670141364fb95ba70bae83c6bf980b88b4..c5e412140e44a4dd54e6f504d51dac8c1087003f 100644 (file)
@@ -9,7 +9,7 @@
 
 #if defined(__APPLE__)
 #define MORESTACK ___morestack
-#define STACK_EXHAUSTED _rust_stack_exhausted
+#define STACK_EXHAUSTED _rust_stack_exhausted@plt
 #else
 #define MORESTACK __morestack
 #define STACK_EXHAUSTED rust_stack_exhausted
@@ -30,6 +30,6 @@
 // FIXME(AARCH64): this might not be perfectly right but works for now
 MORESTACK:
        .cfi_startproc
-       bl STACK_EXHAUSTED@plt
+       bl STACK_EXHAUSTED
        // the above function ensures that it never returns
        .cfi_endproc
diff --git a/src/rt/arch/powerpc/morestack.S b/src/rt/arch/powerpc/morestack.S
new file mode 100644 (file)
index 0000000..2502ac1
--- /dev/null
@@ -0,0 +1,18 @@
+// Mark stack as non-executable
+#if defined(__linux__) && defined(__ELF__)
+.section       .note.GNU-stack, "", %progbits
+#endif
+
+/* See i386/morestack.S for the lengthy, general explanation. */
+
+.global rust_stack_exhausted
+
+.hidden __morestack
+
+// FIXME(POWERPC): this might not be perfectly right but works for now
+__morestack:
+       .cfi_startproc
+       bl rust_stack_exhausted
+       // the above function ensures that it never returns
+       .cfi_endproc
+.end  __morestack
diff --git a/src/rt/arch/powerpc/record_sp.S b/src/rt/arch/powerpc/record_sp.S
new file mode 100644 (file)
index 0000000..e93a69a
--- /dev/null
@@ -0,0 +1,4 @@
+// Mark stack as non-executable
+#if defined(__linux__) && defined(__ELF__)
+.section       .note.GNU-stack, "", %progbits
+#endif
index 44b1630d9fb4c869e7a97f8c2d6b58b4ede7418a..50a6ad43aeeb109474781f9ea68196b1b15f27eb 100644 (file)
@@ -20,6 +20,7 @@
 use book;
 use book::{Book, BookItem};
 use css;
+use javascript;
 
 use regex::Regex;
 
@@ -63,7 +64,7 @@ fn walk_item(item: &BookItem,
         Ok(())
     }
 
-    try!(writeln!(out, "<div id='toc'>"));
+    try!(writeln!(out, "<div id='toc' class='mobile-hidden'>"));
     try!(writeln!(out, "<ul class='chapter'>"));
     try!(walk_items(&book.chapters[], "", path_to_root, out));
     try!(writeln!(out, "</ul>"));
@@ -102,6 +103,14 @@ fn render(book: &Book, tgt: &Path) -> CliResult<()> {
         let prelude = tmp.path().join("prelude.html");
         {
             let mut toc = BufferedWriter::new(try!(File::create(&prelude)));
+            try!(writeln!(&mut toc, r#"<div id="nav">
+                <button id="toggle-nav">
+                  <span class="sr-only">Toggle navigation</span>
+                  <span class="bar"></span>
+                  <span class="bar"></span>
+                  <span class="bar"></span>
+                </button>
+              </div>"#));
             let _ = write_toc(book, &item.path_to_root, &mut toc);
             try!(writeln!(&mut toc, "<div id='page-wrapper'>"));
             try!(writeln!(&mut toc, "<div id='page'>"));
@@ -111,6 +120,7 @@ fn render(book: &Book, tgt: &Path) -> CliResult<()> {
         let postlude = tmp.path().join("postlude.html");
         {
             let mut toc = BufferedWriter::new(try!(File::create(&postlude)));
+            try!(toc.write_str(javascript::JAVASCRIPT));
             try!(writeln!(&mut toc, "</div></div>"));
         }
 
index 92433589155ba91afce3db5b8c965cc8baccc1aa..65ba031a2d63488354ddf81c793b3d71ae0362fb 100644 (file)
@@ -45,7 +45,7 @@
 #page {
     margin-left: auto;
     margin-right:auto;
-    width: 750px;
+    max-width: 750px;
 }
 
 .chapter {
 .chapter li a {
     color: #000000;
 }
+
+@media only screen and (max-width: 1060px) {
+    #toc {
+        width: 100%;
+        margin-right: 0;
+        top: 40px;
+    }
+    #page-wrapper {
+        top: 40px;
+        left: 15px;
+        padding-right: 15px;
+    }
+    .mobile-hidden {
+        display: none;
+    }
+}
+
+
+#toggle-nav {
+    height: 20px;
+    width:  30px;
+    padding: 3px 3px 0 3px;
+}
+
+#toggle-nav {
+    margin-top: 5px;
+    width: 30px;
+    height: 30px;
+    background-color: #FFF;
+    border: 1px solid #666;
+    border-radius: 3px 3px 3px 3px;
+}
+
+.sr-only {
+    position: absolute;
+    width: 1px;
+    height: 1px;
+    margin: -1px;
+    padding: 0;
+    overflow: hidden;
+    clip: rect(0, 0, 0, 0);
+    border: 0;
+}
+
+.bar {
+    display: block;
+    background-color: #000;
+    border-radius: 2px;
+    width: 100%;
+    height: 2px;
+    margin: 2px 0 3px;
+    padding: 0;
+}
+
 "#;
diff --git a/src/rustbook/javascript.rs b/src/rustbook/javascript.rs
new file mode 100644 (file)
index 0000000..eb4401e
--- /dev/null
@@ -0,0 +1,43 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// The rust-book JavaScript in string form.
+
+pub static JAVASCRIPT: &'static str = r#"
+<script type="text/javascript">
+document.addEventListener("DOMContentLoaded", function(event) {
+  document.getElementById("toggle-nav").onclick = toggleNav;
+  function toggleNav() {
+    var toc = document.getElementById("toc");
+    var pagewrapper = document.getElementById("page-wrapper");
+    toggleClass(toc, "mobile-hidden");
+    toggleClass(pagewrapper, "mobile-hidden");
+  };
+
+  function toggleClass(el, className) {
+     // from http://youmightnotneedjquery.com/
+     if (el.classList) {
+       el.classList.toggle(className);
+     } else {
+       var classes = el.className.split(' ');
+       var existingIndex = classes.indexOf(className);
+
+       if (existingIndex >= 0) {
+         classes.splice(existingIndex, 1);
+       } else {
+         classes.push(className);
+       }
+
+       el.className = classes.join(' ');
+     }
+  }
+});
+</script>
+"#;
index 48dad14321a8d57db23e557f4716228980fba9f7..85b9a7d79dbfefc3bcca48eba8b10faee9ec4427 100644 (file)
@@ -39,6 +39,7 @@ macro_rules! try (
 mod test;
 
 mod css;
+mod javascript;
 
 #[cfg(not(test))] // thanks #12327
 fn main() {
index 2ac855681f28b9970b1b95e770552532a30149c5..4a16b9c257cbe953bb1edb192ba7ad43b49604c1 100644 (file)
@@ -1,4 +1,4 @@
 # If this file is modified, then llvm will be forcibly cleaned and then rebuilt.
 # The actual contents of this file do not matter, but to trigger a change on the
 # build bots then the contents should be changed so git updates the mtime.
-2015-01-05
+2015-01-13
index 689610d799ec065d979858c998df04ce60a473d5..cbe56b00c13d59be061059d437efa6751a80c417 100644 (file)
 use std::sync::atomic;
 
 pub const C1: uint = 1;
-pub const C2: atomic::AtomicUint = atomic::ATOMIC_UINT_INIT;
+pub const C2: atomic::AtomicUsize = atomic::ATOMIC_USIZE_INIT;
 pub const C3: fn() = foo;
 pub const C4: uint = C1 * C1 + C1 / C1;
 pub const C5: &'static uint = &C4;
 
 pub static S1: uint = 3;
-pub static S2: atomic::AtomicUint = atomic::ATOMIC_UINT_INIT;
+pub static S2: atomic::AtomicUsize = atomic::ATOMIC_USIZE_INIT;
 
 fn foo() {}
index 9eeb7ee88571ec50bdd98c0b91e906a99cf26933..e3e91e05f55e9197b5e23fe9facff88c17d2626e 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2013-2015 The Rust Project Developers. See the COPYRIGHT
 // file at the top-level directory of this distribution and at
 // http://rust-lang.org/COPYRIGHT.
 //
@@ -16,7 +16,7 @@
 extern crate syntax;
 extern crate rustc;
 
-use syntax::ast::{TokenTree, Item, MetaItem};
+use syntax::ast::{TokenTree, Item, MetaItem, ImplItem, TraitItem, Method};
 use syntax::codemap::Span;
 use syntax::ext::base::*;
 use syntax::parse::token;
@@ -37,6 +37,9 @@ pub fn plugin_registrar(reg: &mut Registry) {
     reg.register_syntax_extension(
         token::intern("into_foo"),
         Modifier(box expand_into_foo));
+    reg.register_syntax_extension(
+        token::intern("into_multi_foo"),
+        MultiModifier(box expand_into_foo_multi));
 }
 
 fn expand_make_a_1(cx: &mut ExtCtxt, sp: Span, tts: &[TokenTree])
@@ -65,6 +68,30 @@ fn expand_into_foo(cx: &mut ExtCtxt, sp: Span, attr: &MetaItem, it: P<Item>)
     })
 }
 
+fn expand_into_foo_multi(cx: &mut ExtCtxt,
+                         sp: Span,
+                         attr: &MetaItem,
+                         it: Annotatable) -> Annotatable {
+    match it {
+        Annotatable::Item(it) => {
+            Annotatable::Item(P(Item {
+                attrs: it.attrs.clone(),
+                ..(*quote_item!(cx, enum Foo2 { Bar2, Baz2 }).unwrap()).clone()
+            }))
+        }
+        Annotatable::ImplItem(it) => {
+            Annotatable::ImplItem(ImplItem::MethodImplItem(
+                quote_method!(cx, fn foo(&self) -> i32 { 42 })
+            ))
+        }
+        Annotatable::TraitItem(it) => {
+            Annotatable::TraitItem(TraitItem::ProvidedMethod(
+                quote_method!(cx, fn foo(&self) -> i32 { 0 })
+            ))
+        }
+    }
+}
+
 fn expand_forged_ident(cx: &mut ExtCtxt, sp: Span, tts: &[TokenTree]) -> Box<MacResult+'static> {
     use syntax::ext::quote::rt::*;
 
index 5a47f9fbc573a7f5ecbac739de55d877bdc9e402..9e5618579e40a5c520bec78e5974cf6bc9c3f129 100644 (file)
@@ -128,7 +128,7 @@ fn make(&mut self, n: uint) -> IoResult<()> {
         copy_memory(buf.as_mut_slice(), alu);
         let buf_len = buf.len();
         copy_memory(buf.slice_mut(alu_len, buf_len),
-                    &alu[0..LINE_LEN]);
+                    &alu[..LINE_LEN]);
 
         let mut pos = 0;
         let mut bytes;
@@ -204,7 +204,7 @@ fn make(&mut self, n: uint) -> IoResult<()> {
         for i in range(0u, chars_left) {
             buf[i] = self.nextc();
         }
-        self.out.write(&buf[0..chars_left])
+        self.out.write(&buf[..chars_left])
     }
 }
 
index ea4b3c4631268d2f6330ed485c425f2b1a7c3d79..47f17997e84e8157a58fca05723e62f83ed9227a 100644 (file)
 use std::sync::mpsc::{channel, Sender, Receiver};
 use std::thread::Thread;
 
-fn start(n_tasks: int, token: int) {
+fn start(n_tasks: i32, token: i32) {
     let (tx, mut rx) = channel();
     tx.send(token).unwrap();
-    for i in range(2, n_tasks + 1) {
+    let mut guards = Vec::with_capacity(n_tasks as usize);
+    for i in 2 .. n_tasks + 1 {
         let (tx, next_rx) = channel();
-        Thread::spawn(move|| roundtrip(i, tx, rx));
-        rx = next_rx;
+        let cur_rx = std::mem::replace(&mut rx, next_rx);
+        guards.push(Thread::scoped(move|| roundtrip(i, tx, cur_rx)));
     }
-    Thread::spawn(move|| roundtrip(1, tx, rx));
+    let guard = Thread::scoped(move|| roundtrip(1, tx, rx));
 }
 
-fn roundtrip(id: int, tx: Sender<int>, rx: Receiver<int>) {
+fn roundtrip(id: i32, tx: Sender<i32>, rx: Receiver<i32>) {
     for token in rx.iter() {
         if token == 1 {
             println!("{}", id);
@@ -64,7 +65,6 @@ fn roundtrip(id: int, tx: Sender<int>, rx: Receiver<int>) {
 
 fn main() {
     let args = std::os::args();
-    let args = args.as_slice();
     let token = if std::os::getenv("RUST_BENCH").is_some() {
         2000000
     } else {
index 6581019fdd52061bbc7507059ada4c55fa99b83e..2415288a3eb73f458881b9a7044e3716b32d93ab 100644 (file)
@@ -9,8 +9,18 @@
 // except according to those terms.
 
 fn main() {
-    let _x: isize = [1is, 2, 3]; //~ ERROR expected isize, found array of 3 elements
+    let _x: isize = [1is, 2, 3];
+    //~^ ERROR mismatched types
+    //~| expected `isize`
+    //~| found `[isize; 3]`
+    //~| expected isize
+    //~| found array of 3 elements
 
     let x: &[isize] = &[1, 2, 3];
-    let _y: &isize = x; //~ ERROR expected isize, found slice
+    let _y: &isize = x;
+    //~^ ERROR mismatched types
+    //~| expected `&isize`
+    //~| found `&[isize]`
+    //~| expected isize
+    //~| found slice
 }
index ed81c0fccbc854687bde295941db5657b497988c..fdfff559086f35c0e91c265dbf96217af88817d2 100644 (file)
@@ -30,7 +30,12 @@ fn foo1<I: Foo<A=Bar>>(x: I) {
 }
 
 fn foo2<I: Foo>(x: I) {
-    let _: Bar = x.boo(); //~ERROR mismatched types
+    let _: Bar = x.boo();
+    //~^ ERROR mismatched types
+    //~| expected `Bar`
+    //~| found `<I as Foo>::A`
+    //~| expected struct `Bar`
+    //~| found associated type
 }
 
 
@@ -41,6 +46,12 @@ pub fn baz(x: &Foo<A=Bar>) {
 
 pub fn main() {
     let a = 42is;
-    foo1(a); //~ERROR expected usize, found struct Bar
-    baz(&a); //~ERROR expected usize, found struct Bar
+    foo1(a);
+    //~^ ERROR type mismatch resolving
+    //~| expected usize
+    //~| found struct `Bar`
+    baz(&a);
+    //~^ ERROR type mismatch resolving
+    //~| expected usize
+    //~| found struct `Bar`
 }
index 74c8dffced5cf9e0d06f2847c0fab8e00dc14d78..5cb9aca8bebd0d97dcd7a5705818abd77c4b64a8 100644 (file)
@@ -25,7 +25,9 @@ pub fn f2<T: Foo>(a: T) -> T::A {
 
 pub fn f1_int_int() {
     f1(2is, 4is);
-    //~^ ERROR expected usize, found isize
+    //~^ ERROR type mismatch resolving
+    //~| expected usize
+    //~| found isize
 }
 
 pub fn f1_int_uint() {
@@ -46,7 +48,11 @@ pub fn f1_uint_int() {
 
 pub fn f2_int() {
     let _: isize = f2(2is);
-    //~^ ERROR expected `isize`, found `usize`
+    //~^ ERROR mismatched types
+    //~| expected `isize`
+    //~| found `usize`
+    //~| expected isize
+    //~| found usize
 }
 
 pub fn main() { }
index 2450f22669a5133045a24f23365b048521f6be0d..ed62506420a7ca7cc3321d36e715035e8140c0d0 100644 (file)
@@ -8,7 +8,10 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// error-pattern:expected `collections::string::String`, found `isize`
-
 static i: String = 10is;
+//~^ ERROR mismatched types
+//~| expected `collections::string::String`
+//~| found `isize`
+//~| expected struct `collections::string::String`
+//~| found isize
 fn main() { println!("{}", i); }
index 687171f8c1f9b348d3dbbb50f13a9a4962cc1fe6..30039a1c54c3a2d9fba92f471cba2d386bddc255 100644 (file)
@@ -8,10 +8,12 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// error-pattern:mismatched types: expected `()`, found `bool`
-
 fn main() {
     loop {
-        true
+        true //~  ERROR mismatched types
+             //~| expected ()
+             //~| found bool
+             //~| expected ()
+             //~| found bool
     }
 }
index 328c032325e0921a64542fd146c3c9368eebb837..6161660ddf7b3ed9daf2ecd36ffb67067256cc9e 100644 (file)
@@ -8,13 +8,15 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// error-pattern:mismatched types: expected `()`, found `bool`
-
 struct r;
 
 impl Drop for r {
     fn drop(&mut self) {
-        true
+        true //~  ERROR mismatched types
+             //~| expected ()
+             //~| found bool
+             //~| expected ()
+             //~| found bool
     }
 }
 
index ed903f3fd65517fe6acbdb950a68ccbf2593878a..ba6340ed395ee934f278d45d66bb7e64ef13e482 100644 (file)
@@ -8,10 +8,12 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// error-pattern:mismatched types: expected `()`, found `bool`
-
 fn main() {
     while true {
-        true
+        true //~  ERROR mismatched types
+             //~| expected `()`
+             //~| found `bool`
+             //~| expected ()
+             //~| found bool
     }
 }
index 8d48ede0e154308afc4388799985dcf596f30181..d7a37d2699186615be74590714c22ed1c65881f2 100644 (file)
 // Tests that we forbid coercion from `[T; n]` to `&[T]`
 
 fn main() {
-    let _: &[isize] = [0is]; //~ERROR: mismatched types: expected `&[isize]`, found `[isize; 1]`
+    let _: &[isize] = [0is];
+    //~^ ERROR mismatched types
+    //~| expected `&[isize]`
+    //~| found `[isize; 1]`
+    //~| expected &-ptr
+    //~| found array of 1 elements
 }
index 6b8e126db7790a51989b47f8ff98a65125090266..6e3732908ac06451beb0f61b3d74f802d0ccf62e 100644 (file)
 
 static a: &'static str = "foo";
 static b: *const u8 = a as *const u8;
-//~^ ERROR mismatched types: expected `*const u8`, found `&'static str`
+//~^ ERROR mismatched types
+//~| expected *const u8
+//~| found &'static str
+//~| expected u8
+//~| found str
 static c: *const u8 = &a as *const u8;
-//~^ ERROR mismatched types: expected `*const u8`, found `&&'static str`
+//~^ ERROR mismatched types
+//~| expected *const u8
+//~| found &&'static str
+//~| expected u8
+//~| found &-ptr
 
 fn main() {
 }
index ff96ea93184e635c6e7c920d076fa07a1b984e89..86b7a8c89184abcbcd51e4bfe711360c61694f68 100644 (file)
@@ -19,6 +19,10 @@ impl Trait for Foo {}
 
 pub fn main() {
     let x: Box<Trait> = box Foo;
-    let _y: &Trait = x; //~ ERROR mismatched types: expected `&Trait`, found `Box<Trait>`
+    let _y: &Trait = x; //~  ERROR mismatched types
+                        //~| expected `&Trait`
+                        //~| found `Box<Trait>`
+                        //~| expected &-ptr
+                        //~| found box
 }
 
index 5166ef8f72f8b1c1cedc01c7031f2376a2cb0ad3..5cc0d6a143ae2078cc1e778741bfeaad116f9bab 100644 (file)
@@ -37,7 +37,22 @@ fn main() {
     let box x = box 1is as Box<T>; //~ ERROR type `Box<T>` cannot be dereferenced
 
     // n > m
-    let &&x = &1is as &T;     //~ ERROR found &-ptr
-    let &&&x = &(&1is as &T); //~ ERROR found &-ptr
-    let box box x = box 1is as Box<T>;    //~ ERROR found box
+    let &&x = &1is as &T;
+    //~^ ERROR mismatched types
+    //~| expected `T`
+    //~| found `&_`
+    //~| expected trait T
+    //~| found &-ptr
+    let &&&x = &(&1is as &T);
+    //~^ ERROR mismatched types
+    //~| expected `T`
+    //~| found `&_`
+    //~| expected trait T
+    //~| found &-ptr
+    let box box x = box 1is as Box<T>;
+    //~^ ERROR mismatched types
+    //~| expected `T`
+    //~| found `Box<_>`
+    //~| expected trait T
+    //~| found box
 }
index 634b5999e9ef28c33bb5adf313ee1ca0f44b1468..152864b601c20818da6b5f6a8eff691d58a97305 100644 (file)
@@ -44,6 +44,11 @@ pub fn main() {
     // Assignment.
     let f5: &mut Fat<ToBar> = &mut Fat { f1: 5, f2: "some str", ptr: Bar1 {f :42} };
     let z: Box<ToBar> = box Bar1 {f: 36};
-    f5.ptr = Bar1 {f: 36}; //~ ERROR mismatched types: expected `ToBar`, found `Bar1`
-    //~^ ERROR the trait `core::marker::Sized` is not implemented for the type `ToBar`
+    f5.ptr = Bar1 {f: 36};
+    //~^ ERROR mismatched types
+    //~| expected `ToBar`
+    //~| found `Bar1`
+    //~| expected trait ToBar
+    //~| found struct `Bar1`
+    //~| ERROR the trait `core::marker::Sized` is not implemented for the type `ToBar`
 }
index e70db87a39a4176007cf87e4061641b78debf4a0..2b96c5ebe1284c1647e9aa991ecb03d651ddbb25 100644 (file)
@@ -22,7 +22,11 @@ pub fn main() {
     let f1 = Fat { ptr: [1, 2, 3] };
     let f2: &Fat<[isize; 3]> = &f1;
     let f3: &Fat<[usize]> = f2;
-    //~^ ERROR mismatched types: expected `&Fat<[usize]>`, found `&Fat<[isize; 3]>`
+    //~^ ERROR mismatched types
+    //~| expected `&Fat<[usize]>`
+    //~| found `&Fat<[isize; 3]>`
+    //~| expected usize
+    //~| found isize
 
     // With a trait.
     let f1 = Fat { ptr: Foo };
index 8e81eacae921ea90f4b28edd6ced111297fb8f31..c1443bdbb309d691375d26c384d7e5b04a2d3c0a 100644 (file)
@@ -18,5 +18,9 @@ pub fn main() {
     // With a vec of isizes.
     let f1: &Fat<[isize]> = &Fat { ptr: [1, 2, 3] };
     let f2: &Fat<[isize; 3]> = f1;
-    //~^ ERROR mismatched types: expected `&Fat<[isize; 3]>`, found `&Fat<[isize]>`
+    //~^ ERROR mismatched types
+    //~| expected `&Fat<[isize; 3]>`
+    //~| found `&Fat<[isize]>`
+    //~| expected array of 3 elements
+    //~| found slice
 }
index fbc5263d82d1018a0d3825953784eea47c077ddb..92542ab3bcb8114fe9a316806c44c7efb8a462b5 100644 (file)
@@ -15,8 +15,14 @@ struct Foo<'a,'b> {
 
 impl<'a,'b> Foo<'a,'b> {
     fn bar(self: Foo<'b,'a>) {}
-    //~^ ERROR mismatched types: expected `Foo<'a, 'b>`, found `Foo<'b, 'a>`
-    //~^^ ERROR mismatched types: expected `Foo<'a, 'b>`, found `Foo<'b, 'a>`
+    //~^ ERROR mismatched types
+    //~| expected `Foo<'a, 'b>`
+    //~| found `Foo<'b, 'a>`
+    //~| lifetime mismatch
+    //~| ERROR mismatched types
+    //~| expected `Foo<'a, 'b>`
+    //~| found `Foo<'b, 'a>`
+    //~| lifetime mismatch
 }
 
 fn main() {}
index b2394a29899e71ff0eaa23deb2946edd7dcf97ba..5015810ff47742cb86dc0e54d54f9ec0e3bf22e2 100644 (file)
@@ -18,8 +18,16 @@ fn eq<T>(x: T, y: T) { }
 
 fn main() {
     let f = if true { foo } else { bar };
-    //~^ ERROR expected fn item, found a different fn item
+    //~^ ERROR if and else have incompatible types
+    //~| expected `fn(isize) -> isize {foo}`
+    //~| found `fn(isize) -> isize {bar}`
+    //~| expected fn item,
+    //~| found a different fn item
 
     eq(foo, bar);
-    //~^ ERROR expected fn item, found a different fn item
+    //~^ ERROR mismatched types
+    //~|  expected `fn(isize) -> isize {foo}`
+    //~|  found `fn(isize) -> isize {bar}`
+    //~|  expected fn item
+    //~|  found a different fn item
 }
index 3f5a92605b7e90fdfd93b31c3198759d648c3b99..f19e27640cbc7ce460b6a9af3bea66680c59f0c7 100644 (file)
 fn needs_fn<F>(x: F) where F: Fn(isize) -> isize {}
 
 fn main() {
-    let _: () = (box |:_: isize| {}) as Box<FnOnce(isize)>; //~ ERROR object-safe
-    //~^ ERROR Box<core::ops::FnOnce(isize)>
+    let _: () = (box |:_: isize| {}) as Box<FnOnce(isize)>;
+    //~^ ERROR object-safe
+    //~| ERROR mismatched types
+    //~| expected `()`
+    //~| found `Box<core::ops::FnOnce(isize)>`
+    //~| expected ()
+    //~| found box
     let _: () = (box |&:_: isize, isize| {}) as Box<Fn(isize, isize)>;
-    //~^ ERROR Box<core::ops::Fn(isize, isize)>
+    //~^ ERROR mismatched types
+    //~| expected `()`
+    //~| found `Box<core::ops::Fn(isize, isize)>`
+    //~| expected ()
+    //~| found box
     let _: () = (box |&mut:| -> isize unimplemented!()) as Box<FnMut() -> isize>;
-    //~^ ERROR Box<core::ops::FnMut() -> isize>
+    //~^ ERROR mismatched types
+    //~| expected `()`
+    //~| found `Box<core::ops::FnMut() -> isize>`
+    //~| expected ()
+    //~| found box
 
     needs_fn(1is); //~ ERROR `core::ops::Fn(isize) -> isize`
 }
index 5ab946a53e5cc8490e000d9b5af5b6e910e97ec6..029acbff9c33327217b8307a05deb6290b0245fb 100644 (file)
@@ -13,5 +13,9 @@
 fn main() {
     let x: Option<usize>;
     x = 5;
-    //~^ ERROR mismatched types: expected `core::option::Option<usize>`
+    //~^ ERROR mismatched types
+    //~| expected `core::option::Option<usize>`
+    //~| found `_`
+    //~| expected enum `core::option::Option`
+    //~| found integral variable
 }
index 94af50dac0ea5d29f4aa6b02d220bbeed5404e49..ab542d90800b24d85f6804565fd89767278a3a39 100644 (file)
@@ -20,7 +20,11 @@ pub enum foo { }
 
 fn bar(x: x::foo) -> y::foo {
     return x;
-    //~^ ERROR mismatched types: expected `y::foo`, found `x::foo`
+    //~^ ERROR mismatched types
+    //~| expected `y::foo`
+    //~| found `x::foo`
+    //~| expected enum `y::foo`
+    //~| found enum `x::foo`
 }
 
 fn main() {
index 9250444c3e6cd2ba69e4e0adbce1fa7b15d2b60e..d6d668b366aa35006332a51de4b9a6a0746e5e26 100644 (file)
 
 fn bar(x: usize) -> Option<usize> {
     return x;
-    //~^ ERROR mismatched types: expected `core::option::Option<usize>`
+    //~^ ERROR mismatched types
+    //~| expected `core::option::Option<usize>`
+    //~| found `usize`
+    //~| expected enum `core::option::Option`
+    //~| found usize
 }
 
 fn main() {
index 5769b9d7932c03d719bcea7bd02fcdfca39a8efd..3e34344d78b9dfbf9bd3da56caeefb116649af03 100644 (file)
 fn main() {
     // Ensure that the printed type doesn't include the default type params...
     let _: Foo<isize> = ();
-    //~^ ERROR mismatched types: expected `Foo<isize>`, found `()`
+    //~^ ERROR mismatched types
+    //~| expected `Foo<isize>`
+    //~| found `()`
+    //~| expected struct `Foo`
+    //~| found ()
 
     // ...even when they're present, but the same types as the defaults.
     let _: Foo<isize, B, C> = ();
-    //~^ ERROR mismatched types: expected `Foo<isize>`, found `()`
+    //~^ ERROR mismatched types
+    //~| expected `Foo<isize>`
+    //~| found `()`
+    //~| expected struct `Foo`
+    //~| found ()
 
     // Including cases where the default is using previous type params.
     let _: HashMap<String, isize> = ();
-    //~^ ERROR mismatched types: expected `HashMap<collections::string::String, isize>`, found `()`
+    //~^ ERROR mismatched types
+    //~| expected `HashMap<collections::string::String, isize>`
+    //~| found `()`
+    //~| expected struct `HashMap`
+    //~| found ()
     let _: HashMap<String, isize, Hash<String>> = ();
-    //~^ ERROR mismatched types: expected `HashMap<collections::string::String, isize>`, found `()`
+    //~^ ERROR mismatched types
+    //~| expected `HashMap<collections::string::String, isize>`
+    //~| found `()`
+    //~| expected struct `HashMap`
+    //~| found ()
 
     // But not when there's a different type in between.
     let _: Foo<A, isize, C> = ();
-    //~^ ERROR mismatched types: expected `Foo<A, isize>`, found `()`
+    //~^ ERROR mismatched types
+    //~| expected `Foo<A, isize>`
+    //~| found `()`
+    //~| expected struct `Foo`
+    //~| found ()
 
     // And don't print <> at all when there's just defaults.
     let _: Foo<A, B, C> = ();
-    //~^ ERROR mismatched types: expected `Foo`, found `()`
+    //~^ ERROR mismatched types
+    //~| expected `Foo`
+    //~| found `()`
+    //~| expected struct `Foo`
+    //~| found ()
 }
index be54554a3c02ff7d844bfefb50dc7a1346ab7f8e..2209a02c6391846a2d7c2e4220d38614680d0ec9 100644 (file)
@@ -10,5 +10,9 @@
 
 fn main() {
     let x = if true { 10is } else { 10us };
-    //~^ ERROR if and else have incompatible types: expected `isize`, found `usize`
+    //~^ ERROR if and else have incompatible types
+    //~| expected `isize`
+    //~| found `usize`
+    //~| expected isize
+    //~| found usize
 }
index 89beb9a31601b510e3a8e7123cf32bce64a1d12a..a9567f4272f507e97576b0818e08960b66ddef87 100644 (file)
 
 fn main() {
     let a = if true { true };
-//~^ ERROR if may be missing an else clause: expected `()`, found `bool` (expected (), found bool)
+    //~^ ERROR if may be missing an else clause
+    //~| expected `()`
+    //~| found `bool`
+    //~| expected ()
+    //~| found bool
     println!("{}", a);
 }
index 1e42a9447f67a5feda876f8c507167209933b783..5d9314faef98219d1dbcd8c0e371af9569a9f252 100644 (file)
@@ -39,62 +39,242 @@ fn id_u32(n: u32) -> u32 { n }
     fn id_u64(n: u64) -> u64 { n }
 
     id_i8(a8); // ok
-    id_i8(a16); //~ ERROR mismatched types: expected `i8`, found `i16`
-    id_i8(a32); //~ ERROR mismatched types: expected `i8`, found `i32`
-    id_i8(a64); //~ ERROR mismatched types: expected `i8`, found `i64`
+    id_i8(a16);
+    //~^ ERROR mismatched types
+    //~| expected `i8`
+    //~| found `i16`
+    //~| expected i8
+    //~| found i16
+    id_i8(a32);
+    //~^ ERROR mismatched types
+    //~| expected `i8`
+    //~| found `i32`
+    //~| expected i8
+    //~| found i32
+    id_i8(a64);
+    //~^ ERROR mismatched types
+    //~| expected `i8`
+    //~| found `i64`
+    //~| expected i8
+    //~| found i64
 
-    id_i16(a8); //~ ERROR mismatched types: expected `i16`, found `i8`
+    id_i16(a8);
+    //~^ ERROR mismatched types
+    //~| expected `i16`
+    //~| found `i8`
+    //~| expected i16
+    //~| found i8
     id_i16(a16); // ok
-    id_i16(a32); //~ ERROR mismatched types: expected `i16`, found `i32`
-    id_i16(a64); //~ ERROR mismatched types: expected `i16`, found `i64`
+    id_i16(a32);
+    //~^ ERROR mismatched types
+    //~| expected `i16`
+    //~| found `i32`
+    //~| expected i16
+    //~| found i32
+    id_i16(a64);
+    //~^ ERROR mismatched types
+    //~| expected `i16`
+    //~| found `i64`
+    //~| expected i16
+    //~| found i64
 
-    id_i32(a8); //~ ERROR mismatched types: expected `i32`, found `i8`
-    id_i32(a16); //~ ERROR mismatched types: expected `i32`, found `i16`
+    id_i32(a8);
+    //~^ ERROR mismatched types
+    //~| expected `i32`
+    //~| found `i8`
+    //~| expected i32
+    //~| found i8
+    id_i32(a16);
+    //~^ ERROR mismatched types
+    //~| expected `i32`
+    //~| found `i16`
+    //~| expected i32
+    //~| found i16
     id_i32(a32); // ok
-    id_i32(a64); //~ ERROR mismatched types: expected `i32`, found `i64`
+    id_i32(a64);
+    //~^ ERROR mismatched types
+    //~| expected `i32`
+    //~| found `i64`
+    //~| expected i32
+    //~| found i64
 
-    id_i64(a8); //~ ERROR mismatched types: expected `i64`, found `i8`
-    id_i64(a16); //~ ERROR mismatched types: expected `i64`, found `i16`
-    id_i64(a32); //~ ERROR mismatched types: expected `i64`, found `i32`
+    id_i64(a8);
+    //~^ ERROR mismatched types
+    //~| expected `i64`
+    //~| found `i8`
+    //~| expected i64
+    //~| found i8
+    id_i64(a16);
+    //~^ ERROR mismatched types
+    //~| expected `i64`
+    //~| found `i16`
+    //~| expected i64
+    //~| found i16
+    id_i64(a32);
+    //~^ ERROR mismatched types
+    //~| expected `i64`
+    //~| found `i32`
+    //~| expected i64
+    //~| found i32
     id_i64(a64); // ok
 
     id_i8(c8); // ok
-    id_i8(c16); //~ ERROR mismatched types: expected `i8`, found `i16`
-    id_i8(c32); //~ ERROR mismatched types: expected `i8`, found `i32`
-    id_i8(c64); //~ ERROR mismatched types: expected `i8`, found `i64`
+    id_i8(c16);
+    //~^ ERROR mismatched types
+    //~| expected `i8`
+    //~| found `i16`
+    //~| expected i8
+    //~| found i16
+    id_i8(c32);
+    //~^ ERROR mismatched types
+    //~| expected `i8`
+    //~| found `i32`
+    //~| expected i8
+    //~| found i32
+    id_i8(c64);
+    //~^ ERROR mismatched types
+    //~| expected `i8`
+    //~| found `i64`
+    //~| expected i8
+    //~| found i64
 
-    id_i16(c8); //~ ERROR mismatched types: expected `i16`, found `i8`
+    id_i16(c8);
+    //~^ ERROR mismatched types
+    //~| expected `i16`
+    //~| found `i8`
+    //~| expected i16
+    //~| found i8
     id_i16(c16); // ok
-    id_i16(c32); //~ ERROR mismatched types: expected `i16`, found `i32`
-    id_i16(c64); //~ ERROR mismatched types: expected `i16`, found `i64`
+    id_i16(c32);
+    //~^ ERROR mismatched types
+    //~| expected `i16`
+    //~| found `i32`
+    //~| expected i16
+    //~| found i32
+    id_i16(c64);
+    //~^ ERROR mismatched types
+    //~| expected `i16`
+    //~| found `i64`
+    //~| expected i16
+    //~| found i64
 
-    id_i32(c8); //~ ERROR mismatched types: expected `i32`, found `i8`
-    id_i32(c16); //~ ERROR mismatched types: expected `i32`, found `i16`
+    id_i32(c8);
+    //~^ ERROR mismatched types
+    //~| expected `i32`
+    //~| found `i8`
+    //~| expected i32
+    //~| found i8
+    id_i32(c16);
+    //~^ ERROR mismatched types
+    //~| expected `i32`
+    //~| found `i16`
+    //~| expected i32
+    //~| found i16
     id_i32(c32); // ok
-    id_i32(c64); //~ ERROR mismatched types: expected `i32`, found `i64`
+    id_i32(c64);
+    //~^ ERROR mismatched types
+    //~| expected `i32`
+    //~| found `i64`
+    //~| expected i32
+    //~| found i64
 
-    id_i64(a8); //~ ERROR mismatched types: expected `i64`, found `i8`
-    id_i64(a16); //~ ERROR mismatched types: expected `i64`, found `i16`
-    id_i64(a32); //~ ERROR mismatched types: expected `i64`, found `i32`
+    id_i64(a8);
+    //~^ ERROR mismatched types
+    //~| expected `i64`
+    //~| found `i8`
+    //~| expected i64
+    //~| found i8
+    id_i64(a16);
+    //~^ ERROR mismatched types
+    //~| expected `i64`
+    //~| found `i16`
+    //~| expected i64
+    //~| found i16
+    id_i64(a32);
+    //~^ ERROR mismatched types
+    //~| expected `i64`
+    //~| found `i32`
+    //~| expected i64
+    //~| found i32
     id_i64(a64); // ok
 
     id_u8(b8); // ok
-    id_u8(b16); //~ ERROR mismatched types: expected `u8`, found `u16`
-    id_u8(b32); //~ ERROR mismatched types: expected `u8`, found `u32`
-    id_u8(b64); //~ ERROR mismatched types: expected `u8`, found `u64`
+    id_u8(b16);
+    //~^ ERROR mismatched types
+    //~| expected `u8`
+    //~| found `u16`
+    //~| expected u8
+    //~| found u16
+    id_u8(b32);
+    //~^ ERROR mismatched types
+    //~| expected `u8`
+    //~| found `u32`
+    //~| expected u8
+    //~| found u32
+    id_u8(b64);
+    //~^ ERROR mismatched types
+    //~| expected `u8`
+    //~| found `u64`
+    //~| expected u8
+    //~| found u64
 
-    id_u16(b8); //~ ERROR mismatched types: expected `u16`, found `u8`
+    id_u16(b8);
+    //~^ ERROR mismatched types
+    //~| expected `u16`
+    //~| found `u8`
+    //~| expected u16
+    //~| found u8
     id_u16(b16); // ok
-    id_u16(b32); //~ ERROR mismatched types: expected `u16`, found `u32`
-    id_u16(b64); //~ ERROR mismatched types: expected `u16`, found `u64`
+    id_u16(b32);
+    //~^ ERROR mismatched types
+    //~| expected `u16`
+    //~| found `u32`
+    //~| expected u16
+    //~| found u32
+    id_u16(b64);
+    //~^ ERROR mismatched types
+    //~| expected `u16`
+    //~| found `u64`
+    //~| expected u16
+    //~| found u64
 
-    id_u32(b8); //~ ERROR mismatched types: expected `u32`, found `u8`
-    id_u32(b16); //~ ERROR mismatched types: expected `u32`, found `u16`
+    id_u32(b8);
+    //~^ ERROR mismatched types
+    //~| expected `u32`
+    //~| found `u8`
+    //~| expected u32
+    //~| found u8
+    id_u32(b16);
+    //~^ ERROR mismatched types
+    //~| expected `u32`
+    //~| found `u16`
+    //~| expected u32
+    //~| found u16
     id_u32(b32); // ok
-    id_u32(b64); //~ ERROR mismatched types: expected `u32`, found `u64`
+    id_u32(b64);
+    //~^ ERROR mismatched types
+    //~| expected `u32`
+    //~| found `u64`
+    //~| expected u32
+    //~| found u64
 
-    id_u64(b8); //~ ERROR mismatched types: expected `u64`, found `u8`
-    id_u64(b16); //~ ERROR mismatched types: expected `u64`, found `u16`
-    id_u64(b32); //~ ERROR mismatched types: expected `u64`, found `u32`
+    id_u64(b8);
+    //~^ ERROR mismatched types
+    //~| expected `u64`
+    //~| found `u8`
+    //~| expected u64
+    //~| found u8
+    id_u64(b16);
+    //~^ ERROR mismatched types
+    //~| expected `u64`
+    //~| found `u16`
+    //~| expected u64
+    //~| found u16
+    id_u64(b32);
+    //~^ ERROR mismatched types
+    //~| expected `u64`
+    //~| found `u32`
+    //~| expected u64
+    //~| found u32
     id_u64(b64); // ok
 }
index fbbe4cf8dbc4b7cd69379074c46b8f3af56603f5..3374f715917c20af3cf13ae41015c4701ffb5847 100644 (file)
@@ -11,5 +11,9 @@
 fn main() {
     let mut x = 2;
     x = 5.0;
-//~^ ERROR expected `_`, found `_` (expected integral variable, found floating-point variable)
+    //~^ ERROR mismatched types
+    //~| expected `_`
+    //~| found `_`
+    //~| expected integral variable
+    //~| found floating-point variable
 }
index 832cc57bd24df396049d650659ff09a7d55a335c..6e84e777898b6d7622ae41c5df3223998a6b9991 100644 (file)
 
 fn f() -> isize {
     (return 1, return 2)
-//~^ ERROR mismatched types: expected `isize`, found `(_, _)` (expected isize, found tuple)
+//~^ ERROR mismatched types
+//~| expected `isize`
+//~| found `(_, _)`
+//~| expected isize
+//~| found tuple
 }
 
 fn main() {}
index c818b3bb26ce6a8d39dabbf2d75e50e4585a45a3..d3e44b71b1c89e44957f17783a7d7a72b089783c 100644 (file)
 
 fn main() {
     match Some(10) {
-    //~^ ERROR match arms have incompatible types: expected `bool`, found `()`
+    //~^ ERROR match arms have incompatible types:
+    //~| expected `bool`
+    //~| found `()`
+    //~| expected bool
+    //~| found ()
         Some(5) => false,
         Some(2) => true,
         None    => (), //~ NOTE match arm with an incompatible type
index 7ce23e1f6ac7971db75d516a2a4d243f92f88487..2de86e527ef594460289a4307d522cd75e6918a1 100644 (file)
 fn main() {
     let x = ();
     1 +
-    x //~ ERROR mismatched types: expected `_`, found `()` (expected integral variable, found ())
+    x //~  ERROR mismatched types
+      //~| expected `_`
+      //~| found `()`
+      //~| expected integral variable
+      //~| found ()
     ;
 
     let x: () = ();
     1 +
-    x //~ ERROR mismatched types: expected `_`, found `()` (expected integral variable, found ())
+    x //~  ERROR mismatched types
+      //~| expected `_`
+      //~| found `()`
+      //~| expected integral variable
+      //~| found ()
     ;
 }
index 39957a242268f885d4fc40d6a480e55846c1c538..1cf534e7e419db0b0403181a71ac5d36dd8fc10b 100644 (file)
 
 //! Test that makes sure wrongly-typed bench functions are rejected
 
-// error-pattern:expected &-ptr, found isize
 #[bench]
 fn bar(x: isize) { }
+//~^ ERROR mismatched types
+//~| expected `fn(&mut test::Bencher)`
+//~| found `fn(isize) {bar}`
+//~| expected &-ptr
+//~| found isize
index eee82483cae1daa052d4393158229d4218a12feb..61b50ef705f6a44f8acc388136e73e6f5ba55f80 100644 (file)
@@ -35,5 +35,9 @@ fn check<'r, I: Iterator<Item=usize>, T: Itble<'r, usize, I>>(cont: &T) -> bool
 
 fn main() {
     check((3us, 5us));
-//~^ ERROR mismatched types: expected `&_`, found `(usize, usize)` (expected &-ptr, found tuple)
+//~^ ERROR mismatched types
+//~| expected `&_`
+//~| found `(usize, usize)`
+//~| expected &-ptr
+//~| found tuple
 }
index 2e33886037708f32bd8bf10579434cd78c68bfd4..c53e5760941f15d9611f00255eafc5cc1d8e6b95 100644 (file)
@@ -14,8 +14,16 @@ fn bar(_s: u32) { }
 
 fn main() {
     foo(1*(1 as isize));
-    //~^ ERROR: mismatched types: expected `i16`, found `isize` (expected i16, found isize)
+    //~^ ERROR mismatched types
+    //~| expected `i16`
+    //~| found `isize`
+    //~| expected i16
+    //~| found isize
 
     bar(1*(1 as usize));
-    //~^ ERROR: mismatched types: expected `u32`, found `usize` (expected u32, found usize)
+    //~^ ERROR mismatched types
+    //~| expected `u32`
+    //~| found `usize`
+    //~| expected u32
+    //~| found usize
 }
index 7d554545b5ed27c94fbbc9b786a7794eff48ff92..09e2905dc401be3563ae5814db429f20032e3587 100644 (file)
@@ -15,7 +15,18 @@ pub fn main() {
     // the actual arm `Result<T, E>` has two. typeck should not be
     // tricked into looking up a non-existing second type parameter.
     let _x: usize = match Some(1us) {
-        Ok(u) => u, //~ ERROR  mismatched types: expected `core::option::Option<usize>`
-        Err(e) => panic!(e)  //~ ERROR mismatched types: expected `core::option::Option<usize>`
+        Ok(u) => u,
+        //~^ ERROR mismatched types
+        //~| expected `core::option::Option<usize>`
+        //~| found `core::result::Result<_, _>`
+        //~| expected enum `core::option::Option`
+        //~| found enum `core::result::Result`
+
+        Err(e) => panic!(e)
+        //~^ ERROR mismatched types
+        //~| expected `core::option::Option<usize>`
+        //~| found `core::result::Result<_, _>`
+        //~| expected enum `core::option::Option`
+        //~| found enum `core::result::Result`
     };
 }
index ef7d3d4d158d9fdcb202c4e0a0944acf10f7d13c..86a79416c77bc6807d16123c3d209a0170165608 100644 (file)
@@ -14,8 +14,11 @@ fn main() {
     let x = [1,2];
     let y = match x {
         [] => None,
-        //~^ ERROR types: expected `[_#0i; 2]`, found `[_#7t; 0]`
-        //         (expected array of 2 elements, found array of 0 elements)
+//~^ ERROR mismatched types
+//~| expected `[_#0i; 2]`
+//~| found `[_#7t; 0]`
+//~| expected an array with a fixed size of 2 elements
+//~| found one with 0 elements
         [a,_] => Some(a)
     };
 }
index 157280b1719ad2ca3a096f0c0692667b11421236..a345ce79612cc37ed80088b1b458b7ebc2820a47 100644 (file)
@@ -12,8 +12,10 @@ fn main() {
   let x = [1,2];
   let y = match x {
     [] => None,
-//~^ ERROR types: expected `[_; 2]`, found `[_; 0]`
-//         (expected array of 2 elements, found array of 0 elements)
+    //~^ ERROR mismatched types
+    //~| expected `[_; 2]`
+    //~| found `[_; 0]`
+    //~| expected array with a fixed size of 2 elements
     [a,_] => Some(a)
   };
 }
index 83612823c591a94970c6fd506bce859947d17559..2a5805790a742798ab39423e239bf75b14d450a3 100644 (file)
@@ -15,7 +15,11 @@ pub enum Enum {
 
   pub fn get_enum_struct_variant() -> () {
     Enum::EnumStructVariant { x: 1, y: 2, z: 3 }
-//~^ ERROR mismatched types: expected `()`, found `a::Enum` (expected (), found enum a::Enum)
+    //~^ ERROR mismatched types
+    //~| expected `()`
+    //~| found `a::Enum`
+    //~| expected ()
+    //~| found enum `a::Enum`
   }
 }
 
@@ -27,8 +31,11 @@ fn test_enum_struct_variant() {
       let enum_struct_variant = ::a::get_enum_struct_variant();
       match enum_struct_variant {
         a::Enum::EnumStructVariant { x, y, z } => {
-        //~^ ERROR mismatched types: expected `()`, found `a::Enum`
-        //         (expected (), found enum a::Enum)
+        //~^ ERROR mismatched types
+        //~| expected `()`
+        //~| found `a::Enum`
+        //~| expected ()
+        // found enum `a::Enum`
         }
       }
     }
index c2ad09f5cb4b1b5b86e42923aaabc95eedfcf87a..3ceb465cb4b23c0ed59fd5313b0031e1dcb402b7 100644 (file)
@@ -8,6 +8,10 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// error-pattern: expected `bool`, found `_` (expected bool, found integral variable)
+// error-pattern:mismatched types
+// error-pattern:expected `bool`
+// error-pattern:found `_`
+// error-pattern:expected bool
+// error-pattern:found integral variable
 
 fn main(){assert!(1,1);}
index ac49f8b99cf2d7b399d839ede01e8fa67d690439..deb8f00cd01c9b14ff3fc422b9ba729d55698493 100644 (file)
@@ -13,8 +13,11 @@ struct vec3 { y: f32, z: f32 }
 
 fn make(v: vec2) {
     let vec3 { y: _, z: _ } = v;
-    //~^ ERROR mismatched types: expected `vec2`, found `vec3`
-    //         (expected struct vec2, found struct vec3)
+    //~^ ERROR mismatched types
+    //~| expected `vec2`
+    //~| found `vec3`
+    //~| expected struct `vec2`
+    //~| found struct `vec3`
 }
 
 fn main() { }
index 5166d84a0254362f12a0503a282ad3f79440936a..d7ff6f2fe63ce38f423aad11654552febbbba6b6 100644 (file)
@@ -16,9 +16,17 @@ struct X {
 fn main() {
     let x = X { a: [0] };
     let _f = &x.a as *mut u8;
-    //~^ ERROR mismatched types: expected `*mut u8`, found `&[u8; 1]`
+    //~^ ERROR mismatched types
+    //~| expected `*mut u8`
+    //~| found `&[u8; 1]`
+    //~| expected u8
+    //~| found array of 1 elements
 
     let local = [0u8];
     let _v = &local as *mut u8;
-    //~^ ERROR mismatched types: expected `*mut u8`, found `&[u8; 1]`
+    //~^ ERROR mismatched types
+    //~| expected `*mut u8`
+    //~| found `&[u8; 1]`
+    //~| expected u8,
+    //~| found array of 1 elements
 }
index 3d8ebc1ecdf19e517bb197f93fe36bbece65ca47..22ba54fea14694f86c9dd2594698c5a395c46cdd 100644 (file)
@@ -20,8 +20,7 @@ struct X { data: u32 }
 
 impl Something for X {
     fn yay<T: Str>(_:Option<X>, thing: &[T]) {
-//~^ ERROR in method `yay`, type parameter 0 requires bound `Str`, which is not required
-
+    //~^ ERROR the requirement `T : Str` appears on the impl method
     }
 }
 
index 1b1b03023839dbf045c01e27f8e73fb861dd18e3..7080db23d42e521c8b42ddb609579128603a24d8 100644 (file)
@@ -14,7 +14,12 @@ pub fn foo(params: Option<&[&str]>) -> usize {
 
 fn main() {
     let name = "Foo";
-    let msg = foo(Some(&[name.as_slice()]));
-//~^ ERROR mismatched types: expected `core::option::Option<&[&str]>`
+    let x = Some(&[name.as_slice()]);
+    let msg = foo(x);
+//~^ ERROR mismatched types
+//~| expected `core::option::Option<&[&str]>`
+//~| found `core::option::Option<&[&str; 1]>`
+//~| expected slice
+//~| found array of 1 elements
     assert_eq!(msg, 3);
 }
index c4373ba3351575d09b5c2252f30b136c950098e9..7381ade263b20ebeca862abcb25878beefa7b1b9 100644 (file)
@@ -19,8 +19,11 @@ enum E { B(R, Tau) }
     let u = match e {
         E::B(
           Tau{t: x},
-          //~^ ERROR mismatched types: expected `main::R`, found `main::Tau`
-          //        (expected enum main::R, found struct main::Tau)
+          //~^ ERROR mismatched types
+          //~| expected `main::R`
+          //~| found `main::Tau`
+          //~| expected enum `main::R`
+          //~| found struct `main::Tau`
           _) => x,
     };
 }
index f62bccb22f3595a738ce1f062e57268083bb6260..ba936561ae53d9ed7bda362e5447369e62414755 100644 (file)
 
 fn main() {
     let Slice { data: data, len: len } = "foo";
-    //~^ ERROR mismatched types: expected `&str`, found `core::raw::Slice<_>`
-    //         (expected &-ptr, found struct core::raw::Slice)
+    //~^ ERROR mismatched types
+    //~| expected `&str`
+    //~| found `core::raw::Slice<_>`
+    //~| expected &-ptr
+    //~| found struct `core::raw::Slice`
 }
 
index 4890cc52c00052252cde3f392657bb4e3cc768ac..b943ef510da28fbf7a3978bf01f8dcf65bbf1604 100644 (file)
 fn main() {
     match () {
         Slice { data: data, len: len } => (),
-        //~^ ERROR mismatched types: expected `()`, found `core::raw::Slice<_>`
-        //         (expected (), found struct core::raw::Slice)
+        //~^ ERROR mismatched types
+        //~| expected `()`
+        //~| found `core::raw::Slice<_>`
+        //~| expected ()
+        //~| found struct `core::raw::Slice`
         _ => unreachable!()
     }
 }
index 5048a9aa919c6e3dc8381b035bf31ac3ef4fb796..6010e206920e5eeaa95dd537211a390b22fb3d14 100644 (file)
 #![feature(overloaded_calls)]
 
 fn f<'r>(p: &'r mut fn(p: &mut ())) {
-    (*p)(()) //~ ERROR mismatched types: expected `&mut ()`, found `()`
+    (*p)(()) //~  ERROR mismatched types
+             //~| expected `&mut ()`
+             //~| found `()`
+             //~| expected &-ptr
+             //~| found ()
 }
 
 fn main() {}
index 0c9fd9d9486d65ea0d14f3b53fdda47d2b66bb6b..4889658d083c1c31804ecf17c2b94332ace33c0b 100644 (file)
@@ -21,17 +21,29 @@ fn main() {
 
     // `x { ... }` should not be interpreted as a struct literal here
     if x = x {
-        //~^ ERROR mismatched types: expected `bool`, found `()` (expected bool, found ())
+        //~^ ERROR mismatched types
+        //~| expected `bool`
+        //~| found `()`
+        //~| expected bool
+        //~| found ()
         println!("{}", x);
     }
     // Explicit parentheses on the left should match behavior of above
     if (x = x) {
-        //~^ ERROR mismatched types: expected `bool`, found `()` (expected bool, found ())
+        //~^ ERROR mismatched types
+        //~| expected `bool`
+        //~| found `()`
+        //~| expected bool
+        //~| found ()
         println!("{}", x);
     }
     // The struct literal interpretation is fine with explicit parentheses on the right
     if y = (Foo { foo: x }) {
-        //~^ ERROR mismatched types: expected `bool`, found `()` (expected bool, found ())
+        //~^ ERROR mismatched types
+        //~| expected `bool`
+        //~| found `()`
+        //~| expected bool
+        //~| found ()
         println!("{}", x);
     }
 }
index 73f86fee903e5b7bfe910ef8d4aeeb7daff99108..b4791eba76e264fb3c071feaaf502b54dfa28a6d 100644 (file)
@@ -14,8 +14,14 @@ struct Foo<'a> {
 
 impl <'a> Foo<'a>{
     fn bar(self: &mut Foo) {
-    //~^ mismatched types: expected `Foo<'a>`, found `Foo<'_>` (lifetime mismatch)
-    //~| mismatched types: expected `Foo<'a>`, found `Foo<'_>` (lifetime mismatch)
+    //~^ mismatched types
+    //~| expected `Foo<'a>`
+    //~| found `Foo<'_>`
+    //~| lifetime mismatch
+    //~| mismatched types
+    //~| expected `Foo<'a>`
+    //~| found `Foo<'_>`
+    //~| lifetime mismatch
     }
 }
 
index 1418cdf403993f7865ee094ca5a1a3094f14db46..9d1047f68e6c7f6ba16f513d86a3c525dc4c919b 100644 (file)
@@ -16,7 +16,10 @@ impl Pair<
     isize
 > {
     fn say(self: &Pair<&str, isize>) {
-//~^ ERROR mismatched types: expected `Pair<&'static str, isize>`, found `Pair<&str, isize>`
+//~^ ERROR mismatched types
+//~| expected `Pair<&'static str, isize>`
+//~| found `Pair<&str, isize>`
+//~| lifetime mismatch
         println!("{}", self);
     }
 }
index 0f1dbfa349277f215bccab001534fb8111bf4d88..2d73b98ec1e607d201c17318d507f78a9aca760e 100644 (file)
 // clause does not exist, instead of the unsympathetic "match arms have incompatible types"
 
 fn main() {
-    if let Some(homura) = Some("madoka") { //~ ERROR missing an else clause: expected `()`
+    if let Some(homura) = Some("madoka") { //~  ERROR missing an else clause
+                                           //~| expected `()`
+                                           //~| found `i32`
+                                           //~| expected ()
+                                           //~| found i32
         765i32
     };
 }
index b141c1f441aeb436f08313a42b7d308d8ab7508a..31796e5e20c4492e683642701852db9bc439bfdf 100644 (file)
@@ -20,7 +20,8 @@ struct E {
 }
 
 impl A for E {
-  fn b<F: Sync, G>(_x: F) -> F { panic!() } //~ ERROR type parameter 0 requires `Sync`
+    fn b<F: Sync, G>(_x: F) -> F { panic!() }
+    //~^ ERROR `F : core::marker::Sync` appears on the impl method
 }
 
 fn main() {}
index 694bf05b21035b432e2a9c5e1a41138fae96d502..d0781b5658087393e06aec24f0cbfcbb2b16000d 100644 (file)
 
 fn foo<T, U>(x: T, y: U) {
     let mut xx = x;
-    xx = y; //~ ERROR expected `T`, found `U`
+    xx = y;
+    //~^  ERROR mismatched types
+    //~| expected `T`
+    //~| found `U`
+    //~| expected type parameter
+    //~| found a different type parameter
 }
 
 fn main() {
index 798a8cfec9a6e202bd1e194e74c2ca53a479d836..5e7c23164cbbbbe65f35aa29e73703b35299d5a7 100644 (file)
@@ -9,5 +9,10 @@
 // except according to those terms.
 
 fn main() {
-    let _p: char = 100; //~ ERROR mismatched types: expected `char`, found
+    let _p: char = 100;
+    //~^ ERROR mismatched types
+    //~| expected `char`
+    //~| found `u8`
+    //~| expected char
+    //~| found u8
 }
index 86ab9be77fc6808389e948f913e33d1ac10ff23e..7ebc5b7a5b96bf3757311379e0ac7aa5ee2ce235 100644 (file)
 
 trait A {
     fn a(&self) {
-        |&:| self.b() //~ ERROR type `&Self` does not implement any method in scope named `b`
-        //~^ ERROR expected (), found closure
+        |&:| self.b()
+        //~^ ERROR type `&Self` does not implement any method in scope named `b`
+        //~| ERROR mismatched types
+        //~| expected `()`
+        //~| found closure
+        //~| expected ()
+        //~| found closure
     }
 }
 fn main() {}
index f018a02a945a925ee04b8fdc5f46a862ff57038f..4aff95b57decbb0c7115bf6bd8d1b046b35407a6 100644 (file)
 fn main() {
     match None {
         Err(_) => ()
-        //~^ ERROR mismatched types: expected `core::option::Option<_>`
-        //         , found `core::result::Result<_, _>`
+        //~^ ERROR mismatched types
+        //~| expected `core::option::Option<_>`
+        //~| found `core::result::Result<_, _>`
+        //~| expected enum `core::option::Option`
+        //~| found enum `core::result::Result`
     }
 }
index 0391c73d90a6cca8032e62e0584c8a659a21ebe0..b5af1f03b635b82d803734034124352eb8f69173 100644 (file)
@@ -12,7 +12,11 @@ fn main() {
     let a = if true {
         0
     } else if false {
-//~^ ERROR if may be missing an else clause: expected `()`, found `_`
+//~^ ERROR if may be missing an else clause
+//~| expected `()`
+//~| found `_`
+//~| expected ()
+//~| found integral variable
         1
     };
 }
index 1943f1e5a195481daff5c649382706d4ee9e506f..881e124fd689289858e82a12ceac9f9a5d4c1410 100644 (file)
@@ -13,6 +13,9 @@ fn bar(int_param: usize) {}
 fn main() {
     let foo: [u8; 4] = [1u8; 4us];
     bar(foo);
-    //~^ ERROR mismatched types: expected `usize`, found `[u8; 4]`
-    //         (expected usize, found vector)
+    //~^ ERROR mismatched types
+    //~| expected `usize`
+    //~| found `[u8; 4]`
+    //~| expected usize
+    //~| found array of 4 elements
 }
index 88933c0add9292b828c610d6559c72a385f78433..e7cd20f38a1d20e052470b6ef9a549ca9b8ec18b 100644 (file)
@@ -13,6 +13,9 @@
 const A: (isize,isize) = (4,2);
 fn main() {
     match 42 { A => () }
-    //~^ ERROR mismatched types: expected `_`, found `(isize, isize)`
-    //         (expected integral variable, found tuple)
+    //~^ ERROR mismatched types
+    //~| expected `_`
+    //~| found `(isize, isize)`
+    //~| expected integral variable
+    //~| found tuple
 }
index ca7f87ff61ae3ccc2638901125ef3cec6532dc26..b051abbc7ff5025af9ff846a0dfa88288628bfb2 100644 (file)
@@ -15,28 +15,48 @@ enum A { B, C }
 fn main() {
     match (true, false) {
         A::B => (),
-//~^ ERROR mismatched types: expected `(bool, bool)`, found `A` (expected tuple, found enum A)
+//~^ ERROR mismatched types:
+//~| expected `(bool, bool)`
+//~| found `A`
+//~| expected tuple
+//~| found enum `A`
         _ => ()
     }
 
     match (true, false) {
         (true, false, false) => ()
-//~^ ERROR mismatched types: expected `(bool, bool)`, found `(_, _, _)`
+//~^ ERROR mismatched types
+//~| expected `(bool, bool)`
+//~| found `(_, _, _)`
+//~| expected a tuple with 2 elements
+//~| found one with 3 elements
     }
 
     match (true, false) {
         (true, false, false) => ()
-//~^ ERROR (expected a tuple with 2 elements, found one with 3 elements)
+//~^ ERROR mismatched types
+//~| expected `(bool, bool)`
+//~| found `(_, _, _)`
+//~| expected a tuple with 2 elements
+//~| found one with 3 elements
     }
 
     match (true, false) {
         box (true, false) => ()
-//~^ ERROR mismatched types: expected `(bool, bool)`, found `Box<_>` (expected tuple, found box)
+//~^ ERROR mismatched types
+//~| expected `(bool, bool)`
+//~| found `Box<_>`
+//~| expected tuple
+//~| found box
     }
 
     match (true, false) {
         &(true, false) => ()
-//~^ ERROR mismatched types: expected `(bool, bool)`, found `&_` (expected tuple, found &-ptr)
+//~^ ERROR mismatched types
+//~| expected `(bool, bool)`
+//~| found `&_`
+//~| expected tuple
+//~| found &-ptr
     }
 
 
@@ -47,5 +67,9 @@ fn main() {
     for &(x,y) in v.iter() {} // should be OK
 
     // Make sure none of the errors above were fatal
-    let x: char = true; //~ ERROR expected `char`, found `bool`
+    let x: char = true; //~  ERROR mismatched types
+                        //~| expected `char`
+                        //~| found `bool`
+                        //~| expected char
+                        //~| found bool
 }
index 96bad3a6a44551115c3a3fa0554aabb13b6966fa..32702d3e2f6fee2245caac9b59a4db008e938213 100644 (file)
@@ -13,7 +13,12 @@ enum Either<T, U> { Left(T), Right(U) }
 
 fn main() {
     match S(Either::Left(5)) {
-        Either::Right(_) => {}  //~ ERROR mismatched types: expected `S`, found `Either
+        Either::Right(_) => {}
+        //~^ ERROR mismatched types
+        //~| expected `S`
+        //~| found `Either<_, _>`
+        //~| expected struct `S`
+        //~| found enum `Either`
         _ => {}
     }
 }
index 56867349065a598a5ac5a74841237d5d078afef1..565634191be9a8808099c81f6ad7dbe5ecd5be15 100644 (file)
@@ -10,5 +10,9 @@
 
 fn main() {
     &panic!()
-    //~^ ERROR mismatched types: expected `()`, found `&_` (expected (), found &-ptr)
+    //~^ ERROR mismatched types
+    //~| expected `()`
+    //~| found `&_`
+    //~| expected ()
+    //~| found &-ptr
 }
index c6869c44057f924885e18f2572723d5c7cfe1a52..e261249bc998e7b5320e904294973f6330049312 100644 (file)
 
 impl<'a> BarStruct {
     fn foo(&'a mut self) -> Box<BarStruct> { self }
-    //~^ ERROR: error: mismatched types: expected `Box<BarStruct>`, found `&'a mut BarStruct
+    //~^ ERROR mismatched types
+    //~| expected `Box<BarStruct>`
+    //~| found `&'a mut BarStruct`
+    //~| expected box
+    //~| found &-ptr
 }
 
 fn main() {}
index 116639f49459f6b4c716758f7b8e85b6fc8bf169..eefb34fbe4c91121419867aa10086f8defdc7083 100644 (file)
@@ -14,7 +14,11 @@ enum Whatever {
 fn foo(x: Whatever) {
     match x {
         Some(field) =>
-//~^ ERROR: mismatched types: expected `Whatever`, found `core::option::Option<_>`
+//~^ ERROR mismatched types
+//~| expected `Whatever`
+//~| found `core::option::Option<_>`
+//~| expected enum `Whatever`
+//~| found enum `core::option::Option`
             field.access(), //~ ERROR the type of this value must be known in this context
     }
 }
index e459a243cc8a505b04422ee235035d9110a0a19a..0e81ec19c815a68c7c8cfe428949517f7ffe78ac 100644 (file)
@@ -14,14 +14,27 @@ mod foo { pub fn bar() {} }
 
 fn main() {
     match (true, false) {
-        A::B => (), //~ ERROR expected `(bool, bool)`, found `A` (expected tuple, found enum A)
+        A::B => (),
+        //~^ ERROR mismatched types
+        //~| expected `(bool, bool)`
+        //~| found `A`
+        //~| expected tuple
+        //~| found enum `A`
         _ => ()
     }
 
     match &Some(42is) {
-        Some(x) => (), //~ ERROR expected `&core::option::Option<isize>`,
-                       //        found `core::option::Option<_>`
-        None => ()     //~ ERROR expected `&core::option::Option<isize>`,
-                       //        found `core::option::Option<_>`
+        Some(x) => (),
+        //~^ ERROR mismatched types
+        //~| expected `&core::option::Option<isize>`
+        //~| found `core::option::Option<_>`
+        //~| expected &-ptr
+        //~| found enum `core::option::Option`
+        None => ()
+        //~^ ERROR mismatched types
+        //~| expected `&core::option::Option<isize>`
+        //~| found `core::option::Option<_>`
+        //~| expected &-ptr
+        //~| found enum `core::option::Option`
     }
 }
index 3f9e92afba2b178915617868092faabd73f49594..30e4ec8ad0e6d104a25e499b2ad32544aece5e47 100644 (file)
 
 enum Foo {
     A = 1i64,
-    //~^ ERROR mismatched types: expected `isize`, found `i64`
+    //~^ ERROR mismatched types
+    //~| expected `isize`
+    //~| found `i64`
+    //~| expected isize
+    //~| found i64
     B = 2u8
-    //~^ ERROR mismatched types: expected `isize`, found `u8`
+    //~^ ERROR mismatched types
+    //~| expected `isize`
+    //~| found `u8`
+    //~| expected isize
+    //~| found u8
 }
 
 fn main() {}
index e3b47372a4f401d2e37fbf4efa5f3863e8d199d2..5bda37896879bb3ff39de012b47239b8f49a6519 100644 (file)
@@ -14,7 +14,12 @@ enum E { C(isize) }
 
 fn main() {
     match (S { a: 1 }) {
-        E::C(_) => (), //~ ERROR mismatched types: expected `S`, found `E`
+        E::C(_) => (),
+        //~^ ERROR mismatched types
+        //~| expected `S`
+        //~| found `E`
+        //~| expected struct `S`
+        //~| found enum `E`
         _ => ()
     }
 }
index 6bb049f3ca5e805bb21d45a2705c3029e0b1b7e0..a4abdf3ddfe94f14f7189ceeb11741be4b25874b 100644 (file)
 fn main() {
     match () {
         [()] => { }
-//~^ ERROR mismatched types: expected `()`, found `&[_]` (expected (), found &-ptr)
+        //~^ ERROR mismatched types
+        //~| expected `()`
+        //~| found `&[_]`
+        //~| expected ()
+        //~| found &-ptr
     }
 }
index 178b73199766e2a49bb2cab3c3339cdd1ac0de2e..4d416ed42debfadf95379a132609a6c707da2f9d 100644 (file)
@@ -18,7 +18,19 @@ fn bar(&self) {}
 
 fn main() {
     let x = Foo;
-    Foo::bar(x); //~ERROR mismatched types: expected `&Foo`, found `Foo`
-    Foo::bar(&&x); //~ERROR mismatched types: expected `&Foo`, found `&&Foo`
-    Foo::bar(&42is); //~ERROR mismatched types: expected `&Foo`, found `&isize`
+    Foo::bar(x); //~  ERROR mismatched types
+                 //~| expected `&Foo`
+                 //~| found `Foo`
+                 //~| expected &-ptr
+                 //~| found struct `Foo`
+    Foo::bar(&&x); //~  ERROR mismatched types
+                   //~| expected `&Foo`
+                   //~| found `&&Foo`
+                   //~| expected struct `Foo`
+                   //~| found &-ptr
+    Foo::bar(&42is); //~  ERROR mismatched types
+                     //~| expected `&Foo`
+                     //~| found `&isize`
+                     //~| expected struct `Foo`
+                     //~| found isize
 }
index 9f1d3d1fb391298559d99fc576f4b23b3304ea9a..a3d016d756ffce9d8ec0211d7dab533090787e23 100644 (file)
@@ -13,12 +13,18 @@ fn main() {
 
     // (separate lines to ensure the spans are accurate)
 
-     let &_ //~ ERROR expected `&mut isize`, found `&_`
+     let &_ //~  ERROR mismatched types
+            //~| expected `&mut isize`
+            //~| found `&_`
+            //~| values differ in mutability
         = foo;
     let &mut _ = foo;
 
     let bar = &1is;
     let &_ = bar;
-    let &mut _ //~ ERROR expected `&isize`, found `&mut _`
+    let &mut _ //~  ERROR mismatched types
+               //~| expected `&isize`
+               //~| found `&mut _`
+               //~| values differ in mutability
          = bar;
 }
diff --git a/src/test/compile-fail/no-type-for-node-ice.rs b/src/test/compile-fail/no-type-for-node-ice.rs
new file mode 100644 (file)
index 0000000..aab4db6
--- /dev/null
@@ -0,0 +1,15 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Related issues: #20401, #20506, #20614, #20752, #20829, #20846, #20885, #20886
+
+fn main() {
+    "".homura[""]; //~ ERROR no field with that name was found
+}
index 8fa4e81c88955ae3e6ce4756eec74e0aae95e9dc..85a47492306aff40e3a725833613e9e7e62c60cc 100644 (file)
@@ -18,5 +18,9 @@ fn main() {
     // because the def_id associated with the type was
     // not convertible to a path.
   let x: isize = noexporttypelib::foo();
-    //~^ ERROR expected `isize`, found `core::option::Option<isize>`
+    //~^ ERROR mismatched types
+    //~| expected `isize`
+    //~| found `core::option::Option<isize>`
+    //~| expected isize
+    //~| found enum `core::option::Option`
 }
index bfabcff511686cebca49b56f1081a9520c614f05..fd2903a85ddb0b43cc71ced72bb20c320d8a3a5e 100644 (file)
@@ -14,5 +14,9 @@ fn main() {
     let f;
     let g;
     g = f;
-    f = box g; //~ ERROR cyclic type of infinite size
+    f = box g;
+    //~^  ERROR mismatched types
+    //~| expected `_`
+    //~| found `Box<_>`
+    //~| cyclic type of infinite size
 }
index 417bd9b57ee0a65d331bc6fc1520f14861f1abe9..036fcc1b9d77930f93f4388161b9659c6ecaf615 100644 (file)
@@ -12,5 +12,9 @@
 
 fn main() {
     let f;
-    f = box f; //~ ERROR cyclic type of infinite size
+    f = box f;
+    //~^ ERROR mismatched types
+    //~| expected `_`
+    //~| found `Box<_>`
+    //~| cyclic type of infinite size
 }
diff --git a/src/test/compile-fail/on-unimplemented-bad-anno.rs b/src/test/compile-fail/on-unimplemented-bad-anno.rs
new file mode 100644 (file)
index 0000000..dda534c
--- /dev/null
@@ -0,0 +1,37 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+// ignore-tidy-linelength
+
+#![feature(on_unimplemented)]
+
+#![allow(unused)]
+
+#[rustc_on_unimplemented = "test error `{Self}` with `{Bar}` `{Baz}` `{Quux}`"]
+trait Foo<Bar, Baz, Quux>{}
+
+#[rustc_on_unimplemented="a collection of type `{Self}` cannot be built from an iterator over elements of type `{A}`"]
+trait MyFromIterator<A> {
+    /// Build a container with elements from an external iterator.
+    fn my_from_iter<T: Iterator<Item=A>>(iterator: T) -> Self;
+}
+
+#[rustc_on_unimplemented] //~ ERROR this attribute must have a value
+trait BadAnnotation1 {}
+
+#[rustc_on_unimplemented = "Unimplemented trait error on `{Self}` with params `<{A},{B},{C}>`"]
+//~^ ERROR there is no type parameter C on trait BadAnnotation2
+trait BadAnnotation2<A,B> {}
+
+#[rustc_on_unimplemented = "Unimplemented trait error on `{Self}` with params `<{A},{B},{}>`"]
+//~^ only named substitution parameters are allowed
+trait BadAnnotation3<A,B> {}
+
+pub fn main() {
+}
diff --git a/src/test/compile-fail/on-unimplemented.rs b/src/test/compile-fail/on-unimplemented.rs
new file mode 100644 (file)
index 0000000..7b406af
--- /dev/null
@@ -0,0 +1,38 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+// ignore-tidy-linelength
+
+#![feature(on_unimplemented)]
+
+#[rustc_on_unimplemented = "test error `{Self}` with `{Bar}` `{Baz}` `{Quux}`"]
+trait Foo<Bar, Baz, Quux>{}
+
+fn foobar<U: Clone, T: Foo<u8, U, u32>>() -> T {
+
+}
+
+#[rustc_on_unimplemented="a collection of type `{Self}` cannot be built from an iterator over elements of type `{A}`"]
+trait MyFromIterator<A> {
+    /// Build a container with elements from an external iterator.
+    fn my_from_iter<T: Iterator<Item=A>>(iterator: T) -> Self;
+}
+
+fn collect<A, I: Iterator<Item=A>, B: MyFromIterator<A>>(it: I) -> B {
+    MyFromIterator::my_from_iter(it)
+}
+
+pub fn main() {
+    let x = vec!(1u8, 2, 3, 4);
+    let y: Option<Vec<u8>> = collect(x.iter()); // this should give approximately the same error for x.iter().collect()
+    //~^ ERROR
+    //~^^ NOTE a collection of type `core::option::Option<collections::vec::Vec<u8>>` cannot be built from an iterator over elements of type `&u8`
+    let x: String = foobar(); //~ ERROR
+    //~^ NOTE test error `collections::string::String` with `u8` `_` `u32`
+}
index c288429dcda0cae59d298bb1fef8758b6002ea81..aa7202574abfc3d15c0230790723e81f0d97b56c 100644 (file)
@@ -30,9 +30,18 @@ fn main() {
     }
     match 'c' {
         S { .. } => (),
-        //~^ ERROR mismatched types: expected `char`, found `S` (expected char, found struct S)
+        //~^ ERROR mismatched types
+        //~| expected `char`
+        //~| found `S`
+        //~| expected char
+        //~| found struct `S`
 
         _ => ()
     }
-    f(true);            //~ ERROR mismatched types: expected `char`, found `bool`
+    f(true);
+    //~^ ERROR mismatched types
+    //~| expected `char`
+    //~| found `bool`
+    //~| expected char
+    //~| found bool
 }
index e3c440d61cec32eab152ecb6fe7642b80afff99c..9e5081ed550281350fcad77c8cd8a73753170e20 100644 (file)
@@ -12,8 +12,16 @@ fn let_in<T, F>(x: T, f: F) where F: FnOnce(T) {}
 
 fn main() {
     let_in(3us, |i| { assert!(i == 3is); });
-    //~^ ERROR expected `usize`, found `isize`
+    //~^ ERROR mismatched types
+    //~| expected `usize`
+    //~| found `isize`
+    //~| expected usize
+    //~| found isize
 
     let_in(3is, |i| { assert!(i == 3us); });
-    //~^ ERROR expected `isize`, found `usize`
+    //~^ ERROR mismatched types
+    //~| expected `isize`
+    //~| found `usize`
+    //~| expected isize
+    //~| found usize
 }
index 392a803b0dd9f0f18a3a6144d4004c82e38837c3..463754b29c7b4eaadd65f9f30a1af1b13291c44e 100644 (file)
 pub fn main() {
     // *const -> *mut
     let x: *const isize = &42is;
-    let x: *mut isize = x; //~ERROR values differ in mutability
+    let x: *mut isize = x; //~  ERROR mismatched types
+                           //~| expected `*mut isize`
+                           //~| found `*const isize`
+                           //~| values differ in mutability
 
     // & -> *mut
-    let x: *mut isize = &42; //~ERROR values differ in mutability
+    let x: *mut isize = &42; //~  ERROR mismatched types
+                             //~| expected `*mut isize`
+                             //~| found `&isize`
+                             //~| values differ in mutability
 
     let x: *const isize = &42;
-    let x: *mut isize = x; //~ERROR values differ in mutability
+    let x: *mut isize = x; //~  ERROR mismatched types
+                           //~| expected `*mut isize`
+                           //~| found `*const isize`
+                           //~| values differ in mutability
 }
index 5028ec8997261c6c2de76cc36ff87e33df9053ab..a3c38dff6b0f62f73275240d21286e2a1fdcc758 100644 (file)
@@ -16,15 +16,16 @@ struct Inv<'a> { // invariant w/r/t 'a
     x: &'a mut &'a isize
 }
 
-pub trait Foo<'a> {
+pub trait Foo<'a, 't> {
     fn no_bound<'b>(self, b: Inv<'b>);
     fn has_bound<'b:'a>(self, b: Inv<'b>);
     fn wrong_bound1<'b,'c,'d:'a+'b>(self, b: Inv<'b>, c: Inv<'c>, d: Inv<'d>);
-    fn wrong_bound2<'b,'c,'d:'a+'b+'c>(self, b: Inv<'b>, c: Inv<'c>, d: Inv<'d>);
+    fn okay_bound<'b,'c,'d:'a+'b+'c>(self, b: Inv<'b>, c: Inv<'c>, d: Inv<'d>);
+    fn another_bound<'x: 'a>(self, x: Inv<'x>);
 }
 
 
-impl<'a> Foo<'a> for &'a isize {
+impl<'a, 't> Foo<'a, 't> for &'a isize {
     fn no_bound<'b:'a>(self, b: Inv<'b>) {
         //~^ ERROR lifetime parameters or bounds on method `no_bound` do not match
     }
@@ -47,9 +48,10 @@ fn wrong_bound1<'b,'c,'d:'a+'c>(self, b: Inv<'b>, c: Inv<'c>, d: Inv<'d>) {
         // cases.
     }
 
-    fn wrong_bound2<'b,'c,'e:'b+'c>(self, b: Inv<'b>, c: Inv<'c>, e: Inv<'e>) {
-        //~^ ERROR distinct set of bounds from its counterpart
+    fn okay_bound<'b,'c,'e:'b+'c>(self, b: Inv<'b>, c: Inv<'c>, e: Inv<'e>) {
     }
+
+    fn another_bound<'x: 't>(self, x: Inv<'x>) {}
 }
 
 fn main() { }
index c26740c9598d61022ee6879e9bca1ceedc84a4e2..7f2889a327be0f7b4e966c132fc689980d093528 100644 (file)
 struct a_class<'a> { x:&'a isize }
 
 fn a_fn1<'a,'b>(e: an_enum<'a>) -> an_enum<'b> {
-    return e; //~ ERROR mismatched types: expected `an_enum<'b>`, found `an_enum<'a>`
+    return e; //~  ERROR mismatched types
+              //~| expected `an_enum<'b>`
+              //~| found `an_enum<'a>`
+              //~| lifetime mismatch
 }
 
 fn a_fn3<'a,'b>(e: a_class<'a>) -> a_class<'b> {
-    return e; //~ ERROR mismatched types: expected `a_class<'b>`, found `a_class<'a>`
+    return e; //~  ERROR mismatched types
+              //~| expected `a_class<'b>`
+              //~| found `a_class<'a>`
+              //~| lifetime mismatch
 }
 
 fn main() { }
index 9de0ed070c7ca6c6598aa092f570a6041ecf752a..4a3ca01c8496dce20b17961504d0bc90b251f767 100644 (file)
@@ -27,7 +27,13 @@ fn get(&self) -> &'a isize {
 
 impl<'a> Box<'a> {
     fn or<'b,G:GetRef<'b>>(&self, g2: G) -> &'a isize {
-        g2.get() //~ ERROR cannot infer an appropriate lifetime for automatic coercion due to
+        g2.get()
+        //~^ ERROR cannot infer an appropriate lifetime for automatic coercion due to
+        //~| ERROR mismatched types
+        //~| expected `&'a isize`
+        //~| found `&'b isize`
+        //~| lifetime mismatch
+
     }
 }
 
index 37b74aea5391343258029d8fafb24625954c2d51..57c8e3f1170aa74d5268761fdeb600db0764501e 100644 (file)
@@ -26,7 +26,12 @@ fn get(&self) -> &'a T {
 }
 
 fn get<'a,'b,G:GetRef<'a, isize>>(g1: G, b: &'b isize) -> &'b isize {
-    g1.get() //~ ERROR cannot infer an appropriate lifetime for automatic coercion due to
+    g1.get()
+    //~^ ERROR cannot infer an appropriate lifetime for automatic coercion due to
+    //~| ERROR mismatched types
+    //~| expected `&'b isize`
+    //~| found `&'a isize`
+    //~| lifetime mismatch
 }
 
 fn main() {
index ac56e8ce14df6ad99820434ef6d7de7af9862d90..ebf7ca289f88969af34ea46342c3358dbf32b959 100644 (file)
@@ -53,7 +53,12 @@ fn supply_F() {
 fn supply_G() {
     want_G(foo);
     want_G(bar);
-    want_G(baz); //~ ERROR expected concrete lifetime
+    want_G(baz);
+    //~^ ERROR mismatched types
+    //~| expected `fn(&'cx S) -> &'static S`
+    //~| found `fn(&S) -> &S {baz}`
+    //~| expected concrete lifetime
+    //~| found bound lifetime parameter 'cx
 }
 
 pub fn main() {
index 0d441380e81447676d44db87a11fc4fb6a471f6b..1d32e8fe7b250c595d2f508e55bfaeb4ff79caa4 100644 (file)
@@ -31,7 +31,10 @@ fn set_f_ok(&mut self, b: Box<b<'a>>) {
 
     fn set_f_bad(&mut self, b: Box<b>) {
         self.f = b;
-        //~^ ERROR mismatched types: expected `Box<Box<&'a isize>>`, found `Box<Box<&isize>>`
+        //~^ ERROR mismatched types
+        //~| expected `Box<Box<&'a isize>>`
+        //~| found `Box<Box<&isize>>`
+        //~| lifetime mismatch
     }
 }
 
index e94bf19955bdc5d6993a4015f5ea07c6f7606d8b..df69e13bf1e65063f3ce019d0b7a36a9b12e3228 100644 (file)
@@ -14,14 +14,33 @@ fn main() {
     let n = 1;
     let a = [0; n]; //~ ERROR expected constant integer for repeat count, found variable
     let b = [0; ()];
-//~^ ERROR expected constant integer for repeat count, found non-constant expression
-//~^^ ERROR: expected `usize`, found `()`
-    let c = [0; true]; //~ ERROR expected positive integer for repeat count, found boolean
-    //~^ ERROR: expected `usize`, found `bool`
-    let d = [0; 0.5]; //~ ERROR expected positive integer for repeat count, found float
-    //~^ ERROR: expected `usize`, found `_`
-    let e = [0; "foo"]; //~ ERROR expected positive integer for repeat count, found string
-    //~^ ERROR: expected `usize`, found `&'static str`
+//~^ ERROR mismatched types
+//~| expected `usize`
+//~| found `()`
+//~| expected usize
+//~| found ()
+//~| ERROR expected constant integer for repeat count, found non-constant expression
+    let c = [0; true];
+    //~^ ERROR mismatched types
+    //~| expected `usize`
+    //~| found `bool`
+    //~| expected usize
+    //~| found bool
+    //~| ERROR expected positive integer for repeat count, found boolean
+    let d = [0; 0.5];
+    //~^ ERROR mismatched types
+    //~| expected `usize`
+    //~| found `_`
+    //~| expected usize
+    //~| found floating-point variable
+    //~| ERROR expected positive integer for repeat count, found float
+    let e = [0; "foo"];
+    //~^ ERROR mismatched types
+    //~| expected `usize`
+    //~| found `&'static str`
+    //~| expected usize
+    //~| found &-ptr
+    //~| ERROR expected positive integer for repeat count, found string
     let f = [0; -4];
     //~^ ERROR expected positive integer for repeat count, found negative integer
     let f = [0us; -1];
index 417885840490513687d282a0f9d0e6cbbc0b071f..66aef0ec3a1b1869f9ae45991dfb43dfc88ce9b0 100644 (file)
@@ -36,7 +36,11 @@ fn foo(p: &Panolpy) {
 
     // Type of the result follows the LHS, not the RHS:
     let _: i32 = 22_i64 >> 1_i32;
-    //~^ ERROR mismatched types: expected `i32`, found `i64`
+    //~^ ERROR mismatched types
+    //~| expected `i32`
+    //~| found `i64`
+    //~| expected i32
+    //~| found i64)
 }
 
 fn main() {
index a655a17c037d249473f7dcbc419957422c5bcd93..1203d622348998d7044f724511726ec6d1456ed2 100644 (file)
 fn main() {
     match Foo(1.1) {
         1 => {}
-    //~^ ERROR expected `Foo<_, _>`, found `_`
+    //~^ ERROR mismatched types
+    //~| expected `Foo<_, _>`
+    //~| found `_`
+    //~| expected struct `Foo`
+    //~| found integral variable
     }
 
 }
index f27fa6470a64c01e81f1ca92fd6cd8d1d6d422d1..9807fc43140d9a8426256f5e315116de7a8d855b 100644 (file)
@@ -17,9 +17,9 @@
 fn main() {
     let x = ATOMIC_BOOL_INIT;
     let x = *&x; //~ ERROR: cannot move out of borrowed content
-    let x = ATOMIC_INT_INIT;
+    let x = ATOMIC_ISIZE_INIT;
     let x = *&x; //~ ERROR: cannot move out of borrowed content
-    let x = ATOMIC_UINT_INIT;
+    let x = ATOMIC_USIZE_INIT;
     let x = *&x; //~ ERROR: cannot move out of borrowed content
     let x: AtomicPtr<usize> = AtomicPtr::new(ptr::null_mut());
     let x = *&x; //~ ERROR: cannot move out of borrowed content
index 2bb8d32a7e3e2930f77656a7c97dcdbd7a17ea8e..71a2b50b612d9d0bf835da50f10faca5b106fe4d 100644 (file)
@@ -12,11 +12,27 @@ struct Foo { a: isize, b: isize }
 struct Bar { x: isize }
 
 static bar: Bar = Bar { x: 5 };
-static foo: Foo = Foo { a: 2, ..bar }; //~ ERROR mismatched types: expected `Foo`, found `Bar`
-static foo_i: Foo = Foo { a: 2, ..4 }; //~ ERROR mismatched types: expected `Foo`
+static foo: Foo = Foo { a: 2, ..bar }; //~  ERROR mismatched types
+                                       //~| expected `Foo`
+                                       //~| found `Bar`
+                                       //~| expected struct `Foo`
+                                       //~| found struct `Bar`
+static foo_i: Foo = Foo { a: 2, ..4 }; //~  ERROR mismatched types
+                                       //~| expected `Foo`
+                                       //~| found `_`
+                                       //~| expected struct `Foo`
+                                       //~| found integral variable
 
 fn main() {
     let b = Bar { x: 5 };
-    let f = Foo { a: 2, ..b }; //~ ERROR mismatched types: expected `Foo`, found `Bar`
-    let f_i = Foo { a: 2, ..4 }; //~ ERROR mismatched types: expected `Foo`
+    let f = Foo { a: 2, ..b }; //~  ERROR mismatched types
+                               //~| expected `Foo`
+                               //~| found `Bar`
+                               //~| expected struct `Foo`
+                               //~| found struct `Bar`
+    let f_i = Foo { a: 2, ..4 }; //~  ERROR mismatched types
+                                 //~| expected `Foo`
+                                 //~| found `_`
+                                 //~| expected struct `Foo`
+                                 //~| found integral variable
 }
index fb84c1e2ebe9a265ab362887edddc617a2af4890..a22f390499f279c4298fbb26fb535c492643c39e 100644 (file)
@@ -24,25 +24,33 @@ struct Pair<T,U> {
 
 fn main() {
     let pt = PointF {
-        //~^ ERROR expected f32, found isize
+        //~^ ERROR structure constructor specifies a structure of type
+        //~| expected f32
+        //~| found isize
         x: 1is,
         y: 2is,
     };
 
     let pt2 = Point::<f32> {
-        //~^ ERROR expected f32, found isize
+        //~^ ERROR structure constructor specifies a structure of type
+        //~| expected f32
+        //~| found isize
         x: 3is,
         y: 4is,
     };
 
     let pair = PairF {
-        //~^ ERROR expected f32, found isize
+        //~^ ERROR structure constructor specifies a structure of type
+        //~| expected f32
+        //~| found isize
         x: 5is,
         y: 6is,
     };
 
     let pair2 = PairF::<isize> {
-        //~^ ERROR expected f32, found isize
+        //~^ ERROR structure constructor specifies a structure of type
+        //~| expected f32
+        //~| found isize
         x: 7is,
         y: 8is,
     };
index 27f50be528c56fa56e855e296cef52e9448d6c48..44de5d8cfe353b083a083534a1185a493540fef0 100644 (file)
 
 fn main() {
     let (x, y) = ();
-//~^ ERROR expected `()`, found `(_, _)` (expected (), found tuple)
+//~^ ERROR mismatched types
+//~| expected `()`
+//~| found `(_, _)`
+//~| expected ()
+//~| found tuple
     return x;
 }
index a9df449032e6fef4d9a22e03b57131458ed0ee03..660c1fa9a88d89c00ab98b4326991e164cce4b7a 100644 (file)
@@ -8,7 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// error-pattern:mismatched types: expected `char`, found
 // Issue #876
 
 #![no_implicit_prelude]
@@ -21,4 +20,9 @@ fn last<T>(v: Vec<&T> ) -> std::option::Option<T> {
 fn main() {
     let y;
     let x : char = last(y);
+    //~^ ERROR mismatched types
+    //~| expected `char`
+    //~| found `core::option::Option<_>`
+    //~| expected char
+    //~| found enum `core::option::Option`
 }
index 1e5422a798e33fedb1d199765c5f4699fc2e31e8..60db35b879f570c03f9dfd1bc2ba5362fef82a26 100644 (file)
@@ -20,7 +20,11 @@ struct bar {
 
 fn want_foo(f: foo) {}
 fn have_bar(b: bar) {
-    want_foo(b); //~ ERROR (expected struct foo, found struct bar)
+    want_foo(b); //~  ERROR mismatched types
+                 //~| expected `foo`
+                 //~| found `bar`
+                 //~| expected struct `foo`
+                 //~| found struct `bar`
 }
 
 fn main() {}
index d1a37c99c47b26fa6ff80ed8f7ed552cbe526995..231d2366b48a85ceb045ccaaf187ed78112ac241 100644 (file)
@@ -18,7 +18,11 @@ struct foo {
 
 fn want_foo(f: foo) {}
 fn have_bar(b: bar) {
-    want_foo(b); //~ ERROR (expected struct foo, found box)
+    want_foo(b); //~  ERROR mismatched types
+                 //~| expected `foo`
+                 //~| found `Box<foo>`
+                 //~| expected struct `foo`
+                 //~| found box
 }
 
 fn main() {}
index 4f405e2558d2399c95512c227d2195c698649acb..79174552ae09c36f5ba136754f7a95cd7d6b6bc0 100644 (file)
@@ -20,7 +20,11 @@ fn c(x: Box<Foo+Sync+Send>) {
 }
 
 fn d(x: Box<Foo>) {
-    a(x); //~ ERROR found no bounds
+    a(x); //~  ERROR mismatched types
+          //~| expected `Box<Foo + Send>`
+          //~| found `Box<Foo>`
+          //~| expected bounds `Send`
+          //~| found no bounds
 }
 
 fn main() { }
index 5fc80d5660d04cd1c722b30eb20f667fc0061d7b..477bd4f5be9a1a8a942acc1fd2b625b82c1fb5c6 100644 (file)
@@ -32,15 +32,15 @@ trait Foo {
 impl Foo for isize {
     // invalid bound for T, was defined as Eq in trait
     fn test_error1_fn<T: Ord>(&self) {}
-    //~^ ERROR in method `test_error1_fn`, type parameter 0 requires bound `core::cmp::Ord`
+    //~^ ERROR the requirement `T : core::cmp::Ord` appears on the impl
 
     // invalid bound for T, was defined as Eq + Ord in trait
     fn test_error2_fn<T: Eq + B>(&self) {}
-    //~^ ERROR in method `test_error2_fn`, type parameter 0 requires bound `B`
+    //~^ ERROR the requirement `T : B` appears on the impl
 
     // invalid bound for T, was defined as Eq + Ord in trait
     fn test_error3_fn<T: B + Eq>(&self) {}
-    //~^ ERROR in method `test_error3_fn`, type parameter 0 requires bound `B`
+    //~^ ERROR the requirement `T : B` appears on the impl
 
     // multiple bounds, same order as in trait
     fn test3_fn<T: Ord + Eq>(&self) {}
@@ -50,16 +50,16 @@ fn test4_fn<T: Eq + Ord>(&self) {}
 
     // parameters in impls must be equal or more general than in the defining trait
     fn test_error5_fn<T: B>(&self) {}
-    //~^ ERROR in method `test_error5_fn`, type parameter 0 requires bound `B`
+    //~^ ERROR the requirement `T : B` appears on the impl
 
     // bound `std::cmp::Eq` not enforced by this implementation, but this is OK
     fn test6_fn<T: A>(&self) {}
 
     fn test_error7_fn<T: A + Eq>(&self) {}
-    //~^ ERROR in method `test_error7_fn`, type parameter 0 requires bound `core::cmp::Eq`
+    //~^ ERROR the requirement `T : core::cmp::Eq` appears on the impl
 
     fn test_error8_fn<T: C>(&self) {}
-    //~^ ERROR in method `test_error8_fn`, type parameter 0 requires bound `C`
+    //~^ ERROR the requirement `T : C` appears on the impl
 }
 
 
@@ -71,8 +71,7 @@ trait Trait {
 
 impl Trait for usize {
     fn method<G: Getter<usize>>() {}
-    //~^ ERROR in method `method`, type parameter 0 requires bound `Getter<usize>`
+    //~^ G : Getter<usize>` appears on the impl method but not on the corresponding trait method
 }
 
 fn main() {}
-
index a970a86408e90ad379aaeb31d8505037dc87691d..8ad19116e7bb13ba2b11af89f5121e45441c9949 100644 (file)
@@ -20,7 +20,7 @@ trait IteratorUtil<A> {
 
 impl<A, T: Iterator<A>> IteratorUtil<A> for T {
     fn zip<B, U: Iterator<B>>(self, other: U) -> ZipIterator<T, U> {
-    //~^ ERROR in method `zip`, type parameter 1 requires bound `Iterator<B>`
+    //~^ ERROR the requirement `U : Iterator<B>` appears on the impl method
         ZipIterator{a: self, b: other}
     }
 }
index 7f073a7bfdbbaa2675070c7a39e50f88bf2f3789..8ad9ca50e30426d694e1adc1a3e6f9568f62bed6 100644 (file)
@@ -14,8 +14,16 @@ fn first((value, _): (isize, f64)) -> isize { value }
 
 fn main() {
     let y = first ((1,2.0,3));
-    //~^ ERROR expected a tuple with 2 elements, found one with 3 elements
+    //~^ ERROR mismatched types
+    //~| expected `(isize, f64)`
+    //~| found `(isize, f64, _)`
+    //~| expected a tuple with 2 elements
+    //~| found one with 3 elements
 
     let y = first ((1,));
-    //~^ ERROR expected `(isize, f64)`, found `(isize,)`
+    //~^ ERROR mismatched types
+    //~| expected `(isize, f64)`
+    //~| found `(isize,)`
+    //~| expected a tuple with 2 elements
+    //~| found one with 1 elements
 }
index 1b44c7e8128a2a229f89333cf5f59346a75b1ac2..c8c596fdb4fcc24b9b0bccf3205dd8b364b9b191 100644 (file)
@@ -17,9 +17,17 @@ fn identity_u16(n: u16) -> u16 { n }
 
     identity_u8(x);  // after this, `x` is assumed to have type `u8`
     identity_u16(x);
-    //~^ ERROR mismatched types: expected `u16`, found `u8`
+    //~^ ERROR mismatched types
+    //~| expected `u16`
+    //~| found `u8`
+    //~| expected u16
+    //~| found u8
     identity_u16(y);
-    //~^ ERROR mismatched types: expected `u16`, found `i32`
+    //~^ ERROR mismatched types
+    //~| expected `u16`
+    //~| found `i32`
+    //~| expected u16
+    //~| found i32
 
     let a = 3is;
 
@@ -27,6 +35,10 @@ fn identity_i(n: isize) -> isize { n }
 
     identity_i(a); // ok
     identity_u16(a);
-    //~^ ERROR mismatched types: expected `u16`, found `isize`
+    //~^ ERROR mismatched types
+    //~| expected `u16`
+    //~| found `isize`
+    //~| expected u16
+    //~| found isize
 
 }
index 8b0897565fb918f6767e94ab3610b6a23b7358c7..4ab6bd531913a5cbcf4ef1ca6ffd7990eadfb790 100644 (file)
@@ -9,7 +9,15 @@
 // except according to those terms.
 
 // Checking that the compiler reports multiple type errors at once
-// error-pattern:mismatched types: expected `bool`
-// error-pattern:mismatched types: expected `isize`
 
 fn main() { let a: bool = 1is; let b: isize = true; }
+//~^ ERROR mismatched types
+//~| expected `bool`
+//~| found `isize`
+//~| expected bool
+//~| found isize
+//~| ERROR mismatched types
+//~| expected `isize`
+//~| found `bool`
+//~| expected isize
+//~| found bool
index 42691fa5229035a282727808ca7e5b4c51c0bdef..408bf72e97c87cd1f09a1c2a569aea348e9ba6d5 100644 (file)
 
 fn foo<Foo, Bar>(x: Foo) -> Bar {
     x
-//~^ ERROR expected `Bar`, found `Foo` (expected type parameter, found a different type parameter)
+//~^ ERROR mismatched types
+//~| expected `Bar`
+//~| found `Foo`
+//~| expected type parameter
+//~| found a different type parameter
 }
 
 fn main() {}
index 66479202e1253e6172fdbcd814b2727d966a7098..de9623de7cd3a551c56e74a21d878e6a4baa8c55 100644 (file)
 
 trait BrokenAdd: Int {
     fn broken_add<T>(&self, rhs: T) -> Self {
-        *self + rhs //~ ERROR expected `Self`, found `T`
+        *self + rhs //~  ERROR mismatched types
+                    //~| expected `Self`
+                    //~| found `T`
+                    //~| expected Self
+                    //~| found type parameter
     }
 }
 
index 92740cf5082a65ef11a45c37b2672f8f98754dd6..a34be63ba6b3c906d5c54063b845999a78bee622 100644 (file)
@@ -19,11 +19,19 @@ pub fn main() {
 
 fn test1() {
     let x: Foo<_> = Bar::<usize>;
-    //~^ ERROR mismatched types: expected `Foo<_>`, found `Bar<usize>`
+    //~^ ERROR mismatched types
+    //~| expected `Foo<_>`
+    //~| found `Bar<usize>`
+    //~| expected struct `Foo`
+    //~| found struct `Bar`
     let y: Foo<usize> = x;
 }
 
 fn test2() {
     let x: Foo<_> = Bar::<usize>;
-    //~^ ERROR mismatched types: expected `Foo<_>`, found `Bar<usize>`
+    //~^ ERROR mismatched types
+    //~| expected `Foo<_>`
+    //~| found `Bar<usize>`
+    //~| expected struct `Foo`
+    //~| found struct `Bar`
 }
index 6c323e8c1ae506ad1485bce8197add550336ea15..cbcf31b5b7edbc46355ea238d31cfad03671517b 100644 (file)
@@ -42,8 +42,15 @@ trait SomeTrait {
 impl<'a, T> SomeTrait for &'a Bar<T> {
     fn dummy1(self: &&'a Bar<T>) { }
     fn dummy2(self: &Bar<T>) {} //~ ERROR mismatched self type
-    fn dummy3(self: &&Bar<T>) {} //~ ERROR lifetime mismatch
-    //~^ ERROR lifetime mismatch
+    fn dummy3(self: &&Bar<T>) {}
+    //~^ ERROR mismatched types
+    //~| expected `&'a Bar<T>`
+    //~| found `&Bar<T>`
+    //~| lifetime mismatch
+    //~| ERROR mismatched types
+    //~| expected `&'a Bar<T>`
+    //~| found `&Bar<T>`
+    //~| lifetime mismatch
 }
 
 fn main() {
diff --git a/src/test/compile-fail/ufcs-qpath-missing-params.rs b/src/test/compile-fail/ufcs-qpath-missing-params.rs
new file mode 100644 (file)
index 0000000..5fa66eb
--- /dev/null
@@ -0,0 +1,17 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use std::borrow::IntoCow;
+
+fn main() {
+    <String as IntoCow>::into_cow("foo".to_string());
+    //~^ ERROR wrong number of type arguments: expected 2, found 0
+}
+
diff --git a/src/test/compile-fail/ufcs-qpath-self-mismatch.rs b/src/test/compile-fail/ufcs-qpath-self-mismatch.rs
new file mode 100644 (file)
index 0000000..868c1ea
--- /dev/null
@@ -0,0 +1,21 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use std::ops::Add;
+
+fn main() {
+    <i32 as Add<u32>>::add(1, 2);
+    //~^ ERROR the trait `core::ops::Add<u32>` is not implemented for the type `i32`
+    <i32 as Add<i32>>::add(1u32, 2);
+    //~^ ERROR mismatched types
+    <i32 as Add<i32>>::add(1, 2u32);
+    //~^ ERROR mismatched types
+}
+
index 702702990c244fc720697bf8a5693945fd3b74d3..86271f670ce6f7d2078c912ae2fa62e81ca05b56 100644 (file)
@@ -24,14 +24,18 @@ fn main() {
         foo(1); //~ ERROR: this function takes at least 2 parameters but 1 parameter was supplied
 
         let x: unsafe extern "C" fn(f: isize, x: u8) = foo;
-        //~^ ERROR: mismatched types: expected `unsafe extern "C" fn(isize, u8)`
-        //         , found `unsafe extern "C" fn(isize, u8, ...)`
-        //          (expected non-variadic fn, found variadic function)
+        //~^ ERROR: mismatched types
+        //~| expected `unsafe extern "C" fn(isize, u8)`
+        //~| found `unsafe extern "C" fn(isize, u8, ...)`
+        //~| expected non-variadic fn
+        //~| found variadic function
 
         let y: unsafe extern "C" fn(f: isize, x: u8, ...) = bar;
-        //~^ ERROR: mismatched types: expected `unsafe extern "C" fn(isize, u8, ...)`
-        //         , found `extern "C" extern fn(isize, u8)`
-        //          (expected variadic fn, found non-variadic function)
+        //~^ ERROR: mismatched types
+        //~| expected `unsafe extern "C" fn(isize, u8, ...)`
+        //~| found `extern "C" fn(isize, u8) {bar}`
+        //~| expected variadic fn
+        //~| found non-variadic function
 
         foo(1, 2, 3f32); //~ ERROR: can't pass an f32 to variadic function, cast to c_double
         foo(1, 2, true); //~ ERROR: can't pass bool to variadic function, cast to c_int
index e6fbcf2d38f2b2b317d5e6ce35e860a124c02984..21c249c0e1fb00cb1d241db40f0381a2c8359d72 100644 (file)
@@ -24,7 +24,7 @@ impl Mul<f64> for Vec1 {
     type Output = Vec1;
 
     fn mul(self, s: &f64) -> Vec1 {
-    //~^ ERROR: method `mul` has an incompatible type for trait: expected f64, found &-ptr
+    //~^ ERROR method `mul` has an incompatible type for trait
         Vec1 {
             x: self.x * *s
         }
@@ -41,7 +41,7 @@ impl Mul<Vec2> for Vec2 {
     type Output = f64;
 
     fn mul(self, s: f64) -> Vec2 {
-    //~^ ERROR: method `mul` has an incompatible type for trait: expected struct Vec2, found f64
+    //~^ ERROR method `mul` has an incompatible type for trait
         Vec2 {
             x: self.x * s,
             y: self.y * s
@@ -60,7 +60,7 @@ impl Mul<f64> for Vec3 {
     type Output = i32;
 
     fn mul(self, s: f64) -> f64 {
-    //~^ ERROR: method `mul` has an incompatible type for trait: expected i32, found f64
+    //~^ ERROR method `mul` has an incompatible type for trait
         s
     }
 }
@@ -72,7 +72,15 @@ pub fn main() {
 
     let x: Vec2 = Vec2 { x: 1.0, y: 2.0 } * 2.0; // trait had reversed order
     //~^ ERROR mismatched types
-    //~^^ ERROR mismatched types
+    //~| expected `Vec2`
+    //~| found `_`
+    //~| expected struct `Vec2`
+    //~| found floating-point variable
+    //~| ERROR mismatched types
+    //~| expected `Vec2`
+    //~| found `f64`
+    //~| expected struct `Vec2`
+    //~| found f64
 
     let x: i32 = Vec3 { x: 1.0, y: 2.0, z: 3.0 } * 2.0;
 }
diff --git a/src/test/debuginfo/associated_types.rs b/src/test/debuginfo/associated_types.rs
new file mode 100644 (file)
index 0000000..92336e9
--- /dev/null
@@ -0,0 +1,28 @@
+// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// ignore-android: FIXME(#10381)
+// min-lldb-version: 310
+
+// compile-flags:-g
+
+struct Peekable<I> where I: Iterator {
+    _iter: I,
+    _next: Option<<I as Iterator>::Item>,
+}
+
+fn main() {
+    let mut iter = Vec::<i32>::new().into_iter();
+    let next = iter.next();
+    let _v = Peekable {
+        _iter: iter,
+        _next : next,
+    };
+}
index 8a0c14d2d7e366ce41772bc7faf066e4790db19b..fe7df6411599c6a5c8882aaa5e59fb32987cf4a7 100644 (file)
@@ -14,7 +14,7 @@
 
 use rustc::session::{build_session, Session};
 use rustc::session::config::{basic_options, build_configuration, Input, OutputTypeExe};
-use rustc_driver::driver::{compile_input};
+use rustc_driver::driver::{compile_input, CompileController};
 use syntax::diagnostics::registry::Registry;
 
 fn main() {
@@ -52,11 +52,13 @@ fn basic_sess(sysroot: Path) -> Session {
 fn compile(code: String, output: Path, sysroot: Path) {
     let sess = basic_sess(sysroot);
     let cfg = build_configuration(&sess);
+    let control = CompileController::basic();
 
     compile_input(sess,
             cfg,
             &Input::Str(code),
             &None,
             &Some(output),
-            None);
+            None,
+            control);
 }
index 4ffb8a3f74d4f0769bd368dc443ab267d595fd9b..5236b35d4d2b9019254dec0dd8d2480a2d7961af 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2013-2015 The Rust Project Developers. See the COPYRIGHT
 // file at the top-level directory of this distribution and at
 // http://rust-lang.org/COPYRIGHT.
 //
 #[derive(PartialEq, Clone, Show)]
 fn foo() -> AFakeTypeThatHadBetterGoAway {}
 
+#[into_multi_foo]
+#[derive(PartialEq, Clone, Show)]
+fn foo() -> AnotherFakeTypeThatHadBetterGoAway {}
+
+trait Qux {
+    #[into_multi_foo]
+    fn bar();
+}
+
+impl Qux for i32 {
+    #[into_multi_foo]
+    fn bar() {}
+}
+
+impl Qux for u8 {}
+
 pub fn main() {
     assert_eq!(1, make_a_1!());
     assert_eq!(2, exported_macro!());
 
     assert_eq!(Foo::Bar, Foo::Bar);
     test(None::<Foo>);
+
+    assert_eq!(Foo2::Bar2, Foo2::Bar2);
+    test(None::<Foo2>);
+
+    let x = 10i32;
+    assert_eq!(x.foo(), 42);
+    let x = 10u8;
+    assert_eq!(x.foo(), 0);
 }
 
 fn test<T: PartialEq+Clone>(_: Option<T>) {}
diff --git a/src/test/run-pass/associated-types-enum-field-named.rs b/src/test/run-pass/associated-types-enum-field-named.rs
new file mode 100644 (file)
index 0000000..a499aa6
--- /dev/null
@@ -0,0 +1,43 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Test associated types appearing in struct-like enum variants.
+
+use self::VarValue::*;
+
+pub trait UnifyKey {
+    type Value;
+    fn to_index(&self) -> usize;
+}
+
+pub enum VarValue<K:UnifyKey> {
+    Redirect { to: K },
+    Root { value: K::Value, rank: usize },
+}
+
+fn get<'a,K:UnifyKey<Value=Option<V>>,V>(table: &'a Vec<VarValue<K>>, key: &K) -> &'a Option<V> {
+    match table[key.to_index()] {
+        VarValue::Redirect { to: ref k } => get(table, k),
+        VarValue::Root { value: ref v, rank: _ } => v,
+    }
+}
+
+impl UnifyKey for usize {
+    type Value = Option<char>;
+    fn to_index(&self) -> usize { *self }
+}
+
+fn main() {
+    let table = vec![/* 0 */ Redirect { to: 1 },
+                     /* 1 */ Redirect { to: 3 },
+                     /* 2 */ Root { value: Some('x'), rank: 0 },
+                     /* 3 */ Redirect { to: 2 }];
+    assert_eq!(get(&table, &0), &Some('x'));
+}
diff --git a/src/test/run-pass/associated-types-enum-field-numbered.rs b/src/test/run-pass/associated-types-enum-field-numbered.rs
new file mode 100644 (file)
index 0000000..e710c53
--- /dev/null
@@ -0,0 +1,43 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Test associated types appearing in tuple-like enum variants.
+
+use self::VarValue::*;
+
+pub trait UnifyKey {
+    type Value;
+    fn to_index(&self) -> usize;
+}
+
+pub enum VarValue<K:UnifyKey> {
+    Redirect(K),
+    Root(K::Value, usize),
+}
+
+fn get<'a,K:UnifyKey<Value=Option<V>>,V>(table: &'a Vec<VarValue<K>>, key: &K) -> &'a Option<V> {
+    match table[key.to_index()] {
+        VarValue::Redirect(ref k) => get(table, k),
+        VarValue::Root(ref v, _) => v,
+    }
+}
+
+impl UnifyKey for usize {
+    type Value = Option<char>;
+    fn to_index(&self) -> usize { *self }
+}
+
+fn main() {
+    let table = vec![/* 0 */ Redirect(1),
+                     /* 1 */ Redirect(3),
+                     /* 2 */ Root(Some('x'), 0),
+                     /* 3 */ Redirect(2)];
+    assert_eq!(get(&table, &0), &Some('x'));
+}
diff --git a/src/test/run-pass/associated-types-projection-in-where-clause.rs b/src/test/run-pass/associated-types-projection-in-where-clause.rs
new file mode 100644 (file)
index 0000000..10a459f
--- /dev/null
@@ -0,0 +1,34 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Test a where clause that uses a non-normalized projection type.
+
+trait Int
+{
+    type T;
+}
+
+trait NonZero
+{
+    fn non_zero(self) -> bool;
+}
+
+fn foo<I:Int<T=J>,J>(t: I) -> bool
+    where <I as Int>::T : NonZero
+    //    ^~~~~~~~~~~~~ canonical form is just J
+{
+    bar::<J>()
+}
+
+fn bar<NZ:NonZero>() -> bool { true }
+
+fn main ()
+{
+}
diff --git a/src/test/run-pass/associated-types-struct-field-named.rs b/src/test/run-pass/associated-types-struct-field-named.rs
new file mode 100644 (file)
index 0000000..1ded34f
--- /dev/null
@@ -0,0 +1,41 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Test that we correctly normalize the type of a struct field
+// which has an associated type.
+
+pub trait UnifyKey {
+    type Value;
+}
+
+pub struct Node<K:UnifyKey> {
+    pub key: K,
+    pub value: K::Value,
+}
+
+fn foo<K : UnifyKey<Value=Option<V>>,V : Clone>(node: &Node<K>) -> Option<V> {
+    node.value.clone()
+}
+
+impl UnifyKey for i32 {
+    type Value = Option<u32>;
+}
+
+impl UnifyKey for u32 {
+    type Value = Option<i32>;
+}
+
+pub fn main() {
+    let node: Node<i32> = Node { key: 1, value: Some(22) };
+    assert_eq!(foo(&node), Some(22_u32));
+
+    let node: Node<u32> = Node { key: 1, value: Some(22) };
+    assert_eq!(foo(&node), Some(22_i32));
+}
diff --git a/src/test/run-pass/associated-types-struct-field-numbered.rs b/src/test/run-pass/associated-types-struct-field-numbered.rs
new file mode 100644 (file)
index 0000000..3669dec
--- /dev/null
@@ -0,0 +1,38 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Test that we correctly normalize the type of a struct field
+// which has an associated type.
+
+pub trait UnifyKey {
+    type Value;
+}
+
+pub struct Node<K:UnifyKey>(K, K::Value);
+
+fn foo<K : UnifyKey<Value=Option<V>>,V : Clone>(node: &Node<K>) -> Option<V> {
+    node.1.clone()
+}
+
+impl UnifyKey for i32 {
+    type Value = Option<u32>;
+}
+
+impl UnifyKey for u32 {
+    type Value = Option<i32>;
+}
+
+pub fn main() {
+    let node: Node<i32> = Node(1, Some(22));
+    assert_eq!(foo(&node), Some(22_u32));
+
+    let node: Node<u32> = Node(1, Some(22));
+    assert_eq!(foo(&node), Some(22_i32));
+}
index da5fa19f816f753771008632a3794a3ae882bf6e..320ad0bf4d1da67238892518a7b8c75dc830542f 100644 (file)
 // ignore-windows FIXME #13259
 
 #![feature(unboxed_closures)]
+#![feature(unsafe_destructor)]
 
 use std::os;
 use std::io::process::Command;
-use std::finally::Finally;
 use std::str;
+use std::ops::{Drop, FnMut, FnOnce};
 
 #[inline(never)]
 fn foo() {
@@ -28,11 +29,15 @@ fn foo() {
 
 #[inline(never)]
 fn double() {
-    (|&mut:| {
-        panic!("once");
-    }).finally(|| {
-        panic!("twice");
-    })
+    struct Double;
+
+    impl Drop for Double {
+        fn drop(&mut self) { panic!("twice") }
+    }
+
+    let _d = Double;
+
+    panic!("once");
 }
 
 fn runtest(me: &str) {
index 3964d54f8609cc8ec03eb005e781ef42104df9f0..f590e6e07283cc208f26e2e63e8aacc22754104d 100644 (file)
@@ -30,4 +30,7 @@ pub fn main() {
     let _: &Fn(int) -> _ = &{ |x| (x as u8) };
     let _: &Show = &if true { false } else { true };
     let _: &Show = &match true { true => 'a', false => 'b' };
+
+    let _: Box<[int]> = Box::new([1, 2, 3]);
+    let _: Box<Fn(int) -> _> = Box::new(|x| (x as u8));
 }
diff --git a/src/test/run-pass/coerce-unify-return.rs b/src/test/run-pass/coerce-unify-return.rs
new file mode 100644 (file)
index 0000000..eeba904
--- /dev/null
@@ -0,0 +1,26 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Check that coercions unify the expected return type of a polymorphic
+// function call, instead of leaving the type variables as they were.
+
+struct Foo;
+impl Foo {
+    fn foo<T>(self, x: T) -> Option<T> { Some(x) }
+}
+
+pub fn main() {
+    let _: Option<fn()> = Some(main);
+    let _: Option<fn()> = Foo.foo(main);
+
+    // The same two cases, with implicit type variables made explicit.
+    let _: Option<fn()> = Some::<_>(main);
+    let _: Option<fn()> = Foo.foo::<_>(main);
+}
index 28b346c9ed4d0532e240902677419fa09dbd8375..f8f92a56adb1a687c65033f37c1747f13b9a74d0 100644 (file)
 
 #![feature(macro_rules)]
 
+use std::borrow::{Cow, IntoCow};
 use std::collections::Bitv;
 use std::default::Default;
 use std::iter::FromIterator;
+use std::ops::Add;
 use std::option::IntoIter as OptionIter;
 use std::rand::Rand;
 use std::rand::XorShiftRng as DummyRng;
@@ -28,6 +30,11 @@ fn u8_as_i8(x: u8) -> i8 { x as i8 }
 fn odd(x: uint) -> bool { x % 2 == 1 }
 fn dummy_rng() -> DummyRng { DummyRng::new_unseeded() }
 
+trait Size: Sized {
+    fn size() -> uint { std::mem::size_of::<Self>() }
+}
+impl<T> Size for T {}
+
 macro_rules! tests {
     ($($expr:expr, $ty:ty, ($($test:expr),*);)+) => (pub fn main() {$({
         const C: $ty = $expr;
@@ -70,14 +77,31 @@ macro_rules! tests {
     //    , (vec![b'f', b'o', b'o'], u8_as_i8);
 
     // Trait static methods.
-    // FIXME qualified path expressions aka UFCS i.e. <T as Trait>::method.
+    <bool as Size>::size, fn() -> uint, ();
     Default::default, fn() -> int, ();
+    <int as Default>::default, fn() -> int, ();
     Rand::rand, fn(&mut DummyRng) -> int, (&mut dummy_rng());
+    <int as Rand>::rand, fn(&mut DummyRng) -> int, (&mut dummy_rng());
     Rand::rand::<DummyRng>, fn(&mut DummyRng) -> int, (&mut dummy_rng());
+    <int as Rand>::rand::<DummyRng>, fn(&mut DummyRng) -> int, (&mut dummy_rng());
 
     // Trait non-static methods.
     Clone::clone, fn(&int) -> int, (&5);
+    <int as Clone>::clone, fn(&int) -> int, (&5);
     FromIterator::from_iter, fn(OptionIter<int>) -> Vec<int>, (Some(5).into_iter());
-    FromIterator::from_iter::<OptionIter<int>>, fn(OptionIter<int>) -> Vec<int>
-       , (Some(5).into_iter());
+    <Vec<_> as FromIterator<_>>::from_iter, fn(OptionIter<int>) -> Vec<int>,
+        (Some(5).into_iter());
+    <Vec<int> as FromIterator<_>>::from_iter, fn(OptionIter<int>) -> Vec<int>,
+        (Some(5).into_iter());
+    FromIterator::from_iter::<OptionIter<int>>, fn(OptionIter<int>) -> Vec<int>,
+        (Some(5).into_iter());
+    <Vec<int> as FromIterator<_>>::from_iter::<OptionIter<int>>, fn(OptionIter<int>) -> Vec<int>,
+        (Some(5).into_iter());
+    Add::add, fn(i32, i32) -> i32, (5, 6);
+    <i32 as Add<_>>::add, fn(i32, i32) -> i32, (5, 6);
+    <i32 as Add<i32>>::add, fn(i32, i32) -> i32, (5, 6);
+    <String as IntoCow<_, _>>::into_cow, fn(String) -> Cow<'static, String, str>,
+        ("foo".to_string());
+    <String as IntoCow<'static, _, _>>::into_cow, fn(String) -> Cow<'static, String, str>,
+        ("foo".to_string());
 }
index 65bf088786efb927273a95a3f2e0418cbe3da9f9..a071224999be094bcfc0d598fce7b86eebd1c2de 100644 (file)
@@ -13,7 +13,7 @@ fn main() {
     let ss: &&[int] = &s;
     let sss: &&&[int] = &ss;
 
-    println!("{:?}", &s[0..3]);
+    println!("{:?}", &s[..3]);
     println!("{:?}", &ss[3..]);
     println!("{:?}", &sss[2..4]);
 }
index 44cf0dd8b8ee8fe23267ce25d4a87205fa47104c..e4782e28928748b584c031bc4405658fb70df79d 100644 (file)
 
 extern crate "issue-17718" as other;
 
-use std::sync::atomic::{AtomicUint, ATOMIC_UINT_INIT, Ordering};
+use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering};
 
 const C1: uint = 1;
-const C2: AtomicUint = ATOMIC_UINT_INIT;
+const C2: AtomicUsize = ATOMIC_USIZE_INIT;
 const C3: fn() = foo;
 const C4: uint = C1 * C1 + C1 / C1;
 const C5: &'static uint = &C4;
@@ -25,7 +25,7 @@
 };
 
 static S1: uint = 3;
-static S2: AtomicUint = ATOMIC_UINT_INIT;
+static S2: AtomicUsize = ATOMIC_USIZE_INIT;
 
 mod test {
     static A: uint = 4;
diff --git a/src/test/run-pass/issue-20575.rs b/src/test/run-pass/issue-20575.rs
new file mode 100644 (file)
index 0000000..f83150b
--- /dev/null
@@ -0,0 +1,19 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Test that overloaded calls work with zero arity closures
+
+#![feature(box_syntax)]
+
+fn main() {
+    let functions: [Box<Fn() -> Option<()>>; 1] = [box || None];
+
+    let _: Option<Vec<()>> = functions.iter().map(|f| (*f)()).collect();
+}
index 42739628eed75c8dcb8f8dbd47316131a266c4e4..f845db9c421634bf0bbab252f85bc3312f488587 100644 (file)
@@ -16,7 +16,7 @@ pub fn main() {
     let abc = [1i, 2, 3];
     let tf = [true, false];
     let x  = [(), ()];
-    let slice = &x[0..1];
+    let slice = &x[..1];
 
     assert_repr_eq(&abc[], "[1i, 2i, 3i]".to_string());
     assert_repr_eq(&tf[], "[true, false]".to_string());
index 8f031d2e97e3ffd90d61a671466b9a32ff4cdef2..43e517404cb09b3adc9414f17584d9da7cfae8b2 100644 (file)
@@ -17,7 +17,7 @@ fn main() {
     let cmp: &[int] = &[3, 4, 5];
     assert!(&x[2..] == cmp);
     let cmp: &[int] = &[1, 2, 3];
-    assert!(&x[0..3] == cmp);
+    assert!(&x[..3] == cmp);
     let cmp: &[int] = &[2, 3, 4];
     assert!(&x[1..4] == cmp);
 
@@ -27,7 +27,7 @@ fn main() {
     let cmp: &[int] = &[3, 4, 5];
     assert!(&x[2..] == cmp);
     let cmp: &[int] = &[1, 2, 3];
-    assert!(&x[0..3] == cmp);
+    assert!(&x[..3] == cmp);
     let cmp: &[int] = &[2, 3, 4];
     assert!(&x[1..4] == cmp);
 
index cad71732034833e01909a7180986c9850f485ba8..c7149fa503bb3d2837503ac6355a20cd03e6501d 100644 (file)
@@ -15,7 +15,7 @@
 
 use std::io::{TcpListener, Listener, Acceptor, EndOfFile, TcpStream};
 use std::sync::Arc;
-use std::sync::atomic::{AtomicUint, Ordering};
+use std::sync::atomic::{AtomicUsize, Ordering};
 use std::sync::mpsc::channel;
 use std::thread::Thread;
 
@@ -30,7 +30,7 @@ fn test() {
     let mut l = TcpListener::bind("127.0.0.1:0").unwrap();
     let addr = l.socket_name().unwrap();
     let mut a = l.listen().unwrap();
-    let cnt = Arc::new(AtomicUint::new(0));
+    let cnt = Arc::new(AtomicUsize::new(0));
 
     let (srv_tx, srv_rx) = channel();
     let (cli_tx, cli_rx) = channel();
diff --git a/src/test/run-pass/trait-false-ambiguity-where-clause-builtin-bound.rs b/src/test/run-pass/trait-false-ambiguity-where-clause-builtin-bound.rs
new file mode 100644 (file)
index 0000000..ca66a10
--- /dev/null
@@ -0,0 +1,23 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Test that we do not error out because of a (False) ambiguity
+// between the builtin rules for Sized and the where clause. Issue
+// #20959.
+
+fn foo<K>(x: Option<K>)
+    where Option<K> : Sized
+{
+    let _y = x;
+}
+
+fn main() {
+    foo(Some(22));
+}
index 29bf82a81d65da7949368c4fd0156b7511530596..9e74c6da548996b6876dccfc5755059a38d1178c 100644 (file)
@@ -8,27 +8,29 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use std::sync::atomic::{AtomicUint, ATOMIC_UINT_INIT, Ordering};
+use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering};
 use std::rand::{thread_rng, Rng, Rand};
 use std::thread::Thread;
 
 const REPEATS: uint = 5;
 const MAX_LEN: uint = 32;
-static drop_counts: [AtomicUint;  MAX_LEN] =
-    // FIXME #5244: AtomicUint is not Copy.
+static drop_counts: [AtomicUsize;  MAX_LEN] =
+    // FIXME #5244: AtomicUsize is not Copy.
     [
-        ATOMIC_UINT_INIT, ATOMIC_UINT_INIT, ATOMIC_UINT_INIT, ATOMIC_UINT_INIT,
-        ATOMIC_UINT_INIT, ATOMIC_UINT_INIT, ATOMIC_UINT_INIT, ATOMIC_UINT_INIT,
-        ATOMIC_UINT_INIT, ATOMIC_UINT_INIT, ATOMIC_UINT_INIT, ATOMIC_UINT_INIT,
-        ATOMIC_UINT_INIT, ATOMIC_UINT_INIT, ATOMIC_UINT_INIT, ATOMIC_UINT_INIT,
-
-        ATOMIC_UINT_INIT, ATOMIC_UINT_INIT, ATOMIC_UINT_INIT, ATOMIC_UINT_INIT,
-        ATOMIC_UINT_INIT, ATOMIC_UINT_INIT, ATOMIC_UINT_INIT, ATOMIC_UINT_INIT,
-        ATOMIC_UINT_INIT, ATOMIC_UINT_INIT, ATOMIC_UINT_INIT, ATOMIC_UINT_INIT,
-        ATOMIC_UINT_INIT, ATOMIC_UINT_INIT, ATOMIC_UINT_INIT, ATOMIC_UINT_INIT,
+        ATOMIC_USIZE_INIT, ATOMIC_USIZE_INIT, ATOMIC_USIZE_INIT,
+        ATOMIC_USIZE_INIT, ATOMIC_USIZE_INIT, ATOMIC_USIZE_INIT,
+        ATOMIC_USIZE_INIT, ATOMIC_USIZE_INIT, ATOMIC_USIZE_INIT,
+        ATOMIC_USIZE_INIT, ATOMIC_USIZE_INIT, ATOMIC_USIZE_INIT,
+        ATOMIC_USIZE_INIT, ATOMIC_USIZE_INIT, ATOMIC_USIZE_INIT,
+        ATOMIC_USIZE_INIT, ATOMIC_USIZE_INIT, ATOMIC_USIZE_INIT,
+        ATOMIC_USIZE_INIT, ATOMIC_USIZE_INIT, ATOMIC_USIZE_INIT,
+        ATOMIC_USIZE_INIT, ATOMIC_USIZE_INIT, ATOMIC_USIZE_INIT,
+        ATOMIC_USIZE_INIT, ATOMIC_USIZE_INIT, ATOMIC_USIZE_INIT,
+        ATOMIC_USIZE_INIT, ATOMIC_USIZE_INIT, ATOMIC_USIZE_INIT,
+        ATOMIC_USIZE_INIT, ATOMIC_USIZE_INIT,
      ];
 
-static creation_count: AtomicUint = ATOMIC_UINT_INIT;
+static creation_count: AtomicUsize = ATOMIC_USIZE_INIT;
 
 #[derive(Clone, PartialEq, PartialOrd, Eq, Ord)]
 struct DropCounter { x: uint, creation_id: uint }
diff --git a/src/test/run-pass/where-clause-bounds-inconsistency.rs b/src/test/run-pass/where-clause-bounds-inconsistency.rs
new file mode 100644 (file)
index 0000000..a1a6112
--- /dev/null
@@ -0,0 +1,28 @@
+// 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 Bound {}
+
+trait Trait {
+    fn a<T>(&self, T) where T: Bound;
+    fn b<T>(&self, T) where T: Bound;
+    fn c<T: Bound>(&self, T);
+    fn d<T: Bound>(&self, T);
+}
+
+impl Trait for bool {
+    fn a<T: Bound>(&self, _: T) {}
+    //^~ This gets rejected but should be accepted
+    fn b<T>(&self, _: T) where T: Bound {}
+    fn c<T: Bound>(&self, _: T) {}
+    fn d<T>(&self, _: T) where T: Bound {}
+}
+
+fn main() {}