]> git.lizzy.rs Git - rust.git/commitdiff
Auto merge of #34946 - alexcrichton:fix-cfg, r=brson
authorbors <bors@rust-lang.org>
Thu, 28 Jul 2016 01:58:04 +0000 (18:58 -0700)
committerGitHub <noreply@github.com>
Thu, 28 Jul 2016 01:58:04 +0000 (18:58 -0700)
std: Fix usage of SOCK_CLOEXEC

This code path was intended to only get executed on Linux, but unfortunately the
`cfg!` was malformed so it actually never got executed.

197 files changed:
mk/cfg/aarch64-apple-ios.mk
mk/cfg/armv7-apple-ios.mk
mk/cfg/armv7s-apple-ios.mk
mk/cfg/asmjs-unknown-emscripten.mk
mk/cfg/i386-apple-ios.mk
mk/cfg/i586-unknown-linux-gnu.mk
mk/cfg/i686-apple-darwin.mk
mk/cfg/i686-pc-windows-gnu.mk
mk/cfg/i686-unknown-freebsd.mk
mk/cfg/i686-unknown-linux-gnu.mk
mk/cfg/i686-unknown-linux-musl.mk
mk/cfg/powerpc-unknown-linux-gnu.mk
mk/cfg/powerpc64-unknown-linux-gnu.mk
mk/cfg/powerpc64le-unknown-linux-gnu.mk
mk/cfg/x86_64-apple-darwin.mk
mk/cfg/x86_64-apple-ios.mk
mk/cfg/x86_64-pc-windows-gnu.mk
mk/cfg/x86_64-rumprun-netbsd.mk
mk/cfg/x86_64-sun-solaris.mk
mk/cfg/x86_64-unknown-bitrig.mk
mk/cfg/x86_64-unknown-dragonfly.mk
mk/cfg/x86_64-unknown-freebsd.mk
mk/cfg/x86_64-unknown-linux-gnu.mk
mk/cfg/x86_64-unknown-linux-musl.mk
mk/cfg/x86_64-unknown-netbsd.mk
mk/cfg/x86_64-unknown-openbsd.mk
mk/rt.mk
mk/tests.mk
src/bootstrap/Cargo.lock
src/bootstrap/Cargo.toml
src/bootstrap/lib.rs
src/bootstrap/native.rs
src/bootstrap/step.rs
src/bootstrap/util.rs
src/doc/book/inline-assembly.md
src/doc/book/loops.md
src/doc/book/syntax-index.md
src/doc/book/trait-objects.md
src/doc/nomicon/phantom-data.md
src/doc/reference.md
src/liballoc/arc.rs
src/libcollections/btree/map.rs
src/libcollections/fmt.rs
src/libcollections/linked_list.rs
src/libcollections/slice.rs
src/libcollections/string.rs
src/libcollections/vec.rs
src/libcollections/vec_deque.rs
src/libcore/fmt/mod.rs
src/libcore/hash/mod.rs
src/libcore/intrinsics.rs
src/libcore/iter/traits.rs
src/libcore/option.rs
src/libcore/slice.rs
src/libpanic_unwind/dwarf/eh.rs
src/libpanic_unwind/gcc.rs
src/libpanic_unwind/lib.rs
src/libpanic_unwind/seh64_gnu.rs
src/librustc/infer/error_reporting.rs
src/librustc/infer/mod.rs
src/librustc/session/config.rs
src/librustc/session/mod.rs
src/librustc/traits/error_reporting.rs
src/librustc/ty/structural_impls.rs
src/librustc_back/target/mips_unknown_linux_gnu.rs
src/librustc_back/target/mod.rs
src/librustc_const_eval/Cargo.toml
src/librustc_const_eval/check_match.rs
src/librustc_const_eval/diagnostics.rs
src/librustc_const_eval/eval.rs
src/librustc_const_eval/lib.rs
src/librustc_driver/driver.rs
src/librustc_errors/lib.rs
src/librustc_mir/pretty.rs
src/librustc_passes/consts.rs
src/librustc_passes/diagnostics.rs
src/librustc_save_analysis/csv_dumper.rs
src/librustc_trans/_match.rs
src/librustc_trans/base.rs
src/librustc_trans/consts.rs
src/librustc_trans/intrinsic.rs
src/librustc_trans/mir/constant.rs
src/librustc_trans/trans_item.rs
src/librustc_trans/tvec.rs
src/librustc_typeck/astconv.rs
src/librustc_typeck/check/_match.rs
src/librustc_typeck/check/callee.rs
src/librustc_typeck/check/cast.rs
src/librustc_typeck/check/compare_method.rs
src/librustc_typeck/check/demand.rs
src/librustc_typeck/check/intrinsic.rs
src/librustc_typeck/check/method/suggest.rs
src/librustc_typeck/check/mod.rs
src/librustc_typeck/check/op.rs
src/librustc_typeck/check/wfcheck.rs
src/librustc_typeck/collect.rs
src/librustc_typeck/diagnostics.rs
src/librustc_typeck/lib.rs
src/librustc_unicode/char.rs
src/librustdoc/html/highlight.rs
src/librustdoc/html/static/rustdoc.css
src/libstd/collections/hash/map.rs
src/libstd/env.rs
src/libstd/fs.rs
src/libstd/io/mod.rs
src/libstd/net/ip.rs
src/libstd/sync/mpsc/mod.rs
src/libstd/sys/unix/ext/fs.rs
src/libstd/sys/unix/os.rs
src/libstd/sys/windows/os.rs
src/libsyntax/ext/quote.rs
src/libsyntax/parse/parser.rs
src/libsyntax/parse/token.rs
src/libsyntax/print/pprust.rs
src/libsyntax_ext/deriving/bounds.rs
src/libsyntax_ext/deriving/clone.rs
src/libsyntax_ext/deriving/cmp/eq.rs
src/libsyntax_ext/deriving/cmp/ord.rs
src/libsyntax_ext/deriving/cmp/partial_eq.rs
src/libsyntax_ext/deriving/cmp/partial_ord.rs
src/libsyntax_ext/deriving/debug.rs
src/libsyntax_ext/deriving/decodable.rs
src/libsyntax_ext/deriving/default.rs
src/libsyntax_ext/deriving/encodable.rs
src/libsyntax_ext/deriving/generic/mod.rs
src/libsyntax_ext/deriving/hash.rs
src/libsyntax_ext/deriving/mod.rs
src/libsyntax_pos/lib.rs
src/libunwind/libunwind.rs
src/rustc/Cargo.lock
src/test/codegen/internalize-closures.rs [new file with mode: 0644]
src/test/compile-fail/array_const_index-0.rs
src/test/compile-fail/array_const_index-1.rs
src/test/compile-fail/associated-const-array-len.rs
src/test/compile-fail/associated-const-impl-wrong-type.rs
src/test/compile-fail/associated-const-type-parameter-arrays-2.rs
src/test/compile-fail/associated-types-eq-3.rs
src/test/compile-fail/associated-types/higher-ranked-projection.rs [new file with mode: 0644]
src/test/compile-fail/const-array-oob.rs
src/test/compile-fail/const-call.rs
src/test/compile-fail/const-err.rs
src/test/compile-fail/const-eval-overflow-2.rs
src/test/compile-fail/const-eval-overflow-3.rs
src/test/compile-fail/const-eval-overflow-4b.rs
src/test/compile-fail/const-eval-overflow.rs
src/test/compile-fail/const-eval-span.rs
src/test/compile-fail/const-fn-error.rs
src/test/compile-fail/const-index-feature-gate.rs
src/test/compile-fail/const-integer-bool-ops.rs
src/test/compile-fail/const-len-underflow-separate-spans.rs
src/test/compile-fail/const-len-underflow-subspans.rs
src/test/compile-fail/const-pattern-not-const-evaluable.rs
src/test/compile-fail/const-slice-oob.rs
src/test/compile-fail/const-tup-index-span.rs
src/test/compile-fail/discrim-ill-typed.rs
src/test/compile-fail/enum-discrim-too-small.rs
src/test/compile-fail/eval-enum.rs
src/test/compile-fail/explicit-self-lifetime-mismatch.rs
src/test/compile-fail/feature-gate-negate-unsigned0.rs
src/test/compile-fail/invalid-path-in-const.rs
src/test/compile-fail/issue-13033.rs
src/test/compile-fail/issue-15094.rs
src/test/compile-fail/issue-17740.rs
src/test/compile-fail/issue-21332.rs
src/test/compile-fail/issue-22933-2.rs
src/test/compile-fail/issue-23217.rs
src/test/compile-fail/issue-24356.rs
src/test/compile-fail/issue-25145.rs
src/test/compile-fail/issue-27008.rs
src/test/compile-fail/issue-27895.rs
src/test/compile-fail/issue-28586.rs
src/test/compile-fail/issue-31173.rs [new file with mode: 0644]
src/test/compile-fail/issue-3521.rs
src/test/compile-fail/issue-8761.rs
src/test/compile-fail/lifetime-inference-give-expl-lifetime-param.rs
src/test/compile-fail/match-range-fail.rs
src/test/compile-fail/non-constant-enum-for-vec-repeat.rs
src/test/compile-fail/non-constant-expr-for-vec-repeat.rs
src/test/compile-fail/non-constant-in-const-path.rs
src/test/compile-fail/repeat_count.rs
src/test/compile-fail/trait-impl-method-mismatch.rs
src/test/compile-fail/ufcs-explicit-self-bad.rs
src/test/compile-fail/unsafe-trait-impl.rs
src/test/debuginfo/function-prologue-stepping-no-stack-check.rs [deleted file]
src/test/debuginfo/type-names.rs
src/test/mir-opt/README.md [new file with mode: 0644]
src/test/mir-opt/return_an_array.rs [new file with mode: 0644]
src/test/mir-opt/simplify_if.rs [new file with mode: 0644]
src/test/run-make/issue-33329/Makefile [new file with mode: 0644]
src/test/run-make/issue-33329/main.rs [new file with mode: 0644]
src/test/run-pass/const-byte-str-cast.rs
src/test/run-pass/env-args-reverse-iterator.rs [new file with mode: 0644]
src/test/run-pass/ifmt.rs
src/test/run-pass/macro-of-higher-order.rs
src/tools/compiletest/src/common.rs
src/tools/compiletest/src/main.rs
src/tools/compiletest/src/runtest.rs

index 8cd09fa9043c8136d1e2d4878f2a1dd304ae8011..5d822f1b1aba62c645969712bab2bba46ad73018 100644 (file)
@@ -17,7 +17,7 @@ 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)
 CFG_JEMALLOC_CFLAGS_aarch64-apple-ios := $(CFG_IOS_SDK_FLAGS_aarch64-apple-ios)
-CFG_GCCISH_CFLAGS_aarch64-apple-ios := -Wall -Werror -fPIC $(CFG_IOS_SDK_FLAGS_aarch64-apple-ios)
+CFG_GCCISH_CFLAGS_aarch64-apple-ios :=  -fPIC $(CFG_IOS_SDK_FLAGS_aarch64-apple-ios)
 CFG_GCCISH_CXXFLAGS_aarch64-apple-ios := -fno-rtti $(CFG_IOS_SDK_FLAGS_aarch64-apple-ios) -I$(CFG_IOS_SDK_aarch64-apple-ios)/usr/include/c++/4.2.1
 CFG_GCCISH_LINK_FLAGS_aarch64-apple-ios := -lpthread -syslibroot $(CFG_IOS_SDK_aarch64-apple-ios) -Wl,-no_compact_unwind
 CFG_GCCISH_DEF_FLAG_aarch64-apple-ios := -Wl,-exported_symbols_list,
index d4696976574e94c52252701a8559f7ac0fbd6b62..34ca4de6563e41626fe59d68bca0af2a3437b724 100644 (file)
@@ -15,7 +15,7 @@ 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)
-CFG_GCCISH_CFLAGS_armv7-apple-ios := -Wall -Werror -g -fPIC $(CFG_IOS_SDK_FLAGS_armv7-apple-ios) -mfpu=vfp3 -arch armv7
+CFG_GCCISH_CFLAGS_armv7-apple-ios :=  -g -fPIC $(CFG_IOS_SDK_FLAGS_armv7-apple-ios) -mfpu=vfp3 -arch armv7
 CFG_GCCISH_CXXFLAGS_armv7-apple-ios := -fno-rtti $(CFG_IOS_SDK_FLAGS_armv7-apple-ios) -I$(CFG_IOS_SDK_armv7-apple-ios)/usr/include/c++/4.2.1
 CFG_GCCISH_LINK_FLAGS_armv7-apple-ios := -lpthread -syslibroot $(CFG_IOS_SDK_armv7-apple-ios) -Wl,-no_compact_unwind
 CFG_GCCISH_DEF_FLAG_armv7-apple-ios := -Wl,-exported_symbols_list,
index efad43d25627d0e611e7a698e84befdfecdb0ba1..6da7905a7003bd955ebd6e7a18b5c3c0dfd2a3df 100644 (file)
@@ -15,7 +15,7 @@ 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 $(CFG_IOS_SDK_FLAGS_armv7s-apple-ios)
-CFG_GCCISH_CFLAGS_armv7s-apple-ios := -Wall -Werror -g -fPIC $(CFG_IOS_SDK_FLAGS_armv7s-apple-ios) -arch armv7s
+CFG_GCCISH_CFLAGS_armv7s-apple-ios :=  -g -fPIC $(CFG_IOS_SDK_FLAGS_armv7s-apple-ios) -arch armv7s
 CFG_GCCISH_CXXFLAGS_armv7s-apple-ios := -fno-rtti $(CFG_IOS_SDK_FLAGS_armv7s-apple-ios) -I$(CFG_IOS_SDK_armv7s-apple-ios)/usr/include/c++/4.2.1
 CFG_GCCISH_LINK_FLAGS_armv7s-apple-ios := -lpthread -syslibroot $(CFG_IOS_SDK_armv7s-apple-ios) -Wl,-no_compact_unwind
 CFG_GCCISH_DEF_FLAG_armv7s-apple-ios := -Wl,-exported_symbols_list,
index 9c98c0a6b4c9d87bbeca499d8a399e1648d33fc1..a98a51b06b5d3374e38a2588b6a30d9adb1febc3 100644 (file)
@@ -8,7 +8,7 @@ CFG_STATIC_LIB_NAME_asmjs-unknown-emscripten=lib$(1).a
 CFG_LIB_GLOB_asmjs-unknown-emscripten=lib$(1)-*.so
 CFG_LIB_DSYM_GLOB_asmjs-unknown-emscripten=lib$(1)-*.dylib.dSYM
 CFG_JEMALLOC_CFLAGS_asmjs-unknown-emscripten := -m32 $(CFLAGS)
-CFG_GCCISH_CFLAGS_asmjs-unknown-emscripten := -Wall -Werror -g -fPIC -m32 $(CFLAGS)
+CFG_GCCISH_CFLAGS_asmjs-unknown-emscripten :=  -g -fPIC -m32 $(CFLAGS)
 CFG_GCCISH_CXXFLAGS_asmjs-unknown-emscripten := -fno-rtti $(CXXFLAGS)
 CFG_GCCISH_LINK_FLAGS_asmjs-unknown-emscripten := -shared -fPIC -ldl -pthread  -lrt -g -m32
 CFG_GCCISH_DEF_FLAG_asmjs-unknown-emscripten := -Wl,--export-dynamic,--dynamic-list=
index 373e2e3b65d15e6d7e39e724ede7498f2a532bf0..bfb7fa281f242aadf870ef16185b5de8faaaed5e 100644 (file)
@@ -14,7 +14,7 @@ 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)
+CFG_GCCISH_CFLAGS_i386-apple-ios :=  -g -fPIC -m32 $(CFG_IOSSIM_FLAGS_i386-apple-ios)
 CFG_GCCISH_CXXFLAGS_i386-apple-ios := -fno-rtti $(CFG_IOSSIM_FLAGS_i386-apple-ios) -I$(CFG_IOSSIM_SDK_i386-apple-ios)/usr/include/c++/4.2.1
 CFG_GCCISH_LINK_FLAGS_i386-apple-ios := -lpthread -m32 -Wl,-no_compact_unwind -m32 -Wl,-syslibroot $(CFG_IOSSIM_SDK_i386-apple-ios)
 CFG_GCCISH_DEF_FLAG_i386-apple-ios := -Wl,-exported_symbols_list,
index 2b28550320d85b2b31ec74495dee6c1dbf24dc53..14b9ebfdba66851f8c8d8031afc2eb006c526359 100644 (file)
@@ -8,7 +8,7 @@ CFG_STATIC_LIB_NAME_i586-unknown-linux-gnu=lib$(1).a
 CFG_LIB_GLOB_i586-unknown-linux-gnu=lib$(1)-*.so
 CFG_LIB_DSYM_GLOB_i586-unknown-linux-gnu=lib$(1)-*.dylib.dSYM
 CFG_JEMALLOC_CFLAGS_i586-unknown-linux-gnu := -m32 $(CFLAGS) -march=pentium
-CFG_GCCISH_CFLAGS_i586-unknown-linux-gnu := -Wall -Werror -g -fPIC -m32 $(CFLAGS) -march=pentium
+CFG_GCCISH_CFLAGS_i586-unknown-linux-gnu :=  -g -fPIC -m32 $(CFLAGS) -march=pentium
 CFG_GCCISH_CXXFLAGS_i586-unknown-linux-gnu := -fno-rtti $(CXXFLAGS) -march=pentium
 CFG_GCCISH_LINK_FLAGS_i586-unknown-linux-gnu := -shared -fPIC -ldl -pthread  -lrt -g -m32
 CFG_GCCISH_DEF_FLAG_i586-unknown-linux-gnu := -Wl,--export-dynamic,--dynamic-list=
index 7ebb492bb21fe1c9d8a50dd4ac697529d85223dc..e4b3431e8b67f0256916445fafa712ffd94f3253 100644 (file)
@@ -8,7 +8,7 @@ CFG_STATIC_LIB_NAME_i686-apple-darwin=lib$(1).a
 CFG_LIB_GLOB_i686-apple-darwin=lib$(1)-*.dylib
 CFG_LIB_DSYM_GLOB_i686-apple-darwin=lib$(1)-*.dylib.dSYM
 CFG_JEMALLOC_CFLAGS_i686-apple-darwin := -m32 -arch i386 $(CFLAGS)
-CFG_GCCISH_CFLAGS_i686-apple-darwin := -Wall -Werror -g -fPIC -m32 -arch i386 $(CFLAGS)
+CFG_GCCISH_CFLAGS_i686-apple-darwin :=  -g -fPIC -m32 -arch i386 $(CFLAGS)
 CFG_GCCISH_CXXFLAGS_i686-apple-darwin := -fno-rtti $(CXXFLAGS)
 CFG_GCCISH_LINK_FLAGS_i686-apple-darwin := -dynamiclib -pthread  -framework CoreServices -m32
 CFG_GCCISH_DEF_FLAG_i686-apple-darwin := -Wl,-exported_symbols_list,
index 3426b30aeeb85f9080d28f6f4dda698c8a11dd28..50c2b8c98acd3c130d221dfdfc327f165b960036 100644 (file)
@@ -9,7 +9,7 @@ CFG_STATIC_LIB_NAME_i686-pc-windows-gnu=$(1).lib
 CFG_LIB_GLOB_i686-pc-windows-gnu=$(1)-*.dll
 CFG_LIB_DSYM_GLOB_i686-pc-windows-gnu=$(1)-*.dylib.dSYM
 CFG_JEMALLOC_CFLAGS_i686-pc-windows-gnu := -march=i686 -m32 -D_WIN32_WINNT=0x0600 -D__USE_MINGW_ANSI_STDIO=1 $(CFLAGS)
-CFG_GCCISH_CFLAGS_i686-pc-windows-gnu := -Wall -Werror -g -m32 -D_WIN32_WINNT=0x0600 -D__USE_MINGW_ANSI_STDIO=1 $(CFLAGS)
+CFG_GCCISH_CFLAGS_i686-pc-windows-gnu :=  -g -m32 -D_WIN32_WINNT=0x0600 -D__USE_MINGW_ANSI_STDIO=1 $(CFLAGS)
 CFG_GCCISH_CXXFLAGS_i686-pc-windows-gnu := -fno-rtti $(CXXFLAGS)
 CFG_GCCISH_LINK_FLAGS_i686-pc-windows-gnu := -shared -g -m32
 CFG_GCCISH_DEF_FLAG_i686-pc-windows-gnu :=
index bbc0c2d6f396ecad629d20fbbf06d03c76eb5108..a9d4446d5d49b5048060977cb1585d62e3b7b77a 100644 (file)
@@ -8,7 +8,7 @@ CFG_STATIC_LIB_NAME_i686-unknown-freebsd=lib$(1).a
 CFG_LIB_GLOB_i686-unknown-freebsd=lib$(1)-*.so
 CFG_LIB_DSYM_GLOB_i686-unknown-freebsd=$(1)-*.dylib.dSYM
 CFG_JEMALLOC_CFLAGS_i686-unknown-freebsd := -m32 -I/usr/local/include $(CFLAGS)
-CFG_GCCISH_CFLAGS_i686-unknown-freebsd := -Wall -Werror -g -fPIC -m32 -arch i386 -I/usr/local/include $(CFLAGS)
+CFG_GCCISH_CFLAGS_i686-unknown-freebsd :=  -g -fPIC -m32 -arch i386 -I/usr/local/include $(CFLAGS)
 CFG_GCCISH_LINK_FLAGS_i686-unknown-freebsd := -m32 -shared -fPIC -g -pthread -lrt
 CFG_GCCISH_DEF_FLAG_i686-unknown-freebsd := -Wl,--export-dynamic,--dynamic-list=
 CFG_LLC_FLAGS_i686-unknown-freebsd :=
index 129af8ac69609396b0b31cd496f294e0e9ed4d18..9e2312008a10ad6916ea34dbe5fb9b32b5d7cb6b 100644 (file)
@@ -8,7 +8,7 @@ CFG_STATIC_LIB_NAME_i686-unknown-linux-gnu=lib$(1).a
 CFG_LIB_GLOB_i686-unknown-linux-gnu=lib$(1)-*.so
 CFG_LIB_DSYM_GLOB_i686-unknown-linux-gnu=lib$(1)-*.dylib.dSYM
 CFG_JEMALLOC_CFLAGS_i686-unknown-linux-gnu := -m32 $(CFLAGS)
-CFG_GCCISH_CFLAGS_i686-unknown-linux-gnu := -Wall -Werror -g -fPIC -m32 $(CFLAGS) -march=i686
+CFG_GCCISH_CFLAGS_i686-unknown-linux-gnu :=  -g -fPIC -m32 $(CFLAGS) -march=i686
 CFG_GCCISH_CXXFLAGS_i686-unknown-linux-gnu := -fno-rtti $(CXXFLAGS)
 CFG_GCCISH_LINK_FLAGS_i686-unknown-linux-gnu := -shared -fPIC -ldl -pthread  -lrt -g -m32
 CFG_GCCISH_DEF_FLAG_i686-unknown-linux-gnu := -Wl,--export-dynamic,--dynamic-list=
index c1cd20a843cec5e2233296dc865acc612c309c2a..80918728316a665f6c110c6aa940cfde8796962b 100644 (file)
@@ -8,7 +8,7 @@ CFG_LIB_NAME_i686-unknown-linux-musl=lib$(1).so
 CFG_STATIC_LIB_NAME_i686-unknown-linux-musl=lib$(1).a
 CFG_LIB_GLOB_i686-unknown-linux-musl=lib$(1)-*.so
 CFG_JEMALLOC_CFLAGS_i686-unknown-linux-musl := -m32 -Wl,-melf_i386
-CFG_GCCISH_CFLAGS_i686-unknown-linux-musl := -Wall -Werror -g -fPIC -m32 -Wl,-melf_i386
+CFG_GCCISH_CFLAGS_i686-unknown-linux-musl :=  -g -fPIC -m32 -Wl,-melf_i386
 CFG_GCCISH_CXXFLAGS_i686-unknown-linux-musl :=
 CFG_GCCISH_LINK_FLAGS_i686-unknown-linux-musl :=
 CFG_GCCISH_DEF_FLAG_i686-unknown-linux-musl :=
index dda957673eba665d15ab266a29e89a76336d370c..9c5720de4b310dc8d44f9691d6382df55a456987 100644 (file)
@@ -9,7 +9,7 @@ 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_CFLAGS_powerpc-unknown-linux-gnu :=  -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=
index f6e6436f6157805254341e7cee3c316f30e775c8..389bb6f0cab492e02110d3f6f1bc74a33faa3f4b 100644 (file)
@@ -10,7 +10,7 @@ CFG_LIB_GLOB_powerpc64-unknown-linux-gnu=lib$(1)-*.so
 CFG_LIB_DSYM_GLOB_powerpc64-unknown-linux-gnu=lib$(1)-*.dylib.dSYM
 CFG_JEMALLOC_CFLAGS_powerpc64-unknown-linux-gnu := -m64
 CFG_CFLAGS_powerpc64-unknown-linux-gnu := -m64 $(CFLAGS)
-CFG_GCCISH_CFLAGS_powerpc64-unknown-linux-gnu := -Wall -Werror -g -fPIC -m64 $(CFLAGS)
+CFG_GCCISH_CFLAGS_powerpc64-unknown-linux-gnu :=  -g -fPIC -m64 $(CFLAGS)
 CFG_GCCISH_CXXFLAGS_powerpc64-unknown-linux-gnu := -fno-rtti $(CXXFLAGS)
 CFG_GCCISH_LINK_FLAGS_powerpc64-unknown-linux-gnu := -shared -fPIC -ldl -pthread  -lrt -g -m64
 CFG_GCCISH_DEF_FLAG_powerpc64-unknown-linux-gnu := -Wl,--export-dynamic,--dynamic-list=
index a2049331ab2e994c3edbff53e06728dc4984219d..6884fa11e7412ceedd76d40cf4a5e44e15143c49 100644 (file)
@@ -9,7 +9,7 @@ CFG_STATIC_LIB_NAME_powerpc64le-unknown-linux-gnu=lib$(1).a
 CFG_LIB_GLOB_powerpc64le-unknown-linux-gnu=lib$(1)-*.so
 CFG_LIB_DSYM_GLOB_powerpc64le-unknown-linux-gnu=lib$(1)-*.dylib.dSYM
 CFG_CFLAGS_powerpc64le-unknown-linux-gnu := -m64 $(CFLAGS)
-CFG_GCCISH_CFLAGS_powerpc64le-unknown-linux-gnu := -Wall -Werror -g -fPIC -m64 $(CFLAGS)
+CFG_GCCISH_CFLAGS_powerpc64le-unknown-linux-gnu :=  -g -fPIC -m64 $(CFLAGS)
 CFG_GCCISH_CXXFLAGS_powerpc64le-unknown-linux-gnu := -fno-rtti $(CXXFLAGS)
 CFG_GCCISH_LINK_FLAGS_powerpc64le-unknown-linux-gnu := -shared -fPIC -ldl -pthread  -lrt -g -m64
 CFG_GCCISH_DEF_FLAG_powerpc64le-unknown-linux-gnu := -Wl,--export-dynamic,--dynamic-list=
index 4c68d3dcf37b4424b10e06ae845bfb30e2950d57..8af47b671a8505a2727b7d69adfae00b23afed19 100644 (file)
@@ -8,7 +8,7 @@ CFG_STATIC_LIB_NAME_x86_64-apple-darwin=lib$(1).a
 CFG_LIB_GLOB_x86_64-apple-darwin=lib$(1)-*.dylib
 CFG_LIB_DSYM_GLOB_x86_64-apple-darwin=lib$(1)-*.dylib.dSYM
 CFG_JEMALLOC_CFLAGS_x86_64-apple-darwin := -m64 -arch x86_64 $(CFLAGS)
-CFG_GCCISH_CFLAGS_x86_64-apple-darwin := -Wall -Werror -g -fPIC -m64 -arch x86_64 $(CFLAGS)
+CFG_GCCISH_CFLAGS_x86_64-apple-darwin :=  -g -fPIC -m64 -arch x86_64 $(CFLAGS)
 CFG_GCCISH_CXXFLAGS_x86_64-apple-darwin := -fno-rtti $(CXXFLAGS)
 CFG_GCCISH_LINK_FLAGS_x86_64-apple-darwin := -dynamiclib -pthread  -framework CoreServices -m64
 CFG_GCCISH_DEF_FLAG_x86_64-apple-darwin := -Wl,-exported_symbols_list,
index dd6080fdb0bab1ecc872a8fd9e0f1160bf37a477..764cdc15996d0c5fe8fc93f8b0d1ca35bc949194 100644 (file)
@@ -16,7 +16,7 @@ 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)
 CFG_JEMALLOC_CFLAGS_x86_64-apple-ios := $(CFG_IOSSIM_FLAGS_x86_64-apple-ios)
-CFG_GCCISH_CFLAGS_x86_64-apple-ios := -Wall -Werror -fPIC $(CFG_IOSSIM_FLAGS_x86_64-apple-ios)
+CFG_GCCISH_CFLAGS_x86_64-apple-ios :=  -fPIC $(CFG_IOSSIM_FLAGS_x86_64-apple-ios)
 CFG_GCCISH_CXXFLAGS_x86_64-apple-ios := -fno-rtti $(CFG_IOSSIM_FLAGS_x86_64-apple-ios) -I$(CFG_IOSSIM_SDK_x86_64-apple-ios)/usr/include/c++/4.2.1
 CFG_GCCISH_LINK_FLAGS_x86_64-apple-ios := -lpthread -Wl,-no_compact_unwind -m64 -Wl,-syslibroot $(CFG_IOSSIM_SDK_x86_64-apple-ios)
 CFG_GCCISH_DEF_FLAG_x86_64-apple-ios := -Wl,-exported_symbols_list,
index f0732d08c71ea84c65b9c5e6140084bb69ac2aa2..82e7b23279fb5339c9fe773df72f26341132880c 100644 (file)
@@ -9,7 +9,7 @@ CFG_STATIC_LIB_NAME_x86_64-pc-windows-gnu=$(1).lib
 CFG_LIB_GLOB_x86_64-pc-windows-gnu=$(1)-*.dll
 CFG_LIB_DSYM_GLOB_x86_64-pc-windows-gnu=$(1)-*.dylib.dSYM
 CFG_JEMALLOC_CFLAGS_x86_64-pc-windows-gnu := -m64 -D_WIN32_WINNT=0x0600 -D__USE_MINGW_ANSI_STDIO=1 $(CFLAGS)
-CFG_GCCISH_CFLAGS_x86_64-pc-windows-gnu := -Wall -Werror -g -m64 -D_WIN32_WINNT=0x0600 -D__USE_MINGW_ANSI_STDIO=1 $(CFLAGS)
+CFG_GCCISH_CFLAGS_x86_64-pc-windows-gnu :=  -g -m64 -D_WIN32_WINNT=0x0600 -D__USE_MINGW_ANSI_STDIO=1 $(CFLAGS)
 CFG_GCCISH_CXXFLAGS_x86_64-pc-windows-gnu := -fno-rtti $(CXXFLAGS)
 CFG_GCCISH_LINK_FLAGS_x86_64-pc-windows-gnu := -shared -g -m64
 CFG_GCCISH_DEF_FLAG_x86_64-pc-windows-gnu :=
index 1b5aa12274d4eaa330f151e67f75446bfa9b8220..53d58b9fceaa6ab0b762bf74229558de5e0ca1a4 100644 (file)
@@ -9,7 +9,7 @@ CFG_LIB_NAME_x86_64-rumprun-netbsd=lib$(1).so
 CFG_STATIC_LIB_NAME_x86_64-rumprun-netbsd=lib$(1).a
 CFG_LIB_GLOB_x86_64-rumprun-netbsd=lib$(1)-*.so
 CFG_JEMALLOC_CFLAGS_x86_64-rumprun-netbsd := -m64
-CFG_GCCISH_CFLAGS_x86_64-rumprun-netbsd := -Wall -Werror -g -fPIC -m64
+CFG_GCCISH_CFLAGS_x86_64-rumprun-netbsd :=  -g -fPIC -m64
 CFG_GCCISH_CXXFLAGS_x86_64-rumprun-netbsd :=
 CFG_GCCISH_LINK_FLAGS_x86_64-rumprun-netbsd :=
 CFG_GCCISH_DEF_FLAG_x86_64-rumprun-netbsd :=
index 0a09a5cf72d9f94ecfbe8199b9dd9e1b837ede99..7fc323b234aee9b750dfff8813d4904caa1a723b 100644 (file)
@@ -9,7 +9,7 @@ CFG_STATIC_LIB_NAME_x86_64-sun-solaris=lib$(1).a
 CFG_LIB_GLOB_x86_64-sun-solaris=lib$(1)-*.so
 CFG_LIB_DSYM_GLOB_x86_64-sun-solaris=$(1)-*.dylib.dSYM
 CFG_JEMALLOC_CFLAGS_x86_64-sun-solaris := -I/usr/local/include $(CFLAGS)
-CFG_GCCISH_CFLAGS_x86_64-sun-solaris := -Wall -Werror -g -D_POSIX_PTHREAD_SEMANTICS -fPIC -I/usr/local/include $(CFLAGS)
+CFG_GCCISH_CFLAGS_x86_64-sun-solaris :=  -g -D_POSIX_PTHREAD_SEMANTICS -fPIC -I/usr/local/include $(CFLAGS)
 CFG_GCCISH_LINK_FLAGS_x86_64-sun-solaris := -shared -fPIC -g -pthread  -lrt
 CFG_GCCISH_DEF_FLAG_x86_64-sun-solaris := -Wl,--export-dynamic,--dynamic-list=
 CFG_LLC_FLAGS_x86_64-sun-solaris :=
index 76b39b4502548e9a52ea316431ff91e0f37ab517..8ac31c176188b0a50a4efcf923f5825868ace821 100644 (file)
@@ -8,7 +8,7 @@ CFG_STATIC_LIB_NAME_x86_64-unknown-bitrig=lib$(1).a
 CFG_LIB_GLOB_x86_64-unknown-bitrig=lib$(1)-*.so
 CFG_LIB_DSYM_GLOB_x86_64-unknown-bitrig=$(1)-*.dylib.dSYM
 CFG_JEMALLOC_CFLAGS_x86_64-unknown-bitrig := -m64 -I/usr/include $(CFLAGS)
-CFG_GCCISH_CFLAGS_x86_64-unknown-bitrig := -Wall -Werror -fPIE -fPIC -m64 -I/usr/include $(CFLAGS)
+CFG_GCCISH_CFLAGS_x86_64-unknown-bitrig :=  -fPIE -fPIC -m64 -I/usr/include $(CFLAGS)
 CFG_GCCISH_LINK_FLAGS_x86_64-unknown-bitrig := -shared -pic -pthread -m64 $(LDFLAGS)
 CFG_GCCISH_DEF_FLAG_x86_64-unknown-bitrig := -Wl,--export-dynamic,--dynamic-list=
 CFG_LLC_FLAGS_x86_64-unknown-bitrig :=
index 4015293826e1a884e2a2c9975908ec09e17ef6eb..579a9a809e205604011e59c73deb368f3eb248ec 100644 (file)
@@ -8,7 +8,7 @@ CFG_STATIC_LIB_NAME_x86_64-unknown-dragonfly=lib$(1).a
 CFG_LIB_GLOB_x86_64-unknown-dragonfly=lib$(1)-*.so
 CFG_LIB_DSYM_GLOB_x86_64-unknown-dragonfly=$(1)-*.dylib.dSYM
 CFG_JEMALLOC_CFLAGS_x86_64-unknown-dragonfly := -m64 -I/usr/include -I/usr/local/include $(CFLAGS)
-CFG_GCCISH_CFLAGS_x86_64-unknown-dragonfly := -Wall -Werror -g -fPIC -m64 -I/usr/include -I/usr/local/include $(CFLAGS)
+CFG_GCCISH_CFLAGS_x86_64-unknown-dragonfly :=  -g -fPIC -m64 -I/usr/include -I/usr/local/include $(CFLAGS)
 CFG_GCCISH_LINK_FLAGS_x86_64-unknown-dragonfly := -shared -fPIC -g -pthread  -lrt -m64
 CFG_GCCISH_DEF_FLAG_x86_64-unknown-dragonfly := -Wl,--export-dynamic,--dynamic-list=
 CFG_LLC_FLAGS_x86_64-unknown-dragonfly :=
index 1bd43168b4f692cf7283560803446569a275ac95..c700601eac7a18a1427d48fcc866e37d5b40ad2b 100644 (file)
@@ -8,7 +8,7 @@ CFG_STATIC_LIB_NAME_x86_64-unknown-freebsd=lib$(1).a
 CFG_LIB_GLOB_x86_64-unknown-freebsd=lib$(1)-*.so
 CFG_LIB_DSYM_GLOB_x86_64-unknown-freebsd=$(1)-*.dylib.dSYM
 CFG_JEMALLOC_CFLAGS_x86_64-unknown-freebsd := -I/usr/local/include $(CFLAGS)
-CFG_GCCISH_CFLAGS_x86_64-unknown-freebsd := -Wall -Werror -g -fPIC -I/usr/local/include $(CFLAGS)
+CFG_GCCISH_CFLAGS_x86_64-unknown-freebsd :=  -g -fPIC -I/usr/local/include $(CFLAGS)
 CFG_GCCISH_LINK_FLAGS_x86_64-unknown-freebsd := -shared -fPIC -g -pthread  -lrt
 CFG_GCCISH_DEF_FLAG_x86_64-unknown-freebsd := -Wl,--export-dynamic,--dynamic-list=
 CFG_LLC_FLAGS_x86_64-unknown-freebsd :=
index 044c687c9fc4c871cb3510dfbf8f7b3e3121caf4..817ce22e4f59d10fdf099113ca8a6ea447210dac 100644 (file)
@@ -8,7 +8,7 @@ CFG_STATIC_LIB_NAME_x86_64-unknown-linux-gnu=lib$(1).a
 CFG_LIB_GLOB_x86_64-unknown-linux-gnu=lib$(1)-*.so
 CFG_LIB_DSYM_GLOB_x86_64-unknown-linux-gnu=lib$(1)-*.dylib.dSYM
 CFG_JEMALLOC_CFLAGS_x86_64-unknown-linux-gnu := -m64
-CFG_GCCISH_CFLAGS_x86_64-unknown-linux-gnu := -Wall -Werror -g -fPIC -m64
+CFG_GCCISH_CFLAGS_x86_64-unknown-linux-gnu :=  -g -fPIC -m64
 CFG_GCCISH_CXXFLAGS_x86_64-unknown-linux-gnu := -fno-rtti
 CFG_GCCISH_LINK_FLAGS_x86_64-unknown-linux-gnu := -shared -fPIC -ldl -pthread  -lrt -g -m64
 CFG_GCCISH_DEF_FLAG_x86_64-unknown-linux-gnu := -Wl,--export-dynamic,--dynamic-list=
index dfe9de18f57878b4db44b7be3e87b75c083b757f..3a03b2accd541449456dcadc2d86b4d11d363cee 100644 (file)
@@ -8,7 +8,7 @@ CFG_LIB_NAME_x86_64-unknown-linux-musl=lib$(1).so
 CFG_STATIC_LIB_NAME_x86_64-unknown-linux-musl=lib$(1).a
 CFG_LIB_GLOB_x86_64-unknown-linux-musl=lib$(1)-*.so
 CFG_JEMALLOC_CFLAGS_x86_64-unknown-linux-musl := -m64
-CFG_GCCISH_CFLAGS_x86_64-unknown-linux-musl := -Wall -Werror -g -fPIC -m64
+CFG_GCCISH_CFLAGS_x86_64-unknown-linux-musl :=  -g -fPIC -m64
 CFG_GCCISH_CXXFLAGS_x86_64-unknown-linux-musl :=
 CFG_GCCISH_LINK_FLAGS_x86_64-unknown-linux-musl :=
 CFG_GCCISH_DEF_FLAG_x86_64-unknown-linux-musl :=
index a77c5fa542eb187535d205e2132082ccbcb46e66..93bb2d672653e8f46b68cf5efb8dc1059fe04abf 100644 (file)
@@ -9,7 +9,7 @@ CFG_STATIC_LIB_NAME_x86_64-unknown-netbsd=lib$(1).a
 CFG_LIB_GLOB_x86_64-unknown-netbsd=lib$(1)-*.so
 CFG_LIB_DSYM_GLOB_x86_64-unknown-netbsd=$(1)-*.dylib.dSYM
 CFG_JEMALLOC_CFLAGS_x86_64-unknown-netbsd := -I/usr/local/include $(CFLAGS)
-CFG_GCCISH_CFLAGS_x86_64-unknown-netbsd := -Wall -Werror -g -fPIC -I/usr/local/include $(CFLAGS)
+CFG_GCCISH_CFLAGS_x86_64-unknown-netbsd :=  -g -fPIC -I/usr/local/include $(CFLAGS)
 CFG_GCCISH_LINK_FLAGS_x86_64-unknown-netbsd := -shared -fPIC -g -pthread  -lrt
 CFG_GCCISH_DEF_FLAG_x86_64-unknown-netbsd := -Wl,--export-dynamic,--dynamic-list=
 CFG_LLC_FLAGS_x86_64-unknown-netbsd :=
index f1e45d76409927fc850f5d61b4028d079920ee51..7cca1f7b18b3d6cdd5ffc65d6cbced0897f0ed6f 100644 (file)
@@ -8,7 +8,7 @@ CFG_STATIC_LIB_NAME_x86_64-unknown-openbsd=lib$(1).a
 CFG_LIB_GLOB_x86_64-unknown-openbsd=lib$(1)-*.so
 CFG_LIB_DSYM_GLOB_x86_64-unknown-openbsd=$(1)-*.dylib.dSYM
 CFG_JEMALLOC_CFLAGS_x86_64-unknown-openbsd := -m64 -I/usr/include $(CFLAGS)
-CFG_GCCISH_CFLAGS_x86_64-unknown-openbsd := -Wall -Werror -g -fPIC -m64 -I/usr/include $(CFLAGS)
+CFG_GCCISH_CFLAGS_x86_64-unknown-openbsd :=  -g -fPIC -m64 -I/usr/include $(CFLAGS)
 CFG_GCCISH_LINK_FLAGS_x86_64-unknown-openbsd := -shared -fPIC -g -pthread -m64
 CFG_GCCISH_DEF_FLAG_x86_64-unknown-openbsd := -Wl,--export-dynamic,--dynamic-list=
 CFG_LLC_FLAGS_x86_64-unknown-openbsd :=
index 8113b68380744dcc837ad9ae920c434840a98c1c..067721fab4fa8353101c7f42aeafad01e8475197 100644 (file)
--- a/mk/rt.mk
+++ b/mk/rt.mk
@@ -223,147 +223,373 @@ endif
 # compiler-rt
 ################################################################################
 
-ifdef CFG_ENABLE_FAST_MAKE
-COMPRT_DEPS := $(S)/.gitmodules
-else
-COMPRT_DEPS := $(wildcard \
-              $(S)src/compiler-rt/* \
-              $(S)src/compiler-rt/*/* \
-              $(S)src/compiler-rt/*/*/* \
-              $(S)src/compiler-rt/*/*/*/*)
-endif
-
-# compiler-rt's build system is a godawful mess. Here we figure out
-# the ridiculous platform-specific values and paths necessary to get
-# useful artifacts out of it.
+# Everything below is a manual compilation of compiler-rt, disregarding its
+# build system. See comments in `src/bootstrap/native.rs` for more information.
 
 COMPRT_NAME_$(1) := $$(call CFG_STATIC_LIB_NAME_$(1),compiler-rt)
 COMPRT_LIB_$(1) := $$(RT_OUTPUT_DIR_$(1))/$$(COMPRT_NAME_$(1))
 COMPRT_BUILD_DIR_$(1) := $$(RT_OUTPUT_DIR_$(1))/compiler-rt
 
-COMPRT_ARCH_$(1) := $$(word 1,$$(subst -, ,$(1)))
+# GENERIC_SOURCES in CMakeLists.txt
+COMPRT_OBJS_$(1) := \
+  absvdi2.o \
+  absvsi2.o \
+  adddf3.o \
+  addsf3.o \
+  addvdi3.o \
+  addvsi3.o \
+  apple_versioning.o \
+  ashldi3.o \
+  ashrdi3.o \
+  clear_cache.o \
+  clzdi2.o \
+  clzsi2.o \
+  cmpdi2.o \
+  comparedf2.o \
+  comparesf2.o \
+  ctzdi2.o \
+  ctzsi2.o \
+  divdc3.o \
+  divdf3.o \
+  divdi3.o \
+  divmoddi4.o \
+  divmodsi4.o \
+  divsc3.o \
+  divsf3.o \
+  divsi3.o \
+  divxc3.o \
+  extendsfdf2.o \
+  extendhfsf2.o \
+  ffsdi2.o \
+  fixdfdi.o \
+  fixdfsi.o \
+  fixsfdi.o \
+  fixsfsi.o \
+  fixunsdfdi.o \
+  fixunsdfsi.o \
+  fixunssfdi.o \
+  fixunssfsi.o \
+  fixunsxfdi.o \
+  fixunsxfsi.o \
+  fixxfdi.o \
+  floatdidf.o \
+  floatdisf.o \
+  floatdixf.o \
+  floatsidf.o \
+  floatsisf.o \
+  floatundidf.o \
+  floatundisf.o \
+  floatundixf.o \
+  floatunsidf.o \
+  floatunsisf.o \
+  int_util.o \
+  lshrdi3.o \
+  moddi3.o \
+  modsi3.o \
+  muldc3.o \
+  muldf3.o \
+  muldi3.o \
+  mulodi4.o \
+  mulosi4.o \
+  muloti4.o \
+  mulsc3.o \
+  mulsf3.o \
+  mulvdi3.o \
+  mulvsi3.o \
+  mulxc3.o \
+  negdf2.o \
+  negdi2.o \
+  negsf2.o \
+  negvdi2.o \
+  negvsi2.o \
+  paritydi2.o \
+  paritysi2.o \
+  popcountdi2.o \
+  popcountsi2.o \
+  powidf2.o \
+  powisf2.o \
+  powixf2.o \
+  subdf3.o \
+  subsf3.o \
+  subvdi3.o \
+  subvsi3.o \
+  truncdfhf2.o \
+  truncdfsf2.o \
+  truncsfhf2.o \
+  ucmpdi2.o \
+  udivdi3.o \
+  udivmoddi4.o \
+  udivmodsi4.o \
+  udivsi3.o \
+  umoddi3.o \
+  umodsi3.o
 
-# All this is to figure out the path to the compiler-rt bin
-ifeq ($$(findstring windows-msvc,$(1)),windows-msvc)
-COMPRT_DIR_$(1) := windows/Release
-COMPRT_LIB_NAME_$(1) := clang_rt.builtins-$$(patsubst i%86,i386,$$(COMPRT_ARCH_$(1)))
+ifeq ($$(findstring ios,$(1)),)
+COMPRT_OBJS_$(1) += \
+  absvti2.o \
+  addtf3.o \
+  addvti3.o \
+  ashlti3.o \
+  ashrti3.o \
+  clzti2.o \
+  cmpti2.o \
+  ctzti2.o \
+  divtf3.o \
+  divti3.o \
+  ffsti2.o \
+  fixdfti.o \
+  fixsfti.o \
+  fixunsdfti.o \
+  fixunssfti.o \
+  fixunsxfti.o \
+  fixxfti.o \
+  floattidf.o \
+  floattisf.o \
+  floattixf.o \
+  floatuntidf.o \
+  floatuntisf.o \
+  floatuntixf.o \
+  lshrti3.o \
+  modti3.o \
+  multf3.o \
+  multi3.o \
+  mulvti3.o \
+  negti2.o \
+  negvti2.o \
+  parityti2.o \
+  popcountti2.o \
+  powitf2.o \
+  subtf3.o \
+  subvti3.o \
+  trampoline_setup.o \
+  ucmpti2.o \
+  udivmodti4.o \
+  udivti3.o \
+  umodti3.o
 endif
 
-ifeq ($$(findstring windows-gnu,$(1)),windows-gnu)
-COMPRT_DIR_$(1) := windows
-COMPRT_LIB_NAME_$(1) := clang_rt.builtins-$$(COMPRT_ARCH_$(1))
+ifeq ($$(findstring apple,$(1)),apple)
+COMPRT_OBJS_$(1) +=  \
+           atomic_flag_clear.o \
+           atomic_flag_clear_explicit.o \
+           atomic_flag_test_and_set.o \
+           atomic_flag_test_and_set_explicit.o \
+           atomic_signal_fence.o \
+           atomic_thread_fence.o
 endif
 
-ifeq ($$(findstring darwin,$(1)),darwin)
-COMPRT_DIR_$(1) := builtins
-COMPRT_LIB_NAME_$(1) := clang_rt.builtins_$$(patsubst i686,i386,$$(COMPRT_ARCH_$(1)))_osx
+
+ifeq ($$(findstring windows,$(1)),)
+COMPRT_OBJS_$(1) += emutls.o
 endif
 
-ifeq ($$(findstring ios,$(1)),ios)
-COMPRT_DIR_$(1) := builtins
-COMPRT_ARCH_$(1) := $$(patsubst armv7s,armv7em,$$(COMPRT_ARCH_$(1)))
-COMPRT_LIB_NAME_$(1) := clang_rt.hard_pic_$$(COMPRT_ARCH_$(1))_macho_embedded
-ifeq ($$(COMPRT_ARCH_$(1)),aarch64)
-COMPRT_LIB_NAME_$(1) := clang_rt.builtins_arm64_ios
+ifeq ($$(findstring msvc,$(1)),)
+COMPRT_OBJS_$(1) += gcc_personality_v0.o
+COMPRT_OBJS_$(1) += emutls.o
+
+ifeq ($$(findstring x86_64,$(1)),x86_64)
+COMPRT_OBJS_$(1) += \
+      x86_64/chkstk.o \
+      x86_64/chkstk2.o \
+      x86_64/floatdidf.o \
+      x86_64/floatdisf.o \
+      x86_64/floatdixf.o \
+      x86_64/floatundidf.o \
+      x86_64/floatundisf.o \
+      x86_64/floatundixf.o
 endif
-COMPRT_DEFINES_$(1) := -DCOMPILER_RT_ENABLE_IOS=ON
+
+ifeq ($$(findstring i686,$$(patsubts i%86,i686,$(1))),i686)
+COMPRT_OBJS_$(1) += \
+      i386/ashldi3.o \
+      i386/ashrdi3.o \
+      i386/chkstk.o \
+      i386/chkstk2.o \
+      i386/divdi3.o \
+      i386/floatdidf.o \
+      i386/floatdisf.o \
+      i386/floatdixf.o \
+      i386/floatundidf.o \
+      i386/floatundisf.o \
+      i386/floatundixf.o \
+      i386/lshrdi3.o \
+      i386/moddi3.o \
+      i386/muldi3.o \
+      i386/udivdi3.o \
+      i386/umoddi3.o
 endif
 
-ifndef COMPRT_DIR_$(1)
-# NB: FreeBSD and NetBSD output to "linux"...
-COMPRT_DIR_$(1) := linux
-COMPRT_ARCH_$(1) := $$(patsubst i586,i386,$$(COMPRT_ARCH_$(1)))
+else
 
-ifeq ($$(findstring android,$(1)),android)
-ifeq ($$(findstring arm,$$(COMPRT_ARCH_$(1))),arm)
-COMPRT_ARCH_$(1) := armhf
-endif
+ifeq ($$(findstring x86_64,$(1)),x86_64)
+COMPRT_OBJS_$(1) += \
+      x86_64/floatdidf.o \
+      x86_64/floatdisf.o \
+      x86_64/floatdixf.o
 endif
 
-ifeq ($$(findstring eabihf,$(1)),eabihf)
-ifeq ($$(findstring armv7,$(1)),)
-COMPRT_LIB_NAME_$(1) := clang_rt.builtins-armhf
-endif
 endif
 
-ifndef COMPRT_LIB_NAME_$(1)
-COMPRT_LIB_NAME_$(1) := clang_rt.builtins-$$(COMPRT_ARCH_$(1))
+# Generic ARM sources, nothing compiles on iOS though
+ifeq ($$(findstring arm,$(1)),arm)
+ifeq ($$(findstring ios,$(1)),)
+COMPRT_OBJS_$(1) += \
+  arm/aeabi_cdcmp.o \
+  arm/aeabi_cdcmpeq_check_nan.o \
+  arm/aeabi_cfcmp.o \
+  arm/aeabi_cfcmpeq_check_nan.o \
+  arm/aeabi_dcmp.o \
+  arm/aeabi_div0.o \
+  arm/aeabi_drsub.o \
+  arm/aeabi_fcmp.o \
+  arm/aeabi_frsub.o \
+  arm/aeabi_idivmod.o \
+  arm/aeabi_ldivmod.o \
+  arm/aeabi_memcmp.o \
+  arm/aeabi_memcpy.o \
+  arm/aeabi_memmove.o \
+  arm/aeabi_memset.o \
+  arm/aeabi_uidivmod.o \
+  arm/aeabi_uldivmod.o \
+  arm/bswapdi2.o \
+  arm/bswapsi2.o \
+  arm/clzdi2.o \
+  arm/clzsi2.o \
+  arm/comparesf2.o \
+  arm/divmodsi4.o \
+  arm/divsi3.o \
+  arm/modsi3.o \
+  arm/switch16.o \
+  arm/switch32.o \
+  arm/switch8.o \
+  arm/switchu8.o \
+  arm/sync_synchronize.o \
+  arm/udivmodsi4.o \
+  arm/udivsi3.o \
+  arm/umodsi3.o
 endif
 endif
 
-
-ifeq ($$(findstring windows-gnu,$(1)),windows-gnu)
-COMPRT_LIB_FILE_$(1) := lib$$(COMPRT_LIB_NAME_$(1)).a
+# Thumb sources
+ifeq ($$(findstring armv7,$(1)),armv7)
+COMPRT_OBJS_$(1) += \
+  arm/sync_fetch_and_add_4.o \
+  arm/sync_fetch_and_add_8.o \
+  arm/sync_fetch_and_and_4.o \
+  arm/sync_fetch_and_and_8.o \
+  arm/sync_fetch_and_max_4.o \
+  arm/sync_fetch_and_max_8.o \
+  arm/sync_fetch_and_min_4.o \
+  arm/sync_fetch_and_min_8.o \
+  arm/sync_fetch_and_nand_4.o \
+  arm/sync_fetch_and_nand_8.o \
+  arm/sync_fetch_and_or_4.o \
+  arm/sync_fetch_and_or_8.o \
+  arm/sync_fetch_and_sub_4.o \
+  arm/sync_fetch_and_sub_8.o \
+  arm/sync_fetch_and_umax_4.o \
+  arm/sync_fetch_and_umax_8.o \
+  arm/sync_fetch_and_umin_4.o \
+  arm/sync_fetch_and_umin_8.o \
+  arm/sync_fetch_and_xor_4.o \
+  arm/sync_fetch_and_xor_8.o
 endif
 
-ifeq ($$(findstring android,$(1)),android)
-ifeq ($$(findstring arm,$(1)),arm)
-COMPRT_LIB_FILE_$(1) := $$(call CFG_STATIC_LIB_NAME_$(1),$$(COMPRT_LIB_NAME_$(1))-android)
-endif
+# VFP sources
+ifeq ($$(findstring eabihf,$(1)),eabihf)
+COMPRT_OBJS_$(1) += \
+  arm/adddf3vfp.o \
+  arm/addsf3vfp.o \
+  arm/divdf3vfp.o \
+  arm/divsf3vfp.o \
+  arm/eqdf2vfp.o \
+  arm/eqsf2vfp.o \
+  arm/extendsfdf2vfp.o \
+  arm/fixdfsivfp.o \
+  arm/fixsfsivfp.o \
+  arm/fixunsdfsivfp.o \
+  arm/fixunssfsivfp.o \
+  arm/floatsidfvfp.o \
+  arm/floatsisfvfp.o \
+  arm/floatunssidfvfp.o \
+  arm/floatunssisfvfp.o \
+  arm/gedf2vfp.o \
+  arm/gesf2vfp.o \
+  arm/gtdf2vfp.o \
+  arm/gtsf2vfp.o \
+  arm/ledf2vfp.o \
+  arm/lesf2vfp.o \
+  arm/ltdf2vfp.o \
+  arm/ltsf2vfp.o \
+  arm/muldf3vfp.o \
+  arm/mulsf3vfp.o \
+  arm/negdf2vfp.o \
+  arm/negsf2vfp.o \
+  arm/nedf2vfp.o \
+  arm/nesf2vfp.o \
+  arm/restore_vfp_d8_d15_regs.o \
+  arm/save_vfp_d8_d15_regs.o \
+  arm/subdf3vfp.o \
+  arm/subsf3vfp.o \
+  arm/truncdfsf2vfp.o \
+  arm/unorddf2vfp.o \
+  arm/unordsf2vfp.o
 endif
 
-ifndef COMPRT_LIB_FILE_$(1)
-COMPRT_LIB_FILE_$(1) := $$(call CFG_STATIC_LIB_NAME_$(1),$$(COMPRT_LIB_NAME_$(1)))
+ifeq ($$(findstring aarch64,$(1)),aarch64)
+COMPRT_OBJS_$(1) += \
+  comparetf2.o \
+  extenddftf2.o \
+  extendsftf2.o \
+  fixtfdi.o \
+  fixtfsi.o \
+  fixtfti.o \
+  fixunstfdi.o \
+  fixunstfsi.o \
+  fixunstfti.o \
+  floatditf.o \
+  floatsitf.o \
+  floatunditf.o \
+  floatunsitf.o \
+  multc3.o \
+  trunctfdf2.o \
+  trunctfsf2.o
 endif
 
-COMPRT_OUTPUT_$(1) := $$(COMPRT_BUILD_DIR_$(1))/lib/$$(COMPRT_DIR_$(1))/$$(COMPRT_LIB_FILE_$(1))
-
-ifeq ($$(findstring windows-msvc,$(1)),windows-msvc)
-COMPRT_BUILD_ARGS_$(1) := //v:m //nologo
-COMPRT_BUILD_TARGET_$(1) := lib/builtins/builtins
-COMPRT_BUILD_CC_$(1) :=
+ifeq ($$(findstring msvc,$(1)),msvc)
+$$(COMPRT_BUILD_DIR_$(1))/%.o: CFLAGS += -Zl -D__func__=__FUNCTION__
 else
-COMPRT_BUILD_ARGS_$(1) :=
-ifndef COMPRT_BUILD_TARGET_$(1)
-COMPRT_BUILD_TARGET_$(1) := $$(COMPRT_LIB_NAME_$(1))
+$$(COMPRT_BUILD_DIR_$(1))/%.o: CFLAGS += -fno-builtin -fvisibility=hidden \
+       -fomit-frame-pointer -ffreestanding
 endif
-COMPRT_BUILD_CC_$(1) := -DCMAKE_C_COMPILER=$$(call FIND_COMPILER,$$(CC_$(1))) \
-                       -DCMAKE_CXX_COMPILER=$$(call FIND_COMPILER,$$(CXX_$(1)))
 
-ifeq ($$(findstring ios,$(1)),)
-COMPRT_BUILD_CC_$(1) := $$(COMPRT_BUILD_CC_$(1)) \
-                       -DCMAKE_C_FLAGS="$$(CFG_GCCISH_CFLAGS_$(1)) -Wno-error"
-endif
+COMPRT_OBJS_$(1) := $$(COMPRT_OBJS_$(1):%=$$(COMPRT_BUILD_DIR_$(1))/%)
+
+$$(COMPRT_BUILD_DIR_$(1))/%.o: $(S)src/compiler-rt/lib/builtins/%.c
+       @mkdir -p $$(@D)
+       @$$(call E, compile: $$@)
+       $$(Q)$$(call CFG_COMPILE_C_$(1),$$@,$$<)
+
+$$(COMPRT_BUILD_DIR_$(1))/%.o: $(S)src/compiler-rt/lib/builtins/%.S \
+           $$(LLVM_CONFIG_$$(CFG_BUILD))
+       @mkdir -p $$(@D)
+       @$$(call E, compile: $$@)
+       $$(Q)$$(call CFG_ASSEMBLE_$(1),$$@,$$<)
 
+ifeq ($$(findstring msvc,$(1)),msvc)
+$$(COMPRT_BUILD_DIR_$(1))/%.o: \
+       export INCLUDE := $$(CFG_MSVC_INCLUDE_PATH_$$(HOST_$(1)))
 endif
 
 ifeq ($$(findstring emscripten,$(1)),emscripten)
-
 # FIXME: emscripten doesn't use compiler-rt and can't build it without
 # further hacks
-$$(COMPRT_LIB_$(1)):
-       touch $$@
-
-else
-
-$$(COMPRT_LIB_$(1)): $$(COMPRT_DEPS) $$(MKFILE_DEPS) $$(LLVM_CONFIG_$$(CFG_BUILD))
-       @$$(call E, cmake: compiler-rt)
-       $$(Q)rm -rf $$(COMPRT_BUILD_DIR_$(1))
-       $$(Q)mkdir $$(COMPRT_BUILD_DIR_$(1))
-       $$(Q)cd "$$(COMPRT_BUILD_DIR_$(1))"; \
-               $$(CFG_CMAKE) "$(S)src/compiler-rt" \
-               -DCMAKE_BUILD_TYPE=$$(LLVM_BUILD_CONFIG_MODE) \
-               -DLLVM_CONFIG_PATH=$$(LLVM_CONFIG_$$(CFG_BUILD)) \
-               -DCOMPILER_RT_DEFAULT_TARGET_TRIPLE=$(1) \
-               -DCOMPILER_RT_BUILD_SANITIZERS=OFF \
-               -DCOMPILER_RT_BUILD_EMUTLS=OFF \
-               $$(COMPRT_DEFINES_$(1)) \
-               $$(COMPRT_BUILD_CC_$(1)) \
-               -G"$$(CFG_CMAKE_GENERATOR)"
-ifneq ($$(CFG_NINJA),)
-       $$(CFG_CMAKE) --build "$$(COMPRT_BUILD_DIR_$(1))" \
-               --target $$(COMPRT_BUILD_TARGET_$(1)) \
-               --config $$(LLVM_BUILD_CONFIG_MODE) \
-               -- $$(COMPRT_BUILD_ARGS_$(1))
-else
-       $$(Q)$$(CFG_CMAKE) --build "$$(COMPRT_BUILD_DIR_$(1))" \
-               --target $$(COMPRT_BUILD_TARGET_$(1)) \
-               --config $$(LLVM_BUILD_CONFIG_MODE) \
-               -- $$(COMPRT_BUILD_ARGS_$(1)) $$(MFLAGS)
+COMPRT_OBJS_$(1) :=
 endif
-       $$(Q)cp "$$(COMPRT_OUTPUT_$(1))" $$@
 
-endif
+$$(COMPRT_LIB_$(1)): $$(COMPRT_OBJS_$(1))
+       @$$(call E, link: $$@)
+       $$(Q)$$(call CFG_CREATE_ARCHIVE_$(1),$$@) $$^
 
 ################################################################################
 # libbacktrace
index ed443147d466e3734bf5a209ff23aed0a7e166f8..201e4cae51d6d9a4e293d2eedfa276f477991cd3 100644 (file)
@@ -277,7 +277,8 @@ check-stage$(1)-T-$(2)-H-$(3)-exec: \
        check-stage$(1)-T-$(2)-H-$(3)-ui-exec \
        check-stage$(1)-T-$(2)-H-$(3)-doc-exec \
        check-stage$(1)-T-$(2)-H-$(3)-doc-error-index-exec \
-       check-stage$(1)-T-$(2)-H-$(3)-pretty-exec
+       check-stage$(1)-T-$(2)-H-$(3)-pretty-exec \
+       check-stage$(1)-T-$(2)-H-$(3)-mir-opt-exec
 
 ifndef CFG_DISABLE_CODEGEN_TESTS
 check-stage$(1)-T-$(2)-H-$(3)-exec: \
@@ -458,6 +459,7 @@ UI_RS := $(call rwildcard,$(S)src/test/ui/,*.rs) \
          $(call rwildcard,$(S)src/test/ui/,*.stdout) \
          $(call rwildcard,$(S)src/test/ui/,*.stderr)
 RUSTDOCCK_RS := $(call rwildcard,$(S)src/test/rustdoc/,*.rs)
+MIR_OPT_RS := $(call rwildcard,$(S)src/test/mir-opt/,*.rs)
 
 RPASS_TESTS := $(RPASS_RS)
 RPASS_VALGRIND_TESTS := $(RPASS_VALGRIND_RS)
@@ -475,6 +477,7 @@ CODEGEN_UNITS_TESTS := $(CODEGEN_UNITS_RS)
 INCREMENTAL_TESTS := $(INCREMENTAL_RS)
 RMAKE_TESTS := $(RMAKE_RS)
 UI_TESTS := $(UI_RS)
+MIR_OPT_TESTS := $(MIR_OPT_RS)
 RUSTDOCCK_TESTS := $(RUSTDOCCK_RS)
 
 CTEST_SRC_BASE_rpass = run-pass
@@ -552,6 +555,11 @@ CTEST_BUILD_BASE_ui = ui
 CTEST_MODE_ui = ui
 CTEST_RUNTOOL_ui = $(CTEST_RUNTOOL)
 
+CTEST_SRC_BASE_mir-opt = mir-opt
+CTEST_BUILD_BASE_mir-opt = mir-opt
+CTEST_MODE_mir-opt = mir-opt
+CTEST_RUNTOOL_mir-opt = $(CTEST_RUNTOOL)
+
 CTEST_SRC_BASE_rustdocck = rustdoc
 CTEST_BUILD_BASE_rustdocck = rustdoc
 CTEST_MODE_rustdocck = rustdoc
@@ -684,6 +692,7 @@ CTEST_DEPS_incremental_$(1)-T-$(2)-H-$(3) = $$(INCREMENTAL_TESTS)
 CTEST_DEPS_rmake_$(1)-T-$(2)-H-$(3) = $$(RMAKE_TESTS) \
        $$(CSREQ$(1)_T_$(3)_H_$(3)) $$(SREQ$(1)_T_$(2)_H_$(3))
 CTEST_DEPS_ui_$(1)-T-$(2)-H-$(3) = $$(UI_TESTS)
+CTEST_DEPS_mir-opt_$(1)-T-$(2)-H-$(3) = $$(MIR_OPT_TESTS)
 CTEST_DEPS_rustdocck_$(1)-T-$(2)-H-$(3) = $$(RUSTDOCCK_TESTS) \
                $$(HBIN$(1)_H_$(3))/rustdoc$$(X_$(3)) \
                $(S)src/etc/htmldocck.py
@@ -755,7 +764,7 @@ endef
 
 CTEST_NAMES = rpass rpass-valgrind rpass-full rfail-full cfail-full rfail cfail pfail \
        debuginfo-gdb debuginfo-lldb codegen codegen-units rustdocck incremental \
-       rmake ui
+       rmake ui mir-opt
 
 $(foreach host,$(CFG_HOST), \
  $(eval $(foreach target,$(CFG_TARGET), \
@@ -964,6 +973,7 @@ TEST_GROUPS = \
        pretty-rfail-full \
        pretty-rfail \
        pretty-pretty \
+       mir-opt \
        $(NULL)
 
 define DEF_CHECK_FOR_STAGE_AND_TARGET_AND_HOST
index 39c7a37501121bb2cce0feef57426b70a9b7a0cd..1290f2a404b22cff42df43f162c667a5ac456cd3 100644 (file)
@@ -5,7 +5,7 @@ dependencies = [
  "build_helper 0.1.0",
  "cmake 0.1.17 (registry+https://github.com/rust-lang/crates.io-index)",
  "filetime 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
- "gcc 0.3.26 (registry+https://github.com/rust-lang/crates.io-index)",
+ "gcc 0.3.31 (git+https://github.com/alexcrichton/gcc-rs)",
  "getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
  "kernel32-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "libc 0.2.9 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -25,7 +25,7 @@ name = "cmake"
 version = "0.1.17"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "gcc 0.3.26 (registry+https://github.com/rust-lang/crates.io-index)",
+ "gcc 0.3.31 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
@@ -38,7 +38,12 @@ dependencies = [
 
 [[package]]
 name = "gcc"
-version = "0.3.26"
+version = "0.3.31"
+source = "git+https://github.com/alexcrichton/gcc-rs#b8e2400883f1a2749b323354dad372cdd1c838c7"
+
+[[package]]
+name = "gcc"
+version = "0.3.31"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
 [[package]]
index cde4a825be1fb81259d354b3cd266bfc47ab84d9..02746034cca695460fac0eccda1fbdf395f59a75 100644 (file)
@@ -29,6 +29,6 @@ getopts = "0.2"
 rustc-serialize = "0.3"
 winapi = "0.2"
 kernel32-sys = "0.2"
-gcc = "0.3.17"
+gcc = { git = "https://github.com/alexcrichton/gcc-rs" }
 libc = "0.2"
 md5 = "0.1"
index caa6ea17ea0544d6f6a5c263239e4548ad469db4..367322e8816465d6f298c1e4a8fec8edcb7fd035 100644 (file)
@@ -388,6 +388,10 @@ pub fn build(&mut self) {
                     check::compiletest(self, &compiler, target.target,
                                        "pretty", "run-pass-valgrind");
                 }
+                CheckMirOpt { compiler } => {
+                    check::compiletest(self, &compiler, target.target,
+                                       "mir-opt", "mir-opt");
+                }
                 CheckCodegen { compiler } => {
                     check::compiletest(self, &compiler, target.target,
                                        "codegen", "codegen");
index 83e9393fbaef7c7f73dfdc7351164703026f41fa..05ecbc0cadaa9ab25113e8ce3bca2ca33e98696f 100644 (file)
@@ -133,86 +133,395 @@ fn check_llvm_version(build: &Build, llvm_config: &Path) {
 
 /// Compiles the `compiler-rt` library, or at least the builtins part of it.
 ///
-/// This uses the CMake build system and an existing LLVM build directory to
-/// compile the project.
+/// Note that while compiler-rt has a build system associated with it, we
+/// specifically don't use it here. The compiler-rt build system, written in
+/// CMake, is actually *very* difficult to work with in terms of getting it to
+/// compile on all the relevant platforms we want it to compile on. In the end
+/// it became so much pain to work with local patches, work around the oddities
+/// of the build system, etc, that we're just building everything by hand now.
+///
+/// In general compiler-rt is just a bunch of intrinsics that are in practice
+/// *very* stable. We just need to make sure that all the relevant functions and
+/// such are compiled somewhere and placed in an object file somewhere.
+/// Eventually, these should all be written in Rust!
+///
+/// So below you'll find a listing of every single file in the compiler-rt repo
+/// that we're compiling. We just reach in and compile with the `gcc` crate
+/// which should have all the relevant flags and such already configured.
+///
+/// The risk here is that if we update compiler-rt we may need to compile some
+/// new intrinsics, but to be honest we surely don't use all of the intrinsics
+/// listed below today so the likelihood of us actually needing a new intrinsic
+/// is quite low. The failure case is also just that someone reports a link
+/// error (if any) and then we just add it to the list. Overall, that cost is
+/// far far less than working with compiler-rt's build system over time.
 pub fn compiler_rt(build: &Build, target: &str) {
-    let dst = build.compiler_rt_out(target);
-    let arch = target.split('-').next().unwrap();
-    let mode = if build.config.rust_optimize {"Release"} else {"Debug"};
+    let build_dir = build.compiler_rt_out(target);
+    let output = build_dir.join(staticlib("compiler-rt", target));
+    build.compiler_rt_built.borrow_mut().insert(target.to_string(),
+                                                output.clone());
+    t!(fs::create_dir_all(&build_dir));
 
-    let build_llvm_config = build.llvm_config(&build.config.build);
-    let mut cfg = cmake::Config::new(build.src.join("src/compiler-rt"));
-    cfg.target(target)
+    let mut cfg = gcc::Config::new();
+    cfg.cargo_metadata(false)
+       .out_dir(&build_dir)
+       .target(target)
        .host(&build.config.build)
-       .out_dir(&dst)
-       .profile(mode)
-       .define("LLVM_CONFIG_PATH", build_llvm_config)
-       .define("COMPILER_RT_DEFAULT_TARGET_TRIPLE", target)
-       .define("COMPILER_RT_BUILD_SANITIZERS", "OFF")
-       .define("COMPILER_RT_BUILD_EMUTLS", "OFF")
-       // inform about c/c++ compilers, the c++ compiler isn't actually used but
-       // it's needed to get the initial configure to work on all platforms.
-       .define("CMAKE_C_COMPILER", build.cc(target))
-       .define("CMAKE_CXX_COMPILER", build.cc(target));
-
-    let (dir, build_target, libname) = if target.contains("linux") ||
-                                          target.contains("freebsd") ||
-                                          target.contains("netbsd") {
-        let os_extra = if target.contains("android") && target.contains("arm") {
-            "-android"
-        } else {
-            ""
-        };
-        let builtins_arch = match arch {
-            "i586" => "i386",
-            "arm" | "armv7" if target.contains("android") => "armhf",
-            "arm" if target.contains("eabihf") => "armhf",
-            _ => arch,
-        };
-        let target = format!("clang_rt.builtins-{}", builtins_arch);
-        ("linux".to_string(),
-         target.clone(),
-         format!("{}{}", target, os_extra))
-    } else if target.contains("apple-darwin") {
-        let builtins_arch = match arch {
-            "i686" => "i386",
-            _ => arch,
-        };
-        let target = format!("clang_rt.builtins_{}_osx", builtins_arch);
-        ("builtins".to_string(), target.clone(), target)
-    } else if target.contains("apple-ios") {
-        cfg.define("COMPILER_RT_ENABLE_IOS", "ON");
-        let target = match arch {
-            "armv7s" => "hard_pic_armv7em_macho_embedded".to_string(),
-            "aarch64" => "builtins_arm64_ios".to_string(),
-            _ => format!("hard_pic_{}_macho_embedded", arch),
-        };
-        ("builtins".to_string(), target.clone(), target)
-    } else if target.contains("windows-gnu") {
-        let target = format!("clang_rt.builtins-{}", arch);
-        ("windows".to_string(), target.clone(), target)
-    } else if target.contains("windows-msvc") {
-        let builtins_arch = match arch {
-            "i586" | "i686" => "i386",
-            _ => arch,
-        };
-        (format!("windows/{}", mode),
-         "lib/builtins/builtins".to_string(),
-         format!("clang_rt.builtins-{}", builtins_arch))
+       .opt_level(2)
+       .debug(false);
+
+    if target.contains("msvc") {
+        // Don't pull in extra libraries on MSVC
+        cfg.flag("/Zl");
+
+        // Emulate C99 and C++11's __func__ for MSVC prior to 2013 CTP
+        cfg.define("__func__", Some("__FUNCTION__"));
     } else {
-        panic!("can't get os from target: {}", target)
-    };
-    let output = dst.join("build/lib").join(dir)
-                    .join(staticlib(&libname, target));
-    build.compiler_rt_built.borrow_mut().insert(target.to_string(),
-                                                output.clone());
-    if fs::metadata(&output).is_ok() {
+        // Turn off various features of gcc and such, mostly copying
+        // compiler-rt's build system already
+        cfg.flag("-fno-builtin");
+        cfg.flag("-fvisibility=hidden");
+        cfg.flag("-fomit-frame-pointer");
+        cfg.flag("-ffreestanding");
+    }
+
+    let mut sources = vec![
+        "absvdi2.c",
+        "absvsi2.c",
+        "adddf3.c",
+        "addsf3.c",
+        "addvdi3.c",
+        "addvsi3.c",
+        "apple_versioning.c",
+        "ashldi3.c",
+        "ashrdi3.c",
+        "clear_cache.c",
+        "clzdi2.c",
+        "clzsi2.c",
+        "cmpdi2.c",
+        "comparedf2.c",
+        "comparesf2.c",
+        "ctzdi2.c",
+        "ctzsi2.c",
+        "divdc3.c",
+        "divdf3.c",
+        "divdi3.c",
+        "divmoddi4.c",
+        "divmodsi4.c",
+        "divsc3.c",
+        "divsf3.c",
+        "divsi3.c",
+        "divxc3.c",
+        "extendsfdf2.c",
+        "extendhfsf2.c",
+        "ffsdi2.c",
+        "fixdfdi.c",
+        "fixdfsi.c",
+        "fixsfdi.c",
+        "fixsfsi.c",
+        "fixunsdfdi.c",
+        "fixunsdfsi.c",
+        "fixunssfdi.c",
+        "fixunssfsi.c",
+        "fixunsxfdi.c",
+        "fixunsxfsi.c",
+        "fixxfdi.c",
+        "floatdidf.c",
+        "floatdisf.c",
+        "floatdixf.c",
+        "floatsidf.c",
+        "floatsisf.c",
+        "floatundidf.c",
+        "floatundisf.c",
+        "floatundixf.c",
+        "floatunsidf.c",
+        "floatunsisf.c",
+        "int_util.c",
+        "lshrdi3.c",
+        "moddi3.c",
+        "modsi3.c",
+        "muldc3.c",
+        "muldf3.c",
+        "muldi3.c",
+        "mulodi4.c",
+        "mulosi4.c",
+        "muloti4.c",
+        "mulsc3.c",
+        "mulsf3.c",
+        "mulvdi3.c",
+        "mulvsi3.c",
+        "mulxc3.c",
+        "negdf2.c",
+        "negdi2.c",
+        "negsf2.c",
+        "negvdi2.c",
+        "negvsi2.c",
+        "paritydi2.c",
+        "paritysi2.c",
+        "popcountdi2.c",
+        "popcountsi2.c",
+        "powidf2.c",
+        "powisf2.c",
+        "powixf2.c",
+        "subdf3.c",
+        "subsf3.c",
+        "subvdi3.c",
+        "subvsi3.c",
+        "truncdfhf2.c",
+        "truncdfsf2.c",
+        "truncsfhf2.c",
+        "ucmpdi2.c",
+        "udivdi3.c",
+        "udivmoddi4.c",
+        "udivmodsi4.c",
+        "udivsi3.c",
+        "umoddi3.c",
+        "umodsi3.c",
+    ];
+
+    if !target.contains("ios") {
+        sources.extend(vec![
+            "absvti2.c",
+            "addtf3.c",
+            "addvti3.c",
+            "ashlti3.c",
+            "ashrti3.c",
+            "clzti2.c",
+            "cmpti2.c",
+            "ctzti2.c",
+            "divtf3.c",
+            "divti3.c",
+            "ffsti2.c",
+            "fixdfti.c",
+            "fixsfti.c",
+            "fixunsdfti.c",
+            "fixunssfti.c",
+            "fixunsxfti.c",
+            "fixxfti.c",
+            "floattidf.c",
+            "floattisf.c",
+            "floattixf.c",
+            "floatuntidf.c",
+            "floatuntisf.c",
+            "floatuntixf.c",
+            "lshrti3.c",
+            "modti3.c",
+            "multf3.c",
+            "multi3.c",
+            "mulvti3.c",
+            "negti2.c",
+            "negvti2.c",
+            "parityti2.c",
+            "popcountti2.c",
+            "powitf2.c",
+            "subtf3.c",
+            "subvti3.c",
+            "trampoline_setup.c",
+            "ucmpti2.c",
+            "udivmodti4.c",
+            "udivti3.c",
+            "umodti3.c",
+        ]);
+    }
+
+    if target.contains("apple") {
+        sources.extend(vec![
+            "atomic_flag_clear.c",
+            "atomic_flag_clear_explicit.c",
+            "atomic_flag_test_and_set.c",
+            "atomic_flag_test_and_set_explicit.c",
+            "atomic_signal_fence.c",
+            "atomic_thread_fence.c",
+        ]);
+    }
+
+    if !target.contains("windows") {
+        sources.push("emutls.c");
+    }
+
+    if target.contains("msvc") {
+        if target.contains("x86_64") {
+            sources.extend(vec![
+                "x86_64/floatdidf.c",
+                "x86_64/floatdisf.c",
+                "x86_64/floatdixf.c",
+            ]);
+        }
+    } else {
+        sources.push("gcc_personality_v0.c");
+
+        if target.contains("x86_64") {
+            sources.extend(vec![
+                "x86_64/chkstk.S",
+                "x86_64/chkstk2.S",
+                "x86_64/floatdidf.c",
+                "x86_64/floatdisf.c",
+                "x86_64/floatdixf.c",
+                "x86_64/floatundidf.S",
+                "x86_64/floatundisf.S",
+                "x86_64/floatundixf.S",
+            ]);
+        }
+
+        if target.contains("i386") ||
+           target.contains("i586") ||
+           target.contains("i686") {
+            sources.extend(vec![
+                "i386/ashldi3.S",
+                "i386/ashrdi3.S",
+                "i386/chkstk.S",
+                "i386/chkstk2.S",
+                "i386/divdi3.S",
+                "i386/floatdidf.S",
+                "i386/floatdisf.S",
+                "i386/floatdixf.S",
+                "i386/floatundidf.S",
+                "i386/floatundisf.S",
+                "i386/floatundixf.S",
+                "i386/lshrdi3.S",
+                "i386/moddi3.S",
+                "i386/muldi3.S",
+                "i386/udivdi3.S",
+                "i386/umoddi3.S",
+            ]);
+        }
+    }
+
+    if target.contains("arm") && !target.contains("ios") {
+        sources.extend(vec![
+            "arm/aeabi_cdcmp.S",
+            "arm/aeabi_cdcmpeq_check_nan.c",
+            "arm/aeabi_cfcmp.S",
+            "arm/aeabi_cfcmpeq_check_nan.c",
+            "arm/aeabi_dcmp.S",
+            "arm/aeabi_div0.c",
+            "arm/aeabi_drsub.c",
+            "arm/aeabi_fcmp.S",
+            "arm/aeabi_frsub.c",
+            "arm/aeabi_idivmod.S",
+            "arm/aeabi_ldivmod.S",
+            "arm/aeabi_memcmp.S",
+            "arm/aeabi_memcpy.S",
+            "arm/aeabi_memmove.S",
+            "arm/aeabi_memset.S",
+            "arm/aeabi_uidivmod.S",
+            "arm/aeabi_uldivmod.S",
+            "arm/bswapdi2.S",
+            "arm/bswapsi2.S",
+            "arm/clzdi2.S",
+            "arm/clzsi2.S",
+            "arm/comparesf2.S",
+            "arm/divmodsi4.S",
+            "arm/divsi3.S",
+            "arm/modsi3.S",
+            "arm/switch16.S",
+            "arm/switch32.S",
+            "arm/switch8.S",
+            "arm/switchu8.S",
+            "arm/sync_synchronize.S",
+            "arm/udivmodsi4.S",
+            "arm/udivsi3.S",
+            "arm/umodsi3.S",
+        ]);
+    }
+
+    if target.contains("armv7") {
+        sources.extend(vec![
+            "arm/sync_fetch_and_add_4.S",
+            "arm/sync_fetch_and_add_8.S",
+            "arm/sync_fetch_and_and_4.S",
+            "arm/sync_fetch_and_and_8.S",
+            "arm/sync_fetch_and_max_4.S",
+            "arm/sync_fetch_and_max_8.S",
+            "arm/sync_fetch_and_min_4.S",
+            "arm/sync_fetch_and_min_8.S",
+            "arm/sync_fetch_and_nand_4.S",
+            "arm/sync_fetch_and_nand_8.S",
+            "arm/sync_fetch_and_or_4.S",
+            "arm/sync_fetch_and_or_8.S",
+            "arm/sync_fetch_and_sub_4.S",
+            "arm/sync_fetch_and_sub_8.S",
+            "arm/sync_fetch_and_umax_4.S",
+            "arm/sync_fetch_and_umax_8.S",
+            "arm/sync_fetch_and_umin_4.S",
+            "arm/sync_fetch_and_umin_8.S",
+            "arm/sync_fetch_and_xor_4.S",
+            "arm/sync_fetch_and_xor_8.S",
+        ]);
+    }
+
+    if target.contains("eabihf") {
+        sources.extend(vec![
+            "arm/adddf3vfp.S",
+            "arm/addsf3vfp.S",
+            "arm/divdf3vfp.S",
+            "arm/divsf3vfp.S",
+            "arm/eqdf2vfp.S",
+            "arm/eqsf2vfp.S",
+            "arm/extendsfdf2vfp.S",
+            "arm/fixdfsivfp.S",
+            "arm/fixsfsivfp.S",
+            "arm/fixunsdfsivfp.S",
+            "arm/fixunssfsivfp.S",
+            "arm/floatsidfvfp.S",
+            "arm/floatsisfvfp.S",
+            "arm/floatunssidfvfp.S",
+            "arm/floatunssisfvfp.S",
+            "arm/gedf2vfp.S",
+            "arm/gesf2vfp.S",
+            "arm/gtdf2vfp.S",
+            "arm/gtsf2vfp.S",
+            "arm/ledf2vfp.S",
+            "arm/lesf2vfp.S",
+            "arm/ltdf2vfp.S",
+            "arm/ltsf2vfp.S",
+            "arm/muldf3vfp.S",
+            "arm/mulsf3vfp.S",
+            "arm/negdf2vfp.S",
+            "arm/negsf2vfp.S",
+            "arm/nedf2vfp.S",
+            "arm/nesf2vfp.S",
+            "arm/restore_vfp_d8_d15_regs.S",
+            "arm/save_vfp_d8_d15_regs.S",
+            "arm/subdf3vfp.S",
+            "arm/subsf3vfp.S",
+            "arm/truncdfsf2vfp.S",
+            "arm/unorddf2vfp.S",
+            "arm/unordsf2vfp.S",
+        ]);
+    }
+
+    if target.contains("aarch64") {
+        sources.extend(vec![
+            "comparetf2.c",
+            "extenddftf2.c",
+            "extendsftf2.c",
+            "fixtfdi.c",
+            "fixtfsi.c",
+            "fixtfti.c",
+            "fixunstfdi.c",
+            "fixunstfsi.c",
+            "fixunstfti.c",
+            "floatditf.c",
+            "floatsitf.c",
+            "floatunditf.c",
+            "floatunsitf.c",
+            "multc3.c",
+            "trunctfdf2.c",
+            "trunctfsf2.c",
+        ]);
+    }
+
+    let mut out_of_date = false;
+    for src in sources {
+        let src = build.src.join("src/compiler-rt/lib/builtins").join(src);
+        out_of_date = out_of_date || !up_to_date(&src, &output);
+        cfg.file(src);
+    }
+    if !out_of_date {
         return
     }
-    let _ = fs::remove_dir_all(&dst);
-    t!(fs::create_dir_all(&dst));
-    cfg.build_target(&build_target);
-    cfg.build();
+    cfg.compile("libcompiler-rt.a");
 }
 
 /// Compiles the `rust_test_helpers.c` library which we used in various
index 82ae70d22ca060336d9088f20cba8834552ea3a9..f715ceb16d71b969313528ebd1a1510d3dfab688 100644 (file)
@@ -124,6 +124,7 @@ macro_rules! targets {
             (check_codegen_units, CheckCodegenUnits { compiler: Compiler<'a> }),
             (check_incremental, CheckIncremental { compiler: Compiler<'a> }),
             (check_ui, CheckUi { compiler: Compiler<'a> }),
+            (check_mir_opt, CheckMirOpt { compiler: Compiler<'a> }),
             (check_debuginfo, CheckDebuginfo { compiler: Compiler<'a> }),
             (check_rustdoc, CheckRustdoc { compiler: Compiler<'a> }),
             (check_docs, CheckDocs { compiler: Compiler<'a> }),
@@ -347,9 +348,7 @@ pub fn deps(&self, build: &'a Build) -> Vec<Step<'a>> {
                 vec![self.libstd(compiler),
                      self.target(host).rustc(compiler.stage)]
             }
-            Source::CompilerRt { _dummy } => {
-                vec![self.llvm(()).target(&build.config.build)]
-            }
+            Source::CompilerRt { _dummy } => Vec::new(),
             Source::Llvm { _dummy } => Vec::new(),
             Source::TestHelpers { _dummy } => Vec::new(),
             Source::DebuggerScripts { stage: _ } => Vec::new(),
@@ -452,6 +451,7 @@ pub fn deps(&self, build: &'a Build) -> Vec<Step<'a>> {
                         self.check_pretty_rfail_full(compiler),
                         self.check_rpass_valgrind(compiler),
                         self.check_rmake(compiler),
+                        self.check_mir_opt(compiler),
 
                         // crates
                         self.check_crate_rustc(compiler),
@@ -479,6 +479,7 @@ pub fn deps(&self, build: &'a Build) -> Vec<Step<'a>> {
             Source::CheckTidy { stage } => {
                 vec![self.tool_tidy(stage)]
             }
+            Source::CheckMirOpt { compiler} |
             Source::CheckPrettyRPass { compiler } |
             Source::CheckPrettyRFail { compiler } |
             Source::CheckRFail { compiler } |
index 3ef7f8cab2d1b26d5a9fc41b2396b38a06215876..b5230132bcb666e3cb9dac6e821fe1d9edd71c3c 100644 (file)
@@ -103,7 +103,10 @@ pub fn add_lib_path(path: Vec<PathBuf>, cmd: &mut Command) {
 /// Uses last-modified time checks to verify this.
 pub fn up_to_date(src: &Path, dst: &Path) -> bool {
     let threshold = mtime(dst);
-    let meta = t!(fs::metadata(src));
+    let meta = match fs::metadata(src) {
+        Ok(meta) => meta,
+        Err(e) => panic!("source {:?} failed to get metadata: {}", src, e),
+    };
     if meta.is_dir() {
         dir_up_to_date(src, &threshold)
     } else {
index a8340d9d31e79d2fe319794ef49f90da988b7721..62e196a7ccdf3a4772db6e8ba86c5808241a6e2f 100644 (file)
@@ -60,6 +60,8 @@ asm!("xor %eax, %eax"
     : "eax"
    );
 # } }
+# #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))]
+# fn main() {}
 ```
 
 Whitespace also doesn't matter:
@@ -70,6 +72,8 @@ Whitespace also doesn't matter:
 # fn main() { unsafe {
 asm!("xor %eax, %eax" ::: "eax");
 # } }
+# #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))]
+# fn main() {}
 ```
 
 ## Operands
@@ -129,6 +133,8 @@ stay valid.
 // Put the value 0x200 in eax
 asm!("mov $$0x200, %eax" : /* no outputs */ : /* no inputs */ : "eax");
 # } }
+# #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))]
+# fn main() {}
 ```
 
 Input and output registers need not be listed since that information
@@ -164,6 +170,8 @@ unsafe {
 }
 println!("eax is currently {}", result);
 # }
+# #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))]
+# fn main() {}
 ```
 
 ## More Information
index e681d1bee06184549861f1045c1b765a1c2a0f7e..e4cb861d3b0f5299243fbd22f22a66ac91561dc3 100644 (file)
@@ -105,19 +105,19 @@ When you need to keep track of how many times you already looped, you can use th
 #### On ranges:
 
 ```rust
-for (i, j) in (5..10).enumerate() {
-    println!("i = {} and j = {}", i, j);
+for (index, value) in (5..10).enumerate() {
+    println!("index = {} and value = {}", index, value);
 }
 ```
 
 Outputs:
 
 ```text
-i = 0 and j = 5
-i = 1 and j = 6
-i = 2 and j = 7
-i = 3 and j = 8
-i = 4 and j = 9
+index = 0 and value = 5
+index = 1 and value = 6
+index = 2 and value = 7
+index = 3 and value = 8
+index = 4 and value = 9
 ```
 
 Don't forget to add the parentheses around the range.
index 3e889f51f542d2d7541933d62771d05942c3e6c6..0259db221b6bc0dbaa0a47c94e7386eec91d22a3 100644 (file)
@@ -94,7 +94,7 @@
 * `|` (`|โ€ฆ| expr`): closures.  See [Closures].
 * `|=` (`var |= expr`): bitwise or & assignment. Overloadable (`BitOrAssign`).
 * `||` (`expr || expr`): logical or.
-* `_`: "ignored" pattern binding.  See [Patterns (Ignoring bindings)].
+* `_`: "ignored" pattern binding (see [Patterns (Ignoring bindings)]). Also used to make integer-literals readable (see [Reference (Integer literals)]).
 
 ## Other Syntax
 
 [Primitive Types (Tuples)]: primitive-types.html#tuples
 [Raw Pointers]: raw-pointers.html
 [Reference (Byte String Literals)]: ../reference.html#byte-string-literals
+[Reference (Integer literals)]: ../reference.html#integer-literals
 [Reference (Raw Byte String Literals)]: ../reference.html#raw-byte-string-literals
 [Reference (Raw String Literals)]: ../reference.html#raw-string-literals
 [References and Borrowing]: references-and-borrowing.html
index b31a34a0425a489f246f2616b499a93cf4f8c918..b1aee579aabc26ae560c72e7187532fc0fd95c00 100644 (file)
@@ -123,7 +123,6 @@ dispatch with trait objects by casting:
 # trait Foo { fn method(&self) -> String; }
 # impl Foo for u8 { fn method(&self) -> String { format!("u8: {}", *self) } }
 # impl Foo for String { fn method(&self) -> String { format!("string: {}", *self) } }
-
 fn do_something(x: &Foo) {
     x.method();
 }
@@ -140,7 +139,6 @@ or by coercing:
 # trait Foo { fn method(&self) -> String; }
 # impl Foo for u8 { fn method(&self) -> String { format!("u8: {}", *self) } }
 # impl Foo for String { fn method(&self) -> String { format!("string: {}", *self) } }
-
 fn do_something(x: &Foo) {
     x.method();
 }
index d565532017a65982d518e2453b780743e609a266..189695716deb1bb776f46aee347699529bcd42c4 100644 (file)
@@ -50,7 +50,7 @@ struct Vec<T> {
 }
 ```
 
-Unlike the previous example it *appears* that everything is exactly as we
+Unlike the previous example, it *appears* that everything is exactly as we
 want. Every generic argument to Vec shows up in at least one field.
 Good to go!
 
@@ -84,4 +84,3 @@ standard library made a utility for itself called `Unique<T>` which:
 * includes a `PhantomData<T>`
 * auto-derives Send/Sync as if T was contained
 * marks the pointer as NonZero for the null-pointer optimization
-
index b8509321e3d19b0679ba7a29aea280336229dab2..a461023642afd6130df80eaf0b95de7c0cd32021 100644 (file)
@@ -1653,14 +1653,43 @@ the Rust ABI and the foreign ABI.
 A number of [attributes](#ffi-attributes) control the behavior of external blocks.
 
 By default external blocks assume that the library they are calling uses the
-standard C "cdecl" ABI. Other ABIs may be specified using an `abi` string, as
-shown here:
+standard C ABI on the specific platform. Other ABIs may be specified using an
+`abi` string, as shown here:
 
 ```ignore
 // Interface to the Windows API
 extern "stdcall" { }
 ```
 
+There are three ABI strings which are cross-platform, and which all compilers
+are guaranteed to support:
+
+* `extern "Rust"` -- The default ABI when you write a normal `fn foo()` in any
+  Rust code.
+* `extern "C"` -- This is the same as `extern fn foo()`; whatever the default
+  your C compiler supports.
+* `extern "system"` -- Usually the same as `extern "C"`, except on Win32, in
+  which case it's `"stdcall"`, or what you should use to link to the Windows API
+  itself
+
+There are also some platform-specific ABI strings:
+
+* `extern "cdecl"` -- The default for x86\_32 C code.
+* `extern "stdcall"` -- The default for the Win32 API on x86\_32.
+* `extern "win64"` -- The default for C code on x86\_64 Windows.
+* `extern "aapcs"` -- The default for ARM.
+* `extern "fastcall"` -- The `fastcall` ABI -- corresponds to MSVC's
+  `__fastcall` and GCC and clang's `__attribute__((fastcall))`
+* `extern "vectorcall"` -- The `vectorcall` ABI -- corresponds to MSVC's
+  `__vectorcall` and clang's `__attribute__((vectorcall))`
+
+Finally, there are some rustc-specific ABI strings:
+
+* `extern "rust-intrinsic"` -- The ABI of rustc intrinsics.
+* `extern "rust-call"` -- The ABI of the Fn::call trait functions.
+* `extern "platform-intrinsic"` -- Specific platform intrinsics -- like, for
+  example, `sqrt` -- have this ABI. You should never have to deal with it.
+
 The `link` attribute allows the name of the library to be specified. When
 specified the compiler will attempt to link against the native library of the
 specified name.
index e762e4d8ce9a26a2d3690a40839d6e47ae280bd5..64b780413f884f4a33045525a98d83717d6053e5 100644 (file)
 //!
 //! Sharing some immutable data between threads:
 //!
+// Note that we **do not** run these tests here. The windows builders get super
+// unhappy of a thread outlives the main thread and then exits at the same time
+// (something deadlocks) so we just avoid this entirely by not running these
+// tests.
 //! ```no_run
 //! use std::sync::Arc;
 //! use std::thread;
 /// by putting it inside `Mutex` and then share `Mutex` immutably
 /// with `Arc<T>` as shown below.
 ///
-/// ```
+// See comment at the top of this file for why the test is no_run
+/// ```no_run
 /// use std::sync::{Arc, Mutex};
 /// use std::thread;
 ///
index aea7a1c13a28171778b427920c78c8cd89d3a1d0..c3a7d4023754aac97d45a0539a9cf0e4a8cfe490 100644 (file)
@@ -313,6 +313,10 @@ pub struct RangeMut<'a, K: 'a, V: 'a> {
 }
 
 /// A view into a single entry in a map, which may either be vacant or occupied.
+/// This enum is constructed from the [`entry`] method on [`BTreeMap`].
+///
+/// [`BTreeMap`]: struct.BTreeMap.html
+/// [`entry`]: struct.BTreeMap.html#method.entry
 #[stable(feature = "rust1", since = "1.0.0")]
 pub enum Entry<'a, K: 'a, V: 'a> {
     /// A vacant Entry
@@ -326,7 +330,23 @@ pub enum Entry<'a, K: 'a, V: 'a> {
              OccupiedEntry<'a, K, V>),
 }
 
-/// A vacant Entry.
+#[stable(feature= "debug_btree_map", since = "1.12.0")]
+impl<'a, K: 'a + Debug + Ord, V: 'a + Debug> Debug for Entry<'a, K, V> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        match *self {
+            Vacant(ref v) => f.debug_tuple("Entry")
+                              .field(v)
+                              .finish(),
+            Occupied(ref o) => f.debug_tuple("Entry")
+                                .field(o)
+                                .finish(),
+        }
+    }
+}
+
+/// A vacant Entry. It is part of the [`Entry`] enum.
+///
+/// [`Entry`]: enum.Entry.html
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct VacantEntry<'a, K: 'a, V: 'a> {
     key: K,
@@ -337,7 +357,18 @@ pub struct VacantEntry<'a, K: 'a, V: 'a> {
     _marker: PhantomData<&'a mut (K, V)>,
 }
 
-/// An occupied Entry.
+#[stable(feature= "debug_btree_map", since = "1.12.0")]
+impl<'a, K: 'a + Debug + Ord, V: 'a> Debug for VacantEntry<'a, K, V> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        f.debug_tuple("VacantEntry")
+         .field(self.key())
+         .finish()
+    }
+}
+
+/// An occupied Entry. It is part of the [`Entry`] enum.
+///
+/// [`Entry`]: enum.Entry.html
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct OccupiedEntry<'a, K: 'a, V: 'a> {
     handle: Handle<NodeRef<marker::Mut<'a>, K, V, marker::LeafOrInternal>, marker::KV>,
@@ -348,6 +379,16 @@ pub struct OccupiedEntry<'a, K: 'a, V: 'a> {
     _marker: PhantomData<&'a mut (K, V)>,
 }
 
+#[stable(feature= "debug_btree_map", since = "1.12.0")]
+impl<'a, K: 'a + Debug + Ord, V: 'a + Debug> Debug for OccupiedEntry<'a, K, V> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        f.debug_struct("OccupiedEntry")
+         .field("key", self.key())
+         .field("value", self.get())
+         .finish()
+    }
+}
+
 // An iterator for merging two sorted sequences into one
 struct MergeIter<K, V, I: Iterator<Item = (K, V)>> {
     left: Peekable<I>,
@@ -1857,6 +1898,17 @@ pub fn is_empty(&self) -> bool {
 impl<'a, K: Ord, V> Entry<'a, K, V> {
     /// Ensures a value is in the entry by inserting the default if empty, and returns
     /// a mutable reference to the value in the entry.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::collections::BTreeMap;
+    ///
+    /// let mut map: BTreeMap<&str, usize> = BTreeMap::new();
+    /// map.entry("poneyland").or_insert(12);
+    ///
+    /// assert_eq!(map["poneyland"], 12);
+    /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn or_insert(self, default: V) -> &'a mut V {
         match self {
@@ -1867,6 +1919,19 @@ pub fn or_insert(self, default: V) -> &'a mut V {
 
     /// Ensures a value is in the entry by inserting the result of the default function if empty,
     /// and returns a mutable reference to the value in the entry.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::collections::BTreeMap;
+    ///
+    /// let mut map: BTreeMap<&str, String> = BTreeMap::new();
+    /// let s = "hoho".to_owned();
+    ///
+    /// map.entry("poneyland").or_insert_with(|| s);
+    ///
+    /// assert_eq!(map["poneyland"], "hoho".to_owned());
+    /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn or_insert_with<F: FnOnce() -> V>(self, default: F) -> &'a mut V {
         match self {
@@ -1876,6 +1941,15 @@ pub fn or_insert_with<F: FnOnce() -> V>(self, default: F) -> &'a mut V {
     }
 
     /// Returns a reference to this entry's key.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::collections::BTreeMap;
+    ///
+    /// let mut map: BTreeMap<&str, usize> = BTreeMap::new();
+    /// assert_eq!(map.entry("poneyland").key(), &"poneyland");
+    /// ```
     #[stable(feature = "map_entry_keys", since = "1.10.0")]
     pub fn key(&self) -> &K {
         match *self {
@@ -1888,12 +1962,36 @@ pub fn key(&self) -> &K {
 impl<'a, K: Ord, V> VacantEntry<'a, K, V> {
     /// Gets a reference to the key that would be used when inserting a value
     /// through the VacantEntry.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::collections::BTreeMap;
+    ///
+    /// let mut map: BTreeMap<&str, usize> = BTreeMap::new();
+    /// assert_eq!(map.entry("poneyland").key(), &"poneyland");
+    /// ```
     #[stable(feature = "map_entry_keys", since = "1.10.0")]
     pub fn key(&self) -> &K {
         &self.key
     }
 
     /// Take ownership of the key.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(map_entry_recover_keys)]
+    ///
+    /// use std::collections::BTreeMap;
+    /// use std::collections::btree_map::Entry;
+    ///
+    /// let mut map: BTreeMap<&str, usize> = BTreeMap::new();
+    ///
+    /// if let Entry::Vacant(v) = map.entry("poneyland") {
+    ///     v.into_key();
+    /// }
+    /// ```
     #[unstable(feature = "map_entry_recover_keys", issue = "34285")]
     pub fn into_key(self) -> K {
         self.key
@@ -1901,6 +1999,21 @@ pub fn into_key(self) -> K {
 
     /// Sets the value of the entry with the VacantEntry's key,
     /// and returns a mutable reference to it.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::collections::BTreeMap;
+    ///
+    /// let mut count: BTreeMap<&str, usize> = BTreeMap::new();
+    ///
+    /// // count the number of occurrences of letters in the vec
+    /// for x in vec!["a","b","a","c","a","b"] {
+    ///     *count.entry(x).or_insert(0) += 1;
+    /// }
+    ///
+    /// assert_eq!(count["a"], 3);
+    /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn insert(self, value: V) -> &'a mut V {
         *self.length += 1;
@@ -1946,30 +2059,106 @@ pub fn insert(self, value: V) -> &'a mut V {
 
 impl<'a, K: Ord, V> OccupiedEntry<'a, K, V> {
     /// Gets a reference to the key in the entry.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::collections::BTreeMap;
+    ///
+    /// let mut map: BTreeMap<&str, usize> = BTreeMap::new();
+    /// map.entry("poneyland").or_insert(12);
+    /// assert_eq!(map.entry("poneyland").key(), &"poneyland");
+    /// ```
     #[stable(feature = "map_entry_keys", since = "1.10.0")]
     pub fn key(&self) -> &K {
         self.handle.reborrow().into_kv().0
     }
 
     /// Take ownership of the key and value from the map.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(map_entry_recover_keys)]
+    ///
+    /// use std::collections::BTreeMap;
+    /// use std::collections::btree_map::Entry;
+    ///
+    /// let mut map: BTreeMap<&str, usize> = BTreeMap::new();
+    /// map.entry("poneyland").or_insert(12);
+    ///
+    /// if let Entry::Occupied(o) = map.entry("poneyland") {
+    ///     // We delete the entry from the map.
+    ///     o.remove_pair();
+    /// }
+    ///
+    /// // If now try to get the value, it will panic:
+    /// // println!("{}", map["poneyland"]);
+    /// ```
     #[unstable(feature = "map_entry_recover_keys", issue = "34285")]
     pub fn remove_pair(self) -> (K, V) {
         self.remove_kv()
     }
 
     /// Gets a reference to the value in the entry.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::collections::BTreeMap;
+    /// use std::collections::btree_map::Entry;
+    ///
+    /// let mut map: BTreeMap<&str, usize> = BTreeMap::new();
+    /// map.entry("poneyland").or_insert(12);
+    ///
+    /// if let Entry::Occupied(o) = map.entry("poneyland") {
+    ///     assert_eq!(o.get(), &12);
+    /// }
+    /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn get(&self) -> &V {
         self.handle.reborrow().into_kv().1
     }
 
     /// Gets a mutable reference to the value in the entry.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::collections::BTreeMap;
+    /// use std::collections::btree_map::Entry;
+    ///
+    /// let mut map: BTreeMap<&str, usize> = BTreeMap::new();
+    /// map.entry("poneyland").or_insert(12);
+    ///
+    /// assert_eq!(map["poneyland"], 12);
+    /// if let Entry::Occupied(mut o) = map.entry("poneyland") {
+    ///      *o.get_mut() += 10;
+    /// }
+    /// assert_eq!(map["poneyland"], 22);
+    /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn get_mut(&mut self) -> &mut V {
         self.handle.kv_mut().1
     }
 
     /// Converts the entry into a mutable reference to its value.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::collections::BTreeMap;
+    /// use std::collections::btree_map::Entry;
+    ///
+    /// let mut map: BTreeMap<&str, usize> = BTreeMap::new();
+    /// map.entry("poneyland").or_insert(12);
+    ///
+    /// assert_eq!(map["poneyland"], 12);
+    /// if let Entry::Occupied(o) = map.entry("poneyland") {
+    ///     *o.into_mut() += 10;
+    /// }
+    /// assert_eq!(map["poneyland"], 22);
+    /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn into_mut(self) -> &'a mut V {
         self.handle.into_kv_mut().1
@@ -1977,12 +2166,43 @@ pub fn into_mut(self) -> &'a mut V {
 
     /// Sets the value of the entry with the OccupiedEntry's key,
     /// and returns the entry's old value.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::collections::BTreeMap;
+    /// use std::collections::btree_map::Entry;
+    ///
+    /// let mut map: BTreeMap<&str, usize> = BTreeMap::new();
+    /// map.entry("poneyland").or_insert(12);
+    ///
+    /// if let Entry::Occupied(mut o) = map.entry("poneyland") {
+    ///     assert_eq!(o.insert(15), 12);
+    /// }
+    /// assert_eq!(map["poneyland"], 15);
+    /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn insert(&mut self, value: V) -> V {
         mem::replace(self.get_mut(), value)
     }
 
     /// Takes the value of the entry out of the map, and returns it.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::collections::BTreeMap;
+    /// use std::collections::btree_map::Entry;
+    ///
+    /// let mut map: BTreeMap<&str, usize> = BTreeMap::new();
+    /// map.entry("poneyland").or_insert(12);
+    ///
+    /// if let Entry::Occupied(o) = map.entry("poneyland") {
+    ///     assert_eq!(o.remove(), 12);
+    /// }
+    /// // If we try to get "poneyland"'s value, it'll panic:
+    /// // println!("{}", map["poneyland"]);
+    /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn remove(self) -> V {
         self.remove_kv().1
index 15de0dd802d99f0a067c6df18d086e1cdb3465b8..c5312d0d9bbd9ad27ee68432f46e40f8ff146842 100644 (file)
 //! ## Precision
 //!
 //! For non-numeric types, this can be considered a "maximum width". If the resulting string is
-//! longer than this width, then it is truncated down to this many characters and only those are
-//! emitted.
+//! longer than this width, then it is truncated down to this many characters and that truncated
+//! value is emitted with proper `fill`, `alignment` and `width` if those parameters are set.
 //!
 //! For integral types, this is ignored.
 //!
 //! ```
 //! println!("{}, `{name:.*}` has 3 fractional digits", "Hello", 3, name=1234.56);
 //! println!("{}, `{name:.*}` has 3 characters", "Hello", 3, name="1234.56");
+//! println!("{}, `{name:>8.*}` has 3 right-aligned characters", "Hello", 3, name="1234.56");
 //! ```
 //!
 //! print two significantly different things:
 //! ```text
 //! Hello, `1234.560` has 3 fractional digits
 //! Hello, `123` has 3 characters
+//! Hello, `     123` has 3 right-aligned characters
 //! ```
 //!
 //! # Escaping
index dbede94f0bf1b668a8fa37173858c44cb2fc757a..3d5c3125fae2489c460f1352aa4776a1017fdf33 100644 (file)
@@ -172,6 +172,14 @@ fn default() -> Self {
 
 impl<T> LinkedList<T> {
     /// Creates an empty `LinkedList`.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::collections::LinkedList;
+    ///
+    /// let list: LinkedList<u32> = LinkedList::new();
+    /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn new() -> Self {
@@ -226,6 +234,24 @@ pub fn append(&mut self, other: &mut Self) {
     }
 
     /// Provides a forward iterator.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::collections::LinkedList;
+    ///
+    /// let mut list: LinkedList<u32> = LinkedList::new();
+    ///
+    /// list.push_back(0);
+    /// list.push_back(1);
+    /// list.push_back(2);
+    ///
+    /// let mut iter = list.iter();
+    /// assert_eq!(iter.next(), Some(&0));
+    /// assert_eq!(iter.next(), Some(&1));
+    /// assert_eq!(iter.next(), Some(&2));
+    /// assert_eq!(iter.next(), None);
+    /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn iter(&self) -> Iter<T> {
@@ -238,6 +264,28 @@ pub fn iter(&self) -> Iter<T> {
     }
 
     /// Provides a forward iterator with mutable references.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::collections::LinkedList;
+    ///
+    /// let mut list: LinkedList<u32> = LinkedList::new();
+    ///
+    /// list.push_back(0);
+    /// list.push_back(1);
+    /// list.push_back(2);
+    ///
+    /// for element in list.iter_mut() {
+    ///     *element += 10;
+    /// }
+    ///
+    /// let mut iter = list.iter();
+    /// assert_eq!(iter.next(), Some(&10));
+    /// assert_eq!(iter.next(), Some(&11));
+    /// assert_eq!(iter.next(), Some(&12));
+    /// assert_eq!(iter.next(), None);
+    /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn iter_mut(&mut self) -> IterMut<T> {
@@ -289,7 +337,6 @@ pub fn is_empty(&self) -> bool {
     ///
     /// dl.push_back(3);
     /// assert_eq!(dl.len(), 3);
-    ///
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -316,7 +363,6 @@ pub fn len(&self) -> usize {
     /// dl.clear();
     /// assert_eq!(dl.len(), 0);
     /// assert_eq!(dl.front(), None);
-    ///
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -326,6 +372,23 @@ pub fn clear(&mut self) {
 
     /// Returns `true` if the `LinkedList` contains an element equal to the
     /// given value.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(linked_list_contains)]
+    ///
+    /// use std::collections::LinkedList;
+    ///
+    /// let mut list: LinkedList<u32> = LinkedList::new();
+    ///
+    /// list.push_back(0);
+    /// list.push_back(1);
+    /// list.push_back(2);
+    ///
+    /// assert_eq!(list.contains(&0), true);
+    /// assert_eq!(list.contains(&10), false);
+    /// ```
     #[unstable(feature = "linked_list_contains", reason = "recently added",
                issue = "32630")]
     pub fn contains(&self, x: &T) -> bool
@@ -347,7 +410,6 @@ pub fn contains(&self, x: &T) -> bool
     ///
     /// dl.push_front(1);
     /// assert_eq!(dl.front(), Some(&1));
-    ///
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -374,7 +436,6 @@ pub fn front(&self) -> Option<&T> {
     ///     Some(x) => *x = 5,
     /// }
     /// assert_eq!(dl.front(), Some(&5));
-    ///
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -395,7 +456,6 @@ pub fn front_mut(&mut self) -> Option<&mut T> {
     ///
     /// dl.push_back(1);
     /// assert_eq!(dl.back(), Some(&1));
-    ///
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -422,7 +482,6 @@ pub fn back(&self) -> Option<&T> {
     ///     Some(x) => *x = 5,
     /// }
     /// assert_eq!(dl.back(), Some(&5));
-    ///
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -446,7 +505,6 @@ pub fn back_mut(&mut self) -> Option<&mut T> {
     ///
     /// dl.push_front(1);
     /// assert_eq!(dl.front().unwrap(), &1);
-    ///
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn push_front(&mut self, elt: T) {
@@ -471,9 +529,7 @@ pub fn push_front(&mut self, elt: T) {
     /// assert_eq!(d.pop_front(), Some(3));
     /// assert_eq!(d.pop_front(), Some(1));
     /// assert_eq!(d.pop_front(), None);
-    ///
     /// ```
-    ///
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn pop_front(&mut self) -> Option<T> {
         self.pop_front_node().map(Node::into_element)
index 2c54dc13c8d0b6440494bf927138dfec7a6b06fd..ccef6c02f9d22f4d15aa3aded94270d16d847a9e 100644 (file)
@@ -544,14 +544,21 @@ pub fn iter_mut(&mut self) -> IterMut<T> {
     ///
     /// # Example
     ///
-    /// Print the adjacent pairs of a slice (i.e. `[1,2]`, `[2,3]`,
-    /// `[3,4]`):
+    /// ```
+    /// let slice = ['r', 'u', 's', 't'];
+    /// let mut iter = slice.windows(2);
+    /// assert_eq!(iter.next().unwrap(), &['r', 'u']);
+    /// assert_eq!(iter.next().unwrap(), &['u', 's']);
+    /// assert_eq!(iter.next().unwrap(), &['s', 't']);
+    /// assert!(iter.next().is_none());
+    /// ```
+    ///
+    /// If the slice is shorter than `size`:
     ///
-    /// ```rust
-    /// let v = &[1, 2, 3, 4];
-    /// for win in v.windows(2) {
-    ///     println!("{:?}", win);
-    /// }
+    /// ```
+    /// let slice = ['f', 'o', 'o'];
+    /// let mut iter = slice.windows(4);
+    /// assert!(iter.next().is_none());
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
@@ -684,15 +691,40 @@ pub fn split_at_mut(&mut self, mid: usize) -> (&mut [T], &mut [T]) {
     ///
     /// # Examples
     ///
-    /// Print the slice split by numbers divisible by 3 (i.e. `[10, 40]`,
-    /// `[20]`, `[50]`):
+    /// ```
+    /// let slice = [10, 40, 33, 20];
+    /// let mut iter = slice.split(|num| num % 3 == 0);
     ///
+    /// assert_eq!(iter.next().unwrap(), &[10, 40]);
+    /// assert_eq!(iter.next().unwrap(), &[20]);
+    /// assert!(iter.next().is_none());
     /// ```
-    /// let v = [10, 40, 30, 20, 60, 50];
     ///
-    /// for group in v.split(|num| *num % 3 == 0) {
-    ///     println!("{:?}", group);
-    /// }
+    /// If the first element is matched, an empty slice will be the first item
+    /// returned by the iterator. Similarly, if the last element in the slice
+    /// is matched, an empty slice will be the last item returned by the
+    /// iterator:
+    ///
+    /// ```
+    /// let slice = [10, 40, 33];
+    /// let mut iter = slice.split(|num| num % 3 == 0);
+    ///
+    /// assert_eq!(iter.next().unwrap(), &[10, 40]);
+    /// assert_eq!(iter.next().unwrap(), &[]);
+    /// assert!(iter.next().is_none());
+    /// ```
+    ///
+    /// If two matched elements are directly adjacent, an empty slice will be
+    /// present between them:
+    ///
+    /// ```
+    /// let slice = [10, 6, 33, 20];
+    /// let mut iter = slice.split(|num| num % 3 == 0);
+    ///
+    /// assert_eq!(iter.next().unwrap(), &[10]);
+    /// assert_eq!(iter.next().unwrap(), &[]);
+    /// assert_eq!(iter.next().unwrap(), &[20]);
+    /// assert!(iter.next().is_none());
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
index eedf4c2c11f34fcf32808df3805259efa9990513..f91d8a5f4e1e84d506fd4562fa69f27d87b4c72d 100644 (file)
@@ -59,7 +59,7 @@
 use core::hash;
 use core::iter::FromIterator;
 use core::mem;
-use core::ops::{self, Add, Index, IndexMut};
+use core::ops::{self, Add, AddAssign, Index, IndexMut};
 use core::ptr;
 use core::str::pattern::Pattern;
 use rustc_unicode::char::{decode_utf16, REPLACEMENT_CHARACTER};
@@ -701,6 +701,12 @@ pub fn from_utf16_lossy(v: &[u16]) -> String {
     /// Violating these may cause problems like corrupting the allocator's
     /// internal datastructures.
     ///
+    /// The ownership of `ptr` is effectively transferred to the
+    /// `String` which may then deallocate, reallocate or change the
+    /// contents of memory pointed to by the pointer at will. Ensure
+    /// that nothing else uses the pointer after calling this
+    /// function.
+    ///
     /// # Examples
     ///
     /// Basic usage:
@@ -1126,18 +1132,62 @@ pub fn insert(&mut self, idx: usize, ch: char) {
         assert!(idx <= len);
         assert!(self.is_char_boundary(idx));
         let bits = ch.encode_utf8();
-        let bits = bits.as_slice();
-        let amt = bits.len();
+
+        unsafe {
+            self.insert_bytes(idx, bits.as_slice());
+        }
+    }
+
+    unsafe fn insert_bytes(&mut self, idx: usize, bytes: &[u8]) {
+        let len = self.len();
+        let amt = bytes.len();
         self.vec.reserve(amt);
 
+        ptr::copy(self.vec.as_ptr().offset(idx as isize),
+                  self.vec.as_mut_ptr().offset((idx + amt) as isize),
+                  len - idx);
+        ptr::copy(bytes.as_ptr(),
+                  self.vec.as_mut_ptr().offset(idx as isize),
+                  amt);
+        self.vec.set_len(len + amt);
+    }
+
+    /// Inserts a string into this `String` at a byte position.
+    ///
+    /// This is an `O(n)` operation as it requires copying every element in the
+    /// buffer.
+    ///
+    /// # Panics
+    ///
+    /// Panics if `idx` is larger than the `String`'s length, or if it does not
+    /// lie on a [`char`] boundary.
+    ///
+    /// [`char`]: ../../std/primitive.char.html
+    ///
+    /// # Examples
+    ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// #![feature(insert_str)]
+    ///
+    /// let mut s = String::from("bar");
+    ///
+    /// s.insert_str(0, "foo");
+    ///
+    /// assert_eq!("foobar", s);
+    /// ```
+    #[inline]
+    #[unstable(feature = "insert_str",
+               reason = "recent addition",
+               issue = "0")]
+    pub fn insert_str(&mut self, idx: usize, string: &str) {
+        let len = self.len();
+        assert!(idx <= len);
+        assert!(self.is_char_boundary(idx));
+
         unsafe {
-            ptr::copy(self.vec.as_ptr().offset(idx as isize),
-                      self.vec.as_mut_ptr().offset((idx + amt) as isize),
-                      len - idx);
-            ptr::copy(bits.as_ptr(),
-                      self.vec.as_mut_ptr().offset(idx as isize),
-                      amt);
-            self.vec.set_len(len + amt);
+            self.insert_bytes(idx, string.as_bytes());
         }
     }
 
@@ -1559,6 +1609,14 @@ fn add(mut self, other: &str) -> String {
     }
 }
 
+#[stable(feature = "stringaddassign", since = "1.12.0")]
+impl<'a> AddAssign<&'a str> for String {
+    #[inline]
+    fn add_assign(&mut self, other: &str) {
+        self.push_str(other);
+    }
+}
+
 #[stable(feature = "rust1", since = "1.0.0")]
 impl ops::Index<ops::Range<usize>> for String {
     type Output = str;
index 7a3c9bc3bb2180c5851fdbffaaf70bede03e5d5b..967baccd2740a7f724dbd17ca5a732aab33ac847 100644 (file)
@@ -342,12 +342,18 @@ pub fn with_capacity(capacity: usize) -> Vec<T> {
     ///
     /// * `ptr` needs to have been previously allocated via `String`/`Vec<T>`
     ///   (at least, it's highly likely to be incorrect if it wasn't).
-    /// * `length` needs to be the length that less than or equal to `capacity`.
+    /// * `length` needs to be less than or equal to `capacity`.
     /// * `capacity` needs to be the capacity that the pointer was allocated with.
     ///
     /// Violating these may cause problems like corrupting the allocator's
     /// internal datastructures.
     ///
+    /// The ownership of `ptr` is effectively transferred to the
+    /// `Vec<T>` which may then deallocate, reallocate or change the
+    /// contents of memory pointed to by the pointer at will. Ensure
+    /// that nothing else uses the pointer after calling this
+    /// function.
+    ///
     /// # Examples
     ///
     /// ```
@@ -479,18 +485,45 @@ pub fn into_boxed_slice(mut self) -> Box<[T]> {
         }
     }
 
-    /// Shorten a vector to be `len` elements long, dropping excess elements.
+    /// Shortens the vector, keeping the first `len` elements and dropping
+    /// the rest.
     ///
     /// If `len` is greater than the vector's current length, this has no
     /// effect.
     ///
+    /// The [`drain`] method can emulate `truncate`, but causes the excess
+    /// elements to be returned instead of dropped.
+    ///
     /// # Examples
     ///
+    /// Truncating a five element vector to two elements:
+    ///
     /// ```
     /// let mut vec = vec![1, 2, 3, 4, 5];
     /// vec.truncate(2);
     /// assert_eq!(vec, [1, 2]);
     /// ```
+    ///
+    /// No truncation occurs when `len` is greater than the vector's current
+    /// length:
+    ///
+    /// ```
+    /// let mut vec = vec![1, 2, 3];
+    /// vec.truncate(8);
+    /// assert_eq!(vec, [1, 2, 3]);
+    /// ```
+    ///
+    /// Truncating when `len == 0` is equivalent to calling the [`clear`]
+    /// method.
+    ///
+    /// ```
+    /// let mut vec = vec![1, 2, 3];
+    /// vec.truncate(0);
+    /// assert_eq!(vec, []);
+    /// ```
+    ///
+    /// [`clear`]: #method.clear
+    /// [`drain`]: #method.drain
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn truncate(&mut self, len: usize) {
         unsafe {
@@ -508,6 +541,14 @@ pub fn truncate(&mut self, len: usize) {
     /// Extracts a slice containing the entire vector.
     ///
     /// Equivalent to `&s[..]`.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::io::{self, Write};
+    /// let buffer = vec![1, 2, 3, 5, 8];
+    /// io::sink().write(buffer.as_slice()).unwrap();
+    /// ```
     #[inline]
     #[stable(feature = "vec_as_slice", since = "1.7.0")]
     pub fn as_slice(&self) -> &[T] {
@@ -517,6 +558,14 @@ pub fn as_slice(&self) -> &[T] {
     /// Extracts a mutable slice of the entire vector.
     ///
     /// Equivalent to `&mut s[..]`.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::io::{self, Read};
+    /// let mut buffer = vec![0; 3];
+    /// io::repeat(0b101).read_exact(buffer.as_mut_slice()).unwrap();
+    /// ```
     #[inline]
     #[stable(feature = "vec_as_slice", since = "1.7.0")]
     pub fn as_mut_slice(&mut self) -> &mut [T] {
@@ -532,9 +581,38 @@ pub fn as_mut_slice(&mut self) -> &mut [T] {
     /// # Examples
     ///
     /// ```
-    /// let mut v = vec![1, 2, 3, 4];
+    /// use std::ptr;
+    ///
+    /// let mut vec = vec!['r', 'u', 's', 't'];
+    ///
+    /// unsafe {
+    ///     ptr::drop_in_place(&mut vec[3]);
+    ///     vec.set_len(3);
+    /// }
+    /// assert_eq!(vec, ['r', 'u', 's']);
+    /// ```
+    ///
+    /// In this example, there is a memory leak since the memory locations
+    /// owned by the inner vectors were not freed prior to the `set_len` call:
+    ///
+    /// ```
+    /// let mut vec = vec![vec![1, 0, 0],
+    ///                    vec![0, 1, 0],
+    ///                    vec![0, 0, 1]];
+    /// unsafe {
+    ///     vec.set_len(0);
+    /// }
+    /// ```
+    ///
+    /// In this example, the vector gets expanded from zero to four items
+    /// without any memory allocations occurring, resulting in vector
+    /// values of unallocated memory:
+    ///
+    /// ```
+    /// let mut vec: Vec<char> = Vec::new();
+    ///
     /// unsafe {
-    ///     v.set_len(1);
+    ///     vec.set_len(4);
     /// }
     /// ```
     #[inline]
index 84a0bbbd24983468ce4b639a9c736db07b193364..9c3792afa2f1c91b5e87e234f1258028d2dc5f30 100644 (file)
@@ -365,12 +365,28 @@ unsafe fn handle_cap_increase(&mut self, old_cap: usize) {
 
 impl<T> VecDeque<T> {
     /// Creates an empty `VecDeque`.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::collections::VecDeque;
+    ///
+    /// let vector: VecDeque<u32> = VecDeque::new();
+    /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn new() -> VecDeque<T> {
         VecDeque::with_capacity(INITIAL_CAPACITY)
     }
 
     /// Creates an empty `VecDeque` with space for at least `n` elements.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::collections::VecDeque;
+    ///
+    /// let vector: VecDeque<u32> = VecDeque::with_capacity(10);
+    /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn with_capacity(n: usize) -> VecDeque<T> {
         // +1 since the ringbuffer always leaves one space empty
@@ -386,6 +402,8 @@ pub fn with_capacity(n: usize) -> VecDeque<T> {
 
     /// Retrieves an element in the `VecDeque` by index.
     ///
+    /// Element at index 0 is the front of the queue.
+    ///
     /// # Examples
     ///
     /// ```
@@ -409,6 +427,8 @@ pub fn get(&self, index: usize) -> Option<&T> {
 
     /// Retrieves an element in the `VecDeque` mutably by index.
     ///
+    /// Element at index 0 is the front of the queue.
+    ///
     /// # Examples
     ///
     /// ```
@@ -440,6 +460,8 @@ pub fn get_mut(&mut self, index: usize) -> Option<&mut T> {
     ///
     /// Fails if there is no element with either index.
     ///
+    /// Element at index 0 is the front of the queue.
+    ///
     /// # Examples
     ///
     /// ```
@@ -696,6 +718,25 @@ pub fn iter_mut(&mut self) -> IterMut<T> {
 
     /// Returns a pair of slices which contain, in order, the contents of the
     /// `VecDeque`.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::collections::VecDeque;
+    ///
+    /// let mut vector: VecDeque<u32> = VecDeque::new();
+    ///
+    /// vector.push_back(0);
+    /// vector.push_back(1);
+    /// vector.push_back(2);
+    ///
+    /// assert_eq!(vector.as_slices(), (&[0u32, 1, 2] as &[u32], &[] as &[u32]));
+    ///
+    /// vector.push_front(10);
+    /// vector.push_front(9);
+    ///
+    /// assert_eq!(vector.as_slices(), (&[9u32, 10] as &[u32], &[0u32, 1, 2] as &[u32]));
+    /// ```
     #[inline]
     #[stable(feature = "deque_extras_15", since = "1.5.0")]
     pub fn as_slices(&self) -> (&[T], &[T]) {
@@ -715,6 +756,24 @@ pub fn as_slices(&self) -> (&[T], &[T]) {
 
     /// Returns a pair of slices which contain, in order, the contents of the
     /// `VecDeque`.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::collections::VecDeque;
+    ///
+    /// let mut vector: VecDeque<u32> = VecDeque::new();
+    ///
+    /// vector.push_back(0);
+    /// vector.push_back(1);
+    ///
+    /// vector.push_front(10);
+    /// vector.push_front(9);
+    ///
+    /// vector.as_mut_slices().0[0] = 42;
+    /// vector.as_mut_slices().1[0] = 24;
+    /// assert_eq!(vector.as_slices(), (&[42u32, 10] as &[u32], &[24u32, 1] as &[u32]));
+    /// ```
     #[inline]
     #[stable(feature = "deque_extras_15", since = "1.5.0")]
     pub fn as_mut_slices(&mut self) -> (&mut [T], &mut [T]) {
@@ -789,7 +848,7 @@ pub fn is_empty(&self) -> bool {
     ///
     /// ```
     /// use std::collections::VecDeque;
-
+    ///
     /// let mut v: VecDeque<_> = vec![1, 2, 3].into_iter().collect();
     /// assert_eq!(vec![3].into_iter().collect::<VecDeque<_>>(), v.drain(2..).collect());
     /// assert_eq!(vec![1, 2].into_iter().collect::<VecDeque<_>>(), v);
@@ -875,6 +934,22 @@ pub fn clear(&mut self) {
 
     /// Returns `true` if the `VecDeque` contains an element equal to the
     /// given value.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(vec_deque_contains)]
+    ///
+    /// use std::collections::VecDeque;
+    ///
+    /// let mut vector: VecDeque<u32> = VecDeque::new();
+    ///
+    /// vector.push_back(0);
+    /// vector.push_back(1);
+    ///
+    /// assert_eq!(vector.contains(&1), true);
+    /// assert_eq!(vector.contains(&10), false);
+    /// ```
     #[unstable(feature = "vec_deque_contains", reason = "recently added",
                issue = "32630")]
     pub fn contains(&self, x: &T) -> bool
@@ -1111,6 +1186,8 @@ fn is_contiguous(&self) -> bool {
     ///
     /// Returns `None` if `index` is out of bounds.
     ///
+    /// Element at index 0 is the front of the queue.
+    ///
     /// # Examples
     ///
     /// ```
@@ -1145,6 +1222,8 @@ pub fn swap_remove_back(&mut self, index: usize) -> Option<T> {
     ///
     /// Returns `None` if `index` is out of bounds.
     ///
+    /// Element at index 0 is the front of the queue.
+    ///
     /// # Examples
     ///
     /// ```
@@ -1176,6 +1255,8 @@ pub fn swap_remove_front(&mut self, index: usize) -> Option<T> {
     /// end is closer to the insertion point will be moved to make room,
     /// and all the affected elements will be moved to new positions.
     ///
+    /// Element at index 0 is the front of the queue.
+    ///
     /// # Panics
     ///
     /// Panics if `index` is greater than `VecDeque`'s length
@@ -1403,7 +1484,10 @@ pub fn insert(&mut self, index: usize, value: T) {
     /// room, and all the affected elements will be moved to new positions.
     /// Returns `None` if `index` is out of bounds.
     ///
+    /// Element at index 0 is the front of the queue.
+    ///
     /// # Examples
+    ///
     /// ```
     /// use std::collections::VecDeque;
     ///
@@ -1581,6 +1665,8 @@ pub fn remove(&mut self, index: usize) -> Option<T> {
     ///
     /// Note that the capacity of `self` does not change.
     ///
+    /// Element at index 0 is the front of the queue.
+    ///
     /// # Panics
     ///
     /// Panics if `at > len`
index 895a679fc3dccf76b1d7efae56248e31733b3f54..e5eb8f21382bebd55d1779d3be20fb0b8b868695 100644 (file)
@@ -980,15 +980,19 @@ pub fn pad(&mut self, s: &str) -> Result {
             return self.buf.write_str(s);
         }
         // The `precision` field can be interpreted as a `max-width` for the
-        // string being formatted
-        if let Some(max) = self.precision {
-            // If there's a maximum width and our string is longer than
-            // that, then we must always have truncation. This is the only
-            // case where the maximum length will matter.
+        // string being formatted.
+        let s = if let Some(max) = self.precision {
+            // If our string is longer that the precision, then we must have
+            // truncation. However other flags like `fill`, `width` and `align`
+            // must act as always.
             if let Some((i, _)) = s.char_indices().skip(max).next() {
-                return self.buf.write_str(&s[..i])
+                &s[..i]
+            } else {
+                &s
             }
-        }
+        } else {
+            &s
+        };
         // The `width` field is more of a `min-width` parameter at this point.
         match self.width {
             // If we're under the maximum length, and there's no minimum length
index 9e3f7a4a84a814b318a9833f18fb6352fca5b1e3..27fdbd383017f08ea3e38350b47e0a6b9c9a84aa 100644 (file)
@@ -234,6 +234,16 @@ pub trait BuildHasher {
     type Hasher: Hasher;
 
     /// Creates a new hasher.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::collections::hash_map::RandomState;
+    /// use std::hash::BuildHasher;
+    ///
+    /// let s = RandomState::new();
+    /// let new_s = s.build_hasher();
+    /// ```
     #[stable(since = "1.7.0", feature = "build_hasher")]
     fn build_hasher(&self) -> Self::Hasher;
 }
index 1bdcc5bfe119dcce59a62e6fa9d4fe396d57d761..c645608dda7902ed3189dbe7ad6af7b948fdf1b4 100644 (file)
     /// Moves a value out of scope without running drop glue.
     pub fn forget<T>(_: T) -> ();
 
-    /// Unsafely transforms a value of one type into a value of another type.
+    /// Reinterprets the bits of a value of one type as another type; both types
+    /// must have the same size. Neither the original, nor the result, may be an
+    /// [invalid value] (../../nomicon/meet-safe-and-unsafe.html).
     ///
-    /// Both types must have the same size.
+    /// `transmute` is semantically equivalent to a bitwise move of one type
+    /// into another. It copies the bits from the destination type into the
+    /// source type, then forgets the original. It's equivalent to C's `memcpy`
+    /// under the hood, just like `transmute_copy`.
+    ///
+    /// `transmute` is incredibly unsafe. There are a vast number of ways to
+    /// cause undefined behavior with this function. `transmute` should be
+    /// the absolute last resort.
+    ///
+    /// The [nomicon](../../nomicon/transmutes.html) has additional
+    /// documentation.
     ///
     /// # Examples
     ///
+    /// There are a few things that `transmute` is really useful for.
+    ///
+    /// Getting the bitpattern of a floating point type (or, more generally,
+    /// type punning, when `T` and `U` aren't pointers):
+    ///
     /// ```
-    /// use std::mem;
+    /// let bitpattern = unsafe {
+    ///     std::mem::transmute::<f32, u32>(1.0)
+    /// };
+    /// assert_eq!(bitpattern, 0x3F800000);
+    /// ```
+    ///
+    /// Turning a pointer into a function pointer:
+    ///
+    /// ```
+    /// fn foo() -> i32 {
+    ///     0
+    /// }
+    /// let pointer = foo as *const ();
+    /// let function = unsafe {
+    ///     std::mem::transmute::<*const (), fn() -> i32>(pointer)
+    /// };
+    /// assert_eq!(function(), 0);
+    /// ```
+    ///
+    /// Extending a lifetime, or shortening an invariant lifetime; this is
+    /// advanced, very unsafe rust:
+    ///
+    /// ```
+    /// struct R<'a>(&'a i32);
+    /// unsafe fn extend_lifetime<'b>(r: R<'b>) -> R<'static> {
+    ///     std::mem::transmute::<R<'b>, R<'static>>(r)
+    /// }
+    ///
+    /// unsafe fn shorten_invariant_lifetime<'b, 'c>(r: &'b mut R<'static>)
+    ///                                              -> &'b mut R<'c> {
+    ///     std::mem::transmute::<&'b mut R<'static>, &'b mut R<'c>>(r)
+    /// }
+    /// ```
+    ///
+    /// # Alternatives
+    ///
+    /// However, many uses of `transmute` can be achieved through other means.
+    /// `transmute` can transform any type into any other, with just the caveat
+    /// that they're the same size, and often interesting results occur. Below
+    /// are common applications of `transmute` which can be replaced with safe
+    /// applications of `as`:
     ///
-    /// let array: &[u8] = unsafe { mem::transmute("Rust") };
-    /// assert_eq!(array, [82, 117, 115, 116]);
+    /// Turning a pointer into a `usize`:
+    ///
+    /// ```
+    /// let ptr = &0;
+    /// let ptr_num_transmute = unsafe {
+    ///     std::mem::transmute::<&i32, usize>(ptr)
+    /// };
+    /// // Use an `as` cast instead
+    /// let ptr_num_cast = ptr as *const i32 as usize;
+    /// ```
+    ///
+    /// Turning a `*mut T` into an `&mut T`:
+    ///
+    /// ```
+    /// let ptr: *mut i32 = &mut 0;
+    /// let ref_transmuted = unsafe {
+    ///     std::mem::transmute::<*mut i32, &mut i32>(ptr)
+    /// };
+    /// // Use a reborrow instead
+    /// let ref_casted = unsafe { &mut *ptr };
+    /// ```
+    ///
+    /// Turning an `&mut T` into an `&mut U`:
+    ///
+    /// ```
+    /// let ptr = &mut 0;
+    /// let val_transmuted = unsafe {
+    ///     std::mem::transmute::<&mut i32, &mut u32>(ptr)
+    /// };
+    /// // Now, put together `as` and reborrowing - note the chaining of `as`
+    /// // `as` is not transitive
+    /// let val_casts = unsafe { &mut *(ptr as *mut i32 as *mut u32) };
+    /// ```
+    ///
+    /// Turning an `&str` into an `&[u8]`:
+    ///
+    /// ```
+    /// // this is not a good way to do this.
+    /// let slice = unsafe { std::mem::transmute::<&str, &[u8]>("Rust") };
+    /// assert_eq!(slice, &[82, 117, 115, 116]);
+    /// // You could use `str::as_bytes`
+    /// let slice = "Rust".as_bytes();
+    /// assert_eq!(slice, &[82, 117, 115, 116]);
+    /// // Or, just use a byte string, if you have control over the string
+    /// // literal
+    /// assert_eq!(b"Rust", &[82, 117, 115, 116]);
+    /// ```
+    ///
+    /// Turning a `Vec<&T>` into a `Vec<Option<&T>>`:
+    ///
+    /// ```
+    /// let store = [0, 1, 2, 3];
+    /// let mut v_orig = store.iter().collect::<Vec<&i32>>();
+    /// // Using transmute: this is Undefined Behavior, and a bad idea.
+    /// // However, it is no-copy.
+    /// let v_transmuted = unsafe {
+    ///     std::mem::transmute::<Vec<&i32>, Vec<Option<&i32>>>(
+    ///         v_orig.clone())
+    /// };
+    /// // This is the suggested, safe way.
+    /// // It does copy the entire Vector, though, into a new array.
+    /// let v_collected = v_orig.clone()
+    ///                         .into_iter()
+    ///                         .map(|r| Some(r))
+    ///                         .collect::<Vec<Option<&i32>>>();
+    /// // The no-copy, unsafe way, still using transmute, but not UB.
+    /// // This is equivalent to the original, but safer, and reuses the
+    /// // same Vec internals. Therefore the new inner type must have the
+    /// // exact same size, and the same or lesser alignment, as the old
+    /// // type. The same caveats exist for this method as transmute, for
+    /// // the original inner type (`&i32`) to the converted inner type
+    /// // (`Option<&i32>`), so read the nomicon pages linked above.
+    /// let v_from_raw = unsafe {
+    ///     Vec::from_raw_parts(v_orig.as_mut_ptr(),
+    ///                         v_orig.len(),
+    ///                         v_orig.capacity())
+    /// };
+    /// std::mem::forget(v_orig);
+    /// ```
+    ///
+    /// Implementing `split_at_mut`:
+    ///
+    /// ```
+    /// use std::{slice, mem};
+    /// // There are multiple ways to do this; and there are multiple problems
+    /// // with the following, transmute, way.
+    /// fn split_at_mut_transmute<T>(slice: &mut [T], mid: usize)
+    ///                              -> (&mut [T], &mut [T]) {
+    ///     let len = slice.len();
+    ///     assert!(mid <= len);
+    ///     unsafe {
+    ///         let slice2 = mem::transmute::<&mut [T], &mut [T]>(slice);
+    ///         // first: transmute is not typesafe; all it checks is that T and
+    ///         // U are of the same size. Second, right here, you have two
+    ///         // mutable references pointing to the same memory.
+    ///         (&mut slice[0..mid], &mut slice2[mid..len])
+    ///     }
+    /// }
+    /// // This gets rid of the typesafety problems; `&mut *` will *only* give
+    /// // you an `&mut T` from an `&mut T` or `*mut T`.
+    /// fn split_at_mut_casts<T>(slice: &mut [T], mid: usize)
+    ///                          -> (&mut [T], &mut [T]) {
+    ///     let len = slice.len();
+    ///     assert!(mid <= len);
+    ///     unsafe {
+    ///         let slice2 = &mut *(slice as *mut [T]);
+    ///         // however, you still have two mutable references pointing to
+    ///         // the same memory.
+    ///         (&mut slice[0..mid], &mut slice2[mid..len])
+    ///     }
+    /// }
+    /// // This is how the standard library does it. This is the best method, if
+    /// // you need to do something like this
+    /// fn split_at_stdlib<T>(slice: &mut [T], mid: usize)
+    ///                       -> (&mut [T], &mut [T]) {
+    ///     let len = slice.len();
+    ///     assert!(mid <= len);
+    ///     unsafe {
+    ///         let ptr = slice.as_mut_ptr();
+    ///         // This now has three mutable references pointing at the same
+    ///         // memory. `slice`, the rvalue ret.0, and the rvalue ret.1.
+    ///         // `slice` is never used after `let ptr = ...`, and so one can
+    ///         // treat it as "dead", and therefore, you only have two real
+    ///         // mutable slices.
+    ///         (slice::from_raw_parts_mut(ptr, mid),
+    ///          slice::from_raw_parts_mut(ptr.offset(mid as isize), len - mid))
+    ///     }
+    /// }
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn transmute<T, U>(e: T) -> U;
index 896d1c6f30bf2cfe0509eb8103e05e89e7927a98..292d72dd362ad5c203497361cd9cda2febfaebc7 100644 (file)
@@ -386,10 +386,11 @@ pub trait Extend<A> {
 /// ```
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait DoubleEndedIterator: Iterator {
-    /// An iterator able to yield elements from both ends.
+    /// Removes and returns an element from the end of the iterator.
     ///
-    /// As this is the only method for this trait, the [trait-level] docs
-    /// contain more details.
+    /// Returns `None` when there are no more elements.
+    ///
+    /// The [trait-level] docs contain more details.
     ///
     /// [trait-level]: trait.DoubleEndedIterator.html
     ///
index 045c1f9feafc605d12a8e727e05f613dfa0873c1..fe508adb71380089d4e313114288410fcb6274eb 100644 (file)
 use self::Option::*;
 
 use clone::Clone;
+use convert::From;
 use default::Default;
 use iter::ExactSizeIterator;
 use iter::{Iterator, DoubleEndedIterator, FromIterator, IntoIterator};
@@ -754,6 +755,13 @@ fn into_iter(mut self) -> IterMut<'a, T> {
     }
 }
 
+#[stable(since = "1.12.0", feature = "option_from")]
+impl<T> From<T> for Option<T> {
+    fn from(val: T) -> Option<T> {
+        Some(val)
+    }
+}
+
 /////////////////////////////////////////////////////////////////////////////
 // The Option Iterators
 /////////////////////////////////////////////////////////////////////////////
index 4f11cac4eb2bec7b7e7ba6c4346e78fd5f3ed354..d8a11581c3b69be0de75868e938add9a8d135a20 100644 (file)
@@ -902,6 +902,8 @@ macro_rules! make_mut_slice {
 
 /// Immutable slice iterator
 ///
+/// This struct is created by the [`iter`] method on [slices].
+///
 /// # Examples
 ///
 /// Basic usage:
@@ -915,6 +917,9 @@ macro_rules! make_mut_slice {
 ///     println!("{}", element);
 /// }
 /// ```
+///
+/// [`iter`]: ../../std/primitive.slice.html#method.iter
+/// [slices]: ../../std/primitive.slice.html
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct Iter<'a, T: 'a> {
     ptr: *const T,
@@ -993,6 +998,8 @@ fn clone(&self) -> Iter<'a, T> { Iter { ptr: self.ptr, end: self.end, _marker: s
 
 /// Mutable slice iterator.
 ///
+/// This struct is created by the [`iter_mut`] method on [slices].
+///
 /// # Examples
 ///
 /// Basic usage:
@@ -1010,6 +1017,9 @@ fn clone(&self) -> Iter<'a, T> { Iter { ptr: self.ptr, end: self.end, _marker: s
 /// // We now have "[2, 3, 4]":
 /// println!("{:?}", slice);
 /// ```
+///
+/// [`iter_mut`]: ../../std/primitive.slice.html#method.iter_mut
+/// [slices]: ../../std/primitive.slice.html
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct IterMut<'a, T: 'a> {
     ptr: *mut T,
index 0ad6a74d1013c60b562ed1d9ff7467b2bedd5075..1e9e9e30f5cfe08df94cebfce04b840e9f23fca5 100644 (file)
 pub const DW_EH_PE_indirect: u8 = 0x80;
 
 #[derive(Copy, Clone)]
-pub struct EHContext {
+pub struct EHContext<'a> {
     pub ip: usize, // Current instruction pointer
     pub func_start: usize, // Address of the current function
-    pub text_start: usize, // Address of the code section
-    pub data_start: usize, // Address of the data section
+    pub get_text_start: &'a Fn() -> usize, // Get address of the code section
+    pub get_data_start: &'a Fn() -> usize, // Get address of the data section
 }
 
-pub unsafe fn find_landing_pad(lsda: *const u8, context: &EHContext) -> Option<usize> {
+pub enum EHAction {
+    None,
+    Cleanup(usize),
+    Catch(usize),
+    Terminate,
+}
+
+pub const USING_SJLJ_EXCEPTIONS: bool = cfg!(all(target_os = "ios", target_arch = "arm"));
+
+pub unsafe fn find_eh_action(lsda: *const u8, context: &EHContext) -> EHAction {
     if lsda.is_null() {
-        return None;
+        return EHAction::None;
     }
 
     let func_start = context.func_start;
@@ -77,32 +86,61 @@ pub unsafe fn find_landing_pad(lsda: *const u8, context: &EHContext) -> Option<u
     let call_site_encoding = reader.read::<u8>();
     let call_site_table_length = reader.read_uleb128();
     let action_table = reader.ptr.offset(call_site_table_length as isize);
-    // Return addresses point 1 byte past the call instruction, which could
-    // be in the next IP range.
-    let ip = context.ip - 1;
-
-    while reader.ptr < action_table {
-        let cs_start = read_encoded_pointer(&mut reader, context, call_site_encoding);
-        let cs_len = read_encoded_pointer(&mut reader, context, call_site_encoding);
-        let cs_lpad = read_encoded_pointer(&mut reader, context, call_site_encoding);
-        let cs_action = reader.read_uleb128();
-        // Callsite table is sorted by cs_start, so if we've passed the ip, we
-        // may stop searching.
-        if ip < func_start + cs_start {
-            break;
+    let ip = context.ip;
+
+    if !USING_SJLJ_EXCEPTIONS {
+        while reader.ptr < action_table {
+            let cs_start = read_encoded_pointer(&mut reader, context, call_site_encoding);
+            let cs_len = read_encoded_pointer(&mut reader, context, call_site_encoding);
+            let cs_lpad = read_encoded_pointer(&mut reader, context, call_site_encoding);
+            let cs_action = reader.read_uleb128();
+            // Callsite table is sorted by cs_start, so if we've passed the ip, we
+            // may stop searching.
+            if ip < func_start + cs_start {
+                break;
+            }
+            if ip < func_start + cs_start + cs_len {
+                if cs_lpad == 0 {
+                    return EHAction::None;
+                } else {
+                    let lpad = lpad_base + cs_lpad;
+                    return interpret_cs_action(cs_action, lpad);
+                }
+            }
         }
-        if ip < func_start + cs_start + cs_len {
-            if cs_lpad != 0 {
-                return Some(lpad_base + cs_lpad);
-            } else {
-                return None;
+        // Ip is not present in the table.  This should not hapen... but it does: issie #35011.
+        // So rather than returning EHAction::Terminate, we do this.
+        EHAction::None
+    } else {
+        // SjLj version:
+        // The "IP" is an index into the call-site table, with two exceptions:
+        // -1 means 'no-action', and 0 means 'terminate'.
+        match ip as isize {
+           -1 => return EHAction::None,
+            0 => return EHAction::Terminate,
+            _ => (),
+        }
+        let mut idx = ip;
+        loop {
+            let cs_lpad = reader.read_uleb128();
+            let cs_action = reader.read_uleb128();
+            idx -= 1;
+            if idx == 0 {
+                // Can never have null landing pad for sjlj -- that would have
+                // been indicated by a -1 call site index.
+                let lpad = (cs_lpad + 1) as usize;
+                return interpret_cs_action(cs_action, lpad);
             }
         }
     }
-    // IP range not found: gcc's C++ personality calls terminate() here,
-    // however the rest of the languages treat this the same as cs_lpad == 0.
-    // We follow this suit.
-    None
+}
+
+fn interpret_cs_action(cs_action: u64, lpad: usize) -> EHAction {
+    if cs_action == 0 {
+        EHAction::Cleanup(lpad)
+    } else {
+        EHAction::Catch(lpad)
+    }
 }
 
 #[inline]
@@ -140,18 +178,16 @@ unsafe fn read_encoded_pointer(reader: &mut DwarfReader,
         DW_EH_PE_absptr => 0,
         // relative to address of the encoded value, despite the name
         DW_EH_PE_pcrel => reader.ptr as usize,
-        DW_EH_PE_textrel => {
-            assert!(context.text_start != 0);
-            context.text_start
-        }
-        DW_EH_PE_datarel => {
-            assert!(context.data_start != 0);
-            context.data_start
-        }
         DW_EH_PE_funcrel => {
             assert!(context.func_start != 0);
             context.func_start
         }
+        DW_EH_PE_textrel => {
+            (*context.get_text_start)()
+        }
+        DW_EH_PE_datarel => {
+            (*context.get_data_start)()
+        }
         _ => panic!(),
     };
 
index 3c46072e17e1a7753aa3939c7676efb8e54ff2bd..cdf772ad3b825481231305ff6ae887bbb9048566 100644 (file)
@@ -106,117 +106,96 @@ fn rust_exception_class() -> uw::_Unwind_Exception_Class {
     0x4d4f5a_00_52555354
 }
 
-// We could implement our personality routine in Rust, however exception
-// info decoding is tedious.  More importantly, personality routines have to
-// handle various platform quirks, which are not fun to maintain.  For this
-// reason, we attempt to reuse personality routine of the C language:
-// __gcc_personality_v0.
-//
-// Since C does not support exception catching, __gcc_personality_v0 simply
-// always returns _URC_CONTINUE_UNWIND in search phase, and always returns
-// _URC_INSTALL_CONTEXT (i.e. "invoke cleanup code") in cleanup phase.
-//
-// This is pretty close to Rust's exception handling approach, except that Rust
-// does have a single "catch-all" handler at the bottom of each thread's stack.
-// So we have two versions of the personality routine:
-// - rust_eh_personality, used by all cleanup landing pads, which never catches,
-//   so the behavior of __gcc_personality_v0 is perfectly adequate there, and
-// - rust_eh_personality_catch, used only by rust_try(), which always catches.
-//
-// See also: rustc_trans::trans::intrinsic::trans_gnu_try
-
-#[cfg(all(not(target_arch = "arm"),
-          not(all(windows, target_arch = "x86_64"))))]
+// All targets, except ARM which uses a slightly different ABI (however, iOS goes here as it uses
+// SjLj unwinding).  Also, 64-bit Windows implementation lives in seh64_gnu.rs
+#[cfg(all(any(target_os = "ios", not(target_arch = "arm"))))]
 pub mod eabi {
     use unwind as uw;
-    use libc::c_int;
+    use libc::{c_int, uintptr_t};
+    use dwarf::eh::{EHContext, EHAction, find_eh_action};
 
-    extern "C" {
-        fn __gcc_personality_v0(version: c_int,
-                                actions: uw::_Unwind_Action,
-                                exception_class: uw::_Unwind_Exception_Class,
-                                ue_header: *mut uw::_Unwind_Exception,
-                                context: *mut uw::_Unwind_Context)
-                                -> uw::_Unwind_Reason_Code;
-    }
+    // Register ids were lifted from LLVM's TargetLowering::getExceptionPointerRegister()
+    // and TargetLowering::getExceptionSelectorRegister() for each architecture,
+    // then mapped to DWARF register numbers via register definition tables
+    // (typically <arch>RegisterInfo.td, search for "DwarfRegNum").
+    // See also http://llvm.org/docs/WritingAnLLVMBackend.html#defining-a-register.
 
-    #[lang = "eh_personality"]
-    #[no_mangle]
-    extern "C" fn rust_eh_personality(version: c_int,
-                                      actions: uw::_Unwind_Action,
-                                      exception_class: uw::_Unwind_Exception_Class,
-                                      ue_header: *mut uw::_Unwind_Exception,
-                                      context: *mut uw::_Unwind_Context)
-                                      -> uw::_Unwind_Reason_Code {
-        unsafe { __gcc_personality_v0(version, actions, exception_class, ue_header, context) }
-    }
+    #[cfg(target_arch = "x86")]
+    const UNWIND_DATA_REG: (i32, i32) = (0, 2); // EAX, EDX
 
-    #[lang = "eh_personality_catch"]
-    #[no_mangle]
-    pub extern "C" fn rust_eh_personality_catch(version: c_int,
-                                                actions: uw::_Unwind_Action,
-                                                exception_class: uw::_Unwind_Exception_Class,
-                                                ue_header: *mut uw::_Unwind_Exception,
-                                                context: *mut uw::_Unwind_Context)
-                                                -> uw::_Unwind_Reason_Code {
+    #[cfg(target_arch = "x86_64")]
+    const UNWIND_DATA_REG: (i32, i32) = (0, 1); // RAX, RDX
 
-        if (actions as c_int & uw::_UA_SEARCH_PHASE as c_int) != 0 {
-            // search phase
-            uw::_URC_HANDLER_FOUND // catch!
-        } else {
-            // cleanup phase
-            unsafe { __gcc_personality_v0(version, actions, exception_class, ue_header, context) }
-        }
-    }
-}
-
-// iOS on armv7 is using SjLj exceptions and therefore requires to use
-// a specialized personality routine: __gcc_personality_sj0
+    #[cfg(any(target_arch = "arm", target_arch = "aarch64"))]
+    const UNWIND_DATA_REG: (i32, i32) = (0, 1); // R0, R1 / X0, X1
 
-#[cfg(all(target_os = "ios", target_arch = "arm"))]
-pub mod eabi {
-    use unwind as uw;
-    use libc::c_int;
+    #[cfg(any(target_arch = "mips", target_arch = "mipsel"))]
+    const UNWIND_DATA_REG: (i32, i32) = (4, 5); // A0, A1
 
-    extern "C" {
-        fn __gcc_personality_sj0(version: c_int,
-                                 actions: uw::_Unwind_Action,
-                                 exception_class: uw::_Unwind_Exception_Class,
-                                 ue_header: *mut uw::_Unwind_Exception,
-                                 context: *mut uw::_Unwind_Context)
-                                 -> uw::_Unwind_Reason_Code;
-    }
+    #[cfg(any(target_arch = "powerpc", target_arch = "powerpc64"))]
+    const UNWIND_DATA_REG: (i32, i32) = (3, 4); // R3, R4 / X3, X4
 
+    // Based on GCC's C and C++ personality routines.  For reference, see:
+    // https://github.com/gcc-mirror/gcc/blob/master/libstdc++-v3/libsupc++/eh_personality.cc
+    // https://github.com/gcc-mirror/gcc/blob/trunk/libgcc/unwind-c.c
     #[lang = "eh_personality"]
     #[no_mangle]
-    pub extern "C" fn rust_eh_personality(version: c_int,
-                                          actions: uw::_Unwind_Action,
-                                          exception_class: uw::_Unwind_Exception_Class,
-                                          ue_header: *mut uw::_Unwind_Exception,
-                                          context: *mut uw::_Unwind_Context)
-                                          -> uw::_Unwind_Reason_Code {
-        unsafe { __gcc_personality_sj0(version, actions, exception_class, ue_header, context) }
+    #[allow(unused)]
+    unsafe extern "C" fn rust_eh_personality(version: c_int,
+                                             actions: uw::_Unwind_Action,
+                                             exception_class: uw::_Unwind_Exception_Class,
+                                             exception_object: *mut uw::_Unwind_Exception,
+                                             context: *mut uw::_Unwind_Context)
+                                             -> uw::_Unwind_Reason_Code {
+        if version != 1 {
+            return uw::_URC_FATAL_PHASE1_ERROR;
+        }
+        let lsda = uw::_Unwind_GetLanguageSpecificData(context) as *const u8;
+        let mut ip_before_instr: c_int = 0;
+        let ip = uw::_Unwind_GetIPInfo(context, &mut ip_before_instr);
+        let eh_context = EHContext {
+            // The return address points 1 byte past the call instruction,
+            // which could be in the next IP range in LSDA range table.
+            ip: if ip_before_instr != 0 { ip } else { ip - 1 },
+            func_start: uw::_Unwind_GetRegionStart(context),
+            get_text_start: &|| uw::_Unwind_GetTextRelBase(context),
+            get_data_start: &|| uw::_Unwind_GetDataRelBase(context),
+        };
+        let eh_action = find_eh_action(lsda, &eh_context);
+
+        if actions as i32 & uw::_UA_SEARCH_PHASE as i32 != 0 {
+            match eh_action {
+                EHAction::None | EHAction::Cleanup(_) => return uw::_URC_CONTINUE_UNWIND,
+                EHAction::Catch(_) => return uw::_URC_HANDLER_FOUND,
+                EHAction::Terminate => return uw::_URC_FATAL_PHASE1_ERROR,
+            }
+        } else {
+            match eh_action {
+                EHAction::None => return uw::_URC_CONTINUE_UNWIND,
+                EHAction::Cleanup(lpad) | EHAction::Catch(lpad) => {
+                    uw::_Unwind_SetGR(context, UNWIND_DATA_REG.0, exception_object as uintptr_t);
+                    uw::_Unwind_SetGR(context, UNWIND_DATA_REG.1, 0);
+                    uw::_Unwind_SetIP(context, lpad);
+                    return uw::_URC_INSTALL_CONTEXT;
+                }
+                EHAction::Terminate => return uw::_URC_FATAL_PHASE2_ERROR,
+            }
+        }
     }
 
+    #[cfg(stage0)]
     #[lang = "eh_personality_catch"]
     #[no_mangle]
-    pub extern "C" fn rust_eh_personality_catch(version: c_int,
-                                                actions: uw::_Unwind_Action,
-                                                exception_class: uw::_Unwind_Exception_Class,
-                                                ue_header: *mut uw::_Unwind_Exception,
-                                                context: *mut uw::_Unwind_Context)
-                                                -> uw::_Unwind_Reason_Code {
-        if (actions as c_int & uw::_UA_SEARCH_PHASE as c_int) != 0 {
-            // search phase
-            uw::_URC_HANDLER_FOUND // catch!
-        } else {
-            // cleanup phase
-            unsafe { __gcc_personality_sj0(version, actions, exception_class, ue_header, context) }
-        }
+    pub unsafe extern "C" fn rust_eh_personality_catch(version: c_int,
+                                                       actions: uw::_Unwind_Action,
+                                                       exception_class: uw::_Unwind_Exception_Class,
+                                                       ue_header: *mut uw::_Unwind_Exception,
+                                                       context: *mut uw::_Unwind_Context)
+                                                       -> uw::_Unwind_Reason_Code {
+        rust_eh_personality(version, actions, exception_class, ue_header, context)
     }
 }
 
-
 // ARM EHABI uses a slightly different personality routine signature,
 // but otherwise works the same.
 #[cfg(all(target_arch = "arm", not(target_os = "ios")))]
index b765ee6f81cf9a70468f9e02cfe3849c73a8ff08..11dd9befe0a82e940da630f68317591ef960187b 100644 (file)
 // Entry point for raising an exception, just delegates to the platform-specific
 // implementation.
 #[no_mangle]
+#[unwind]
 pub unsafe extern "C" fn __rust_start_panic(data: usize, vtable: usize) -> u32 {
     imp::panic(mem::transmute(raw::TraitObject {
         data: data as *mut (),
index 56801e8cb6bcf3d5583a7ca409a2aac4a8db965d..7dc428871b387f2e83792d468706fa8b6c99675f 100644 (file)
@@ -19,7 +19,7 @@
 use core::any::Any;
 use core::intrinsics;
 use core::ptr;
-use dwarf::eh;
+use dwarf::eh::{EHContext, EHAction, find_eh_action};
 use windows as c;
 
 // Define our exception codes:
@@ -81,6 +81,7 @@ pub unsafe fn cleanup(ptr: *mut u8) -> Box<Any + Send> {
 // This is considered acceptable, because the behavior of throwing exceptions
 // through a C ABI boundary is undefined.
 
+#[cfg(stage0)]
 #[lang = "eh_personality_catch"]
 #[cfg(not(test))]
 unsafe extern "C" fn rust_eh_personality_catch(exceptionRecord: *mut c::EXCEPTION_RECORD,
@@ -132,11 +133,17 @@ pub unsafe fn cleanup(ptr: *mut u8) -> Box<Any + Send> {
 }
 
 unsafe fn find_landing_pad(dc: &c::DISPATCHER_CONTEXT) -> Option<usize> {
-    let eh_ctx = eh::EHContext {
-        ip: dc.ControlPc as usize,
+    let eh_ctx = EHContext {
+        // The return address points 1 byte past the call instruction,
+        // which could be in the next IP range in LSDA range table.
+        ip: dc.ControlPc as usize - 1,
         func_start: dc.ImageBase as usize + (*dc.FunctionEntry).BeginAddress as usize,
-        text_start: dc.ImageBase as usize,
-        data_start: 0,
+        get_text_start: &|| dc.ImageBase as usize,
+        get_data_start: &|| unimplemented!(),
     };
-    eh::find_landing_pad(dc.HandlerData, &eh_ctx)
+    match find_eh_action(dc.HandlerData, &eh_ctx) {
+        EHAction::None => None,
+        EHAction::Cleanup(lpad) | EHAction::Catch(lpad) => Some(lpad),
+        EHAction::Terminate => intrinsics::abort(),
+    }
 }
index 96ecad629f543f24d7a7e586a351e7163375b4c1..511cc32d2e1e6cfeb47d00fa65076fba5445de64 100644 (file)
@@ -83,7 +83,7 @@
 use infer::{self, TypeOrigin};
 use middle::region;
 use ty::subst;
-use ty::{self, Ty, TyCtxt, TypeFoldable};
+use ty::{self, TyCtxt, TypeFoldable};
 use ty::{Region, ReFree};
 use ty::error::TypeError;
 
@@ -462,52 +462,6 @@ fn append_to_same_regions(same_regions: &mut Vec<SameRegions>,
         }
     }
 
-    fn report_type_error(&self,
-                         trace: TypeTrace<'tcx>,
-                         terr: &TypeError<'tcx>)
-                         -> DiagnosticBuilder<'tcx> {
-        let (expected, found) = match self.values_str(&trace.values) {
-            Some(v) => v,
-            None => {
-                return self.tcx.sess.diagnostic().struct_dummy(); /* derived error */
-            }
-        };
-
-        let is_simple_error = if let &TypeError::Sorts(ref values) = terr {
-            values.expected.is_primitive() && values.found.is_primitive()
-        } else {
-            false
-        };
-
-        let mut err = struct_span_err!(self.tcx.sess,
-                                       trace.origin.span(),
-                                       E0308,
-                                       "{}",
-                                       trace.origin);
-
-        if !is_simple_error || check_old_school() {
-            err.note_expected_found(&"type", &expected, &found);
-        }
-
-        err.span_label(trace.origin.span(), &terr);
-
-        self.check_and_note_conflicting_crates(&mut err, terr, trace.origin.span());
-
-        match trace.origin {
-            TypeOrigin::MatchExpressionArm(_, arm_span, source) => match source {
-                hir::MatchSource::IfLetDesugar{..} => {
-                    err.span_note(arm_span, "`if let` arm with an incompatible type");
-                }
-                _ => {
-                    err.span_note(arm_span, "match arm with an incompatible type");
-                }
-            },
-            _ => ()
-        }
-
-        err
-    }
-
     /// Adds a note if the types come from similarly named crates
     fn check_and_note_conflicting_crates(&self,
                                          err: &mut DiagnosticBuilder,
@@ -550,42 +504,102 @@ fn check_and_note_conflicting_crates(&self,
         }
     }
 
+    fn note_error_origin(&self,
+                         err: &mut DiagnosticBuilder<'tcx>,
+                         origin: &TypeOrigin)
+    {
+        match origin {
+            &TypeOrigin::MatchExpressionArm(_, arm_span, source) => match source {
+                hir::MatchSource::IfLetDesugar {..} => {
+                    err.span_note(arm_span, "`if let` arm with an incompatible type");
+                }
+                _ => {
+                    err.span_note(arm_span, "match arm with an incompatible type");
+                }
+            },
+            _ => ()
+        }
+    }
+
+    pub fn note_type_err(&self,
+                         diag: &mut DiagnosticBuilder<'tcx>,
+                         origin: TypeOrigin,
+                         values: Option<ValuePairs<'tcx>>,
+                         terr: &TypeError<'tcx>)
+    {
+        let expected_found = match values {
+            None => None,
+            Some(values) => match self.values_str(&values) {
+                Some((expected, found)) => Some((expected, found)),
+                None => {
+                    // Derived error. Cancel the emitter.
+                    self.tcx.sess.diagnostic().cancel(diag);
+                    return
+                }
+            }
+        };
+
+        let span = origin.span();
+
+        let mut is_simple_error = false;
+
+        if let Some((expected, found)) = expected_found {
+            is_simple_error = if let &TypeError::Sorts(ref values) = terr {
+                values.expected.is_primitive() && values.found.is_primitive()
+            } else {
+                false
+            };
+
+            if !is_simple_error || check_old_school() {
+                diag.note_expected_found(&"type", &expected, &found);
+            }
+        }
+
+        if !is_simple_error && check_old_school() {
+            diag.span_note(span, &format!("{}", terr));
+        } else {
+            diag.span_label(span, &terr);
+        }
+
+        self.note_error_origin(diag, &origin);
+        self.check_and_note_conflicting_crates(diag, terr, span);
+        self.tcx.note_and_explain_type_err(diag, terr, span);
+    }
+
     pub fn report_and_explain_type_error(&self,
                                          trace: TypeTrace<'tcx>,
                                          terr: &TypeError<'tcx>)
-                                         -> DiagnosticBuilder<'tcx> {
-        let span = trace.origin.span();
-        let mut err = self.report_type_error(trace, terr);
-        self.tcx.note_and_explain_type_err(&mut err, terr, span);
-        err
+                                         -> DiagnosticBuilder<'tcx>
+    {
+        // FIXME: do we want to use a different error code for each origin?
+        let mut diag = struct_span_err!(
+            self.tcx.sess, trace.origin.span(), E0308,
+            "{}", trace.origin.as_failure_str()
+        );
+        self.note_type_err(&mut diag, trace.origin, Some(trace.values), terr);
+        diag
     }
 
-    /// Returns a string of the form "expected `{}`, found `{}`", or None if this is a derived
-    /// error.
+    /// Returns a string of the form "expected `{}`, found `{}`".
     fn values_str(&self, values: &ValuePairs<'tcx>) -> Option<(String, String)> {
         match *values {
             infer::Types(ref exp_found) => self.expected_found_str(exp_found),
             infer::TraitRefs(ref exp_found) => self.expected_found_str(exp_found),
-            infer::PolyTraitRefs(ref exp_found) => self.expected_found_str(exp_found)
+            infer::PolyTraitRefs(ref exp_found) => self.expected_found_str(exp_found),
         }
     }
 
-    fn expected_found_str<T: fmt::Display + Resolvable<'tcx> + TypeFoldable<'tcx>>(
+    fn expected_found_str<T: fmt::Display + TypeFoldable<'tcx>>(
         &self,
         exp_found: &ty::error::ExpectedFound<T>)
         -> Option<(String, String)>
     {
-        let expected = exp_found.expected.resolve(self);
-        if expected.references_error() {
-            return None;
-        }
-
-        let found = exp_found.found.resolve(self);
-        if found.references_error() {
+        let exp_found = self.resolve_type_vars_if_possible(exp_found);
+        if exp_found.references_error() {
             return None;
         }
 
-        Some((format!("{}", expected), format!("{}", found)))
+        Some((format!("{}", exp_found.expected), format!("{}", exp_found.found)))
     }
 
     fn report_generic_bound_failure(&self,
@@ -1608,59 +1622,21 @@ fn report_inference_failure(&self,
     fn note_region_origin(&self, err: &mut DiagnosticBuilder, origin: &SubregionOrigin<'tcx>) {
         match *origin {
             infer::Subtype(ref trace) => {
-                let desc = match trace.origin {
-                    TypeOrigin::Misc(_) => {
-                        "types are compatible"
-                    }
-                    TypeOrigin::MethodCompatCheck(_) => {
-                        "method type is compatible with trait"
-                    }
-                    TypeOrigin::ExprAssignable(_) => {
-                        "expression is assignable"
-                    }
-                    TypeOrigin::RelateTraitRefs(_) => {
-                        "traits are compatible"
-                    }
-                    TypeOrigin::RelateSelfType(_) => {
-                        "self type matches impl self type"
-                    }
-                    TypeOrigin::RelateOutputImplTypes(_) => {
-                        "trait type parameters matches those \
-                                 specified on the impl"
-                    }
-                    TypeOrigin::MatchExpressionArm(_, _, _) => {
-                        "match arms have compatible types"
-                    }
-                    TypeOrigin::IfExpression(_) => {
-                        "if and else have compatible types"
-                    }
-                    TypeOrigin::IfExpressionWithNoElse(_) => {
-                        "if may be missing an else clause"
-                    }
-                    TypeOrigin::RangeExpression(_) => {
-                        "start and end of range have compatible types"
-                    }
-                    TypeOrigin::EquatePredicate(_) => {
-                        "equality where clause is satisfied"
-                    }
-                };
-
-                match self.values_str(&trace.values) {
-                    Some((expected, found)) => {
-                        err.span_note(
-                            trace.origin.span(),
-                            &format!("...so that {} (expected {}, found {})",
-                                    desc, expected, found));
-                    }
-                    None => {
-                        // Really should avoid printing this error at
-                        // all, since it is derived, but that would
-                        // require more refactoring than I feel like
-                        // doing right now. - nmatsakis
-                        err.span_note(
-                            trace.origin.span(),
-                            &format!("...so that {}", desc));
-                    }
+                if let Some((expected, found)) = self.values_str(&trace.values) {
+                    // FIXME: do we want a "the" here?
+                    err.span_note(
+                        trace.origin.span(),
+                        &format!("...so that {} (expected {}, found {})",
+                                 trace.origin.as_requirement_str(), expected, found));
+                } else {
+                    // FIXME: this really should be handled at some earlier stage. Our
+                    // handling of region checking when type errors are present is
+                    // *terrible*.
+
+                    err.span_note(
+                        trace.origin.span(),
+                        &format!("...so that {}",
+                                 trace.origin.as_requirement_str()));
                 }
             }
             infer::Reborrow(span) => {
@@ -1803,32 +1779,6 @@ fn note_region_origin(&self, err: &mut DiagnosticBuilder, origin: &SubregionOrig
     }
 }
 
-pub trait Resolvable<'tcx> {
-    fn resolve<'a, 'gcx>(&self, infcx: &InferCtxt<'a, 'gcx, 'tcx>) -> Self;
-}
-
-impl<'tcx> Resolvable<'tcx> for Ty<'tcx> {
-    fn resolve<'a, 'gcx>(&self, infcx: &InferCtxt<'a, 'gcx, 'tcx>) -> Ty<'tcx> {
-        infcx.resolve_type_vars_if_possible(self)
-    }
-}
-
-impl<'tcx> Resolvable<'tcx> for ty::TraitRef<'tcx> {
-    fn resolve<'a, 'gcx>(&self, infcx: &InferCtxt<'a, 'gcx, 'tcx>)
-                         -> ty::TraitRef<'tcx> {
-        infcx.resolve_type_vars_if_possible(self)
-    }
-}
-
-impl<'tcx> Resolvable<'tcx> for ty::PolyTraitRef<'tcx> {
-    fn resolve<'a, 'gcx>(&self,
-                         infcx: &InferCtxt<'a, 'gcx, 'tcx>)
-                         -> ty::PolyTraitRef<'tcx>
-    {
-        infcx.resolve_type_vars_if_possible(self)
-    }
-}
-
 fn lifetimes_in_scope<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
                                       scope_id: ast::NodeId)
                                       -> Vec<hir::LifetimeDef> {
index 2ea2978b2940d858a482a408b98c424a4d2394b8..87882c5528ec163cd60fce350bc9071066f9c639 100644 (file)
@@ -32,7 +32,7 @@
 use ty::{TyVid, IntVid, FloatVid};
 use ty::{self, Ty, TyCtxt};
 use ty::error::{ExpectedFound, TypeError, UnconstrainedNumeric};
-use ty::fold::TypeFoldable;
+use ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
 use ty::relate::{Relate, RelateResult, TypeRelation};
 use traits::{self, PredicateObligations, ProjectionMode};
 use rustc_data_structures::unify::{self, UnificationTable};
@@ -196,12 +196,6 @@ pub enum TypeOrigin {
     // FIXME(eddyb) #11161 is the original Expr required?
     ExprAssignable(Span),
 
-    // Relating trait refs when resolving vtables
-    RelateTraitRefs(Span),
-
-    // Relating self types when resolving vtables
-    RelateSelfType(Span),
-
     // Relating trait type parameters to those found in impl etc
     RelateOutputImplTypes(Span),
 
@@ -219,16 +213,26 @@ pub enum TypeOrigin {
 
     // `where a == b`
     EquatePredicate(Span),
+
+    // `main` has wrong type
+    MainFunctionType(Span),
+
+    // `start` has wrong type
+    StartFunctionType(Span),
+
+    // intrinsic has wrong type
+    IntrinsicType(Span),
+
+    // method receiver
+    MethodReceiver(Span),
 }
 
 impl TypeOrigin {
-    fn as_str(&self) -> &'static str {
+    fn as_failure_str(&self) -> &'static str {
         match self {
             &TypeOrigin::Misc(_) |
-            &TypeOrigin::RelateSelfType(_) |
             &TypeOrigin::RelateOutputImplTypes(_) |
             &TypeOrigin::ExprAssignable(_) => "mismatched types",
-            &TypeOrigin::RelateTraitRefs(_) => "mismatched traits",
             &TypeOrigin::MethodCompatCheck(_) => "method not compatible with trait",
             &TypeOrigin::MatchExpressionArm(_, _, source) => match source {
                 hir::MatchSource::IfLetDesugar{..} => "`if let` arms have incompatible types",
@@ -238,13 +242,31 @@ fn as_str(&self) -> &'static str {
             &TypeOrigin::IfExpressionWithNoElse(_) => "if may be missing an else clause",
             &TypeOrigin::RangeExpression(_) => "start and end of range have incompatible types",
             &TypeOrigin::EquatePredicate(_) => "equality predicate not satisfied",
+            &TypeOrigin::MainFunctionType(_) => "main function has wrong type",
+            &TypeOrigin::StartFunctionType(_) => "start function has wrong type",
+            &TypeOrigin::IntrinsicType(_) => "intrinsic has wrong type",
+            &TypeOrigin::MethodReceiver(_) => "mismatched method receiver",
         }
     }
-}
 
-impl fmt::Display for TypeOrigin {
-    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(),fmt::Error> {
-        fmt::Display::fmt(self.as_str(), f)
+    fn as_requirement_str(&self) -> &'static str {
+        match self {
+            &TypeOrigin::Misc(_) => "types are compatible",
+            &TypeOrigin::MethodCompatCheck(_) => "method type is compatible with trait",
+            &TypeOrigin::ExprAssignable(_) => "expression is assignable",
+            &TypeOrigin::RelateOutputImplTypes(_) => {
+                "trait type parameters matches those specified on the impl"
+            }
+            &TypeOrigin::MatchExpressionArm(_, _, _) => "match arms have compatible types",
+            &TypeOrigin::IfExpression(_) => "if and else have compatible types",
+            &TypeOrigin::IfExpressionWithNoElse(_) => "if missing an else returns ()",
+            &TypeOrigin::RangeExpression(_) => "start and end of range have compatible types",
+            &TypeOrigin::EquatePredicate(_) => "equality where clause is satisfied",
+            &TypeOrigin::MainFunctionType(_) => "`main` function has the correct type",
+            &TypeOrigin::StartFunctionType(_) => "`start` function has the correct type",
+            &TypeOrigin::IntrinsicType(_) => "intrinsic has the correct type",
+            &TypeOrigin::MethodReceiver(_) => "method receiver has the correct type",
+        }
     }
 }
 
@@ -1468,104 +1490,50 @@ pub fn fully_resolve<T:TypeFoldable<'tcx>>(&self, value: &T) -> FixupResult<T> {
     // error type, meaning that an error occurred when typechecking this expression),
     // this is a derived error. The error cascaded from another error (that was already
     // reported), so it's not useful to display it to the user.
-    // The following four methods -- type_error_message_str, type_error_message_str_with_expected,
-    // type_error_message, and report_mismatched_types -- implement this logic.
+    // The following methods implement this logic.
     // They check if either the actual or expected type is TyError, and don't print the error
     // in this case. The typechecker should only ever report type errors involving mismatched
-    // types using one of these four methods, and should not call span_err directly for such
+    // types using one of these methods, and should not call span_err directly for such
     // errors.
-    pub fn type_error_message_str<M>(&self,
-                                     sp: Span,
-                                     mk_msg: M,
-                                     actual_ty: String,
-                                     err: Option<&TypeError<'tcx>>)
-        where M: FnOnce(Option<String>, String) -> String,
-    {
-        self.type_error_message_str_with_expected(sp, mk_msg, None, actual_ty, err)
-    }
-
-    pub fn type_error_struct_str<M>(&self,
-                                    sp: Span,
-                                    mk_msg: M,
-                                    actual_ty: String,
-                                    err: Option<&TypeError<'tcx>>)
-                                    -> DiagnosticBuilder<'tcx>
-        where M: FnOnce(Option<String>, String) -> String,
-    {
-        self.type_error_struct_str_with_expected(sp, mk_msg, None, actual_ty, err)
-    }
-
-    pub fn type_error_message_str_with_expected<M>(&self,
-                                                   sp: Span,
-                                                   mk_msg: M,
-                                                   expected_ty: Option<Ty<'tcx>>,
-                                                   actual_ty: String,
-                                                   err: Option<&TypeError<'tcx>>)
-        where M: FnOnce(Option<String>, String) -> String,
-    {
-        self.type_error_struct_str_with_expected(sp, mk_msg, expected_ty, actual_ty, err)
-            .emit();
-    }
-
-    pub fn type_error_struct_str_with_expected<M>(&self,
-                                                  sp: Span,
-                                                  mk_msg: M,
-                                                  expected_ty: Option<Ty<'tcx>>,
-                                                  actual_ty: String,
-                                                  err: Option<&TypeError<'tcx>>)
-                                                  -> DiagnosticBuilder<'tcx>
-        where M: FnOnce(Option<String>, String) -> String,
-    {
-        debug!("hi! expected_ty = {:?}, actual_ty = {}", expected_ty, actual_ty);
-
-        let resolved_expected = expected_ty.map(|e_ty| self.resolve_type_vars_if_possible(&e_ty));
-
-        if !resolved_expected.references_error() {
-            let error_str = err.map_or("".to_string(), |t_err| {
-                format!(" ({})", t_err)
-            });
-
-            let mut db = self.tcx.sess.struct_span_err(sp, &format!("{}{}",
-                mk_msg(resolved_expected.map(|t| self.ty_to_string(t)), actual_ty),
-                error_str));
-
-            if let Some(err) = err {
-                self.tcx.note_and_explain_type_err(&mut db, err, sp);
-            }
-            db
-        } else {
-            self.tcx.sess.diagnostic().struct_dummy()
-        }
-    }
 
     pub fn type_error_message<M>(&self,
                                  sp: Span,
                                  mk_msg: M,
-                                 actual_ty: Ty<'tcx>,
-                                 err: Option<&TypeError<'tcx>>)
+                                 actual_ty: Ty<'tcx>)
         where M: FnOnce(String) -> String,
     {
-        self.type_error_struct(sp, mk_msg, actual_ty, err).emit();
+        self.type_error_struct(sp, mk_msg, actual_ty).emit();
     }
 
+    // FIXME: this results in errors without an error code. Deprecate?
     pub fn type_error_struct<M>(&self,
                                 sp: Span,
                                 mk_msg: M,
-                                actual_ty: Ty<'tcx>,
-                                err: Option<&TypeError<'tcx>>)
+                                actual_ty: Ty<'tcx>)
                                 -> DiagnosticBuilder<'tcx>
         where M: FnOnce(String) -> String,
+    {
+        self.type_error_struct_with_diag(sp, |actual_ty| {
+            self.tcx.sess.struct_span_err(sp, &mk_msg(actual_ty))
+        }, actual_ty)
+    }
+
+    pub fn type_error_struct_with_diag<M>(&self,
+                                          sp: Span,
+                                          mk_diag: M,
+                                          actual_ty: Ty<'tcx>)
+                                          -> DiagnosticBuilder<'tcx>
+        where M: FnOnce(String) -> DiagnosticBuilder<'tcx>,
     {
         let actual_ty = self.resolve_type_vars_if_possible(&actual_ty);
+        debug!("type_error_struct_with_diag({:?}, {:?})", sp, actual_ty);
 
         // Don't report an error if actual type is TyError.
         if actual_ty.references_error() {
             return self.tcx.sess.diagnostic().struct_dummy();
         }
 
-        self.type_error_struct_str(sp,
-            move |_e, a| { mk_msg(a) },
-            self.ty_to_string(actual_ty), err)
+        mk_diag(self.ty_to_string(actual_ty))
     }
 
     pub fn report_mismatched_types(&self,
@@ -1833,14 +1801,16 @@ pub fn span(&self) -> Span {
             TypeOrigin::MethodCompatCheck(span) => span,
             TypeOrigin::ExprAssignable(span) => span,
             TypeOrigin::Misc(span) => span,
-            TypeOrigin::RelateTraitRefs(span) => span,
-            TypeOrigin::RelateSelfType(span) => span,
             TypeOrigin::RelateOutputImplTypes(span) => span,
             TypeOrigin::MatchExpressionArm(match_span, _, _) => match_span,
             TypeOrigin::IfExpression(span) => span,
             TypeOrigin::IfExpressionWithNoElse(span) => span,
             TypeOrigin::RangeExpression(span) => span,
             TypeOrigin::EquatePredicate(span) => span,
+            TypeOrigin::MainFunctionType(span) => span,
+            TypeOrigin::StartFunctionType(span) => span,
+            TypeOrigin::IntrinsicType(span) => span,
+            TypeOrigin::MethodReceiver(span) => span,
         }
     }
 }
@@ -1891,3 +1861,50 @@ pub fn span(&self) -> Span {
         }
     }
 }
+
+impl<'tcx> TypeFoldable<'tcx> for TypeOrigin {
+    fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, _folder: &mut F) -> Self {
+        self.clone()
+    }
+
+    fn super_visit_with<V: TypeVisitor<'tcx>>(&self, _visitor: &mut V) -> bool {
+        false
+    }
+}
+
+impl<'tcx> TypeFoldable<'tcx> for ValuePairs<'tcx> {
+    fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
+        match *self {
+            ValuePairs::Types(ref ef) => {
+                ValuePairs::Types(ef.fold_with(folder))
+            }
+            ValuePairs::TraitRefs(ref ef) => {
+                ValuePairs::TraitRefs(ef.fold_with(folder))
+            }
+            ValuePairs::PolyTraitRefs(ref ef) => {
+                ValuePairs::PolyTraitRefs(ef.fold_with(folder))
+            }
+        }
+    }
+
+    fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
+        match *self {
+            ValuePairs::Types(ref ef) => ef.visit_with(visitor),
+            ValuePairs::TraitRefs(ref ef) => ef.visit_with(visitor),
+            ValuePairs::PolyTraitRefs(ref ef) => ef.visit_with(visitor),
+        }
+    }
+}
+
+impl<'tcx> TypeFoldable<'tcx> for TypeTrace<'tcx> {
+    fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
+        TypeTrace {
+            origin: self.origin.fold_with(folder),
+            values: self.values.fold_with(folder)
+        }
+    }
+
+    fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
+        self.origin.visit_with(visitor) || self.values.visit_with(visitor)
+    }
+}
index 65b97abfccbd75f5cb456115f24431e70340939a..a0c2416d24cff97d58815849830aec33e81ba55a 100644 (file)
@@ -747,6 +747,8 @@ fn parse_panic_strategy(slot: &mut PanicStrategy, v: Option<&str>) -> bool {
           "set the MIR optimization level (0-3)"),
     dump_mir: Option<String> = (None, parse_opt_string,
           "dump MIR state at various points in translation"),
+    dump_mir_dir: Option<String> = (None, parse_opt_string,
+          "the directory the MIR is dumped into"),
     orbit: bool = (false, parse_bool,
           "get MIR where it belongs - everywhere; most importantly, in orbit"),
 }
index fa9bc7c83680c45009f1bf09f72685b38d7e1f09..5901c42b525826881c2746a00e16c45c9bed4847 100644 (file)
@@ -126,20 +126,14 @@ pub fn struct_span_err<'a, S: Into<MultiSpan>>(&'a self,
                                                    sp: S,
                                                    msg: &str)
                                                    -> DiagnosticBuilder<'a>  {
-        match split_msg_into_multilines(msg) {
-            Some(ref msg) => self.diagnostic().struct_span_err(sp, msg),
-            None => self.diagnostic().struct_span_err(sp, msg),
-        }
+        self.diagnostic().struct_span_err(sp, msg)
     }
     pub fn struct_span_err_with_code<'a, S: Into<MultiSpan>>(&'a self,
                                                              sp: S,
                                                              msg: &str,
                                                              code: &str)
                                                              -> DiagnosticBuilder<'a>  {
-        match split_msg_into_multilines(msg) {
-            Some(ref msg) => self.diagnostic().struct_span_err_with_code(sp, msg, code),
-            None => self.diagnostic().struct_span_err_with_code(sp, msg, code),
-        }
+        self.diagnostic().struct_span_err_with_code(sp, msg, code)
     }
     pub fn struct_err<'a>(&'a self, msg: &str) -> DiagnosticBuilder<'a>  {
         self.diagnostic().struct_err(msg)
@@ -178,16 +172,10 @@ pub fn span_err_or_warn<S: Into<MultiSpan>>(&self, is_warning: bool, sp: S, msg:
         }
     }
     pub fn span_err<S: Into<MultiSpan>>(&self, sp: S, msg: &str) {
-        match split_msg_into_multilines(msg) {
-            Some(msg) => self.diagnostic().span_err(sp, &msg),
-            None => self.diagnostic().span_err(sp, msg)
-        }
+        self.diagnostic().span_err(sp, msg)
     }
     pub fn span_err_with_code<S: Into<MultiSpan>>(&self, sp: S, msg: &str, code: &str) {
-        match split_msg_into_multilines(msg) {
-            Some(msg) => self.diagnostic().span_err_with_code(sp, &msg, code),
-            None => self.diagnostic().span_err_with_code(sp, msg, code)
-        }
+        self.diagnostic().span_err_with_code(sp, &msg, code)
     }
     pub fn err(&self, msg: &str) {
         self.diagnostic().err(msg)
@@ -343,67 +331,6 @@ pub fn host_filesearch(&self, kind: PathKind) -> filesearch::FileSearch {
     }
 }
 
-fn split_msg_into_multilines(msg: &str) -> Option<String> {
-    // 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") &&
-        !msg.contains("has an incompatible type for trait") {
-            return None
-    }
-    let first = msg.match_indices("expected").filter(|s| {
-        let last = msg[..s.0].chars().rev().next();
-        last == Some(' ') || last == Some('(')
-    }).map(|(a, b)| (a - 1, a + b.len()));
-    let second = msg.match_indices("found").filter(|s| {
-        msg[..s.0].chars().rev().next() == Some(' ')
-    }).map(|(a, b)| (a - 1, a + b.len()));
-
-    let mut new_msg = String::new();
-    let mut head = 0;
-
-    // Insert `\n` before expected and found.
-    for (pos1, pos2) in first.zip(second) {
-        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..];
-    let third = tail.find("(values differ")
-                   .or(tail.find("(lifetime"))
-                   .or(tail.find("(cyclic type of infinite size"));
-    // Insert `\n` before any remaining messages which match.
-    if let Some(pos) = third {
-        // 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].trim_right() + // prefix
-                  "\n" +                     // insert before paren
-                  &tail[pos..];              // append the tail
-
-        tail = "";
-    }
-
-    new_msg.push_str(tail);
-    return Some(new_msg);
-}
-
 pub fn build_session(sopts: config::Options,
                      dep_graph: &DepGraph,
                      local_crate_source_file: Option<PathBuf>,
index 3b9ecb88258540cd011bb543b07be1a8bd5145e7..67ad887530eb318ccabe450784dc9480e11e5297 100644 (file)
@@ -26,8 +26,9 @@
 
 use fmt_macros::{Parser, Piece, Position};
 use hir::def_id::DefId;
-use infer::{InferCtxt};
+use infer::{self, InferCtxt, TypeOrigin};
 use ty::{self, ToPredicate, ToPolyTraitRef, Ty, TyCtxt, TypeFoldable};
+use ty::error::ExpectedFound;
 use ty::fast_reject;
 use ty::fold::TypeFolder;
 use ty::subst::{self, Subst, TypeSpace};
@@ -107,24 +108,63 @@ fn report_projection_error(&self,
         let predicate =
             self.resolve_type_vars_if_possible(&obligation.predicate);
 
-        if !predicate.references_error() {
-            if let Some(warning_node_id) = warning_node_id {
-                self.tcx.sess.add_lint(
-                    ::lint::builtin::UNSIZED_IN_TUPLE,
-                    warning_node_id,
+        if predicate.references_error() {
+            return
+        }
+        if let Some(warning_node_id) = warning_node_id {
+            self.tcx.sess.add_lint(
+                ::lint::builtin::UNSIZED_IN_TUPLE,
+                warning_node_id,
+                obligation.cause.span,
+                format!("type mismatch resolving `{}`: {}",
+                        predicate,
+                        error.err));
+            return
+        }
+        self.probe(|_| {
+            let origin = TypeOrigin::Misc(obligation.cause.span);
+            let err_buf;
+            let mut err = &error.err;
+            let mut values = None;
+
+            // try to find the mismatched types to report the error with.
+            //
+            // this can fail if the problem was higher-ranked, in which
+            // cause I have no idea for a good error message.
+            if let ty::Predicate::Projection(ref data) = predicate {
+                let mut selcx = SelectionContext::new(self);
+                let (data, _) = self.replace_late_bound_regions_with_fresh_var(
                     obligation.cause.span,
-                    format!("type mismatch resolving `{}`: {}",
-                            predicate,
-                            error.err));
-            } else {
-                let mut err = struct_span_err!(self.tcx.sess, obligation.cause.span, E0271,
-                                               "type mismatch resolving `{}`: {}",
-                                               predicate,
-                                               error.err);
-                self.note_obligation_cause(&mut err, obligation);
-                err.emit();
+                    infer::LateBoundRegionConversionTime::HigherRankedType,
+                    data);
+                let normalized = super::normalize_projection_type(
+                    &mut selcx,
+                    data.projection_ty,
+                    obligation.cause.clone(),
+                    0
+                );
+                let origin = TypeOrigin::Misc(obligation.cause.span);
+                if let Err(error) = self.eq_types(
+                    false, origin,
+                    data.ty, normalized.value
+                ) {
+                    values = Some(infer::ValuePairs::Types(ExpectedFound {
+                        expected: normalized.value,
+                        found: data.ty,
+                    }));
+                    err_buf = error;
+                    err = &err_buf;
+                }
             }
-        }
+
+            let mut diag = struct_span_err!(
+                self.tcx.sess, origin.span(), E0271,
+                "type mismatch resolving `{}`", predicate
+            );
+            self.note_type_err(&mut diag, origin, values, err);
+            self.note_obligation_cause(&mut diag, obligation);
+            diag.emit();
+        });
     }
 
     fn impl_substs(&self,
index 1e2920ca87ea6d712b3a2f64839160f1fcc7a542..16a54c20925deda7b8417a3747be29e6e0289bec 100644 (file)
@@ -1018,3 +1018,16 @@ fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
         self.generics.visit_with(visitor) || self.ty.visit_with(visitor)
     }
 }
+
+impl<'tcx, T: TypeFoldable<'tcx>> TypeFoldable<'tcx> for ty::error::ExpectedFound<T> {
+    fn super_fold_with<'gcx: 'tcx, F: TypeFolder<'gcx, 'tcx>>(&self, folder: &mut F) -> Self {
+        ty::error::ExpectedFound {
+            expected: self.expected.fold_with(folder),
+            found: self.found.fold_with(folder),
+        }
+    }
+
+    fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
+        self.expected.visit_with(visitor) || self.found.visit_with(visitor)
+    }
+}
index 794e4d4996c9422ab649bd38e81be71e962aaf8c..ceb17e53a5552e41540b94e3d850f72d4d08b07c 100644 (file)
@@ -22,7 +22,7 @@ pub fn target() -> Target {
         target_vendor: "unknown".to_string(),
         options: TargetOptions {
             cpu: "mips32r2".to_string(),
-            features: "+mips32r2,+soft-float".to_string(),
+            features: "+mips32r2".to_string(),
             max_atomic_width: 32,
             ..super::linux_base::opts()
         },
index 2163a8a1689b601e7240806ed25563cf88294852..99bc26848025ec0ec030a28776c5b3634226a455 100644 (file)
@@ -70,20 +70,18 @@ macro_rules! supported_targets {
         /// List of supported targets
         pub const TARGETS: &'static [&'static str] = &[$($triple),*];
 
-        // this would use a match if stringify! were allowed in pattern position
         fn load_specific(target: &str) -> Option<Target> {
-            let target = target.replace("-", "_");
-            if false { }
-            $(
-                else if target == stringify!($module) {
-                    let mut t = $module::target();
-                    t.options.is_builtin = true;
-                    debug!("Got builtin target: {:?}", t);
-                    return Some(t);
-                }
-            )*
-
-            None
+            match target {
+                $(
+                    $triple => {
+                        let mut t = $module::target();
+                        t.options.is_builtin = true;
+                        debug!("Got builtin target: {:?}", t);
+                        Some(t)
+                    },
+                )+
+                _ => None
+            }
         }
     )
 }
index 01872bbe3c04996a87089b757b494c253dd42c3d..8967672548b101b3b35a01f04b8207ab8b5d1198 100644 (file)
@@ -14,6 +14,7 @@ serialize = { path = "../libserialize" }
 rustc = { path = "../librustc" }
 rustc_back = { path = "../librustc_back" }
 rustc_const_math = { path = "../librustc_const_math" }
+rustc_errors = { path = "../librustc_errors" }
 syntax = { path = "../libsyntax" }
 graphviz = { path = "../libgraphviz" }
 syntax_pos = { path = "../libsyntax_pos" }
\ No newline at end of file
index 0de00d9d7f631edc634f6b757ac106361f1a5062..915a0cf0bdc7301ecda143b9d51745a827453b37 100644 (file)
@@ -17,6 +17,7 @@
 use ::{eval_const_expr, eval_const_expr_partial, compare_const_vals};
 use ::{const_expr_to_pat, lookup_const_by_id};
 use ::EvalHint::ExprTypeChecked;
+use eval::report_const_eval_err;
 use rustc::hir::def::*;
 use rustc::hir::def_id::{DefId};
 use rustc::middle::expr_use_visitor::{ConsumeMode, Delegate, ExprUseVisitor};
@@ -42,6 +43,7 @@
 use rustc::hir::fold::{Folder, noop_fold_pat};
 use rustc::hir::print::pat_to_string;
 use syntax::ptr::P;
+use rustc::util::common::ErrorReported;
 use rustc::util::nodemap::FnvHashMap;
 
 pub const DUMMY_WILD_PAT: &'static Pat = &Pat {
@@ -279,13 +281,7 @@ fn check_for_static_nan(cx: &MatchCheckCtxt, pat: &Pat) {
                 Ok(_) => {}
 
                 Err(err) => {
-                    let mut diag = struct_span_err!(cx.tcx.sess, err.span, E0471,
-                                                    "constant evaluation error: {}",
-                                                    err.description());
-                    if !p.span.contains(err.span) {
-                        diag.span_note(p.span, "in pattern here");
-                    }
-                    diag.emit();
+                    report_const_eval_err(cx.tcx, &err, p.span, "pattern").emit();
                 }
             }
         }
@@ -838,22 +834,19 @@ pub fn constructor_arity(_cx: &MatchCheckCtxt, ctor: &Constructor, ty: Ty) -> us
     }
 }
 
-fn range_covered_by_constructor(ctor: &Constructor,
-                                from: &ConstVal, to: &ConstVal) -> Option<bool> {
+fn range_covered_by_constructor(tcx: TyCtxt, span: Span,
+                                ctor: &Constructor,
+                                from: &ConstVal, to: &ConstVal)
+                                -> Result<bool, ErrorReported> {
     let (c_from, c_to) = match *ctor {
         ConstantValue(ref value)        => (value, value),
         ConstantRange(ref from, ref to) => (from, to),
-        Single                          => return Some(true),
+        Single                          => return Ok(true),
         _                               => bug!()
     };
-    let cmp_from = compare_const_vals(c_from, from);
-    let cmp_to = compare_const_vals(c_to, to);
-    match (cmp_from, cmp_to) {
-        (Some(cmp_from), Some(cmp_to)) => {
-            Some(cmp_from != Ordering::Less && cmp_to != Ordering::Greater)
-        }
-        _ => None
-    }
+    let cmp_from = compare_const_vals(tcx, span, c_from, from)?;
+    let cmp_to = compare_const_vals(tcx, span, c_to, to)?;
+    Ok(cmp_from != Ordering::Less && cmp_to != Ordering::Greater)
 }
 
 fn wrap_pat<'a, 'b, 'tcx>(cx: &MatchCheckCtxt<'b, 'tcx>,
@@ -965,13 +958,12 @@ pub fn specialize<'a, 'b, 'tcx>(
                 Some(vec![(pat, Some(mt.ty))])
             } else {
                 let expr_value = eval_const_expr(cx.tcx, &expr);
-                match range_covered_by_constructor(constructor, &expr_value, &expr_value) {
-                    Some(true) => Some(vec![]),
-                    Some(false) => None,
-                    None => {
-                        span_err!(cx.tcx.sess, pat_span, E0298, "mismatched types between arms");
-                        None
-                    }
+                match range_covered_by_constructor(
+                    cx.tcx, expr.span, constructor, &expr_value, &expr_value
+                ) {
+                    Ok(true) => Some(vec![]),
+                    Ok(false) => None,
+                    Err(ErrorReported) => None,
                 }
             }
         }
@@ -979,13 +971,12 @@ pub fn specialize<'a, 'b, 'tcx>(
         PatKind::Range(ref from, ref to) => {
             let from_value = eval_const_expr(cx.tcx, &from);
             let to_value = eval_const_expr(cx.tcx, &to);
-            match range_covered_by_constructor(constructor, &from_value, &to_value) {
-                Some(true) => Some(vec![]),
-                Some(false) => None,
-                None => {
-                    span_err!(cx.tcx.sess, pat_span, E0299, "mismatched types between arms");
-                    None
-                }
+            match range_covered_by_constructor(
+                cx.tcx, pat_span, constructor, &from_value, &to_value
+            ) {
+                Ok(true) => Some(vec![]),
+                Ok(false) => None,
+                Err(ErrorReported) => None,
             }
         }
 
index f2abdf831a3b8fdbdae8c6033bbc17085e38b3cc..45414c33c075448640ef116443fcaf58f23d4e0d 100644 (file)
@@ -551,44 +551,46 @@ enum Method { GET, POST }
 See also https://github.com/rust-lang/rust/issues/14587
 "##,
 
-E0306: r##"
-In an array literal `[x; N]`, `N` is the number of elements in the array. This
-must be an unsigned integer. Erroneous code example:
+E0080: r##"
+This error indicates that the compiler was unable to sensibly evaluate an
+constant expression that had to be evaluated. Attempting to divide by 0
+or causing integer overflow are two ways to induce this error. For example:
 
 ```compile_fail
-let x = [0i32; true]; // error: expected positive integer for repeat count,
-                      //        found boolean
+enum Enum {
+    X = (1 << 500),
+    Y = (1 / 0)
+}
 ```
 
-Working example:
+Ensure that the expressions given can be evaluated as the desired integer type.
+See the FFI section of the Reference for more information about using a custom
+integer type:
 
-```
-let x = [0i32; 2];
-```
+https://doc.rust-lang.org/reference.html#ffi-attributes
 "##,
 
-E0307: r##"
-The length of an array is part of its type. For this reason, this length must
-be a compile-time constant. Erroneous code example:
+
+E0306: r##"
+In an array literal `[x; N]`, `N` is the number of elements in the array. This
+must be an unsigned integer. Erroneous code example:
 
 ```compile_fail
-    let len = 10;
-    let x = [0i32; len]; // error: expected constant integer for repeat count,
-                         //        found variable
+let x = [0i32; true]; // error: expected positive integer for repeat count,
+                      //        found boolean
 ```
 
 Working example:
 
 ```
-let x = [0i32; 10];
+let x = [0i32; 2];
 ```
 "##,
-
 }
 
 
 register_diagnostics! {
-E0298, // mismatched types between arms
-E0299, // mismatched types between arms
-E0471, // constant evaluation error: ..
+    E0298, // cannot compare constants
+//  E0299, // mismatched types between arms
+//  E0471, // constant evaluation error (in pattern)
 }
index a3c707e82a0ff45e45be5c74e951c184296f8cb5..dd21bb17a2da95e810945c02d3f3f0323e2fcb15 100644 (file)
@@ -25,6 +25,7 @@
 use rustc::ty::{self, Ty, TyCtxt, subst};
 use rustc::ty::util::IntTypeExt;
 use rustc::traits::ProjectionMode;
+use rustc::util::common::ErrorReported;
 use rustc::util::nodemap::NodeMap;
 use rustc::lint;
 
@@ -43,6 +44,7 @@
 use std::collections::hash_map::Entry::Vacant;
 
 use rustc_const_math::*;
+use rustc_errors::{DiagnosticBuilder, check_old_school};
 
 macro_rules! math {
     ($e:expr, $op:expr) => {
@@ -338,20 +340,71 @@ pub fn const_expr_to_pat<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     Ok(P(hir::Pat { id: expr.id, node: pat, span: span }))
 }
 
+pub fn report_const_eval_err<'a, 'tcx>(
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
+    err: &ConstEvalErr,
+    primary_span: Span,
+    primary_kind: &str)
+    -> DiagnosticBuilder<'tcx>
+{
+    let mut err = err;
+    while let &ConstEvalErr { kind: ErroneousReferencedConstant(box ref i_err), .. } = err {
+        err = i_err;
+    }
+
+    let mut diag = struct_span_err!(tcx.sess, err.span, E0080, "constant evaluation error");
+    note_const_eval_err(tcx, err, primary_span, primary_kind, &mut diag);
+    diag
+}
+
+pub fn fatal_const_eval_err<'a, 'tcx>(
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
+    err: &ConstEvalErr,
+    primary_span: Span,
+    primary_kind: &str)
+    -> !
+{
+    report_const_eval_err(tcx, err, primary_span, primary_kind).emit();
+    tcx.sess.abort_if_errors();
+    unreachable!()
+}
+
+pub fn note_const_eval_err<'a, 'tcx>(
+    _tcx: TyCtxt<'a, 'tcx, 'tcx>,
+    err: &ConstEvalErr,
+    primary_span: Span,
+    primary_kind: &str,
+    diag: &mut DiagnosticBuilder)
+{
+    match err.description() {
+        ConstEvalErrDescription::Simple(message) => {
+            if check_old_school() {
+                diag.note(&message);
+            } else {
+                diag.span_label(err.span, &message);
+            }
+        }
+    }
+
+    if !primary_span.contains(err.span) {
+        diag.span_note(primary_span,
+                       &format!("for {} here", primary_kind));
+    }
+}
+
 pub fn eval_const_expr<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                  e: &Expr) -> ConstVal {
     match eval_const_expr_partial(tcx, e, ExprTypeChecked, None) {
         Ok(r) => r,
         // non-const path still needs to be a fatal error, because enums are funky
         Err(s) => {
+            report_const_eval_err(tcx, &s, e.span, "expression").emit();
             match s.kind {
                 NonConstPath |
-                UnimplementedConstVal(_) => tcx.sess.span_fatal(s.span, &s.description()),
-                _ => {
-                    tcx.sess.span_err(s.span, &s.description());
-                    Dummy
-                }
+                UnimplementedConstVal(_) => tcx.sess.abort_if_errors(),
+                _ => {}
             }
+            Dummy
         },
     }
 }
@@ -400,6 +453,7 @@ pub enum ErrKind {
     IntermediateUnsignedNegative,
     /// Expected, Got
     TypeMismatch(String, ConstInt),
+
     BadType(ConstVal),
     ErroneousReferencedConstant(Box<ConstEvalErr>),
     CharCast(ConstInt),
@@ -411,57 +465,79 @@ fn from(err: ConstMathErr) -> ErrKind {
     }
 }
 
+#[derive(Clone, Debug)]
+pub enum ConstEvalErrDescription<'a> {
+    Simple(Cow<'a, str>),
+}
+
+impl<'a> ConstEvalErrDescription<'a> {
+    /// Return a one-line description of the error, for lints and such
+    pub fn into_oneline(self) -> Cow<'a, str> {
+        match self {
+            ConstEvalErrDescription::Simple(simple) => simple,
+        }
+    }
+}
+
 impl ConstEvalErr {
-    pub fn description(&self) -> Cow<str> {
+    pub fn description(&self) -> ConstEvalErrDescription {
         use self::ErrKind::*;
+        use self::ConstEvalErrDescription::*;
+
+        macro_rules! simple {
+            ($msg:expr) => ({ Simple($msg.into_cow()) });
+            ($fmt:expr, $($arg:tt)+) => ({
+                Simple(format!($fmt, $($arg)+).into_cow())
+            })
+        }
 
         match self.kind {
-            CannotCast => "can't cast this type".into_cow(),
-            CannotCastTo(s) => format!("can't cast this type to {}", s).into_cow(),
-            InvalidOpForInts(_) =>  "can't do this op on integrals".into_cow(),
-            InvalidOpForBools(_) =>  "can't do this op on bools".into_cow(),
-            InvalidOpForFloats(_) => "can't do this op on floats".into_cow(),
-            InvalidOpForIntUint(..) => "can't do this op on an isize and usize".into_cow(),
-            InvalidOpForUintInt(..) => "can't do this op on a usize and isize".into_cow(),
-            NegateOn(ref const_val) => format!("negate on {}", const_val.description()).into_cow(),
-            NotOn(ref const_val) => format!("not on {}", const_val.description()).into_cow(),
-            CallOn(ref const_val) => format!("call on {}", const_val.description()).into_cow(),
-
-            MissingStructField  => "nonexistent struct field".into_cow(),
-            NonConstPath        => "non-constant path in constant expression".into_cow(),
+            CannotCast => simple!("can't cast this type"),
+            CannotCastTo(s) => simple!("can't cast this type to {}", s),
+            InvalidOpForInts(_) =>  simple!("can't do this op on integrals"),
+            InvalidOpForBools(_) =>  simple!("can't do this op on bools"),
+            InvalidOpForFloats(_) => simple!("can't do this op on floats"),
+            InvalidOpForIntUint(..) => simple!("can't do this op on an isize and usize"),
+            InvalidOpForUintInt(..) => simple!("can't do this op on a usize and isize"),
+            NegateOn(ref const_val) => simple!("negate on {}", const_val.description()),
+            NotOn(ref const_val) => simple!("not on {}", const_val.description()),
+            CallOn(ref const_val) => simple!("call on {}", const_val.description()),
+
+            MissingStructField  => simple!("nonexistent struct field"),
+            NonConstPath        => simple!("non-constant path in constant expression"),
             UnimplementedConstVal(what) =>
-                format!("unimplemented constant expression: {}", what).into_cow(),
-            UnresolvedPath => "unresolved path in constant expression".into_cow(),
-            ExpectedConstTuple => "expected constant tuple".into_cow(),
-            ExpectedConstStruct => "expected constant struct".into_cow(),
-            TupleIndexOutOfBounds => "tuple index out of bounds".into_cow(),
-            IndexedNonVec => "indexing is only supported for arrays".into_cow(),
-            IndexNegative => "indices must be non-negative integers".into_cow(),
-            IndexNotInt => "indices must be integers".into_cow(),
+                simple!("unimplemented constant expression: {}", what),
+            UnresolvedPath => simple!("unresolved path in constant expression"),
+            ExpectedConstTuple => simple!("expected constant tuple"),
+            ExpectedConstStruct => simple!("expected constant struct"),
+            TupleIndexOutOfBounds => simple!("tuple index out of bounds"),
+            IndexedNonVec => simple!("indexing is only supported for arrays"),
+            IndexNegative => simple!("indices must be non-negative integers"),
+            IndexNotInt => simple!("indices must be integers"),
             IndexOutOfBounds { len, index } => {
-                format!("index out of bounds: the len is {} but the index is {}",
-                        len, index).into_cow()
+                simple!("index out of bounds: the len is {} but the index is {}",
+                        len, index)
             }
-            RepeatCountNotNatural => "repeat count must be a natural number".into_cow(),
-            RepeatCountNotInt => "repeat count must be integers".into_cow(),
+            RepeatCountNotNatural => simple!("repeat count must be a natural number"),
+            RepeatCountNotInt => simple!("repeat count must be integers"),
 
-            MiscBinaryOp => "bad operands for binary".into_cow(),
-            MiscCatchAll => "unsupported constant expr".into_cow(),
-            IndexOpFeatureGated => "the index operation on const values is unstable".into_cow(),
-            Math(ref err) => err.description().into_cow(),
+            MiscBinaryOp => simple!("bad operands for binary"),
+            MiscCatchAll => simple!("unsupported constant expr"),
+            IndexOpFeatureGated => simple!("the index operation on const values is unstable"),
+            Math(ref err) => Simple(err.description().into_cow()),
 
-            IntermediateUnsignedNegative => "during the computation of an unsigned a negative \
-                                             number was encountered. This is most likely a bug in\
-                                             the constant evaluator".into_cow(),
+            IntermediateUnsignedNegative => simple!(
+                "during the computation of an unsigned a negative \
+                 number was encountered. This is most likely a bug in\
+                 the constant evaluator"),
 
             TypeMismatch(ref expected, ref got) => {
-                format!("mismatched types: expected `{}`, found `{}`",
-                        expected, got.description()).into_cow()
+                simple!("expected {}, found {}", expected, got.description())
             },
-            BadType(ref i) => format!("value of wrong type: {:?}", i).into_cow(),
-            ErroneousReferencedConstant(_) => "could not evaluate referenced constant".into_cow(),
+            BadType(ref i) => simple!("value of wrong type: {:?}", i),
+            ErroneousReferencedConstant(_) => simple!("could not evaluate referenced constant"),
             CharCast(ref got) => {
-                format!("only `u8` can be cast as `char`, not `{}`", got.description()).into_cow()
+                simple!("only `u8` can be cast as `char`, not `{}`", got.description())
             },
         }
     }
@@ -1105,11 +1181,25 @@ fn cast_const<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, val: ConstVal, ty: ty::Ty)
         Float(f) => cast_const_float(tcx, f, ty),
         Char(c) => cast_const_int(tcx, Infer(c as u64), ty),
         Function(_) => Err(UnimplementedConstVal("casting fn pointers")),
-        ByteStr(_) => match ty.sty {
+        ByteStr(b) => match ty.sty {
             ty::TyRawPtr(_) => {
                 Err(ErrKind::UnimplementedConstVal("casting a bytestr to a raw ptr"))
             },
-            ty::TyRef(..) => Err(ErrKind::UnimplementedConstVal("casting a bytestr to slice")),
+            ty::TyRef(_, ty::TypeAndMut { ref ty, mutbl: hir::MutImmutable }) => match ty.sty {
+                ty::TyArray(ty, n) if ty == tcx.types.u8 && n == b.len() => Ok(ByteStr(b)),
+                ty::TySlice(_) => {
+                    Err(ErrKind::UnimplementedConstVal("casting a bytestr to slice"))
+                },
+                _ => Err(CannotCast),
+            },
+            _ => Err(CannotCast),
+        },
+        Str(s) => match ty.sty {
+            ty::TyRawPtr(_) => Err(ErrKind::UnimplementedConstVal("casting a str to a raw ptr")),
+            ty::TyRef(_, ty::TypeAndMut { ref ty, mutbl: hir::MutImmutable }) => match ty.sty {
+                ty::TyStr => Ok(Str(s)),
+                _ => Err(CannotCast),
+            },
             _ => Err(CannotCast),
         },
         _ => Err(CannotCast),
@@ -1185,8 +1275,10 @@ fn parse_float(num: &str, fty_hint: Option<ast::FloatTy>, span: Span) -> ConstFl
     })
 }
 
-pub fn compare_const_vals(a: &ConstVal, b: &ConstVal) -> Option<Ordering> {
-    match (a, b) {
+pub fn compare_const_vals(tcx: TyCtxt, span: Span, a: &ConstVal, b: &ConstVal)
+                          -> Result<Ordering, ErrorReported>
+{
+    let result = match (a, b) {
         (&Integral(a), &Integral(b)) => a.try_cmp(b).ok(),
         (&Float(a), &Float(b)) => a.try_cmp(b).ok(),
         (&Str(ref a), &Str(ref b)) => Some(a.cmp(b)),
@@ -1194,62 +1286,82 @@ pub fn compare_const_vals(a: &ConstVal, b: &ConstVal) -> Option<Ordering> {
         (&ByteStr(ref a), &ByteStr(ref b)) => Some(a.cmp(b)),
         (&Char(a), &Char(ref b)) => Some(a.cmp(b)),
         _ => None,
+    };
+
+    match result {
+        Some(result) => Ok(result),
+        None => {
+            // FIXME: can this ever be reached?
+            span_err!(tcx.sess, span, E0298,
+                      "type mismatch comparing {} and {}",
+                      a.description(),
+                      b.description());
+            Err(ErrorReported)
+        }
     }
 }
 
 pub fn compare_lit_exprs<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                                   span: Span,
                                    a: &Expr,
-                                   b: &Expr) -> Option<Ordering> {
+                                   b: &Expr) -> Result<Ordering, ErrorReported> {
     let a = match eval_const_expr_partial(tcx, a, ExprTypeChecked, None) {
         Ok(a) => a,
         Err(e) => {
-            tcx.sess.span_err(a.span, &e.description());
-            return None;
+            report_const_eval_err(tcx, &e, a.span, "expression").emit();
+            return Err(ErrorReported);
         }
     };
     let b = match eval_const_expr_partial(tcx, b, ExprTypeChecked, None) {
         Ok(b) => b,
         Err(e) => {
-            tcx.sess.span_err(b.span, &e.description());
-            return None;
+            report_const_eval_err(tcx, &e, b.span, "expression").emit();
+            return Err(ErrorReported);
         }
     };
-    compare_const_vals(&a, &b)
+    compare_const_vals(tcx, span, &a, &b)
 }
 
 
-/// Returns the repeat count for a repeating vector expression.
-pub fn eval_repeat_count<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                                   count_expr: &hir::Expr) -> usize {
+/// Returns the value of the length-valued expression
+pub fn eval_length<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                             count_expr: &hir::Expr,
+                             reason: &str)
+                             -> Result<usize, ErrorReported>
+{
     let hint = UncheckedExprHint(tcx.types.usize);
     match eval_const_expr_partial(tcx, count_expr, hint, None) {
         Ok(Integral(Usize(count))) => {
             let val = count.as_u64(tcx.sess.target.uint_type);
             assert_eq!(val as usize as u64, val);
-            val as usize
+            Ok(val as usize)
         },
         Ok(const_val) => {
             span_err!(tcx.sess, count_expr.span, E0306,
-                      "expected positive integer for repeat count, found {}",
+                      "expected usize for {}, found {}",
+                      reason,
                       const_val.description());
-            0
+            Err(ErrorReported)
         }
         Err(err) => {
-            let err_msg = match count_expr.node {
+            let mut diag = report_const_eval_err(
+                tcx, &err, count_expr.span, reason);
+
+            match count_expr.node {
                 hir::ExprPath(None, hir::Path {
                     global: false,
                     ref segments,
                     ..
-                }) if segments.len() == 1 =>
-                    format!("found variable"),
-                _ => match err.kind {
-                    MiscCatchAll => format!("but found {}", err.description()),
-                    _ => format!("but {}", err.description())
+                }) if segments.len() == 1 => {
+                    if let Some(Def::Local(..)) = tcx.expect_def_or_none(count_expr.id) {
+                        diag.note(&format!("`{}` is a variable", segments[0].name));
+                    }
                 }
-            };
-            span_err!(tcx.sess, count_expr.span, E0307,
-                "expected constant integer for repeat count, {}", err_msg);
-            0
+                _ => {}
+            }
+
+            diag.emit();
+            Err(ErrorReported)
         }
     }
 }
index 726ba4fc1924fd48f3b3fc25b7c0d38df381c0f3..a6714c178e7cf68c46e750891dd39703f285c401 100644 (file)
@@ -36,6 +36,7 @@
 #[macro_use] extern crate rustc;
 extern crate rustc_back;
 extern crate rustc_const_math;
+extern crate rustc_errors;
 extern crate graphviz;
 extern crate syntax_pos;
 extern crate serialize as rustc_serialize; // used by deriving
index ab3b20e08c8099130c1b5c3a874a519f9b29fddb..9a94cc16bfe8ceda4709be95262b1a6ff4cdc001 100644 (file)
@@ -478,10 +478,6 @@ pub fn phase_1_parse_input<'a>(sess: &'a Session,
                                cfg: ast::CrateConfig,
                                input: &Input)
                                -> PResult<'a, ast::Crate> {
-    // These may be left in an incoherent state after a previous compile.
-    syntax::ext::hygiene::reset_hygiene_data();
-    // `clear_ident_interner` can be used to free memory, but it does not restore the initial state.
-    token::reset_ident_interner();
     let continue_after_error = sess.opts.continue_parse_after_error;
     sess.diagnostic().set_continue_after_error(continue_after_error);
 
@@ -1298,3 +1294,11 @@ pub fn build_output_filenames(input: &Input,
         }
     }
 }
+
+// For use by the `rusti` project (https://github.com/murarth/rusti).
+pub fn reset_thread_local_state() {
+    // These may be left in an incoherent state after a previous compile.
+    syntax::ext::hygiene::reset_hygiene_data();
+    // `clear_ident_interner` can be used to free memory, but it does not restore the initial state.
+    token::reset_ident_interner();
+}
index 6a48f65714cc50d95e6463d337ec64af32233dd1..610e5647d6d12893547923c65d361474d0914c00 100644 (file)
@@ -531,10 +531,12 @@ pub fn struct_fatal<'a>(&'a self, msg: &str) -> DiagnosticBuilder<'a> {
         DiagnosticBuilder::new(self, Level::Fatal, msg)
     }
 
-    pub fn cancel(&mut self, err: &mut DiagnosticBuilder) {
+    pub fn cancel(&self, err: &mut DiagnosticBuilder) {
         if err.level == Level::Error || err.level == Level::Fatal {
-            assert!(self.has_errors());
-            self.err_count.set(self.err_count.get() + 1);
+            self.err_count.set(
+                self.err_count.get().checked_sub(1)
+                    .expect("cancelled an error but err_count is 0")
+            );
         }
         err.cancel();
     }
index 515620d425389676617e3efa5f9cbba8cf5c96b3..d1b88ddda0c674987bb3e605b315b9cc20330b36 100644 (file)
@@ -19,6 +19,7 @@
 use std::fs;
 use std::io::{self, Write};
 use syntax::ast::NodeId;
+use std::path::{PathBuf, Path};
 
 const INDENT: &'static str = "    ";
 /// Alignment for lining up comments following MIR statements
@@ -66,9 +67,15 @@ pub fn dump_mir<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         _ => String::new()
     };
 
+    let mut file_path = PathBuf::new();
+    if let Some(ref file_dir) = tcx.sess.opts.debugging_opts.dump_mir_dir {
+        let p = Path::new(file_dir);
+        file_path.push(p);
+    };
     let file_name = format!("rustc.node{}{}.{}.{}.mir",
                             node_id, promotion_id, pass_name, disambiguator);
-    let _ = fs::File::create(&file_name).and_then(|mut file| {
+    file_path.push(&file_name);
+    let _ = fs::File::create(&file_path).and_then(|mut file| {
         try!(writeln!(file, "// MIR for `{}`", node_path));
         try!(writeln!(file, "// node_id = {}", node_id));
         try!(writeln!(file, "// pass_name = {}", pass_name));
@@ -195,7 +202,7 @@ fn write_basic_block(tcx: TyCtxt,
              ALIGN,
              comment(tcx, data.terminator().source_info))?;
 
-    writeln!(w, "{}}}\n", INDENT)
+    writeln!(w, "{}}}", INDENT)
 }
 
 fn comment(tcx: TyCtxt, SourceInfo { span, scope }: SourceInfo) -> String {
index 27ce03b2d9390c8c250f921282b072a33e3961c0..b0ba38f1db67322d33aa51dac8e0d5fd41f26492 100644 (file)
@@ -40,6 +40,7 @@
 use rustc::middle::mem_categorization::Categorization;
 use rustc::ty::{self, Ty, TyCtxt};
 use rustc::traits::ProjectionMode;
+use rustc::util::common::ErrorReported;
 use rustc::util::nodemap::NodeMap;
 use rustc::middle::const_qualif::ConstQualif;
 use rustc::lint::builtin::CONST_ERR;
@@ -116,7 +117,7 @@ fn global_expr(&mut self, mode: Mode, expr: &hir::Expr) -> ConstQualif {
                 _ => self.tcx.sess.add_lint(CONST_ERR, expr.id, expr.span,
                                          format!("constant evaluation error: {}. This will \
                                                  become a HARD ERROR in the future",
-                                                 err.description())),
+                                                 err.description().into_oneline())),
             }
         }
         self.with_mode(mode, |this| {
@@ -211,15 +212,6 @@ fn record_borrow(&mut self, id: ast::NodeId, mutbl: hir::Mutability) {
             }
         }
     }
-
-    fn msg(&self) -> &'static str {
-        match self.mode {
-            Mode::Const => "constant",
-            Mode::ConstFn => "constant function",
-            Mode::StaticMut | Mode::Static => "static",
-            Mode::Var => bug!(),
-        }
-    }
 }
 
 impl<'a, 'tcx, 'v> Visitor<'v> for CheckCrateVisitor<'a, 'tcx> {
@@ -289,18 +281,14 @@ fn visit_pat(&mut self, p: &hir::Pat) {
                 self.global_expr(Mode::Const, &start);
                 self.global_expr(Mode::Const, &end);
 
-                match compare_lit_exprs(self.tcx, start, end) {
-                    Some(Ordering::Less) |
-                    Some(Ordering::Equal) => {}
-                    Some(Ordering::Greater) => {
+                match compare_lit_exprs(self.tcx, p.span, start, end) {
+                    Ok(Ordering::Less) |
+                    Ok(Ordering::Equal) => {}
+                    Ok(Ordering::Greater) => {
                         span_err!(self.tcx.sess, start.span, E0030,
                             "lower range bound must be less than or equal to upper");
                     }
-                    None => {
-                        span_err!(self.tcx.sess, p.span, E0014,
-                                  "paths in {}s may only refer to constants",
-                                  self.msg());
-                    }
+                    Err(ErrorReported) => {}
                 }
             }
             _ => intravisit::walk_pat(self, p)
@@ -429,7 +417,7 @@ fn visit_expr(&mut self, ex: &hir::Expr) {
                 Err(msg) => {
                     self.tcx.sess.add_lint(CONST_ERR, ex.id,
                                            msg.span,
-                                           msg.description().into_owned())
+                                           msg.description().into_oneline().into_owned())
                 }
             }
         }
index 918e17d21ea998e35ca91df67c1115bd564d70a9..a616b95ef7203ad312ba54a6a6af4c127d907aca 100644 (file)
@@ -11,7 +11,7 @@
 #![allow(non_snake_case)]
 
 register_long_diagnostics! {
-
+/*
 E0014: r##"
 Constants can only be initialized by a constant value or, in a future
 version of Rust, a call to a const function. This error indicates the use
@@ -30,7 +30,7 @@
 const FOO2: i32 = { 0 }; // but brackets are useless here
 ```
 "##,
-
+*/
 E0030: r##"
 When matching against a range, the compiler verifies that the range is
 non-empty.  Range patterns include both end-points, so this is equivalent to
index e7cc534c5b55537d45dce95db500d26e160e6625..0fd95500422ff193af8a29aa1f8ea615657eb775 100644 (file)
@@ -427,7 +427,7 @@ fn make_values_str(pairs: &[(&'static str, &str)]) -> String {
 }
 
 fn span_extent_str(span: SpanData) -> String {
-    format!("file_name,\"{}\",file_line,{},file_col,{},byte_start,{}\
+    format!("file_name,\"{}\",file_line,{},file_col,{},byte_start,{},\
              file_line_end,{},file_col_end,{},byte_end,{}",
              span.file_name, span.line_start, span.column_start, span.byte_start,
              span.line_end, span.column_end, span.byte_end)
index 08e894ffbcfd48c4e37fde4d75f6565713c79f80..f7fd970f37f2f89e1a4686f541ef9ea5984343bc 100644 (file)
 
 use llvm::{ValueRef, BasicBlockRef};
 use rustc_const_eval::check_match::{self, Constructor, StaticInliner};
-use rustc_const_eval::{compare_lit_exprs, eval_const_expr};
+use rustc_const_eval::{compare_lit_exprs, eval_const_expr, fatal_const_eval_err};
 use rustc::hir::def::{Def, DefMap};
 use rustc::hir::def_id::DefId;
 use middle::expr_use_visitor as euv;
 
 impl<'a> ConstantExpr<'a> {
     fn eq<'b, 'tcx>(self, other: ConstantExpr<'a>, tcx: TyCtxt<'b, 'tcx, 'tcx>) -> bool {
-        match compare_lit_exprs(tcx, self.0, other.0) {
-            Some(result) => result == Ordering::Equal,
-            None => bug!("compare_list_exprs: type mismatch"),
+        match compare_lit_exprs(tcx, self.0.span, self.0, other.0) {
+            Ok(result) => result == Ordering::Equal,
+            Err(_) => bug!("compare_list_exprs: type mismatch"),
         }
     }
 }
@@ -288,7 +288,9 @@ fn trans<'blk>(&self, mut bcx: Block<'blk, 'tcx>) -> OptResult<'blk, 'tcx> {
                 let expr = consts::const_expr(ccx, &lit_expr, bcx.fcx.param_substs, None, Yes);
                 let llval = match expr {
                     Ok((llval, _)) => llval,
-                    Err(err) => bcx.ccx().sess().span_fatal(lit_expr.span, &err.description()),
+                    Err(err) => {
+                        fatal_const_eval_err(bcx.tcx(), err.as_inner(), lit_expr.span, "pattern");
+                    }
                 };
                 let lit_datum = immediate_rvalue(llval, lit_ty);
                 let lit_datum = unpack_datum!(bcx, lit_datum.to_appropriate_datum(bcx));
@@ -297,11 +299,11 @@ fn trans<'blk>(&self, mut bcx: Block<'blk, 'tcx>) -> OptResult<'blk, 'tcx> {
             ConstantRange(ConstantExpr(ref l1), ConstantExpr(ref l2), _) => {
                 let l1 = match consts::const_expr(ccx, &l1, bcx.fcx.param_substs, None, Yes) {
                     Ok((l1, _)) => l1,
-                    Err(err) => bcx.ccx().sess().span_fatal(l1.span, &err.description()),
+                    Err(err) => fatal_const_eval_err(bcx.tcx(), err.as_inner(), l1.span, "pattern"),
                 };
                 let l2 = match consts::const_expr(ccx, &l2, bcx.fcx.param_substs, None, Yes) {
                     Ok((l2, _)) => l2,
-                    Err(err) => bcx.ccx().sess().span_fatal(l2.span, &err.description()),
+                    Err(err) => fatal_const_eval_err(bcx.tcx(), err.as_inner(), l2.span, "pattern"),
                 };
                 RangeResult(Result::new(bcx, l1), Result::new(bcx, l2))
             }
index c8b9fea15ba8b0e12cb4c3557411deddb8f3b056..ea8c248d0239fb2fd842c8f5af9e913f5fbf31d3 100644 (file)
 use Disr;
 use util::common::indenter;
 use util::sha2::Sha256;
-use util::nodemap::{NodeMap, NodeSet};
+use util::nodemap::{NodeMap, NodeSet, FnvHashSet};
 
 use arena::TypedArena;
 use libc::c_uint;
 use std::ffi::{CStr, CString};
+use std::borrow::Cow;
 use std::cell::{Cell, RefCell};
-use std::collections::{HashMap, HashSet};
+use std::collections::HashMap;
 use std::ptr;
 use std::rc::Rc;
 use std::str;
@@ -2256,12 +2257,20 @@ fn write_metadata(cx: &SharedCrateContext,
 
 /// Find any symbols that are defined in one compilation unit, but not declared
 /// in any other compilation unit.  Give these symbols internal linkage.
-fn internalize_symbols(cx: &CrateContextList, reachable: &HashSet<&str>) {
+fn internalize_symbols<'a, 'tcx>(ccxs: &CrateContextList<'a, 'tcx>,
+                                 symbol_map: &SymbolMap<'tcx>,
+                                 reachable: &FnvHashSet<&str>) {
+    let scx = ccxs.shared();
+    let tcx = scx.tcx();
+
+    // 'unsafe' because we are holding on to CStr's from the LLVM module within
+    // this block.
     unsafe {
-        let mut declared = HashSet::new();
+        let mut referenced_somewhere = FnvHashSet();
 
-        // Collect all external declarations in all compilation units.
-        for ccx in cx.iter() {
+        // Collect all symbols that need to stay externally visible because they
+        // are referenced via a declaration in some other codegen unit.
+        for ccx in ccxs.iter() {
             for val in iter_globals(ccx.llmod()).chain(iter_functions(ccx.llmod())) {
                 let linkage = llvm::LLVMGetLinkage(val);
                 // We only care about external declarations (not definitions)
@@ -2270,39 +2279,67 @@ fn internalize_symbols(cx: &CrateContextList, reachable: &HashSet<&str>) {
                 let is_decl = llvm::LLVMIsDeclaration(val) != 0;
 
                 if is_decl || is_available_externally {
-                    let name = CStr::from_ptr(llvm::LLVMGetValueName(val));
-                    declared.insert(name);
+                    let symbol_name = CStr::from_ptr(llvm::LLVMGetValueName(val));
+                    referenced_somewhere.insert(symbol_name);
                 }
             }
         }
 
+        // Also collect all symbols for which we cannot adjust linkage, because
+        // it is fixed by some directive in the source code (e.g. #[no_mangle]).
+        let linkage_fixed_explicitly: FnvHashSet<_> = scx
+            .translation_items()
+            .borrow()
+            .iter()
+            .cloned()
+            .filter(|trans_item|{
+                let def_id = match *trans_item {
+                    TransItem::DropGlue(..) => {
+                        return false
+                    },
+                    TransItem::Fn(ref instance) => {
+                        instance.def
+                    }
+                    TransItem::Static(node_id) => {
+                        tcx.map.local_def_id(node_id)
+                    }
+                };
+
+                trans_item.explicit_linkage(tcx).is_some() ||
+                attr::contains_extern_indicator(tcx.sess.diagnostic(),
+                                                &tcx.get_attrs(def_id))
+            })
+            .map(|trans_item| symbol_map.get_or_compute(scx, trans_item))
+            .collect();
+
         // Examine each external definition.  If the definition is not used in
         // any other compilation unit, and is not reachable from other crates,
         // then give it internal linkage.
-        for ccx in cx.iter() {
+        for ccx in ccxs.iter() {
             for val in iter_globals(ccx.llmod()).chain(iter_functions(ccx.llmod())) {
                 let linkage = llvm::LLVMGetLinkage(val);
 
                 let is_externally_visible = (linkage == llvm::ExternalLinkage as c_uint) ||
                                             (linkage == llvm::LinkOnceODRLinkage as c_uint) ||
                                             (linkage == llvm::WeakODRLinkage as c_uint);
-                let is_definition = llvm::LLVMIsDeclaration(val) != 0;
+                let is_definition = llvm::LLVMIsDeclaration(val) == 0;
 
                 // If this is a definition (as opposed to just a declaration)
                 // and externally visible, check if we can internalize it
                 if is_definition && is_externally_visible {
                     let name_cstr = CStr::from_ptr(llvm::LLVMGetValueName(val));
                     let name_str = name_cstr.to_str().unwrap();
+                    let name_cow = Cow::Borrowed(name_str);
 
-                    let is_referenced_somewhere = declared.contains(&name_cstr);
-                    let is_reachable = reachable.contains(name_str);
+                    let is_referenced_somewhere = referenced_somewhere.contains(&name_cstr);
+                    let is_reachable = reachable.contains(&name_str);
+                    let has_fixed_linkage = linkage_fixed_explicitly.contains(&name_cow);
 
-                    if !is_referenced_somewhere && !is_reachable {
+                    if !is_referenced_somewhere && !is_reachable && !has_fixed_linkage {
                         llvm::SetLinkage(val, llvm::InternalLinkage);
                         llvm::SetDLLStorageClass(val, llvm::DefaultStorageClass);
                         llvm::UnsetComdat(val);
                     }
-
                 }
             }
         }
@@ -2616,8 +2653,13 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
         }));
     }
 
-    internalize_symbols(&crate_context_list,
-                        &reachable_symbols.iter().map(|x| &x[..]).collect());
+    time(shared_ccx.sess().time_passes(), "internalize symbols", || {
+        internalize_symbols(&crate_context_list,
+                            &symbol_map,
+                            &reachable_symbols.iter()
+                                              .map(|s| &s[..])
+                                              .collect())
+    });
 
     if sess.target.target.options.is_like_msvc &&
        sess.crate_types.borrow().iter().any(|ct| *ct == config::CrateTypeRlib) {
index 00feb2cd1de0961f5ec1e97965ea1480d3ee3543..f662ba75cc6fea7c5e4f014d30e4c69ba67171f8 100644 (file)
@@ -14,7 +14,7 @@
 use llvm::{InternalLinkage, ValueRef, Bool, True};
 use middle::const_qualif::ConstQualif;
 use rustc_const_eval::{ConstEvalErr, lookup_const_fn_by_id, lookup_const_by_id, ErrKind};
-use rustc_const_eval::eval_repeat_count;
+use rustc_const_eval::{eval_length, report_const_eval_err, note_const_eval_err};
 use rustc::hir::def::Def;
 use rustc::hir::def_id::DefId;
 use rustc::hir::map as hir_map;
@@ -44,7 +44,6 @@
 use rustc::hir;
 
 use std::ffi::{CStr, CString};
-use std::borrow::Cow;
 use libc::c_uint;
 use syntax::ast::{self, LitKind};
 use syntax::attr::{self, AttrMetaMethods};
@@ -250,10 +249,11 @@ fn into_inner(self) -> ConstEvalErr {
             Compiletime(e) => e,
         }
     }
-    pub fn description(&self) -> Cow<str> {
+
+    pub fn as_inner(&self) -> &ConstEvalErr {
         match self {
-            &Runtime(ref e) => e.description(),
-            &Compiletime(ref e) => e.description(),
+            &Runtime(ref e) => e,
+            &Compiletime(ref e) => e,
         }
     }
 }
@@ -274,7 +274,7 @@ fn get_const_val<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
     let empty_substs = ccx.tcx().mk_substs(Substs::empty());
     match get_const_expr_as_global(ccx, expr, ConstQualif::empty(), empty_substs, TrueConst::Yes) {
         Err(Runtime(err)) => {
-            ccx.tcx().sess.span_err(expr.span, &err.description());
+            report_const_eval_err(ccx.tcx(), &err, expr.span, "expression").emit();
             Err(Compiletime(err))
         },
         other => other,
@@ -526,12 +526,15 @@ pub fn const_err<T>(cx: &CrateContext,
         (Ok(x), _) => Ok(x),
         (Err(err), TrueConst::Yes) => {
             let err = ConstEvalErr{ span: span, kind: err };
-            cx.tcx().sess.span_err(span, &err.description());
+            report_const_eval_err(cx.tcx(), &err, span, "expression").emit();
             Err(Compiletime(err))
         },
         (Err(err), TrueConst::No) => {
             let err = ConstEvalErr{ span: span, kind: err };
-            cx.tcx().sess.span_warn(span, &err.description());
+            let mut diag = cx.tcx().sess.struct_span_warn(
+                span, "this expression will panic at run-time");
+            note_const_eval_err(cx.tcx(), &err, span, "expression", &mut diag);
+            diag.emit();
             Err(Runtime(err))
         },
     }
@@ -875,7 +878,7 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
         hir::ExprRepeat(ref elem, ref count) => {
             let unit_ty = ety.sequence_element_type(cx.tcx());
             let llunitty = type_of::type_of(cx, unit_ty);
-            let n = eval_repeat_count(cx.tcx(), count);
+            let n = eval_length(cx.tcx(), count, "repeat count").unwrap();
             let unit_val = const_expr(cx, &elem, param_substs, fn_args, trueconst)?.0;
             let vs = vec![unit_val; n];
             if val_ty(unit_val) != llunitty {
index a721361fce0e3aecbbd152edb8fd663507383df3..e657a086581e2dadfff30deedc5c7a07288b6861 100644 (file)
@@ -44,6 +44,7 @@
 use syntax::parse::token;
 
 use rustc::session::Session;
+use rustc_const_eval::fatal_const_eval_err;
 use syntax_pos::{Span, DUMMY_SP};
 
 use std::cmp::Ordering;
@@ -1193,11 +1194,17 @@ fn trans_gnu_try<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
         // managed by the standard library.
 
         attributes::emit_uwtable(bcx.fcx.llfn, true);
-        let catch_pers = match tcx.lang_items.eh_personality_catch() {
-            Some(did) => {
-                Callee::def(ccx, did, tcx.mk_substs(Substs::empty())).reify(ccx).val
+        let target = &bcx.sess().target.target;
+        let catch_pers = if target.arch == "arm" && target.target_os != "ios" {
+            // Only ARM still uses a separate catch personality (for now)
+            match tcx.lang_items.eh_personality_catch() {
+                Some(did) => {
+                    Callee::def(ccx, did, tcx.mk_substs(Substs::empty())).reify(ccx).val
+                }
+                None => bug!("eh_personality_catch not defined"),
             }
-            None => bug!("eh_personality_catch not defined"),
+        } else {
+            bcx.fcx.eh_personality()
         };
 
         let then = bcx.fcx.new_temp_block("then");
@@ -1408,7 +1415,10 @@ macro_rules! require_simd {
                                          // this should probably help simd error reporting
                                          consts::TrueConst::Yes) {
                     Ok((vector, _)) => vector,
-                    Err(err) => bcx.sess().span_fatal(span, &err.description()),
+                    Err(err) => {
+                        fatal_const_eval_err(bcx.tcx(), err.as_inner(), span,
+                                             "shuffle indices");
+                    }
                 }
             }
             None => llargs[2]
index da72793abf6dab869a558e9993e7362c342ef916..1f3b13203163f7fbf6cbab2ea681e6fea84572f7 100644 (file)
@@ -925,7 +925,7 @@ pub fn trans_constant(&mut self,
             }
             Err(ConstEvalFailure::Runtime(err)) => {
                 span_bug!(constant.span,
-                          "MIR constant {:?} results in runtime panic: {}",
+                          "MIR constant {:?} results in runtime panic: {:?}",
                           constant, err.description())
             }
         }
index 8b8e658533ed09db43dad823f5e6914d7901ef2c..fc95d208f32ccdda8c926e2be3a03e1a6c11eb95 100644 (file)
@@ -29,6 +29,7 @@
 use rustc::ty::{self, Ty, TyCtxt, TypeFoldable};
 use rustc::ty::subst;
 use rustc::dep_graph::DepNode;
+use rustc_const_eval::fatal_const_eval_err;
 use std::hash::{Hash, Hasher};
 use syntax::ast::{self, NodeId};
 use syntax::{attr,errors};
@@ -81,7 +82,11 @@ pub fn define(&self, ccx: &CrateContext<'a, 'tcx>) {
                 if let hir::ItemStatic(_, m, ref expr) = item.node {
                     match consts::trans_static(&ccx, m, expr, item.id, &item.attrs) {
                         Ok(_) => { /* Cool, everything's alright. */ },
-                        Err(err) => ccx.tcx().sess.span_fatal(expr.span, &err.description()),
+                        Err(err) => {
+                            // FIXME: shouldn't this be a `span_err`?
+                            fatal_const_eval_err(
+                                ccx.tcx(), &err, expr.span, "static");
+                        }
                     };
                 } else {
                     span_bug!(item.span, "Mismatch between hir::Item type and TransItem type")
index f5b9bef5313f23a34039747e79d6f0c634ffd88e..92a2d3787bfd6b60bc5184233f24893e10e91ab3 100644 (file)
@@ -30,7 +30,7 @@
 use rustc::ty::{self, Ty};
 
 use rustc::hir;
-use rustc_const_eval::eval_repeat_count;
+use rustc_const_eval::eval_length;
 
 use syntax::ast;
 use syntax::parse::token::InternedString;
@@ -218,7 +218,7 @@ fn write_content<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                     return expr::trans_into(bcx, &element, Ignore);
                 }
                 SaveIn(lldest) => {
-                    match eval_repeat_count(bcx.tcx(), &count_expr) {
+                    match eval_length(bcx.tcx(), &count_expr, "repeat count").unwrap() {
                         0 => expr::trans_into(bcx, &element, Ignore),
                         1 => expr::trans_into(bcx, &element, SaveIn(lldest)),
                         count => {
@@ -268,7 +268,7 @@ fn elements_required(bcx: Block, content_expr: &hir::Expr) -> usize {
         },
         hir::ExprVec(ref es) => es.len(),
         hir::ExprRepeat(_, ref count_expr) => {
-            eval_repeat_count(bcx.tcx(), &count_expr)
+            eval_length(bcx.tcx(), &count_expr, "repeat count").unwrap()
         }
         _ => span_bug!(content_expr.span, "unexpected vec content")
     }
index 9ff30f9ede26295d85f4e94c853d817ce3bf3d84..b642a7122194de3059babc25f116b8725dbd31a1 100644 (file)
 //! case but `&a` in the second.  Basically, defaults that appear inside
 //! an rptr (`&r.T`) use the region `r` that appears in the rptr.
 
-use middle::const_val::ConstVal;
-use rustc_const_eval::{eval_const_expr_partial, ConstEvalErr};
-use rustc_const_eval::EvalHint::UncheckedExprHint;
-use rustc_const_eval::ErrKind::ErroneousReferencedConstant;
+use rustc_const_eval::eval_length;
 use hir::{self, SelfKind};
 use hir::def::{Def, PathResolution};
 use hir::def_id::DefId;
@@ -70,7 +67,6 @@
 use util::common::{ErrorReported, FN_OUTPUT_NAME};
 use util::nodemap::{NodeMap, FnvHashSet};
 
-use rustc_const_math::ConstInt;
 use std::cell::RefCell;
 use syntax::{abi, ast};
 use syntax::feature_gate::{GateIssue, emit_feature_err};
@@ -1741,33 +1737,10 @@ pub fn ast_ty_to_ty(&self, rscope: &RegionScope, ast_ty: &hir::Ty) -> Ty<'tcx> {
                 ty
             }
             hir::TyFixedLengthVec(ref ty, ref e) => {
-                let hint = UncheckedExprHint(tcx.types.usize);
-                match eval_const_expr_partial(tcx.global_tcx(), &e, hint, None) {
-                    Ok(ConstVal::Integral(ConstInt::Usize(i))) => {
-                        let i = i.as_u64(tcx.sess.target.uint_type);
-                        assert_eq!(i as usize as u64, i);
-                        tcx.mk_array(self.ast_ty_to_ty(rscope, &ty), i as usize)
-                    },
-                    Ok(val) => {
-                        span_err!(tcx.sess, ast_ty.span, E0249,
-                                  "expected usize value for array length, got {}",
-                                  val.description());
-                        self.tcx().types.err
-                    },
-                    // array length errors happen before the global constant check
-                    // so we need to report the real error
-                    Err(ConstEvalErr { kind: ErroneousReferencedConstant(box r), ..}) |
-                    Err(r) => {
-                        let mut err = struct_span_err!(tcx.sess, r.span, E0250,
-                                                       "array length constant \
-                                                        evaluation error: {}",
-                                                       r.description());
-                        if !ast_ty.span.contains(r.span) {
-                            span_note!(&mut err, ast_ty.span, "for array length here")
-                        }
-                        err.emit();
-                        self.tcx().types.err
-                    }
+                if let Ok(length) = eval_length(tcx.global_tcx(), &e, "array length") {
+                    tcx.mk_array(self.ast_ty_to_ty(rscope, &ty), length)
+                } else {
+                    self.tcx().types.err
                 }
             }
             hir::TyTypeof(ref _e) => {
index e90b32cd5dfc0192c5001b46a8dc2795acab7f39..aae6e3ad36dfe7ee2ba7b1ec173cd2d3f8193a82 100644 (file)
@@ -103,15 +103,6 @@ pub fn check_pat(&self, pat: &'gcx hir::Pat, expected: Ty<'tcx>) {
                     return;
                 }
 
-                // Check that the types of the end-points can be unified.
-                let types_unify = self.require_same_types(pat.span, rhs_ty, lhs_ty,
-                                                          "mismatched types in range");
-
-                // It's ok to return without a message as `require_same_types` prints an error.
-                if !types_unify {
-                    return;
-                }
-
                 // Now that we know the types can be unified we find the unified type and use
                 // it to type the entire expression.
                 let common_type = self.resolve_type_vars_if_possible(&lhs_ty);
@@ -120,6 +111,7 @@ pub fn check_pat(&self, pat: &'gcx hir::Pat, expected: Ty<'tcx>) {
 
                 // subtyping doesn't matter here, as the value is some kind of scalar
                 self.demand_eqtype(pat.span, expected, lhs_ty);
+                self.demand_eqtype(pat.span, expected, rhs_ty);
             }
             PatKind::Binding(bm, _, ref sub) => {
                 let typ = self.local_ty(pat.span, pat.id);
index 2c7e7d284fa160250de1ba5b9e7b71c37be092b7..9c6727ebbfcf955d30f6507ef5b1719b3b5314d5 100644 (file)
@@ -216,7 +216,7 @@ fn confirm_builtin_call(&self,
             _ => {
                 let mut err = self.type_error_struct(call_expr.span, |actual| {
                     format!("expected function, found `{}`", actual)
-                }, callee_ty, None);
+                }, callee_ty);
 
                 if let hir::ExprCall(ref expr, _) = call_expr.node {
                     let tcx = self.tcx;
index 22ac8bc56907bfd9578e94134ea0ea1ad3117c50..7a4cc09a7d5064d3a9ac408103df64cdf885dca3 100644 (file)
@@ -149,7 +149,7 @@ fn report_cast_error(&self, fcx: &FnCtxt<'a, 'gcx, 'tcx>, e: CastError) {
                     format!("casting `{}` as `{}` is invalid",
                             actual,
                             fcx.ty_to_string(self.cast_ty))
-                }, self.expr_ty, None)
+                }, self.expr_ty)
                     .help(&format!("cast through {} first", match e {
                             CastError::NeedViaPtr => "a raw pointer",
                             CastError::NeedViaThinPtr => "a thin pointer",
@@ -167,35 +167,35 @@ fn report_cast_error(&self, fcx: &FnCtxt<'a, 'gcx, 'tcx>, e: CastError) {
             CastError::CastToChar => {
                 fcx.type_error_message(self.span, |actual| {
                     format!("only `u8` can be cast as `char`, not `{}`", actual)
-                }, self.expr_ty, None);
+                }, self.expr_ty);
             }
             CastError::NonScalar => {
                 fcx.type_error_message(self.span, |actual| {
                     format!("non-scalar cast: `{}` as `{}`",
                             actual,
                             fcx.ty_to_string(self.cast_ty))
-                }, self.expr_ty, None);
+                }, self.expr_ty);
             }
             CastError::IllegalCast => {
                 fcx.type_error_message(self.span, |actual| {
                     format!("casting `{}` as `{}` is invalid",
                             actual,
                             fcx.ty_to_string(self.cast_ty))
-                }, self.expr_ty, None);
+                }, self.expr_ty);
             }
             CastError::SizedUnsizedCast => {
                 fcx.type_error_message(self.span, |actual| {
                     format!("cannot cast thin pointer `{}` to fat pointer `{}`",
                             actual,
                             fcx.ty_to_string(self.cast_ty))
-                }, self.expr_ty, None)
+                }, self.expr_ty)
             }
             CastError::DifferingKinds => {
                 fcx.type_error_struct(self.span, |actual| {
                     format!("casting `{}` as `{}` is invalid",
                             actual,
                             fcx.ty_to_string(self.cast_ty))
-                }, self.expr_ty, None)
+                }, self.expr_ty)
                     .note("vtable kinds may not match")
                     .emit();
             }
@@ -213,7 +213,7 @@ fn report_cast_to_unsized_type(&self, fcx: &FnCtxt<'a, 'gcx, 'tcx>) {
         let tstr = fcx.ty_to_string(self.cast_ty);
         let mut err = fcx.type_error_struct(self.span, |actual| {
             format!("cast to unsized type: `{}` as `{}`", actual, tstr)
-        }, self.expr_ty, None);
+        }, self.expr_ty);
         match self.expr_ty.sty {
             ty::TyRef(_, ty::TypeAndMut { mutbl: mt, .. }) => {
                 let mtstr = match mt {
@@ -484,4 +484,3 @@ fn type_is_known_to_be_sized(&self,
         traits::type_known_to_meet_builtin_bound(self, ty, ty::BoundSized, span)
     }
 }
-
index 35a5bc9c60967d69512b3b573d26b903e59ce187..9844377d0bd32f5241c1e0cb948f48597c1d5673 100644 (file)
@@ -12,6 +12,7 @@
 use rustc::infer::{self, InferOk, TypeOrigin};
 use rustc::ty;
 use rustc::traits::{self, ProjectionMode};
+use rustc::ty::error::ExpectedFound;
 use rustc::ty::subst::{self, Subst, Substs, VecPerParamSpace};
 
 use syntax::ast;
@@ -324,10 +325,19 @@ pub fn compare_impl_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
             debug!("sub_types failed: impl ty {:?}, trait ty {:?}",
                    impl_fty,
                    trait_fty);
-            span_err!(tcx.sess, impl_m_span, E0053,
-                      "method `{}` has an incompatible type for trait: {}",
-                      trait_m.name,
-                      terr);
+
+            let mut diag = struct_span_err!(
+                tcx.sess, origin.span(), E0053,
+                "method `{}` has an incompatible type for trait", trait_m.name
+            );
+            infcx.note_type_err(
+                &mut diag, origin,
+                Some(infer::ValuePairs::Types(ExpectedFound {
+                    expected: trait_fty,
+                    found: impl_fty
+                })), &terr
+            );
+            diag.emit();
             return
         }
 
@@ -437,10 +447,9 @@ pub fn compare_const_impl<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
         // Compute skolemized form of impl and trait const tys.
         let impl_ty = impl_c.ty.subst(tcx, impl_to_skol_substs);
         let trait_ty = trait_c.ty.subst(tcx, &trait_to_skol_substs);
+        let origin = TypeOrigin::Misc(impl_c_span);
 
         let err = infcx.commit_if_ok(|_| {
-            let origin = TypeOrigin::Misc(impl_c_span);
-
             // There is no "body" here, so just pass dummy id.
             let impl_ty =
                 assoc::normalize_associated_types_in(&infcx,
@@ -473,11 +482,19 @@ pub fn compare_const_impl<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
             debug!("checking associated const for compatibility: impl ty {:?}, trait ty {:?}",
                    impl_ty,
                    trait_ty);
-            span_err!(tcx.sess, impl_c_span, E0326,
-                      "implemented const `{}` has an incompatible type for \
-                      trait: {}",
-                      trait_c.name,
-                      terr);
+            let mut diag = struct_span_err!(
+                tcx.sess, origin.span(), E0326,
+                "implemented const `{}` has an incompatible type for trait",
+                trait_c.name
+            );
+            infcx.note_type_err(
+                &mut diag, origin,
+                Some(infer::ValuePairs::Types(ExpectedFound {
+                    expected: trait_ty,
+                    found: impl_ty
+                })), &terr
+            );
+            diag.emit();
         }
     });
 }
index eeebd6a7f626b74160e7c2d4c27d1844cc3bd5db..1f3a83ebc1d567da7a2ae7174213e62feaafd451 100644 (file)
@@ -33,7 +33,14 @@ pub fn demand_suptype(&self, sp: Span, expected: Ty<'tcx>, actual: Ty<'tcx>) {
     }
 
     pub fn demand_eqtype(&self, sp: Span, expected: Ty<'tcx>, actual: Ty<'tcx>) {
-        let origin = TypeOrigin::Misc(sp);
+        self.demand_eqtype_with_origin(TypeOrigin::Misc(sp), expected, actual);
+    }
+
+    pub fn demand_eqtype_with_origin(&self,
+                                     origin: TypeOrigin,
+                                     expected: Ty<'tcx>,
+                                     actual: Ty<'tcx>)
+    {
         match self.eq_types(false, origin, actual, expected) {
             Ok(InferOk { obligations, .. }) => {
                 // FIXME(#32730) propagate obligations
@@ -54,16 +61,4 @@ pub fn demand_coerce(&self, expr: &hir::Expr, expected: Ty<'tcx>) {
             self.report_mismatched_types(origin, expected, expr_ty, e);
         }
     }
-
-    pub fn require_same_types(&self, span: Span, t1: Ty<'tcx>, t2: Ty<'tcx>, msg: &str)
-                              -> bool {
-        if let Err(err) = self.eq_types(false, TypeOrigin::Misc(span), t1, t2) {
-            let found_ty = self.resolve_type_vars_if_possible(&t1);
-            let expected_ty = self.resolve_type_vars_if_possible(&t2);
-            ::emit_type_err(self.tcx, span, found_ty, expected_ty, &err, msg);
-            false
-        } else {
-            true
-        }
-    }
 }
index 5a3268e9e447b25a9165c02eec623c5f6164cedd..8a53c59b4c7fad08dafbe1215cb6d8bf52914885 100644 (file)
@@ -12,6 +12,7 @@
 //! intrinsics that the compiler exposes.
 
 use intrinsics;
+use rustc::infer::TypeOrigin;
 use rustc::ty::subst::{self, Substs};
 use rustc::ty::FnSig;
 use rustc::ty::{self, Ty};
@@ -56,10 +57,9 @@ fn equate_intrinsic_type<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
              i_n_tps, n_tps);
     } else {
         require_same_types(ccx,
-                           it.span,
+                           TypeOrigin::IntrinsicType(it.span),
                            i_ty.ty,
-                           fty,
-                           "intrinsic has wrong type");
+                           fty);
     }
 }
 
index f20dcdc35aea5c7af46ded13c2b84800a42ddc63..346449d0a51331465bde2b99b5eec3048bb74e7c 100644 (file)
@@ -160,8 +160,7 @@ pub fn report_method_error(&self,
                                 item_name,
                                 actual)
                     },
-                    rcvr_ty,
-                    None);
+                    rcvr_ty);
 
                 // If the item has the name of a field, give a help note
                 if let (&ty::TyStruct(def, substs), Some(expr)) = (&rcvr_ty.sty, rcvr_expr) {
index fc1d2236f3feaa07c63c5e99e424500bc5704b53..6062bd048b3d27f8972edfbdce5efa766c448aab 100644 (file)
 use rustc::hir::{self, PatKind};
 use rustc::hir::print as pprust;
 use rustc_back::slice;
-use rustc_const_eval::eval_repeat_count;
+use rustc_const_eval::eval_length;
 
 mod assoc;
 mod autoderef;
@@ -2541,21 +2541,21 @@ fn parameter_count_error<'tcx>(sess: &Session, sp: Span, fn_inputs: &[Ty<'tcx>],
                         self.type_error_message(arg.span, |t| {
                             format!("can't pass an `{}` to variadic \
                                      function, cast to `c_double`", t)
-                        }, arg_ty, None);
+                        }, arg_ty);
                     }
                     ty::TyInt(ast::IntTy::I8) | ty::TyInt(ast::IntTy::I16) | ty::TyBool => {
                         self.type_error_message(arg.span, |t| {
                             format!("can't pass `{}` to variadic \
                                      function, cast to `c_int`",
                                            t)
-                        }, arg_ty, None);
+                        }, arg_ty);
                     }
                     ty::TyUint(ast::UintTy::U8) | ty::TyUint(ast::UintTy::U16) => {
                         self.type_error_message(arg.span, |t| {
                             format!("can't pass `{}` to variadic \
                                      function, cast to `c_uint`",
                                            t)
-                        }, arg_ty, None);
+                        }, arg_ty);
                     }
                     ty::TyFnDef(_, _, f) => {
                         let ptr_ty = self.tcx.mk_fn_ptr(f);
@@ -2564,7 +2564,7 @@ fn parameter_count_error<'tcx>(sess: &Session, sp: Span, fn_inputs: &[Ty<'tcx>],
                                                 |t| {
                             format!("can't pass `{}` to variadic \
                                      function, cast to `{}`", t, ptr_ty)
-                        }, arg_ty, None);
+                        }, arg_ty);
                     }
                     _ => {}
                 }
@@ -2908,9 +2908,8 @@ fn check_field(&self,
             self.type_error_struct(field.span, |actual| {
                 format!("attempted to take value of method `{}` on type \
                          `{}`", field.node, actual)
-            }, expr_t, None)
-                .help(
-                       "maybe a `()` to call it is missing? \
+            }, expr_t)
+                .help("maybe a `()` to call it is missing? \
                        If not, try an anonymous function")
                 .emit();
             self.write_error(expr.id);
@@ -2919,7 +2918,7 @@ fn check_field(&self,
                 format!("attempted access of field `{}` on type `{}`, \
                          but no field with that name was found",
                         field.node, actual)
-            }, expr_t, None);
+            }, expr_t);
             if let ty::TyStruct(def, _) = expr_t.sty {
                 Self::suggest_field_names(&mut err, def.struct_variant(), field, vec![]);
             }
@@ -3019,7 +3018,7 @@ fn check_tup_field(&self,
                                     actual)
                 }
             },
-            expr_t, None);
+            expr_t);
 
         self.write_error(expr.id);
     }
@@ -3029,17 +3028,18 @@ fn report_unknown_field(&self,
                             variant: ty::VariantDef<'tcx>,
                             field: &hir::Field,
                             skip_fields: &[hir::Field]) {
-        let mut err = self.type_error_struct(
+        let mut err = self.type_error_struct_with_diag(
             field.name.span,
             |actual| if let ty::TyEnum(..) = ty.sty {
-                format!("struct variant `{}::{}` has no field named `{}`",
-                        actual, variant.name.as_str(), field.name.node)
+                struct_span_err!(self.tcx.sess, field.name.span, E0559,
+                                 "struct variant `{}::{}` has no field named `{}`",
+                                 actual, variant.name.as_str(), field.name.node)
             } else {
-                format!("structure `{}` has no field named `{}`",
-                        actual, field.name.node)
+                struct_span_err!(self.tcx.sess, field.name.span, E0560,
+                                 "structure `{}` has no field named `{}`",
+                                 actual, field.name.node)
             },
-            ty,
-            None);
+            ty);
         // prevent all specified fields from being suggested
         let skip_fields = skip_fields.iter().map(|ref x| x.name.node.as_str());
         Self::suggest_field_names(&mut err, variant, &field.name, skip_fields.collect());
@@ -3272,7 +3272,7 @@ fn check_expr_with_expectation_and_lvalue_pref(&self,
                             self.type_error_message(expr.span, |actual| {
                                 format!("type `{}` cannot be \
                                         dereferenced", actual)
-                            }, oprnd_t, None);
+                            }, oprnd_t);
                             oprnd_t = tcx.types.err;
                         }
                     }
@@ -3541,7 +3541,8 @@ fn check_expr_with_expectation_and_lvalue_pref(&self,
           }
           hir::ExprRepeat(ref element, ref count_expr) => {
             self.check_expr_has_type(&count_expr, tcx.types.usize);
-            let count = eval_repeat_count(self.tcx.global_tcx(), &count_expr);
+            let count = eval_length(self.tcx.global_tcx(), &count_expr, "repeat count")
+                  .unwrap_or(0);
 
             let uty = match expected {
                 ExpectHasType(uty) => {
@@ -3647,8 +3648,7 @@ fn check_expr_with_expectation_and_lvalue_pref(&self,
                                   format!("cannot index a value of type `{}`",
                                           actual)
                               },
-                              base_t,
-                              None);
+                              base_t);
                           // Try to give some advice about indexing tuples.
                           if let ty::TyTuple(_) = base_t.sty {
                               let mut needs_note = true;
@@ -4523,7 +4523,7 @@ fn structurally_resolve_type_or_else<F>(&self, sp: Span, ty: Ty<'tcx>, f: F)
                 if !self.is_tainted_by_errors() {
                     self.type_error_message(sp, |_actual| {
                         "the type of this value must be known in this context".to_string()
-                    }, ty, None);
+                    }, ty);
                 }
                 self.demand_suptype(sp, self.tcx.types.err, ty);
                 ty = self.tcx.types.err;
index 8604dadf46dff2f4011aa22f67fb948f0a634ea0..d02f87d0b9cd64236700279cd10bfc1744f0c7af 100644 (file)
@@ -239,7 +239,7 @@ pub fn check_user_unop(&self,
                 self.type_error_message(ex.span, |actual| {
                     format!("cannot apply unary operator `{}` to type `{}`",
                             op_str, actual)
-                }, operand_ty, None);
+                }, operand_ty);
                 self.tcx.types.err
             }
         }
index d101381e2565c72823332aefc602e721c228bfb8..907cb734c2ff9f00128641761e20eb9543b323fe 100644 (file)
@@ -13,6 +13,7 @@
 use CrateCtxt;
 use hir::def_id::DefId;
 use middle::region::{CodeExtent};
+use rustc::infer::TypeOrigin;
 use rustc::ty::subst::{self, TypeSpace, FnSpace, ParamSpace, SelfSpace};
 use rustc::traits;
 use rustc::ty::{self, Ty, TyCtxt};
@@ -157,7 +158,10 @@ fn check_item_well_formed(&mut self, item: &hir::Item) {
         }
     }
 
-    fn check_trait_or_impl_item(&mut self, item_id: ast::NodeId, span: Span) {
+    fn check_trait_or_impl_item(&mut self,
+                                item_id: ast::NodeId,
+                                span: Span,
+                                sig_if_method: Option<&hir::MethodSig>) {
         let code = self.code.clone();
         self.for_id(item_id, span).with_fcx(|fcx, this| {
             let free_substs = &fcx.parameter_environment.free_substs;
@@ -182,7 +186,8 @@ fn check_trait_or_impl_item(&mut self, item_id: ast::NodeId, span: Span) {
                     let predicates = fcx.instantiate_bounds(span, free_substs, &method.predicates);
                     this.check_fn_or_method(fcx, span, &method_ty, &predicates,
                                             free_id_outlive, &mut implied_bounds);
-                    this.check_method_receiver(fcx, span, &method,
+                    let sig_if_method = sig_if_method.expect("bad signature for method");
+                    this.check_method_receiver(fcx, sig_if_method, &method,
                                                free_id_outlive, self_ty);
                 }
                 ty::TypeTraitItem(assoc_type) => {
@@ -405,20 +410,15 @@ fn check_fn_or_method<'fcx, 'tcx>(&mut self,
 
     fn check_method_receiver<'fcx, 'tcx>(&mut self,
                                          fcx: &FnCtxt<'fcx, 'gcx, 'tcx>,
-                                         span: Span,
+                                         method_sig: &hir::MethodSig,
                                          method: &ty::Method<'tcx>,
                                          free_id_outlive: CodeExtent,
                                          self_ty: ty::Ty<'tcx>)
     {
         // check that the type of the method's receiver matches the
         // method's first parameter.
-
-        let free_substs = &fcx.parameter_environment.free_substs;
-        let fty = fcx.instantiate_type_scheme(span, free_substs, &method.fty);
-        let sig = fcx.tcx.liberate_late_bound_regions(free_id_outlive, &fty.sig);
-
-        debug!("check_method_receiver({:?},cat={:?},self_ty={:?},sig={:?})",
-               method.name, method.explicit_self, self_ty, sig);
+        debug!("check_method_receiver({:?},cat={:?},self_ty={:?})",
+               method.name, method.explicit_self, self_ty);
 
         let rcvr_ty = match method.explicit_self {
             ty::ExplicitSelfCategory::Static => return,
@@ -431,14 +431,23 @@ fn check_method_receiver<'fcx, 'tcx>(&mut self,
             }
             ty::ExplicitSelfCategory::ByBox => fcx.tcx.mk_box(self_ty)
         };
+
+        let span = method_sig.decl.inputs[0].pat.span;
+
+        let free_substs = &fcx.parameter_environment.free_substs;
+        let fty = fcx.instantiate_type_scheme(span, free_substs, &method.fty);
+        let sig = fcx.tcx.liberate_late_bound_regions(free_id_outlive, &fty.sig);
+
+        debug!("check_method_receiver: sig={:?}", sig);
+
         let rcvr_ty = fcx.instantiate_type_scheme(span, free_substs, &rcvr_ty);
         let rcvr_ty = fcx.tcx.liberate_late_bound_regions(free_id_outlive,
                                                           &ty::Binder(rcvr_ty));
 
         debug!("check_method_receiver: receiver ty = {:?}", rcvr_ty);
 
-        fcx.require_same_types(span, sig.inputs[0], rcvr_ty,
-                               "mismatched method receiver");
+        let origin = TypeOrigin::MethodReceiver(span);
+        fcx.demand_eqtype_with_origin(origin, rcvr_ty, sig.inputs[0]);
     }
 
     fn check_variances_for_type_defn(&self,
@@ -553,13 +562,21 @@ fn visit_item(&mut self, i: &hir::Item) {
 
     fn visit_trait_item(&mut self, trait_item: &'v hir::TraitItem) {
         debug!("visit_trait_item: {:?}", trait_item);
-        self.check_trait_or_impl_item(trait_item.id, trait_item.span);
+        let method_sig = match trait_item.node {
+            hir::TraitItem_::MethodTraitItem(ref sig, _) => Some(sig),
+            _ => None
+        };
+        self.check_trait_or_impl_item(trait_item.id, trait_item.span, method_sig);
         intravisit::walk_trait_item(self, trait_item)
     }
 
     fn visit_impl_item(&mut self, impl_item: &'v hir::ImplItem) {
         debug!("visit_impl_item: {:?}", impl_item);
-        self.check_trait_or_impl_item(impl_item.id, impl_item.span);
+        let method_sig = match impl_item.node {
+            hir::ImplItemKind::Method(ref sig, _) => Some(sig),
+            _ => None
+        };
+        self.check_trait_or_impl_item(impl_item.id, impl_item.span, method_sig);
         intravisit::walk_impl_item(self, impl_item)
     }
 }
index 41e7a467fa33a89ff80aa890306ccdaf63d1b511..57602b55cc96f10e5bb4110692cd481c361bdf95 100644 (file)
@@ -66,8 +66,7 @@
 use middle::lang_items::SizedTraitLangItem;
 use middle::const_val::ConstVal;
 use rustc_const_eval::EvalHint::UncheckedExprHint;
-use rustc_const_eval::{eval_const_expr_partial, ConstEvalErr};
-use rustc_const_eval::ErrKind::ErroneousReferencedConstant;
+use rustc_const_eval::{eval_const_expr_partial, report_const_eval_err};
 use rustc::ty::subst::{Substs, FnSpace, ParamSpace, SelfSpace, TypeSpace, VecPerParamSpace};
 use rustc::ty::{ToPredicate, ImplContainer, ImplOrTraitItemContainer, TraitContainer};
 use rustc::ty::{self, ToPolyTraitRef, Ty, TyCtxt, TypeScheme};
@@ -1091,14 +1090,9 @@ fn evaluate_disr_expr(ccx: &CrateCtxt, repr_ty: attr::IntType, e: &hir::Expr)
             },
             // enum variant evaluation happens before the global constant check
             // so we need to report the real error
-            Err(ConstEvalErr { kind: ErroneousReferencedConstant(box err), ..}) |
             Err(err) => {
-                let mut diag = struct_span_err!(ccx.tcx.sess, err.span, E0080,
-                                                "constant evaluation error: {}",
-                                                err.description());
-                if !e.span.contains(err.span) {
-                    diag.span_note(e.span, "for enum discriminant here");
-                }
+                let mut diag = report_const_eval_err(
+                    ccx.tcx, &err, e.span, "enum discriminant");
                 diag.emit();
                 None
             }
index 8769bc1a32b5080856297c7f7928c14e8b3eeb32..500f624ea3f72f870eece3b65108997dfc74f6f7 100644 (file)
@@ -1079,25 +1079,6 @@ fn get_str(&self) -> &'static str {
 ```
 "##,
 
-E0080: r##"
-This error indicates that the compiler was unable to sensibly evaluate an
-integer expression provided as an enum discriminant. Attempting to divide by 0
-or causing integer overflow are two ways to induce this error. For example:
-
-```compile_fail
-enum Enum {
-    X = (1 << 500),
-    Y = (1 / 0)
-}
-```
-
-Ensure that the expressions given can be evaluated as the desired integer type.
-See the FFI section of the Reference for more information about using a custom
-integer type:
-
-https://doc.rust-lang.org/reference.html#ffi-attributes
-"##,
-
 E0081: r##"
 Enum discriminants are used to differentiate enum variants stored in memory.
 This error indicates that the same value was used for two or more variants,
@@ -2660,6 +2641,7 @@ impl<P1, ..., Pm> ForeignTrait<T1, ..., Tn> for T0 { ... }
 [RFC 1023]: https://github.com/rust-lang/rfcs/pull/1023
 "##,
 
+/*
 E0211: r##"
 You used a function or type which doesn't fit the requirements for where it was
 used. Erroneous code examples:
@@ -2739,6 +2721,7 @@ fn x(self: Box<Foo>) {} // ok!
 }
 ```
 "##,
+     */
 
 E0214: r##"
 A generic type was described using parentheses rather than angle brackets. For
@@ -2968,38 +2951,6 @@ fn do_something(x: Foo::Bar) { }
 behavior for specific enum variants.
 "##,
 
-E0249: r##"
-This error indicates a constant expression for the array length was found, but
-it was not an integer (signed or unsigned) expression.
-
-Some examples of code that produces this error are:
-
-```compile_fail
-const A: [u32; "hello"] = []; // error
-const B: [u32; true] = []; // error
-const C: [u32; 0.0] = []; // error
-"##,
-
-E0250: r##"
-There was an error while evaluating the expression for the length of a fixed-
-size array type.
-
-Some examples of this error are:
-
-```compile_fail
-// divide by zero in the length expression
-const A: [u32; 1/0] = [];
-
-// Rust currently will not evaluate the function `foo` at compile time
-fn foo() -> usize { 12 }
-const B: [u32; foo()] = [];
-
-// it is an error to try to add `u8` and `f64`
-use std::{f64, u8};
-const C: [u32; u8::MAX + f64::EPSILON] = [];
-```
-"##,
-
 E0318: r##"
 Default impls for a trait must be located in the same crate where the trait was
 defined. For more information see the [opt-in builtin traits RFC](https://github
@@ -4029,6 +3980,57 @@ fn fly(&self) {} // And now that's ok!
 ```
 "##,
 
+E0559: r##"
+An unknown field was specified into an enum's structure variant.
+
+Erroneous code example:
+
+```compile_fail,E0559
+enum Field {
+    Fool { x: u32 },
+}
+
+let s = Field::Fool { joke: 0 };
+// error: struct variant `Field::Fool` has no field named `joke`
+```
+
+Verify you didn't misspell the field's name or that the field exists. Example:
+
+```
+enum Field {
+    Fool { joke: u32 },
+}
+
+let s = Field::Fool { joke: 0 }; // ok!
+```
+"##,
+
+E0560: r##"
+An unknown field was specified into a structure.
+
+Erroneous code example:
+
+```compile_fail,E0560
+struct Simba {
+    mother: u32,
+}
+
+let s = Simba { mother: 1, father: 0 };
+// error: structure `Simba` has no field named `father`
+```
+
+Verify you didn't misspell the field's name or that the field exists. Example:
+
+```
+struct Simba {
+    mother: u32,
+    father: u32,
+}
+
+let s = Simba { mother: 1, father: 0 }; // ok!
+```
+"##,
+
 }
 
 register_diagnostics! {
@@ -4086,6 +4088,7 @@ fn fly(&self) {} // And now that's ok!
     E0245, // not a trait
 //  E0246, // invalid recursive type
 //  E0247,
+//  E0249,
 //  E0319, // trait impls for defaulted traits allowed just for structs/enums
     E0320, // recursive overflow during dropck
     E0328, // cannot implement Unsize explicitly
index 84452589dfda389a9bc7e708c55dc16f9f497e9f..3b2d02dc861c4c62c0b8542f0b3f0da67eddbef8 100644 (file)
@@ -186,28 +186,14 @@ fn require_c_abi_if_variadic(tcx: TyCtxt,
     }
 }
 
-pub fn emit_type_err<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
-                                     span: Span,
-                                     found_ty: Ty<'tcx>,
-                                     expected_ty: Ty<'tcx>,
-                                     terr: &ty::error::TypeError<'tcx>,
-                                     msg: &str) {
-    let mut err = struct_span_err!(tcx.sess, span, E0211, "{}", msg);
-    err.span_label(span, &terr);
-    err.note_expected_found(&"type", &expected_ty, &found_ty);
-    tcx.note_and_explain_type_err(&mut err, terr, span);
-    err.emit();
-}
-
 fn require_same_types<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
-                                span: Span,
+                                origin: TypeOrigin,
                                 t1: Ty<'tcx>,
-                                t2: Ty<'tcx>,
-                                msg: &str)
+                                t2: Ty<'tcx>)
                                 -> bool {
     ccx.tcx.infer_ctxt(None, None, ProjectionMode::AnyFinal).enter(|infcx| {
-        if let Err(err) = infcx.eq_types(false, TypeOrigin::Misc(span), t1, t2) {
-            emit_type_err(infcx.tcx, span, t1, t2, &err, msg);
+        if let Err(err) = infcx.eq_types(false, origin.clone(), t1, t2) {
+            infcx.report_mismatched_types(origin, t1, t2, err);
             false
         } else {
             true
@@ -249,8 +235,11 @@ fn check_main_fn_ty(ccx: &CrateCtxt,
                 })
             }));
 
-            require_same_types(ccx, main_span, main_t, se_ty,
-                               "main function has wrong type");
+            require_same_types(
+                ccx,
+                TypeOrigin::MainFunctionType(main_span),
+                main_t,
+                se_ty);
         }
         _ => {
             span_bug!(main_span,
@@ -298,8 +287,11 @@ fn check_start_fn_ty(ccx: &CrateCtxt,
                 }),
             }));
 
-            require_same_types(ccx, start_span, start_t, se_ty,
-                               "start function has wrong type");
+            require_same_types(
+                ccx,
+                TypeOrigin::StartFunctionType(start_span),
+                start_t,
+                se_ty);
         }
         _ => {
             span_bug!(start_span,
index 7445ff94eb50277ca217c8f3627f7e4f8aa2ae98..1ea0f8d70a8eb70c5102ba9e041e093356d3178b 100644 (file)
@@ -392,7 +392,7 @@ pub fn len_utf16(self) -> usize {
         C::len_utf16(self)
     }
 
-    /// Returns an interator over the bytes of this character as UTF-8.
+    /// Returns an iterator over the bytes of this character as UTF-8.
     ///
     /// The returned iterator also has an `as_slice()` method to view the
     /// encoded bytes as a byte slice.
@@ -415,7 +415,7 @@ pub fn encode_utf8(self) -> EncodeUtf8 {
         C::encode_utf8(self)
     }
 
-    /// Returns an interator over the `u16` entries of this character as UTF-16.
+    /// Returns an iterator over the `u16` entries of this character as UTF-16.
     ///
     /// The returned iterator also has an `as_slice()` method to view the
     /// encoded form as a slice.
index 096e1ecc9ffb6a33a67b1dceb84a2b8837dd1d26..6cb79d6e8630f570d0ff065b37db361ed2c1795d 100644 (file)
@@ -233,6 +233,7 @@ fn write_token<W: Writer>(&mut self,
             token::Dot | token::DotDot | token::DotDotDot | token::Comma | token::Semi |
                 token::Colon | token::ModSep | token::LArrow | token::OpenDelim(_) |
                 token::CloseDelim(token::Brace) | token::CloseDelim(token::Paren) |
+                token::CloseDelim(token::NoDelim) |
                 token::Question => Class::None,
             token::Dollar => {
                 if self.lexer.peek().tok.is_ident() {
index 303cc671f4a230c79181cd8ad91ad8b66992b237..de0457592fc8834cfa5bbc62cf38bd2c1182f2fc 100644 (file)
@@ -636,8 +636,11 @@ span.since {
     margin-right: 5px;
 }
 
-.enum > .toggle-wrapper > .collapse-toggle, .struct > .toggle-wrapper > .collapse-toggle {
+.toggle-wrapper > .collapse-toggle {
     left: 0;
+}
+
+.variant + .toggle-wrapper > a {
     margin-top: 5px;
 }
 
index 60d7e01d98814a99dc61c725a6fd97c09713c7e2..fd7b0a2e6bbf6d9b0d8834c911e7dca320c7c298 100644 (file)
@@ -877,7 +877,7 @@ pub fn values(&self) -> Values<K, V> {
     /// }
     ///
     /// for val in map.values() {
-    ///     print!("{}", val);
+    ///     println!("{}", val);
     /// }
     /// ```
     #[stable(feature = "map_values_mut", since = "1.10.0")]
@@ -1336,6 +1336,10 @@ fn into_entry(self, key: K) -> Option<Entry<'a, K, V>> {
 }
 
 /// A view into a single location in a map, which may be vacant or occupied.
+/// This enum is constructed from the [`entry`] method on [`HashMap`].
+///
+/// [`HashMap`]: struct.HashMap.html
+/// [`entry`]: struct.HashMap.html#method.entry
 #[stable(feature = "rust1", since = "1.0.0")]
 pub enum Entry<'a, K: 'a, V: 'a> {
     /// An occupied Entry.
@@ -1351,14 +1355,44 @@ pub enum Entry<'a, K: 'a, V: 'a> {
     ),
 }
 
+#[stable(feature= "debug_hash_map", since = "1.12.0")]
+impl<'a, K: 'a + Debug, V: 'a + Debug> Debug for Entry<'a, K, V> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        match *self {
+            Vacant(ref v) => f.debug_tuple("Entry")
+                              .field(v)
+                              .finish(),
+            Occupied(ref o) => f.debug_tuple("Entry")
+                                .field(o)
+                                .finish(),
+        }
+    }
+}
+
 /// A view into a single occupied location in a HashMap.
+/// It is part of the [`Entry`] enum.
+///
+/// [`Entry`]: enum.Entry.html
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct OccupiedEntry<'a, K: 'a, V: 'a> {
     key: Option<K>,
     elem: FullBucket<K, V, &'a mut RawTable<K, V>>,
 }
 
+#[stable(feature= "debug_hash_map", since = "1.12.0")]
+impl<'a, K: 'a + Debug, V: 'a + Debug> Debug for OccupiedEntry<'a, K, V> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        f.debug_struct("OccupiedEntry")
+         .field("key", self.key())
+         .field("value", self.get())
+         .finish()
+    }
+}
+
 /// A view into a single empty location in a HashMap.
+/// It is part of the [`Entry`] enum.
+///
+/// [`Entry`]: enum.Entry.html
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct VacantEntry<'a, K: 'a, V: 'a> {
     hash: SafeHash,
@@ -1366,6 +1400,15 @@ pub struct VacantEntry<'a, K: 'a, V: 'a> {
     elem: VacantEntryState<K, V, &'a mut RawTable<K, V>>,
 }
 
+#[stable(feature= "debug_hash_map", since = "1.12.0")]
+impl<'a, K: 'a + Debug, V: 'a> Debug for VacantEntry<'a, K, V> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        f.debug_tuple("VacantEntry")
+         .field(self.key())
+         .finish()
+    }
+}
+
 /// Possible states of a VacantEntry.
 enum VacantEntryState<K, V, M> {
     /// The index is occupied, but the key to insert has precedence,
@@ -1518,6 +1561,20 @@ impl<'a, K, V> Entry<'a, K, V> {
     #[stable(feature = "rust1", since = "1.0.0")]
     /// Ensures a value is in the entry by inserting the default if empty, and returns
     /// a mutable reference to the value in the entry.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::collections::HashMap;
+    ///
+    /// let mut map: HashMap<&str, u32> = HashMap::new();
+    /// map.entry("poneyland").or_insert(12);
+    ///
+    /// assert_eq!(map["poneyland"], 12);
+    ///
+    /// *map.entry("poneyland").or_insert(12) += 10;
+    /// assert_eq!(map["poneyland"], 22);
+    /// ```
     pub fn or_insert(self, default: V) -> &'a mut V {
         match self {
             Occupied(entry) => entry.into_mut(),
@@ -1528,6 +1585,19 @@ pub fn or_insert(self, default: V) -> &'a mut V {
     #[stable(feature = "rust1", since = "1.0.0")]
     /// Ensures a value is in the entry by inserting the result of the default function if empty,
     /// and returns a mutable reference to the value in the entry.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::collections::HashMap;
+    ///
+    /// let mut map: HashMap<&str, String> = HashMap::new();
+    /// let s = "hoho".to_owned();
+    ///
+    /// map.entry("poneyland").or_insert_with(|| s);
+    ///
+    /// assert_eq!(map["poneyland"], "hoho".to_owned());
+    /// ```
     pub fn or_insert_with<F: FnOnce() -> V>(self, default: F) -> &'a mut V {
         match self {
             Occupied(entry) => entry.into_mut(),
@@ -1536,6 +1606,15 @@ pub fn or_insert_with<F: FnOnce() -> V>(self, default: F) -> &'a mut V {
     }
 
     /// Returns a reference to this entry's key.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::collections::HashMap;
+    ///
+    /// let mut map: HashMap<&str, u32> = HashMap::new();
+    /// assert_eq!(map.entry("poneyland").key(), &"poneyland");
+    /// ```
     #[stable(feature = "map_entry_keys", since = "1.10.0")]
     pub fn key(&self) -> &K {
         match *self {
@@ -1547,37 +1626,130 @@ pub fn key(&self) -> &K {
 
 impl<'a, K, V> OccupiedEntry<'a, K, V> {
     /// Gets a reference to the key in the entry.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::collections::HashMap;
+    ///
+    /// let mut map: HashMap<&str, u32> = HashMap::new();
+    /// map.entry("poneyland").or_insert(12);
+    /// assert_eq!(map.entry("poneyland").key(), &"poneyland");
+    /// ```
     #[stable(feature = "map_entry_keys", since = "1.10.0")]
     pub fn key(&self) -> &K {
         self.elem.read().0
     }
 
     /// Take the ownership of the key and value from the map.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(map_entry_recover_keys)]
+    ///
+    /// use std::collections::HashMap;
+    /// use std::collections::hash_map::Entry;
+    ///
+    /// let mut map: HashMap<&str, u32> = HashMap::new();
+    /// map.entry("poneyland").or_insert(12);
+    ///
+    /// if let Entry::Occupied(o) = map.entry("poneyland") {
+    ///     // We delete the entry from the map.
+    ///     o.remove_pair();
+    /// }
+    ///
+    /// assert_eq!(map.contains_key("poneyland"), false);
+    /// ```
     #[unstable(feature = "map_entry_recover_keys", issue = "34285")]
     pub fn remove_pair(self) -> (K, V) {
         pop_internal(self.elem)
     }
 
     /// Gets a reference to the value in the entry.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::collections::HashMap;
+    /// use std::collections::hash_map::Entry;
+    ///
+    /// let mut map: HashMap<&str, u32> = HashMap::new();
+    /// map.entry("poneyland").or_insert(12);
+    ///
+    /// if let Entry::Occupied(o) = map.entry("poneyland") {
+    ///     assert_eq!(o.get(), &12);
+    /// }
+    /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn get(&self) -> &V {
         self.elem.read().1
     }
 
     /// Gets a mutable reference to the value in the entry.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::collections::HashMap;
+    /// use std::collections::hash_map::Entry;
+    ///
+    /// let mut map: HashMap<&str, u32> = HashMap::new();
+    /// map.entry("poneyland").or_insert(12);
+    ///
+    /// assert_eq!(map["poneyland"], 12);
+    /// if let Entry::Occupied(mut o) = map.entry("poneyland") {
+    ///      *o.get_mut() += 10;
+    /// }
+    ///
+    /// assert_eq!(map["poneyland"], 22);
+    /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn get_mut(&mut self) -> &mut V {
         self.elem.read_mut().1
     }
 
     /// Converts the OccupiedEntry into a mutable reference to the value in the entry
-    /// with a lifetime bound to the map itself
+    /// with a lifetime bound to the map itself.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::collections::HashMap;
+    /// use std::collections::hash_map::Entry;
+    ///
+    /// let mut map: HashMap<&str, u32> = HashMap::new();
+    /// map.entry("poneyland").or_insert(12);
+    ///
+    /// assert_eq!(map["poneyland"], 12);
+    /// if let Entry::Occupied(o) = map.entry("poneyland") {
+    ///     *o.into_mut() += 10;
+    /// }
+    ///
+    /// assert_eq!(map["poneyland"], 22);
+    /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn into_mut(self) -> &'a mut V {
         self.elem.into_mut_refs().1
     }
 
-    /// Sets the value of the entry, and returns the entry's old value
+    /// Sets the value of the entry, and returns the entry's old value.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::collections::HashMap;
+    /// use std::collections::hash_map::Entry;
+    ///
+    /// let mut map: HashMap<&str, u32> = HashMap::new();
+    /// map.entry("poneyland").or_insert(12);
+    ///
+    /// if let Entry::Occupied(mut o) = map.entry("poneyland") {
+    ///     assert_eq!(o.insert(15), 12);
+    /// }
+    ///
+    /// assert_eq!(map["poneyland"], 15);
+    /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn insert(&mut self, mut value: V) -> V {
         let old_value = self.get_mut();
@@ -1585,7 +1757,23 @@ pub fn insert(&mut self, mut value: V) -> V {
         value
     }
 
-    /// Takes the value out of the entry, and returns it
+    /// Takes the value out of the entry, and returns it.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::collections::HashMap;
+    /// use std::collections::hash_map::Entry;
+    ///
+    /// let mut map: HashMap<&str, u32> = HashMap::new();
+    /// map.entry("poneyland").or_insert(12);
+    ///
+    /// if let Entry::Occupied(o) = map.entry("poneyland") {
+    ///     assert_eq!(o.remove(), 12);
+    /// }
+    ///
+    /// assert_eq!(map.contains_key("poneyland"), false);
+    /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn remove(self) -> V {
         pop_internal(self.elem).1
@@ -1601,20 +1789,58 @@ fn take_key(&mut self) -> Option<K> {
 
 impl<'a, K: 'a, V: 'a> VacantEntry<'a, K, V> {
     /// Gets a reference to the key that would be used when inserting a value
-    /// through the VacantEntry.
+    /// through the `VacantEntry`.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::collections::HashMap;
+    ///
+    /// let mut map: HashMap<&str, u32> = HashMap::new();
+    /// assert_eq!(map.entry("poneyland").key(), &"poneyland");
+    /// ```
     #[stable(feature = "map_entry_keys", since = "1.10.0")]
     pub fn key(&self) -> &K {
         &self.key
     }
 
     /// Take ownership of the key.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// #![feature(map_entry_recover_keys)]
+    ///
+    /// use std::collections::HashMap;
+    /// use std::collections::hash_map::Entry;
+    ///
+    /// let mut map: HashMap<&str, u32> = HashMap::new();
+    ///
+    /// if let Entry::Vacant(v) = map.entry("poneyland") {
+    ///     v.into_key();
+    /// }
+    /// ```
     #[unstable(feature = "map_entry_recover_keys", issue = "34285")]
     pub fn into_key(self) -> K {
         self.key
     }
 
     /// Sets the value of the entry with the VacantEntry's key,
-    /// and returns a mutable reference to it
+    /// and returns a mutable reference to it.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::collections::HashMap;
+    /// use std::collections::hash_map::Entry;
+    ///
+    /// let mut map: HashMap<&str, u32> = HashMap::new();
+    ///
+    /// if let Entry::Vacant(o) = map.entry("poneyland") {
+    ///     o.insert(37);
+    /// }
+    /// assert_eq!(map["poneyland"], 37);
+    /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn insert(self, value: V) -> &'a mut V {
         match self.elem {
@@ -1666,6 +1892,17 @@ fn extend<T: IntoIterator<Item=(&'a K, &'a V)>>(&mut self, iter: T) {
 /// A particular instance `RandomState` will create the same instances of
 /// `Hasher`, but the hashers created by two different `RandomState`
 /// instances are unlikely to produce the same result for the same values.
+///
+/// # Examples
+///
+/// ```
+/// use std::collections::HashMap;
+/// use std::collections::hash_map::RandomState;
+///
+/// let s = RandomState::new();
+/// let mut map = HashMap::with_hasher(s);
+/// map.insert(1, 2);
+/// ```
 #[derive(Clone)]
 #[stable(feature = "hashmap_build_hasher", since = "1.7.0")]
 pub struct RandomState {
@@ -1675,6 +1912,14 @@ pub struct RandomState {
 
 impl RandomState {
     /// Constructs a new `RandomState` that is initialized with random keys.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::collections::hash_map::RandomState;
+    ///
+    /// let s = RandomState::new();
+    /// ```
     #[inline]
     #[allow(deprecated)] // rand
     #[stable(feature = "hashmap_build_hasher", since = "1.7.0")]
index 6956dc0d901a44a9f235546463a80eb64f522218..d6d62ce79d4e6ff94aa780736adcce7d8b9da3ba 100644 (file)
@@ -493,6 +493,44 @@ pub fn temp_dir() -> PathBuf {
 /// that can fail for a good number of reasons. Some errors can include, but not
 /// be limited to, filesystem operations failing or general syscall failures.
 ///
+/// # Security
+///
+/// The output of this function should not be used in anything that might have
+/// security implications. For example:
+///
+/// ```
+/// fn main() {
+///     println!("{:?}", std::env::current_exe());
+/// }
+/// ```
+///
+/// On Linux systems, if this is compiled as `foo`:
+///
+/// ```bash
+/// $ rustc foo.rs
+/// $ ./foo
+/// Ok("/home/alex/foo")
+/// ```
+///
+/// And you make a symbolic link of the program:
+///
+/// ```bash
+/// $ ln foo bar
+/// ```
+///
+/// When you run it, you won't get the original executable, you'll get the
+/// symlink:
+///
+/// ```bash
+/// $ ./bar
+/// Ok("/home/alex/bar")
+/// ```
+///
+/// This sort of behavior has been known to [lead to privledge escalation] when
+/// used incorrectly, for example.
+///
+/// [lead to privledge escalation]: http://securityvulns.com/Wdocument183.html
+///
 /// # Examples
 ///
 /// ```
@@ -587,6 +625,13 @@ impl ExactSizeIterator for Args {
     fn len(&self) -> usize { self.inner.len() }
 }
 
+#[stable(feature = "env_iterators", since = "1.11.0")]
+impl DoubleEndedIterator for Args {
+    fn next_back(&mut self) -> Option<String> {
+        self.inner.next_back().map(|s| s.into_string().unwrap())
+    }
+}
+
 #[stable(feature = "env", since = "1.0.0")]
 impl Iterator for ArgsOs {
     type Item = OsString;
@@ -599,6 +644,10 @@ impl ExactSizeIterator for ArgsOs {
     fn len(&self) -> usize { self.inner.len() }
 }
 
+#[stable(feature = "env_iterators", since = "1.11.0")]
+impl DoubleEndedIterator for ArgsOs {
+    fn next_back(&mut self) -> Option<OsString> { self.inner.next_back() }
+}
 /// Constants associated with the current target
 #[stable(feature = "env", since = "1.0.0")]
 pub mod consts {
index 83439b3f132153eef1009c507e2bec78318aa408..48753ccf1c353cfe8ba172dbb347cf47c54f4f5e 100644 (file)
@@ -58,28 +58,37 @@ pub struct File {
 
 /// Metadata information about a file.
 ///
-/// This structure is returned from the `metadata` function or method and
+/// This structure is returned from the [`metadata`] function or method and
 /// represents known metadata about a file such as its permissions, size,
 /// modification times, etc.
+///
+/// [`metadata`]: fn.metadata.html
 #[stable(feature = "rust1", since = "1.0.0")]
 #[derive(Clone)]
 pub struct Metadata(fs_imp::FileAttr);
 
 /// Iterator over the entries in a directory.
 ///
-/// This iterator is returned from the `read_dir` function of this module and
-/// will yield instances of `io::Result<DirEntry>`. Through a `DirEntry`
+/// This iterator is returned from the [`read_dir`] function of this module and
+/// will yield instances of `io::Result<DirEntry>`. Through a [`DirEntry`]
 /// information like the entry's path and possibly other metadata can be
 /// learned.
 ///
+/// [`read_dir`]: fn.read_dir.html
+/// [`DirEntry`]: struct.DirEntry.html
+///
 /// # Errors
 ///
-/// This `io::Result` will be an `Err` if there's some sort of intermittent
+/// This [`io::Result`] will be an `Err` if there's some sort of intermittent
 /// IO error during iteration.
+///
+/// [`io::Result`]: ../io/type.Result.html
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct ReadDir(fs_imp::ReadDir);
 
-/// Entries returned by the `ReadDir` iterator.
+/// Entries returned by the [`ReadDir`] iterator.
+///
+/// [`ReadDir`]: struct.ReadDir.html
 ///
 /// An instance of `DirEntry` represents an entry inside of a directory on the
 /// filesystem. Each entry can be inspected via methods to learn about the full
@@ -89,17 +98,23 @@ pub struct File {
 
 /// Options and flags which can be used to configure how a file is opened.
 ///
-/// This builder exposes the ability to configure how a `File` is opened and
-/// what operations are permitted on the open file. The `File::open` and
-/// `File::create` methods are aliases for commonly used options using this
+/// This builder exposes the ability to configure how a [`File`] is opened and
+/// what operations are permitted on the open file. The [`File::open`] and
+/// [`File::create`] methods are aliases for commonly used options using this
 /// builder.
 ///
-/// Generally speaking, when using `OpenOptions`, you'll first call `new()`,
-/// then chain calls to methods to set each option, then call `open()`, passing
-/// the path of the file you're trying to open. This will give you a
+/// [`File`]: struct.File.html
+/// [`File::open`]: struct.File.html#method.open
+/// [`File::create`]: struct.File.html#method.create
+///
+/// Generally speaking, when using `OpenOptions`, you'll first call [`new()`],
+/// then chain calls to methods to set each option, then call [`open()`],
+/// passing the path of the file you're trying to open. This will give you a
 /// [`io::Result`][result] with a [`File`][file] inside that you can further
 /// operate on.
 ///
+/// [`new()`]: struct.OpenOptions.html#method.new
+/// [`open()`]: struct.OpenOptions.html#method.open
 /// [result]: ../io/type.Result.html
 /// [file]: struct.File.html
 ///
@@ -131,10 +146,12 @@ pub struct File {
 
 /// Representation of the various permissions on a file.
 ///
-/// This module only currently provides one bit of information, `readonly`,
+/// This module only currently provides one bit of information, [`readonly`],
 /// which is exposed on all currently supported platforms. Unix-specific
 /// functionality, such as mode bits, is available through the
 /// `os::unix::PermissionsExt` trait.
+///
+/// [`readonly`]: struct.Permissions.html#method.readonly
 #[derive(Clone, PartialEq, Eq, Debug)]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct Permissions(fs_imp::FilePermissions);
@@ -156,12 +173,14 @@ pub struct DirBuilder {
 impl File {
     /// Attempts to open a file in read-only mode.
     ///
-    /// See the `OpenOptions::open` method for more details.
+    /// See the [`OpenOptions::open`] method for more details.
     ///
     /// # Errors
     ///
     /// This function will return an error if `path` does not already exist.
-    /// Other errors may also be returned according to `OpenOptions::open`.
+    /// Other errors may also be returned according to [`OpenOptions::open`].
+    ///
+    /// [`OpenOptions::open`]: struct.OpenOptions.html#method.open
     ///
     /// # Examples
     ///
@@ -183,7 +202,9 @@ pub fn open<P: AsRef<Path>>(path: P) -> io::Result<File> {
     /// This function will create a file if it does not exist,
     /// and will truncate it if it does.
     ///
-    /// See the `OpenOptions::open` function for more details.
+    /// See the [`OpenOptions::open`] function for more details.
+    ///
+    /// [`OpenOptions::open`]: struct.OpenOptions.html#method.open
     ///
     /// # Examples
     ///
@@ -224,7 +245,7 @@ pub fn sync_all(&self) -> io::Result<()> {
         self.inner.fsync()
     }
 
-    /// This function is similar to `sync_all`, except that it may not
+    /// This function is similar to [`sync_all`], except that it may not
     /// synchronize file metadata to the filesystem.
     ///
     /// This is intended for use cases that must synchronize content, but don't
@@ -232,7 +253,9 @@ pub fn sync_all(&self) -> io::Result<()> {
     /// operations.
     ///
     /// Note that some platforms may simply implement this in terms of
-    /// `sync_all`.
+    /// [`sync_all`].
+    ///
+    /// [`sync_all`]: struct.File.html#method.sync_all
     ///
     /// # Examples
     ///
@@ -304,6 +327,18 @@ pub fn metadata(&self) -> io::Result<Metadata> {
     /// The returned `File` is a reference to the same state that this object
     /// references. Both handles will read and write with the same cursor
     /// position.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::fs::File;
+    ///
+    /// # fn foo() -> std::io::Result<()> {
+    /// let mut f = try!(File::open("foo.txt"));
+    /// let file_copy = try!(f.try_clone());
+    /// # Ok(())
+    /// # }
+    /// ```
     #[stable(feature = "file_try_clone", since = "1.9.0")]
     pub fn try_clone(&self) -> io::Result<File> {
         Ok(File {
@@ -791,8 +826,8 @@ fn next(&mut self) -> Option<io::Result<DirEntry>> {
 impl DirEntry {
     /// Returns the full path to the file that this entry represents.
     ///
-    /// The full path is created by joining the original path to `read_dir` or
-    /// `walk_dir` with the filename of this entry.
+    /// The full path is created by joining the original path to `read_dir`
+    /// with the filename of this entry.
     ///
     /// # Examples
     ///
@@ -829,6 +864,26 @@ pub fn path(&self) -> PathBuf { self.0.path() }
     /// On Windows this function is cheap to call (no extra system calls
     /// needed), but on Unix platforms this function is the equivalent of
     /// calling `symlink_metadata` on the path.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::fs;
+    ///
+    /// if let Ok(entries) = fs::read_dir(".") {
+    ///     for entry in entries {
+    ///         if let Ok(entry) = entry {
+    ///             // Here, `entry` is a `DirEntry`.
+    ///             if let Ok(metadata) = entry.metadata() {
+    ///                 // Now let's show our entry's permissions!
+    ///                 println!("{:?}: {:?}", entry.path(), metadata.permissions());
+    ///             } else {
+    ///                 println!("Couldn't get metadata for {:?}", entry.path());
+    ///             }
+    ///         }
+    ///     }
+    /// }
+    /// ```
     #[stable(feature = "dir_entry_ext", since = "1.1.0")]
     pub fn metadata(&self) -> io::Result<Metadata> {
         self.0.metadata().map(Metadata)
@@ -844,6 +899,26 @@ pub fn metadata(&self) -> io::Result<Metadata> {
     /// On Windows and most Unix platforms this function is free (no extra
     /// system calls needed), but some Unix platforms may require the equivalent
     /// call to `symlink_metadata` to learn about the target file type.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::fs;
+    ///
+    /// if let Ok(entries) = fs::read_dir(".") {
+    ///     for entry in entries {
+    ///         if let Ok(entry) = entry {
+    ///             // Here, `entry` is a `DirEntry`.
+    ///             if let Ok(file_type) = entry.file_type() {
+    ///                 // Now let's show our entry's file type!
+    ///                 println!("{:?}: {:?}", entry.path(), file_type);
+    ///             } else {
+    ///                 println!("Couldn't get file type for {:?}", entry.path());
+    ///             }
+    ///         }
+    ///     }
+    /// }
+    /// ```
     #[stable(feature = "dir_entry_ext", since = "1.1.0")]
     pub fn file_type(&self) -> io::Result<FileType> {
         self.0.file_type().map(FileType)
@@ -851,6 +926,21 @@ pub fn file_type(&self) -> io::Result<FileType> {
 
     /// Returns the bare file name of this directory entry without any other
     /// leading path component.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::fs;
+    ///
+    /// if let Ok(entries) = fs::read_dir(".") {
+    ///     for entry in entries {
+    ///         if let Ok(entry) = entry {
+    ///             // Here, `entry` is a `DirEntry`.
+    ///             println!("{:?}", entry.file_name());
+    ///         }
+    ///     }
+    /// }
+    /// ```
     #[stable(feature = "dir_entry_ext", since = "1.1.0")]
     pub fn file_name(&self) -> OsString {
         self.0.file_name()
@@ -1397,6 +1487,14 @@ pub fn set_permissions<P: AsRef<Path>>(path: P, perm: Permissions)
 impl DirBuilder {
     /// Creates a new set of options with default mode/security settings for all
     /// platforms and also non-recursive.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::fs::DirBuilder;
+    ///
+    /// let builder = DirBuilder::new();
+    /// ```
     #[stable(feature = "dir_builder", since = "1.6.0")]
     pub fn new() -> DirBuilder {
         DirBuilder {
@@ -1409,7 +1507,16 @@ pub fn new() -> DirBuilder {
     /// all parent directories if they do not exist with the same security and
     /// permissions settings.
     ///
-    /// This option defaults to `false`
+    /// This option defaults to `false`.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::fs::DirBuilder;
+    ///
+    /// let mut builder = DirBuilder::new();
+    /// builder.recursive(true);
+    /// ```
     #[stable(feature = "dir_builder", since = "1.6.0")]
     pub fn recursive(&mut self, recursive: bool) -> &mut Self {
         self.recursive = recursive;
index a058337a50afda4e2607ca3f9cd83e1511b0dfd9..d5b255ee57376fb9dac3495ad74a9d453477f9ce 100644 (file)
@@ -1522,6 +1522,18 @@ fn consume(&mut self, amt: usize) {
     }
 }
 
+fn read_one_byte(reader: &mut Read) -> Option<Result<u8>> {
+    let mut buf = [0];
+    loop {
+        return match reader.read(&mut buf) {
+            Ok(0) => None,
+            Ok(..) => Some(Ok(buf[0])),
+            Err(ref e) if e.kind() == ErrorKind::Interrupted => continue,
+            Err(e) => Some(Err(e)),
+        };
+    }
+}
+
 /// An iterator over `u8` values of a reader.
 ///
 /// This struct is generally created by calling [`bytes()`][bytes] on a reader.
@@ -1538,12 +1550,7 @@ impl<R: Read> Iterator for Bytes<R> {
     type Item = Result<u8>;
 
     fn next(&mut self) -> Option<Result<u8>> {
-        let mut buf = [0];
-        match self.inner.read(&mut buf) {
-            Ok(0) => None,
-            Ok(..) => Some(Ok(buf[0])),
-            Err(e) => Some(Err(e)),
-        }
+        read_one_byte(&mut self.inner)
     }
 }
 
@@ -1579,11 +1586,10 @@ impl<R: Read> Iterator for Chars<R> {
     type Item = result::Result<char, CharsError>;
 
     fn next(&mut self) -> Option<result::Result<char, CharsError>> {
-        let mut buf = [0];
-        let first_byte = match self.inner.read(&mut buf) {
-            Ok(0) => return None,
-            Ok(..) => buf[0],
-            Err(e) => return Some(Err(CharsError::Other(e))),
+        let first_byte = match read_one_byte(&mut self.inner) {
+            None => return None,
+            Some(Ok(b)) => b,
+            Some(Err(e)) => return Some(Err(CharsError::Other(e))),
         };
         let width = core_str::utf8_char_width(first_byte);
         if width == 1 { return Some(Ok(first_byte as char)) }
@@ -1595,6 +1601,7 @@ fn next(&mut self) -> Option<result::Result<char, CharsError>> {
                 match self.inner.read(&mut buf[start..width]) {
                     Ok(0) => return Some(Err(CharsError::NotUtf8)),
                     Ok(n) => start += n,
+                    Err(ref e) if e.kind() == ErrorKind::Interrupted => continue,
                     Err(e) => return Some(Err(CharsError::Other(e))),
                 }
             }
index 67410e87a8bea898050978c9eb5f0a898e40d942..2a8bd0c88beb6f535d2a53d81b839d3eb9cab951 100644 (file)
@@ -59,6 +59,66 @@ pub enum Ipv6MulticastScope {
     Global
 }
 
+impl IpAddr {
+    /// Returns true for the special 'unspecified' address ([IPv4], [IPv6]).
+    /// [IPv4]: ../../std/net/struct.Ipv4Addr.html#method.is_unspecified
+    /// [IPv6]: ../../std/net/struct.Ipv6Addr.html#method.is_unspecified
+    #[unstable(feature="ip", issue="27709",
+               reason="recently added and depends on unstable Ipv4Addr.is_unspecified()")]
+    pub fn is_unspecified(&self) -> bool {
+        match *self {
+            IpAddr::V4(ref a) => a.is_unspecified(),
+            IpAddr::V6(ref a) => a.is_unspecified(),
+        }
+    }
+
+    /// Returns true if this is a loopback address ([IPv4], [IPv6]).
+    /// [IPv4]: ../../std/net/struct.Ipv4Addr.html#method.is_loopback
+    /// [IPv6]: ../../std/net/struct.Ipv6Addr.html#method.is_loopback
+    #[unstable(feature="ip", reason="recently added", issue="27709")]
+    pub fn is_loopback(&self) -> bool {
+        match *self {
+            IpAddr::V4(ref a) => a.is_loopback(),
+            IpAddr::V6(ref a) => a.is_loopback(),
+        }
+    }
+
+    /// Returns true if the address appears to be globally routable ([IPv4], [IPv6]).
+    /// [IPv4]: ../../std/net/struct.Ipv4Addr.html#method.is_global
+    /// [IPv6]: ../../std/net/struct.Ipv6Addr.html#method.is_global
+    #[unstable(feature="ip", issue="27709",
+               reason="recently added and depends on unstable Ip{v4,v6}Addr.is_global()")]
+    pub fn is_global(&self) -> bool {
+        match *self {
+            IpAddr::V4(ref a) => a.is_global(),
+            IpAddr::V6(ref a) => a.is_global(),
+        }
+    }
+
+    /// Returns true if this is a multicast address ([IPv4], [IPv6]).
+    /// [IPv4]: ../../std/net/struct.Ipv4Addr.html#method.is_multicast
+    /// [IPv6]: ../../std/net/struct.Ipv6Addr.html#method.is_multicast
+    #[unstable(feature="ip", reason="recently added", issue="27709")]
+    pub fn is_multicast(&self) -> bool {
+        match *self {
+            IpAddr::V4(ref a) => a.is_multicast(),
+            IpAddr::V6(ref a) => a.is_multicast(),
+        }
+    }
+
+    /// Returns true if this address is in a range designated for documentation ([IPv4], [IPv6]).
+    /// [IPv4]: ../../std/net/struct.Ipv4Addr.html#method.is_documentation
+    /// [IPv6]: ../../std/net/struct.Ipv6Addr.html#method.is_documentation
+    #[unstable(feature="ip", issue="27709",
+               reason="recently added and depends on unstable Ipv6Addr.is_documentation()")]
+    pub fn is_documentation(&self) -> bool {
+        match *self {
+            IpAddr::V4(ref a) => a.is_documentation(),
+            IpAddr::V6(ref a) => a.is_documentation(),
+        }
+    }
+}
+
 impl Ipv4Addr {
     /// Creates a new IPv4 address from four eight-bit octets.
     ///
@@ -760,6 +820,67 @@ fn ipv6_to_ipv4() {
                    None);
     }
 
+    #[test]
+    fn ip_properties() {
+        fn check4(octets: &[u8; 4], unspec: bool, loopback: bool,
+                  global: bool, multicast: bool, documentation: bool) {
+            let ip = IpAddr::V4(Ipv4Addr::new(octets[0], octets[1], octets[2], octets[3]));
+            assert_eq!(ip.is_unspecified(), unspec);
+            assert_eq!(ip.is_loopback(), loopback);
+            assert_eq!(ip.is_global(), global);
+            assert_eq!(ip.is_multicast(), multicast);
+            assert_eq!(ip.is_documentation(), documentation);
+        }
+
+        fn check6(str_addr: &str, unspec: bool, loopback: bool,
+                  global: bool, u_doc: bool, mcast: bool) {
+            let ip = IpAddr::V6(str_addr.parse().unwrap());
+            assert_eq!(ip.is_unspecified(), unspec);
+            assert_eq!(ip.is_loopback(), loopback);
+            assert_eq!(ip.is_global(), global);
+            assert_eq!(ip.is_documentation(), u_doc);
+            assert_eq!(ip.is_multicast(), mcast);
+        }
+
+        //     address                unspec loopbk global multicast doc
+        check4(&[0, 0, 0, 0],         true,  false, false,  false,   false);
+        check4(&[0, 0, 0, 1],         false, false, true,   false,   false);
+        check4(&[0, 1, 0, 0],         false, false, true,   false,   false);
+        check4(&[10, 9, 8, 7],        false, false, false,  false,   false);
+        check4(&[127, 1, 2, 3],       false, true,  false,  false,   false);
+        check4(&[172, 31, 254, 253],  false, false, false,  false,   false);
+        check4(&[169, 254, 253, 242], false, false, false,  false,   false);
+        check4(&[192, 0, 2, 183],     false, false, false,  false,   true);
+        check4(&[192, 1, 2, 183],     false, false, true,   false,   false);
+        check4(&[192, 168, 254, 253], false, false, false,  false,   false);
+        check4(&[198, 51, 100, 0],    false, false, false,  false,   true);
+        check4(&[203, 0, 113, 0],     false, false, false,  false,   true);
+        check4(&[203, 2, 113, 0],     false, false, true,   false,   false);
+        check4(&[224, 0, 0, 0],       false, false, true,   true,    false);
+        check4(&[239, 255, 255, 255], false, false, true,   true,    false);
+        check4(&[255, 255, 255, 255], false, false, false,  false,   false);
+
+        //     address                            unspec loopbk global doc    mcast
+        check6("::",                              true,  false, false, false, false);
+        check6("::1",                             false, true,  false, false, false);
+        check6("::0.0.0.2",                       false, false, true,  false, false);
+        check6("1::",                             false, false, true,  false, false);
+        check6("fc00::",                          false, false, false, false, false);
+        check6("fdff:ffff::",                     false, false, false, false, false);
+        check6("fe80:ffff::",                     false, false, false, false, false);
+        check6("febf:ffff::",                     false, false, false, false, false);
+        check6("fec0::",                          false, false, false, false, false);
+        check6("ff01::",                          false, false, false, false, true);
+        check6("ff02::",                          false, false, false, false, true);
+        check6("ff03::",                          false, false, false, false, true);
+        check6("ff04::",                          false, false, false, false, true);
+        check6("ff05::",                          false, false, false, false, true);
+        check6("ff08::",                          false, false, false, false, true);
+        check6("ff0e::",                          false, false, true,  false, true);
+        check6("2001:db8:85a3::8a2e:370:7334",    false, false, false, true,  false);
+        check6("102:304:506:708:90a:b0c:d0e:f10", false, false, true,  false, false);
+    }
+
     #[test]
     fn ipv4_properties() {
         fn check(octets: &[u8; 4], unspec: bool, loopback: bool,
index d96fd6228e62ebe57a1388159b8431699bfa1edc..11f785dffd16a6b1f67cc0f5e542c02aa23c937a 100644 (file)
@@ -311,6 +311,17 @@ pub struct Iter<'a, T: 'a> {
     rx: &'a Receiver<T>
 }
 
+/// An iterator that attempts to yield all pending values for a receiver.
+/// `None` will be returned when there are no pending values remaining or
+/// if the corresponding channel has hung up.
+///
+/// This Iterator will never block the caller in order to wait for data to
+/// become available. Instead, it will return `None`.
+#[unstable(feature = "receiver_try_iter", issue = "34931")]
+pub struct TryIter<'a, T: 'a> {
+    rx: &'a Receiver<T>
+}
+
 /// An owning iterator over messages on a receiver, this iterator will block
 /// whenever `next` is called, waiting for a new message, and `None` will be
 /// returned when the corresponding channel has hung up.
@@ -982,6 +993,16 @@ fn recv_max_until(&self, deadline: Instant) -> Result<T, RecvTimeoutError> {
     pub fn iter(&self) -> Iter<T> {
         Iter { rx: self }
     }
+
+    /// Returns an iterator that will attempt to yield all pending values.
+    /// It will return `None` if there are no more pending values or if the
+    /// channel has hung up. The iterator will never `panic!` or block the
+    /// user by waiting for values.
+    #[unstable(feature = "receiver_try_iter", issue = "34931")]
+    pub fn try_iter(&self) -> TryIter<T> {
+        TryIter { rx: self }
+    }
+
 }
 
 impl<T> select::Packet for Receiver<T> {
@@ -1077,6 +1098,13 @@ impl<'a, T> Iterator for Iter<'a, T> {
     fn next(&mut self) -> Option<T> { self.rx.recv().ok() }
 }
 
+#[unstable(feature = "receiver_try_iter", issue = "34931")]
+impl<'a, T> Iterator for TryIter<'a, T> {
+    type Item = T;
+
+    fn next(&mut self) -> Option<T> { self.rx.try_recv().ok() }
+}
+
 #[stable(feature = "receiver_into_iter", since = "1.1.0")]
 impl<'a, T> IntoIterator for &'a Receiver<T> {
     type Item = T;
@@ -1814,6 +1842,34 @@ fn test_recv_iter_break() {
         assert_eq!(count_rx.recv().unwrap(), 4);
     }
 
+    #[test]
+    fn test_recv_try_iter() {
+        let (request_tx, request_rx) = channel();
+        let (response_tx, response_rx) = channel();
+
+        // Request `x`s until we have `6`.
+        let t = thread::spawn(move|| {
+            let mut count = 0;
+            loop {
+                for x in response_rx.try_iter() {
+                    count += x;
+                    if count == 6 {
+                        return count;
+                    }
+                }
+                request_tx.send(()).unwrap();
+            }
+        });
+
+        for _ in request_rx.iter() {
+            if response_tx.send(2).is_err() {
+                break;
+            }
+        }
+
+        assert_eq!(t.join().unwrap(), 6);
+    }
+
     #[test]
     fn test_recv_into_iter_owned() {
         let mut iter = {
index bb90a977433e0c5f2c37db74c1ffe8817e08c8d7..54340773a42b52e5bb672e41edde061cc487f769 100644 (file)
@@ -196,6 +196,22 @@ fn is_socket(&self) -> bool { self.as_inner().is(libc::S_IFSOCK) }
 pub trait DirEntryExt {
     /// Returns the underlying `d_ino` field in the contained `dirent`
     /// structure.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::fs;
+    /// use std::os::unix::fs::DirEntryExt;
+    ///
+    /// if let Ok(entries) = fs::read_dir(".") {
+    ///     for entry in entries {
+    ///         if let Ok(entry) = entry {
+    ///             // Here, `entry` is a `DirEntry`.
+    ///             println!("{:?}: {}", entry.file_name(), entry.ino());
+    ///         }
+    ///     }
+    /// }
+    /// ```
     #[stable(feature = "dir_entry_ext", since = "1.1.0")]
     fn ino(&self) -> u64;
 }
@@ -239,6 +255,16 @@ pub fn symlink<P: AsRef<Path>, Q: AsRef<Path>>(src: P, dst: Q) -> io::Result<()>
 pub trait DirBuilderExt {
     /// Sets the mode to create new directories with. This option defaults to
     /// 0o777.
+    ///
+    /// # Examples
+    ///
+    /// ```ignore
+    /// use std::fs::DirBuilder;
+    /// use std::os::unix::fs::DirBuilderExt;
+    ///
+    /// let mut builder = DirBuilder::new();
+    /// builder.mode(0o755);
+    /// ```
     #[stable(feature = "dir_builder", since = "1.6.0")]
     fn mode(&mut self, mode: u32) -> &mut Self;
 }
index 63e13f0bb473849c6b8073190fcc8d8158fb9bc5..4c3558f91f5f22e65cf3c3892f45af47576e9a60 100644 (file)
@@ -317,6 +317,10 @@ impl ExactSizeIterator for Args {
     fn len(&self) -> usize { self.iter.len() }
 }
 
+impl DoubleEndedIterator for Args {
+    fn next_back(&mut self) -> Option<OsString> { self.iter.next_back() }
+}
+
 /// Returns the command line arguments
 ///
 /// Returns a list of the command line arguments.
index 32ca32e76cb626aee457870c00020279bf5d5127..0cea7f81e363237fa745023505916db18df864fc 100644 (file)
@@ -278,23 +278,30 @@ pub struct Args {
     cur: *mut *mut u16,
 }
 
+unsafe fn os_string_from_ptr(ptr: *mut u16) -> OsString {
+    let mut len = 0;
+    while *ptr.offset(len) != 0 { len += 1; }
+
+    // Push it onto the list.
+    let ptr = ptr as *const u16;
+    let buf = slice::from_raw_parts(ptr, len as usize);
+    OsStringExt::from_wide(buf)
+}
+
 impl Iterator for Args {
     type Item = OsString;
     fn next(&mut self) -> Option<OsString> {
-        self.range.next().map(|i| unsafe {
-            let ptr = *self.cur.offset(i);
-            let mut len = 0;
-            while *ptr.offset(len) != 0 { len += 1; }
-
-            // Push it onto the list.
-            let ptr = ptr as *const u16;
-            let buf = slice::from_raw_parts(ptr, len as usize);
-            OsStringExt::from_wide(buf)
-        })
+        self.range.next().map(|i| unsafe { os_string_from_ptr(*self.cur.offset(i)) } )
     }
     fn size_hint(&self) -> (usize, Option<usize>) { self.range.size_hint() }
 }
 
+impl DoubleEndedIterator for Args {
+    fn next_back(&mut self) -> Option<OsString> {
+        self.range.next_back().map(|i| unsafe { os_string_from_ptr(*self.cur.offset(i)) } )
+    }
+}
+
 impl ExactSizeIterator for Args {
     fn len(&self) -> usize { self.range.len() }
 }
index ffc950d76dd27f43047bb06e54def08e5f265266..b70e270df54d2a08ef7169bd34219a1077cf6e8f 100644 (file)
@@ -581,9 +581,10 @@ fn mk_binop(cx: &ExtCtxt, sp: Span, bop: token::BinOpToken) -> P<ast::Expr> {
 
 fn mk_delim(cx: &ExtCtxt, sp: Span, delim: token::DelimToken) -> P<ast::Expr> {
     let name = match delim {
-        token::Paren     => "Paren",
-        token::Bracket   => "Bracket",
-        token::Brace     => "Brace",
+        token::Paren   => "Paren",
+        token::Bracket => "Bracket",
+        token::Brace   => "Brace",
+        token::NoDelim => "NoDelim",
     };
     mk_token_path(cx, sp, name)
 }
index 125f1abb062bf2966b17a31cb428edd4a8fe6620..c143e190c6fc16ce814c785d88aab8e0d5889974 100644 (file)
@@ -258,6 +258,7 @@ pub struct Parser<'a> {
     pub tokens_consumed: usize,
     pub restrictions: Restrictions,
     pub quote_depth: usize, // not (yet) related to the quasiquoter
+    parsing_token_tree: bool,
     pub reader: Box<Reader+'a>,
     /// The set of seen errors about obsolete syntax. Used to suppress
     /// extra detail when the same error is seen twice
@@ -374,6 +375,7 @@ pub fn new(sess: &'a ParseSess,
             tokens_consumed: 0,
             restrictions: Restrictions::empty(),
             quote_depth: 0,
+            parsing_token_tree: false,
             obsolete_set: HashSet::new(),
             mod_path_stack: Vec::new(),
             filename: filename,
@@ -2663,7 +2665,7 @@ fn parse_unquoted(&mut self) -> PResult<'a, TokenTree> {
     }
 
     pub fn check_unknown_macro_variable(&mut self) {
-        if self.quote_depth == 0 {
+        if self.quote_depth == 0 && !self.parsing_token_tree {
             match self.token {
                 token::SubstNt(name) =>
                     self.fatal(&format!("unknown macro variable `{}`", name)).emit(),
@@ -2723,6 +2725,7 @@ pub fn parse_token_tree(&mut self) -> PResult<'a, TokenTree> {
                 Err(err)
             },
             token::OpenDelim(delim) => {
+                let parsing_token_tree = ::std::mem::replace(&mut self.parsing_token_tree, true);
                 // The span for beginning of the delimited section
                 let pre_span = self.span;
 
@@ -2787,6 +2790,7 @@ pub fn parse_token_tree(&mut self) -> PResult<'a, TokenTree> {
                     _ => {}
                 }
 
+                self.parsing_token_tree = parsing_token_tree;
                 Ok(TokenTree::Delimited(span, Rc::new(Delimited {
                     delim: delim,
                     open_span: open_span,
index f0a6f8edeec73a241622a50a937b604c5896c6bd..6fdc9b714d34724202173d5417087ba1ea0bd4f3 100644 (file)
@@ -48,6 +48,8 @@ pub enum DelimToken {
     Bracket,
     /// A curly brace: `{` or `}`
     Brace,
+    /// An empty delimiter
+    NoDelim,
 }
 
 #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Hash, Debug, Copy)]
index 8866ffc2575cca42176d10f1c77c1162d67d2446..a619da84b2d510529d679312641bf89b257b50e0 100644 (file)
@@ -242,6 +242,8 @@ pub fn token_to_string(tok: &Token) -> String {
         token::CloseDelim(token::Bracket) => "]".to_string(),
         token::OpenDelim(token::Brace) => "{".to_string(),
         token::CloseDelim(token::Brace) => "}".to_string(),
+        token::OpenDelim(token::NoDelim) => " ".to_string(),
+        token::CloseDelim(token::NoDelim) => " ".to_string(),
         token::Pound                => "#".to_string(),
         token::Dollar               => "$".to_string(),
         token::Question             => "?".to_string(),
@@ -1777,12 +1779,14 @@ pub fn print_mac(&mut self, m: &ast::Mac, delim: token::DelimToken)
                 try!(self.head(""));
                 try!(self.bopen());
             }
+            token::NoDelim => {}
         }
         try!(self.print_tts(&m.node.tts));
         match delim {
             token::Paren => self.pclose(),
             token::Bracket => word(&mut self.s, "]"),
             token::Brace => self.bclose(m.span),
+            token::NoDelim => Ok(()),
         }
     }
 
index 36818e000b55bf0d3f94fdcd73325f77122ac202..cfc98bf36871f5d78353ff9903ba8ee4c6ba5fdf 100644 (file)
 use deriving::generic::ty::*;
 
 use syntax::ast::MetaItem;
-use syntax::ext::base::{ExtCtxt, Annotatable};
+use syntax::ext::base::{Annotatable, ExtCtxt};
 use syntax_pos::Span;
 
 pub fn expand_deriving_unsafe_bound(cx: &mut ExtCtxt,
                                     span: Span,
                                     _: &MetaItem,
                                     _: &Annotatable,
-                                    _: &mut FnMut(Annotatable))
-{
+                                    _: &mut FnMut(Annotatable)) {
     cx.span_err(span, "this unsafe trait should be implemented explicitly");
 }
 
@@ -28,8 +27,7 @@ pub fn expand_deriving_copy(cx: &mut ExtCtxt,
                             span: Span,
                             mitem: &MetaItem,
                             item: &Annotatable,
-                            push: &mut FnMut(Annotatable))
-{
+                            push: &mut FnMut(Annotatable)) {
     let mut v = cx.crate_root.map(|s| vec![s]).unwrap_or(Vec::new());
     v.push("marker");
     v.push("Copy");
index 1e47ebb85837a761a9596bfafcb1369ba783db7e..ce8ce2209d8c4513038fb21f84780c7aa870537d 100644 (file)
 use deriving::generic::*;
 use deriving::generic::ty::*;
 
-use syntax::ast::{Expr, ItemKind, Generics, MetaItem, VariantData};
+use syntax::ast::{Expr, Generics, ItemKind, MetaItem, VariantData};
 use syntax::attr;
-use syntax::ext::base::{ExtCtxt, Annotatable};
+use syntax::ext::base::{Annotatable, ExtCtxt};
 use syntax::ext::build::AstBuilder;
 use syntax::parse::token::InternedString;
 use syntax::ptr::P;
 use syntax_pos::Span;
 
 #[derive(PartialEq)]
-enum Mode { Deep, Shallow }
+enum Mode {
+    Deep,
+    Shallow,
+}
 
 pub fn expand_deriving_clone(cx: &mut ExtCtxt,
                              span: Span,
                              mitem: &MetaItem,
                              item: &Annotatable,
-                             push: &mut FnMut(Annotatable))
-{
+                             push: &mut FnMut(Annotatable)) {
     // check if we can use a short form
     //
     // the short form is `fn clone(&self) -> Self { *self }`
@@ -46,8 +48,8 @@ pub fn expand_deriving_clone(cx: &mut ExtCtxt,
             match annitem.node {
                 ItemKind::Struct(_, Generics { ref ty_params, .. }) |
                 ItemKind::Enum(_, Generics { ref ty_params, .. })
-                    if ty_params.is_empty()
-                        && attr::contains_name(&annitem.attrs, "derive_Copy") => {
+                    if ty_params.is_empty() &&
+                       attr::contains_name(&annitem.attrs, "derive_Copy") => {
 
                     bounds = vec![Literal(path_std!(cx, core::marker::Copy))];
                     unify_fieldless_variants = true;
@@ -66,11 +68,11 @@ pub fn expand_deriving_clone(cx: &mut ExtCtxt,
             }
         }
 
-        _ => cx.span_bug(span, "#[derive(Clone)] on trait item or impl item")
+        _ => cx.span_bug(span, "#[derive(Clone)] on trait item or impl item"),
     }
 
     let inline = cx.meta_word(span, InternedString::new("inline"));
-    let attrs = vec!(cx.attribute(span, inline));
+    let attrs = vec![cx.attribute(span, inline)];
     let trait_def = TraitDef {
         span: span,
         attributes: Vec::new(),
@@ -78,42 +80,41 @@ pub fn expand_deriving_clone(cx: &mut ExtCtxt,
         additional_bounds: bounds,
         generics: LifetimeBounds::empty(),
         is_unsafe: false,
-        methods: vec!(
-            MethodDef {
-                name: "clone",
-                generics: LifetimeBounds::empty(),
-                explicit_self: borrowed_explicit_self(),
-                args: Vec::new(),
-                ret_ty: Self_,
-                attributes: attrs,
-                is_unsafe: false,
-                unify_fieldless_variants: unify_fieldless_variants,
-                combine_substructure: substructure,
-            }
-        ),
+        methods: vec![MethodDef {
+                          name: "clone",
+                          generics: LifetimeBounds::empty(),
+                          explicit_self: borrowed_explicit_self(),
+                          args: Vec::new(),
+                          ret_ty: Self_,
+                          attributes: attrs,
+                          is_unsafe: false,
+                          unify_fieldless_variants: unify_fieldless_variants,
+                          combine_substructure: substructure,
+                      }],
         associated_types: Vec::new(),
     };
 
     trait_def.expand(cx, mitem, item, push)
 }
 
-fn cs_clone(
-    name: &str,
-    cx: &mut ExtCtxt, trait_span: Span,
-    substr: &Substructure,
-    mode: Mode) -> P<Expr> {
+fn cs_clone(name: &str,
+            cx: &mut ExtCtxt,
+            trait_span: Span,
+            substr: &Substructure,
+            mode: Mode)
+            -> P<Expr> {
     let ctor_path;
     let all_fields;
     let fn_path = match mode {
         Mode::Shallow => cx.std_path(&["clone", "assert_receiver_is_clone"]),
-        Mode::Deep  => cx.std_path(&["clone", "Clone", "clone"]),
+        Mode::Deep => cx.std_path(&["clone", "Clone", "clone"]),
     };
     let subcall = |field: &FieldInfo| {
         let args = vec![cx.expr_addr_of(field.span, field.self_.clone())];
 
         let span = if mode == Mode::Shallow {
             // set the expn ID so we can call the unstable method
-            Span { expn_id: cx.backtrace(), .. trait_span }
+            Span { expn_id: cx.backtrace(), ..trait_span }
         } else {
             field.span
         };
@@ -131,15 +132,15 @@ fn cs_clone(
             ctor_path = cx.path(trait_span, vec![substr.type_ident, variant.node.name]);
             all_fields = af;
             vdata = &variant.node.data;
-        },
-        EnumNonMatchingCollapsed (..) => {
+        }
+        EnumNonMatchingCollapsed(..) => {
             cx.span_bug(trait_span,
                         &format!("non-matching enum variants in \
-                                 `derive({})`", name))
+                                 `derive({})`",
+                                 name))
         }
         StaticEnum(..) | StaticStruct(..) => {
-            cx.span_bug(trait_span,
-                        &format!("static method in `derive({})`", name))
+            cx.span_bug(trait_span, &format!("static method in `derive({})`", name))
         }
     }
 
@@ -153,17 +154,20 @@ fn cs_clone(
         Mode::Deep => {
             match *vdata {
                 VariantData::Struct(..) => {
-                    let fields = all_fields.iter().map(|field| {
-                        let ident = match field.name {
-                            Some(i) => i,
-                            None => {
-                                cx.span_bug(trait_span,
-                                            &format!("unnamed field in normal struct in \
-                                                     `derive({})`", name))
-                            }
-                        };
-                        cx.field_imm(field.span, ident, subcall(field))
-                    }).collect::<Vec<_>>();
+                    let fields = all_fields.iter()
+                        .map(|field| {
+                            let ident = match field.name {
+                                Some(i) => i,
+                                None => {
+                                    cx.span_bug(trait_span,
+                                                &format!("unnamed field in normal struct in \
+                                                     `derive({})`",
+                                                         name))
+                                }
+                            };
+                            cx.field_imm(field.span, ident, subcall(field))
+                        })
+                        .collect::<Vec<_>>();
 
                     cx.expr_struct(trait_span, ctor_path, fields)
                 }
@@ -172,9 +176,7 @@ fn cs_clone(
                     let path = cx.expr_path(ctor_path);
                     cx.expr_call(trait_span, path, subcalls)
                 }
-                VariantData::Unit(..) => {
-                    cx.expr_path(ctor_path)
-                }
+                VariantData::Unit(..) => cx.expr_path(ctor_path),
             }
         }
     }
index 9c5072eeb3e0b79dc9ba58c4b447eba4efc146a9..2ab0f0ff54669c40e94e3fa0cd99f734ae672fdb 100644 (file)
@@ -11,8 +11,8 @@
 use deriving::generic::*;
 use deriving::generic::ty::*;
 
-use syntax::ast::{MetaItem, Expr};
-use syntax::ext::base::{ExtCtxt, Annotatable};
+use syntax::ast::{Expr, MetaItem};
+use syntax::ext::base::{Annotatable, ExtCtxt};
 use syntax::ext::build::AstBuilder;
 use syntax::parse::token::InternedString;
 use syntax::ptr::P;
@@ -22,30 +22,27 @@ pub fn expand_deriving_eq(cx: &mut ExtCtxt,
                           span: Span,
                           mitem: &MetaItem,
                           item: &Annotatable,
-                          push: &mut FnMut(Annotatable))
-{
+                          push: &mut FnMut(Annotatable)) {
     fn cs_total_eq_assert(cx: &mut ExtCtxt, span: Span, substr: &Substructure) -> P<Expr> {
-        cs_same_method(
-            |cx, span, exprs| {
-                // create `a.<method>(); b.<method>(); c.<method>(); ...`
-                // (where method is `assert_receiver_is_total_eq`)
-                let stmts = exprs.into_iter().map(|e| cx.stmt_expr(e)).collect();
-                let block = cx.block(span, stmts);
-                cx.expr_block(block)
-            },
-            Box::new(|cx, sp, _, _| {
-                cx.span_bug(sp, "non matching enums in derive(Eq)?") }),
-            cx,
-            span,
-            substr
-        )
+        cs_same_method(|cx, span, exprs| {
+            // create `a.<method>(); b.<method>(); c.<method>(); ...`
+            // (where method is `assert_receiver_is_total_eq`)
+            let stmts = exprs.into_iter().map(|e| cx.stmt_expr(e)).collect();
+            let block = cx.block(span, stmts);
+            cx.expr_block(block)
+        },
+                       Box::new(|cx, sp, _, _| {
+                           cx.span_bug(sp, "non matching enums in derive(Eq)?")
+                       }),
+                       cx,
+                       span,
+                       substr)
     }
 
     let inline = cx.meta_word(span, InternedString::new("inline"));
     let hidden = cx.meta_word(span, InternedString::new("hidden"));
-    let doc = cx.meta_list(span, InternedString::new("doc"), vec!(hidden));
-    let attrs = vec!(cx.attribute(span, inline),
-                     cx.attribute(span, doc));
+    let doc = cx.meta_list(span, InternedString::new("doc"), vec![hidden]);
+    let attrs = vec![cx.attribute(span, inline), cx.attribute(span, doc)];
     let trait_def = TraitDef {
         span: span,
         attributes: Vec::new(),
@@ -53,21 +50,19 @@ fn cs_total_eq_assert(cx: &mut ExtCtxt, span: Span, substr: &Substructure) -> P<
         additional_bounds: Vec::new(),
         generics: LifetimeBounds::empty(),
         is_unsafe: false,
-        methods: vec!(
-            MethodDef {
-                name: "assert_receiver_is_total_eq",
-                generics: LifetimeBounds::empty(),
-                explicit_self: borrowed_explicit_self(),
-                args: vec!(),
-                ret_ty: nil_ty(),
-                attributes: attrs,
-                is_unsafe: false,
-                unify_fieldless_variants: true,
-                combine_substructure: combine_substructure(Box::new(|a, b, c| {
-                    cs_total_eq_assert(a, b, c)
-                }))
-            }
-        ),
+        methods: vec![MethodDef {
+                          name: "assert_receiver_is_total_eq",
+                          generics: LifetimeBounds::empty(),
+                          explicit_self: borrowed_explicit_self(),
+                          args: vec![],
+                          ret_ty: nil_ty(),
+                          attributes: attrs,
+                          is_unsafe: false,
+                          unify_fieldless_variants: true,
+                          combine_substructure: combine_substructure(Box::new(|a, b, c| {
+                              cs_total_eq_assert(a, b, c)
+                          })),
+                      }],
         associated_types: Vec::new(),
     };
     trait_def.expand(cx, mitem, item, push)
index cbd7ac0eadad039ae287dc25781ed596f0edee3a..8ae77e79310b2805886363bbf7c23b2b50a35d32 100644 (file)
@@ -11,8 +11,8 @@
 use deriving::generic::*;
 use deriving::generic::ty::*;
 
-use syntax::ast::{MetaItem, Expr, self};
-use syntax::ext::base::{ExtCtxt, Annotatable};
+use syntax::ast::{self, Expr, MetaItem};
+use syntax::ext::base::{Annotatable, ExtCtxt};
 use syntax::ext::build::AstBuilder;
 use syntax::parse::token::InternedString;
 use syntax::ptr::P;
@@ -22,10 +22,9 @@ pub fn expand_deriving_ord(cx: &mut ExtCtxt,
                            span: Span,
                            mitem: &MetaItem,
                            item: &Annotatable,
-                           push: &mut FnMut(Annotatable))
-{
+                           push: &mut FnMut(Annotatable)) {
     let inline = cx.meta_word(span, InternedString::new("inline"));
-    let attrs = vec!(cx.attribute(span, inline));
+    let attrs = vec![cx.attribute(span, inline)];
     let trait_def = TraitDef {
         span: span,
         attributes: Vec::new(),
@@ -33,21 +32,19 @@ pub fn expand_deriving_ord(cx: &mut ExtCtxt,
         additional_bounds: Vec::new(),
         generics: LifetimeBounds::empty(),
         is_unsafe: false,
-        methods: vec!(
-            MethodDef {
-                name: "cmp",
-                generics: LifetimeBounds::empty(),
-                explicit_self: borrowed_explicit_self(),
-                args: vec!(borrowed_self()),
-                ret_ty: Literal(path_std!(cx, core::cmp::Ordering)),
-                attributes: attrs,
-                is_unsafe: false,
-                unify_fieldless_variants: true,
-                combine_substructure: combine_substructure(Box::new(|a, b, c| {
-                    cs_cmp(a, b, c)
-                })),
-            }
-        ),
+        methods: vec![MethodDef {
+                          name: "cmp",
+                          generics: LifetimeBounds::empty(),
+                          explicit_self: borrowed_explicit_self(),
+                          args: vec![borrowed_self()],
+                          ret_ty: Literal(path_std!(cx, core::cmp::Ordering)),
+                          attributes: attrs,
+                          is_unsafe: false,
+                          unify_fieldless_variants: true,
+                          combine_substructure: combine_substructure(Box::new(|a, b, c| {
+                              cs_cmp(a, b, c)
+                          })),
+                      }],
         associated_types: Vec::new(),
     };
 
@@ -57,76 +54,73 @@ pub fn expand_deriving_ord(cx: &mut ExtCtxt,
 
 pub fn ordering_collapsed(cx: &mut ExtCtxt,
                           span: Span,
-                          self_arg_tags: &[ast::Ident]) -> P<ast::Expr> {
+                          self_arg_tags: &[ast::Ident])
+                          -> P<ast::Expr> {
     let lft = cx.expr_ident(span, self_arg_tags[0]);
     let rgt = cx.expr_addr_of(span, cx.expr_ident(span, self_arg_tags[1]));
     cx.expr_method_call(span, lft, cx.ident_of("cmp"), vec![rgt])
 }
 
-pub fn cs_cmp(cx: &mut ExtCtxt, span: Span,
-              substr: &Substructure) -> P<Expr> {
+pub fn cs_cmp(cx: &mut ExtCtxt, span: Span, substr: &Substructure) -> P<Expr> {
     let test_id = cx.ident_of("__cmp");
-    let equals_path = cx.path_global(span,
-                                     cx.std_path(&["cmp", "Ordering", "Equal"]));
+    let equals_path = cx.path_global(span, cx.std_path(&["cmp", "Ordering", "Equal"]));
 
     let cmp_path = cx.std_path(&["cmp", "Ord", "cmp"]);
 
-    /*
-    Builds:
+    // Builds:
+    //
+    // match ::std::cmp::Ord::cmp(&self_field1, &other_field1) {
+    // ::std::cmp::Ordering::Equal =>
+    // match ::std::cmp::Ord::cmp(&self_field2, &other_field2) {
+    // ::std::cmp::Ordering::Equal => {
+    // ...
+    // }
+    // __cmp => __cmp
+    // },
+    // __cmp => __cmp
+    // }
+    //
+    cs_fold(// foldr nests the if-elses correctly, leaving the first field
+            // as the outermost one, and the last as the innermost.
+            false,
+            |cx, span, old, self_f, other_fs| {
+        // match new {
+        //     ::std::cmp::Ordering::Equal => old,
+        //     __cmp => __cmp
+        // }
 
-    match ::std::cmp::Ord::cmp(&self_field1, &other_field1) {
-        ::std::cmp::Ordering::Equal =>
-            match ::std::cmp::Ord::cmp(&self_field2, &other_field2) {
-                ::std::cmp::Ordering::Equal => {
-                    ...
-                }
-                __cmp => __cmp
-            },
-        __cmp => __cmp
-    }
-    */
-    cs_fold(
-        // foldr nests the if-elses correctly, leaving the first field
-        // as the outermost one, and the last as the innermost.
-        false,
-        |cx, span, old, self_f, other_fs| {
-            // match new {
-            //     ::std::cmp::Ordering::Equal => old,
-            //     __cmp => __cmp
-            // }
-
-            let new = {
-                let other_f = match (other_fs.len(), other_fs.get(0)) {
-                    (1, Some(o_f)) => o_f,
-                    _ => cx.span_bug(span, "not exactly 2 arguments in `derive(Ord)`"),
-                };
+        let new = {
+            let other_f = match (other_fs.len(), other_fs.get(0)) {
+                (1, Some(o_f)) => o_f,
+                _ => cx.span_bug(span, "not exactly 2 arguments in `derive(Ord)`"),
+            };
 
-                let args = vec![
+            let args = vec![
                     cx.expr_addr_of(span, self_f),
                     cx.expr_addr_of(span, other_f.clone()),
                 ];
 
-                cx.expr_call_global(span, cmp_path.clone(), args)
-            };
+            cx.expr_call_global(span, cmp_path.clone(), args)
+        };
 
-            let eq_arm = cx.arm(span,
-                                vec![cx.pat_enum(span,
-                                                 equals_path.clone(),
-                                                 vec![])],
-                                old);
-            let neq_arm = cx.arm(span,
-                                 vec![cx.pat_ident(span, test_id)],
-                                 cx.expr_ident(span, test_id));
+        let eq_arm = cx.arm(span,
+                            vec![cx.pat_enum(span, equals_path.clone(), vec![])],
+                            old);
+        let neq_arm = cx.arm(span,
+                             vec![cx.pat_ident(span, test_id)],
+                             cx.expr_ident(span, test_id));
 
-            cx.expr_match(span, new, vec![eq_arm, neq_arm])
-        },
-        cx.expr_path(equals_path.clone()),
-        Box::new(|cx, span, (self_args, tag_tuple), _non_self_args| {
-            if self_args.len() != 2 {
-                cx.span_bug(span, "not exactly 2 arguments in `derive(Ord)`")
-            } else {
-                ordering_collapsed(cx, span, tag_tuple)
-            }
-        }),
-        cx, span, substr)
+        cx.expr_match(span, new, vec![eq_arm, neq_arm])
+    },
+            cx.expr_path(equals_path.clone()),
+            Box::new(|cx, span, (self_args, tag_tuple), _non_self_args| {
+        if self_args.len() != 2 {
+            cx.span_bug(span, "not exactly 2 arguments in `derive(Ord)`")
+        } else {
+            ordering_collapsed(cx, span, tag_tuple)
+        }
+    }),
+            cx,
+            span,
+            substr)
 }
index b5a8167fb555093be14b8940764d6c4d33f2bd43..f70e0cf4ac45768048ff1070b605372a9cd20959 100644 (file)
@@ -11,8 +11,8 @@
 use deriving::generic::*;
 use deriving::generic::ty::*;
 
-use syntax::ast::{MetaItem, Expr, BinOpKind};
-use syntax::ext::base::{ExtCtxt, Annotatable};
+use syntax::ast::{BinOpKind, Expr, MetaItem};
+use syntax::ext::base::{Annotatable, ExtCtxt};
 use syntax::ext::build::AstBuilder;
 use syntax::parse::token::InternedString;
 use syntax::ptr::P;
@@ -22,43 +22,44 @@ pub fn expand_deriving_partial_eq(cx: &mut ExtCtxt,
                                   span: Span,
                                   mitem: &MetaItem,
                                   item: &Annotatable,
-                                  push: &mut FnMut(Annotatable))
-{
+                                  push: &mut FnMut(Annotatable)) {
     // structures are equal if all fields are equal, and non equal, if
     // any fields are not equal or if the enum variants are different
     fn cs_eq(cx: &mut ExtCtxt, span: Span, substr: &Substructure) -> P<Expr> {
-        cs_fold(
-            true,  // use foldl
-            |cx, span, subexpr, self_f, other_fs| {
-                let other_f = match (other_fs.len(), other_fs.get(0)) {
-                    (1, Some(o_f)) => o_f,
-                    _ => cx.span_bug(span, "not exactly 2 arguments in `derive(PartialEq)`")
-                };
+        cs_fold(true, // use foldl
+                |cx, span, subexpr, self_f, other_fs| {
+            let other_f = match (other_fs.len(), other_fs.get(0)) {
+                (1, Some(o_f)) => o_f,
+                _ => cx.span_bug(span, "not exactly 2 arguments in `derive(PartialEq)`"),
+            };
 
-                let eq = cx.expr_binary(span, BinOpKind::Eq, self_f, other_f.clone());
+            let eq = cx.expr_binary(span, BinOpKind::Eq, self_f, other_f.clone());
 
-                cx.expr_binary(span, BinOpKind::And, subexpr, eq)
-            },
-            cx.expr_bool(span, true),
-            Box::new(|cx, span, _, _| cx.expr_bool(span, false)),
-            cx, span, substr)
+            cx.expr_binary(span, BinOpKind::And, subexpr, eq)
+        },
+                cx.expr_bool(span, true),
+                Box::new(|cx, span, _, _| cx.expr_bool(span, false)),
+                cx,
+                span,
+                substr)
     }
     fn cs_ne(cx: &mut ExtCtxt, span: Span, substr: &Substructure) -> P<Expr> {
-        cs_fold(
-            true,  // use foldl
-            |cx, span, subexpr, self_f, other_fs| {
-                let other_f = match (other_fs.len(), other_fs.get(0)) {
-                    (1, Some(o_f)) => o_f,
-                    _ => cx.span_bug(span, "not exactly 2 arguments in `derive(PartialEq)`")
-                };
+        cs_fold(true, // use foldl
+                |cx, span, subexpr, self_f, other_fs| {
+            let other_f = match (other_fs.len(), other_fs.get(0)) {
+                (1, Some(o_f)) => o_f,
+                _ => cx.span_bug(span, "not exactly 2 arguments in `derive(PartialEq)`"),
+            };
 
-                let eq = cx.expr_binary(span, BinOpKind::Ne, self_f, other_f.clone());
+            let eq = cx.expr_binary(span, BinOpKind::Ne, self_f, other_f.clone());
 
-                cx.expr_binary(span, BinOpKind::Or, subexpr, eq)
-            },
-            cx.expr_bool(span, false),
-            Box::new(|cx, span, _, _| cx.expr_bool(span, true)),
-            cx, span, substr)
+            cx.expr_binary(span, BinOpKind::Or, subexpr, eq)
+        },
+                cx.expr_bool(span, false),
+                Box::new(|cx, span, _, _| cx.expr_bool(span, true)),
+                cx,
+                span,
+                substr)
     }
 
     macro_rules! md {
index 26c14ae934f72796e58c20b6727d04603ff50bdc..10a9738742e4486c470f6e531eee3b1c9cefd89f 100644 (file)
@@ -13,8 +13,8 @@
 use deriving::generic::*;
 use deriving::generic::ty::*;
 
-use syntax::ast::{MetaItem, Expr, BinOpKind, self};
-use syntax::ext::base::{ExtCtxt, Annotatable};
+use syntax::ast::{self, BinOpKind, Expr, MetaItem};
+use syntax::ext::base::{Annotatable, ExtCtxt};
 use syntax::ext::build::AstBuilder;
 use syntax::parse::token::InternedString;
 use syntax::ptr::P;
@@ -24,8 +24,7 @@ pub fn expand_deriving_partial_ord(cx: &mut ExtCtxt,
                                    span: Span,
                                    mitem: &MetaItem,
                                    item: &Annotatable,
-                                   push: &mut FnMut(Annotatable))
-{
+                                   push: &mut FnMut(Annotatable)) {
     macro_rules! md {
         ($name:expr, $op:expr, $equal:expr) => { {
             let inline = cx.meta_word(span, InternedString::new("inline"));
@@ -53,7 +52,7 @@ macro_rules! md {
                                     true));
 
     let inline = cx.meta_word(span, InternedString::new("inline"));
-    let attrs = vec!(cx.attribute(span, inline));
+    let attrs = vec![cx.attribute(span, inline)];
 
     let partial_cmp_def = MethodDef {
         name: "partial_cmp",
@@ -66,7 +65,7 @@ macro_rules! md {
         unify_fieldless_variants: true,
         combine_substructure: combine_substructure(Box::new(|cx, span, substr| {
             cs_partial_cmp(cx, span, substr)
-        }))
+        })),
     };
 
     // avoid defining extra methods if we can
@@ -75,13 +74,11 @@ macro_rules! md {
     let methods = if is_type_without_fields(item) {
         vec![partial_cmp_def]
     } else {
-        vec![
-            partial_cmp_def,
-            md!("lt", true, false),
-            md!("le", true, true),
-            md!("gt", false, false),
-            md!("ge", false, true)
-        ]
+        vec![partial_cmp_def,
+             md!("lt", true, false),
+             md!("le", true, true),
+             md!("gt", false, false),
+             md!("ge", false, true)]
     };
 
     let trait_def = TraitDef {
@@ -99,142 +96,146 @@ macro_rules! md {
 
 #[derive(Copy, Clone)]
 pub enum OrderingOp {
-    PartialCmpOp, LtOp, LeOp, GtOp, GeOp,
+    PartialCmpOp,
+    LtOp,
+    LeOp,
+    GtOp,
+    GeOp,
 }
 
 pub fn some_ordering_collapsed(cx: &mut ExtCtxt,
                                span: Span,
                                op: OrderingOp,
-                               self_arg_tags: &[ast::Ident]) -> P<ast::Expr> {
+                               self_arg_tags: &[ast::Ident])
+                               -> P<ast::Expr> {
     let lft = cx.expr_ident(span, self_arg_tags[0]);
     let rgt = cx.expr_addr_of(span, cx.expr_ident(span, self_arg_tags[1]));
     let op_str = match op {
         PartialCmpOp => "partial_cmp",
-        LtOp => "lt", LeOp => "le",
-        GtOp => "gt", GeOp => "ge",
+        LtOp => "lt",
+        LeOp => "le",
+        GtOp => "gt",
+        GeOp => "ge",
     };
     cx.expr_method_call(span, lft, cx.ident_of(op_str), vec![rgt])
 }
 
-pub fn cs_partial_cmp(cx: &mut ExtCtxt, span: Span,
-              substr: &Substructure) -> P<Expr> {
+pub fn cs_partial_cmp(cx: &mut ExtCtxt, span: Span, substr: &Substructure) -> P<Expr> {
     let test_id = cx.ident_of("__cmp");
-    let ordering = cx.path_global(span,
-                                  cx.std_path(&["cmp", "Ordering", "Equal"]));
+    let ordering = cx.path_global(span, cx.std_path(&["cmp", "Ordering", "Equal"]));
     let ordering_expr = cx.expr_path(ordering.clone());
     let equals_expr = cx.expr_some(span, ordering_expr);
 
     let partial_cmp_path = cx.std_path(&["cmp", "PartialOrd", "partial_cmp"]);
 
-    /*
-    Builds:
-
-    match ::std::cmp::PartialOrd::partial_cmp(&self_field1, &other_field1) {
-        ::std::option::Option::Some(::std::cmp::Ordering::Equal) =>
-            match ::std::cmp::PartialOrd::partial_cmp(&self_field2, &other_field2) {
-                ::std::option::Option::Some(::std::cmp::Ordering::Equal) => {
-                    ...
-                }
-                __cmp => __cmp
-            },
-        __cmp => __cmp
-    }
-    */
-    cs_fold(
-        // foldr nests the if-elses correctly, leaving the first field
-        // as the outermost one, and the last as the innermost.
-        false,
-        |cx, span, old, self_f, other_fs| {
-            // match new {
-            //     Some(::std::cmp::Ordering::Equal) => old,
-            //     __cmp => __cmp
-            // }
-
-            let new = {
-                let other_f = match (other_fs.len(), other_fs.get(0)) {
-                    (1, Some(o_f)) => o_f,
-                    _ => cx.span_bug(span, "not exactly 2 arguments in `derive(PartialOrd)`"),
-                };
-
-                let args = vec![
+    // Builds:
+    //
+    // match ::std::cmp::PartialOrd::partial_cmp(&self_field1, &other_field1) {
+    // ::std::option::Option::Some(::std::cmp::Ordering::Equal) =>
+    // match ::std::cmp::PartialOrd::partial_cmp(&self_field2, &other_field2) {
+    // ::std::option::Option::Some(::std::cmp::Ordering::Equal) => {
+    // ...
+    // }
+    // __cmp => __cmp
+    // },
+    // __cmp => __cmp
+    // }
+    //
+    cs_fold(// foldr nests the if-elses correctly, leaving the first field
+            // as the outermost one, and the last as the innermost.
+            false,
+            |cx, span, old, self_f, other_fs| {
+        // match new {
+        //     Some(::std::cmp::Ordering::Equal) => old,
+        //     __cmp => __cmp
+        // }
+
+        let new = {
+            let other_f = match (other_fs.len(), other_fs.get(0)) {
+                (1, Some(o_f)) => o_f,
+                _ => cx.span_bug(span, "not exactly 2 arguments in `derive(PartialOrd)`"),
+            };
+
+            let args = vec![
                     cx.expr_addr_of(span, self_f),
                     cx.expr_addr_of(span, other_f.clone()),
                 ];
 
-                cx.expr_call_global(span, partial_cmp_path.clone(), args)
-            };
-
-            let eq_arm = cx.arm(span,
-                                vec![cx.pat_some(span,
-                                                 cx.pat_enum(span,
-                                                             ordering.clone(),
-                                                             vec![]))],
-                                old);
-            let neq_arm = cx.arm(span,
-                                 vec![cx.pat_ident(span, test_id)],
-                                 cx.expr_ident(span, test_id));
-
-            cx.expr_match(span, new, vec![eq_arm, neq_arm])
-        },
-        equals_expr.clone(),
-        Box::new(|cx, span, (self_args, tag_tuple), _non_self_args| {
-            if self_args.len() != 2 {
-                cx.span_bug(span, "not exactly 2 arguments in `derive(PartialOrd)`")
-            } else {
-                some_ordering_collapsed(cx, span, PartialCmpOp, tag_tuple)
-            }
-        }),
-        cx, span, substr)
+            cx.expr_call_global(span, partial_cmp_path.clone(), args)
+        };
+
+        let eq_arm = cx.arm(span,
+                            vec![cx.pat_some(span, cx.pat_enum(span, ordering.clone(), vec![]))],
+                            old);
+        let neq_arm = cx.arm(span,
+                             vec![cx.pat_ident(span, test_id)],
+                             cx.expr_ident(span, test_id));
+
+        cx.expr_match(span, new, vec![eq_arm, neq_arm])
+    },
+            equals_expr.clone(),
+            Box::new(|cx, span, (self_args, tag_tuple), _non_self_args| {
+        if self_args.len() != 2 {
+            cx.span_bug(span, "not exactly 2 arguments in `derive(PartialOrd)`")
+        } else {
+            some_ordering_collapsed(cx, span, PartialCmpOp, tag_tuple)
+        }
+    }),
+            cx,
+            span,
+            substr)
 }
 
 /// Strict inequality.
-fn cs_op(less: bool, equal: bool, cx: &mut ExtCtxt,
-         span: Span, substr: &Substructure) -> P<Expr> {
+fn cs_op(less: bool, equal: bool, cx: &mut ExtCtxt, span: Span, substr: &Substructure) -> P<Expr> {
     let op = if less { BinOpKind::Lt } else { BinOpKind::Gt };
-    cs_fold(
-        false, // need foldr,
-        |cx, span, subexpr, self_f, other_fs| {
-            /*
-            build up a series of chain ||'s and &&'s from the inside
-            out (hence foldr) to get lexical ordering, i.e. for op ==
-            `ast::lt`
-
-            ```
-            self.f1 < other.f1 || (!(other.f1 < self.f1) &&
-                (self.f2 < other.f2 || (!(other.f2 < self.f2) &&
-                    (false)
-                ))
-            )
-            ```
-
-            The optimiser should remove the redundancy. We explicitly
-            get use the binops to avoid auto-deref dereferencing too many
-            layers of pointers, if the type includes pointers.
-            */
-            let other_f = match (other_fs.len(), other_fs.get(0)) {
-                (1, Some(o_f)) => o_f,
-                _ => cx.span_bug(span, "not exactly 2 arguments in `derive(PartialOrd)`")
+    cs_fold(false, // need foldr,
+            |cx, span, subexpr, self_f, other_fs| {
+        // build up a series of chain ||'s and &&'s from the inside
+        // out (hence foldr) to get lexical ordering, i.e. for op ==
+        // `ast::lt`
+        //
+        // ```
+        // self.f1 < other.f1 || (!(other.f1 < self.f1) &&
+        // (self.f2 < other.f2 || (!(other.f2 < self.f2) &&
+        // (false)
+        // ))
+        // )
+        // ```
+        //
+        // The optimiser should remove the redundancy. We explicitly
+        // get use the binops to avoid auto-deref dereferencing too many
+        // layers of pointers, if the type includes pointers.
+        //
+        let other_f = match (other_fs.len(), other_fs.get(0)) {
+            (1, Some(o_f)) => o_f,
+            _ => cx.span_bug(span, "not exactly 2 arguments in `derive(PartialOrd)`"),
+        };
+
+        let cmp = cx.expr_binary(span, op, self_f.clone(), other_f.clone());
+
+        let not_cmp = cx.expr_unary(span,
+                                    ast::UnOp::Not,
+                                    cx.expr_binary(span, op, other_f.clone(), self_f));
+
+        let and = cx.expr_binary(span, BinOpKind::And, not_cmp, subexpr);
+        cx.expr_binary(span, BinOpKind::Or, cmp, and)
+    },
+            cx.expr_bool(span, equal),
+            Box::new(|cx, span, (self_args, tag_tuple), _non_self_args| {
+        if self_args.len() != 2 {
+            cx.span_bug(span, "not exactly 2 arguments in `derive(PartialOrd)`")
+        } else {
+            let op = match (less, equal) {
+                (true, true) => LeOp,
+                (true, false) => LtOp,
+                (false, true) => GeOp,
+                (false, false) => GtOp,
             };
-
-            let cmp = cx.expr_binary(span, op, self_f.clone(), other_f.clone());
-
-            let not_cmp = cx.expr_unary(span, ast::UnOp::Not,
-                                        cx.expr_binary(span, op, other_f.clone(), self_f));
-
-            let and = cx.expr_binary(span, BinOpKind::And, not_cmp, subexpr);
-            cx.expr_binary(span, BinOpKind::Or, cmp, and)
-        },
-        cx.expr_bool(span, equal),
-        Box::new(|cx, span, (self_args, tag_tuple), _non_self_args| {
-            if self_args.len() != 2 {
-                cx.span_bug(span, "not exactly 2 arguments in `derive(PartialOrd)`")
-            } else {
-                let op = match (less, equal) {
-                    (true,  true) => LeOp, (true,  false) => LtOp,
-                    (false, true) => GeOp, (false, false) => GtOp,
-                };
-                some_ordering_collapsed(cx, span, op, tag_tuple)
-            }
-        }),
-        cx, span, substr)
+            some_ordering_collapsed(cx, span, op, tag_tuple)
+        }
+    }),
+            cx,
+            span,
+            substr)
 }
index 34c872bef11d10916698f2a57a6475dfe798fa66..a31c695e360490e7e6077f4ce995c3514f028d6a 100644 (file)
 use deriving::generic::ty::*;
 
 use syntax::ast;
-use syntax::ast::{MetaItem, Expr};
-use syntax::ext::base::{ExtCtxt, Annotatable};
+use syntax::ast::{Expr, MetaItem};
+use syntax::ext::base::{Annotatable, ExtCtxt};
 use syntax::ext::build::AstBuilder;
 use syntax::parse::token;
 use syntax::ptr::P;
-use syntax_pos::{Span, DUMMY_SP};
+use syntax_pos::{DUMMY_SP, Span};
 
 pub fn expand_deriving_debug(cx: &mut ExtCtxt,
-                            span: Span,
-                            mitem: &MetaItem,
-                            item: &Annotatable,
-                            push: &mut FnMut(Annotatable))
-{
+                             span: Span,
+                             mitem: &MetaItem,
+                             item: &Annotatable,
+                             push: &mut FnMut(Annotatable)) {
     // &mut ::std::fmt::Formatter
     let fmtr = Ptr(Box::new(Literal(path_std!(cx, core::fmt::Formatter))),
                    Borrowed(None, ast::Mutability::Mutable));
@@ -36,57 +35,54 @@ pub fn expand_deriving_debug(cx: &mut ExtCtxt,
         additional_bounds: Vec::new(),
         generics: LifetimeBounds::empty(),
         is_unsafe: false,
-        methods: vec![
-            MethodDef {
-                name: "fmt",
-                generics: LifetimeBounds::empty(),
-                explicit_self: borrowed_explicit_self(),
-                args: vec!(fmtr),
-                ret_ty: Literal(path_std!(cx, core::fmt::Result)),
-                attributes: Vec::new(),
-                is_unsafe: false,
-                unify_fieldless_variants: false,
-                combine_substructure: combine_substructure(Box::new(|a, b, c| {
-                    show_substructure(a, b, c)
-                }))
-            }
-        ],
+        methods: vec![MethodDef {
+                          name: "fmt",
+                          generics: LifetimeBounds::empty(),
+                          explicit_self: borrowed_explicit_self(),
+                          args: vec![fmtr],
+                          ret_ty: Literal(path_std!(cx, core::fmt::Result)),
+                          attributes: Vec::new(),
+                          is_unsafe: false,
+                          unify_fieldless_variants: false,
+                          combine_substructure: combine_substructure(Box::new(|a, b, c| {
+                              show_substructure(a, b, c)
+                          })),
+                      }],
         associated_types: Vec::new(),
     };
     trait_def.expand(cx, mitem, item, push)
 }
 
 /// We use the debug builders to do the heavy lifting here
-fn show_substructure(cx: &mut ExtCtxt, span: Span,
-                     substr: &Substructure) -> P<Expr> {
+fn show_substructure(cx: &mut ExtCtxt, span: Span, substr: &Substructure) -> P<Expr> {
     // build fmt.debug_struct(<name>).field(<fieldname>, &<fieldval>)....build()
     // or fmt.debug_tuple(<name>).field(&<fieldval>)....build()
     // based on the "shape".
     let (ident, is_struct) = match *substr.fields {
         Struct(vdata, _) => (substr.type_ident, vdata.is_struct()),
         EnumMatching(_, v, _) => (v.node.name, v.node.data.is_struct()),
-        EnumNonMatchingCollapsed(..) | StaticStruct(..) | StaticEnum(..) => {
-            cx.span_bug(span, "nonsensical .fields in `#[derive(Debug)]`")
-        }
+        EnumNonMatchingCollapsed(..) |
+        StaticStruct(..) |
+        StaticEnum(..) => cx.span_bug(span, "nonsensical .fields in `#[derive(Debug)]`"),
     };
 
     // We want to make sure we have the expn_id set so that we can use unstable methods
-    let span = Span { expn_id: cx.backtrace(), .. span };
-    let name = cx.expr_lit(span, ast::LitKind::Str(ident.name.as_str(), ast::StrStyle::Cooked));
+    let span = Span { expn_id: cx.backtrace(), ..span };
+    let name = cx.expr_lit(span,
+                           ast::LitKind::Str(ident.name.as_str(), ast::StrStyle::Cooked));
     let builder = token::str_to_ident("builder");
     let builder_expr = cx.expr_ident(span, builder.clone());
 
     let fmt = substr.nonself_args[0].clone();
 
     let mut stmts = match *substr.fields {
-        Struct(_, ref fields) | EnumMatching(_, _, ref fields) => {
+        Struct(_, ref fields) |
+        EnumMatching(_, _, ref fields) => {
             let mut stmts = vec![];
             if !is_struct {
                 // tuple struct/"normal" variant
-                let expr = cx.expr_method_call(span,
-                                               fmt,
-                                               token::str_to_ident("debug_tuple"),
-                                               vec![name]);
+                let expr =
+                    cx.expr_method_call(span, fmt, token::str_to_ident("debug_tuple"), vec![name]);
                 stmts.push(cx.stmt_let(DUMMY_SP, true, builder, expr));
 
                 for field in fields {
@@ -105,16 +101,14 @@ fn show_substructure(cx: &mut ExtCtxt, span: Span,
                 }
             } else {
                 // normal struct/struct variant
-                let expr = cx.expr_method_call(span,
-                                               fmt,
-                                               token::str_to_ident("debug_struct"),
-                                               vec![name]);
+                let expr =
+                    cx.expr_method_call(span, fmt, token::str_to_ident("debug_struct"), vec![name]);
                 stmts.push(cx.stmt_let(DUMMY_SP, true, builder, expr));
 
                 for field in fields {
-                    let name = cx.expr_lit(field.span, ast::LitKind::Str(
-                            field.name.unwrap().name.as_str(),
-                            ast::StrStyle::Cooked));
+                    let name = cx.expr_lit(field.span,
+                                           ast::LitKind::Str(field.name.unwrap().name.as_str(),
+                                                             ast::StrStyle::Cooked));
 
                     // Use double indirection to make sure this works for unsized types
                     let field = cx.expr_addr_of(field.span, field.self_.clone());
@@ -128,22 +122,17 @@ fn show_substructure(cx: &mut ExtCtxt, span: Span,
             }
             stmts
         }
-        _ => unreachable!()
+        _ => unreachable!(),
     };
 
-    let expr = cx.expr_method_call(span,
-                                   builder_expr,
-                                   token::str_to_ident("finish"),
-                                   vec![]);
+    let expr = cx.expr_method_call(span, builder_expr, token::str_to_ident("finish"), vec![]);
 
     stmts.push(cx.stmt_expr(expr));
     let block = cx.block(span, stmts);
     cx.expr_block(block)
 }
 
-fn stmt_let_undescore(cx: &mut ExtCtxt,
-                      sp: Span,
-                      expr: P<ast::Expr>) -> ast::Stmt {
+fn stmt_let_undescore(cx: &mut ExtCtxt, sp: Span, expr: P<ast::Expr>) -> ast::Stmt {
     let local = P(ast::Local {
         pat: cx.pat_wild(sp),
         ty: None,
index 488402c48f70a985bde3775011b26719ec601ee2..9a332227053c7bab3576145baf8b5c0eca153fe9 100644 (file)
@@ -15,8 +15,8 @@
 use deriving::generic::ty::*;
 
 use syntax::ast;
-use syntax::ast::{MetaItem, Expr, Mutability};
-use syntax::ext::base::{ExtCtxt, Annotatable};
+use syntax::ast::{Expr, MetaItem, Mutability};
+use syntax::ext::base::{Annotatable, ExtCtxt};
 use syntax::ext::build::AstBuilder;
 use syntax::parse::token::InternedString;
 use syntax::parse::token;
@@ -27,8 +27,7 @@ pub fn expand_deriving_rustc_decodable(cx: &mut ExtCtxt,
                                        span: Span,
                                        mitem: &MetaItem,
                                        item: &Annotatable,
-                                       push: &mut FnMut(Annotatable))
-{
+                                       push: &mut FnMut(Annotatable)) {
     expand_deriving_decodable_imp(cx, span, mitem, item, push, "rustc_serialize")
 }
 
@@ -36,8 +35,7 @@ pub fn expand_deriving_decodable(cx: &mut ExtCtxt,
                                  span: Span,
                                  mitem: &MetaItem,
                                  item: &Annotatable,
-                                 push: &mut FnMut(Annotatable))
-{
+                                 push: &mut FnMut(Annotatable)) {
     expand_deriving_decodable_imp(cx, span, mitem, item, push, "serialize")
 }
 
@@ -46,13 +44,13 @@ fn expand_deriving_decodable_imp(cx: &mut ExtCtxt,
                                  mitem: &MetaItem,
                                  item: &Annotatable,
                                  push: &mut FnMut(Annotatable),
-                                 krate: &'static str)
-{
+                                 krate: &'static str) {
     if cx.crate_root != Some("std") {
         // FIXME(#21880): lift this requirement.
-        cx.span_err(span, "this trait cannot be derived with #![no_std] \
+        cx.span_err(span,
+                    "this trait cannot be derived with #![no_std] \
                            or #![no_core]");
-        return
+        return;
     }
 
     let typaram = &*deriving::hygienic_type_parameter(item, "__D");
@@ -60,50 +58,50 @@ fn expand_deriving_decodable_imp(cx: &mut ExtCtxt,
     let trait_def = TraitDef {
         span: span,
         attributes: Vec::new(),
-        path: Path::new_(vec!(krate, "Decodable"), None, vec!(), true),
+        path: Path::new_(vec![krate, "Decodable"], None, vec![], true),
         additional_bounds: Vec::new(),
         generics: LifetimeBounds::empty(),
         is_unsafe: false,
-        methods: vec!(
-            MethodDef {
-                name: "decode",
-                generics: LifetimeBounds {
-                    lifetimes: Vec::new(),
-                    bounds: vec![(typaram,
-                                  vec![Path::new_(vec!(krate, "Decoder"), None, vec!(), true)])]
-                },
-                explicit_self: None,
-                args: vec!(Ptr(Box::new(Literal(Path::new_local(typaram))),
-                           Borrowed(None, Mutability::Mutable))),
-                ret_ty: Literal(Path::new_(
-                    pathvec_std!(cx, core::result::Result),
-                    None,
-                    vec!(Box::new(Self_), Box::new(Literal(Path::new_(
+        methods: vec![MethodDef {
+                          name: "decode",
+                          generics: LifetimeBounds {
+                              lifetimes: Vec::new(),
+                              bounds: vec![(typaram,
+                                            vec![Path::new_(vec![krate, "Decoder"],
+                                                            None,
+                                                            vec![],
+                                                            true)])],
+                          },
+                          explicit_self: None,
+                          args: vec![Ptr(Box::new(Literal(Path::new_local(typaram))),
+                                         Borrowed(None, Mutability::Mutable))],
+                          ret_ty:
+                              Literal(Path::new_(pathvec_std!(cx, core::result::Result),
+                                                 None,
+                                                 vec!(Box::new(Self_), Box::new(Literal(Path::new_(
                         vec![typaram, "Error"], None, vec![], false
                     )))),
-                    true
-                )),
-                attributes: Vec::new(),
-                is_unsafe: false,
-                unify_fieldless_variants: false,
-                combine_substructure: combine_substructure(Box::new(|a, b, c| {
-                    decodable_substructure(a, b, c, krate)
-                })),
-            }
-        ),
+                                                 true)),
+                          attributes: Vec::new(),
+                          is_unsafe: false,
+                          unify_fieldless_variants: false,
+                          combine_substructure: combine_substructure(Box::new(|a, b, c| {
+                              decodable_substructure(a, b, c, krate)
+                          })),
+                      }],
         associated_types: Vec::new(),
     };
 
     trait_def.expand(cx, mitem, item, push)
 }
 
-fn decodable_substructure(cx: &mut ExtCtxt, trait_span: Span,
+fn decodable_substructure(cx: &mut ExtCtxt,
+                          trait_span: Span,
                           substr: &Substructure,
-                          krate: &str) -> P<Expr> {
+                          krate: &str)
+                          -> P<Expr> {
     let decoder = substr.nonself_args[0].clone();
-    let recurse = vec!(cx.ident_of(krate),
-                    cx.ident_of("Decodable"),
-                    cx.ident_of("decode"));
+    let recurse = vec![cx.ident_of(krate), cx.ident_of("Decodable"), cx.ident_of("decode")];
     let exprdecode = cx.expr_path(cx.path_global(trait_span, recurse));
     // throw an underscore in front to suppress unused variable warnings
     let blkarg = cx.ident_of("_d");
@@ -113,31 +111,28 @@ fn decodable_substructure(cx: &mut ExtCtxt, trait_span: Span,
         StaticStruct(_, ref summary) => {
             let nfields = match *summary {
                 Unnamed(ref fields) => fields.len(),
-                Named(ref fields) => fields.len()
+                Named(ref fields) => fields.len(),
             };
             let read_struct_field = cx.ident_of("read_struct_field");
 
             let path = cx.path_ident(trait_span, substr.type_ident);
-            let result = decode_static_fields(cx,
-                                              trait_span,
-                                              path,
-                                              summary,
-                                              |cx, span, name, field| {
-                cx.expr_try(span,
-                    cx.expr_method_call(span, blkdecoder.clone(), read_struct_field,
-                                        vec!(cx.expr_str(span, name),
-                                          cx.expr_usize(span, field),
-                                          exprdecode.clone())))
-            });
+            let result =
+                decode_static_fields(cx, trait_span, path, summary, |cx, span, name, field| {
+                    cx.expr_try(span,
+                                cx.expr_method_call(span,
+                                                    blkdecoder.clone(),
+                                                    read_struct_field,
+                                                    vec![cx.expr_str(span, name),
+                                                         cx.expr_usize(span, field),
+                                                         exprdecode.clone()]))
+                });
             let result = cx.expr_ok(trait_span, result);
             cx.expr_method_call(trait_span,
                                 decoder,
                                 cx.ident_of("read_struct"),
-                                vec!(
-                cx.expr_str(trait_span, substr.type_ident.name.as_str()),
-                cx.expr_usize(trait_span, nfields),
-                cx.lambda_expr_1(trait_span, result, blkarg)
-            ))
+                                vec![cx.expr_str(trait_span, substr.type_ident.name.as_str()),
+                                     cx.expr_usize(trait_span, nfields),
+                                     cx.lambda_expr_1(trait_span, result, blkarg)])
         }
         StaticEnum(_, ref fields) => {
             let variant = cx.ident_of("i");
@@ -150,42 +145,39 @@ fn decodable_substructure(cx: &mut ExtCtxt, trait_span: Span,
                 variants.push(cx.expr_str(v_span, ident.name.as_str()));
 
                 let path = cx.path(trait_span, vec![substr.type_ident, ident]);
-                let decoded = decode_static_fields(cx,
-                                                   v_span,
-                                                   path,
-                                                   parts,
-                                                   |cx, span, _, field| {
+                let decoded = decode_static_fields(cx, v_span, path, parts, |cx, span, _, field| {
                     let idx = cx.expr_usize(span, field);
                     cx.expr_try(span,
-                        cx.expr_method_call(span, blkdecoder.clone(), rvariant_arg,
-                                            vec!(idx, exprdecode.clone())))
+                                cx.expr_method_call(span,
+                                                    blkdecoder.clone(),
+                                                    rvariant_arg,
+                                                    vec![idx, exprdecode.clone()]))
                 });
 
                 arms.push(cx.arm(v_span,
-                                 vec!(cx.pat_lit(v_span, cx.expr_usize(v_span, i))),
+                                 vec![cx.pat_lit(v_span, cx.expr_usize(v_span, i))],
                                  decoded));
             }
 
             arms.push(cx.arm_unreachable(trait_span));
 
-            let result = cx.expr_ok(trait_span,
-                                    cx.expr_match(trait_span,
-                                                  cx.expr_ident(trait_span, variant), arms));
-            let lambda = cx.lambda_expr(trait_span, vec!(blkarg, variant), result);
+            let result =
+                cx.expr_ok(trait_span,
+                           cx.expr_match(trait_span, cx.expr_ident(trait_span, variant), arms));
+            let lambda = cx.lambda_expr(trait_span, vec![blkarg, variant], result);
             let variant_vec = cx.expr_vec(trait_span, variants);
             let variant_vec = cx.expr_addr_of(trait_span, variant_vec);
-            let result = cx.expr_method_call(trait_span, blkdecoder,
+            let result = cx.expr_method_call(trait_span,
+                                             blkdecoder,
                                              cx.ident_of("read_enum_variant"),
-                                             vec!(variant_vec, lambda));
+                                             vec![variant_vec, lambda]);
             cx.expr_method_call(trait_span,
                                 decoder,
                                 cx.ident_of("read_enum"),
-                                vec!(
-                cx.expr_str(trait_span, substr.type_ident.name.as_str()),
-                cx.lambda_expr_1(trait_span, result, blkarg)
-            ))
+                                vec![cx.expr_str(trait_span, substr.type_ident.name.as_str()),
+                                     cx.lambda_expr_1(trait_span, result, blkarg)])
         }
-        _ => cx.bug("expected StaticEnum or StaticStruct in derive(Decodable)")
+        _ => cx.bug("expected StaticEnum or StaticStruct in derive(Decodable)"),
     };
 }
 
@@ -197,8 +189,8 @@ fn decode_static_fields<F>(cx: &mut ExtCtxt,
                            outer_pat_path: ast::Path,
                            fields: &StaticFields,
                            mut getarg: F)
-                           -> P<Expr> where
-    F: FnMut(&mut ExtCtxt, Span, InternedString, usize) -> P<Expr>,
+                           -> P<Expr>
+    where F: FnMut(&mut ExtCtxt, Span, InternedString, usize) -> P<Expr>
 {
     match *fields {
         Unnamed(ref fields) => {
@@ -206,21 +198,28 @@ fn decode_static_fields<F>(cx: &mut ExtCtxt,
             if fields.is_empty() {
                 path_expr
             } else {
-                let fields = fields.iter().enumerate().map(|(i, &span)| {
-                    getarg(cx, span,
-                           token::intern_and_get_ident(&format!("_field{}", i)),
-                           i)
-                }).collect();
+                let fields = fields.iter()
+                    .enumerate()
+                    .map(|(i, &span)| {
+                        getarg(cx,
+                               span,
+                               token::intern_and_get_ident(&format!("_field{}", i)),
+                               i)
+                    })
+                    .collect();
 
                 cx.expr_call(trait_span, path_expr, fields)
             }
         }
         Named(ref fields) => {
             // use the field's span to get nicer error messages.
-            let fields = fields.iter().enumerate().map(|(i, &(ident, span))| {
-                let arg = getarg(cx, span, ident.name.as_str(), i);
-                cx.field_imm(span, ident, arg)
-            }).collect();
+            let fields = fields.iter()
+                .enumerate()
+                .map(|(i, &(ident, span))| {
+                    let arg = getarg(cx, span, ident.name.as_str(), i);
+                    cx.field_imm(span, ident, arg)
+                })
+                .collect();
             cx.expr_struct(trait_span, outer_pat_path, fields)
         }
     }
index 2711ccba81914ec7e05a5962455e9e4492e3bdaf..9df3db938b1f918fba8649a251f19ff34aa2511e 100644 (file)
@@ -11,8 +11,8 @@
 use deriving::generic::*;
 use deriving::generic::ty::*;
 
-use syntax::ast::{MetaItem, Expr};
-use syntax::ext::base::{ExtCtxt, Annotatable};
+use syntax::ast::{Expr, MetaItem};
+use syntax::ext::base::{Annotatable, ExtCtxt};
 use syntax::ext::build::AstBuilder;
 use syntax::parse::token::InternedString;
 use syntax::ptr::P;
@@ -22,10 +22,9 @@ pub fn expand_deriving_default(cx: &mut ExtCtxt,
                                span: Span,
                                mitem: &MetaItem,
                                item: &Annotatable,
-                               push: &mut FnMut(Annotatable))
-{
+                               push: &mut FnMut(Annotatable)) {
     let inline = cx.meta_word(span, InternedString::new("inline"));
-    let attrs = vec!(cx.attribute(span, inline));
+    let attrs = vec![cx.attribute(span, inline)];
     let trait_def = TraitDef {
         span: span,
         attributes: Vec::new(),
@@ -33,21 +32,19 @@ pub fn expand_deriving_default(cx: &mut ExtCtxt,
         additional_bounds: Vec::new(),
         generics: LifetimeBounds::empty(),
         is_unsafe: false,
-        methods: vec!(
-            MethodDef {
-                name: "default",
-                generics: LifetimeBounds::empty(),
-                explicit_self: None,
-                args: Vec::new(),
-                ret_ty: Self_,
-                attributes: attrs,
-                is_unsafe: false,
-                unify_fieldless_variants: false,
-                combine_substructure: combine_substructure(Box::new(|a, b, c| {
-                    default_substructure(a, b, c)
-                }))
-            }
-        ),
+        methods: vec![MethodDef {
+                          name: "default",
+                          generics: LifetimeBounds::empty(),
+                          explicit_self: None,
+                          args: Vec::new(),
+                          ret_ty: Self_,
+                          attributes: attrs,
+                          is_unsafe: false,
+                          unify_fieldless_variants: false,
+                          combine_substructure: combine_substructure(Box::new(|a, b, c| {
+                              default_substructure(a, b, c)
+                          })),
+                      }],
         associated_types: Vec::new(),
     };
     trait_def.expand(cx, mitem, item, push)
@@ -69,18 +66,19 @@ fn default_substructure(cx: &mut ExtCtxt, trait_span: Span, substr: &Substructur
                     }
                 }
                 Named(ref fields) => {
-                    let default_fields = fields.iter().map(|&(ident, span)| {
-                        cx.field_imm(span, ident, default_call(span))
-                    }).collect();
+                    let default_fields = fields.iter()
+                        .map(|&(ident, span)| cx.field_imm(span, ident, default_call(span)))
+                        .collect();
                     cx.expr_struct_ident(trait_span, substr.type_ident, default_fields)
                 }
             }
         }
         StaticEnum(..) => {
-            cx.span_err(trait_span, "`Default` cannot be derived for enums, only structs");
+            cx.span_err(trait_span,
+                        "`Default` cannot be derived for enums, only structs");
             // let compilation continue
             cx.expr_usize(trait_span, 0)
         }
-        _ => cx.span_bug(trait_span, "Non-static method in `derive(Default)`")
+        _ => cx.span_bug(trait_span, "Non-static method in `derive(Default)`"),
     };
 }
index ad3786212475eaa76f23a82963fab1270827aa13..940fdf037711ffac788171a8c8a30423744bd04e 100644 (file)
@@ -92,8 +92,8 @@
 use deriving::generic::*;
 use deriving::generic::ty::*;
 
-use syntax::ast::{MetaItem, Expr, ExprKind, Mutability};
-use syntax::ext::base::{ExtCtxt,Annotatable};
+use syntax::ast::{Expr, ExprKind, MetaItem, Mutability};
+use syntax::ext::base::{Annotatable, ExtCtxt};
 use syntax::ext::build::AstBuilder;
 use syntax::parse::token;
 use syntax::ptr::P;
@@ -103,8 +103,7 @@ pub fn expand_deriving_rustc_encodable(cx: &mut ExtCtxt,
                                        span: Span,
                                        mitem: &MetaItem,
                                        item: &Annotatable,
-                                       push: &mut FnMut(Annotatable))
-{
+                                       push: &mut FnMut(Annotatable)) {
     expand_deriving_encodable_imp(cx, span, mitem, item, push, "rustc_serialize")
 }
 
@@ -112,8 +111,7 @@ pub fn expand_deriving_encodable(cx: &mut ExtCtxt,
                                  span: Span,
                                  mitem: &MetaItem,
                                  item: &Annotatable,
-                                 push: &mut FnMut(Annotatable))
-{
+                                 push: &mut FnMut(Annotatable)) {
     expand_deriving_encodable_imp(cx, span, mitem, item, push, "serialize")
 }
 
@@ -122,11 +120,11 @@ fn expand_deriving_encodable_imp(cx: &mut ExtCtxt,
                                  mitem: &MetaItem,
                                  item: &Annotatable,
                                  push: &mut FnMut(Annotatable),
-                                 krate: &'static str)
-{
+                                 krate: &'static str) {
     if cx.crate_root != Some("std") {
         // FIXME(#21880): lift this requirement.
-        cx.span_err(span, "this trait cannot be derived with #![no_std] \
+        cx.span_err(span,
+                    "this trait cannot be derived with #![no_std] \
                            or #![no_core]");
         return;
     }
@@ -136,7 +134,7 @@ fn expand_deriving_encodable_imp(cx: &mut ExtCtxt,
     let trait_def = TraitDef {
         span: span,
         attributes: Vec::new(),
-        path: Path::new_(vec!(krate, "Encodable"), None, vec!(), true),
+        path: Path::new_(vec![krate, "Encodable"], None, vec![], true),
         additional_bounds: Vec::new(),
         generics: LifetimeBounds::empty(),
         is_unsafe: false,
@@ -173,40 +171,38 @@ fn expand_deriving_encodable_imp(cx: &mut ExtCtxt,
     trait_def.expand(cx, mitem, item, push)
 }
 
-fn encodable_substructure(cx: &mut ExtCtxt, trait_span: Span,
-                          substr: &Substructure, krate: &'static str) -> P<Expr> {
+fn encodable_substructure(cx: &mut ExtCtxt,
+                          trait_span: Span,
+                          substr: &Substructure,
+                          krate: &'static str)
+                          -> P<Expr> {
     let encoder = substr.nonself_args[0].clone();
     // throw an underscore in front to suppress unused variable warnings
     let blkarg = cx.ident_of("_e");
     let blkencoder = cx.expr_ident(trait_span, blkarg);
-    let fn_path = cx.expr_path(cx.path_global(trait_span, vec![cx.ident_of(krate),
-                                                               cx.ident_of("Encodable"),
-                                                               cx.ident_of("encode")]));
+    let fn_path = cx.expr_path(cx.path_global(trait_span,
+                                              vec![cx.ident_of(krate),
+                                                   cx.ident_of("Encodable"),
+                                                   cx.ident_of("encode")]));
 
     return match *substr.fields {
         Struct(_, ref fields) => {
             let emit_struct_field = cx.ident_of("emit_struct_field");
             let mut stmts = Vec::new();
-            for (i, &FieldInfo {
-                    name,
-                    ref self_,
-                    span,
-                    ..
-                }) in fields.iter().enumerate() {
+            for (i, &FieldInfo { name, ref self_, span, .. }) in fields.iter().enumerate() {
                 let name = match name {
                     Some(id) => id.name.as_str(),
-                    None => {
-                        token::intern_and_get_ident(&format!("_field{}", i))
-                    }
+                    None => token::intern_and_get_ident(&format!("_field{}", i)),
                 };
                 let self_ref = cx.expr_addr_of(span, self_.clone());
                 let enc = cx.expr_call(span, fn_path.clone(), vec![self_ref, blkencoder.clone()]);
                 let lambda = cx.lambda_expr_1(span, enc, blkarg);
-                let call = cx.expr_method_call(span, blkencoder.clone(),
+                let call = cx.expr_method_call(span,
+                                               blkencoder.clone(),
                                                emit_struct_field,
-                                               vec!(cx.expr_str(span, name),
-                                                 cx.expr_usize(span, i),
-                                                 lambda));
+                                               vec![cx.expr_str(span, name),
+                                                    cx.expr_usize(span, i),
+                                                    lambda]);
 
                 // last call doesn't need a try!
                 let last = fields.len() - 1;
@@ -229,11 +225,9 @@ fn encodable_substructure(cx: &mut ExtCtxt, trait_span: Span,
             cx.expr_method_call(trait_span,
                                 encoder,
                                 cx.ident_of("emit_struct"),
-                                vec!(
-                cx.expr_str(trait_span, substr.type_ident.name.as_str()),
-                cx.expr_usize(trait_span, fields.len()),
-                blk
-            ))
+                                vec![cx.expr_str(trait_span, substr.type_ident.name.as_str()),
+                                     cx.expr_usize(trait_span, fields.len()),
+                                     blk])
         }
 
         EnumMatching(idx, variant, ref fields) => {
@@ -248,14 +242,14 @@ fn encodable_substructure(cx: &mut ExtCtxt, trait_span: Span,
             if !fields.is_empty() {
                 let last = fields.len() - 1;
                 for (i, &FieldInfo { ref self_, span, .. }) in fields.iter().enumerate() {
-                let self_ref = cx.expr_addr_of(span, self_.clone());
-                    let enc = cx.expr_call(span, fn_path.clone(), vec![self_ref,
-                                                                       blkencoder.clone()]);
+                    let self_ref = cx.expr_addr_of(span, self_.clone());
+                    let enc =
+                        cx.expr_call(span, fn_path.clone(), vec![self_ref, blkencoder.clone()]);
                     let lambda = cx.lambda_expr_1(span, enc, blkarg);
-                    let call = cx.expr_method_call(span, blkencoder.clone(),
+                    let call = cx.expr_method_call(span,
+                                                   blkencoder.clone(),
                                                    emit_variant_arg,
-                                                   vec!(cx.expr_usize(span, i),
-                                                        lambda));
+                                                   vec![cx.expr_usize(span, i), lambda]);
                     let call = if i != last {
                         cx.expr_try(span, call)
                     } else {
@@ -271,23 +265,23 @@ fn encodable_substructure(cx: &mut ExtCtxt, trait_span: Span,
 
             let blk = cx.lambda_stmts_1(trait_span, stmts, blkarg);
             let name = cx.expr_str(trait_span, variant.node.name.name.as_str());
-            let call = cx.expr_method_call(trait_span, blkencoder,
+            let call = cx.expr_method_call(trait_span,
+                                           blkencoder,
                                            cx.ident_of("emit_enum_variant"),
-                                           vec!(name,
-                                             cx.expr_usize(trait_span, idx),
-                                             cx.expr_usize(trait_span, fields.len()),
-                                             blk));
+                                           vec![name,
+                                                cx.expr_usize(trait_span, idx),
+                                                cx.expr_usize(trait_span, fields.len()),
+                                                blk]);
             let blk = cx.lambda_expr_1(trait_span, call, blkarg);
             let ret = cx.expr_method_call(trait_span,
                                           encoder,
                                           cx.ident_of("emit_enum"),
-                                          vec!(
-                cx.expr_str(trait_span, substr.type_ident.name.as_str()),
-                blk
-            ));
+                                          vec![cx.expr_str(trait_span,
+                                                           substr.type_ident.name.as_str()),
+                                               blk]);
             cx.expr_block(cx.block(trait_span, vec![me, cx.stmt_expr(ret)]))
         }
 
-        _ => cx.bug("expected Struct or EnumMatching in derive(Encodable)")
+        _ => cx.bug("expected Struct or EnumMatching in derive(Encodable)"),
     };
 }
index f33898109cc57e3110aa40a13b1ac7cfeaefe1da..cd49e7ec9d2c6764ce98c42a3bd270eace612025 100644 (file)
 use std::vec;
 
 use syntax::abi::Abi;
-use syntax::ast::{self, EnumDef, Expr, Ident, Generics, VariantData, BinOpKind, PatKind};
+use syntax::ast::{self, BinOpKind, EnumDef, Expr, Generics, Ident, PatKind, VariantData};
 use syntax::attr;
 use syntax::attr::AttrMetaMethods;
-use syntax::ext::base::{ExtCtxt, Annotatable};
+use syntax::ext::base::{Annotatable, ExtCtxt};
 use syntax::ext::build::AstBuilder;
 use syntax::codemap::{self, respan};
 use syntax::util::move_map::MoveMap;
-use syntax::parse::token::{keywords, InternedString};
+use syntax::parse::token::{InternedString, keywords};
 use syntax::ptr::P;
-use syntax_pos::{Span, DUMMY_SP};
+use syntax_pos::{DUMMY_SP, Span};
 use errors::Handler;
 
 use self::ty::{LifetimeBounds, Path, Ptr, PtrTy, Self_, Ty};
@@ -273,7 +273,7 @@ pub struct Substructure<'a> {
     pub self_args: &'a [P<Expr>],
     /// verbatim access to any other arguments
     pub nonself_args: &'a [P<Expr>],
-    pub fields: &'a SubstructureFields<'a>
+    pub fields: &'a SubstructureFields<'a>,
 }
 
 /// Summary of the relevant parts of a struct/enum field.
@@ -338,14 +338,17 @@ pub enum SubstructureFields<'a> {
     Box<FnMut(&mut ExtCtxt, Span, (&[Ident], &[Ident]), &[P<Expr>]) -> P<Expr> + 'a>;
 
 pub fn combine_substructure<'a>(f: CombineSubstructureFunc<'a>)
-    -> RefCell<CombineSubstructureFunc<'a>> {
+                                -> RefCell<CombineSubstructureFunc<'a>> {
     RefCell::new(f)
 }
 
 /// This method helps to extract all the type parameters referenced from a
 /// type. For a type parameter `<T>`, it looks for either a `TyPath` that
 /// is not global and starts with `T`, or a `TyQPath`.
-fn find_type_parameters(ty: &ast::Ty, ty_param_names: &[ast::Name], span: Span, cx: &ExtCtxt)
+fn find_type_parameters(ty: &ast::Ty,
+                        ty_param_names: &[ast::Name],
+                        span: Span,
+                        cx: &ExtCtxt)
                         -> Vec<P<ast::Ty>> {
     use syntax::visit;
 
@@ -395,23 +398,15 @@ pub fn expand(&self,
                   cx: &mut ExtCtxt,
                   mitem: &ast::MetaItem,
                   item: &'a Annotatable,
-                  push: &mut FnMut(Annotatable))
-    {
+                  push: &mut FnMut(Annotatable)) {
         match *item {
             Annotatable::Item(ref item) => {
                 let newitem = match item.node {
                     ast::ItemKind::Struct(ref struct_def, ref generics) => {
-                        self.expand_struct_def(cx,
-                                               &struct_def,
-                                               item.ident,
-                                               generics)
+                        self.expand_struct_def(cx, &struct_def, item.ident, generics)
                     }
                     ast::ItemKind::Enum(ref enum_def, ref generics) => {
-                        self.expand_enum_def(cx,
-                                             enum_def,
-                                             &item.attrs,
-                                             item.ident,
-                                             generics)
+                        self.expand_enum_def(cx, enum_def, &item.attrs, item.ident, generics)
                     }
                     _ => {
                         cx.span_err(mitem.span,
@@ -422,19 +417,20 @@ pub fn expand(&self,
                 // Keep the lint attributes of the previous item to control how the
                 // generated implementations are linted
                 let mut attrs = newitem.attrs.clone();
-                attrs.extend(item.attrs.iter().filter(|a| {
-                    match &a.name()[..] {
-                        "allow" | "warn" | "deny" | "forbid" | "stable" | "unstable" => true,
-                        _ => false,
-                    }
-                }).cloned());
-                push(Annotatable::Item(P(ast::Item {
-                    attrs: attrs,
-                    ..(*newitem).clone()
-                })))
+                attrs.extend(item.attrs
+                    .iter()
+                    .filter(|a| {
+                        match &a.name()[..] {
+                            "allow" | "warn" | "deny" | "forbid" | "stable" | "unstable" => true,
+                            _ => false,
+                        }
+                    })
+                    .cloned());
+                push(Annotatable::Item(P(ast::Item { attrs: attrs, ..(*newitem).clone() })))
             }
             _ => {
-                cx.span_err(mitem.span, "`derive` may only be applied to structs and enums");
+                cx.span_err(mitem.span,
+                            "`derive` may only be applied to structs and enums");
             }
         }
     }
@@ -475,7 +471,8 @@ fn create_derived_impl(&self,
                            type_ident: Ident,
                            generics: &Generics,
                            field_tys: Vec<P<ast::Ty>>,
-                           methods: Vec<ast::ImplItem>) -> P<ast::Item> {
+                           methods: Vec<ast::ImplItem>)
+                           -> P<ast::Item> {
         let trait_path = self.path.to_path(cx, self.span, type_ident, generics);
 
         // Transform associated types from `deriving::ty::Ty` into `ast::ImplItem`
@@ -487,16 +484,12 @@ fn create_derived_impl(&self,
                 vis: ast::Visibility::Inherited,
                 defaultness: ast::Defaultness::Final,
                 attrs: Vec::new(),
-                node: ast::ImplItemKind::Type(type_def.to_ty(cx,
-                    self.span,
-                    type_ident,
-                    generics
-                )),
+                node: ast::ImplItemKind::Type(type_def.to_ty(cx, self.span, type_ident, generics)),
             }
         });
 
-        let Generics { mut lifetimes, ty_params, mut where_clause } =
-            self.generics.to_generics(cx, self.span, type_ident, generics);
+        let Generics { mut lifetimes, ty_params, mut where_clause } = self.generics
+            .to_generics(cx, self.span, type_ident, generics);
         let mut ty_params = ty_params.into_vec();
 
         // Copy the lifetimes
@@ -521,10 +514,7 @@ fn create_derived_impl(&self,
                 bounds.push((*declared_bound).clone());
             }
 
-            cx.typaram(self.span,
-                       ty_param.ident,
-                       P::from_vec(bounds),
-                       None)
+            cx.typaram(self.span, ty_param.ident, P::from_vec(bounds), None)
         }));
 
         // and similarly for where clauses
@@ -542,7 +532,7 @@ fn create_derived_impl(&self,
                     ast::WherePredicate::RegionPredicate(ast::WhereRegionPredicate {
                         span: self.span,
                         lifetime: rb.lifetime,
-                        bounds: rb.bounds.iter().cloned().collect()
+                        bounds: rb.bounds.iter().cloned().collect(),
                     })
                 }
                 ast::WherePredicate::EqPredicate(ref we) => {
@@ -550,7 +540,7 @@ fn create_derived_impl(&self,
                         id: ast::DUMMY_NODE_ID,
                         span: self.span,
                         path: we.path.clone(),
-                        ty: we.ty.clone()
+                        ty: we.ty.clone(),
                     })
                 }
             }
@@ -568,16 +558,17 @@ fn create_derived_impl(&self,
                 for ty in tys {
                     // if we have already handled this type, skip it
                     if let ast::TyKind::Path(_, ref p) = ty.node {
-                        if p.segments.len() == 1
-                            && ty_param_names.contains(&p.segments[0].identifier.name)
-                            || processed_field_types.contains(&p.segments) {
+                        if p.segments.len() == 1 &&
+                           ty_param_names.contains(&p.segments[0].identifier.name) ||
+                           processed_field_types.contains(&p.segments) {
                             continue;
                         };
                         processed_field_types.insert(p.segments.clone());
                     }
-                    let mut bounds: Vec<_> = self.additional_bounds.iter().map(|p| {
-                        cx.typarambound(p.to_path(cx, self.span, type_ident, generics))
-                    }).collect();
+                    let mut bounds: Vec<_> = self.additional_bounds
+                        .iter()
+                        .map(|p| cx.typarambound(p.to_path(cx, self.span, type_ident, generics)))
+                        .collect();
 
                     // require the current trait
                     bounds.push(cx.typarambound(trait_path.clone()));
@@ -598,40 +589,41 @@ fn create_derived_impl(&self,
         let trait_generics = Generics {
             lifetimes: lifetimes,
             ty_params: P::from_vec(ty_params),
-            where_clause: where_clause
+            where_clause: where_clause,
         };
 
         // Create the reference to the trait.
         let trait_ref = cx.trait_ref(trait_path);
 
         // Create the type parameters on the `self` path.
-        let self_ty_params = generics.ty_params.iter().map(|ty_param| {
-            cx.ty_ident(self.span, ty_param.ident)
-        }).collect();
+        let self_ty_params = generics.ty_params
+            .iter()
+            .map(|ty_param| cx.ty_ident(self.span, ty_param.ident))
+            .collect();
 
-        let self_lifetimes: Vec<ast::Lifetime> =
-            generics.lifetimes
+        let self_lifetimes: Vec<ast::Lifetime> = generics.lifetimes
             .iter()
             .map(|ld| ld.lifetime)
             .collect();
 
         // Create the type of `self`.
-        let self_type = cx.ty_path(
-            cx.path_all(self.span, false, vec!( type_ident ), self_lifetimes,
-                        self_ty_params, Vec::new()));
-
-        let attr = cx.attribute(
-            self.span,
-            cx.meta_word(self.span,
-                         InternedString::new("automatically_derived")));
+        let self_type = cx.ty_path(cx.path_all(self.span,
+                                               false,
+                                               vec![type_ident],
+                                               self_lifetimes,
+                                               self_ty_params,
+                                               Vec::new()));
+
+        let attr = cx.attribute(self.span,
+                                cx.meta_word(self.span,
+                                             InternedString::new("automatically_derived")));
         // Just mark it now since we know that it'll end up used downstream
         attr::mark_used(&attr);
         let opt_trait_ref = Some(trait_ref);
-        let unused_qual = cx.attribute(
-            self.span,
-            cx.meta_list(self.span,
-                         InternedString::new("allow"),
-                         vec![cx.meta_word(self.span,
+        let unused_qual = cx.attribute(self.span,
+                                       cx.meta_list(self.span,
+                                                    InternedString::new("allow"),
+                                                    vec![cx.meta_word(self.span,
                                            InternedString::new("unused_qualifications"))]));
         let mut a = vec![attr, unused_qual];
         a.extend(self.attributes.iter().cloned());
@@ -642,58 +634,60 @@ fn create_derived_impl(&self,
             ast::Unsafety::Normal
         };
 
-        cx.item(
-            self.span,
-            keywords::Invalid.ident(),
-            a,
-            ast::ItemKind::Impl(unsafety,
-                                ast::ImplPolarity::Positive,
-                                trait_generics,
-                                opt_trait_ref,
-                                self_type,
-                                methods.into_iter().chain(associated_types).collect()))
+        cx.item(self.span,
+                keywords::Invalid.ident(),
+                a,
+                ast::ItemKind::Impl(unsafety,
+                                    ast::ImplPolarity::Positive,
+                                    trait_generics,
+                                    opt_trait_ref,
+                                    self_type,
+                                    methods.into_iter().chain(associated_types).collect()))
     }
 
     fn expand_struct_def(&self,
                          cx: &mut ExtCtxt,
                          struct_def: &'a VariantData,
                          type_ident: Ident,
-                         generics: &Generics) -> P<ast::Item> {
-        let field_tys: Vec<P<ast::Ty>> = struct_def.fields().iter()
+                         generics: &Generics)
+                         -> P<ast::Item> {
+        let field_tys: Vec<P<ast::Ty>> = struct_def.fields()
+            .iter()
             .map(|field| field.ty.clone())
             .collect();
 
-        let methods = self.methods.iter().map(|method_def| {
-            let (explicit_self, self_args, nonself_args, tys) =
-                method_def.split_self_nonself_args(
-                    cx, self, type_ident, generics);
-
-            let body = if method_def.is_static() {
-                method_def.expand_static_struct_method_body(
-                    cx,
-                    self,
-                    struct_def,
-                    type_ident,
-                    &self_args[..],
-                    &nonself_args[..])
-            } else {
-                method_def.expand_struct_method_body(cx,
-                                                     self,
-                                                     struct_def,
-                                                     type_ident,
-                                                     &self_args[..],
-                                                     &nonself_args[..])
-            };
-
-            method_def.create_method(cx,
-                                     self,
-                                     type_ident,
-                                     generics,
-                                     Abi::Rust,
-                                     explicit_self,
-                                     tys,
-                                     body)
-        }).collect();
+        let methods = self.methods
+            .iter()
+            .map(|method_def| {
+                let (explicit_self, self_args, nonself_args, tys) =
+                    method_def.split_self_nonself_args(cx, self, type_ident, generics);
+
+                let body = if method_def.is_static() {
+                    method_def.expand_static_struct_method_body(cx,
+                                                                self,
+                                                                struct_def,
+                                                                type_ident,
+                                                                &self_args[..],
+                                                                &nonself_args[..])
+                } else {
+                    method_def.expand_struct_method_body(cx,
+                                                         self,
+                                                         struct_def,
+                                                         type_ident,
+                                                         &self_args[..],
+                                                         &nonself_args[..])
+                };
+
+                method_def.create_method(cx,
+                                         self,
+                                         type_ident,
+                                         generics,
+                                         Abi::Rust,
+                                         explicit_self,
+                                         tys,
+                                         body)
+            })
+            .collect();
 
         self.create_derived_impl(cx, type_ident, generics, field_tys, methods)
     }
@@ -703,53 +697,57 @@ fn expand_enum_def(&self,
                        enum_def: &'a EnumDef,
                        type_attrs: &[ast::Attribute],
                        type_ident: Ident,
-                       generics: &Generics) -> P<ast::Item> {
+                       generics: &Generics)
+                       -> P<ast::Item> {
         let mut field_tys = Vec::new();
 
         for variant in &enum_def.variants {
-            field_tys.extend(variant.node.data.fields().iter()
+            field_tys.extend(variant.node
+                .data
+                .fields()
+                .iter()
                 .map(|field| field.ty.clone()));
         }
 
-        let methods = self.methods.iter().map(|method_def| {
-            let (explicit_self, self_args, nonself_args, tys) =
-                method_def.split_self_nonself_args(cx, self,
-                                                   type_ident, generics);
-
-            let body = if method_def.is_static() {
-                method_def.expand_static_enum_method_body(
-                    cx,
-                    self,
-                    enum_def,
-                    type_ident,
-                    &self_args[..],
-                    &nonself_args[..])
-            } else {
-                method_def.expand_enum_method_body(cx,
-                                                   self,
-                                                   enum_def,
-                                                   type_attrs,
-                                                   type_ident,
-                                                   self_args,
-                                                   &nonself_args[..])
-            };
-
-            method_def.create_method(cx,
-                                     self,
-                                     type_ident,
-                                     generics,
-                                     Abi::Rust,
-                                     explicit_self,
-                                     tys,
-                                     body)
-        }).collect();
+        let methods = self.methods
+            .iter()
+            .map(|method_def| {
+                let (explicit_self, self_args, nonself_args, tys) =
+                    method_def.split_self_nonself_args(cx, self, type_ident, generics);
+
+                let body = if method_def.is_static() {
+                    method_def.expand_static_enum_method_body(cx,
+                                                              self,
+                                                              enum_def,
+                                                              type_ident,
+                                                              &self_args[..],
+                                                              &nonself_args[..])
+                } else {
+                    method_def.expand_enum_method_body(cx,
+                                                       self,
+                                                       enum_def,
+                                                       type_attrs,
+                                                       type_ident,
+                                                       self_args,
+                                                       &nonself_args[..])
+                };
+
+                method_def.create_method(cx,
+                                         self,
+                                         type_ident,
+                                         generics,
+                                         Abi::Rust,
+                                         explicit_self,
+                                         tys,
+                                         body)
+            })
+            .collect();
 
         self.create_derived_impl(cx, type_ident, generics, field_tys, methods)
     }
 }
 
-fn find_repr_type_name(diagnostic: &Handler,
-                       type_attrs: &[ast::Attribute]) -> &'static str {
+fn find_repr_type_name(diagnostic: &Handler, type_attrs: &[ast::Attribute]) -> &'static str {
     let mut repr_type_name = "isize";
     for a in type_attrs {
         for r in &attr::find_repr_attrs(diagnostic, a) {
@@ -782,13 +780,13 @@ fn call_substructure_method(&self,
                                 self_args: &[P<Expr>],
                                 nonself_args: &[P<Expr>],
                                 fields: &SubstructureFields)
-        -> P<Expr> {
+                                -> P<Expr> {
         let substructure = Substructure {
             type_ident: type_ident,
             method_ident: cx.ident_of(self.name),
             self_args: self_args,
             nonself_args: nonself_args,
-            fields: fields
+            fields: fields,
         };
         let mut f = self.combine_substructure.borrow_mut();
         let f: &mut CombineSubstructureFunc = &mut *f;
@@ -808,12 +806,13 @@ fn is_static(&self) -> bool {
         self.explicit_self.is_none()
     }
 
-    fn split_self_nonself_args(&self,
-                               cx: &mut ExtCtxt,
-                               trait_: &TraitDef,
-                               type_ident: Ident,
-                               generics: &Generics)
-        -> (Option<ast::ExplicitSelf>, Vec<P<Expr>>, Vec<P<Expr>>, Vec<(Ident, P<ast::Ty>)>) {
+    fn split_self_nonself_args
+        (&self,
+         cx: &mut ExtCtxt,
+         trait_: &TraitDef,
+         type_ident: Ident,
+         generics: &Generics)
+         -> (Option<ast::ExplicitSelf>, Vec<P<Expr>>, Vec<P<Expr>>, Vec<(Ident, P<ast::Ty>)>) {
 
         let mut self_args = Vec::new();
         let mut nonself_args = Vec::new();
@@ -839,7 +838,7 @@ fn split_self_nonself_args(&self,
             match *ty {
                 // for static methods, just treat any Self
                 // arguments as a normal arg
-                Self_ if nonstatic  => {
+                Self_ if nonstatic => {
                     self_args.push(arg_expr);
                 }
                 Ptr(ref ty, _) if **ty == Self_ && nonstatic => {
@@ -861,18 +860,20 @@ fn create_method(&self,
                      generics: &Generics,
                      abi: Abi,
                      explicit_self: Option<ast::ExplicitSelf>,
-                     arg_types: Vec<(Ident, P<ast::Ty>)> ,
-                     body: P<Expr>) -> ast::ImplItem {
+                     arg_types: Vec<(Ident, P<ast::Ty>)>,
+                     body: P<Expr>)
+                     -> ast::ImplItem {
 
         // create the generics that aren't for Self
         let fn_generics = self.generics.to_generics(cx, trait_.span, type_ident, generics);
 
         let args = {
             let self_args = explicit_self.map(|explicit_self| {
-                ast::Arg::from_self(explicit_self, respan(trait_.span, keywords::SelfValue.ident()))
+                ast::Arg::from_self(explicit_self,
+                                    respan(trait_.span, keywords::SelfValue.ident()))
             });
             let nonself_args = arg_types.into_iter()
-                                        .map(|(name, ty)| cx.arg(trait_.span, name, ty));
+                .map(|(name, ty)| cx.arg(trait_.span, name, ty));
             self_args.into_iter().chain(nonself_args).collect()
         };
 
@@ -897,12 +898,13 @@ fn create_method(&self,
             defaultness: ast::Defaultness::Final,
             ident: method_ident,
             node: ast::ImplItemKind::Method(ast::MethodSig {
-                generics: fn_generics,
-                abi: abi,
-                unsafety: unsafety,
-                constness: ast::Constness::NotConst,
-                decl: fn_decl
-            }, body_block)
+                                                generics: fn_generics,
+                                                abi: abi,
+                                                unsafety: unsafety,
+                                                constness: ast::Constness::NotConst,
+                                                decl: fn_decl,
+                                            },
+                                            body_block),
         }
     }
 
@@ -926,26 +928,24 @@ fn create_method(&self,
     /// }
     /// ```
     fn expand_struct_method_body<'b>(&self,
-                                 cx: &mut ExtCtxt,
-                                 trait_: &TraitDef<'b>,
-                                 struct_def: &'b VariantData,
-                                 type_ident: Ident,
-                                 self_args: &[P<Expr>],
-                                 nonself_args: &[P<Expr>])
-        -> P<Expr> {
+                                     cx: &mut ExtCtxt,
+                                     trait_: &TraitDef<'b>,
+                                     struct_def: &'b VariantData,
+                                     type_ident: Ident,
+                                     self_args: &[P<Expr>],
+                                     nonself_args: &[P<Expr>])
+                                     -> P<Expr> {
 
         let mut raw_fields = Vec::new(); // Vec<[fields of self],
                                  // [fields of next Self arg], [etc]>
         let mut patterns = Vec::new();
         for i in 0..self_args.len() {
-            let struct_path= cx.path(DUMMY_SP, vec!( type_ident ));
-            let (pat, ident_expr) =
-                trait_.create_struct_pattern(cx,
-                                             struct_path,
-                                             struct_def,
-                                             &format!("__self_{}",
-                                                     i),
-                                             ast::Mutability::Immutable);
+            let struct_path = cx.path(DUMMY_SP, vec![type_ident]);
+            let (pat, ident_expr) = trait_.create_struct_pattern(cx,
+                                                                 struct_path,
+                                                                 struct_def,
+                                                                 &format!("__self_{}", i),
+                                                                 ast::Mutability::Immutable);
             patterns.push(pat);
             raw_fields.push(ident_expr);
         }
@@ -954,21 +954,23 @@ fn expand_struct_method_body<'b>(&self,
         let fields = if !raw_fields.is_empty() {
             let mut raw_fields = raw_fields.into_iter().map(|v| v.into_iter());
             let first_field = raw_fields.next().unwrap();
-            let mut other_fields: Vec<vec::IntoIter<_>>
-                = raw_fields.collect();
+            let mut other_fields: Vec<vec::IntoIter<_>> = raw_fields.collect();
             first_field.map(|(span, opt_id, field, attrs)| {
-                FieldInfo {
-                    span: span,
-                    name: opt_id,
-                    self_: field,
-                    other: other_fields.iter_mut().map(|l| {
-                        match l.next().unwrap() {
-                            (_, _, ex, _) => ex
-                        }
-                    }).collect(),
-                    attrs: attrs,
-                }
-            }).collect()
+                    FieldInfo {
+                        span: span,
+                        name: opt_id,
+                        self_: field,
+                        other: other_fields.iter_mut()
+                            .map(|l| {
+                                match l.next().unwrap() {
+                                    (_, _, ex, _) => ex,
+                                }
+                            })
+                            .collect(),
+                        attrs: attrs,
+                    }
+                })
+                .collect()
         } else {
             cx.span_bug(trait_.span,
                         "no self arguments to non-static method in generic \
@@ -976,20 +978,20 @@ fn expand_struct_method_body<'b>(&self,
         };
 
         // body of the inner most destructuring match
-        let mut body = self.call_substructure_method(
-            cx,
-            trait_,
-            type_ident,
-            self_args,
-            nonself_args,
-            &Struct(struct_def, fields));
+        let mut body = self.call_substructure_method(cx,
+                                                     trait_,
+                                                     type_ident,
+                                                     self_args,
+                                                     nonself_args,
+                                                     &Struct(struct_def, fields));
 
         // make a series of nested matches, to destructure the
         // structs. This is actually right-to-left, but it shouldn't
         // matter.
         for (arg_expr, pat) in self_args.iter().zip(patterns) {
-            body = cx.expr_match(trait_.span, arg_expr.clone(),
-                                     vec!( cx.arm(trait_.span, vec!(pat.clone()), body) ))
+            body = cx.expr_match(trait_.span,
+                                 arg_expr.clone(),
+                                 vec![cx.arm(trait_.span, vec![pat.clone()], body)])
         }
 
         body
@@ -1002,13 +1004,14 @@ fn expand_static_struct_method_body(&self,
                                         type_ident: Ident,
                                         self_args: &[P<Expr>],
                                         nonself_args: &[P<Expr>])
-        -> P<Expr> {
+                                        -> P<Expr> {
         let summary = trait_.summarise_struct(cx, struct_def);
 
         self.call_substructure_method(cx,
                                       trait_,
                                       type_ident,
-                                      self_args, nonself_args,
+                                      self_args,
+                                      nonself_args,
                                       &StaticStruct(struct_def, summary))
     }
 
@@ -1042,16 +1045,21 @@ fn expand_static_struct_method_body(&self,
     /// as their results are unused.  The point of `__self_vi` and
     /// `__arg_1_vi` is for `PartialOrd`; see #15503.)
     fn expand_enum_method_body<'b>(&self,
-                               cx: &mut ExtCtxt,
-                               trait_: &TraitDef<'b>,
-                               enum_def: &'b EnumDef,
-                               type_attrs: &[ast::Attribute],
-                               type_ident: Ident,
-                               self_args: Vec<P<Expr>>,
-                               nonself_args: &[P<Expr>])
-                               -> P<Expr> {
-        self.build_enum_match_tuple(
-            cx, trait_, enum_def, type_attrs, type_ident, self_args, nonself_args)
+                                   cx: &mut ExtCtxt,
+                                   trait_: &TraitDef<'b>,
+                                   enum_def: &'b EnumDef,
+                                   type_attrs: &[ast::Attribute],
+                                   type_ident: Ident,
+                                   self_args: Vec<P<Expr>>,
+                                   nonself_args: &[P<Expr>])
+                                   -> P<Expr> {
+        self.build_enum_match_tuple(cx,
+                                    trait_,
+                                    enum_def,
+                                    type_attrs,
+                                    type_ident,
+                                    self_args,
+                                    nonself_args)
     }
 
 
@@ -1090,20 +1098,21 @@ fn expand_enum_method_body<'b>(&self,
     ///     ... // catch-all remainder can inspect above variant index values.
     /// }
     /// ```
-    fn build_enum_match_tuple<'b>(
-        &self,
-        cx: &mut ExtCtxt,
-        trait_: &TraitDef<'b>,
-        enum_def: &'b EnumDef,
-        type_attrs: &[ast::Attribute],
-        type_ident: Ident,
-        self_args: Vec<P<Expr>>,
-        nonself_args: &[P<Expr>]) -> P<Expr> {
+    fn build_enum_match_tuple<'b>(&self,
+                                  cx: &mut ExtCtxt,
+                                  trait_: &TraitDef<'b>,
+                                  enum_def: &'b EnumDef,
+                                  type_attrs: &[ast::Attribute],
+                                  type_ident: Ident,
+                                  self_args: Vec<P<Expr>>,
+                                  nonself_args: &[P<Expr>])
+                                  -> P<Expr> {
 
         let sp = trait_.span;
         let variants = &enum_def.variants;
 
-        let self_arg_names = self_args.iter().enumerate()
+        let self_arg_names = self_args.iter()
+            .enumerate()
             .map(|(arg_count, _self_arg)| {
                 if arg_count == 0 {
                     "__self".to_string()
@@ -1114,22 +1123,24 @@ fn build_enum_match_tuple<'b>(
             .collect::<Vec<String>>();
 
         let self_arg_idents = self_arg_names.iter()
-            .map(|name|cx.ident_of(&name[..]))
+            .map(|name| cx.ident_of(&name[..]))
             .collect::<Vec<ast::Ident>>();
 
         // The `vi_idents` will be bound, solely in the catch-all, to
         // a series of let statements mapping each self_arg to an int
         // value corresponding to its discriminant.
         let vi_idents: Vec<ast::Ident> = self_arg_names.iter()
-            .map(|name| { let vi_suffix = format!("{}_vi", &name[..]);
-                          cx.ident_of(&vi_suffix[..]) })
+            .map(|name| {
+                let vi_suffix = format!("{}_vi", &name[..]);
+                cx.ident_of(&vi_suffix[..])
+            })
             .collect::<Vec<ast::Ident>>();
 
         // Builds, via callback to call_substructure_method, the
         // delegated expression that handles the catch-all case,
         // using `__variants_tuple` to drive logic if necessary.
-        let catch_all_substructure = EnumNonMatchingCollapsed(
-            self_arg_idents, &variants[..], &vi_idents[..]);
+        let catch_all_substructure =
+            EnumNonMatchingCollapsed(self_arg_idents, &variants[..], &vi_idents[..]);
 
         let first_fieldless = variants.iter().find(|v| v.node.data.fields().is_empty());
 
@@ -1138,15 +1149,16 @@ fn build_enum_match_tuple<'b>(
         // (Variant2, Variant2, ...) => Body2
         // ...
         // where each tuple has length = self_args.len()
-        let mut match_arms: Vec<ast::Arm> = variants.iter().enumerate()
+        let mut match_arms: Vec<ast::Arm> = variants.iter()
+            .enumerate()
             .filter(|&(_, v)| !(self.unify_fieldless_variants && v.node.data.fields().is_empty()))
             .map(|(index, variant)| {
                 let mk_self_pat = |cx: &mut ExtCtxt, self_arg_name: &str| {
-                    let (p, idents) = trait_.create_enum_variant_pattern(
-                        cx, type_ident,
-                        variant,
-                        self_arg_name,
-                        ast::Mutability::Immutable);
+                    let (p, idents) = trait_.create_enum_variant_pattern(cx,
+                                                     type_ident,
+                                                     variant,
+                                                     self_arg_name,
+                                                     ast::Mutability::Immutable);
                     (cx.pat(sp, PatKind::Ref(p, ast::Mutability::Immutable)), idents)
                 };
 
@@ -1213,24 +1225,29 @@ fn build_enum_match_tuple<'b>(
                 // expressions for referencing every field of every
                 // Self arg, assuming all are instances of VariantK.
                 // Build up code associated with such a case.
-                let substructure = EnumMatching(index,
-                                                variant,
-                                                field_tuples);
-                let arm_expr = self.call_substructure_method(
-                    cx, trait_, type_ident, &self_args[..], nonself_args,
-                    &substructure);
+                let substructure = EnumMatching(index, variant, field_tuples);
+                let arm_expr = self.call_substructure_method(cx,
+                                                             trait_,
+                                                             type_ident,
+                                                             &self_args[..],
+                                                             nonself_args,
+                                                             &substructure);
 
                 cx.arm(sp, vec![single_pat], arm_expr)
-            }).collect();
+            })
+            .collect();
 
         let default = match first_fieldless {
             Some(v) if self.unify_fieldless_variants => {
                 // We need a default case that handles the fieldless variants.
                 // The index and actual variant aren't meaningful in this case,
                 // so just use whatever
-                Some(self.call_substructure_method(
-                    cx, trait_, type_ident, &self_args[..], nonself_args,
-                    &EnumMatching(0, v, Vec::new())))
+                Some(self.call_substructure_method(cx,
+                                                   trait_,
+                                                   type_ident,
+                                                   &self_args[..],
+                                                   nonself_args,
+                                                   &EnumMatching(0, v, Vec::new())))
             }
             _ if variants.len() > 1 && self_args.len() > 1 => {
                 // Since we know that all the arguments will match if we reach
@@ -1238,7 +1255,7 @@ fn build_enum_match_tuple<'b>(
                 // result of the catch all which should help llvm in optimizing it
                 Some(deriving::call_intrinsic(cx, sp, "unreachable", vec![]))
             }
-            _ => None
+            _ => None,
         };
         if let Some(arm) = default {
             match_arms.push(cx.arm(sp, vec![cx.pat_wild(sp)], arm));
@@ -1279,20 +1296,17 @@ fn build_enum_match_tuple<'b>(
             // ```
             let mut index_let_stmts: Vec<ast::Stmt> = Vec::new();
 
-            //We also build an expression which checks whether all discriminants are equal
+            // We also build an expression which checks whether all discriminants are equal
             // discriminant_test = __self0_vi == __self1_vi && __self0_vi == __self2_vi && ...
             let mut discriminant_test = cx.expr_bool(sp, true);
 
-            let target_type_name =
-                find_repr_type_name(&cx.parse_sess.span_diagnostic, type_attrs);
+            let target_type_name = find_repr_type_name(&cx.parse_sess.span_diagnostic, type_attrs);
 
             let mut first_ident = None;
             for (&ident, self_arg) in vi_idents.iter().zip(&self_args) {
                 let self_addr = cx.expr_addr_of(sp, self_arg.clone());
-                let variant_value = deriving::call_intrinsic(cx,
-                                                             sp,
-                                                             "discriminant_value",
-                                                             vec![self_addr]);
+                let variant_value =
+                    deriving::call_intrinsic(cx, sp, "discriminant_value", vec![self_addr]);
 
                 let target_ty = cx.ty_ident(sp, cx.ident_of(target_type_name));
                 let variant_disr = cx.expr_cast(sp, variant_value, target_ty);
@@ -1304,8 +1318,8 @@ fn build_enum_match_tuple<'b>(
                         let first_expr = cx.expr_ident(sp, first);
                         let id = cx.expr_ident(sp, ident);
                         let test = cx.expr_binary(sp, BinOpKind::Eq, first_expr, id);
-                        discriminant_test = cx.expr_binary(sp, BinOpKind::And,
-                                                           discriminant_test, test)
+                        discriminant_test =
+                            cx.expr_binary(sp, BinOpKind::And, discriminant_test, test)
                     }
                     None => {
                         first_ident = Some(ident);
@@ -1313,9 +1327,12 @@ fn build_enum_match_tuple<'b>(
                 }
             }
 
-            let arm_expr = self.call_substructure_method(
-                cx, trait_, type_ident, &self_args[..], nonself_args,
-                &catch_all_substructure);
+            let arm_expr = self.call_substructure_method(cx,
+                                                         trait_,
+                                                         type_ident,
+                                                         &self_args[..],
+                                                         nonself_args,
+                                                         &catch_all_substructure);
 
             // Final wrinkle: the self_args are expressions that deref
             // down to desired l-values, but we cannot actually deref
@@ -1325,7 +1342,7 @@ fn build_enum_match_tuple<'b>(
             let borrowed_self_args = self_args.move_map(|self_arg| cx.expr_addr_of(sp, self_arg));
             let match_arg = cx.expr(sp, ast::ExprKind::Tup(borrowed_self_args));
 
-            //Lastly we create an expression which branches on all discriminants being equal
+            // Lastly we create an expression which branches on all discriminants being equal
             //  if discriminant_test {
             //      match (...) {
             //          (Variant1, Variant1, ...) => Body1
@@ -1392,8 +1409,7 @@ fn build_enum_match_tuple<'b>(
             // that needs the feature gate enabled.)
 
             deriving::call_intrinsic(cx, sp, "unreachable", vec![])
-        }
-        else {
+        } else {
 
             // Final wrinkle: the self_args are expressions that deref
             // down to desired l-values, but we cannot actually deref
@@ -1413,26 +1429,30 @@ fn expand_static_enum_method_body(&self,
                                       type_ident: Ident,
                                       self_args: &[P<Expr>],
                                       nonself_args: &[P<Expr>])
-        -> P<Expr> {
-        let summary = enum_def.variants.iter().map(|v| {
-            let ident = v.node.name;
-            let summary = trait_.summarise_struct(cx, &v.node.data);
-            (ident, v.span, summary)
-        }).collect();
-        self.call_substructure_method(cx, trait_, type_ident,
-                                      self_args, nonself_args,
+                                      -> P<Expr> {
+        let summary = enum_def.variants
+            .iter()
+            .map(|v| {
+                let ident = v.node.name;
+                let summary = trait_.summarise_struct(cx, &v.node.data);
+                (ident, v.span, summary)
+            })
+            .collect();
+        self.call_substructure_method(cx,
+                                      trait_,
+                                      type_ident,
+                                      self_args,
+                                      nonself_args,
                                       &StaticEnum(enum_def, summary))
     }
 }
 
 // general helper methods.
 impl<'a> TraitDef<'a> {
-    fn summarise_struct(&self,
-                        cx: &mut ExtCtxt,
-                        struct_def: &VariantData) -> StaticFields {
+    fn summarise_struct(&self, cx: &mut ExtCtxt, struct_def: &VariantData) -> StaticFields {
         let mut named_idents = Vec::new();
         let mut just_spans = Vec::new();
-        for field in struct_def.fields(){
+        for field in struct_def.fields() {
             let sp = Span { expn_id: self.span.expn_id, ..field.span };
             match field.ident {
                 Some(ident) => named_idents.push((ident, sp)),
@@ -1441,9 +1461,11 @@ fn summarise_struct(&self,
         }
 
         match (just_spans.is_empty(), named_idents.is_empty()) {
-            (false, false) => cx.span_bug(self.span,
-                                          "a struct with named and unnamed \
-                                          fields in generic `derive`"),
+            (false, false) => {
+                cx.span_bug(self.span,
+                            "a struct with named and unnamed \
+                                          fields in generic `derive`")
+            }
             // named fields
             (_, false) => Named(named_idents),
             // empty structs
@@ -1454,46 +1476,57 @@ fn summarise_struct(&self,
 
     fn create_subpatterns(&self,
                           cx: &mut ExtCtxt,
-                          field_paths: Vec<ast::SpannedIdent> ,
+                          field_paths: Vec<ast::SpannedIdent>,
                           mutbl: ast::Mutability)
                           -> Vec<P<ast::Pat>> {
-        field_paths.iter().map(|path| {
-            cx.pat(path.span,
-                        PatKind::Ident(ast::BindingMode::ByRef(mutbl), (*path).clone(), None))
-        }).collect()
+        field_paths.iter()
+            .map(|path| {
+                cx.pat(path.span,
+                       PatKind::Ident(ast::BindingMode::ByRef(mutbl), (*path).clone(), None))
+            })
+            .collect()
     }
 
-    fn create_struct_pattern(&self,
-                             cx: &mut ExtCtxt,
-                             struct_path: ast::Path,
-                             struct_def: &'a VariantData,
-                             prefix: &str,
-                             mutbl: ast::Mutability)
-                             -> (P<ast::Pat>, Vec<(Span, Option<Ident>,
-                                                   P<Expr>,
-                                                   &'a [ast::Attribute])>) {
+    fn create_struct_pattern
+        (&self,
+         cx: &mut ExtCtxt,
+         struct_path: ast::Path,
+         struct_def: &'a VariantData,
+         prefix: &str,
+         mutbl: ast::Mutability)
+         -> (P<ast::Pat>, Vec<(Span, Option<Ident>, P<Expr>, &'a [ast::Attribute])>) {
         let mut paths = Vec::new();
         let mut ident_exprs = Vec::new();
         for (i, struct_field) in struct_def.fields().iter().enumerate() {
             let sp = Span { expn_id: self.span.expn_id, ..struct_field.span };
             let ident = cx.ident_of(&format!("{}_{}", prefix, i));
-            paths.push(codemap::Spanned{span: sp, node: ident});
-            let val = cx.expr_deref(sp, cx.expr_path(cx.path_ident(sp,ident)));
+            paths.push(codemap::Spanned {
+                span: sp,
+                node: ident,
+            });
+            let val = cx.expr_deref(sp, cx.expr_path(cx.path_ident(sp, ident)));
             let val = cx.expr(sp, ast::ExprKind::Paren(val));
             ident_exprs.push((sp, struct_field.ident, val, &struct_field.attrs[..]));
         }
 
         let subpats = self.create_subpatterns(cx, paths, mutbl);
         let pattern = if struct_def.is_struct() {
-            let field_pats = subpats.into_iter().zip(&ident_exprs).map(|(pat, &(sp, ident, _, _))| {
-                if ident.is_none() {
-                    cx.span_bug(sp, "a braced struct with unnamed fields in `derive`");
-                }
-                codemap::Spanned {
-                    span: pat.span,
-                    node: ast::FieldPat { ident: ident.unwrap(), pat: pat, is_shorthand: false },
-                }
-            }).collect();
+            let field_pats = subpats.into_iter()
+                .zip(&ident_exprs)
+                .map(|(pat, &(sp, ident, _, _))| {
+                    if ident.is_none() {
+                        cx.span_bug(sp, "a braced struct with unnamed fields in `derive`");
+                    }
+                    codemap::Spanned {
+                        span: pat.span,
+                        node: ast::FieldPat {
+                            ident: ident.unwrap(),
+                            pat: pat,
+                            is_shorthand: false,
+                        },
+                    }
+                })
+                .collect();
             cx.pat_struct(self.span, struct_path, field_pats)
         } else {
             cx.pat_enum(self.span, struct_path, subpats)
@@ -1502,20 +1535,21 @@ fn create_struct_pattern(&self,
         (pattern, ident_exprs)
     }
 
-    fn create_enum_variant_pattern(&self,
-                                   cx: &mut ExtCtxt,
-                                   enum_ident: ast::Ident,
-                                   variant: &'a ast::Variant,
-                                   prefix: &str,
-                                   mutbl: ast::Mutability)
-        -> (P<ast::Pat>, Vec<(Span, Option<Ident>, P<Expr>, &'a [ast::Attribute])>) {
+    fn create_enum_variant_pattern
+        (&self,
+         cx: &mut ExtCtxt,
+         enum_ident: ast::Ident,
+         variant: &'a ast::Variant,
+         prefix: &str,
+         mutbl: ast::Mutability)
+         -> (P<ast::Pat>, Vec<(Span, Option<Ident>, P<Expr>, &'a [ast::Attribute])>) {
         let variant_ident = variant.node.name;
         let variant_path = cx.path(variant.span, vec![enum_ident, variant_ident]);
         self.create_struct_pattern(cx, variant_path, &variant.node.data, prefix, mutbl)
     }
 }
 
-/* helpful premade recipes */
+// helpful premade recipes
 
 /// Fold the fields. `use_foldl` controls whether this is done
 /// left-to-right (`true`) or right-to-left (`false`).
@@ -1526,35 +1560,29 @@ pub fn cs_fold<F>(use_foldl: bool,
                   cx: &mut ExtCtxt,
                   trait_span: Span,
                   substructure: &Substructure)
-                  -> P<Expr> where
-    F: FnMut(&mut ExtCtxt, Span, P<Expr>, P<Expr>, &[P<Expr>]) -> P<Expr>,
+                  -> P<Expr>
+    where F: FnMut(&mut ExtCtxt, Span, P<Expr>, P<Expr>, &[P<Expr>]) -> P<Expr>
 {
     match *substructure.fields {
-        EnumMatching(_, _, ref all_fields) | Struct(_, ref all_fields) => {
+        EnumMatching(_, _, ref all_fields) |
+        Struct(_, ref all_fields) => {
             if use_foldl {
                 all_fields.iter().fold(base, |old, field| {
-                    f(cx,
-                      field.span,
-                      old,
-                      field.self_.clone(),
-                      &field.other)
+                    f(cx, field.span, old, field.self_.clone(), &field.other)
                 })
             } else {
                 all_fields.iter().rev().fold(base, |old, field| {
-                    f(cx,
-                      field.span,
-                      old,
-                      field.self_.clone(),
-                      &field.other)
+                    f(cx, field.span, old, field.self_.clone(), &field.other)
                 })
             }
-        },
-        EnumNonMatchingCollapsed(ref all_args, _, tuple) =>
-            enum_nonmatch_f(cx, trait_span, (&all_args[..], tuple),
-                            substructure.nonself_args),
-        StaticEnum(..) | StaticStruct(..) => {
-            cx.span_bug(trait_span, "static function in `derive`")
         }
+        EnumNonMatchingCollapsed(ref all_args, _, tuple) => {
+            enum_nonmatch_f(cx,
+                            trait_span,
+                            (&all_args[..], tuple),
+                            substructure.nonself_args)
+        }
+        StaticEnum(..) | StaticStruct(..) => cx.span_bug(trait_span, "static function in `derive`"),
     }
 }
 
@@ -1572,29 +1600,34 @@ pub fn cs_same_method<F>(f: F,
                          cx: &mut ExtCtxt,
                          trait_span: Span,
                          substructure: &Substructure)
-                         -> P<Expr> where
-    F: FnOnce(&mut ExtCtxt, Span, Vec<P<Expr>>) -> P<Expr>,
+                         -> P<Expr>
+    where F: FnOnce(&mut ExtCtxt, Span, Vec<P<Expr>>) -> P<Expr>
 {
     match *substructure.fields {
-        EnumMatching(_, _, ref all_fields) | Struct(_, ref all_fields) => {
+        EnumMatching(_, _, ref all_fields) |
+        Struct(_, ref all_fields) => {
             // call self_n.method(other_1_n, other_2_n, ...)
-            let called = all_fields.iter().map(|field| {
-                cx.expr_method_call(field.span,
-                                    field.self_.clone(),
-                                    substructure.method_ident,
-                                    field.other.iter()
-                                               .map(|e| cx.expr_addr_of(field.span, e.clone()))
-                                               .collect())
-            }).collect();
+            let called = all_fields.iter()
+                .map(|field| {
+                    cx.expr_method_call(field.span,
+                                        field.self_.clone(),
+                                        substructure.method_ident,
+                                        field.other
+                                            .iter()
+                                            .map(|e| cx.expr_addr_of(field.span, e.clone()))
+                                            .collect())
+                })
+                .collect();
 
             f(cx, trait_span, called)
-        },
-        EnumNonMatchingCollapsed(ref all_self_args, _, tuple) =>
-            enum_nonmatch_f(cx, trait_span, (&all_self_args[..], tuple),
-                            substructure.nonself_args),
-        StaticEnum(..) | StaticStruct(..) => {
-            cx.span_bug(trait_span, "static function in `derive`")
         }
+        EnumNonMatchingCollapsed(ref all_self_args, _, tuple) => {
+            enum_nonmatch_f(cx,
+                            trait_span,
+                            (&all_self_args[..], tuple),
+                            substructure.nonself_args)
+        }
+        StaticEnum(..) | StaticStruct(..) => cx.span_bug(trait_span, "static function in `derive`"),
     }
 }
 
@@ -1606,10 +1639,8 @@ pub fn is_type_without_fields(item: &Annotatable) -> bool {
             ast::ItemKind::Enum(ref enum_def, _) => {
                 enum_def.variants.iter().all(|v| v.node.data.fields().is_empty())
             }
-            ast::ItemKind::Struct(ref variant_data, _) => {
-                variant_data.fields().is_empty()
-            }
-            _ => false
+            ast::ItemKind::Struct(ref variant_data, _) => variant_data.fields().is_empty(),
+            _ => false,
         }
     } else {
         false
index 0fad96c84ef3d2a859569768a4115995ebfc54b0..81c8e7112dbd590d131d29dc9165e6b6a05fb45d 100644 (file)
@@ -12,8 +12,8 @@
 use deriving::generic::*;
 use deriving::generic::ty::*;
 
-use syntax::ast::{MetaItem, Expr, Mutability};
-use syntax::ext::base::{ExtCtxt, Annotatable};
+use syntax::ast::{Expr, MetaItem, Mutability};
+use syntax::ext::base::{Annotatable, ExtCtxt};
 use syntax::ext::build::AstBuilder;
 use syntax::ptr::P;
 use syntax_pos::Span;
@@ -22,11 +22,9 @@ pub fn expand_deriving_hash(cx: &mut ExtCtxt,
                             span: Span,
                             mitem: &MetaItem,
                             item: &Annotatable,
-                            push: &mut FnMut(Annotatable))
-{
+                            push: &mut FnMut(Annotatable)) {
 
-    let path = Path::new_(pathvec_std!(cx, core::hash::Hash), None,
-                          vec!(), true);
+    let path = Path::new_(pathvec_std!(cx, core::hash::Hash), None, vec![], true);
 
     let typaram = &*deriving::hygienic_type_parameter(item, "__H");
 
@@ -38,25 +36,23 @@ pub fn expand_deriving_hash(cx: &mut ExtCtxt,
         additional_bounds: Vec::new(),
         generics: LifetimeBounds::empty(),
         is_unsafe: false,
-        methods: vec!(
-            MethodDef {
-                name: "hash",
-                generics: LifetimeBounds {
-                    lifetimes: Vec::new(),
-                    bounds: vec![(typaram,
-                                  vec![path_std!(cx, core::hash::Hasher)])],
-                },
-                explicit_self: borrowed_explicit_self(),
-                args: vec!(Ptr(Box::new(Literal(arg)), Borrowed(None, Mutability::Mutable))),
-                ret_ty: nil_ty(),
-                attributes: vec![],
-                is_unsafe: false,
-                unify_fieldless_variants: true,
-                combine_substructure: combine_substructure(Box::new(|a, b, c| {
-                    hash_substructure(a, b, c)
-                }))
-            }
-        ),
+        methods: vec![MethodDef {
+                          name: "hash",
+                          generics: LifetimeBounds {
+                              lifetimes: Vec::new(),
+                              bounds: vec![(typaram, vec![path_std!(cx, core::hash::Hasher)])],
+                          },
+                          explicit_self: borrowed_explicit_self(),
+                          args: vec![Ptr(Box::new(Literal(arg)),
+                                         Borrowed(None, Mutability::Mutable))],
+                          ret_ty: nil_ty(),
+                          attributes: vec![],
+                          is_unsafe: false,
+                          unify_fieldless_variants: true,
+                          combine_substructure: combine_substructure(Box::new(|a, b, c| {
+                              hash_substructure(a, b, c)
+                          })),
+                      }],
         associated_types: Vec::new(),
     };
 
@@ -66,7 +62,10 @@ pub fn expand_deriving_hash(cx: &mut ExtCtxt,
 fn hash_substructure(cx: &mut ExtCtxt, trait_span: Span, substr: &Substructure) -> P<Expr> {
     let state_expr = match (substr.nonself_args.len(), substr.nonself_args.get(0)) {
         (1, Some(o_f)) => o_f,
-        _ => cx.span_bug(trait_span, "incorrect number of arguments in `derive(Hash)`")
+        _ => {
+            cx.span_bug(trait_span,
+                        "incorrect number of arguments in `derive(Hash)`")
+        }
     };
     let call_hash = |span, thing_expr| {
         let hash_path = {
@@ -75,7 +74,7 @@ fn hash_substructure(cx: &mut ExtCtxt, trait_span: Span, substr: &Substructure)
             cx.expr_path(cx.path_global(span, strs))
         };
         let ref_thing = cx.expr_addr_of(span, thing_expr);
-        let expr = cx.expr_call(span, hash_path, vec!(ref_thing, state_expr.clone()));
+        let expr = cx.expr_call(span, hash_path, vec![ref_thing, state_expr.clone()]);
         cx.stmt_expr(expr)
     };
     let mut stmts = Vec::new();
@@ -92,7 +91,7 @@ fn hash_substructure(cx: &mut ExtCtxt, trait_span: Span, substr: &Substructure)
 
             fs
         }
-        _ => cx.span_bug(trait_span, "impossible substructure in `derive(Hash)`")
+        _ => cx.span_bug(trait_span, "impossible substructure in `derive(Hash)`"),
     };
 
     for &FieldInfo { ref self_, span, .. } in fields {
index 169e8073661976cf56c709ac1b1aa3bcb641d3a5..80e2a923e5569ef9693f5efd9742c17e46e1198c 100644 (file)
@@ -10,9 +10,9 @@
 
 //! The compiler code necessary to implement the `#[derive]` extensions.
 
-use syntax::ast::{MetaItem, MetaItemKind, self};
+use syntax::ast::{self, MetaItem, MetaItemKind};
 use syntax::attr::AttrMetaMethods;
-use syntax::ext::base::{ExtCtxt, SyntaxEnv, Annotatable};
+use syntax::ext::base::{Annotatable, ExtCtxt, SyntaxEnv};
 use syntax::ext::base::{MultiDecorator, MultiItemDecorator, MultiModifier};
 use syntax::ext::build::AstBuilder;
 use syntax::feature_gate;
@@ -123,7 +123,8 @@ fn expand_derive(cx: &mut ExtCtxt,
                             span: Some(titem.span),
                             allow_internal_unstable: true,
                         },
-                    }), ..titem.span
+                    }),
+                    ..titem.span
                 };
 
                 if &tname[..] == "Eq" {
@@ -133,8 +134,9 @@ fn expand_derive(cx: &mut ExtCtxt,
                 }
 
                 // #[derive(Foo, Bar)] expands to #[derive_Foo] #[derive_Bar]
-                item.attrs.push(cx.attribute(span, cx.meta_word(titem.span,
-                    intern_and_get_ident(&format!("derive_{}", tname)))));
+                item.attrs.push(cx.attribute(span,
+                               cx.meta_word(titem.span,
+                                            intern_and_get_ident(&format!("derive_{}", tname)))));
             }
 
             // RFC #1445. `#[derive(PartialEq, Eq)]` adds a (trusted)
@@ -142,18 +144,18 @@ fn expand_derive(cx: &mut ExtCtxt,
             if let Some(eq_span) = eq_span {
                 if found_partial_eq {
                     let structural_match = intern_and_get_ident("structural_match");
-                    item.attrs.push(cx.attribute(eq_span,
-                                                 cx.meta_word(eq_span,
-                                                              structural_match)));
+                    item.attrs.push(cx.attribute(eq_span, cx.meta_word(eq_span, structural_match)));
                 }
             }
 
             item
         })
-    }, |a| {
-        cx.span_err(span, "`derive` can only be applied to items");
-        a
-    });
+    },
+                                        |a| {
+                                            cx.span_err(span,
+                                                        "`derive` can only be applied to items");
+                                            a
+                                        });
     debug!("expand_derive: annotatable output = {:?}", annot);
     annot
 }
@@ -261,8 +263,10 @@ fn warn_if_deprecated(ecx: &mut ExtCtxt, sp: Span, name: &str) {
         "Decodable" => Some("RustcDecodable"),
         _ => None,
     } {
-        ecx.span_warn(sp, &format!("derive({}) is deprecated in favor of derive({})",
-                                   name, replacement));
+        ecx.span_warn(sp,
+                      &format!("derive({}) is deprecated in favor of derive({})",
+                               name,
+                               replacement));
     }
 }
 
@@ -275,8 +279,7 @@ fn hygienic_type_parameter(item: &Annotatable, base: &str) -> String {
     if let Annotatable::Item(ref item) = *item {
         match item.node {
             ast::ItemKind::Struct(_, ast::Generics { ref ty_params, .. }) |
-                ast::ItemKind::Enum(_, ast::Generics { ref ty_params, .. }) => {
-
+            ast::ItemKind::Enum(_, ast::Generics { ref ty_params, .. }) => {
                 for ty in ty_params.iter() {
                     typaram.push_str(&ty.ident.name.as_str());
                 }
@@ -293,7 +296,8 @@ fn hygienic_type_parameter(item: &Annotatable, base: &str) -> String {
 fn call_intrinsic(cx: &ExtCtxt,
                   span: Span,
                   intrinsic: &str,
-                  args: Vec<P<ast::Expr>>) -> P<ast::Expr> {
+                  args: Vec<P<ast::Expr>>)
+                  -> P<ast::Expr> {
     let path = cx.std_path(&["intrinsics", intrinsic]);
     let call = cx.expr_call_global(span, path, args);
 
@@ -301,6 +305,6 @@ fn call_intrinsic(cx: &ExtCtxt,
         stmts: vec![cx.stmt_expr(call)],
         id: ast::DUMMY_NODE_ID,
         rules: ast::BlockCheckMode::Unsafe(ast::CompilerGenerated),
-        span: span }))
+        span: span,
+    }))
 }
-
index 7dfe19452a2a933a64cdd849e2a21ce535880f50..c96be8fec2b02abb4ffffecddaa0884187641303 100644 (file)
@@ -193,20 +193,6 @@ pub fn new() -> MultiSpan {
         }
     }
 
-    pub fn from_span(primary_span: Span) -> MultiSpan {
-        MultiSpan {
-            primary_spans: vec![primary_span],
-            span_labels: vec![]
-        }
-    }
-
-    pub fn from_spans(vec: Vec<Span>) -> MultiSpan {
-        MultiSpan {
-            primary_spans: vec,
-            span_labels: vec![]
-        }
-    }
-
     pub fn push_span_label(&mut self, span: Span, label: String) {
         self.span_labels.push((span, label));
     }
@@ -254,7 +240,10 @@ pub fn span_labels(&self) -> Vec<SpanLabel> {
 
 impl From<Span> for MultiSpan {
     fn from(span: Span) -> MultiSpan {
-        MultiSpan::from_span(span)
+        MultiSpan {
+            primary_spans: vec![span],
+            span_labels: vec![]
+        }
     }
 }
 
index aadfe202afe796ba6d05257e5df80196e0aff51d..d9b6c9ed74dd21b4fec9ec88ebbce37b27990ea3 100644 (file)
@@ -58,6 +58,7 @@ pub enum _Unwind_Reason_Code {
 pub type _Unwind_Exception_Class = u64;
 
 pub type _Unwind_Word = libc::uintptr_t;
+pub type _Unwind_Ptr = libc::uintptr_t;
 
 pub type _Unwind_Trace_Fn = extern "C" fn(ctx: *mut _Unwind_Context, arg: *mut libc::c_void)
                                           -> _Unwind_Reason_Code;
@@ -156,6 +157,13 @@ pub fn _Unwind_GetIPInfo(ctx: *mut _Unwind_Context,
                              ip_before_insn: *mut libc::c_int)
                              -> libc::uintptr_t;
 
+    pub fn _Unwind_GetLanguageSpecificData(ctx: *mut _Unwind_Context) -> _Unwind_Ptr;
+    pub fn _Unwind_GetRegionStart(ctx: *mut _Unwind_Context) -> _Unwind_Ptr;
+    pub fn _Unwind_GetTextRelBase(ctx: *mut _Unwind_Context) -> _Unwind_Ptr;
+    pub fn _Unwind_GetDataRelBase(ctx: *mut _Unwind_Context) -> _Unwind_Ptr;
+    pub fn _Unwind_SetGR(ctx: *mut _Unwind_Context, reg_index: libc::c_int, value: _Unwind_Ptr);
+    pub fn _Unwind_SetIP(ctx: *mut _Unwind_Context, value: _Unwind_Ptr);
+
     #[cfg(all(not(target_os = "android"),
               not(all(target_os = "linux", target_arch = "arm"))))]
     pub fn _Unwind_FindEnclosingFunction(pc: *mut libc::c_void) -> *mut libc::c_void;
index 4def60e485f7e0a05635c3648f5edf0669ea535a..0b2287cf233d15becbf9d5da283d62194d473483 100644 (file)
@@ -105,6 +105,7 @@ dependencies = [
  "rustc 0.0.0",
  "rustc_back 0.0.0",
  "rustc_const_math 0.0.0",
+ "rustc_errors 0.0.0",
  "serialize 0.0.0",
  "syntax 0.0.0",
  "syntax_pos 0.0.0",
diff --git a/src/test/codegen/internalize-closures.rs b/src/test/codegen/internalize-closures.rs
new file mode 100644 (file)
index 0000000..90aafd6
--- /dev/null
@@ -0,0 +1,20 @@
+// Copyright 2016 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.
+
+// compile-flags: -C no-prepopulate-passes
+
+pub fn main() {
+
+    // We want to make sure that closures get 'internal' linkage instead of
+    // 'weak_odr' when they are not shared between codegen units
+    // CHECK: define internal {{.*}}_ZN20internalize_closures4main{{.*}}$u7b$$u7b$closure$u7d$$u7d$
+    let c = |x:i32| { x + 1 };
+    let _ = c(1);
+}
index e65230389f9c0412297a2d5fa95c25934e1ada3b..501c66e75cded115892fddfe02c0be9588b0c9c0 100644 (file)
@@ -10,7 +10,8 @@
 
 const A: &'static [i32] = &[];
 const B: i32 = (&A)[1];
-//~^ ERROR index out of bounds: the len is 0 but the index is 1
+//~^ ERROR constant evaluation error
+//~| index out of bounds: the len is 0 but the index is 1
 
 fn main() {
     let _ = B;
index 69d84e24c4982db2c7d5549461b425eb2f74a4b3..d3b43e83bfe5218ac914584e6424f6fd4ee4a9d4 100644 (file)
@@ -10,7 +10,8 @@
 
 const A: [i32; 0] = [];
 const B: i32 = A[1];
-//~^ ERROR index out of bounds: the len is 0 but the index is 1
+//~^ ERROR constant evaluation error
+//~| index out of bounds: the len is 0 but the index is 1
 
 fn main() {
     let _ = B;
index 5d8007defc9065d15bc3db1b33929f31ba56e11e..0239986f5ad3aef5dfe5886ed2f142bc93c902e1 100644 (file)
@@ -14,7 +14,7 @@ trait Foo {
     const ID: usize;
 }
 
-const X: [i32; <i32 as Foo>::ID] = [0, 1, 2]; //~ ERROR E0250
+const X: [i32; <i32 as Foo>::ID] = [0, 1, 2]; //~ ERROR E0080
 
 fn main() {
     assert_eq!(1, X);
index 4658d0f057d71c85aeeab2c9040bf4fd2c92bf40..95508a31044b87797dff021bc5a6a07b23cd2ff9 100644 (file)
@@ -18,9 +18,8 @@ trait Foo {
 
 impl Foo for SignedBar {
     const BAR: i32 = -1;
-    //~^ ERROR implemented const `BAR` has an incompatible type for trait
-    //~| expected u32,
-    //~| found i32 [E0326]
+    //~^ ERROR implemented const `BAR` has an incompatible type for trait [E0326]
+    //~| expected u32, found i32
 }
 
 fn main() {}
index 2f687350f34e0bcd30b266f42fd7fa05854ccc77..c3fa39659b968217fb83481c75edea49d0855a37 100644 (file)
@@ -25,7 +25,8 @@ impl Foo for Def {
 }
 
 pub fn test<A: Foo, B: Foo>() {
-    let _array = [4; <A as Foo>::Y]; //~ error: expected constant integer
+    let _array = [4; <A as Foo>::Y]; //~ ERROR E0080
+                                     //~| non-constant path in constant
 }
 
 fn main() {
index 8c66160e8a36f723c0a16c017d2956a83814f8fe..cb952f6534f0e57da26b0e45b6d91a14c64be083 100644 (file)
@@ -47,10 +47,8 @@ pub fn main() {
     let a = 42;
     foo1(a);
     //~^ ERROR type mismatch resolving
-    //~| expected usize
-    //~| found struct `Bar`
+    //~| expected usize, found struct `Bar`
     baz(&a);
     //~^ ERROR type mismatch resolving
-    //~| expected usize
-    //~| found struct `Bar`
+    //~| expected usize, found struct `Bar`
 }
diff --git a/src/test/compile-fail/associated-types/higher-ranked-projection.rs b/src/test/compile-fail/associated-types/higher-ranked-projection.rs
new file mode 100644 (file)
index 0000000..12341fa
--- /dev/null
@@ -0,0 +1,38 @@
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(rustc_attrs)]
+
+// revisions: good bad
+
+trait Mirror {
+    type Image;
+}
+
+impl<T> Mirror for T {
+    type Image = T;
+}
+
+#[cfg(bad)]
+fn foo<U, T>(_t: T)
+    where for<'a> &'a T: Mirror<Image=U>
+{}
+
+#[cfg(good)]
+fn foo<U, T>(_t: T)
+    where for<'a> &'a T: Mirror<Image=&'a U>
+{}
+
+#[rustc_error]
+fn main() { //[good]~ ERROR compilation successful
+    foo(());
+    //[bad]~^ ERROR type mismatch resolving `for<'a> <&'a _ as Mirror>::Image == _`
+    //[bad]~| expected bound lifetime parameter 'a, found concrete lifetime
+}
index faabed4fd5e422d5f73ba2a92fc8b705848d8c72..b980bc02c85a24fb22a4d7cb0e161768a0b858fa 100644 (file)
@@ -16,7 +16,8 @@
 const BAR: u32 = FOO[5]; // no error, because the error below occurs before regular const eval
 
 const BLUB: [u32; FOO[4]] = [5, 6];
-//~^ ERROR array length constant evaluation error: index out of bounds: the len is 3 but the index is 4 [E0250]
+//~^ ERROR constant evaluation error [E0080]
+//~| index out of bounds: the len is 3 but the index is 4
 
 fn main() {
     let _ = BAR;
index 1143d3bd5cd96491e1e5c5116eef414e01843d5a..7e2eabf412d6c2683646b19a0bdb27c4e65c4a21 100644 (file)
@@ -15,5 +15,6 @@ fn f(x: usize) -> usize {
 }
 
 fn main() {
-    let _ = [0; f(2)]; //~ ERROR: non-constant path in constant expression [E0307]
+    let _ = [0; f(2)]; //~ ERROR constant evaluation error [E0080]
+                       //~| non-constant path in constant expression
 }
index a1d3888e78ea0dc16fe3d9cd6bd454a0764fc51e..f2079800cad311e624ee9ca644603877889353d1 100644 (file)
@@ -22,21 +22,29 @@ fn black_box<T>(_: T) {
 
 // Make sure that the two uses get two errors.
 const FOO: u8 = [5u8][1];
-//~^ ERROR index out of bounds: the len is 1 but the index is 1
-//~^^ ERROR index out of bounds: the len is 1 but the index is 1
+//~^ ERROR constant evaluation error
+//~| index out of bounds: the len is 1 but the index is 1
+//~^^^ ERROR constant evaluation error
+//~| index out of bounds: the len is 1 but the index is 1
 
 fn main() {
     let a = -std::i8::MIN;
-    //~^ WARN attempted to negate with overflow
+    //~^ WARN this expression will panic at run-time
+    //~| attempted to negate with overflow
     let b = 200u8 + 200u8 + 200u8;
-    //~^ WARN attempted to add with overflow
-    //~| WARN attempted to add with overflow
+    //~^ WARN this expression will panic at run-time
+    //~| attempted to add with overflow
+    //~^^^ WARN this expression will panic at run-time
+    //~| attempted to add with overflow
     let c = 200u8 * 4;
-    //~^ WARN attempted to multiply with overflow
+    //~^ WARN this expression will panic at run-time
+    //~| attempted to multiply with overflow
     let d = 42u8 - (42u8 + 1);
-    //~^ WARN attempted to subtract with overflow
+    //~^ WARN this expression will panic at run-time
+    //~| attempted to subtract with overflow
     let _e = [5u8][1];
-    //~^ WARN index out of bounds: the len is 1 but the index is 1
+    //~^ WARN this expression will panic at run-time
+    //~| index out of bounds: the len is 1 but the index is 1
     black_box(a);
     black_box(b);
     black_box(c);
index 07e27a7dc9a9a412b2eb14155044584b7980c325..4749457da8814ba89b294c624f1397770bb495ae 100644 (file)
 
 const NEG_128: i8 = -128;
 const NEG_NEG_128: i8 = -NEG_128;
-//~^ ERROR constant evaluation error: attempted to negate with overflow
-//~| ERROR attempted to negate with overflow
-//~| ERROR attempted to negate with overflow
+//~^ ERROR constant evaluation error
+//~| attempted to negate with overflow
+//~| ERROR constant evaluation error
+//~| attempted to negate with overflow
+//~| ERROR constant evaluation error
+//~| attempted to negate with overflow
 
 fn main() {
     match -128i8 {
-        NEG_NEG_128 => println!("A"), //~ NOTE in pattern here
+        NEG_NEG_128 => println!("A"), //~ NOTE for pattern here
         _ => println!("B"),
     }
 }
index c90ae045f96b4aa0430e2b3c020f47d33caeba1a..c78c74e9e231b5d8ccfdfbf1b2b250c6e1e4afba 100644 (file)
@@ -17,7 +17,7 @@
 // self-hosted and a cross-compiled setup; therefore resorting to
 // error-pattern for now.
 
-// error-pattern: expected constant integer for repeat count, but attempted to add with overflow
+// error-pattern: attempted to add with overflow
 
 #![allow(unused_imports)]
 
index 31e1a72967f4dcf4860574ce6f563503a3d2637d..9e7a5ecae105a2b123a51519f20a2944b26bfe6a 100644 (file)
@@ -20,9 +20,8 @@
 
 const A_I8_T
     : [u32; (i8::MAX as i8 + 1u8) as usize]
-    //~^ ERROR mismatched types:
-    //~| expected `i8`,
-    //~| found `u8` [E0250]
+    //~^ ERROR constant evaluation error [E0080]
+    //~| expected i8, found u8
     = [0; (i8::MAX as usize) + 1];
 
 
@@ -33,7 +32,8 @@
 
 const A_BAD_CHAR_USIZE
     : [u32; 5i8 as char as usize]
-    //~^ ERROR only `u8` can be cast as `char`, not `i8`
+    //~^ ERROR constant evaluation error
+    //~| only `u8` can be cast as `char`, not `i8`
     = [0; 5];
 
 fn main() {}
index 3dfcb5bb29a24a68701b48d195f62aca3361240c..c1c693544fa96e7fd224ebdeceb01341a3894d2e 100644 (file)
 
 const VALS_I8: (i8, i8, i8, i8) =
     (-i8::MIN,
-     //~^ ERROR attempted to negate with overflow
+     //~^ ERROR constant evaluation error
+     //~| attempted to negate with overflow
      i8::MIN - 1,
-     //~^ ERROR attempted to subtract with overflow
+     //~^ ERROR constant evaluation error
+     //~| attempted to subtract with overflow
      i8::MAX + 1,
-     //~^ ERROR attempted to add with overflow
+     //~^ ERROR constant evaluation error
+     //~| attempted to add with overflow
      i8::MIN * 2,
-     //~^ ERROR attempted to multiply with overflow
+     //~^ ERROR constant evaluation error
+     //~| attempted to multiply with overflow
      );
 
 const VALS_I16: (i16, i16, i16, i16) =
     (-i16::MIN,
-     //~^ ERROR attempted to negate with overflow
+     //~^ ERROR constant evaluation error
+     //~| attempted to negate with overflow
      i16::MIN - 1,
-     //~^ ERROR attempted to subtract with overflow
+     //~^ ERROR constant evaluation error
+     //~| attempted to subtract with overflow
      i16::MAX + 1,
-     //~^ ERROR attempted to add with overflow
+     //~^ ERROR constant evaluation error
+     //~| attempted to add with overflow
      i16::MIN * 2,
-     //~^ ERROR attempted to multiply with overflow
+     //~^ ERROR constant evaluation error
+     //~| attempted to multiply with overflow
      );
 
 const VALS_I32: (i32, i32, i32, i32) =
     (-i32::MIN,
-     //~^ ERROR attempted to negate with overflow
+     //~^ ERROR constant evaluation error
+     //~| attempted to negate with overflow
      i32::MIN - 1,
-     //~^ ERROR attempted to subtract with overflow
+     //~^ ERROR constant evaluation error
+     //~| attempted to subtract with overflow
      i32::MAX + 1,
-     //~^ ERROR attempted to add with overflow
+     //~^ ERROR constant evaluation error
+     //~| attempted to add with overflow
      i32::MIN * 2,
-     //~^ ERROR attempted to multiply with overflow
+     //~^ ERROR constant evaluation error
+     //~| attempted to multiply with overflow
      );
 
 const VALS_I64: (i64, i64, i64, i64) =
     (-i64::MIN,
-     //~^ ERROR attempted to negate with overflow
+     //~^ ERROR constant evaluation error
+     //~| attempted to negate with overflow
      i64::MIN - 1,
-     //~^ ERROR attempted to subtract with overflow
+     //~^ ERROR constant evaluation error
+     //~| attempted to subtract with overflow
      i64::MAX + 1,
-     //~^ ERROR attempted to add with overflow
+     //~^ ERROR constant evaluation error
+     //~| attempted to add with overflow
      i64::MAX * 2,
-     //~^ ERROR attempted to multiply with overflow
+     //~^ ERROR constant evaluation error
+     //~| attempted to multiply with overflow
      );
 
 const VALS_U8: (u8, u8, u8, u8) =
     (-(u8::MIN as i8) as u8,
      u8::MIN - 1,
-     //~^ ERROR attempted to subtract with overflow
+     //~^ ERROR constant evaluation error
+     //~| attempted to subtract with overflow
      u8::MAX + 1,
-     //~^ ERROR attempted to add with overflow
+     //~^ ERROR constant evaluation error
+     //~| attempted to add with overflow
      u8::MAX * 2,
-     //~^ ERROR attempted to multiply with overflow
+     //~^ ERROR constant evaluation error
+     //~| attempted to multiply with overflow
      );
 
 const VALS_U16: (u16, u16, u16, u16) =
     (-(u16::MIN as i16) as u16,
      u16::MIN - 1,
-     //~^ ERROR attempted to subtract with overflow
+     //~^ ERROR constant evaluation error
+     //~| attempted to subtract with overflow
      u16::MAX + 1,
-     //~^ ERROR attempted to add with overflow
+     //~^ ERROR constant evaluation error
+     //~| attempted to add with overflow
      u16::MAX * 2,
-     //~^ ERROR attempted to multiply with overflow
+     //~^ ERROR constant evaluation error
+     //~| attempted to multiply with overflow
      );
 
 const VALS_U32: (u32, u32, u32, u32) =
     (-(u32::MIN as i32) as u32,
      u32::MIN - 1,
-     //~^ ERROR attempted to subtract with overflow
+     //~^ ERROR constant evaluation error
+     //~| attempted to subtract with overflow
      u32::MAX + 1,
-     //~^ ERROR attempted to add with overflow
+     //~^ ERROR constant evaluation error
+     //~| attempted to add with overflow
      u32::MAX * 2,
-     //~^ ERROR attempted to multiply with overflow
+     //~^ ERROR constant evaluation error
+     //~| attempted to multiply with overflow
      );
 
 const VALS_U64: (u64, u64, u64, u64) =
     (-(u64::MIN as i64) as u64,
      u64::MIN - 1,
-     //~^ ERROR attempted to subtract with overflow
+     //~^ ERROR constant evaluation error
+     //~| attempted to subtract with overflow
      u64::MAX + 1,
-     //~^ ERROR attempted to add with overflow
+     //~^ ERROR constant evaluation error
+     //~| attempted to add with overflow
      u64::MAX * 2,
-     //~^ ERROR attempted to multiply with overflow
+     //~^ ERROR constant evaluation error
+     //~| attempted to multiply with overflow
      );
 
 fn main() {
index 9fdd24c42fdbd48447d526393e541ac19312c354..73351429b50608b770bb11571880aa364e46d666 100644 (file)
@@ -14,7 +14,8 @@
 struct S(i32);
 
 const CONSTANT: S = S(0);
-//~^ ERROR: unimplemented constant expression: tuple struct constructors [E0080]
+//~^ ERROR E0080
+//~| unimplemented constant expression: tuple struct constructors
 
 enum E {
     V = CONSTANT,
index 45a00de48e71210b697b9b820c00af3a973e8dc9..dd0f058f2c95c06909e2132d64902b6a1d5c7970 100644 (file)
@@ -17,10 +17,11 @@ const fn f(x: usize) -> usize {
     for i in 0..x {
         sum += i;
     }
-    sum //~ ERROR: E0250
+    sum //~ ERROR E0080
+        //~| non-constant path in constant
 }
 
 #[allow(unused_variables)]
 fn main() {
-    let a : [i32; f(X)];
+    let a : [i32; f(X)]; //~ NOTE for array length here
 }
index 09822e46cc1abddae32cc258e101ce57e5c27989..4f92770df289c50c57c43c58e163158ddea6fdc7 100644 (file)
@@ -9,7 +9,8 @@
 // except according to those terms.
 
 const ARR: [usize; 1] = [2];
-const ARR2: [i32; ARR[0]] = [5, 6]; //~ ERROR unstable
+const ARR2: [i32; ARR[0]] = [5, 6]; //~ ERROR E0080
+                                    //~| unstable
 
 fn main() {
 }
index 0d6cf3bab453fac0892aca6ff79efa9986f75507..5dadd892f83520cca532436ce88986e7b4649476 100644 (file)
@@ -8,30 +8,34 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-const X: usize = 42 && 39; //~ ERROR: can't do this op on integrals
+const X: usize = 42 && 39; //~ ERROR E0080
+                           //~| can't do this op on integrals
 const ARR: [i32; X] = [99; 34]; //~ NOTE: for array length here
 
-const X1: usize = 42 || 39; //~ ERROR: can't do this op on integrals
+const X1: usize = 42 || 39; //~ ERROR E0080
+                            //~| can't do this op on integrals
 const ARR1: [i32; X1] = [99; 47]; //~ NOTE: for array length here
 
-const X2: usize = -42 || -39; //~ ERROR: unary negation of unsigned integer
+const X2: usize = -42 || -39; //~ ERROR E0080
+                              //~| unary negation of unsigned integer
 const ARR2: [i32; X2] = [99; 18446744073709551607]; //~ NOTE: for array length here
 
-const X3: usize = -42 && -39; //~ ERROR: unary negation of unsigned integer
+const X3: usize = -42 && -39; //~ ERROR E0080
+                              //~| unary negation of unsigned integer
 const ARR3: [i32; X3] = [99; 6]; //~ NOTE: for array length here
 
 const Y: usize = 42.0 == 42.0;
-const ARRR: [i32; Y] = [99; 1]; //~ ERROR: expected usize value for array length
+const ARRR: [i32; Y] = [99; 1]; //~ ERROR: expected usize for array length
 const Y1: usize = 42.0 >= 42.0;
-const ARRR1: [i32; Y] = [99; 1]; //~ ERROR: expected usize value for array length
+const ARRR1: [i32; Y] = [99; 1]; //~ ERROR: expected usize for array length
 const Y2: usize = 42.0 <= 42.0;
-const ARRR2: [i32; Y] = [99; 1]; //~ ERROR: expected usize value for array length
+const ARRR2: [i32; Y] = [99; 1]; //~ ERROR: expected usize for array length
 const Y3: usize = 42.0 > 42.0;
-const ARRR3: [i32; Y] = [99; 0]; //~ ERROR: expected usize value for array length
+const ARRR3: [i32; Y] = [99; 0]; //~ ERROR: expected usize for array length
 const Y4: usize = 42.0 < 42.0;
-const ARRR4: [i32; Y] = [99; 0]; //~ ERROR: expected usize value for array length
+const ARRR4: [i32; Y] = [99; 0]; //~ ERROR: expected usize for array length
 const Y5: usize = 42.0 != 42.0;
-const ARRR5: [i32; Y] = [99; 0]; //~ ERROR: expected usize value for array length
+const ARRR5: [i32; Y] = [99; 0]; //~ ERROR: expected usize for array length
 
 fn main() {
     let _ = ARR;
index 9c6b774b99039811fb6482e80d2e98c649f5f6aa..43375ee3d18968e83645b150088189cdfef4a9ea 100644 (file)
@@ -15,7 +15,8 @@
 const ONE: usize = 1;
 const TWO: usize = 2;
 const LEN: usize = ONE - TWO;
-//~^ ERROR array length constant evaluation error: attempted to subtract with overflow [E0250]
+//~^ ERROR E0080
+//~| attempted to subtract with overflow
 
 fn main() {
     let a: [i8; LEN] = unimplemented!();
index d51f31087d0df1494c5cce1005433e6839109a92..e338f206553b422110dc9086c5190878b02f91c5 100644 (file)
@@ -16,5 +16,6 @@
 
 fn main() {
     let a: [i8; ONE - TWO] = unimplemented!();
-    //~^ ERROR array length constant evaluation error: attempted to subtract with overflow [E0250]
+    //~^ ERROR constant evaluation error [E0080]
+    //~| attempted to subtract with overflow
 }
index 4567cd4a74bb2a3ae343d9aea7679b1c8324e0fa..d68d63683a79cc6b2db9beddf7f4ad236bb39ae0 100644 (file)
@@ -17,22 +17,26 @@ enum Cake {
 use Cake::*;
 
 const BOO: (Cake, Cake) = (Marmor, BlackForest);
-//~^ ERROR: constant evaluation error: unimplemented constant expression: enum variants [E0471]
+//~^ ERROR: constant evaluation error [E0080]
+//~| unimplemented constant expression: enum variants
 const FOO: Cake = BOO.1;
 
 const fn foo() -> Cake {
-    Marmor //~ ERROR: constant evaluation error: unimplemented constant expression: enum variants
-    //~^ ERROR: unimplemented constant expression: enum variants
+    Marmor
+        //~^ ERROR: constant evaluation error [E0080]
+        //~| unimplemented constant expression: enum variants
+        //~^^^ ERROR: constant evaluation error [E0080]
+        //~| unimplemented constant expression: enum variants
 }
 
 const WORKS: Cake = Marmor;
 
-const GOO: Cake = foo();
+const GOO: Cake = foo(); //~ NOTE for expression here
 
 fn main() {
     match BlackForest {
-        FOO => println!("hi"), //~ NOTE: in pattern here
-        GOO => println!("meh"), //~ NOTE: in pattern here
+        FOO => println!("hi"), //~ NOTE: for pattern here
+        GOO => println!("meh"), //~ NOTE: for pattern here
         WORKS => println!("mรถp"),
         _ => println!("bye"),
     }
index d63b0097e5a0ce3fe0dc5ae0bdc7a66d2fefc212..b1b4bfe2d1c39a1e2a08a9e76117699d1e1d854c 100644 (file)
@@ -10,7 +10,8 @@
 
 const FOO: &'static[u32] = &[1, 2, 3];
 const BAR: u32 = FOO[5];
-//~^ ERROR index out of bounds: the len is 3 but the index is 5
+//~^ ERROR constant evaluation error [E0080]
+//~| index out of bounds: the len is 3 but the index is 5
 
 fn main() {
     let _ = BAR;
index 9d3c432d14878de269cf86ba9616dc7cc7c9d7af..6f095b3041ffedc833eef1b3ecc985f809ca60d9 100644 (file)
@@ -11,7 +11,8 @@
 // Test spans of errors
 
 const TUP: (usize,) = 5 << 64;
-//~^ ERROR: attempted to shift left with overflow [E0250]
+//~^ ERROR E0080
+//~| attempted to shift left with overflow
 const ARR: [i32; TUP.0] = [];
 
 fn main() {
index 23106c99594a6f69e7f2c0ba3734453145a1df19..c73b7e831b3217051eb1eef9b64372af92abda81 100644 (file)
@@ -25,7 +25,8 @@ enum A {
         Ok = i8::MAX - 1,
         Ok2,
         OhNo = 0_u8,
-        //~^ ERROR mismatched types
+        //~^ ERROR E0080
+        //~| expected i8, found u8
     }
 
     let x = A::Ok;
@@ -37,7 +38,8 @@ enum A {
         Ok = u8::MAX - 1,
         Ok2,
         OhNo = 0_i8,
-        //~^  ERROR mismatched types
+        //~^ ERROR E0080
+        //~| expected u8, found i8
     }
 
     let x = A::Ok;
@@ -49,7 +51,8 @@ enum A {
         Ok = i16::MAX - 1,
         Ok2,
         OhNo = 0_u16,
-        //~^ ERROR mismatched types
+        //~^ ERROR E0080
+        //~| expected i16, found u16
     }
 
     let x = A::Ok;
@@ -61,7 +64,8 @@ enum A {
         Ok = u16::MAX - 1,
         Ok2,
         OhNo = 0_i16,
-        //~^ ERROR mismatched types
+        //~^ ERROR E0080
+        //~| expected u16, found i16
     }
 
     let x = A::Ok;
@@ -73,7 +77,8 @@ enum A {
         Ok = i32::MAX - 1,
         Ok2,
         OhNo = 0_u32,
-        //~^ ERROR mismatched types
+        //~^ ERROR E0080
+        //~| expected i32, found u32
     }
 
     let x = A::Ok;
@@ -85,7 +90,8 @@ enum A {
         Ok = u32::MAX - 1,
         Ok2,
         OhNo = 0_i32,
-        //~^ ERROR mismatched types
+        //~^ ERROR E0080
+        //~| expected u32, found i32
     }
 
     let x = A::Ok;
@@ -97,7 +103,8 @@ enum A {
         Ok = i64::MAX - 1,
         Ok2,
         OhNo = 0_u64,
-        //~^ ERROR mismatched types
+        //~^ ERROR E0080
+        //~| expected i64, found u64
     }
 
     let x = A::Ok;
@@ -109,7 +116,8 @@ enum A {
         Ok = u64::MAX - 1,
         Ok2,
         OhNo = 0_i64,
-        //~^ ERROR mismatched types
+        //~^ ERROR E0080
+        //~| expected u64, found i64
     }
 
     let x = A::Ok;
index d6ba09bb4c5bf072692b9677f3f4883dc99e4951..bbdb3891d99807dbd989d231ddbcdfbb3805993c 100644 (file)
 enum Eu8 {
     Au8 = 23,
     Bu8 = 223,
-    Cu8 = -23, //~ ERROR unary negation of unsigned integer
+    Cu8 = -23, //~ ERROR E0080
+               //~| unary negation of unsigned integer
 }
 
 #[repr(u16)]
 enum Eu16 {
     Au16 = 23,
     Bu16 = 55555,
-    Cu16 = -22333, //~ ERROR unary negation of unsigned integer
+    Cu16 = -22333, //~ ERROR E0080
+                   //~| unary negation of unsigned integer
 }
 
 #[repr(u32)]
 enum Eu32 {
     Au32 = 23,
     Bu32 = 3_000_000_000,
-    Cu32 = -2_000_000_000, //~ ERROR unary negation of unsigned integer
+    Cu32 = -2_000_000_000, //~ ERROR E0080
+                           //~| unary negation of unsigned integer
 }
 
 #[repr(u64)]
 enum Eu64 {
     Au32 = 23,
     Bu32 = 3_000_000_000,
-    Cu32 = -2_000_000_000, //~ ERROR unary negation of unsigned integer
+    Cu32 = -2_000_000_000, //~ ERROR E0080
+                           //~| unary negation of unsigned integer
 }
 
 // u64 currently allows negative numbers, and i64 allows numbers greater than `1<<63`.  This is a
index 7ca274b81e574a5c6cf6962b926ddfb3ceff5b05..57db583aefe2355cb46bde8df1027c98637b18e7 100644 (file)
@@ -9,9 +9,11 @@
 // except according to those terms.
 
 enum test {
-    div_zero = 1/0, //~ERROR constant evaluation error: attempted to divide by zero
+    div_zero = 1/0, //~ ERROR E0080
+                    //~| attempted to divide by zero
     rem_zero = 1%0,
-//~^ ERROR constant evaluation error: attempted to calculate the remainder with a divisor of zero
+    //~^ ERROR E0080
+    //~| attempted to calculate the remainder with a divisor of zero
 }
 
 fn main() {}
index b5432fafb1b855f0b09cb6a1a2634b847673acc8..f8aa1ea95f0f66d51039d8bb09d1c11502bf1ec2 100644 (file)
@@ -14,15 +14,17 @@ struct Foo<'a,'b> {
 }
 
 impl<'a,'b> Foo<'a,'b> {
-    fn bar(self: Foo<'b,'a>) {}
-    //~^ ERROR mismatched types
+    fn bar(
+        self
+    //~^ ERROR mismatched method receiver
     //~| expected type `Foo<'a, 'b>`
     //~| found type `Foo<'b, 'a>`
     //~| lifetime mismatch
-    //~| ERROR mismatched types
+    //~| ERROR mismatched method receiver
     //~| expected type `Foo<'a, 'b>`
     //~| found type `Foo<'b, 'a>`
     //~| lifetime mismatch
+            : Foo<'b,'a>) {}
 }
 
 fn main() {}
index 05b194345d40534692d57eaa4072262d765c46e7..89ae1a09bd3e47b2eca8b28e006031c79d1b5f72 100644 (file)
@@ -18,14 +18,17 @@ fn neg(self) -> u32 { 0 }
 
 fn main() {
     let a = -1;
-    //~^ ERROR unary negation of unsigned integer
+    //~^ ERROR E0080
+    //~| unary negation of unsigned integer
     let _b : u8 = a; // for infering variable a to u8.
 
     let _d = -1u8;
-    //~^ ERROR unary negation of unsigned integer
+    //~^ ERROR E0080
+    //~| unary negation of unsigned integer
 
     for _ in -10..10u8 {}
-    //~^ ERROR unary negation of unsigned integer
+    //~^ ERROR E0080
+    //~| unary negation of unsigned integer
 
     -S; // should not trigger the gate; issue 26840
 }
index 3c4ad5a56ec362ba221e64cf879cd5ea3acf2616..9a9358b787f5386cbebd0231958212dc4c61fc4d 100644 (file)
@@ -10,5 +10,6 @@
 
 fn main() {
     fn f(a: [u8; u32::DOESNOTEXIST]) {}
-    //~^ ERROR unresolved path in constant expression
+    //~^ ERROR constant evaluation error
+    //~| unresolved path in constant expression
 }
index 43cf70e5bc3cf086cefb00fcac577b41ec5ac266..3d9d81471cb1e40da806c9348464d193ff9cfa98 100644 (file)
@@ -16,7 +16,9 @@ trait Foo {
 
 impl Foo for Baz {
     fn bar(&mut self, other: &Foo) {}
-    //~^ ERROR method `bar` has an incompatible type for trait: values differ in mutability [E0053]
+    //~^ ERROR method `bar` has an incompatible type for trait
+    //~| expected type `fn(&mut Baz, &mut Foo)`
+    //~| found type `fn(&mut Baz, &Foo)`
 }
 
 fn main() {}
index 42e3456b309be35585a6ed39181eaebbb63aa745..da48bbb3ecd711a99a730cf859ec74f17bc9cc06 100644 (file)
@@ -20,8 +20,8 @@ impl<T: fmt::Debug> ops::FnOnce<(),> for Debuger<T> {
     type Output = ();
     fn call_once(self, _args: ()) {
     //~^ ERROR `call_once` has an incompatible type for trait
-    //~| expected "rust-call" fn,
-    //~| found "Rust" fn
+    //~| expected type `extern "rust-call" fn
+    //~| found type `fn
         println!("{:?}", self.x);
     }
 }
index 6b9294b2038f18fff4070765df96e8d574a31605..664d62e87ae61cf2f61a5f45d308275ce6f60856 100644 (file)
@@ -14,11 +14,11 @@ struct Foo<'a> {
 
 impl <'a> Foo<'a>{
     fn bar(self: &mut Foo) {
-    //~^ mismatched types
+    //~^ mismatched method receiver
     //~| expected type `&mut Foo<'a>`
     //~| found type `&mut Foo<'_>`
     //~| lifetime mismatch
-    //~| mismatched types
+    //~| mismatched method receiver
     //~| expected type `&mut Foo<'a>`
     //~| found type `&mut Foo<'_>`
     //~| lifetime mismatch
index b36918149fa99008b7fd5d7560a63ad82081b759..db3334834d44ec97e5230755df303f1f2e0b4a65 100644 (file)
@@ -14,8 +14,7 @@ impl Iterator for S {
     type Item = i32;
     fn next(&mut self) -> Result<i32, i32> { Ok(7) }
     //~^ ERROR method `next` has an incompatible type for trait
-    //~| expected enum `std::option::Option`
-    //~|    found enum `std::result::Result` [E0053]
+    //~| expected enum `std::option::Option`, found enum `std::result::Result`
 }
 
 fn main() {}
index 7d619c270d32b962913e7999a206a1c0fa38762a..54a24089354614f05c4e90e04e1e3bdce16fba17 100644 (file)
@@ -12,10 +12,12 @@ enum Delicious {
     Pie      = 0x1,
     Apple    = 0x2,
     ApplePie = Delicious::Apple as isize | Delicious::PIE as isize,
-    //~^ ERROR constant evaluation error: unresolved path in constant expression
+    //~^ ERROR constant evaluation error
+    //~| unresolved path in constant expression
 }
 
 const FOO: [u32; u8::MIN as usize] = [];
-//~^ ERROR array length constant evaluation error: unresolved path in constant expression
+//~^ ERROR constant evaluation error
+//~| unresolved path in constant expression
 
 fn main() {}
index 32cdd6b5ed9f20a5dc1e1d3ab74c915166331fd8..c2bcbb9d54a9a447c1f5c0bf873d8a8542226f4a 100644 (file)
@@ -10,7 +10,8 @@
 
 pub enum SomeEnum {
     B = SomeEnum::A,
-    //~^ ERROR constant evaluation error: unresolved path in constant expression
+    //~^ ERROR constant evaluation error
+    //~| unresolved path in constant expression
 }
 
 fn main() {}
index 27d46be40fbeb69bbe96b617eff5dce36c28d484..ede81bea32ae3bfaea3db5168a4ea23f2ed19a1d 100644 (file)
@@ -30,9 +30,6 @@ fn deref(&self) -> &i8 { &self.0 }
         impl Deref for Thing {
             //~^ ERROR not all trait items implemented, missing: `Target` [E0046]
             fn deref(&self) -> i8 { self.0 }
-            //~^ ERROR method `deref` has an incompatible type for trait
-            //~| expected &-ptr
-            //~| found i8 [E0053]
         }
 
         let thing = Thing(72);
index e8a9c8d2ea34bc06e6c6225e84419b2e2a9777ff..93f75e9bfed0dddc09f23fbcede1fcad238e351a 100644 (file)
@@ -17,6 +17,7 @@ impl S {
 }
 
 static STUFF: [u8; S::N] = [0; S::N];
-//~^ ERROR array length constant evaluation error: unresolved path in constant expression
+//~^ ERROR constant evaluation error
+//~| unresolved path in constant expression
 
 fn main() {}
index bdcbaf09177fe8c2e53c0aeb82262de6890e0a98..ee6ec52761266607887eef14302a41e2102c6278 100644 (file)
@@ -16,5 +16,5 @@ fn main() {
     //~| expected type `usize`
     //~| found type `S`
     //~| expected usize, found struct `S`
-    //~| ERROR expected positive integer for repeat count, found struct
+    //~| ERROR expected usize for repeat count, found struct
 }
index 3b3abc94a4900f391d2746a17dab1e1d74398bac..ca8d5a1f70473563b3badf884ffd97d5ae67111a 100644 (file)
@@ -14,7 +14,8 @@ fn main() {
 
     match i {
         0...index => println!("winner"),
-        //~^ ERROR non-constant path in constant expression
+        //~^ ERROR constant evaluation error
+        //~| non-constant path in constant expression
         _ => println!("hello"),
     }
 }
index c8a1e424da2e2c71a2f0e09d3acdc5583b39948a..1dfd146985ff48a8df17ee421986e27306637c67 100644 (file)
@@ -11,6 +11,6 @@
 // Regression test for issue #28586
 
 pub trait Foo {}
-impl Foo for [u8; usize::BYTES] {} //~ ERROR E0250
+impl Foo for [u8; usize::BYTES] {} //~ ERROR E0080
 
 fn main() { }
diff --git a/src/test/compile-fail/issue-31173.rs b/src/test/compile-fail/issue-31173.rs
new file mode 100644 (file)
index 0000000..fb1e3cc
--- /dev/null
@@ -0,0 +1,27 @@
+// Copyright 2016 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::vec::IntoIter;
+
+pub fn get_tok(it: &mut IntoIter<u8>) {
+    let mut found_e = false;
+
+    let temp: Vec<u8> = it.take_while(|&x| {
+        found_e = true;
+        false
+    })
+        .cloned()
+        //~^ ERROR type mismatch resolving
+        //~| expected type `u8`
+        //~| found type `&_`
+        .collect(); //~ ERROR no method named `collect`
+}
+
+fn main() {}
index 52375ef281ace24513c5f70d46257acd5512d401..1b6e4b1d289e42d31c25c39983f188e578c87c18 100644 (file)
@@ -15,7 +15,8 @@ fn main() {
     enum Stuff {
         Bar = foo
         //~^ ERROR attempt to use a non-constant value in a constant
-        //~^^ ERROR constant evaluation error: non-constant path in constant expression
+        //~^^ ERROR constant evaluation error
+        //~| non-constant path in constant expression
     }
 
     println!("{}", Stuff::Bar);
index 1c98abce0304e149f092ea7e0a4137c0cac303d5..91a07dd9ba6dd68ede4d5bf9129a180f1d579d89 100644 (file)
 
 enum Foo {
     A = 1i64,
-    //~^ ERROR mismatched types:
-    //~| expected `isize`,
-    //~| found `i64` [E0080]
+    //~^ ERROR constant evaluation error
+    //~| expected isize, found i64
     B = 2u8
-    //~^ ERROR mismatched types:
-    //~| expected `isize`,
-    //~| found `u8` [E0080]
+    //~^ ERROR constant evaluation error
+    //~| expected isize, found u8
 }
 
 fn main() {}
index e34a3c4569d0a4c451d053ff13837bd0e9c7abad..6da87fca3f35606fe3398f127a626adc751dd763 100644 (file)
@@ -49,7 +49,8 @@ struct Baz<'x> {
 
 impl<'a> Baz<'a> {
     fn baz2<'b>(&self, x: &isize) -> (&'b isize, &'b isize) {
-        //~^ HELP consider using an explicit lifetime parameter as shown: fn baz2<'b>(&self, x: &'a isize) -> (&'a isize, &'a isize)
+        //~^ HELP consider using an explicit lifetime parameter as shown: fn baz2<'b>(&self, x: &'
+        // FIXME #35038: The above suggestion is different on Linux and Mac.
         (self.bar, x) //~ ERROR E0312
         //~^ ERROR E0312
     }
index 526aa83dec7fd2410b4539818b2265c5cbf91256..2c4c2563021867ddbd6c305f1500b60c6971a5e4 100644 (file)
@@ -27,6 +27,7 @@ fn main() {
         'c' ... 100 => { }
         _ => { }
     };
-    //~^^^ ERROR mismatched types in range
-    //~| expected char, found integral variable
+    //~^^^ ERROR mismatched types
+    //~| expected type `_`
+    //~| found type `char`
 }
index 9564a080b8ee7d6ca7f8c8dbb04d125921408ba9..cadfec5a38d3d9fbdc27d1569013b31482708da2 100644 (file)
@@ -15,5 +15,6 @@ enum State { ST_NULL, ST_WHITESPACE }
 
 fn main() {
     [State::ST_NULL; (State::ST_WHITESPACE as usize)];
-    //~^ ERROR expected constant integer for repeat count, but unimplemented constant expression
+    //~^ ERROR constant evaluation error
+    //~| unimplemented constant expression: enum variants
 }
index 3ce206ff7fb2c0c13b1a5a7b1079aa2e65e9a16d..a6f88a57b9125846a8f5ba8b52a91b18f7157736 100644 (file)
@@ -13,6 +13,8 @@
 fn main() {
     fn bar(n: usize) {
         let _x = [0; n];
-        //~^ ERROR expected constant integer for repeat count, found variable
+        //~^ ERROR constant evaluation error
+        //~| non-constant path in constant expression
+        //~| NOTE `n` is a variable
     }
 }
index ee88168515d39f5a7319f21a7527177c3584e985..737f80372debf55c8e99bba7cd5970b199dea579 100644 (file)
@@ -12,6 +12,7 @@ fn main() {
     let x = 0;
     match 1 {
         0 ... x => {}
-        //~^ ERROR non-constant path in constant expression
+        //~^ ERROR constant evaluation error
+        //~| non-constant path in constant expression
     };
 }
index ab5af64d95c1352d215b1757f29227c17360e458..3a7e9cc4191ec2af4de80bacf0579705aefe9bd8 100644 (file)
 fn main() {
     let n = 1;
     let a = [0; n];
-    //~^ ERROR expected constant integer for repeat count, found variable [E0307]
+    //~^ ERROR constant evaluation error
+    //~| non-constant path in constant expression
     let b = [0; ()];
     //~^ ERROR mismatched types
     //~| expected type `usize`
     //~| found type `()`
     //~| expected usize, found ()
-    //~| ERROR expected positive integer for repeat count, found tuple [E0306]
+    //~| ERROR expected usize for repeat count, found tuple [E0306]
     let c = [0; true];
     //~^ ERROR mismatched types
     //~| expected usize, found bool
-    //~| ERROR expected positive integer for repeat count, found boolean [E0306]
+    //~| ERROR expected usize for repeat count, found boolean [E0306]
     let d = [0; 0.5];
     //~^ ERROR mismatched types
     //~| expected type `usize`
     //~| found type `_`
     //~| expected usize, found floating-point variable
-    //~| ERROR expected positive integer for repeat count, found float [E0306]
+    //~| ERROR expected usize for repeat count, found float [E0306]
     let e = [0; "foo"];
     //~^ ERROR mismatched types
     //~| expected type `usize`
     //~| found type `&'static str`
     //~| expected usize, found &-ptr
-    //~| ERROR expected positive integer for repeat count, found string literal [E0306]
+    //~| ERROR expected usize for repeat count, found string literal [E0306]
     let f = [0; -4_isize];
-    //~^ ERROR mismatched types
-    //~| expected `usize`
-    //~| found `isize`
-    //~| ERROR mismatched types:
+    //~^ ERROR constant evaluation error
+    //~| expected usize, found isize
+    //~| ERROR mismatched types
     //~| expected usize, found isize
     let f = [0_usize; -1_isize];
-    //~^ ERROR mismatched types
-    //~| expected `usize`
-    //~| found `isize`
+    //~^ ERROR constant evaluation error
+    //~| expected usize, found isize
     //~| ERROR mismatched types
     //~| expected usize, found isize
     struct G {
@@ -56,5 +55,5 @@ struct G {
     //~| expected type `usize`
     //~| found type `main::G`
     //~| expected usize, found struct `main::G`
-    //~| ERROR expected positive integer for repeat count, found struct [E0306]
+    //~| ERROR expected usize for repeat count, found struct [E0306]
 }
index f86d9b7648bbebfd19a2f9740fffdb0ad394c106..a05e007d6b7393e5774e44d76904c35b39fb3243 100644 (file)
@@ -17,8 +17,8 @@ impl Mumbo for usize {
     // Cannot have a larger effect than the trait:
     unsafe fn jumbo(&self, x: &usize) { *self + *x; }
     //~^ ERROR method `jumbo` has an incompatible type for trait
-    //~| expected normal fn,
-    //~| found unsafe fn
+    //~| expected type `fn
+    //~| found type `unsafe fn
 }
 
 fn main() {}
index f14a3505cdeb486510da18e7f6dd72d2184f8d58..a98b7cd43090f3768723cdc4fdb175eb4a91d410 100644 (file)
@@ -41,14 +41,14 @@ trait SomeTrait {
 
 impl<'a, T> SomeTrait for &'a Bar<T> {
     fn dummy1(self: &&'a Bar<T>) { }
-    fn dummy2(self: &Bar<T>) {} //~ ERROR mismatched types
-    //~^ ERROR mismatched types
+    fn dummy2(self: &Bar<T>) {} //~ ERROR mismatched method receiver
+    //~^ ERROR mismatched method receiver
     fn dummy3(self: &&Bar<T>) {}
-    //~^ ERROR mismatched types
+    //~^ ERROR mismatched method receiver
     //~| expected type `&&'a Bar<T>`
     //~| found type `&&Bar<T>`
     //~| lifetime mismatch
-    //~| ERROR mismatched types
+    //~| ERROR mismatched method receiver
     //~| expected type `&&'a Bar<T>`
     //~| found type `&&Bar<T>`
     //~| lifetime mismatch
index 51f876661f6510834a4dfd78ea2ea39a770b5440..fb4652affd0d8c3ce6c8ce7f7023b57f447c3137 100644 (file)
@@ -17,8 +17,8 @@ trait Foo {
 impl Foo for u32 {
     fn len(&self) -> u32 { *self }
     //~^ ERROR method `len` has an incompatible type for trait
-    //~| expected unsafe fn,
-    //~| found normal fn
+    //~| expected type `unsafe fn(&u32) -> u32`
+    //~| found type `fn(&u32) -> u32`
 }
 
 fn main() { }
diff --git a/src/test/debuginfo/function-prologue-stepping-no-stack-check.rs b/src/test/debuginfo/function-prologue-stepping-no-stack-check.rs
deleted file mode 100644 (file)
index b5b6ca7..0000000
+++ /dev/null
@@ -1,369 +0,0 @@
-// 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
-
-// This test case checks if function arguments already have the correct value
-// when breaking at the beginning of a function. Functions with the
-// #[no_stack_check] attribute have the same prologue as regular C functions
-// compiled with GCC or Clang and therefore are better handled by GDB. As a
-// consequence, and as opposed to regular Rust functions, we can set the
-// breakpoints via the function name (and don't have to fall back on using line
-// numbers). For LLDB this shouldn't make a difference because it can handle
-// both cases.
-
-// compile-flags:-g
-
-// === GDB TESTS ===================================================================================
-
-// gdb-command:rbreak immediate_args
-// gdb-command:rbreak binding
-// gdb-command:rbreak assignment
-// gdb-command:rbreak function_call
-// gdb-command:rbreak identifier
-// gdb-command:rbreak return_expr
-// gdb-command:rbreak arithmetic_expr
-// gdb-command:rbreak if_expr
-// gdb-command:rbreak while_expr
-// gdb-command:rbreak loop_expr
-// gdb-command:run
-
-// IMMEDIATE ARGS
-// gdb-command:print a
-// gdb-check:$1 = 1
-// gdb-command:print b
-// gdb-check:$2 = true
-// gdb-command:print c
-// gdb-check:$3 = 2.5
-// gdb-command:continue
-
-// NON IMMEDIATE ARGS
-// gdb-command:print a
-// gdb-check:$4 = {a = 3, b = 4, c = 5, d = 6, e = 7, f = 8, g = 9, h = 10}
-// gdb-command:print b
-// gdb-check:$5 = {a = 11, b = 12, c = 13, d = 14, e = 15, f = 16, g = 17, h = 18}
-// gdb-command:continue
-
-// BINDING
-// gdb-command:print a
-// gdb-check:$6 = 19
-// gdb-command:print b
-// gdb-check:$7 = 20
-// gdb-command:print c
-// gdb-check:$8 = 21.5
-// gdb-command:continue
-
-// ASSIGNMENT
-// gdb-command:print a
-// gdb-check:$9 = 22
-// gdb-command:print b
-// gdb-check:$10 = 23
-// gdb-command:print c
-// gdb-check:$11 = 24.5
-// gdb-command:continue
-
-// FUNCTION CALL
-// gdb-command:print x
-// gdb-check:$12 = 25
-// gdb-command:print y
-// gdb-check:$13 = 26
-// gdb-command:print z
-// gdb-check:$14 = 27.5
-// gdb-command:continue
-
-// EXPR
-// gdb-command:print x
-// gdb-check:$15 = 28
-// gdb-command:print y
-// gdb-check:$16 = 29
-// gdb-command:print z
-// gdb-check:$17 = 30.5
-// gdb-command:continue
-
-// RETURN EXPR
-// gdb-command:print x
-// gdb-check:$18 = 31
-// gdb-command:print y
-// gdb-check:$19 = 32
-// gdb-command:print z
-// gdb-check:$20 = 33.5
-// gdb-command:continue
-
-// ARITHMETIC EXPR
-// gdb-command:print x
-// gdb-check:$21 = 34
-// gdb-command:print y
-// gdb-check:$22 = 35
-// gdb-command:print z
-// gdb-check:$23 = 36.5
-// gdb-command:continue
-
-// IF EXPR
-// gdb-command:print x
-// gdb-check:$24 = 37
-// gdb-command:print y
-// gdb-check:$25 = 38
-// gdb-command:print z
-// gdb-check:$26 = 39.5
-// gdb-command:continue
-
-// WHILE EXPR
-// gdb-command:print x
-// gdb-check:$27 = 40
-// gdb-command:print y
-// gdb-check:$28 = 41
-// gdb-command:print z
-// gdb-check:$29 = 42
-// gdb-command:continue
-
-// LOOP EXPR
-// gdb-command:print x
-// gdb-check:$30 = 43
-// gdb-command:print y
-// gdb-check:$31 = 44
-// gdb-command:print z
-// gdb-check:$32 = 45
-// gdb-command:continue
-
-
-// === LLDB TESTS ==================================================================================
-
-// lldb-command:breakpoint set --name immediate_args
-// lldb-command:breakpoint set --name non_immediate_args
-// lldb-command:breakpoint set --name binding
-// lldb-command:breakpoint set --name assignment
-// lldb-command:breakpoint set --name function_call
-// lldb-command:breakpoint set --name identifier
-// lldb-command:breakpoint set --name return_expr
-// lldb-command:breakpoint set --name arithmetic_expr
-// lldb-command:breakpoint set --name if_expr
-// lldb-command:breakpoint set --name while_expr
-// lldb-command:breakpoint set --name loop_expr
-// lldb-command:run
-
-// IMMEDIATE ARGS
-// lldb-command:print a
-// lldb-check:[...]$0 = 1
-// lldb-command:print b
-// lldb-check:[...]$1 = true
-// lldb-command:print c
-// lldb-check:[...]$2 = 2.5
-// lldb-command:continue
-
-// NON IMMEDIATE ARGS
-// lldb-command:print a
-// lldb-check:[...]$3 = BigStruct { a: 3, b: 4, c: 5, d: 6, e: 7, f: 8, g: 9, h: 10 }
-// lldb-command:print b
-// lldb-check:[...]$4 = BigStruct { a: 11, b: 12, c: 13, d: 14, e: 15, f: 16, g: 17, h: 18 }
-// lldb-command:continue
-
-// BINDING
-// lldb-command:print a
-// lldb-check:[...]$5 = 19
-// lldb-command:print b
-// lldb-check:[...]$6 = 20
-// lldb-command:print c
-// lldb-check:[...]$7 = 21.5
-// lldb-command:continue
-
-// ASSIGNMENT
-// lldb-command:print a
-// lldb-check:[...]$8 = 22
-// lldb-command:print b
-// lldb-check:[...]$9 = 23
-// lldb-command:print c
-// lldb-check:[...]$10 = 24.5
-// lldb-command:continue
-
-// FUNCTION CALL
-// lldb-command:print x
-// lldb-check:[...]$11 = 25
-// lldb-command:print y
-// lldb-check:[...]$12 = 26
-// lldb-command:print z
-// lldb-check:[...]$13 = 27.5
-// lldb-command:continue
-
-// EXPR
-// lldb-command:print x
-// lldb-check:[...]$14 = 28
-// lldb-command:print y
-// lldb-check:[...]$15 = 29
-// lldb-command:print z
-// lldb-check:[...]$16 = 30.5
-// lldb-command:continue
-
-// RETURN EXPR
-// lldb-command:print x
-// lldb-check:[...]$17 = 31
-// lldb-command:print y
-// lldb-check:[...]$18 = 32
-// lldb-command:print z
-// lldb-check:[...]$19 = 33.5
-// lldb-command:continue
-
-// ARITHMETIC EXPR
-// lldb-command:print x
-// lldb-check:[...]$20 = 34
-// lldb-command:print y
-// lldb-check:[...]$21 = 35
-// lldb-command:print z
-// lldb-check:[...]$22 = 36.5
-// lldb-command:continue
-
-// IF EXPR
-// lldb-command:print x
-// lldb-check:[...]$23 = 37
-// lldb-command:print y
-// lldb-check:[...]$24 = 38
-// lldb-command:print z
-// lldb-check:[...]$25 = 39.5
-// lldb-command:continue
-
-// WHILE EXPR
-// lldb-command:print x
-// lldb-check:[...]$26 = 40
-// lldb-command:print y
-// lldb-check:[...]$27 = 41
-// lldb-command:print z
-// lldb-check:[...]$28 = 42
-// lldb-command:continue
-
-// LOOP EXPR
-// lldb-command:print x
-// lldb-check:[...]$29 = 43
-// lldb-command:print y
-// lldb-check:[...]$30 = 44
-// lldb-command:print z
-// lldb-check:[...]$31 = 45
-// lldb-command:continue
-
-#![allow(dead_code, unused_assignments, unused_variables)]
-#![feature(omit_gdb_pretty_printer_section)]
-#![omit_gdb_pretty_printer_section]
-
-#[no_stack_check]
-fn immediate_args(a: isize, b: bool, c: f64) {
-    println!("");
-}
-
-struct BigStruct {
-    a: u64,
-    b: u64,
-    c: u64,
-    d: u64,
-    e: u64,
-    f: u64,
-    g: u64,
-    h: u64
-}
-
-#[no_stack_check]
-fn non_immediate_args(a: BigStruct, b: BigStruct) {
-    println!("");
-}
-
-#[no_stack_check]
-fn binding(a: i64, b: u64, c: f64) {
-    let x = 0;
-    println!("");
-}
-
-#[no_stack_check]
-fn assignment(mut a: u64, b: u64, c: f64) {
-    a = b;
-    println!("");
-}
-
-#[no_stack_check]
-fn function_call(x: u64, y: u64, z: f64) {
-    println!("Hi!")
-}
-
-#[no_stack_check]
-fn identifier(x: u64, y: u64, z: f64) -> u64 {
-    x
-}
-
-#[no_stack_check]
-fn return_expr(x: u64, y: u64, z: f64) -> u64 {
-    return x;
-}
-
-#[no_stack_check]
-fn arithmetic_expr(x: u64, y: u64, z: f64) -> u64 {
-    x + y
-}
-
-#[no_stack_check]
-fn if_expr(x: u64, y: u64, z: f64) -> u64 {
-    if x + y < 1000 {
-        x
-    } else {
-        y
-    }
-}
-
-#[no_stack_check]
-fn while_expr(mut x: u64, y: u64, z: u64) -> u64 {
-    while x + y < 1000 {
-        x += z
-    }
-    return x;
-}
-
-#[no_stack_check]
-fn loop_expr(mut x: u64, y: u64, z: u64) -> u64 {
-    loop {
-        x += z;
-
-        if x + y > 1000 {
-            return x;
-        }
-    }
-}
-
-fn main() {
-    immediate_args(1, true, 2.5);
-
-    non_immediate_args(
-        BigStruct {
-            a: 3,
-            b: 4,
-            c: 5,
-            d: 6,
-            e: 7,
-            f: 8,
-            g: 9,
-            h: 10
-        },
-        BigStruct {
-            a: 11,
-            b: 12,
-            c: 13,
-            d: 14,
-            e: 15,
-            f: 16,
-            g: 17,
-            h: 18
-        }
-    );
-
-    binding(19, 20, 21.5);
-    assignment(22, 23, 24.5);
-    function_call(25, 26, 27.5);
-    identifier(28, 29, 30.5);
-    return_expr(31, 32, 33.5);
-    arithmetic_expr(34, 35, 36.5);
-    if_expr(37, 38, 39.5);
-    while_expr(40, 41, 42);
-    loop_expr(43, 44, 45);
-}
index a74369ed3c3a13b7a779c7099185c29f1a7b7bbd..2419625cbd3748f8e3f690e39c38072b61e5a5e7 100644 (file)
@@ -11,6 +11,8 @@
 // ignore-tidy-linelength
 // ignore-lldb
 // ignore-android: FIXME(#24958)
+// ignore-arm: FIXME(#24958)
+// ignore-aarch64: FIXME(#24958)
 
 // compile-flags:-g
 
diff --git a/src/test/mir-opt/README.md b/src/test/mir-opt/README.md
new file mode 100644 (file)
index 0000000..9144e97
--- /dev/null
@@ -0,0 +1,44 @@
+This folder contains tests for MIR optimizations.
+
+The test format is:
+
+```
+(arbitrary rust code)
+// END RUST SOURCE
+// START $file_name_of_some_mir_dump_0
+//  $expected_line_0
+// ...
+// $expected_line_N
+// END $file_name_of_some_mir_dump_0
+// ...
+// START $file_name_of_some_mir_dump_N
+//  $expected_line_0
+// ...
+// $expected_line_N
+// END $file_name_of_some_mir_dump_N
+```
+
+All the test information is in comments so the test is runnable.
+
+For each $file_name, compiletest expects [$expected_line_0, ...,
+$expected_line_N] to appear in the dumped MIR in order.  Currently it allows
+other non-matched lines before, after and in-between.  
+
+Lines match ignoring whitespace, and the prefix "//" is removed.
+
+It also currently strips trailing comments -- partly because the full file path
+in "scope comments" is unpredictable and partly because tidy complains about
+the lines being too long.
+
+compiletest handles dumping the MIR before and after every pass for you.  The
+test writer only has to specify the file names of the dumped files (not the
+full path to the file) and what lines to expect.  I added an option to rustc
+that tells it to dump the mir into some directly (rather then always dumping to
+the current directory).  
+
+Lines match ignoring whitespace, and the prefix "//" is removed of course.
+
+It also currently strips trailing comments -- partly because the full file path
+in "scope comments" is unpredictable and partly because tidy complains about
+the lines being too long.
+
diff --git a/src/test/mir-opt/return_an_array.rs b/src/test/mir-opt/return_an_array.rs
new file mode 100644 (file)
index 0000000..4409f16
--- /dev/null
@@ -0,0 +1,18 @@
+// Copyright 2012-2016 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.
+
+// this tests move up progration, which is not yet implemented
+
+fn foo() -> [u8; 1024] {
+        let x = [0; 1024];
+        return x;
+}
+
+fn main() { }
\ No newline at end of file
diff --git a/src/test/mir-opt/simplify_if.rs b/src/test/mir-opt/simplify_if.rs
new file mode 100644 (file)
index 0000000..dd6a857
--- /dev/null
@@ -0,0 +1,27 @@
+// Copyright 2012-2016 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.
+
+fn main() {
+    if false {
+        println!("hello world!");
+    }
+}
+
+// END RUST SOURCE
+// START rustc.node4.SimplifyBranches.initial-before.mir
+// bb0: {
+//     if(const false) -> [true: bb1, false: bb2]; // scope 0 at simplify_if.rs:12:5: 14:6
+// }
+// END rustc.node4.SimplifyBranches.initial-before.mir
+// START rustc.node4.SimplifyBranches.initial-after.mir
+// bb0: {
+//     goto -> bb2;                     // scope 0 at simplify_if.rs:12:5: 14:6
+// }
+// END rustc.node4.SimplifyBranches.initial-after.mir
\ No newline at end of file
diff --git a/src/test/run-make/issue-33329/Makefile b/src/test/run-make/issue-33329/Makefile
new file mode 100644 (file)
index 0000000..c53f51d
--- /dev/null
@@ -0,0 +1,5 @@
+-include ../tools.mk
+
+all:
+       $(RUSTC) --target x86_64_unknown-linux-musl main.rs 2>&1 | \
+               grep "error: Error loading target specification: Could not find specification for target"
diff --git a/src/test/run-make/issue-33329/main.rs b/src/test/run-make/issue-33329/main.rs
new file mode 100644 (file)
index 0000000..e06c0a5
--- /dev/null
@@ -0,0 +1,11 @@
+// Copyright 2016 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.
+
+fn main() {}
index 2f265b9112b9809be21c450095f950cead56a0bc..7297c71a6d668b7aa2844d4f9714858166f53cd3 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright 2013 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
 // file at the top-level directory of this distribution and at
 // http://rust-lang.org/COPYRIGHT.
 //
@@ -12,4 +12,7 @@
 
 pub fn main() {
     let _ = b"x" as &[u8];
+    let _ = b"y" as &[u8; 1];
+    let _ = b"z" as *const u8;
+    let _ = "รค" as *const str;
 }
diff --git a/src/test/run-pass/env-args-reverse-iterator.rs b/src/test/run-pass/env-args-reverse-iterator.rs
new file mode 100644 (file)
index 0000000..d22fa64
--- /dev/null
@@ -0,0 +1,44 @@
+// 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::env::args;
+use std::process::Command;
+
+fn assert_reverse_iterator_for_program_arguments(program_name: &str) {
+    let args: Vec<_> = args().rev().collect();
+
+    assert!(args.len() == 4);
+    assert_eq!(args[0], "c");
+    assert_eq!(args[1], "b");
+    assert_eq!(args[2], "a");
+    assert_eq!(args[3], program_name);
+
+    println!("passed");
+}
+
+fn main() {
+    let mut args = args();
+    let me = args.next().unwrap();
+
+    if let Some(_) = args.next() {
+        assert_reverse_iterator_for_program_arguments(&me);
+        return
+    }
+
+    let output = Command::new(&me)
+        .arg("a")
+        .arg("b")
+        .arg("c")
+        .output()
+        .unwrap();
+    assert!(output.status.success());
+    assert!(output.stderr.is_empty());
+    assert_eq!(output.stdout, b"passed\n");
+}
index 0a69ccf47dd9f99959e154c3b12e949670a377c4..ed56519d23628c26ae4092151b490c923276ffce 100644 (file)
@@ -125,7 +125,7 @@ pub fn main() {
     t!(format!("{:<4.4}", "aaaaaaaaaaaaaaaaaa"), "aaaa");
     t!(format!("{:>4.4}", "aaaaaaaaaaaaaaaaaa"), "aaaa");
     t!(format!("{:^4.4}", "aaaaaaaaaaaaaaaaaa"), "aaaa");
-    t!(format!("{:>10.4}", "aaaaaaaaaaaaaaaaaa"), "aaaa");
+    t!(format!("{:>10.4}", "aaaaaaaaaaaaaaaaaa"), "      aaaa");
     t!(format!("{:2.4}", "aaaaa"), "aaaa");
     t!(format!("{:2.4}", "aaaa"), "aaaa");
     t!(format!("{:2.4}", "aaa"), "aaa");
@@ -140,6 +140,7 @@ pub fn main() {
     t!(format!("{:a$}", "a", a=4), "a   ");
     t!(format!("{:-#}", "a"), "a");
     t!(format!("{:+#}", "a"), "a");
+    t!(format!("{:/^10.8}", "1234567890"), "/12345678/");
 
     // Some float stuff
     t!(format!("{:}", 1.0f32), "1");
index 52e19b37d7935659707399c89ba330b4b6a108c4..c982e8ac6f83e2927c8e81a63b11d4152786df34 100644 (file)
@@ -16,7 +16,16 @@ macro_rules! anon { $lhs => $rhs }
     });
 }
 
+macro_rules! outer {
+    ($x:expr; $fragment:ident) => {
+        macro_rules! inner { ($y:$fragment) => { $x + $y } }
+    }
+}
+
 fn main() {
     let val = higher_order!(subst ($x:expr, $y:expr, $foo:expr) => (($x + $y, $foo)));
     assert_eq!(val, (3, "foo"));
+
+    outer!(2; expr);
+    assert_eq!(inner!(3), 5);
 }
index 5ec62e06e37aea6bee989fb95e15229cf1b42b6e..2a35fab9676a71b9f45bea98a44a6409553df18a 100644 (file)
@@ -29,6 +29,7 @@ pub enum Mode {
     Incremental,
     RunMake,
     Ui,
+    MirOpt,
 }
 
 impl FromStr for Mode {
@@ -49,6 +50,7 @@ fn from_str(s: &str) -> Result<Mode, ()> {
           "incremental" => Ok(Incremental),
           "run-make" => Ok(RunMake),
           "ui" => Ok(Ui),
+          "mir-opt" => Ok(MirOpt),
           _ => Err(()),
         }
     }
@@ -71,6 +73,7 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
             Incremental => "incremental",
             RunMake => "run-make",
             Ui => "ui",
+            MirOpt => "mir-opt",
         }, f)
     }
 }
index 6830f32bb2ce117bb522b0762ef4a57fdf04a15f..cefcc11486fe230c8659e989e3575d0233e7c47c 100644 (file)
@@ -86,7 +86,7 @@ pub fn parse_config(args: Vec<String> ) -> Config {
           reqopt("", "stage-id", "the target-stage identifier", "stageN-TARGET"),
           reqopt("", "mode", "which sort of compile tests to run",
                  "(compile-fail|parse-fail|run-fail|run-pass|\
-                  run-pass-valgrind|pretty|debug-info|incremental)"),
+                  run-pass-valgrind|pretty|debug-info|incremental|mir-opt)"),
           optflag("", "ignored", "run tests marked as ignored"),
           optopt("", "runtool", "supervisor program to run tests under \
                                  (eg. emulator, valgrind)", "PROGRAM"),
index 577da5c5af11d2b012eed6d4f860731c3050a452..f2acfa517ced5b3e36aa75afa5537ac5cfbcbf1f 100644 (file)
@@ -11,7 +11,7 @@
 use common::Config;
 use common::{CompileFail, ParseFail, Pretty, RunFail, RunPass, RunPassValgrind};
 use common::{Codegen, DebugInfoLldb, DebugInfoGdb, Rustdoc, CodegenUnits};
-use common::{Incremental, RunMake, Ui};
+use common::{Incremental, RunMake, Ui, MirOpt};
 use errors::{self, ErrorKind, Error};
 use json;
 use header::TestProps;
@@ -117,6 +117,7 @@ fn run_revision(&self) {
             Incremental => self.run_incremental_test(),
             RunMake => self.run_rmake_test(),
             Ui => self.run_ui_test(),
+            MirOpt => self.run_mir_opt_test(),
         }
     }
 
@@ -1336,7 +1337,22 @@ fn make_compile_args(&self,
                                 .map(|s| s.to_string()));
                 }
             }
+            MirOpt => {
+                args.extend(["-Z",
+                             "dump-mir=all",
+                             "-Z"]
+                            .iter()
+                            .map(|s| s.to_string()));
 
+
+                let mir_dump_dir = self.get_mir_dump_dir();
+                self.create_dir_racy(mir_dump_dir.as_path());
+                let mut dir_opt = "dump-mir-dir=".to_string();
+                dir_opt.push_str(mir_dump_dir.to_str().unwrap());
+                debug!("dir_opt: {:?}", dir_opt);
+
+                args.push(dir_opt);
+            }
             RunFail |
             RunPass |
             RunPassValgrind |
@@ -2145,6 +2161,100 @@ fn run_ui_test(&self) {
         }
     }
 
+    fn run_mir_opt_test(&self) {
+        let proc_res = self.compile_test();
+
+        if !proc_res.status.success() {
+            self.fatal_proc_rec("compilation failed!", &proc_res);
+        }
+
+        let proc_res = self.exec_compiled_test();
+
+        if !proc_res.status.success() {
+            self.fatal_proc_rec("test run failed!", &proc_res);
+        }
+        self.check_mir_dump();
+    }
+
+    fn check_mir_dump(&self) {
+        let mut test_file_contents = String::new();
+        fs::File::open(self.testpaths.file.clone()).unwrap()
+                                                   .read_to_string(&mut test_file_contents)
+                                                   .unwrap();
+        if let Some(idx) =  test_file_contents.find("// END RUST SOURCE") {
+            let (_, tests_text) = test_file_contents.split_at(idx + "// END_RUST SOURCE".len());
+            let tests_text_str = String::from(tests_text);
+            let mut curr_test : Option<&str> = None;
+            let mut curr_test_contents = Vec::new();
+            for l in tests_text_str.lines() {
+                debug!("line: {:?}", l);
+                if l.starts_with("// START ") {
+                    let (_, t) = l.split_at("// START ".len());
+                    curr_test = Some(t);
+                } else if l.starts_with("// END") {
+                    let (_, t) = l.split_at("// END ".len());
+                    if Some(t) != curr_test {
+                        panic!("mismatched START END test name");
+                    }
+                    self.compare_mir_test_output(curr_test.unwrap(), &curr_test_contents);
+                    curr_test = None;
+                    curr_test_contents.clear();
+                } else if l.is_empty() {
+                    // ignore
+                } else if l.starts_with("// ") {
+                    let (_, test_content) = l.split_at("// ".len());
+                    curr_test_contents.push(test_content);
+                }
+            }
+        }
+    }
+
+    fn compare_mir_test_output(&self, test_name: &str, expected_content: &Vec<&str>) {
+        let mut output_file = PathBuf::new();
+        output_file.push(self.get_mir_dump_dir());
+        output_file.push(test_name);
+        debug!("comparing the contests of: {:?}", output_file);
+        debug!("with: {:?}", expected_content);
+
+        let mut dumped_file = fs::File::open(output_file.clone()).unwrap();
+        let mut dumped_string = String::new();
+        dumped_file.read_to_string(&mut dumped_string).unwrap();
+        let mut dumped_lines = dumped_string.lines().filter(|l| !l.is_empty());
+        let mut expected_lines = expected_content.iter().filter(|l| !l.is_empty());
+
+        // We expect each non-empty line from expected_content to appear
+        // in the dump in order, but there may be extra lines interleaved
+        while let Some(expected_line) = expected_lines.next() {
+            let e_norm = normalize_mir_line(expected_line);
+            if e_norm.is_empty() {
+                continue;
+            };
+            let mut found = false;
+            while let Some(dumped_line) = dumped_lines.next() {
+                let d_norm = normalize_mir_line(dumped_line);
+                debug!("found: {:?}", d_norm);
+                debug!("expected: {:?}", e_norm);
+                if e_norm == d_norm {
+                    found = true;
+                    break;
+                };
+            }
+            if !found {
+                panic!("ran out of mir dump output to match against");
+            }
+        }
+    }
+
+    fn get_mir_dump_dir(&self) -> PathBuf {
+        let mut mir_dump_dir = PathBuf::from(self.config.build_base
+                                                    .as_path()
+                                                    .to_str()
+                                                    .unwrap());
+        debug!("input_file: {:?}", self.testpaths.file);
+        mir_dump_dir.push(self.testpaths.file.file_stem().unwrap().to_str().unwrap());
+        mir_dump_dir
+    }
+
     fn normalize_output(&self, output: &str) -> String {
         let parent_dir = self.testpaths.file.parent().unwrap();
         let parent_dir_str = parent_dir.display().to_string();
@@ -2274,3 +2384,12 @@ enum TargetLocation {
     ThisDirectory(PathBuf),
 }
 
+fn normalize_mir_line(line: &str) -> String {
+    let no_comments = if let Some(idx) = line.find("//") {
+        let (l, _) = line.split_at(idx);
+        l
+    } else {
+        line
+    };
+    no_comments.replace(char::is_whitespace, "")
+}