]> git.lizzy.rs Git - rust.git/commitdiff
Auto merge of #24902 - bombless:configure, r=pnkfelix
authorbors <bors@rust-lang.org>
Thu, 30 Apr 2015 15:16:24 +0000 (15:16 +0000)
committerbors <bors@rust-lang.org>
Thu, 30 Apr 2015 15:16:24 +0000 (15:16 +0000)
Closes #24840

316 files changed:
configure
mk/cfg/aarch64-apple-ios.mk
mk/cfg/aarch64-linux-android.mk
mk/cfg/aarch64-unknown-linux-gnu.mk
mk/cfg/arm-linux-androideabi.mk
mk/cfg/arm-unknown-linux-gnueabi.mk
mk/cfg/arm-unknown-linux-gnueabihf.mk
mk/cfg/armv7-apple-ios.mk
mk/cfg/armv7s-apple-ios.mk
mk/cfg/i386-apple-ios.mk
mk/cfg/i686-apple-darwin.mk
mk/cfg/i686-pc-windows-gnu.mk
mk/cfg/i686-unknown-linux-gnu.mk
mk/cfg/mips-unknown-linux-gnu.mk
mk/cfg/mipsel-unknown-linux-gnu.mk
mk/cfg/powerpc-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-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 [new file with mode: 0644]
mk/cfg/x86_64-unknown-openbsd.mk
mk/crates.mk
mk/main.mk
mk/prepare.mk
mk/rt.mk
mk/rustllvm.mk
mk/target.mk
mk/tests.mk
src/compiletest/header.rs
src/compiletest/runtest.rs
src/compiletest/util.rs
src/doc/not_found.md
src/doc/reference.md
src/doc/trpl/README.md
src/doc/trpl/benchmark-tests.md
src/doc/trpl/casting-between-types.md
src/doc/trpl/inline-assembly.md
src/doc/trpl/macros.md
src/doc/trpl/ufcs.md
src/liballoc/arc.rs
src/liballoc/heap.rs
src/liballoc/lib.rs
src/liballoc/rc.rs
src/libarena/lib.rs
src/libcollections/binary_heap.rs
src/libcollections/btree/node.rs
src/libcollections/lib.rs
src/libcollections/linked_list.rs
src/libcollections/range.rs [new file with mode: 0644]
src/libcollections/vec.rs
src/libcollections/vec_deque.rs
src/libcollections/vec_map.rs
src/libcollectionstest/lib.rs
src/libcollectionstest/vec.rs
src/libcore/cell.rs
src/libcore/fmt/mod.rs
src/libcore/fmt/rt/v1.rs
src/libcore/intrinsics.rs
src/libcore/iter.rs
src/libcore/lib.rs
src/libcore/marker.rs
src/libcore/nonzero.rs
src/libcore/num/mod.rs
src/libcore/ops.rs
src/libcore/ptr.rs
src/libcoretest/iter.rs
src/libcoretest/lib.rs
src/libcoretest/option.rs
src/libcoretest/result.rs
src/liblibc/lib.rs
src/librustc/README.md
src/librustc/diagnostics.rs
src/librustc/lib.rs
src/librustc/metadata/creader.rs
src/librustc/metadata/filesearch.rs
src/librustc/metadata/loader.rs
src/librustc/middle/check_const.rs
src/librustc/middle/mem_categorization.rs
src/librustc/middle/ty.rs
src/librustc/session/config.rs
src/librustc_back/fs.rs [deleted file]
src/librustc_back/lib.rs
src/librustc_back/rpath.rs
src/librustc_back/target/aarch64_apple_ios.rs
src/librustc_back/target/aarch64_linux_android.rs
src/librustc_back/target/aarch64_unknown_linux_gnu.rs
src/librustc_back/target/android_base.rs [new file with mode: 0644]
src/librustc_back/target/arm_linux_androideabi.rs
src/librustc_back/target/arm_unknown_linux_gnueabi.rs
src/librustc_back/target/arm_unknown_linux_gnueabihf.rs
src/librustc_back/target/armv7_apple_ios.rs
src/librustc_back/target/armv7s_apple_ios.rs
src/librustc_back/target/i386_apple_ios.rs
src/librustc_back/target/i686_apple_darwin.rs
src/librustc_back/target/i686_pc_windows_gnu.rs
src/librustc_back/target/i686_unknown_dragonfly.rs
src/librustc_back/target/i686_unknown_linux_gnu.rs
src/librustc_back/target/linux_base.rs
src/librustc_back/target/mips_unknown_linux_gnu.rs
src/librustc_back/target/mipsel_unknown_linux_gnu.rs
src/librustc_back/target/mod.rs
src/librustc_back/target/powerpc_unknown_linux_gnu.rs
src/librustc_back/target/x86_64_apple_darwin.rs
src/librustc_back/target/x86_64_apple_ios.rs
src/librustc_back/target/x86_64_pc_windows_gnu.rs
src/librustc_back/target/x86_64_unknown_bitrig.rs
src/librustc_back/target/x86_64_unknown_dragonfly.rs
src/librustc_back/target/x86_64_unknown_freebsd.rs
src/librustc_back/target/x86_64_unknown_linux_gnu.rs
src/librustc_back/target/x86_64_unknown_linux_musl.rs [new file with mode: 0644]
src/librustc_back/target/x86_64_unknown_openbsd.rs
src/librustc_bitflags/lib.rs
src/librustc_borrowck/diagnostics.rs
src/librustc_borrowck/lib.rs
src/librustc_driver/lib.rs
src/librustc_lint/builtin.rs
src/librustc_lint/lib.rs
src/librustc_llvm/archive_ro.rs
src/librustc_llvm/lib.rs
src/librustc_resolve/build_reduced_graph.rs
src/librustc_resolve/diagnostics.rs
src/librustc_resolve/lib.rs
src/librustc_resolve/resolve_imports.rs
src/librustc_trans/back/link.rs
src/librustc_trans/lib.rs
src/librustc_trans/save/mod.rs
src/librustc_trans/trans/adt.rs
src/librustc_trans/trans/attributes.rs
src/librustc_trans/trans/base.rs
src/librustc_trans/trans/build.rs
src/librustc_trans/trans/builder.rs
src/librustc_trans/trans/cabi_aarch64.rs
src/librustc_trans/trans/cabi_arm.rs
src/librustc_trans/trans/cabi_mips.rs
src/librustc_trans/trans/cabi_powerpc.rs
src/librustc_trans/trans/cabi_x86.rs
src/librustc_trans/trans/cabi_x86_64.rs
src/librustc_trans/trans/cabi_x86_win64.rs
src/librustc_trans/trans/cleanup.rs
src/librustc_trans/trans/consts.rs
src/librustc_trans/trans/context.rs
src/librustc_trans/trans/debuginfo.rs [deleted file]
src/librustc_trans/trans/debuginfo/create_scope_map.rs [new file with mode: 0644]
src/librustc_trans/trans/debuginfo/doc.rs [new file with mode: 0644]
src/librustc_trans/trans/debuginfo/gdb.rs [new file with mode: 0644]
src/librustc_trans/trans/debuginfo/metadata.rs [new file with mode: 0644]
src/librustc_trans/trans/debuginfo/mod.rs [new file with mode: 0644]
src/librustc_trans/trans/debuginfo/namespace.rs [new file with mode: 0644]
src/librustc_trans/trans/debuginfo/source_loc.rs [new file with mode: 0644]
src/librustc_trans/trans/debuginfo/type_names.rs [new file with mode: 0644]
src/librustc_trans/trans/debuginfo/utils.rs [new file with mode: 0644]
src/librustc_trans/trans/declare.rs
src/librustc_trans/trans/expr.rs
src/librustc_trans/trans/foreign.rs
src/librustc_trans/trans/glue.rs
src/librustc_trans/trans/intrinsic.rs
src/librustc_typeck/check/dropck.rs
src/librustc_typeck/check/mod.rs
src/librustc_typeck/diagnostics.rs
src/librustc_typeck/lib.rs
src/libstd/collections/hash/table.rs
src/libstd/dynamic_lib.rs
src/libstd/fs.rs
src/libstd/io/buffered.rs
src/libstd/io/mod.rs
src/libstd/lib.rs
src/libstd/macros.rs
src/libstd/net/addr.rs
src/libstd/net/ip.rs
src/libstd/net/mod.rs
src/libstd/net/tcp.rs
src/libstd/net/udp.rs
src/libstd/os.rs [deleted file]
src/libstd/os/android/mod.rs [new file with mode: 0644]
src/libstd/os/android/raw.rs [new file with mode: 0644]
src/libstd/os/bitrig/mod.rs [new file with mode: 0644]
src/libstd/os/bitrig/raw.rs [new file with mode: 0644]
src/libstd/os/dragonfly/mod.rs [new file with mode: 0644]
src/libstd/os/dragonfly/raw.rs [new file with mode: 0644]
src/libstd/os/freebsd/mod.rs [new file with mode: 0644]
src/libstd/os/freebsd/raw.rs [new file with mode: 0644]
src/libstd/os/ios/mod.rs [new file with mode: 0644]
src/libstd/os/ios/raw.rs [new file with mode: 0644]
src/libstd/os/linux/mod.rs [new file with mode: 0644]
src/libstd/os/linux/raw.rs [new file with mode: 0644]
src/libstd/os/macos/mod.rs [new file with mode: 0644]
src/libstd/os/macos/raw.rs [new file with mode: 0644]
src/libstd/os/mod.rs [new file with mode: 0644]
src/libstd/os/nacl/mod.rs [new file with mode: 0644]
src/libstd/os/nacl/raw.rs [new file with mode: 0644]
src/libstd/os/openbsd/mod.rs [new file with mode: 0644]
src/libstd/os/openbsd/raw.rs [new file with mode: 0644]
src/libstd/os/raw.rs [new file with mode: 0644]
src/libstd/process.rs
src/libstd/rt/libunwind.rs
src/libstd/rt/unwind.rs
src/libstd/rtdeps.rs
src/libstd/sync/mpsc/mod.rs
src/libstd/sync/mpsc/mpsc_queue.rs
src/libstd/sync/mpsc/oneshot.rs
src/libstd/sync/mpsc/select.rs
src/libstd/sync/mpsc/shared.rs
src/libstd/sync/mpsc/spsc_queue.rs
src/libstd/sync/mpsc/stream.rs
src/libstd/sync/mpsc/sync.rs
src/libstd/sync/mutex.rs
src/libstd/sync/once.rs
src/libstd/sync/rwlock.rs
src/libstd/sync/semaphore.rs
src/libstd/sys/common/remutex.rs
src/libstd/sys/unix/c.rs
src/libstd/sys/unix/ext.rs [deleted file]
src/libstd/sys/unix/ext/ffi.rs [new file with mode: 0644]
src/libstd/sys/unix/ext/fs.rs [new file with mode: 0644]
src/libstd/sys/unix/ext/io.rs [new file with mode: 0644]
src/libstd/sys/unix/ext/mod.rs [new file with mode: 0644]
src/libstd/sys/unix/ext/process.rs [new file with mode: 0644]
src/libstd/sys/unix/ext/raw.rs [new file with mode: 0644]
src/libstd/sys/unix/fs2.rs
src/libstd/sys/unix/mod.rs
src/libstd/sys/unix/thread.rs
src/libstd/sys/unix/time.rs
src/libstd/sys/windows/backtrace.rs
src/libstd/sys/windows/ext.rs [deleted file]
src/libstd/sys/windows/ext/ffi.rs [new file with mode: 0644]
src/libstd/sys/windows/ext/fs.rs [new file with mode: 0644]
src/libstd/sys/windows/ext/io.rs [new file with mode: 0644]
src/libstd/sys/windows/ext/mod.rs [new file with mode: 0644]
src/libstd/sys/windows/ext/raw.rs [new file with mode: 0644]
src/libstd/sys/windows/fs2.rs
src/libstd/sys/windows/handle.rs
src/libstd/sys/windows/process2.rs
src/libstd/sys/windows/stdio.rs
src/libstd/thread/local.rs
src/libstd/thread/mod.rs
src/libstd/thread/scoped_tls.rs
src/libsyntax/diagnostics/metadata.rs [new file with mode: 0644]
src/libsyntax/diagnostics/plugin.rs
src/libsyntax/feature_gate.rs
src/libsyntax/lib.rs
src/libsyntax/parse/parser.rs
src/rt/rust_builtin.c
src/rustllvm/RustWrapper.cpp
src/snapshots.txt
src/test/auxiliary/cross_crate_spans.rs
src/test/auxiliary/issue-2526.rs
src/test/auxiliary/issue24687_lib.rs [new file with mode: 0644]
src/test/auxiliary/issue24687_mbcs_in_comments.rs [new file with mode: 0644]
src/test/auxiliary/linkage-visibility.rs
src/test/bench/noise.rs
src/test/bench/shootout-k-nucleotide-pipes.rs
src/test/bench/shootout-k-nucleotide.rs
src/test/bench/shootout-reverse-complement.rs
src/test/bench/task-perf-alloc-unwind.rs
src/test/compile-fail/borrowck-borrowed-uniq-rvalue-2.rs
src/test/compile-fail/dropck_arr_cycle_checked.rs
src/test/compile-fail/dropck_direct_cycle_with_drop.rs
src/test/compile-fail/dropck_tarena_cycle_checked.rs
src/test/compile-fail/dropck_tarena_unsound_drop.rs
src/test/compile-fail/dropck_vec_cycle_checked.rs
src/test/compile-fail/exclusive-drop-and-copy.rs
src/test/compile-fail/gated-unsafe-destructor.rs [deleted file]
src/test/compile-fail/issue-24895-copy-clone-dropck.rs [new file with mode: 0644]
src/test/compile-fail/lint-no-drop-on-repr-extern.rs [new file with mode: 0644]
src/test/compile-fail/no-send-res-ports.rs
src/test/compile-fail/reject-specialized-drops-8142.rs
src/test/compile-fail/unique-vec-res.rs
src/test/compile-fail/vec-must-not-hide-type-from-dropck.rs
src/test/debuginfo/constant-debug-locs.rs
src/test/debuginfo/constant-in-match-pattern.rs
src/test/debuginfo/cross-crate-spans.rs
src/test/debuginfo/function-prologue-stepping-no-stack-check.rs
src/test/debuginfo/gdb-pretty-std.rs
src/test/debuginfo/gdb-pretty-struct-and-enums-pre-gdb-7-7.rs
src/test/debuginfo/gdb-pretty-struct-and-enums.rs
src/test/debuginfo/type-names.rs
src/test/debuginfo/vec-slices.rs
src/test/run-make/issue-19371/foo.rs
src/test/run-pass-fulldeps/issue-13560.rs
src/test/run-pass/attr-no-drop-flag-size.rs
src/test/run-pass/backtrace.rs
src/test/run-pass/drop-trait-generic.rs
src/test/run-pass/dropck_tarena_sound_drop.rs
src/test/run-pass/init-res-into-things.rs
src/test/run-pass/intrinsics-integer.rs
src/test/run-pass/issue-12133-3.rs
src/test/run-pass/issue-15858.rs
src/test/run-pass/issue-15924.rs
src/test/run-pass/issue-16492.rs
src/test/run-pass/issue-17216.rs
src/test/run-pass/issue-24945-repeat-dash-opts.rs [new file with mode: 0644]
src/test/run-pass/issue-2718.rs
src/test/run-pass/issue-2735-2.rs
src/test/run-pass/issue-2735-3.rs
src/test/run-pass/issue-4252.rs
src/test/run-pass/issue-979.rs
src/test/run-pass/issue24687-embed-debuginfo.rs [new file with mode: 0644]
src/test/run-pass/linkage-visibility.rs
src/test/run-pass/newtype-struct-drop-run.rs
src/test/run-pass/nullable-pointer-opt-closures.rs [new file with mode: 0644]
src/test/run-pass/option-unwrap.rs
src/test/run-pass/out-of-stack-new-thread-no-split.rs
src/test/run-pass/packed-struct-vec.rs
src/test/run-pass/regions-no-bound-in-argument-cleanup.rs
src/test/run-pass/resource-assign-is-not-copy.rs
src/test/run-pass/resource-destruct.rs
src/test/run-pass/resource-in-struct.rs
src/test/run-pass/sepcomp-extern.rs
src/test/run-pass/sync-send-iterators-in-libcollections.rs
src/test/run-pass/unboxed-closures-infer-fnonce-move.rs
src/test/run-pass/unboxed-closures-infer-fnonce.rs
src/test/run-pass/vec-slice-drop.rs

index 2a6d858e6af9d6c8ba0fdcf48125b09a2b8d62f0..9aebfe07967d99fc1fc268dd7649486f4fac933f 100755 (executable)
--- a/configure
+++ b/configure
@@ -551,6 +551,7 @@ opt valgrind-rpass 1 "run rpass-valgrind tests with valgrind"
 opt docs     1 "build standard library documentation"
 opt compiler-docs     0 "build compiler documentation"
 opt optimize-tests 1 "build tests with optimizations"
+opt debuginfo-tests 0 "build tests with debugger metadata"
 opt libcpp 1 "build with llvm with libc++ instead of libstdc++ when using clang"
 opt llvm-assertions 0 "build LLVM with assertions"
 opt debug-assertions 0 "build with debugging assertions"
@@ -583,6 +584,7 @@ valopt jemalloc-root "" "set directory where libjemalloc_pic.a is located"
 valopt build "${DEFAULT_BUILD}" "GNUs ./configure syntax LLVM build triple"
 valopt android-cross-path "/opt/ndk_standalone" "Android NDK standalone path"
 valopt release-channel "dev" "the name of the release channel to build"
+valopt musl-root "/usr/local" "MUSL root installation directory"
 
 # Many of these are saved below during the "writing configuration" step
 # (others are conditionally saved).
@@ -1058,6 +1060,13 @@ do
             fi
             ;;
 
+
+        *-musl)
+            if [ ! -f $CFG_MUSL_ROOT/lib/libc.a ]
+            then
+                err "musl libc $CFG_MUSL_ROOT/lib/libc.a not found"
+            fi
+            ;;
         *)
             ;;
     esac
index 0219ab960579bb81239b8df362a522c7e4615834..7767129a5e21821e60e477205e0ec446b15b3237 100644 (file)
@@ -20,16 +20,12 @@ CFG_GCCISH_CFLAGS_aarch64-apple-ios := -Wall -Werror -fPIC $(CFG_IOS_SDK_FLAGS_a
 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,
-CFG_GCCISH_PRE_LIB_FLAGS_aarch64-apple-ios :=
-CFG_GCCISH_POST_LIB_FLAGS_aarch64-apple-ios :=
-CFG_DEF_SUFFIX_aarch64-apple-ios := .darwin.def
 CFG_LLC_FLAGS_aarch64-apple-ios := -mattr=+neon,+cyclone,+fp-armv8
 CFG_INSTALL_NAME_aarch64-apple-ios = -Wl,-install_name,@rpath/$(1)
 CFG_LIBUV_LINK_FLAGS_aarch64-apple-ios =
 CFG_EXE_SUFFIX_aarch64-apple-ios :=
 CFG_WINDOWSY_aarch64-apple-ios :=
 CFG_UNIXY_aarch64-apple-ios := 1
-CFG_PATH_MUNGE_aarch64-apple-ios := true
 CFG_LDPATH_aarch64-apple-ios :=
 CFG_RUN_aarch64-apple-ios = $(2)
 CFG_RUN_TARG_aarch64-apple-ios = $(call CFG_RUN_aarch64-apple-ios,,$(2))
index a6f7f2ba1d66eb592e98cf844ce1c6a856b9c390..d7a1405c3d0a87036bf199887ee3fea99f6c4497 100644 (file)
@@ -13,15 +13,11 @@ CFG_GCCISH_CFLAGS_aarch64-linux-android := -Wall -g -fPIC -D__aarch64__ -DANDROI
 CFG_GCCISH_CXXFLAGS_aarch64-linux-android := -fno-rtti $(CXXFLAGS)
 CFG_GCCISH_LINK_FLAGS_aarch64-linux-android := -shared -fPIC -ldl -g -lm -lsupc++
 CFG_GCCISH_DEF_FLAG_aarch64-linux-android := -Wl,--export-dynamic,--dynamic-list=
-CFG_GCCISH_PRE_LIB_FLAGS_aarch64-linux-android := -Wl,-whole-archive
-CFG_GCCISH_POST_LIB_FLAGS_aarch64-linux-android := -Wl,-no-whole-archive
-CFG_DEF_SUFFIX_aarch64-linux-android := .android.def
 CFG_LLC_FLAGS_aarch64-linux-android :=
 CFG_INSTALL_NAME_aarch64-linux-android =
 CFG_EXE_SUFFIX_aarch64-linux-android :=
 CFG_WINDOWSY_aarch64-linux-android :=
 CFG_UNIXY_aarch64-linux-android := 1
-CFG_PATH_MUNGE_aarch64-linux-android := true
 CFG_LDPATH_aarch64-linux-android :=
 CFG_RUN_aarch64-linux-android=
 CFG_RUN_TARG_aarch64-linux-android=
index fade026654960e764ecfb3fcceec880e197c7d52..6637423e4951a9826c7b3004d1c939a4713cad47 100644 (file)
@@ -13,15 +13,11 @@ CFG_GCCISH_CFLAGS_aarch64-unknown-linux-gnu := -Wall -g -fPIC -D__aarch64__ $(CF
 CFG_GCCISH_CXXFLAGS_aarch64-unknown-linux-gnu := -fno-rtti $(CXXFLAGS)
 CFG_GCCISH_LINK_FLAGS_aarch64-unknown-linux-gnu := -shared -fPIC -g
 CFG_GCCISH_DEF_FLAG_aarch64-unknown-linux-gnu := -Wl,--export-dynamic,--dynamic-list=
-CFG_GCCISH_PRE_LIB_FLAGS_aarch64-unknown-linux-gnu := -Wl,-whole-archive
-CFG_GCCISH_POST_LIB_FLAGS_aarch64-unknown-linux-gnu := -Wl,-no-whole-archive
-CFG_DEF_SUFFIX_aarch64-unknown-linux-gnu := .linux.def
 CFG_LLC_FLAGS_aarch64-unknown-linux-gnu :=
 CFG_INSTALL_NAME_aarch64-unknown-linux-gnu =
 CFG_EXE_SUFFIX_aarch64-unknown-linux-gnu :=
 CFG_WINDOWSY_aarch64-unknown-linux-gnu :=
 CFG_UNIXY_aarch64-unknown-linux-gnu := 1
-CFG_PATH_MUNGE_aarch64-unknown-linux-gnu := true
 CFG_LDPATH_aarch64-unknown-linux-gnu :=
 CFG_RUN_aarch64-unknown-linux-gnu=$(2)
 CFG_RUN_TARG_aarch64-unknown-linux-gnu=$(call CFG_RUN_aarch64-unknown-linux-gnu,,$(2))
index 471220e2b6618ae08bb6726c0489b39ed3b5c358..fdd38ba75fe585e02d9491b2a154dcee786eec8b 100644 (file)
@@ -12,15 +12,11 @@ CFG_GCCISH_CFLAGS_arm-linux-androideabi := -Wall -g -fPIC -D__arm__ -DANDROID -D
 CFG_GCCISH_CXXFLAGS_arm-linux-androideabi := -fno-rtti $(CXXFLAGS)
 CFG_GCCISH_LINK_FLAGS_arm-linux-androideabi := -shared -fPIC -ldl -g -lm -lsupc++
 CFG_GCCISH_DEF_FLAG_arm-linux-androideabi := -Wl,--export-dynamic,--dynamic-list=
-CFG_GCCISH_PRE_LIB_FLAGS_arm-linux-androideabi := -Wl,-whole-archive
-CFG_GCCISH_POST_LIB_FLAGS_arm-linux-androideabi := -Wl,-no-whole-archive
-CFG_DEF_SUFFIX_arm-linux-androideabi := .android.def
 CFG_LLC_FLAGS_arm-linux-androideabi :=
 CFG_INSTALL_NAME_arm-linux-androideabi =
 CFG_EXE_SUFFIX_arm-linux-androideabi :=
 CFG_WINDOWSY_arm-linux-androideabi :=
 CFG_UNIXY_arm-linux-androideabi := 1
-CFG_PATH_MUNGE_arm-linux-androideabi := true
 CFG_LDPATH_arm-linux-androideabi :=
 CFG_RUN_arm-linux-androideabi=
 CFG_RUN_TARG_arm-linux-androideabi=
index b4c604b26bae04eda24ecf4b801c37fc55489e67..9a91097458e90fdd101dbafc0d51e777935b78ad 100644 (file)
@@ -13,15 +13,11 @@ CFG_GCCISH_CFLAGS_arm-unknown-linux-gnueabi := -Wall -g -fPIC -D__arm__ -mfpu=vf
 CFG_GCCISH_CXXFLAGS_arm-unknown-linux-gnueabi := -fno-rtti $(CXXFLAGS)
 CFG_GCCISH_LINK_FLAGS_arm-unknown-linux-gnueabi := -shared -fPIC -g
 CFG_GCCISH_DEF_FLAG_arm-unknown-linux-gnueabi := -Wl,--export-dynamic,--dynamic-list=
-CFG_GCCISH_PRE_LIB_FLAGS_arm-unknown-linux-gnueabi := -Wl,-whole-archive
-CFG_GCCISH_POST_LIB_FLAGS_arm-unknown-linux-gnueabi := -Wl,-no-whole-archive
-CFG_DEF_SUFFIX_arm-unknown-linux-gnueabi := .linux.def
 CFG_LLC_FLAGS_arm-unknown-linux-gnueabi :=
 CFG_INSTALL_NAME_arm-unknown-linux-gnueabi =
 CFG_EXE_SUFFIX_arm-unknown-linux-gnueabi :=
 CFG_WINDOWSY_arm-unknown-linux-gnueabi :=
 CFG_UNIXY_arm-unknown-linux-gnueabi := 1
-CFG_PATH_MUNGE_arm-unknown-linux-gnueabi := true
 CFG_LDPATH_arm-unknown-linux-gnueabi :=
 CFG_RUN_arm-unknown-linux-gnueabi=$(2)
 CFG_RUN_TARG_arm-unknown-linux-gnueabi=$(call CFG_RUN_arm-unknown-linux-gnueabi,,$(2))
index 4f02de0f6b5e67893d589ffea47831a22b6a3d38..0bd661ea00db22a8b2484b8f98da1bc97e993438 100644 (file)
@@ -13,15 +13,11 @@ CFG_GCCISH_CFLAGS_arm-unknown-linux-gnueabihf := -Wall -g -fPIC -D__arm__ $(CFLA
 CFG_GCCISH_CXXFLAGS_arm-unknown-linux-gnueabihf := -fno-rtti $(CXXFLAGS)
 CFG_GCCISH_LINK_FLAGS_arm-unknown-linux-gnueabihf := -shared -fPIC -g
 CFG_GCCISH_DEF_FLAG_arm-unknown-linux-gnueabihf := -Wl,--export-dynamic,--dynamic-list=
-CFG_GCCISH_PRE_LIB_FLAGS_arm-unknown-linux-gnueabihf := -Wl,-whole-archive
-CFG_GCCISH_POST_LIB_FLAGS_arm-unknown-linux-gnueabihf := -Wl,-no-whole-archive
-CFG_DEF_SUFFIX_arm-unknown-linux-gnueabihf := .linux.def
 CFG_LLC_FLAGS_arm-unknown-linux-gnueabihf :=
 CFG_INSTALL_NAME_ar,-unknown-linux-gnueabihf =
 CFG_EXE_SUFFIX_arm-unknown-linux-gnueabihf :=
 CFG_WINDOWSY_arm-unknown-linux-gnueabihf :=
 CFG_UNIXY_arm-unknown-linux-gnueabihf := 1
-CFG_PATH_MUNGE_arm-unknown-linux-gnueabihf := true
 CFG_LDPATH_arm-unknown-linux-gnueabihf :=
 CFG_RUN_arm-unknown-linux-gnueabihf=$(2)
 CFG_RUN_TARG_arm-unknown-linux-gnueabihf=$(call CFG_RUN_arm-unknown-linux-gnueabihf,,$(2))
index aee4e64addfc1834040be1717ca8379d63ea781f..d4696976574e94c52252701a8559f7ac0fbd6b62 100644 (file)
@@ -19,15 +19,11 @@ CFG_GCCISH_CFLAGS_armv7-apple-ios := -Wall -Werror -g -fPIC $(CFG_IOS_SDK_FLAGS_
 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,
-CFG_GCCISH_PRE_LIB_FLAGS_armv7-apple-ios :=
-CFG_GCCISH_POST_LIB_FLAGS_armv7-apple-ios :=
-CFG_DEF_SUFFIX_armv7-apple-ios := .darwin.def
 CFG_LLC_FLAGS_armv7-apple-ios := -mattr=+vfp3,+v7,+neon -march=arm
 CFG_INSTALL_NAME_armv7-apple-ios = -Wl,-install_name,@rpath/$(1)
 CFG_EXE_SUFFIX_armv7-apple-ios :=
 CFG_WINDOWSY_armv7-apple-ios :=
 CFG_UNIXY_armv7-apple-ios := 1
-CFG_PATH_MUNGE_armv7-apple-ios := true
 CFG_LDPATH_armv7-apple-ios :=
 CFG_RUN_armv7-apple-ios = $(2)
 CFG_RUN_TARG_armv7-apple-ios = $(call CFG_RUN_armv7-apple-ios,,$(2))
index 7540bd44de878211e1b540e05465c8d1c23358e4..96ca07648949ff500c50b8bfac253527a1564658 100644 (file)
@@ -19,15 +19,11 @@ CFG_GCCISH_CFLAGS_armv7s-apple-ios := -Wall -Werror -g -fPIC $(CFG_IOS_SDK_FLAGS
 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,
-CFG_GCCISH_PRE_LIB_FLAGS_armv7s-apple-ios :=
-CFG_GCCISH_POST_LIB_FLAGS_armv7s-apple-ios :=
-CFG_DEF_SUFFIX_armv7s-apple-ios := .darwin.def
 CFG_LLC_FLAGS_armv7s-apple-ios := -mattr=+vfp4,+v7,+neon
 CFG_INSTALL_NAME_armv7s-apple-ios = -Wl,-install_name,@rpath/$(1)
 CFG_EXE_SUFFIX_armv7s-apple-ios :=
 CFG_WINDOWSY_armv7s-apple-ios :=
 CFG_UNIXY_armv7s-apple-ios := 1
-CFG_PATH_MUNGE_armv7s-apple-ios := true
 CFG_LDPATH_armv7s-apple-ios :=
 CFG_RUN_armv7s-apple-ios = $(2)
 CFG_RUN_TARG_armv7s-apple-ios = $(call CFG_RUN_armv7s-apple-ios,,$(2))
index e84bf49d4079a39830b28f95f958e3caf1bc4c21..373e2e3b65d15e6d7e39e724ede7498f2a532bf0 100644 (file)
@@ -18,15 +18,11 @@ CFG_GCCISH_CFLAGS_i386-apple-ios := -Wall -Werror -g -fPIC -m32 $(CFG_IOSSIM_FLA
 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,
-CFG_GCCISH_PRE_LIB_FLAGS_i386-apple-ios :=
-CFG_GCCISH_POST_LIB_FLAGS_i386-apple-ios :=
-CFG_DEF_SUFFIX_i386-apple-ios := .darwin.def
 CFG_LLC_FLAGS_i386-apple-ios =
 CFG_INSTALL_NAME_i386-apple-ios = -Wl,-install_name,@rpath/$(1)
 CFG_EXE_SUFFIX_i386-apple-ios :=
 CFG_WINDOWSY_i386-apple-ios :=
 CFG_UNIXY_i386-apple-ios := 1
-CFG_PATH_MUNGE_i386-apple-ios = :true
 CFG_LDPATH_i386-apple-ios =
 CFG_RUN_i386-apple-ios = $(2)
 CFG_RUN_TARG_i386-apple-ios = $(call CFG_RUN_i386-apple-ios,,$(2))
index e935ce053e02aa273b0423522cd427446d89a326..7ebb492bb21fe1c9d8a50dd4ac697529d85223dc 100644 (file)
@@ -12,15 +12,11 @@ CFG_GCCISH_CFLAGS_i686-apple-darwin := -Wall -Werror -g -fPIC -m32 -arch i386 $(
 CFG_GCCISH_CXXFLAGS_i686-apple-darwin := -fno-rtti $(CXXFLAGS)
 CFG_GCCISH_LINK_FLAGS_i686-apple-darwin := -dynamiclib -pthread  -framework CoreServices -m32
 CFG_GCCISH_DEF_FLAG_i686-apple-darwin := -Wl,-exported_symbols_list,
-CFG_GCCISH_PRE_LIB_FLAGS_i686-apple-darwin :=
-CFG_GCCISH_POST_LIB_FLAGS_i686-apple-darwin :=
-CFG_DEF_SUFFIX_i686-apple-darwin := .darwin.def
 CFG_LLC_FLAGS_i686-apple-darwin :=
 CFG_INSTALL_NAME_i686-apple-darwin = -Wl,-install_name,@rpath/$(1)
 CFG_EXE_SUFFIX_i686-apple-darwin :=
 CFG_WINDOWSY_i686-apple-darwin :=
 CFG_UNIXY_i686-apple-darwin := 1
-CFG_PATH_MUNGE_i686-apple-darwin := true
 CFG_LDPATH_i686-apple-darwin :=
 CFG_RUN_i686-apple-darwin=$(2)
 CFG_RUN_TARG_i686-apple-darwin=$(call CFG_RUN_i686-apple-darwin,,$(2))
index 357a321688bcace7c9ac062e4b1a65ba0297fbba..174671a9a8812a3370888a2b7730cab3d6f952d6 100644 (file)
@@ -13,15 +13,11 @@ CFG_GCCISH_CFLAGS_i686-pc-windows-gnu := -Wall -Werror -g -m32 -D_WIN32_WINNT=0x
 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 :=
-CFG_GCCISH_PRE_LIB_FLAGS_i686-pc-windows-gnu :=
-CFG_GCCISH_POST_LIB_FLAGS_i686-pc-windows-gnu :=
-CFG_DEF_SUFFIX_i686-pc-windows-gnu := .windows.def
 CFG_LLC_FLAGS_i686-pc-windows-gnu :=
 CFG_INSTALL_NAME_i686-pc-windows-gnu =
 CFG_EXE_SUFFIX_i686-pc-windows-gnu := .exe
 CFG_WINDOWSY_i686-pc-windows-gnu := 1
 CFG_UNIXY_i686-pc-windows-gnu :=
-CFG_PATH_MUNGE_i686-pc-windows-gnu :=
 CFG_LDPATH_i686-pc-windows-gnu :=
 CFG_RUN_i686-pc-windows-gnu=$(2)
 CFG_RUN_TARG_i686-pc-windows-gnu=$(call CFG_RUN_i686-pc-windows-gnu,,$(2))
index 1cc9c143e8d470860a269334b94929f10bcfc934..88c0907f63b2ac8f8be2e4d30078d31fe75db184 100644 (file)
@@ -12,15 +12,11 @@ CFG_GCCISH_CFLAGS_i686-unknown-linux-gnu := -Wall -Werror -g -fPIC -m32 $(CFLAGS
 CFG_GCCISH_CXXFLAGS_i686-unknown-linux-gnu := -fno-rtti $(CXXFLAGS)
 CFG_GCCISH_LINK_FLAGS_i686-unknown-linux-gnu := -shared -fPIC -ldl -pthread  -lrt -g -m32
 CFG_GCCISH_DEF_FLAG_i686-unknown-linux-gnu := -Wl,--export-dynamic,--dynamic-list=
-CFG_GCCISH_PRE_LIB_FLAGS_i686-unknown-linux-gnu := -Wl,-whole-archive
-CFG_GCCISH_POST_LIB_FLAGS_i686-unknown-linux-gnu := -Wl,-no-whole-archive
-CFG_DEF_SUFFIX_i686-unknown-linux-gnu := .linux.def
 CFG_LLC_FLAGS_i686-unknown-linux-gnu :=
 CFG_INSTALL_NAME_i686-unknown-linux-gnu =
 CFG_EXE_SUFFIX_i686-unknown-linux-gnu =
 CFG_WINDOWSY_i686-unknown-linux-gnu :=
 CFG_UNIXY_i686-unknown-linux-gnu := 1
-CFG_PATH_MUNGE_i686-unknown-linux-gnu := true
 CFG_LDPATH_i686-unknown-linux-gnu :=
 CFG_RUN_i686-unknown-linux-gnu=$(2)
 CFG_RUN_TARG_i686-unknown-linux-gnu=$(call CFG_RUN_i686-unknown-linux-gnu,,$(2))
index c5d84966f8526f332b2a19b3d3ab3c00e1eb88b7..ba5f6d0e756343af7fb01c1b2e398d9644f56018 100644 (file)
@@ -12,15 +12,11 @@ CFG_GCCISH_CFLAGS_mips-unknown-linux-gnu := -Wall -g -fPIC -mips32r2 -msoft-floa
 CFG_GCCISH_CXXFLAGS_mips-unknown-linux-gnu := -fno-rtti $(CXXFLAGS)
 CFG_GCCISH_LINK_FLAGS_mips-unknown-linux-gnu := -shared -fPIC -g -mips32r2 -msoft-float -mabi=32
 CFG_GCCISH_DEF_FLAG_mips-unknown-linux-gnu := -Wl,--export-dynamic,--dynamic-list=
-CFG_GCCISH_PRE_LIB_FLAGS_mips-unknown-linux-gnu := -Wl,-whole-archive
-CFG_GCCISH_POST_LIB_FLAGS_mips-unknown-linux-gnu := -Wl,-no-whole-archive
-CFG_DEF_SUFFIX_mips-unknown-linux-gnu := .linux.def
 CFG_LLC_FLAGS_mips-unknown-linux-gnu :=
 CFG_INSTALL_NAME_mips-unknown-linux-gnu =
 CFG_EXE_SUFFIX_mips-unknown-linux-gnu :=
 CFG_WINDOWSY_mips-unknown-linux-gnu :=
 CFG_UNIXY_mips-unknown-linux-gnu := 1
-CFG_PATH_MUNGE_mips-unknown-linux-gnu := true
 CFG_LDPATH_mips-unknown-linux-gnu :=
 CFG_RUN_mips-unknown-linux-gnu=
 CFG_RUN_TARG_mips-unknown-linux-gnu=
index eb2f300abffd8072665fab3d8c68ac8a527ee6e9..539038c7434606dfc4825052af1a35a431445096 100644 (file)
@@ -12,15 +12,11 @@ CFG_GCCISH_CFLAGS_mipsel-unknown-linux-gnu := -Wall -g -fPIC -mips32 -mabi=32 $(
 CFG_GCCISH_CXXFLAGS_mipsel-unknown-linux-gnu := -fno-rtti $(CXXFLAGS)
 CFG_GCCISH_LINK_FLAGS_mipsel-unknown-linux-gnu := -shared -fPIC -g -mips32
 CFG_GCCISH_DEF_FLAG_mipsel-unknown-linux-gnu := -Wl,--export-dynamic,--dynamic-list=
-CFG_GCCISH_PRE_LIB_FLAGS_mipsel-unknown-linux-gnu := -Wl,-whole-archive
-CFG_GCCISH_POST_LIB_FLAGS_mipsel-unknown-linux-gnu := -Wl,-no-whole-archive
-CFG_DEF_SUFFIX_mipsel-unknown-linux-gnu := .linux.def
 CFG_LLC_FLAGS_mipsel-unknown-linux-gnu :=
 CFG_INSTALL_NAME_mipsel-unknown-linux-gnu =
 CFG_EXE_SUFFIX_mipsel-unknown-linux-gnu :=
 CFG_WINDOWSY_mipsel-unknown-linux-gnu :=
 CFG_UNIXY_mipsel-unknown-linux-gnu := 1
-CFG_PATH_MUNGE_mipsel-unknown-linux-gnu := true
 CFG_LDPATH_mipsel-unknown-linux-gnu :=
 CFG_RUN_mipsel-unknown-linux-gnu=
 CFG_RUN_TARG_mipsel-unknown-linux-gnu=
index fd37bd663f7dddb96e0222062d0c0e713e8ea0e6..dda957673eba665d15ab266a29e89a76336d370c 100644 (file)
@@ -13,15 +13,11 @@ CFG_GCCISH_CFLAGS_powerpc-unknown-linux-gnu := -Wall -Werror -g -fPIC -m32 $(CFL
 CFG_GCCISH_CXXFLAGS_powerpc-unknown-linux-gnu := -fno-rtti $(CXXFLAGS)
 CFG_GCCISH_LINK_FLAGS_powerpc-unknown-linux-gnu := -shared -fPIC -ldl -pthread  -lrt -g -m32
 CFG_GCCISH_DEF_FLAG_powerpc-unknown-linux-gnu := -Wl,--export-dynamic,--dynamic-list=
-CFG_GCCISH_PRE_LIB_FLAGS_powerpc-unknown-linux-gnu := -Wl,-whole-archive
-CFG_GCCISH_POST_LIB_FLAGS_powerpc-unknown-linux-gnu := -Wl,-no-whole-archive
-CFG_DEF_SUFFIX_powerpc-unknown-linux-gnu := .linux.def
 CFG_LLC_FLAGS_powerpc-unknown-linux-gnu :=
 CFG_INSTALL_NAME_powerpc-unknown-linux-gnu =
 CFG_EXE_SUFFIX_powerpc-unknown-linux-gnu =
 CFG_WINDOWSY_powerpc-unknown-linux-gnu :=
 CFG_UNIXY_powerpc-unknown-linux-gnu := 1
-CFG_PATH_MUNGE_powerpc-unknown-linux-gnu := true
 CFG_LDPATH_powerpc-unknown-linux-gnu :=
 CFG_RUN_powerpc-unknown-linux-gnu=$(2)
 CFG_RUN_TARG_powerpc-unknown-linux-gnu=$(call CFG_RUN_powerpc-unknown-linux-gnu,,$(2))
index dbd67542ab75a08c994c27454a6189ba8297ef3c..4c68d3dcf37b4424b10e06ae845bfb30e2950d57 100644 (file)
@@ -12,15 +12,11 @@ CFG_GCCISH_CFLAGS_x86_64-apple-darwin := -Wall -Werror -g -fPIC -m64 -arch x86_6
 CFG_GCCISH_CXXFLAGS_x86_64-apple-darwin := -fno-rtti $(CXXFLAGS)
 CFG_GCCISH_LINK_FLAGS_x86_64-apple-darwin := -dynamiclib -pthread  -framework CoreServices -m64
 CFG_GCCISH_DEF_FLAG_x86_64-apple-darwin := -Wl,-exported_symbols_list,
-CFG_GCCISH_PRE_LIB_FLAGS_x86_64-apple-darwin :=
-CFG_GCCISH_POST_LIB_FLAGS_x86_64-apple-darwin :=
-CFG_DEF_SUFFIX_x86_64-apple-darwin := .darwin.def
 CFG_LLC_FLAGS_x86_64-apple-darwin :=
 CFG_INSTALL_NAME_x86_64-apple-darwin = -Wl,-install_name,@rpath/$(1)
 CFG_EXE_SUFFIX_x86_64-apple-darwin :=
 CFG_WINDOWSY_x86_64-apple-darwin :=
 CFG_UNIXY_x86_64-apple-darwin := 1
-CFG_PATH_MUNGE_x86_64-apple-darwin := true
 CFG_LDPATH_x86_64-apple-darwin :=
 CFG_RUN_x86_64-apple-darwin=$(2)
 CFG_RUN_TARG_x86_64-apple-darwin=$(call CFG_RUN_x86_64-apple-darwin,,$(2))
index b3f05a895a49fe0f65c912ac9997a59270fb1744..dd6080fdb0bab1ecc872a8fd9e0f1160bf37a477 100644 (file)
@@ -20,16 +20,12 @@ CFG_GCCISH_CFLAGS_x86_64-apple-ios := -Wall -Werror -fPIC $(CFG_IOSSIM_FLAGS_x86
 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,
-CFG_GCCISH_PRE_LIB_FLAGS_x86_64-apple-ios :=
-CFG_GCCISH_POST_LIB_FLAGS_x86_64-apple-ios :=
-CFG_DEF_SUFFIX_x86_64-apple-ios := .darwin.def
 CFG_LLC_FLAGS_x86_64-apple-ios :=
 CFG_INSTALL_NAME_x86_64-apple-ios = -Wl,-install_name,@rpath/$(1)
 CFG_LIBUV_LINK_FLAGS_x86_64-apple-ios :=
 CFG_EXE_SUFFIX_x86_64-apple-ios :=
 CFG_WINDOWSY_x86_64-apple-ios :=
 CFG_UNIXY_x86_64-apple-ios := 1
-CFG_PATH_MUNGE_x86_64-apple-ios := true
 CFG_LDPATH_x86_64-apple-ios :=
 CFG_RUN_x86_64-apple-ios = $(2)
 CFG_RUN_TARG_x86_64-apple-ios = $(call CFG_RUN_x86_64-apple-ios,,$(2))
index e9e5f04ea54336a3a2737c80f65b850a0ed24773..4118ea26c072b0e13587bcc293d38a5c55b56329 100644 (file)
@@ -13,15 +13,11 @@ CFG_GCCISH_CFLAGS_x86_64-pc-windows-gnu := -Wall -Werror -g -m64 -D_WIN32_WINNT=
 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 :=
-CFG_GCCISH_PRE_LIB_FLAGS_x86_64-pc-windows-gnu :=
-CFG_GCCISH_POST_LIB_FLAGS_x86_64-pc-windows-gnu :=
-CFG_DEF_SUFFIX_x86_64-pc-windows-gnu := .windows.def
 CFG_LLC_FLAGS_x86_64-pc-windows-gnu :=
 CFG_INSTALL_NAME_x86_64-pc-windows-gnu =
 CFG_EXE_SUFFIX_x86_64-pc-windows-gnu := .exe
 CFG_WINDOWSY_x86_64-pc-windows-gnu := 1
 CFG_UNIXY_x86_64-pc-windows-gnu :=
-CFG_PATH_MUNGE_x86_64-pc-windows-gnu :=
 CFG_LDPATH_x86_64-pc-windows-gnu :=
 CFG_RUN_x86_64-pc-windows-gnu=$(2)
 CFG_RUN_TARG_x86_64-pc-windows-gnu=$(call CFG_RUN_x86_64-pc-windows-gnu,,$(2))
index ad34988cb1bc00369ca1f92826a066715e05590a..dd6d19f7491bb688d8f7c588392afd18c9a6a4c5 100644 (file)
@@ -11,15 +11,11 @@ CFG_JEMALLOC_CFLAGS_x86_64-unknown-bitrig := -m64 -I/usr/include $(CFLAGS)
 CFG_GCCISH_CFLAGS_x86_64-unknown-bitrig := -Wall -Werror -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_GCCISH_PRE_LIB_FLAGS_x86_64-unknown-bitrig := -Wl,-pic -Wl,-whole-archive
-CFG_GCCISH_POST_LIB_FLAGS_x86_64-unknown-bitrig := -Wl,-no-whole-archive
-CFG_DEF_SUFFIX_x86_64-unknown-bitrig := .bsd.def
 CFG_LLC_FLAGS_x86_64-unknown-bitrig :=
 CFG_INSTALL_NAME_x86_64-unknown-bitrig =
 CFG_EXE_SUFFIX_x86_64-unknown-bitrig :=
 CFG_WINDOWSY_x86_64-unknown-bitrig :=
 CFG_UNIXY_x86_64-unknown-bitrig := 1
-CFG_PATH_MUNGE_x86_64-unknown-bitrig :=
 CFG_LDPATH_x86_64-unknown-bitrig :=
 CFG_RUN_x86_64-unknown-bitrig=$(2)
 CFG_RUN_TARG_x86_64-unknown-bitrig=$(call CFG_RUN_x86_64-unknown-bitrig,,$(2))
index 9665b5c7802729b09b84e531e2e7a4c99e98930b..4015293826e1a884e2a2c9975908ec09e17ef6eb 100644 (file)
@@ -11,15 +11,11 @@ CFG_JEMALLOC_CFLAGS_x86_64-unknown-dragonfly := -m64 -I/usr/include -I/usr/local
 CFG_GCCISH_CFLAGS_x86_64-unknown-dragonfly := -Wall -Werror -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_GCCISH_PRE_LIB_FLAGS_x86_64-unknown-dragonfly := -Wl,-whole-archive
-CFG_GCCISH_POST_LIB_FLAGS_x86_64-unknown-dragonfly := -Wl,-no-whole-archive
-CFG_DEF_SUFFIX_x86_64-unknown-dragonfly := .bsd.def
 CFG_LLC_FLAGS_x86_64-unknown-dragonfly :=
 CFG_INSTALL_NAME_x86_64-unknown-dragonfly =
 CFG_EXE_SUFFIX_x86_64-unknown-dragonfly :=
 CFG_WINDOWSY_x86_64-unknown-dragonfly :=
 CFG_UNIXY_x86_64-unknown-dragonfly := 1
-CFG_PATH_MUNGE_x86_64-unknown-dragonfly :=
 CFG_LDPATH_x86_64-unknown-dragonfly :=
 CFG_RUN_x86_64-unknown-dragonfly=$(2)
 CFG_RUN_TARG_x86_64-unknown-dragonfly=$(call CFG_RUN_x86_64-unknown-dragonfly,,$(2))
index 4e847ea78a717e13f258003aa3b56447a837cc29..1bd43168b4f692cf7283560803446569a275ac95 100644 (file)
@@ -11,15 +11,11 @@ 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_LINK_FLAGS_x86_64-unknown-freebsd := -shared -fPIC -g -pthread  -lrt
 CFG_GCCISH_DEF_FLAG_x86_64-unknown-freebsd := -Wl,--export-dynamic,--dynamic-list=
-CFG_GCCISH_PRE_LIB_FLAGS_x86_64-unknown-freebsd := -Wl,-whole-archive
-CFG_GCCISH_POST_LIB_FLAGS_x86_64-unknown-freebsd := -Wl,-no-whole-archive
-CFG_DEF_SUFFIX_x86_64-unknown-freebsd := .bsd.def
 CFG_LLC_FLAGS_x86_64-unknown-freebsd :=
 CFG_INSTALL_NAME_x86_64-unknown-freebsd =
 CFG_EXE_SUFFIX_x86_64-unknown-freebsd :=
 CFG_WINDOWSY_x86_64-unknown-freebsd :=
 CFG_UNIXY_x86_64-unknown-freebsd := 1
-CFG_PATH_MUNGE_x86_64-unknown-freebsd :=
 CFG_LDPATH_x86_64-unknown-freebsd :=
 CFG_RUN_x86_64-unknown-freebsd=$(2)
 CFG_RUN_TARG_x86_64-unknown-freebsd=$(call CFG_RUN_x86_64-unknown-freebsd,,$(2))
index e5866094ee84f7b181fc0de2f8c86d4210c5f881..044c687c9fc4c871cb3510dfbf8f7b3e3121caf4 100644 (file)
@@ -12,15 +12,11 @@ CFG_GCCISH_CFLAGS_x86_64-unknown-linux-gnu := -Wall -Werror -g -fPIC -m64
 CFG_GCCISH_CXXFLAGS_x86_64-unknown-linux-gnu := -fno-rtti
 CFG_GCCISH_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=
-CFG_GCCISH_PRE_LIB_FLAGS_x86_64-unknown-linux-gnu := -Wl,-whole-archive
-CFG_GCCISH_POST_LIB_FLAGS_x86_64-unknown-linux-gnu := -Wl,-no-whole-archive
-CFG_DEF_SUFFIX_x86_64-unknown-linux-gnu := .linux.def
 CFG_LLC_FLAGS_x86_64-unknown-linux-gnu :=
 CFG_INSTALL_NAME_x86_64-unknown-linux-gnu =
 CFG_EXE_SUFFIX_x86_64-unknown-linux-gnu =
 CFG_WINDOWSY_x86_64-unknown-linux-gnu :=
 CFG_UNIXY_x86_64-unknown-linux-gnu := 1
-CFG_PATH_MUNGE_x86_64-unknown-linux-gnu := true
 CFG_LDPATH_x86_64-unknown-linux-gnu :=
 CFG_RUN_x86_64-unknown-linux-gnu=$(2)
 CFG_RUN_TARG_x86_64-unknown-linux-gnu=$(call CFG_RUN_x86_64-unknown-linux-gnu,,$(2))
diff --git a/mk/cfg/x86_64-unknown-linux-musl.mk b/mk/cfg/x86_64-unknown-linux-musl.mk
new file mode 100644 (file)
index 0000000..b3dea6f
--- /dev/null
@@ -0,0 +1,27 @@
+# x86_64-unknown-linux-musl configuration
+CC_x86_64-unknown-linux-musl=$(CFG_MUSL_ROOT)/bin/musl-gcc
+CXX_x86_64-unknown-linux-musl=notaprogram
+CPP_x86_64-unknown-linux-musl=$(CFG_MUSL_ROOT)/bin/musl-gcc -E
+AR_x86_64-unknown-linux-musl=$(AR)
+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_CXXFLAGS_x86_64-unknown-linux-musl :=
+CFG_GCCISH_LINK_FLAGS_x86_64-unknown-linux-musl :=
+CFG_GCCISH_DEF_FLAG_x86_64-unknown-linux-musl :=
+CFG_LLC_FLAGS_x86_64-unknown-linux-musl :=
+CFG_INSTALL_NAME_x86_64-unknown-linux-musl =
+CFG_EXE_SUFFIX_x86_64-unknown-linux-musl =
+CFG_WINDOWSY_x86_64-unknown-linux-musl :=
+CFG_UNIXY_x86_64-unknown-linux-musl := 1
+CFG_LDPATH_x86_64-unknown-linux-musl :=
+CFG_RUN_x86_64-unknown-linux-musl=$(2)
+CFG_RUN_TARG_x86_64-unknown-linux-musl=$(call CFG_RUN_x86_64-unknown-linux-musl,,$(2))
+CFG_GNU_TRIPLE_x86_64-unknown-linux-musl := x86_64-unknown-linux-musl
+
+NATIVE_DEPS_libc_T_x86_64-unknown-linux-musl += libc.a
+NATIVE_DEPS_std_T_x86_64-unknown-linux-musl += libunwind.a \
+       crt1.o crti.o crtn.o
+INSTALLED_OBJECTS_x86_64-unknown-linux-musl += crt1.o crti.o crtn.o
index 582d75c3eaf09dba7313d4f91336b11490746c37..261616ecf1fdaea8c14cff20c9bf49c7c44d1c30 100644 (file)
@@ -11,15 +11,11 @@ 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_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_GCCISH_PRE_LIB_FLAGS_x86_64-unknown-openbsd := -Wl,-whole-archive
-CFG_GCCISH_POST_LIB_FLAGS_x86_64-unknown-openbsd := -Wl,-no-whole-archive
-CFG_DEF_SUFFIX_x86_64-unknown-openbsd := .bsd.def
 CFG_LLC_FLAGS_x86_64-unknown-openbsd :=
 CFG_INSTALL_NAME_x86_64-unknown-openbsd =
 CFG_EXE_SUFFIX_x86_64-unknown-openbsd :=
 CFG_WINDOWSY_x86_64-unknown-openbsd :=
 CFG_UNIXY_x86_64-unknown-openbsd := 1
-CFG_PATH_MUNGE_x86_64-unknown-openbsd :=
 CFG_LDPATH_x86_64-unknown-openbsd :=
 CFG_RUN_x86_64-unknown-openbsd=$(2)
 CFG_RUN_TARG_x86_64-unknown-openbsd=$(call CFG_RUN_x86_64-unknown-openbsd,,$(2))
index e7c6a716f4cfcde236b5db33b02194fa8043c213..367c25a8a6d495f5281ae94980101e70b699f0b2 100644 (file)
@@ -123,6 +123,9 @@ ONLY_RLIB_rustc_bitflags := 1
 # Documented-by-default crates
 DOC_CRATES := std alloc collections core libc rustc_unicode
 
+# Installed objects/libraries by default
+INSTALLED_OBJECTS := libmorestack.a libcompiler-rt.a
+
 ################################################################################
 # You should not need to edit below this line
 ################################################################################
index c1ce1051d0a86ca7c7d34275b091197016ea1495..9ac96aa90f6b9b9a1035b40994bbbfeb6f7784cd 100644 (file)
@@ -399,8 +399,10 @@ endif
 # Prerequisites for using the stageN compiler to build target artifacts
 TSREQ$(1)_T_$(2)_H_$(3) = \
        $$(HSREQ$(1)_H_$(3)) \
-       $$(TLIB$(1)_T_$(2)_H_$(3))/libmorestack.a \
-       $$(TLIB$(1)_T_$(2)_H_$(3))/libcompiler-rt.a
+       $$(foreach obj,$$(INSTALLED_OBJECTS),\
+               $$(TLIB$(1)_T_$(2)_H_$(3))/$$(obj)) \
+       $$(foreach obj,$$(INSTALLED_OBJECTS_$(2)),\
+               $$(TLIB$(1)_T_$(2)_H_$(3))/$$(obj))
 
 # Prerequisites for a working stageN compiler and libraries, for a specific
 # target
index 4ded8a7916b9ba4d386d61f3d5198fffc5109063..1382d160e13999063b3ac7674ab95c0de600854b 100644 (file)
@@ -140,8 +140,8 @@ prepare-target-$(2)-host-$(3)-$(1)-$(4): prepare-maybe-clean-$(4) \
           $$(if $$(findstring $(2),$$(CFG_HOST)), \
             $$(foreach crate,$$(HOST_CRATES), \
               $$(call PREPARE_LIB,$$(call CFG_LIB_GLOB_$(2),$$(crate)))),) \
-          $$(call PREPARE_LIB,libmorestack.a) \
-          $$(call PREPARE_LIB,libcompiler-rt.a),),),)
+         $$(foreach object,$$(INSTALLED_OBJECTS) $$(INSTALLED_OBJECTS_$(2)),\
+           $$(call PREPARE_LIB,$$(object))),),),)
 endef
 
 define INSTALL_GDB_DEBUGGER_SCRIPTS_COMMANDS
index 70abce8b4606751f1bda548dcd97a31f0661fecc..bd6578d3b724b9baeffaab93ac7d40fa81215747 100644 (file)
--- a/mk/rt.mk
+++ b/mk/rt.mk
@@ -74,7 +74,8 @@ $$(RT_OUTPUT_DIR_$(1))/%.o: $(S)src/rt/%.ll $$(MKFILE_DEPS) \
        @mkdir -p $$(@D)
        @$$(call E, compile: $$@)
        $$(Q)$$(LLC_$$(CFG_BUILD)) $$(CFG_LLC_FLAGS_$(1)) \
-           -filetype=obj -mtriple=$$(CFG_LLVM_TARGET_$(1)) -relocation-model=pic -o $$@ $$<
+           -filetype=obj -mtriple=$$(CFG_LLVM_TARGET_$(1)) \
+           -relocation-model=pic -o $$@ $$<
 
 $$(RT_OUTPUT_DIR_$(1))/%.o: $(S)src/rt/%.c $$(MKFILE_DEPS)
        @mkdir -p $$(@D)
@@ -110,6 +111,11 @@ $$(RT_OUTPUT_DIR_$(1))/$$(NATIVE_$(2)_$(1)): $$(OBJS_$(2)_$(1))
        @$$(call E, link: $$@)
        $$(Q)$$(AR_$(1)) rcs $$@ $$^
 
+ifeq ($$(findstring windows,$(1)),windows)
+$$(RT_OUTPUT_DIR_$(1))/lib$(2).a: $$(RT_OUTPUT_DIR_$(1))/$$(NATIVE_$(2)_$(1))
+       $$(Q)cp $$^ $$@
+endif
+
 endef
 
 $(foreach target,$(CFG_TARGET), \
@@ -221,7 +227,7 @@ COMPRT_DEPS := $(wildcard \
               $(S)src/compiler-rt/*/*/*/*)
 endif
 
-COMPRT_NAME_$(1) := $$(call CFG_STATIC_LIB_NAME_$(1),compiler-rt)
+COMPRT_NAME_$(1) := libcompiler-rt.a
 COMPRT_LIB_$(1) := $$(RT_OUTPUT_DIR_$(1))/$$(COMPRT_NAME_$(1))
 COMPRT_BUILD_DIR_$(1) := $$(RT_OUTPUT_DIR_$(1))/compiler-rt
 
@@ -312,6 +318,19 @@ endif # endif for windowsy
 endif # endif for ios
 endif # endif for darwin
 
+################################################################################
+# libc/libunwind for musl
+#
+# When we're building a musl-like target we're going to link libc/libunwind
+# statically into the standard library and liblibc, so we need to make sure
+# they're in a location that we can find
+################################################################################
+
+ifeq ($$(findstring musl,$(1)),musl)
+$$(RT_OUTPUT_DIR_$(1))/%: $$(CFG_MUSL_ROOT)/lib/%
+       cp $$^ $$@
+endif
+
 endef
 
 # Instantiate template for all stages/targets
index 44225020811c0470848bb5130b4f022e970b6142..363022e8781d08bfd28ef2ca213374409a8e4010 100644 (file)
@@ -25,8 +25,6 @@ endif
 RUSTLLVM_OBJS_CS_$(1) := $$(addprefix rustllvm/, \
        ExecutionEngineWrapper.cpp RustWrapper.cpp PassWrapper.cpp)
 
-RUSTLLVM_DEF_$(1) := $(1)/rustllvm/rustllvm$(CFG_DEF_SUFFIX_$(1))
-
 RUSTLLVM_INCS_$(1) = $$(LLVM_EXTRA_INCDIRS_$(1)) \
                      -iquote $$(LLVM_INCDIR_$(1)) \
                      -iquote $$(S)src/rustllvm/include
index 8cc74a9cbfb76f81b77d67843c569725bf7da40c..319f44fd35b77c1058c4627b77640cf913ffc09f 100644 (file)
@@ -35,7 +35,9 @@ CRATE_FULLDEPS_$(1)_T_$(2)_H_$(3)_$(4) := \
                $$(foreach dep,$$(RUST_DEPS_$(4)), \
                  $$(TLIB$(1)_T_$(2)_H_$(3))/stamp.$$(dep)) \
                $$(foreach dep,$$(NATIVE_DEPS_$(4)), \
-                 $$(RT_OUTPUT_DIR_$(2))/$$(call CFG_STATIC_LIB_NAME_$(2),$$(dep)))
+                 $$(RT_OUTPUT_DIR_$(2))/$$(call CFG_STATIC_LIB_NAME_$(2),$$(dep))) \
+               $$(foreach dep,$$(NATIVE_DEPS_$(4)_T_$(2)), \
+                 $$(RT_OUTPUT_DIR_$(2))/$$(dep))
 endef
 
 $(foreach host,$(CFG_HOST), \
@@ -143,14 +145,7 @@ $$(TBIN$(1)_T_$(2)_H_$(3))/:
 $$(TLIB$(1)_T_$(2)_H_$(3))/:
        mkdir -p $$@
 
-$$(TLIB$(1)_T_$(2)_H_$(3))/libcompiler-rt.a: \
-           $$(RT_OUTPUT_DIR_$(2))/$$(call CFG_STATIC_LIB_NAME_$(2),compiler-rt) \
-           | $$(TLIB$(1)_T_$(2)_H_$(3))/ $$(SNAPSHOT_RUSTC_POST_CLEANUP)
-       @$$(call E, cp: $$@)
-       $$(Q)cp $$< $$@
-
-$$(TLIB$(1)_T_$(2)_H_$(3))/libmorestack.a: \
-           $$(RT_OUTPUT_DIR_$(2))/$$(call CFG_STATIC_LIB_NAME_$(2),morestack) \
+$$(TLIB$(1)_T_$(2)_H_$(3))/%: $$(RT_OUTPUT_DIR_$(2))/% \
            | $$(TLIB$(1)_T_$(2)_H_$(3))/ $$(SNAPSHOT_RUSTC_POST_CLEANUP)
        @$$(call E, cp: $$@)
        $$(Q)cp $$< $$@
index 3c4818f65dade1a6335d57105f2456bec484793f..f391d8555fc2bff578a2a6c329b79cf71aa84542 100644 (file)
@@ -632,6 +632,13 @@ ifndef CFG_DISABLE_OPTIMIZE_TESTS
 CTEST_RUSTC_FLAGS += -O
 endif
 
+# Analogously to the above, whether to pass `-g` when compiling tests
+# is a separate choice from whether to pass `-g` when building the
+# compiler and standard library themselves.
+CTEST_RUSTC_FLAGS := $$(subst -g,,$$(CTEST_RUSTC_FLAGS))
+ifdef CFG_ENABLE_DEBUGINFO_TESTS
+CTEST_RUSTC_FLAGS += -g
+endif
 
 CTEST_COMMON_ARGS$(1)-T-$(2)-H-$(3) := \
                --compile-lib-path $$(HLIB$(1)_H_$(3)) \
index f5505b6e83a6738dd073b68513a4ef5755a339e4..a648e51497e79dbcc726065863d61807733a50fd 100644 (file)
@@ -170,6 +170,9 @@ fn ignore_stage(config: &Config) -> String {
         format!("ignore-{}",
                 config.stage_id.split('-').next().unwrap())
     }
+    fn ignore_env(config: &Config) -> String {
+        format!("ignore-{}", util::get_env(&config.target).unwrap_or("<unknown>"))
+    }
     fn ignore_gdb(config: &Config, line: &str) -> bool {
         if config.mode != common::DebugInfoGdb {
             return false;
@@ -231,6 +234,7 @@ fn ignore_lldb(config: &Config, line: &str) -> bool {
         !parse_name_directive(ln, &ignore_target(config)) &&
         !parse_name_directive(ln, &ignore_architecture(config)) &&
         !parse_name_directive(ln, &ignore_stage(config)) &&
+        !parse_name_directive(ln, &ignore_env(config)) &&
         !(config.mode == common::Pretty && parse_name_directive(ln, "ignore-pretty")) &&
         !(config.target != config.host && parse_name_directive(ln, "ignore-cross-compile")) &&
         !ignore_gdb(config, ln) &&
index 3d4aebad9d69f7d9965de858b7c8601033338047..33d4f761eea841ee7730abd6f3b98bd02f9a523a 100644 (file)
@@ -1233,7 +1233,20 @@ fn compose_and_run_compiler(config: &Config, props: &TestProps,
         let mut crate_type = if aux_props.no_prefer_dynamic {
             Vec::new()
         } else {
-            vec!("--crate-type=dylib".to_string())
+            // We primarily compile all auxiliary libraries as dynamic libraries
+            // to avoid code size bloat and large binaries as much as possible
+            // for the test suite (otherwise including libstd statically in all
+            // executables takes up quite a bit of space).
+            //
+            // For targets like MUSL, however, there is no support for dynamic
+            // libraries so we just go back to building a normal library. Note,
+            // however, that if the library is built with `force_host` then it's
+            // ok to be a dylib as the host should always support dylibs.
+            if config.target.contains("musl") && !aux_props.force_host {
+                vec!("--crate-type=lib".to_string())
+            } else {
+                vec!("--crate-type=dylib".to_string())
+            }
         };
         crate_type.extend(extra_link_args.clone().into_iter());
         let aux_args =
index a8b26cb3ef76835a5fb498ca76a347eabcfee5e8..184d62db45114682d21ffe8303424c89e7f5405e 100644 (file)
@@ -60,6 +60,10 @@ pub fn get_arch(triple: &str) -> &'static str {
     panic!("Cannot determine Architecture from triple");
 }
 
+pub fn get_env(triple: &str) -> Option<&str> {
+    triple.split('-').nth(3)
+}
+
 pub fn make_new_path(path: &str) -> String {
     assert!(cfg!(windows));
     // Windows just uses PATH as the library search path, so we have to
index eae2bf1925a99622c2f8b8f2486270da30d96897..e740bf3c223aef1a34278be7c5811df77d63ff78 100644 (file)
@@ -57,8 +57,12 @@ function populate_rust_search() {
 
     // #18540, use a single token
 
+    var a = document.createElement("a");
+    a.href = "http://doc.rust-lang.org/core/?search=" + encodeURIComponent(lt);
+    a.textContent = lt;
     var search = document.getElementById('core-search');
-    search.innerHTML = "<a href=\"http://doc.rust-lang.org/core/?search=" + lt + "\">" + lt + "</a>";
+    search.innerHTML = "";
+    search.appendChild(a);
 }
 populate_site_search();
 populate_rust_search();
index a71f8cf4250a6465f5ce6a0799f409a509032f30..19cbd6f90a58146402abf38283d285cac38cae85 100644 (file)
@@ -103,7 +103,7 @@ Non-doc comments are interpreted as a form of whitespace.
 
 ## Whitespace
 
-Whitespace is any non-empty string containing any the following characters:
+Whitespace is any non-empty string containing only the following characters:
 
 - `U+0020` (space, `' '`)
 - `U+0009` (tab, `'\t'`)
@@ -1897,8 +1897,8 @@ release builds.
 
 There are two kinds of configuration options, one that is either defined or not
 (`#[cfg(foo)]`), and the other that contains a string that can be checked
-against (`#[cfg(bar = "baz")]` (currently only compiler-defined configuration
-options can have the latter form).
+against (`#[cfg(bar = "baz")]`). Currently, only compiler-defined configuration
+options can have the latter form.
 
 ```
 // The function is only included in the build when compiling for OSX
index a892f67d571af9bd9c7cb221c74be5c15177ed4d..280665af787423b67abbce2ffddc9e4962e63742 100644 (file)
@@ -127,7 +127,7 @@ vector. When we try to compile this program, we get an error:
 
 ```text
 error: cannot borrow `x` as mutable because it is also borrowed as immutable
-    x.push(4);
+    x.push("foo");
     ^
 note: previous borrow of `x` occurs here; the immutable borrow prevents
 subsequent moves or mutable borrows of `x` until the borrow ends
index 890a2f8ae7de7d29b3dbd14bf867ca83f7c02563..887965375932b3fe4953179a96d4dd54ec23c32e 100644 (file)
@@ -13,7 +13,7 @@ pub fn add_two(a: i32) -> i32 {
 }
 
 #[cfg(test)]
-mod test {
+mod tests {
     use super::*;
     use test::Bencher;
 
index f0c673b561a0ee2f662fd6f0a67b02c8a7eebff2..dbacd405065d421ab090c3214f1e9aca8dcb613b 100644 (file)
@@ -43,7 +43,7 @@ what it does is very simple, but very scary. It tells Rust to treat a value of
 one type as though it were another type. It does this regardless of the
 typechecking system, and just completely trusts you.
 
-[intrinsic]: intrinsics.html
+[intrinsics]: intrinsics.html
 
 In our previous example, we know that an array of four `u8`s represents a `u32`
 properly, and so we want to do the cast. Using `transmute` instead of `as`,
index 1a4592f980fa720c5a5cbbac5548b86d39cf741b..58c2a982dd3097443c88eb98e614e4a05690869b 100644 (file)
@@ -58,7 +58,7 @@ but you must add the right number of `:` if you skip them:
 asm!("xor %eax, %eax"
     :
     :
-    : "eax"
+    : "{eax}"
    );
 # } }
 ```
@@ -69,7 +69,7 @@ Whitespace also doesn't matter:
 # #![feature(asm)]
 # #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
 # fn main() { unsafe {
-asm!("xor %eax, %eax" ::: "eax");
+asm!("xor %eax, %eax" ::: "{eax}");
 # } }
 ```
 
@@ -77,13 +77,13 @@ asm!("xor %eax, %eax" ::: "eax");
 
 Input and output operands follow the same format: `:
 "constraints1"(expr1), "constraints2"(expr2), ..."`. Output operand
-expressions must be mutable lvalues:
+expressions must be mutable lvalues, or not yet assigned:
 
 ```
 # #![feature(asm)]
 # #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
 fn add(a: i32, b: i32) -> i32 {
-    let mut c = 0;
+    let c: i32;
     unsafe {
         asm!("add $2, $0"
              : "=r"(c)
@@ -100,6 +100,22 @@ fn main() {
 }
 ```
 
+If you would like to use real operands in this position, however,
+you are required to put curly braces `{}` around the register that
+you want, and you are required to put the specific size of the
+operand. This is useful for very low level programming, where 
+which register you use is important:
+
+```
+# #![feature(asm)]
+# #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
+# unsafe fn read_byte_in(port: u16) -> u8 {
+let result: u8;
+asm!("in %dx, %al" : "={al}"(result) : "{dx}"(port));
+result
+# }
+```
+
 ## Clobbers
 
 Some instructions modify registers which might otherwise have held
@@ -112,7 +128,7 @@ stay valid.
 # #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
 # fn main() { unsafe {
 // Put the value 0x200 in eax
-asm!("mov $$0x200, %eax" : /* no outputs */ : /* no inputs */ : "eax");
+asm!("mov $$0x200, %eax" : /* no outputs */ : /* no inputs */ : "{eax}");
 # } }
 ```
 
@@ -139,3 +155,14 @@ Current valid options are:
    the compiler to insert its usual stack alignment code
 3. *intel* - use intel syntax instead of the default AT&T.
 
+```
+# #![feature(asm)]
+# #[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
+# fn main() {
+let result: i32;
+unsafe {
+   asm!("mov eax, 2" : "={eax}"(result) : : : "intel")
+}
+println!("eax is currently {}", result);
+# }
+```
index 9d01f104ddaafcdcb824ccf4241189c743667c58..d504fab206ddfd185d65c4b6362e5395eb8b7e9b 100644 (file)
@@ -765,7 +765,7 @@ as `unimplemented!` until you’re ready to write them.
 # Procedural macros
 
 If Rust’s macro system can’t do what you need, you may want to write a
-[compiler plugin](plugins.html) instead. Compared to `macro_rules!`
+[compiler plugin](compiler-plugins.html) instead. Compared to `macro_rules!`
 macros, this is significantly more work, the interfaces are much less stable,
 and bugs can be much harder to track down. In exchange you get the
 flexibility of running arbitrary Rust code within the compiler. Syntax
index 2d5c742ddb8482312a2ee0661f46808b694c8c50..2353c63a606af070be774e1e9bb2ccb5de1142f5 100644 (file)
@@ -89,7 +89,7 @@ not, and so we need to pass an explicit `&b`.
 The form of UFCS we just talked about:
 
 ```rust,ignore
-Type::method(args);
+Trait::method(args);
 ```
 
 Is a short-hand. There’s an expanded form of this that’s needed in some
index 9d7f9ea89908f21cab8ee01ca16c381028b2f38b..ab7030bee1554a52bccddfc7c2213d222fbeef23 100644 (file)
@@ -355,7 +355,6 @@ pub fn make_unique(&mut self) -> &mut T {
     }
 }
 
-#[unsafe_destructor]
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T> Drop for Arc<T> {
     /// Drops the `Arc<T>`.
@@ -489,7 +488,6 @@ fn clone(&self) -> Weak<T> {
     }
 }
 
-#[unsafe_destructor]
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T> Drop for Weak<T> {
     /// Drops the `Weak<T>`.
index 9d1d8a7ac24b8a16a8eb7b8422d7d6f65f36ce66..86a04a0687a5bb11b92aa8748c5556f24b520709 100644 (file)
@@ -211,7 +211,9 @@ fn je_malloc_stats_print(write_cb: Option<extern "C" fn(cbopaque: *mut c_void,
     }
 
     // -lpthread needs to occur after -ljemalloc, the earlier argument isn't enough
-    #[cfg(all(not(windows), not(target_os = "android")))]
+    #[cfg(all(not(windows),
+              not(target_os = "android"),
+              not(target_env = "musl")))]
     #[link(name = "pthread")]
     extern {}
 
index a8be63d637359beff197d7947b43a037023d8b15..c0974dcb2a0f06180518f1baaf4113aa8f8fb83d 100644 (file)
@@ -73,7 +73,7 @@
 #![feature(allocator)]
 #![feature(custom_attribute)]
 #![feature(fundamental)]
-#![feature(lang_items, unsafe_destructor)]
+#![feature(lang_items)]
 #![feature(box_syntax)]
 #![feature(optin_builtin_traits)]
 #![feature(unboxed_closures)]
index 2ee229ab1dfc5fa6bc5ce80c3571accb9291cbb7..015d0330ed72d79f58257604fb6339295525e15f 100644 (file)
@@ -375,7 +375,6 @@ fn deref(&self) -> &T {
     }
 }
 
-#[unsafe_destructor]
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T> Drop for Rc<T> {
     /// Drops the `Rc<T>`.
@@ -693,7 +692,6 @@ pub fn upgrade(&self) -> Option<Rc<T>> {
     }
 }
 
-#[unsafe_destructor]
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T> Drop for Weak<T> {
     /// Drops the `Weak<T>`.
index e190fb422261534c83fed4f8f3825c5c464ca95e..adfcca14d8d5a138284b9ab09ee940c8293d3d17 100644 (file)
@@ -35,7 +35,6 @@
 #![feature(core)]
 #![feature(staged_api)]
 #![feature(unboxed_closures)]
-#![feature(unsafe_destructor)]
 #![cfg_attr(test, feature(test))]
 
 extern crate alloc;
@@ -124,7 +123,6 @@ fn chunk(size: usize, is_copy: bool) -> Chunk {
     }
 }
 
-#[unsafe_destructor]
 impl<'longer_than_self> Drop for Arena<'longer_than_self> {
     fn drop(&mut self) {
         unsafe {
@@ -510,7 +508,6 @@ fn grow(&self) {
     }
 }
 
-#[unsafe_destructor]
 impl<T> Drop for TypedArena<T> {
     fn drop(&mut self) {
         unsafe {
index 0f05e5796aa15fb044a173337e989472b7449982..af7112a5cb4e30147c7a3228eb3832c3d89c4e80 100644 (file)
@@ -546,7 +546,7 @@ pub fn is_empty(&self) -> bool { self.len() == 0 }
     #[unstable(feature = "collections",
                reason = "matches collection reform specification, waiting for dust to settle")]
     pub fn drain(&mut self) -> Drain<T> {
-        Drain { iter: self.data.drain() }
+        Drain { iter: self.data.drain(..) }
     }
 
     /// Drops all items from the binary heap.
index a480335c946939d8ee6f15dd678d9d44fe3805b5..bca0e1427e4426ae687d4e7d2f34a499daf0dea6 100644 (file)
@@ -270,14 +270,12 @@ fn next_back(&mut self) -> Option<T> {
     }
 }
 
-#[unsafe_destructor]
 impl<T> Drop for RawItems<T> {
     fn drop(&mut self) {
         for _ in self.by_ref() {}
     }
 }
 
-#[unsafe_destructor]
 impl<K, V> Drop for Node<K, V> {
     fn drop(&mut self) {
         if self.keys.is_null() ||
@@ -1394,7 +1392,6 @@ fn next_edge_back(&mut self) -> Option<Node<K, V>> {
     }
 }
 
-#[unsafe_destructor]
 impl<K, V> Drop for MoveTraversalImpl<K, V> {
     fn drop(&mut self) {
         // We need to cleanup the stored values manually, as the RawItems destructor would run
index 0ea8975bbde1f4b81b447dd09f2454875c30395f..ecbe9369e781f68ccdfd5c9b592a355f80c356aa 100644 (file)
@@ -33,7 +33,6 @@
 #![feature(staged_api)]
 #![feature(unboxed_closures)]
 #![feature(unicode)]
-#![feature(unsafe_destructor)]
 #![feature(unique)]
 #![feature(unsafe_no_drop_flag, filling_drop)]
 #![feature(step_by)]
@@ -42,7 +41,8 @@
 #![feature(slice_patterns)]
 #![feature(debug_builders)]
 #![feature(utf8_error)]
-#![cfg_attr(test, feature(rand, rustc_private, test, hash, collections))]
+#![cfg_attr(test, feature(rand, rustc_private, test, hash, collections,
+                          collections_drain, collections_range))]
 #![cfg_attr(test, allow(deprecated))] // rand
 
 #![feature(no_std)]
@@ -82,6 +82,7 @@
 pub mod enum_set;
 pub mod fmt;
 pub mod linked_list;
+pub mod range;
 pub mod slice;
 pub mod str;
 pub mod string;
index c73a6f9b324a3698aa7b16063ee31aa4e958a702..f6dc5cf7d90a0045146754af6fa4d52594463768 100644 (file)
@@ -624,7 +624,6 @@ pub fn split_off(&mut self, at: usize) -> LinkedList<T> {
     }
 }
 
-#[unsafe_destructor]
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T> Drop for LinkedList<T> {
     fn drop(&mut self) {
diff --git a/src/libcollections/range.rs b/src/libcollections/range.rs
new file mode 100644 (file)
index 0000000..6ab1439
--- /dev/null
@@ -0,0 +1,45 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+#![unstable(feature = "collections_range", reason = "was just added")]
+
+//! Range syntax.
+
+use core::option::Option::{self, None, Some};
+use core::ops::{RangeFull, Range, RangeTo, RangeFrom};
+
+/// **RangeArgument** is implemented by Rust's built-in range types, produced
+/// by range syntax like `..`, `a..`, `..b` or `c..d`.
+pub trait RangeArgument<T> {
+    /// Start index (inclusive)
+    ///
+    /// Return start value if present, else `None`.
+    fn start(&self) -> Option<&T> { None }
+
+    /// End index (exclusive)
+    ///
+    /// Return end value if present, else `None`.
+    fn end(&self) -> Option<&T> { None }
+}
+
+
+impl<T> RangeArgument<T> for RangeFull {}
+
+impl<T> RangeArgument<T> for RangeFrom<T> {
+    fn start(&self) -> Option<&T> { Some(&self.start) }
+}
+
+impl<T> RangeArgument<T> for RangeTo<T> {
+    fn end(&self) -> Option<&T> { Some(&self.end) }
+}
+
+impl<T> RangeArgument<T> for Range<T> {
+    fn start(&self) -> Option<&T> { Some(&self.start) }
+    fn end(&self) -> Option<&T> { Some(&self.end) }
+}
index b033c2d90e1780a2dad7185abcc7e0f1f3ef983b..4f0b17a563b796198d19b0d913dd7b893ed482fb 100644 (file)
@@ -69,6 +69,8 @@
 
 use borrow::{Cow, IntoCow};
 
+use super::range::RangeArgument;
+
 // FIXME- fix places which assume the max vector allowed has memory usize::MAX.
 static MAX_MEMORY_SIZE: usize = isize::MAX as usize;
 
@@ -714,36 +716,61 @@ pub fn append(&mut self, other: &mut Self) {
         unsafe { other.set_len(0); }
     }
 
-    /// Creates a draining iterator that clears the `Vec` and iterates over
-    /// the removed items from start to end.
+    /// Create a draining iterator that removes the specified range in the vector
+    /// and yields the removed items from start to end. The element range is
+    /// removed even if the iterator is not consumed until the end.
+    ///
+    /// Note: It is unspecified how many elements are removed from the vector,
+    /// if the `Drain` value is leaked.
+    ///
+    /// # Panics
+    ///
+    /// Panics if the starting point is greater than the end point or if
+    /// the end point is greater than the length of the vector.
     ///
     /// # Examples
     ///
     /// ```
-    /// # #![feature(collections)]
-    /// let mut v = vec!["a".to_string(), "b".to_string()];
-    /// for s in v.drain() {
-    ///     // s has type String, not &String
-    ///     println!("{}", s);
-    /// }
-    /// assert!(v.is_empty());
+    /// # #![feature(collections_drain, collections_range)]
+    ///
+    /// // Draining using `..` clears the whole vector.
+    /// let mut v = vec![1, 2, 3];
+    /// let u: Vec<_> = v.drain(..).collect();
+    /// assert_eq!(v, &[]);
+    /// assert_eq!(u, &[1, 2, 3]);
     /// ```
-    #[inline]
-    #[unstable(feature = "collections",
-               reason = "matches collection reform specification, waiting for dust to settle")]
-    pub fn drain(&mut self) -> Drain<T> {
+    #[unstable(feature = "collections_drain",
+               reason = "recently added, matches RFC")]
+    pub fn drain<R>(&mut self, range: R) -> Drain<T> where R: RangeArgument<usize> {
+        // Memory safety
+        //
+        // When the Drain is first created, it shortens the length of
+        // the source vector to make sure no uninitalized or moved-from elements
+        // are accessible at all if the Drain's destructor never gets to run.
+        //
+        // Drain will ptr::read out the values to remove.
+        // When finished, remaining tail of the vec is copied back to cover
+        // the hole, and the vector length is restored to the new length.
+        //
+        let len = self.len();
+        let start = *range.start().unwrap_or(&0);
+        let end = *range.end().unwrap_or(&len);
+        assert!(start <= end);
+        assert!(end <= len);
+
         unsafe {
-            let begin = *self.ptr as *const T;
-            let end = if mem::size_of::<T>() == 0 {
-                (*self.ptr as usize + self.len()) as *const T
-            } else {
-                (*self.ptr).offset(self.len() as isize) as *const T
-            };
-            self.set_len(0);
+            // set self.vec length's to start, to be safe in case Drain is leaked
+            self.set_len(start);
+            // Use the borrow in the IterMut to indicate borrowing behavior of the
+            // whole Drain iterator (like &mut T).
+            let range_slice = slice::from_raw_parts_mut(
+                                        self.as_mut_ptr().offset(start as isize),
+                                        end - start);
             Drain {
-                ptr: begin,
-                end: end,
-                marker: PhantomData,
+                tail_start: end,
+                tail_len: len - end,
+                iter: range_slice.iter_mut(),
+                vec: self as *mut _,
             }
         }
     }
@@ -1599,7 +1626,6 @@ fn add(mut self, rhs: &[T]) -> Vec<T> {
     }
 }
 
-#[unsafe_destructor]
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T> Drop for Vec<T> {
     fn drop(&mut self) {
@@ -1781,7 +1807,6 @@ fn next_back(&mut self) -> Option<T> {
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T> ExactSizeIterator for IntoIter<T> {}
 
-#[unsafe_destructor]
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T> Drop for IntoIter<T> {
     fn drop(&mut self) {
@@ -1795,14 +1820,16 @@ fn drop(&mut self) {
     }
 }
 
-/// An iterator that drains a vector.
-#[unsafe_no_drop_flag]
-#[unstable(feature = "collections",
-           reason = "recently added as part of collections reform 2")]
-pub struct Drain<'a, T:'a> {
-    ptr: *const T,
-    end: *const T,
-    marker: PhantomData<&'a T>,
+/// A draining iterator for `Vec<T>`.
+#[unstable(feature = "collections_drain", reason = "recently added")]
+pub struct Drain<'a, T: 'a> {
+    /// Index of tail to preserve
+    tail_start: usize,
+    /// Length of tail
+    tail_len: usize,
+    /// Current remaining range to remove
+    iter: slice::IterMut<'a, T>,
+    vec: *mut Vec<T>,
 }
 
 unsafe impl<'a, T: Sync> Sync for Drain<'a, T> {}
@@ -1814,34 +1841,15 @@ impl<'a, T> Iterator for Drain<'a, T> {
 
     #[inline]
     fn next(&mut self) -> Option<T> {
-        unsafe {
-            if self.ptr == self.end {
-                None
-            } else {
-                if mem::size_of::<T>() == 0 {
-                    // purposefully don't use 'ptr.offset' because for
-                    // vectors with 0-size elements this would return the
-                    // same pointer.
-                    self.ptr = mem::transmute(self.ptr as usize + 1);
-
-                    // Use a non-null pointer value
-                    Some(ptr::read(EMPTY as *mut T))
-                } else {
-                    let old = self.ptr;
-                    self.ptr = self.ptr.offset(1);
-
-                    Some(ptr::read(old))
-                }
+        self.iter.next().map(|elt|
+            unsafe {
+                ptr::read(elt as *const _)
             }
-        }
+        )
     }
 
-    #[inline]
     fn size_hint(&self) -> (usize, Option<usize>) {
-        let diff = (self.end as usize) - (self.ptr as usize);
-        let size = mem::size_of::<T>();
-        let exact = diff / (if size == 0 {1} else {size});
-        (exact, Some(exact))
+        self.iter.size_hint()
     }
 }
 
@@ -1849,41 +1857,39 @@ fn size_hint(&self) -> (usize, Option<usize>) {
 impl<'a, T> DoubleEndedIterator for Drain<'a, T> {
     #[inline]
     fn next_back(&mut self) -> Option<T> {
-        unsafe {
-            if self.end == self.ptr {
-                None
-            } else {
-                if mem::size_of::<T>() == 0 {
-                    // See above for why 'ptr.offset' isn't used
-                    self.end = mem::transmute(self.end as usize - 1);
-
-                    // Use a non-null pointer value
-                    Some(ptr::read(EMPTY as *mut T))
-                } else {
-                    self.end = self.end.offset(-1);
-
-                    Some(ptr::read(self.end))
-                }
+        self.iter.next_back().map(|elt|
+            unsafe {
+                ptr::read(elt as *const _)
             }
-        }
+        )
     }
 }
 
-#[stable(feature = "rust1", since = "1.0.0")]
-impl<'a, T> ExactSizeIterator for Drain<'a, T> {}
-
-#[unsafe_destructor]
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, T> Drop for Drain<'a, T> {
     fn drop(&mut self) {
-        // self.ptr == self.end == mem::POST_DROP_USIZE if drop has already been called,
-        // so we can use #[unsafe_no_drop_flag].
+        // exhaust self first
+        while let Some(_) = self.next() { }
 
-        // destroy the remaining elements
-        for _x in self.by_ref() {}
+        if self.tail_len > 0 {
+            unsafe {
+                let source_vec = &mut *self.vec;
+                // memmove back untouched tail, update to new length
+                let start = source_vec.len();
+                let tail = self.tail_start;
+                let src = source_vec.as_ptr().offset(tail as isize);
+                let dst = source_vec.as_mut_ptr().offset(start as isize);
+                ptr::copy(src, dst, self.tail_len);
+                source_vec.set_len(start + self.tail_len);
+            }
+        }
     }
 }
 
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<'a, T> ExactSizeIterator for Drain<'a, T> {}
+
 ////////////////////////////////////////////////////////////////////////////////
 // Conversion from &[T] to &Vec<T>
 ////////////////////////////////////////////////////////////////////////////////
@@ -1905,7 +1911,6 @@ fn deref<'b>(&'b self) -> &'b Vec<T> {
 }
 
 // Prevent the inner `Vec<T>` from attempting to deallocate memory.
-#[unsafe_destructor]
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, T> Drop for DerefVec<'a, T> {
     fn drop(&mut self) {
@@ -1974,7 +1979,6 @@ struct PartialVecZeroSized<T,U> {
     marker: PhantomData<::core::cell::Cell<(T,U)>>,
 }
 
-#[unsafe_destructor]
 impl<T,U> Drop for PartialVecNonZeroSized<T,U> {
     fn drop(&mut self) {
         unsafe {
@@ -2000,7 +2004,6 @@ fn drop(&mut self) {
     }
 }
 
-#[unsafe_destructor]
 impl<T,U> Drop for PartialVecZeroSized<T,U> {
     fn drop(&mut self) {
         unsafe {
index 61369b30dea1797c25d954883c5f988fee433de7..3032b13855ba3b1b510fc6e7afa853d1f339dd6f 100644 (file)
@@ -59,7 +59,6 @@ fn clone(&self) -> VecDeque<T> {
     }
 }
 
-#[unsafe_destructor]
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T> Drop for VecDeque<T> {
     fn drop(&mut self) {
@@ -1612,7 +1611,6 @@ pub struct Drain<'a, T: 'a> {
     inner: &'a mut VecDeque<T>,
 }
 
-#[unsafe_destructor]
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, T: 'a> Drop for Drain<'a, T> {
     fn drop(&mut self) {
index d473504d5445470e676f4cce2e142f6c90215115..6ff819fc87cdbd0c3d702a608f786b4e63c1e43c 100644 (file)
@@ -418,7 +418,7 @@ fn filter<A>((i, v): (usize, Option<A>)) -> Option<(usize, A)> {
         }
         let filter: fn((usize, Option<V>)) -> Option<(usize, V)> = filter; // coerce to fn ptr
 
-        Drain { iter: self.v.drain().enumerate().filter_map(filter) }
+        Drain { iter: self.v.drain(..).enumerate().filter_map(filter) }
     }
 
     /// Returns the number of elements in the map.
index 5c109dc8104f21492347aa57d7a549d1a5028a10..57a95633b678f3ac0c9536450996f0dec1911a37 100644 (file)
@@ -10,6 +10,7 @@
 
 #![feature(box_syntax)]
 #![feature(collections)]
+#![feature(collections_drain)]
 #![feature(core)]
 #![feature(hash)]
 #![feature(rand)]
@@ -17,7 +18,6 @@
 #![feature(test)]
 #![feature(unboxed_closures)]
 #![feature(unicode)]
-#![feature(unsafe_destructor)]
 #![feature(into_cow)]
 #![feature(step_by)]
 #![cfg_attr(test, feature(str_char))]
index 2923bea982845e25139c8377ceca3e3d2aa03f6e..8a8da0d9faaeac1fb7332f4e63897167dfd6da29 100644 (file)
@@ -18,7 +18,6 @@ struct DropCounter<'a> {
     count: &'a mut u32
 }
 
-#[unsafe_destructor]
 impl<'a> Drop for DropCounter<'a> {
     fn drop(&mut self) {
         *self.count += 1;
@@ -460,7 +459,7 @@ fn test_move_items_zero_sized() {
 fn test_drain_items() {
     let mut vec = vec![1, 2, 3];
     let mut vec2 = vec![];
-    for i in vec.drain() {
+    for i in vec.drain(..) {
         vec2.push(i);
     }
     assert_eq!(vec, []);
@@ -471,7 +470,7 @@ fn test_drain_items() {
 fn test_drain_items_reverse() {
     let mut vec = vec![1, 2, 3];
     let mut vec2 = vec![];
-    for i in vec.drain().rev() {
+    for i in vec.drain(..).rev() {
         vec2.push(i);
     }
     assert_eq!(vec, []);
@@ -482,13 +481,43 @@ fn test_drain_items_reverse() {
 fn test_drain_items_zero_sized() {
     let mut vec = vec![(), (), ()];
     let mut vec2 = vec![];
-    for i in vec.drain() {
+    for i in vec.drain(..) {
         vec2.push(i);
     }
     assert_eq!(vec, []);
     assert_eq!(vec2, [(), (), ()]);
 }
 
+#[test]
+#[should_panic]
+fn test_drain_out_of_bounds() {
+    let mut v = vec![1, 2, 3, 4, 5];
+    v.drain(5..6);
+}
+
+#[test]
+fn test_drain_range() {
+    let mut v = vec![1, 2, 3, 4, 5];
+    for _ in v.drain(4..) {
+    }
+    assert_eq!(v, &[1, 2, 3, 4]);
+
+    let mut v: Vec<_> = (1..6).map(|x| x.to_string()).collect();
+    for _ in v.drain(1..4) {
+    }
+    assert_eq!(v, &[1.to_string(), 5.to_string()]);
+
+    let mut v: Vec<_> = (1..6).map(|x| x.to_string()).collect();
+    for _ in v.drain(1..4).rev() {
+    }
+    assert_eq!(v, &[1.to_string(), 5.to_string()]);
+
+    let mut v: Vec<_> = vec![(); 5];
+    for _ in v.drain(1..4).rev() {
+    }
+    assert_eq!(v, &[(), ()]);
+}
+
 #[test]
 fn test_into_boxed_slice() {
     let xs = vec![1, 2, 3];
index b4b25258bbfd63d9683d4201308553db1011eb34..9ff447a87f1fea6730580fa1b17b7afb4727bf2e 100644 (file)
@@ -493,7 +493,6 @@ fn new(borrow: &'b Cell<BorrowFlag>) -> Option<BorrowRef<'b>> {
     }
 }
 
-#[unsafe_destructor]
 impl<'b> Drop for BorrowRef<'b> {
     #[inline]
     fn drop(&mut self) {
@@ -557,7 +556,6 @@ struct BorrowRefMut<'b> {
     _borrow: &'b Cell<BorrowFlag>,
 }
 
-#[unsafe_destructor]
 impl<'b> Drop for BorrowRefMut<'b> {
     #[inline]
     fn drop(&mut self) {
index 0178b321e88c35a68be363b49bf4a91eb4b097c4..73778bfd0380991efbc3e56e0eba93b56f1ce240 100644 (file)
@@ -34,8 +34,7 @@
 mod float;
 mod builders;
 
-#[cfg_attr(stage0, stable(feature = "rust1", since = "1.0.0"))]
-#[cfg_attr(not(stage0), unstable(feature = "core", reason = "internal to format_args!"))]
+#[unstable(feature = "core", reason = "internal to format_args!")]
 #[doc(hidden)]
 pub mod rt {
     pub mod v1;
@@ -148,8 +147,7 @@ enum Void {}
 /// compile time it is ensured that the function and the value have the correct
 /// types, and then this struct is used to canonicalize arguments to one type.
 #[derive(Copy)]
-#[cfg_attr(stage0, stable(feature = "rust1", since = "1.0.0"))]
-#[cfg_attr(not(stage0), unstable(feature = "core", reason = "internal to format_args!"))]
+#[unstable(feature = "core", reason = "internal to format_args!")]
 #[doc(hidden)]
 pub struct ArgumentV1<'a> {
     value: &'a Void,
@@ -169,8 +167,7 @@ fn show_usize(x: &usize, f: &mut Formatter) -> Result {
     }
 
     #[doc(hidden)]
-    #[cfg_attr(stage0, stable(feature = "rust1", since = "1.0.0"))]
-    #[cfg_attr(not(stage0), unstable(feature = "core", reason = "internal to format_args!"))]
+    #[unstable(feature = "core", reason = "internal to format_args!")]
     pub fn new<'b, T>(x: &'b T,
                       f: fn(&T, &mut Formatter) -> Result) -> ArgumentV1<'b> {
         unsafe {
@@ -182,8 +179,7 @@ pub fn new<'b, T>(x: &'b T,
     }
 
     #[doc(hidden)]
-    #[cfg_attr(stage0, stable(feature = "rust1", since = "1.0.0"))]
-    #[cfg_attr(not(stage0), unstable(feature = "core", reason = "internal to format_args!"))]
+    #[unstable(feature = "core", reason = "internal to format_args!")]
     pub fn from_usize(x: &usize) -> ArgumentV1 {
         ArgumentV1::new(x, ArgumentV1::show_usize)
     }
@@ -206,8 +202,7 @@ impl<'a> Arguments<'a> {
     /// When using the format_args!() macro, this function is used to generate the
     /// Arguments structure.
     #[doc(hidden)] #[inline]
-    #[cfg_attr(stage0, stable(feature = "rust1", since = "1.0.0"))]
-    #[cfg_attr(not(stage0), unstable(feature = "core", reason = "internal to format_args!"))]
+    #[unstable(feature = "core", reason = "internal to format_args!")]
     pub fn new_v1(pieces: &'a [&'a str],
                   args: &'a [ArgumentV1<'a>]) -> Arguments<'a> {
         Arguments {
@@ -224,8 +219,7 @@ pub fn new_v1(pieces: &'a [&'a str],
     /// created with `argumentusize`. However, failing to do so doesn't cause
     /// unsafety, but will ignore invalid .
     #[doc(hidden)] #[inline]
-    #[cfg_attr(stage0, stable(feature = "rust1", since = "1.0.0"))]
-    #[cfg_attr(not(stage0), unstable(feature = "core", reason = "internal to format_args!"))]
+    #[unstable(feature = "core", reason = "internal to format_args!")]
     pub fn new_v1_formatted(pieces: &'a [&'a str],
                             args: &'a [ArgumentV1<'a>],
                             fmt: &'a [rt::v1::Argument]) -> Arguments<'a> {
index 0d851c1e897a9a67fe2bdfd85e8a50bdc6e08e1e..2afd8abeb31aa5810f414924a06e080ac2e357c6 100644 (file)
 //! These definitions are similar to their `ct` equivalents, but differ in that
 //! these can be statically allocated and are slightly optimized for the runtime
 
-#![cfg_attr(stage0, stable(feature = "rust1", since = "1.0.0"))]
-#![cfg_attr(not(stage0), unstable(feature = "core", reason = "internal to format_args!"))]
+#![unstable(feature = "core", reason = "internal to format_args!")]
 
 #[derive(Copy, Clone)]
-#[cfg_attr(stage0, stable(feature = "rust1", since = "1.0.0"))]
 pub struct Argument {
-    #[cfg_attr(stage0, stable(feature = "rust1", since = "1.0.0"))]
     pub position: Position,
-    #[cfg_attr(stage0, stable(feature = "rust1", since = "1.0.0"))]
     pub format: FormatSpec,
 }
 
 #[derive(Copy, Clone)]
-#[cfg_attr(stage0, stable(feature = "rust1", since = "1.0.0"))]
 pub struct FormatSpec {
-    #[cfg_attr(stage0, stable(feature = "rust1", since = "1.0.0"))]
     pub fill: char,
-    #[cfg_attr(stage0, stable(feature = "rust1", since = "1.0.0"))]
     pub align: Alignment,
-    #[cfg_attr(stage0, stable(feature = "rust1", since = "1.0.0"))]
     pub flags: u32,
-    #[cfg_attr(stage0, stable(feature = "rust1", since = "1.0.0"))]
     pub precision: Count,
-    #[cfg_attr(stage0, stable(feature = "rust1", since = "1.0.0"))]
     pub width: Count,
 }
 
 /// Possible alignments that can be requested as part of a formatting directive.
 #[derive(Copy, Clone, PartialEq)]
-#[cfg_attr(stage0, stable(feature = "rust1", since = "1.0.0"))]
 pub enum Alignment {
     /// Indication that contents should be left-aligned.
-    #[cfg_attr(stage0, stable(feature = "rust1", since = "1.0.0"))]
     Left,
     /// Indication that contents should be right-aligned.
-    #[cfg_attr(stage0, stable(feature = "rust1", since = "1.0.0"))]
     Right,
     /// Indication that contents should be center-aligned.
-    #[cfg_attr(stage0, stable(feature = "rust1", since = "1.0.0"))]
     Center,
     /// No alignment was requested.
-    #[cfg_attr(stage0, stable(feature = "rust1", since = "1.0.0"))]
     Unknown,
 }
 
 #[derive(Copy, Clone)]
-#[cfg_attr(stage0, stable(feature = "rust1", since = "1.0.0"))]
 pub enum Count {
-    #[cfg_attr(stage0, stable(feature = "rust1", since = "1.0.0"))]
     Is(usize),
-    #[cfg_attr(stage0, stable(feature = "rust1", since = "1.0.0"))]
     Param(usize),
-    #[cfg_attr(stage0, stable(feature = "rust1", since = "1.0.0"))]
     NextParam,
-    #[cfg_attr(stage0, stable(feature = "rust1", since = "1.0.0"))]
     Implied,
 }
 
 #[derive(Copy, Clone)]
-#[cfg_attr(stage0, stable(feature = "rust1", since = "1.0.0"))]
 pub enum Position {
-    #[cfg_attr(stage0, stable(feature = "rust1", since = "1.0.0"))]
     Next,
-    #[cfg_attr(stage0, stable(feature = "rust1", since = "1.0.0"))]
     At(usize)
 }
index 8ed89adec5b69385d208b821dcd39cfb67530497..ac43055a7c4a5ff65e3110ad4b5765fb19a0756c 100644 (file)
     pub fn atomic_fence_rel();
     pub fn atomic_fence_acqrel();
 
+    /// A compiler-only memory barrier.
+    ///
+    /// Memory accesses will never be reordered across this barrier by the compiler,
+    /// but no instructions will be emitted for it. This is appropriate for operations
+    /// on the same thread that may be preempted, such as when interacting with signal
+    /// handlers.
+    #[cfg(not(stage0))]     // SNAP 857ef6e
+    pub fn atomic_singlethreadfence();
+    #[cfg(not(stage0))]     // SNAP 857ef6e
+    pub fn atomic_singlethreadfence_acq();
+    #[cfg(not(stage0))]     // SNAP 857ef6e
+    pub fn atomic_singlethreadfence_rel();
+    #[cfg(not(stage0))]     // SNAP 857ef6e
+    pub fn atomic_singlethreadfence_acqrel();
+
     /// Aborts the execution of the process.
     pub fn abort() -> !;
 
     /// Returns `true` if a type is managed (will be allocated on the local heap)
     pub fn owns_managed<T>() -> bool;
 
-    /// Calculates the offset from a pointer. The offset *must* be in-bounds of
-    /// the object, or one-byte-past-the-end. An arithmetic overflow is also
-    /// undefined behaviour.
+    /// Calculates the offset from a pointer.
     ///
     /// This is implemented as an intrinsic to avoid converting to and from an
     /// integer, since the conversion would throw away aliasing information.
+    ///
+    /// # Safety
+    ///
+    /// Both the starting and resulting pointer must be either in bounds or one
+    /// byte past the end of an allocated object. If either pointer is out of
+    /// bounds or arithmetic overflow occurs then any further use of the
+    /// returned value will result in undefined behavior.
     pub fn offset<T>(dst: *const T, offset: isize) -> *const T;
 
     /// Copies `count * size_of<T>` bytes from `src` to `dst`. The source
     /// }
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[cfg(not(stage0))]
     pub fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: usize);
 
-    /// dox
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[cfg(stage0)]
-    pub fn copy_nonoverlapping<T>(dst: *mut T, src: *const T, count: usize);
-
     /// Copies `count * size_of<T>` bytes from `src` to `dst`. The source
     /// and destination may overlap.
     ///
     /// ```
     ///
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[cfg(not(stage0))]
     pub fn copy<T>(src: *const T, dst: *mut T, count: usize);
 
-    /// dox
-    #[stable(feature = "rust1", since = "1.0.0")]
-    #[cfg(stage0)]
-    pub fn copy<T>(dst: *mut T, src: *const T, count: usize);
-
     /// Invokes memset on the specified pointer, setting `count * size_of::<T>()`
     /// bytes of memory starting at `dst` to `c`.
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -572,7 +580,22 @@ pub fn volatile_copy_nonoverlapping_memory<T>(dst: *mut T, src: *const T,
 
     /// Returns the value of the discriminant for the variant in 'v',
     /// cast to a `u64`; if `T` has no discriminant, returns 0.
-    // SNAP 5520801
-    #[cfg(not(stage0))]
     pub fn discriminant_value<T>(v: &T) -> u64;
 }
+
+#[cfg(not(stage0))]
+extern "rust-intrinsic" {
+    /// Performs an unchecked signed division, which results in undefined behavior,
+    /// in cases where y == 0, or x == int::MIN and y == -1
+    pub fn unchecked_sdiv<T>(x: T, y: T) -> T;
+    /// Performs an unchecked unsigned division, which results in undefined behavior,
+    /// in cases where y == 0
+    pub fn unchecked_udiv<T>(x: T, y: T) -> T;
+
+    /// Returns the remainder of an unchecked signed division, which results in
+    /// undefined behavior, in cases where y == 0, or x == int::MIN and y == -1
+    pub fn unchecked_urem<T>(x: T, y: T) -> T;
+    /// Returns the remainder of an unchecked signed division, which results in
+    /// undefined behavior, in cases where y == 0
+    pub fn unchecked_srem<T>(x: T, y: T) -> T;
+}
index 21510e1a83b8f73c914fe5dbb6dc5fbc79b03ce2..0fa27a4312d5760948c12ce5dcc6df8bf3918241 100644 (file)
@@ -2407,12 +2407,14 @@ pub trait Step: PartialOrd {
     /// `start` should always be less than `end`, so the result should never
     /// be negative.
     ///
+    /// `by` must be > 0.
+    ///
     /// Returns `None` if it is not possible to calculate steps_between
     /// without overflow.
     fn steps_between(start: &Self, end: &Self, by: &Self) -> Option<usize>;
 }
 
-macro_rules! step_impl {
+macro_rules! step_impl_unsigned {
     ($($t:ty)*) => ($(
         impl Step for $t {
             #[inline]
@@ -2423,7 +2425,33 @@ fn step(&self, by: &$t) -> Option<$t> {
             #[allow(trivial_numeric_casts)]
             fn steps_between(start: &$t, end: &$t, by: &$t) -> Option<usize> {
                 if *start <= *end {
-                    Some(((*end - *start) / *by) as usize)
+                    // Note: We assume $t <= usize here
+                    Some((*end - *start) as usize / (*by as usize))
+                } else {
+                    Some(0)
+                }
+            }
+        }
+    )*)
+}
+macro_rules! step_impl_signed {
+    ($($t:ty)*) => ($(
+        impl Step for $t {
+            #[inline]
+            fn step(&self, by: &$t) -> Option<$t> {
+                (*self).checked_add(*by)
+            }
+            #[inline]
+            #[allow(trivial_numeric_casts)]
+            fn steps_between(start: &$t, end: &$t, by: &$t) -> Option<usize> {
+                if *start <= *end {
+                    // Note: We assume $t <= isize here
+                    // Use .wrapping_sub and cast to usize to compute the
+                    // difference that may not fit inside the range of isize.
+                    Some(
+                        ((*end as isize).wrapping_sub(*start as isize) as usize
+                        / (*by as usize))
+                    )
                 } else {
                     Some(0)
                 }
@@ -2447,9 +2475,12 @@ fn steps_between(_a: &$t, _b: &$t, _by: &$t) -> Option<usize> {
     )*)
 }
 
-step_impl!(usize u8 u16 u32 isize i8 i16 i32);
+step_impl_unsigned!(usize u8 u16 u32);
+step_impl_signed!(isize i8 i16 i32);
+#[cfg(target_pointer_width = "64")]
+step_impl_unsigned!(u64);
 #[cfg(target_pointer_width = "64")]
-step_impl!(u64 i64);
+step_impl_signed!(i64);
 #[cfg(target_pointer_width = "32")]
 step_impl_no_between!(u64 i64);
 
index 249f0a0c389a3deda580019f845e047ed3aed18d..dd06c3d0987d98b7e0da0444eaaebf21f932093e 100644 (file)
@@ -65,7 +65,7 @@
 
 #![feature(intrinsics, lang_items)]
 #![feature(on_unimplemented)]
-#![feature(simd, unsafe_destructor)]
+#![feature(simd)]
 #![feature(staged_api)]
 #![feature(unboxed_closures)]
 #![feature(rustc_attrs)]
index fdabdbc5ed4ce0c59c8d2853e662084247d7544c..44e5390098bee7b194b3724e9099d9100337de48 100644 (file)
 #[stable(feature = "rust1", since = "1.0.0")]
 #[lang="send"]
 #[rustc_on_unimplemented = "`{Self}` cannot be sent between threads safely"]
-#[cfg(not(stage0))]
 pub unsafe trait Send {
     // empty.
 }
 
-/// Types able to be transferred across thread boundaries.
-#[stable(feature = "rust1", since = "1.0.0")]
-#[lang="send"]
-#[rustc_on_unimplemented = "`{Self}` cannot be sent between threads safely"]
-#[cfg(stage0)]
-pub unsafe trait Send : MarkerTrait {
-    // empty.
-}
-
 unsafe impl Send for .. { }
 
 impl<T> !Send for *const T { }
@@ -60,21 +50,10 @@ impl !Send for Managed { }
 #[lang="sized"]
 #[rustc_on_unimplemented = "`{Self}` does not have a constant size known at compile-time"]
 #[fundamental] // for Default, for example, which requires that `[T]: !Default` be evaluatable
-#[cfg(not(stage0))]
 pub trait Sized {
     // Empty.
 }
 
-/// Types with a constant size known at compile-time.
-#[stable(feature = "rust1", since = "1.0.0")]
-#[lang="sized"]
-#[rustc_on_unimplemented = "`{Self}` does not have a constant size known at compile-time"]
-#[fundamental] // for Default, for example, which requires that `[T]: !Default` be evaluatable
-#[cfg(stage0)]
-pub trait Sized : MarkerTrait {
-    // Empty.
-}
-
 /// Types that can be copied by simply copying bits (i.e. `memcpy`).
 ///
 /// By default, variable bindings have 'move semantics.' In other
@@ -222,7 +201,6 @@ pub trait Copy : Clone {
 /// wrapper around the value(s) which can be mutated when behind a `&`
 /// reference; not doing this is undefined behaviour (for example,
 /// `transmute`-ing from `&T` to `&mut T` is illegal).
-#[cfg(not(stage0))]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[lang="sync"]
 #[rustc_on_unimplemented = "`{Self}` cannot be shared between threads safely"]
@@ -230,15 +208,6 @@ pub unsafe trait Sync {
     // Empty
 }
 
-/// dox
-#[cfg(stage0)]
-#[stable(feature = "rust1", since = "1.0.0")]
-#[lang="sync"]
-#[rustc_on_unimplemented = "`{Self}` cannot be shared between threads safely"]
-pub unsafe trait Sync : MarkerTrait {
-    // Empty
-}
-
 unsafe impl Sync for .. { }
 
 impl<T> !Sync for *const T { }
@@ -301,20 +270,6 @@ fn clone(&self) -> $t<T> {
         )
 }
 
-/// dox
-#[stable(feature = "rust1", since = "1.0.0")]
-#[cfg(stage0)]
-pub trait MarkerTrait : PhantomFn<Self,Self> { }
-
-#[cfg(stage0)]
-impl<T: ?Sized> MarkerTrait for T {}
-
-/// dox
-#[lang="phantom_fn"]
-#[cfg(stage0)]
-pub trait PhantomFn<A:?Sized,R:?Sized=()> {
-}
-
 /// `PhantomData<T>` allows you to describe that a type acts as if it stores a value of type `T`,
 /// even though it does not. This allows you to inform the compiler about certain safety properties
 /// of your code.
@@ -461,14 +416,6 @@ unsafe impl<'a, T: Send + ?Sized> Send for &'a mut T {}
 #[rustc_reflect_like]
 #[unstable(feature = "core", reason = "requires RFC and more experience")]
 #[allow(deprecated)]
-#[cfg(not(stage0))]
 pub trait Reflect {}
 
-/// dox
-#[rustc_reflect_like]
-#[unstable(feature = "core", reason = "requires RFC and more experience")]
-#[cfg(stage0)]
-pub trait Reflect: MarkerTrait {}
-
 impl Reflect for .. { }
-
index 9ea44c39fe9c6382c6a27b441df0f0a028d62a36..640703ca2f9c2d293f9b3351e95539e4a32df473 100644 (file)
 
 use marker::Sized;
 use ops::Deref;
-#[cfg(stage0)] use marker::MarkerTrait;
 
 /// Unsafe trait to indicate what types are usable with the NonZero struct
-#[cfg(not(stage0))]
 pub unsafe trait Zeroable {}
 
-/// Unsafe trait to indicate what types are usable with the NonZero struct
-#[cfg(stage0)]
-pub unsafe trait Zeroable: MarkerTrait {}
-
 unsafe impl<T:?Sized> Zeroable for *const T {}
 unsafe impl<T:?Sized> Zeroable for *mut T {}
 unsafe impl Zeroable for isize {}
index 44d5333ce1f46bb582a11b97e2fe08718c52029e..b8638c5b09be257ea87e9c7db993ea0c930328d5 100644 (file)
@@ -745,7 +745,20 @@ pub fn leading_zeros(self) -> u32 {
         #[stable(feature = "rust1", since = "1.0.0")]
         #[inline]
         pub fn trailing_zeros(self) -> u32 {
-            unsafe { $cttz(self as $ActualT) as u32 }
+            // As of LLVM 3.6 the codegen for the zero-safe cttz8 intrinsic
+            // emits two conditional moves on x86_64. By promoting the value to
+            // u16 and setting bit 8, we get better code without any conditional
+            // operations.
+            // FIXME: There's a LLVM patch (http://reviews.llvm.org/D9284)
+            // pending, remove this workaround once LLVM generates better code
+            // for cttz8.
+            unsafe {
+                if $BITS == 8 {
+                    intrinsics::cttz16(self as u16 | 0x100) as u32
+                } else {
+                    $cttz(self as $ActualT) as u32
+                }
+            }
         }
 
         /// Shifts the bits to the left by a specified amount, `n`,
index adfbd14121f586270155d387fe4d2ea6c3f59975..8a4f603ec472036be4366cadda7a0613f8a82534 100644 (file)
@@ -508,8 +508,6 @@ macro_rules! neg_impl_numeric {
 macro_rules! neg_impl_unsigned {
     ($($t:ty)*) => {
         neg_impl_core!{ x => {
-            #[cfg(stage0)]
-            use ::num::wrapping::WrappingOps;
             !x.wrapping_add(1)
         }, $($t)*} }
 }
@@ -1162,7 +1160,6 @@ pub trait FnOnce<Args> {
     extern "rust-call" fn call_once(self, args: Args) -> Self::Output;
 }
 
-#[cfg(not(stage0))]
 mod impls {
     use marker::Sized;
     use super::{Fn, FnMut, FnOnce};
index 0e9570df09d55cf19ac0495e0d670f93cb5aadea..47c029f11b38fad65971f9822d532aae935a161b 100644 (file)
 // FIXME #19649: intrinsic docs don't render, so these have no docs :(
 
 #[stable(feature = "rust1", since = "1.0.0")]
-#[cfg(not(stage0))]
 pub use intrinsics::copy_nonoverlapping;
 
-/// dox
-#[cfg(stage0)]
 #[stable(feature = "rust1", since = "1.0.0")]
-pub unsafe fn copy_nonoverlapping<T>(src: *const T, dst: *mut T, count: usize) {
-    intrinsics::copy_nonoverlapping(dst, src, count)
-}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-#[cfg(not(stage0))]
 pub use intrinsics::copy;
 
-/// dox
-#[cfg(stage0)]
-#[stable(feature = "rust1", since = "1.0.0")]
-pub unsafe fn copy<T>(src: *const T, dst: *mut T, count: usize) {
-    intrinsics::copy(dst, src, count)
-}
-
-
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use intrinsics::write_bytes;
 
@@ -301,9 +284,10 @@ pub unsafe fn as_ref<'a>(&self) -> Option<&'a T> where T: Sized {
     ///
     /// # Safety
     ///
-    /// The offset must be in-bounds of the object, or one-byte-past-the-end.
-    /// Otherwise `offset` invokes Undefined Behaviour, regardless of whether
-    /// the pointer is used.
+    /// Both the starting and resulting pointer must be either in bounds or one
+    /// byte past the end of an allocated object. If either pointer is out of
+    /// bounds or arithmetic overflow occurs then
+    /// any further use of the returned value will result in undefined behavior.
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub unsafe fn offset(self, count: isize) -> *const T where T: Sized {
index 2866c193c3b1546a99f10736c0f4d11bade8343a..bb36630f1682f5ea1c1f869c7a907426509b6231 100644 (file)
@@ -11,6 +11,7 @@
 use core::iter::*;
 use core::iter::order::*;
 use core::iter::MinMaxResult::*;
+use core::isize;
 use core::usize;
 use core::cmp;
 
@@ -758,6 +759,11 @@ fn test_range() {
     assert_eq!((usize::MAX - 1..usize::MAX).size_hint(), (1, Some(1)));
     assert_eq!((-10..-1).size_hint(), (9, Some(9)));
     assert_eq!((-1..-10).size_hint(), (0, Some(0)));
+
+    assert_eq!((-70..58i8).size_hint(), (128, Some(128)));
+    assert_eq!((-128..127i8).size_hint(), (255, Some(255)));
+    assert_eq!((-2..isize::MAX).size_hint(),
+               (isize::MAX as usize + 2, Some(isize::MAX as usize + 2)));
 }
 
 #[test]
index e0e8e46af6cdde2a241b352e7d427013866a9ce9..1566972275284f3bf829f4cc5fee6041b68e8031 100644 (file)
@@ -13,7 +13,6 @@
 
 #![feature(box_syntax)]
 #![feature(unboxed_closures)]
-#![feature(unsafe_destructor)]
 #![feature(core)]
 #![feature(test)]
 #![feature(rand)]
index 569142c0d7dc9609d0e1f04d7b837c6fb3bf9458..66945ad251f1ed3dc9a68912aa699a0e2e44dcbe 100644 (file)
@@ -44,8 +44,7 @@ struct R {
        i: Rc<RefCell<isize>>,
     }
 
-    #[unsafe_destructor]
-    impl Drop for R {
+        impl Drop for R {
        fn drop(&mut self) {
             let ii = &*self.i;
             let i = *ii.borrow();
@@ -220,7 +219,6 @@ fn test_ord() {
     assert!(big > None);
 }
 
-/* FIXME(#20575)
 #[test]
 fn test_collect() {
     let v: Option<Vec<isize>> = (0..0).map(|_| Some(0)).collect();
@@ -242,28 +240,26 @@ fn test_collect() {
 
     assert!(v == None);
 }
-*/
+
 
 #[test]
 fn test_cloned() {
-    let val1 = 1u32;
-    let mut val2 = 2u32;
-    let val1_ref = &val1;
+    let val = 1u32;
+    let val_ref = &val;
     let opt_none: Option<&'static u32> = None;
-    let opt_ref = Some(&val1);
-    let opt_ref_ref = Some(&val1_ref);
-    let opt_mut_ref = Some(&mut val2);
+    let opt_ref = Some(&val);
+    let opt_ref_ref = Some(&val_ref);
 
     // None works
     assert_eq!(opt_none.clone(), None);
     assert_eq!(opt_none.cloned(), None);
 
     // Immutable ref works
-    assert_eq!(opt_ref.clone(), Some(&val1));
+    assert_eq!(opt_ref.clone(), Some(&val));
     assert_eq!(opt_ref.cloned(), Some(1u32));
 
     // Double Immutable ref works
-    assert_eq!(opt_ref_ref.clone(), Some(&val1_ref));
-    assert_eq!(opt_ref_ref.clone().cloned(), Some(&val1));
+    assert_eq!(opt_ref_ref.clone(), Some(&val_ref));
+    assert_eq!(opt_ref_ref.clone().cloned(), Some(&val));
     assert_eq!(opt_ref_ref.cloned().cloned(), Some(1u32));
 }
index ac8c2b953ae965d185873e429c84a5f547f93e29..3fdb102875332f7aa4b26db6993abfb9ab5c6151 100644 (file)
@@ -8,11 +8,11 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-pub fn op1() -> Result<isize, &'static str> { Ok(666) }
-pub fn op2() -> Result<isize, &'static str> { Err("sadface") }
+fn op1() -> Result<isize, &'static str> { Ok(666) }
+fn op2() -> Result<isize, &'static str> { Err("sadface") }
 
 #[test]
-pub fn test_and() {
+fn test_and() {
     assert_eq!(op1().and(Ok(667)).unwrap(), 667);
     assert_eq!(op1().and(Err::<i32, &'static str>("bad")).unwrap_err(),
                "bad");
@@ -23,7 +23,7 @@ pub fn test_and() {
 }
 
 #[test]
-pub fn test_and_then() {
+fn test_and_then() {
     assert_eq!(op1().and_then(|i| Ok::<isize, &'static str>(i + 1)).unwrap(), 667);
     assert_eq!(op1().and_then(|_| Err::<isize, &'static str>("bad")).unwrap_err(),
                "bad");
@@ -35,7 +35,7 @@ pub fn test_and_then() {
 }
 
 #[test]
-pub fn test_or() {
+fn test_or() {
     assert_eq!(op1().or(Ok::<_, &'static str>(667)).unwrap(), 666);
     assert_eq!(op1().or(Err("bad")).unwrap(), 666);
 
@@ -44,7 +44,7 @@ pub fn test_or() {
 }
 
 #[test]
-pub fn test_or_else() {
+fn test_or_else() {
     assert_eq!(op1().or_else(|_| Ok::<isize, &'static str>(667)).unwrap(), 666);
     assert_eq!(op1().or_else(|e| Err::<isize, &'static str>(e)).unwrap(), 666);
 
@@ -54,18 +54,17 @@ pub fn test_or_else() {
 }
 
 #[test]
-pub fn test_impl_map() {
+fn test_impl_map() {
     assert!(Ok::<isize, isize>(1).map(|x| x + 1) == Ok(2));
     assert!(Err::<isize, isize>(1).map(|x| x + 1) == Err(1));
 }
 
 #[test]
-pub fn test_impl_map_err() {
+fn test_impl_map_err() {
     assert!(Ok::<isize, isize>(1).map_err(|x| x + 1) == Ok(1));
     assert!(Err::<isize, isize>(1).map_err(|x| x + 1) == Err(2));
 }
 
-/* FIXME(#20575)
 #[test]
 fn test_collect() {
     let v: Result<Vec<isize>, ()> = (0..0).map(|_| Ok::<isize, ()>(0)).collect();
@@ -86,10 +85,9 @@ fn test_collect() {
     let v: Result<Vec<()>, isize> = functions.iter_mut().map(|f| (*f)()).collect();
     assert!(v == Err(1));
 }
-*/
 
 #[test]
-pub fn test_fmt_default() {
+fn test_fmt_default() {
     let ok: Result<isize, &'static str> = Ok(100);
     let err: Result<isize, &'static str> = Err("Err");
 
@@ -100,7 +98,7 @@ pub fn test_fmt_default() {
 }
 
 #[test]
-pub fn test_unwrap_or() {
+fn test_unwrap_or() {
     let ok: Result<isize, &'static str> = Ok(100);
     let ok_err: Result<isize, &'static str> = Err("Err");
 
@@ -109,7 +107,7 @@ pub fn test_unwrap_or() {
 }
 
 #[test]
-pub fn test_unwrap_or_else() {
+fn test_unwrap_or_else() {
     fn handler(msg: &'static str) -> isize {
         if msg == "I got this." {
             50
index 4fbcdaa378e25cef101fcc258c5b695266fa536a..999e7c643e576b0b4aa0a3d9f977fc133d75af88 100644 (file)
 
 // On NaCl, these libraries are static. Thus it would be a Bad Idea to link them
 // in when creating a test crate.
-#[cfg(not(any(windows, all(target_os = "nacl", test))))]
+#[cfg(not(any(windows, target_env = "musl", all(target_os = "nacl", test))))]
 #[link(name = "c")]
 #[link(name = "m")]
 extern {}
 
+#[cfg(all(target_env = "musl", not(test)))]
+#[link(name = "c", kind = "static")]
+extern {}
+
 // libnacl provides functions that require a trip through the IRT to work.
 // ie: _exit, mmap, nanosleep, etc. Anything that would otherwise require a trip
 // to the kernel.
index 31812e19aee86d4c90bff5c5ad55a6aee9784cff..2ef9dfd4da8dae56fff54612e90165a321bb0c27 100644 (file)
@@ -71,7 +71,7 @@ The rustc crate itself consists of the following submodules
 - util: ubiquitous types and helper functions
 - lib: bindings to LLVM
 
-The entry-point for the compiler is main() in the librustc_trans
+The entry-point for the compiler is main() in the librustc_driver
 crate.
 
 The 3 central data structures:
index 182405a640dbcfb2d506607c6c6194f355c5c06e..a363c483579f7f127d3171aaaeeeb2968c0b8097 100644 (file)
@@ -168,6 +168,31 @@ struct X { x: (), }
 ```
 "##,
 
+E0010: r##"
+The value of statics and constants must be known at compile time, and they live
+for the entire lifetime of a program. Creating a boxed value allocates memory on
+the heap at runtime, and therefore cannot be done at compile time.
+"##,
+
+E0013: r##"
+Static and const variables can refer to other const variables. But a const
+variable cannot refer to a static variable. For example, `Y` cannot refer to `X`
+here:
+
+```
+static X: i32 = 42;
+const Y: i32 = X;
+```
+
+To fix this, the value can be extracted as a const and then used:
+
+```
+const A: i32 = 42;
+static X: i32 = A;
+const Y: i32 = A;
+```
+"##,
+
 E0015: r##"
 The only function calls allowed in static or constant expressions are enum
 variant constructors or struct constructors (for unit or tuple structs). This
@@ -336,6 +361,22 @@ enum Method { GET, POST }
 ```
 "##,
 
+E0265: r##"
+This error indicates that a static or constant references itself.
+All statics and constants need to resolve to a value in an acyclic manner.
+
+For example, neither of the following can be sensibly compiled:
+
+```
+const X: u32 = X;
+```
+
+```
+const X: u32 = Y;
+const Y: u32 = X;
+```
+"##,
+
 E0267: r##"
 This error indicates the use of loop keyword (break or continue) inside a
 closure but outside of any loop. Break and continue can be used as normal
@@ -459,10 +500,8 @@ enum Method { GET, POST }
 }
 
 register_diagnostics! {
-    E0010,
     E0011,
     E0012,
-    E0013,
     E0014,
     E0016,
     E0017,
@@ -482,7 +521,6 @@ enum Method { GET, POST }
     E0262, // illegal lifetime parameter name
     E0263, // lifetime name declared twice in same scope
     E0264, // unknown external lang item
-    E0265, // recursive constant
     E0266, // expected item
     E0269, // not all control paths return a value
     E0270, // computation may converge in a function marked as diverging
@@ -517,5 +555,3 @@ enum Method { GET, POST }
     E0316, // nested quantification of lifetimes
     E0370  // discriminant overflow
 }
-
-__build_diagnostic_array! { DIAGNOSTICS }
index d4012f2057b5dac8306e189e3401d6bc9b6a981c..5bd3759a6e04e5386fadf522afb4aa21a5c74077 100644 (file)
       html_favicon_url = "http://www.rust-lang.org/favicon.ico",
       html_root_url = "http://doc.rust-lang.org/nightly/")]
 
+#![feature(associated_consts)]
 #![feature(box_patterns)]
 #![feature(box_syntax)]
 #![feature(collections)]
 #![feature(core)]
+#![feature(fs_canonicalize)]
 #![feature(hash)]
+#![feature(into_cow)]
 #![feature(libc)]
+#![feature(path_ext)]
 #![feature(quote)]
 #![feature(rustc_diagnostic_macros)]
 #![feature(rustc_private)]
-#![feature(unsafe_destructor)]
+#![feature(slice_patterns)]
 #![feature(staged_api)]
 #![feature(std_misc)]
-#![feature(path_ext)]
 #![feature(str_char)]
-#![feature(into_cow)]
-#![feature(slice_patterns)]
 #![cfg_attr(test, feature(test))]
 
 #![allow(trivial_casts)]
@@ -139,7 +140,6 @@ pub mod middle {
 pub mod lint;
 
 pub mod util {
-    pub use rustc_back::fs;
     pub use rustc_back::sha2;
 
     pub mod common;
@@ -161,3 +161,9 @@ pub mod lib {
 mod rustc {
     pub use lint;
 }
+
+// Build the diagnostics array at the end so that the metadata includes error use sites.
+#[cfg(stage0)]
+__build_diagnostic_array! { DIAGNOSTICS }
+#[cfg(not(stage0))]
+__build_diagnostic_array! { librustc, DIAGNOSTICS }
index 802c5815398f2c4398c25b24dd50d8594c491177..12112fd45ebe9b2d0911992f79cc1e7bd4c0b38e 100644 (file)
 use metadata::loader;
 use metadata::loader::CratePaths;
 
-use std::path::{Path, PathBuf};
+use std::path::PathBuf;
 use std::rc::Rc;
+use std::fs;
+
 use syntax::ast;
 use syntax::abi;
 use syntax::attr;
@@ -32,7 +34,6 @@
 use syntax::parse::token::InternedString;
 use syntax::parse::token;
 use syntax::visit;
-use util::fs;
 use log;
 
 pub struct CrateReader<'a> {
@@ -322,7 +323,7 @@ fn existing_match(&self, name: &str, hash: Option<&Svh>, kind: PathKind)
             let source = self.sess.cstore.get_used_crate_source(cnum).unwrap();
             if let Some(locs) = self.sess.opts.externs.get(name) {
                 let found = locs.iter().any(|l| {
-                    let l = fs::realpath(&Path::new(&l[..])).ok();
+                    let l = fs::canonicalize(l).ok();
                     source.dylib.as_ref().map(|p| &p.0) == l.as_ref() ||
                     source.rlib.as_ref().map(|p| &p.0) == l.as_ref()
                 });
@@ -664,7 +665,7 @@ fn import_codemap(local_codemap: &codemap::CodeMap,
                     .into_inner()
                     .map_in_place(|mbc|
                         codemap::MultiByteChar {
-                            pos: mbc.pos + start_pos,
+                            pos: mbc.pos - start_pos,
                             bytes: mbc.bytes
                         });
 
index 1567f4b99475cb1fe345e0f1983f487cb695e12b..7d8cf5b22a9016c6b9dec3ff8a61b147a6ee6ca5 100644 (file)
@@ -18,7 +18,6 @@
 use std::io::prelude::*;
 use std::path::{Path, PathBuf};
 
-use util::fs as myfs;
 use session::search_paths::{SearchPaths, PathKind};
 
 #[derive(Copy, Clone)]
@@ -191,7 +190,7 @@ pub fn get_or_default_sysroot() -> PathBuf {
     // Follow symlinks.  If the resolved path is relative, make it absolute.
     fn canonicalize(path: Option<PathBuf>) -> Option<PathBuf> {
         path.and_then(|path| {
-            match myfs::realpath(&path) {
+            match fs::canonicalize(&path) {
                 Ok(canon) => Some(canon),
                 Err(e) => panic!("failed to get realpath: {}", e),
             }
index bbb2452ca29ee84d7334c1962b52e224859b849e..062a156637a358d1af5b286c08aad6791f02281f 100644 (file)
 use metadata::filesearch::{FileSearch, FileMatches, FileDoesntMatch};
 use syntax::codemap::Span;
 use syntax::diagnostic::SpanHandler;
-use util::fs;
 use util::common;
 use rustc_back::target::Target;
 
 use std::cmp;
 use std::collections::HashMap;
+use std::fs;
 use std::io::prelude::*;
 use std::io;
 use std::path::{Path, PathBuf};
@@ -430,9 +430,9 @@ fn find_library_crate(&mut self) -> Option<Library> {
                                  .or_insert_with(|| (HashMap::new(), HashMap::new()));
             let (ref mut rlibs, ref mut dylibs) = *slot;
             if rlib {
-                rlibs.insert(fs::realpath(path).unwrap(), kind);
+                rlibs.insert(fs::canonicalize(path).unwrap(), kind);
             } else {
-                dylibs.insert(fs::realpath(path).unwrap(), kind);
+                dylibs.insert(fs::canonicalize(path).unwrap(), kind);
             }
 
             FileMatches
@@ -660,10 +660,10 @@ fn find_commandline_library(&mut self, locs: &[String]) -> Option<Library> {
             // there's at most one rlib and at most one dylib.
             for loc in locs {
                 if loc.file_name().unwrap().to_str().unwrap().ends_with(".rlib") {
-                    rlibs.insert(fs::realpath(&loc).unwrap(),
+                    rlibs.insert(fs::canonicalize(&loc).unwrap(),
                                  PathKind::ExternFlag);
                 } else {
-                    dylibs.insert(fs::realpath(&loc).unwrap(),
+                    dylibs.insert(fs::canonicalize(&loc).unwrap(),
                                   PathKind::ExternFlag);
                 }
             }
index 80326229618c23d05a28312c194c8506cc6675a6..5b0eea6bcc51678466a24364db67707f4ef8b08b 100644 (file)
     #[derive(RustcEncodable, RustcDecodable)]
     flags ConstQualif: u8 {
         // Const rvalue which can be placed behind a reference.
-        const PURE_CONST          = 0b000000,
+        const PURE_CONST         0,
         // Inner mutability (can not be placed behind a reference) or behind
         // &mut in a non-global expression. Can be copied from static memory.
-        const MUTABLE_MEM         = 0b000001,
+        const MUTABLE_MEM        = 1 << 0,
         // Constant value with a type that implements Drop. Can be copied
         // from static memory, similar to MUTABLE_MEM.
-        const NEEDS_DROP          = 0b000010,
+        const NEEDS_DROP         = 1 << 1,
         // Even if the value can be placed in static memory, copying it from
         // there is more expensive than in-place instantiation, and/or it may
         // be too large. This applies to [T; N] and everything containing it.
         // N.B.: references need to clear this flag to not end up on the stack.
-        const PREFER_IN_PLACE     = 0b000100,
+        const PREFER_IN_PLACE    = 1 << 2,
         // May use more than 0 bytes of memory, doesn't impact the constness
         // directly, but is not allowed to be borrowed mutably in a constant.
-        const NON_ZERO_SIZED      = 0b001000,
+        const NON_ZERO_SIZED     = 1 << 3,
         // Actually borrowed, has to always be in static memory. Does not
         // propagate, and requires the expression to behave like a 'static
         // lvalue. The set of expressions with this flag is the minimum
         // that have to be promoted.
-        const HAS_STATIC_BORROWS  = 0b010000,
+        const HAS_STATIC_BORROWS = 1 << 4,
         // Invalid const for miscellaneous reasons (e.g. not implemented).
-        const NOT_CONST           = 0b100000,
+        const NOT_CONST          = 1 << 5,
 
         // Borrowing the expression won't produce &'static T if any of these
         // bits are set, though the value could be copied from static memory
         // if `NOT_CONST` isn't set.
-        const NON_STATIC_BORROWS = MUTABLE_MEM.bits | NEEDS_DROP.bits | NOT_CONST.bits
+        const NON_STATIC_BORROWS = ConstQualif::MUTABLE_MEM.bits |
+                                   ConstQualif::NEEDS_DROP.bits |
+                                   ConstQualif::NOT_CONST.bits
     }
 }
 
@@ -102,7 +104,7 @@ fn with_mode<F, R>(&mut self, mode: Mode, f: F) -> R where
     {
         let (old_mode, old_qualif) = (self.mode, self.qualif);
         self.mode = mode;
-        self.qualif = PURE_CONST;
+        self.qualif = ConstQualif::PURE_CONST;
         let r = f(self);
         self.mode = old_mode;
         self.qualif = old_qualif;
@@ -126,7 +128,7 @@ fn global_expr(&mut self, mode: Mode, expr: &ast::Expr) -> ConstQualif {
             Entry::Occupied(entry) => return *entry.get(),
             Entry::Vacant(entry) => {
                 // Prevent infinite recursion on re-entry.
-                entry.insert(PURE_CONST);
+                entry.insert(ConstQualif::PURE_CONST);
             }
         }
         self.with_mode(mode, |this| {
@@ -271,7 +273,7 @@ fn visit_pat(&mut self, p: &ast::Pat) {
 
     fn visit_expr(&mut self, ex: &ast::Expr) {
         let mut outer = self.qualif;
-        self.qualif = PURE_CONST;
+        self.qualif = ConstQualif::PURE_CONST;
 
         let node_ty = ty::node_id_to_type(self.tcx, ex.id);
         check_expr(self, ex, node_ty);
@@ -287,7 +289,7 @@ fn visit_expr(&mut self, ex: &ast::Expr) {
                 self.visit_expr(&**callee);
                 // The callee's size doesn't count in the call.
                 let added = self.qualif - inner;
-                self.qualif = inner | (added - NON_ZERO_SIZED);
+                self.qualif = inner | (added - ConstQualif::NON_ZERO_SIZED);
             }
             ast::ExprRepeat(ref element, _) => {
                 self.visit_expr(&**element);
@@ -298,7 +300,7 @@ fn visit_expr(&mut self, ex: &ast::Expr) {
                 };
                 // [element; 0] is always zero-sized.
                 if count == 0 {
-                    self.qualif = self.qualif - (NON_ZERO_SIZED | PREFER_IN_PLACE);
+                    self.qualif.remove(ConstQualif::NON_ZERO_SIZED | ConstQualif::PREFER_IN_PLACE);
                 }
             }
             ast::ExprMatch(ref discr, ref arms, _) => {
@@ -325,7 +327,7 @@ fn visit_expr(&mut self, ex: &ast::Expr) {
                 let div_or_rem = op.node == ast::BiDiv || op.node == ast::BiRem;
                 match node_ty.sty {
                     ty::ty_uint(_) | ty::ty_int(_) if div_or_rem => {
-                        if !self.qualif.intersects(NOT_CONST) {
+                        if !self.qualif.intersects(ConstQualif::NOT_CONST) {
                             match const_eval::eval_const_expr_partial(self.tcx, ex, None) {
                                 Ok(_) => {}
                                 Err(msg) => {
@@ -348,11 +350,11 @@ fn visit_expr(&mut self, ex: &ast::Expr) {
                 // Constants cannot be borrowed if they contain interior mutability as
                 // it means that our "silent insertion of statics" could change
                 // initializer values (very bad).
-                // If the type doesn't have interior mutability, then `MUTABLE_MEM` has
+                // If the type doesn't have interior mutability, then `ConstQualif::MUTABLE_MEM` has
                 // propagated from another error, so erroring again would be just noise.
                 let tc = ty::type_contents(self.tcx, node_ty);
-                if self.qualif.intersects(MUTABLE_MEM) && tc.interior_unsafe() {
-                    outer = outer | NOT_CONST;
+                if self.qualif.intersects(ConstQualif::MUTABLE_MEM) && tc.interior_unsafe() {
+                    outer = outer | ConstQualif::NOT_CONST;
                     if self.mode != Mode::Var {
                         self.tcx.sess.span_err(ex.span,
                             "cannot borrow a constant which contains \
@@ -361,32 +363,32 @@ fn visit_expr(&mut self, ex: &ast::Expr) {
                 }
                 // If the reference has to be 'static, avoid in-place initialization
                 // as that will end up pointing to the stack instead.
-                if !self.qualif.intersects(NON_STATIC_BORROWS) {
-                    self.qualif = self.qualif - PREFER_IN_PLACE;
-                    self.add_qualif(HAS_STATIC_BORROWS);
+                if !self.qualif.intersects(ConstQualif::NON_STATIC_BORROWS) {
+                    self.qualif = self.qualif - ConstQualif::PREFER_IN_PLACE;
+                    self.add_qualif(ConstQualif::HAS_STATIC_BORROWS);
                 }
             }
             Some(ast::MutMutable) => {
                 // `&mut expr` means expr could be mutated, unless it's zero-sized.
-                if self.qualif.intersects(NON_ZERO_SIZED) {
+                if self.qualif.intersects(ConstQualif::NON_ZERO_SIZED) {
                     if self.mode == Mode::Var {
-                        outer = outer | NOT_CONST;
-                        self.add_qualif(MUTABLE_MEM);
+                        outer = outer | ConstQualif::NOT_CONST;
+                        self.add_qualif(ConstQualif::MUTABLE_MEM);
                     } else {
                         span_err!(self.tcx.sess, ex.span, E0017,
                             "references in {}s may only refer \
                              to immutable values", self.msg())
                     }
                 }
-                if !self.qualif.intersects(NON_STATIC_BORROWS) {
-                    self.add_qualif(HAS_STATIC_BORROWS);
+                if !self.qualif.intersects(ConstQualif::NON_STATIC_BORROWS) {
+                    self.add_qualif(ConstQualif::HAS_STATIC_BORROWS);
                 }
             }
             None => {}
         }
         self.tcx.const_qualif_map.borrow_mut().insert(ex.id, self.qualif);
         // Don't propagate certain flags.
-        self.qualif = outer | (self.qualif - HAS_STATIC_BORROWS);
+        self.qualif = outer | (self.qualif - ConstQualif::HAS_STATIC_BORROWS);
     }
 }
 
@@ -401,7 +403,7 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>,
     match node_ty.sty {
         ty::ty_struct(did, _) |
         ty::ty_enum(did, _) if ty::has_dtor(v.tcx, did) => {
-            v.add_qualif(NEEDS_DROP);
+            v.add_qualif(ConstQualif::NEEDS_DROP);
             if v.mode != Mode::Var {
                 v.tcx.sess.span_err(e.span,
                                     &format!("{}s are not allowed to have destructors",
@@ -416,7 +418,7 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>,
         ast::ExprUnary(..) |
         ast::ExprBinary(..) |
         ast::ExprIndex(..) if v.tcx.method_map.borrow().contains_key(&method_call) => {
-            v.add_qualif(NOT_CONST);
+            v.add_qualif(ConstQualif::NOT_CONST);
             if v.mode != Mode::Var {
                 span_err!(v.tcx.sess, e.span, E0011,
                             "user-defined operators are not allowed in {}s", v.msg());
@@ -424,7 +426,7 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>,
         }
         ast::ExprBox(..) |
         ast::ExprUnary(ast::UnUniq, _) => {
-            v.add_qualif(NOT_CONST);
+            v.add_qualif(ConstQualif::NOT_CONST);
             if v.mode != Mode::Var {
                 span_err!(v.tcx.sess, e.span, E0010,
                           "allocations are not allowed in {}s", v.msg());
@@ -434,7 +436,7 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>,
             match ty::node_id_to_type(v.tcx, ptr.id).sty {
                 ty::ty_ptr(_) => {
                     // This shouldn't be allowed in constants at all.
-                    v.add_qualif(NOT_CONST);
+                    v.add_qualif(ConstQualif::NOT_CONST);
                 }
                 _ => {}
             }
@@ -447,7 +449,7 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>,
                 ty::type_is_unsafe_ptr(toty) ||
                 (ty::type_is_bare_fn(toty) && ty::type_is_bare_fn_item(fromty));
             if !is_legal_cast {
-                v.add_qualif(NOT_CONST);
+                v.add_qualif(ConstQualif::NOT_CONST);
                 if v.mode != Mode::Var {
                     span_err!(v.tcx.sess, e.span, E0012,
                               "can not cast to `{}` in {}s",
@@ -455,7 +457,7 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>,
                 }
             }
             if ty::type_is_unsafe_ptr(fromty) && ty::type_is_numeric(toty) {
-                v.add_qualif(NOT_CONST);
+                v.add_qualif(ConstQualif::NOT_CONST);
                 if v.mode != Mode::Var {
                     span_err!(v.tcx.sess, e.span, E0018,
                               "can not cast a pointer to an integer in {}s", v.msg());
@@ -467,17 +469,17 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>,
             match def {
                 Some(def::DefVariant(_, _, _)) => {
                     // Count the discriminator or function pointer.
-                    v.add_qualif(NON_ZERO_SIZED);
+                    v.add_qualif(ConstQualif::NON_ZERO_SIZED);
                 }
                 Some(def::DefStruct(_)) => {
                     if let ty::ty_bare_fn(..) = node_ty.sty {
                         // Count the function pointer.
-                        v.add_qualif(NON_ZERO_SIZED);
+                        v.add_qualif(ConstQualif::NON_ZERO_SIZED);
                     }
                 }
                 Some(def::DefFn(..)) | Some(def::DefMethod(..)) => {
                     // Count the function pointer.
-                    v.add_qualif(NON_ZERO_SIZED);
+                    v.add_qualif(ConstQualif::NON_ZERO_SIZED);
                 }
                 Some(def::DefStatic(..)) => {
                     match v.mode {
@@ -487,7 +489,7 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>,
                                 "constants cannot refer to other statics, \
                                  insert an intermediate constant instead");
                         }
-                        Mode::Var => v.add_qualif(NOT_CONST)
+                        Mode::Var => v.add_qualif(ConstQualif::NOT_CONST)
                     }
                 }
                 Some(def::DefConst(did)) |
@@ -503,7 +505,7 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>,
                     }
                 }
                 def => {
-                    v.add_qualif(NOT_CONST);
+                    v.add_qualif(ConstQualif::NOT_CONST);
                     if v.mode != Mode::Var {
                         debug!("(checking const) found bad def: {:?}", def);
                         span_err!(v.tcx.sess, e.span, E0014,
@@ -530,10 +532,10 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>,
                 Some(def::DefStruct(..)) => {}
                 Some(def::DefVariant(..)) => {
                     // Count the discriminator.
-                    v.add_qualif(NON_ZERO_SIZED);
+                    v.add_qualif(ConstQualif::NON_ZERO_SIZED);
                 }
                 _ => {
-                    v.add_qualif(NOT_CONST);
+                    v.add_qualif(ConstQualif::NOT_CONST);
                     if v.mode != Mode::Var {
                         span_err!(v.tcx.sess, e.span, E0015,
                                   "function calls in {}s are limited to \
@@ -545,7 +547,7 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>,
         ast::ExprBlock(ref block) => {
             // Check all statements in the block
             let mut block_span_err = |span| {
-                v.add_qualif(NOT_CONST);
+                v.add_qualif(ConstQualif::NOT_CONST);
                 if v.mode != Mode::Var {
                     span_err!(v.tcx.sess, span, E0016,
                               "blocks in {}s are limited to items and \
@@ -574,17 +576,17 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>,
         ast::ExprStruct(..) => {
             let did = v.tcx.def_map.borrow().get(&e.id).map(|def| def.def_id());
             if did == v.tcx.lang_items.unsafe_cell_type() {
-                v.add_qualif(MUTABLE_MEM);
+                v.add_qualif(ConstQualif::MUTABLE_MEM);
             }
         }
 
         ast::ExprLit(_) |
         ast::ExprAddrOf(..) => {
-            v.add_qualif(NON_ZERO_SIZED);
+            v.add_qualif(ConstQualif::NON_ZERO_SIZED);
         }
 
         ast::ExprRepeat(..) => {
-            v.add_qualif(PREFER_IN_PLACE);
+            v.add_qualif(ConstQualif::PREFER_IN_PLACE);
         }
 
         ast::ExprClosure(..) => {
@@ -593,7 +595,7 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>,
             if ty::with_freevars(v.tcx, e.id, |fv| !fv.is_empty()) {
                 assert!(v.mode == Mode::Var,
                         "global closures can't capture anything");
-                v.add_qualif(NOT_CONST);
+                v.add_qualif(ConstQualif::NOT_CONST);
             }
         }
 
@@ -631,7 +633,7 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>,
         ast::ExprAssignOp(..) |
         ast::ExprInlineAsm(_) |
         ast::ExprMac(_) => {
-            v.add_qualif(NOT_CONST);
+            v.add_qualif(ConstQualif::NOT_CONST);
             if v.mode != Mode::Var {
                 span_err!(v.tcx.sess, e.span, E0019,
                           "{} contains unimplemented expression type", v.msg());
@@ -644,7 +646,7 @@ pub fn check_crate(tcx: &ty::ctxt) {
     visit::walk_crate(&mut CheckCrateVisitor {
         tcx: tcx,
         mode: Mode::Var,
-        qualif: NOT_CONST,
+        qualif: ConstQualif::NOT_CONST,
         rvalue_borrows: NodeMap()
     }, tcx.map.krate());
 
index 587194bafada48acfa17742614d982f44821f933..c4ab89e3b4da07ef0de3663309127aeda946a7b9 100644 (file)
@@ -838,20 +838,20 @@ pub fn cat_rvalue_node(&self,
                            expr_ty: Ty<'tcx>)
                            -> cmt<'tcx> {
         let qualif = self.tcx().const_qualif_map.borrow().get(&id).cloned()
-                               .unwrap_or(check_const::NOT_CONST);
+                               .unwrap_or(check_const::ConstQualif::NOT_CONST);
 
         // Only promote `[T; 0]` before an RFC for rvalue promotions
         // is accepted.
         let qualif = match expr_ty.sty {
             ty::ty_vec(_, Some(0)) => qualif,
-            _ => check_const::NOT_CONST
+            _ => check_const::ConstQualif::NOT_CONST
         };
 
         // Compute maximum lifetime of this rvalue. This is 'static if
         // we can promote to a constant, otherwise equal to enclosing temp
         // lifetime.
-        let re = match qualif & check_const::NON_STATIC_BORROWS {
-            check_const::PURE_CONST => ty::ReStatic,
+        let re = match qualif & check_const::ConstQualif::NON_STATIC_BORROWS {
+            check_const::ConstQualif::PURE_CONST => ty::ReStatic,
             _ => self.temporary_scope(id),
         };
         let ret = self.cat_rvalue(id, span, re, expr_ty);
index f172815a4d1437734225dd399aea80ad4c07f16b..33ba21bc7b15445c16a860328e2ca10e8f2f8b01 100644 (file)
@@ -848,16 +848,18 @@ pub fn free_region_map(&self, id: NodeId) -> FreeRegionMap {
 // recursing over the type itself.
 bitflags! {
     flags TypeFlags: u32 {
-        const NO_TYPE_FLAGS       = 0b0,
-        const HAS_PARAMS          = 0b1,
-        const HAS_SELF            = 0b10,
-        const HAS_TY_INFER        = 0b100,
-        const HAS_RE_INFER        = 0b1000,
-        const HAS_RE_LATE_BOUND   = 0b10000,
-        const HAS_REGIONS         = 0b100000,
-        const HAS_TY_ERR          = 0b1000000,
-        const HAS_PROJECTION      = 0b10000000,
-        const NEEDS_SUBST   = HAS_PARAMS.bits | HAS_SELF.bits | HAS_REGIONS.bits,
+        const NO_TYPE_FLAGS     = 0,
+        const HAS_PARAMS        = 1 << 0,
+        const HAS_SELF          = 1 << 1,
+        const HAS_TY_INFER      = 1 << 2,
+        const HAS_RE_INFER      = 1 << 3,
+        const HAS_RE_LATE_BOUND = 1 << 4,
+        const HAS_REGIONS       = 1 << 5,
+        const HAS_TY_ERR        = 1 << 6,
+        const HAS_PROJECTION    = 1 << 7,
+        const NEEDS_SUBST       = TypeFlags::HAS_PARAMS.bits |
+                                  TypeFlags::HAS_SELF.bits |
+                                  TypeFlags::HAS_REGIONS.bits,
     }
 }
 
@@ -890,8 +892,8 @@ pub fn go(tcx: &ty::ctxt) {
                         ty::ty_err => /* unimportant */ continue,
                         $(ty::$variant(..) => &mut $variant,)*
                     };
-                    let region = t.flags.intersects(ty::HAS_RE_INFER);
-                    let ty = t.flags.intersects(ty::HAS_TY_INFER);
+                    let region = t.flags.intersects(ty::TypeFlags::HAS_RE_INFER);
+                    let ty = t.flags.intersects(ty::TypeFlags::HAS_TY_INFER);
 
                     variant.total += 1;
                     total.total += 1;
@@ -993,23 +995,23 @@ fn borrow<'a>(&'a self) -> &'a sty<'tcx> {
 }
 
 pub fn type_has_params(ty: Ty) -> bool {
-    ty.flags.intersects(HAS_PARAMS)
+    ty.flags.intersects(TypeFlags::HAS_PARAMS)
 }
 pub fn type_has_self(ty: Ty) -> bool {
-    ty.flags.intersects(HAS_SELF)
+    ty.flags.intersects(TypeFlags::HAS_SELF)
 }
 pub fn type_has_ty_infer(ty: Ty) -> bool {
-    ty.flags.intersects(HAS_TY_INFER)
+    ty.flags.intersects(TypeFlags::HAS_TY_INFER)
 }
 pub fn type_needs_infer(ty: Ty) -> bool {
-    ty.flags.intersects(HAS_TY_INFER | HAS_RE_INFER)
+    ty.flags.intersects(TypeFlags::HAS_TY_INFER | TypeFlags::HAS_RE_INFER)
 }
 pub fn type_has_projection(ty: Ty) -> bool {
-    ty.flags.intersects(HAS_PROJECTION)
+    ty.flags.intersects(TypeFlags::HAS_PROJECTION)
 }
 
 pub fn type_has_late_bound_regions(ty: Ty) -> bool {
-    ty.flags.intersects(HAS_RE_LATE_BOUND)
+    ty.flags.intersects(TypeFlags::HAS_RE_LATE_BOUND)
 }
 
 /// An "escaping region" is a bound region whose binder is not part of `t`.
@@ -2810,7 +2812,7 @@ struct FlagComputation {
 
 impl FlagComputation {
     fn new() -> FlagComputation {
-        FlagComputation { flags: NO_TYPE_FLAGS, depth: 0 }
+        FlagComputation { flags: TypeFlags::NO_TYPE_FLAGS, depth: 0 }
     }
 
     fn for_sty(st: &sty) -> FlagComputation {
@@ -2855,20 +2857,20 @@ fn add_sty(&mut self, st: &sty) {
 
             // You might think that we could just return ty_err for
             // any type containing ty_err as a component, and get
-            // rid of the HAS_TY_ERR flag -- likewise for ty_bot (with
+            // rid of the TypeFlags::HAS_TY_ERR flag -- likewise for ty_bot (with
             // the exception of function types that return bot).
             // But doing so caused sporadic memory corruption, and
             // neither I (tjc) nor nmatsakis could figure out why,
             // so we're doing it this way.
             &ty_err => {
-                self.add_flags(HAS_TY_ERR)
+                self.add_flags(TypeFlags::HAS_TY_ERR)
             }
 
             &ty_param(ref p) => {
                 if p.space == subst::SelfSpace {
-                    self.add_flags(HAS_SELF);
+                    self.add_flags(TypeFlags::HAS_SELF);
                 } else {
-                    self.add_flags(HAS_PARAMS);
+                    self.add_flags(TypeFlags::HAS_PARAMS);
                 }
             }
 
@@ -2877,7 +2879,7 @@ fn add_sty(&mut self, st: &sty) {
             }
 
             &ty_infer(_) => {
-                self.add_flags(HAS_TY_INFER)
+                self.add_flags(TypeFlags::HAS_TY_INFER)
             }
 
             &ty_enum(_, substs) | &ty_struct(_, substs) => {
@@ -2885,7 +2887,7 @@ fn add_sty(&mut self, st: &sty) {
             }
 
             &ty_projection(ref data) => {
-                self.add_flags(HAS_PROJECTION);
+                self.add_flags(TypeFlags::HAS_PROJECTION);
                 self.add_projection_ty(data);
             }
 
@@ -2949,11 +2951,11 @@ fn add_fn_sig(&mut self, fn_sig: &PolyFnSig) {
     }
 
     fn add_region(&mut self, r: Region) {
-        self.add_flags(HAS_REGIONS);
+        self.add_flags(TypeFlags::HAS_REGIONS);
         match r {
-            ty::ReInfer(_) => { self.add_flags(HAS_RE_INFER); }
+            ty::ReInfer(_) => { self.add_flags(TypeFlags::HAS_RE_INFER); }
             ty::ReLateBound(debruijn, _) => {
-                self.add_flags(HAS_RE_LATE_BOUND);
+                self.add_flags(TypeFlags::HAS_RE_LATE_BOUND);
                 self.add_depth(debruijn.depth);
             }
             _ => { }
@@ -3307,11 +3309,11 @@ pub fn type_is_nil(ty: Ty) -> bool {
 }
 
 pub fn type_is_error(ty: Ty) -> bool {
-    ty.flags.intersects(HAS_TY_ERR)
+    ty.flags.intersects(TypeFlags::HAS_TY_ERR)
 }
 
 pub fn type_needs_subst(ty: Ty) -> bool {
-    ty.flags.intersects(NEEDS_SUBST)
+    ty.flags.intersects(TypeFlags::NEEDS_SUBST)
 }
 
 pub fn trait_ref_contains_error(tref: &ty::TraitRef) -> bool {
index 050ccd6471288ae759c4570657b68f624eec40ea..b999929c4af9e4a5a24d75e4c15042865f9aa1ae 100644 (file)
@@ -621,6 +621,7 @@ pub fn default_configuration(sess: &Session) -> ast::CrateConfig {
     let arch = &sess.target.target.arch;
     let wordsz = &sess.target.target.target_pointer_width;
     let os = &sess.target.target.target_os;
+    let env = &sess.target.target.target_env;
 
     let fam = match sess.target.target.options.is_like_windows {
         true  => InternedString::new("windows"),
@@ -634,8 +635,8 @@ pub fn default_configuration(sess: &Session) -> ast::CrateConfig {
          mk(InternedString::new("target_family"), fam),
          mk(InternedString::new("target_arch"), intern(arch)),
          mk(InternedString::new("target_endian"), intern(end)),
-         mk(InternedString::new("target_pointer_width"),
-            intern(wordsz))
+         mk(InternedString::new("target_pointer_width"), intern(wordsz)),
+         mk(InternedString::new("target_env"), intern(env)),
     ];
     if sess.opts.debug_assertions {
         ret.push(attr::mk_word_item(InternedString::new("debug_assertions")));
@@ -754,11 +755,14 @@ pub fn     opt(a: S, b: S, c: S, d: S) -> R { stable(getopts::optopt(a, b, c, d)
     pub fn   multi(a: S, b: S, c: S, d: S) -> R { stable(getopts::optmulti(a, b, c, d)) }
     pub fn    flag(a: S, b: S, c: S)       -> R { stable(getopts::optflag(a, b, c)) }
     pub fn flagopt(a: S, b: S, c: S, d: S) -> R { stable(getopts::optflagopt(a, b, c, d)) }
+    pub fn flagmulti(a: S, b: S, c: S)     -> R { stable(getopts::optflagmulti(a, b, c)) }
+
 
     pub fn     opt_u(a: S, b: S, c: S, d: S) -> R { unstable(getopts::optopt(a, b, c, d)) }
     pub fn   multi_u(a: S, b: S, c: S, d: S) -> R { unstable(getopts::optmulti(a, b, c, d)) }
     pub fn    flag_u(a: S, b: S, c: S)       -> R { unstable(getopts::optflag(a, b, c)) }
     pub fn flagopt_u(a: S, b: S, c: S, d: S) -> R { unstable(getopts::optflagopt(a, b, c, d)) }
+    pub fn flagmulti_u(a: S, b: S, c: S)     -> R { unstable(getopts::optflagmulti(a, b, c)) }
 }
 
 /// Returns the "short" subset of the rustc command line options,
@@ -785,8 +789,8 @@ pub fn rustc_short_optgroups() -> Vec<RustcOptGroup> {
         opt::multi("", "print", "Comma separated list of compiler information to \
                                print on stdout",
                  "[crate-name|file-names|sysroot]"),
-        opt::flag("g",  "",  "Equivalent to -C debuginfo=2"),
-        opt::flag("O", "", "Equivalent to -C opt-level=2"),
+        opt::flagmulti("g",  "",  "Equivalent to -C debuginfo=2"),
+        opt::flagmulti("O", "", "Equivalent to -C opt-level=2"),
         opt::opt("o", "", "Write output to <filename>", "FILENAME"),
         opt::opt("",  "out-dir", "Write output to compiler-chosen filename \
                                 in <dir>", "DIR"),
diff --git a/src/librustc_back/fs.rs b/src/librustc_back/fs.rs
deleted file mode 100644 (file)
index 37e3efb..0000000
+++ /dev/null
@@ -1,91 +0,0 @@
-// 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::io;
-use std::path::{Path, PathBuf};
-
-#[cfg(windows)]
-pub fn realpath(original: &Path) -> io::Result<PathBuf> {
-    Ok(original.to_path_buf())
-}
-
-#[cfg(unix)]
-pub fn realpath(original: &Path) -> io::Result<PathBuf> {
-    use libc;
-    use std::ffi::{OsString, CString};
-    use std::os::unix::prelude::*;
-
-    extern {
-        fn realpath(pathname: *const libc::c_char, resolved: *mut libc::c_char)
-                    -> *mut libc::c_char;
-    }
-
-    let path = try!(CString::new(original.as_os_str().as_bytes()));
-    let mut buf = vec![0u8; 16 * 1024];
-    unsafe {
-        let r = realpath(path.as_ptr(), buf.as_mut_ptr() as *mut _);
-        if r.is_null() {
-            return Err(io::Error::last_os_error())
-        }
-    }
-    let p = buf.iter().position(|i| *i == 0).unwrap();
-    buf.truncate(p);
-    Ok(PathBuf::from(OsString::from_vec(buf)))
-}
-
-#[cfg(all(not(windows), test))]
-mod tests {
-    use tempdir::TempDir;
-    use std::fs::{self, File};
-    use super::realpath;
-
-    #[test]
-    fn realpath_works() {
-        let tmpdir = TempDir::new("rustc-fs").unwrap();
-        let tmpdir = realpath(tmpdir.path()).unwrap();
-        let file = tmpdir.join("test");
-        let dir = tmpdir.join("test2");
-        let link = dir.join("link");
-        let linkdir = tmpdir.join("test3");
-
-        File::create(&file).unwrap();
-        fs::create_dir(&dir).unwrap();
-        fs::soft_link(&file, &link).unwrap();
-        fs::soft_link(&dir, &linkdir).unwrap();
-
-        assert_eq!(realpath(&tmpdir).unwrap(), tmpdir);
-        assert_eq!(realpath(&file).unwrap(), file);
-        assert_eq!(realpath(&link).unwrap(), file);
-        assert_eq!(realpath(&linkdir).unwrap(), dir);
-        assert_eq!(realpath(&linkdir.join("link")).unwrap(), file);
-    }
-
-    #[test]
-    fn realpath_works_tricky() {
-        let tmpdir = TempDir::new("rustc-fs").unwrap();
-        let tmpdir = realpath(tmpdir.path()).unwrap();
-
-        let a = tmpdir.join("a");
-        let b = a.join("b");
-        let c = b.join("c");
-        let d = a.join("d");
-        let e = d.join("e");
-        let f = a.join("f");
-
-        fs::create_dir_all(&b).unwrap();
-        fs::create_dir_all(&d).unwrap();
-        File::create(&f).unwrap();
-        fs::soft_link("../d/e", &c).unwrap();
-        fs::soft_link("../f", &e).unwrap();
-
-        assert_eq!(realpath(&c).unwrap(), f);
-        assert_eq!(realpath(&e).unwrap(), f);
-    }
-}
index 22dea4757ed662a8942c198ab7ac0e7b5a38b655..3e55f7f8045b59b60ee38723f34655e43f987924 100644 (file)
@@ -41,6 +41,7 @@
 #![feature(path_ext)]
 #![feature(step_by)]
 #![feature(libc)]
+#![feature(fs_canonicalize)]
 #![cfg_attr(test, feature(test, rand))]
 
 extern crate syntax;
@@ -53,7 +54,6 @@
 pub mod archive;
 pub mod tempdir;
 pub mod arm;
-pub mod fs;
 pub mod mips;
 pub mod mipsel;
 pub mod rpath;
index 1daeb1cb223e279670efd5d089a07ef87b19a1a3..6674d3135a0bdb671dbd621a1979dd97df196fca 100644 (file)
@@ -10,8 +10,8 @@
 
 use std::collections::HashSet;
 use std::env;
-use std::io;
 use std::path::{Path, PathBuf};
+use std::fs;
 use syntax::ast;
 
 pub struct RPathConfig<'a> {
@@ -20,7 +20,6 @@ pub struct RPathConfig<'a> {
     pub is_like_osx: bool,
     pub has_rpath: bool,
     pub get_install_prefix_lib_path: &'a mut FnMut() -> PathBuf,
-    pub realpath: &'a mut FnMut(&Path) -> io::Result<PathBuf>,
 }
 
 pub fn get_rpath_flags(config: &mut RPathConfig) -> Vec<String> {
@@ -95,11 +94,11 @@ fn get_rpath_relative_to_output(config: &mut RPathConfig, lib: &Path) -> String
     };
 
     let cwd = env::current_dir().unwrap();
-    let mut lib = (config.realpath)(&cwd.join(lib)).unwrap();
+    let mut lib = fs::canonicalize(&cwd.join(lib)).unwrap_or(cwd.join(lib));
     lib.pop();
     let mut output = cwd.join(&config.out_filename);
     output.pop();
-    let output = (config.realpath)(&output).unwrap();
+    let output = fs::canonicalize(&output).unwrap_or(output);
     let relative = path_relative_from(&lib, &output)
         .expect(&format!("couldn't create relative path from {:?} to {:?}", output, lib));
     // FIXME (#9639): This needs to handle non-utf8 paths
@@ -231,7 +230,6 @@ fn test_rpath_relative() {
                 is_like_osx: true,
                 out_filename: PathBuf::from("bin/rustc"),
                 get_install_prefix_lib_path: &mut || panic!(),
-                realpath: &mut |p| Ok(p.to_path_buf()),
             };
             let res = get_rpath_relative_to_output(config,
                                                    Path::new("lib/libstd.so"));
@@ -243,7 +241,6 @@ fn test_rpath_relative() {
                 get_install_prefix_lib_path: &mut || panic!(),
                 has_rpath: true,
                 is_like_osx: false,
-                realpath: &mut |p| Ok(p.to_path_buf()),
             };
             let res = get_rpath_relative_to_output(config,
                                                    Path::new("lib/libstd.so"));
index 2ceb34e68b7720ac7574818046f2d6a81657a4d1..dd6bc672a03d996ab8d1cf390eac171cef3696e5 100644 (file)
@@ -22,6 +22,7 @@ pub fn target() -> Target {
         target_pointer_width: "64".to_string(),
         arch: "aarch64".to_string(),
         target_os: "ios".to_string(),
+        target_env: "".to_string(),
         options: TargetOptions {
             features: "+neon,+fp-armv8,+cyclone".to_string(),
             eliminate_frame_pointer: false,
index 64b0e0cfd6baca44462cd6b733329580aaf1c277..67194e7ac5c7c8c43832803f755df8aae57081a5 100644 (file)
 use target::Target;
 
 pub fn target() -> Target {
-    let mut base = super::linux_base::opts();
-    base.pre_link_args.push("-Wl,--allow-multiple-definition".to_string());
-    base.is_like_android = true;
-    base.position_independent_executables = true;
     Target {
         data_layout: "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-\
                       f32:32:32-f64:64:64-v64:64:64-v128:128:128-a:0:64-\
@@ -24,6 +20,7 @@ pub fn target() -> Target {
         target_pointer_width: "64".to_string(),
         arch: "aarch64".to_string(),
         target_os: "android".to_string(),
-        options: base,
+        target_env: "".to_string(),
+        options: super::android_base::opts(),
     }
 }
index a3ef6372f0648b9e1046b1ea1cd14584f9ab1749..18e67d066d03632f8c148a54c03326411364fc44 100644 (file)
@@ -19,6 +19,7 @@ pub fn target() -> Target {
         llvm_target: "aarch64-unknown-linux-gnu".to_string(),
         target_endian: "little".to_string(),
         target_pointer_width: "64".to_string(),
+        target_env: "gnu".to_string(),
         arch: "aarch64".to_string(),
         target_os: "linux".to_string(),
         options: base,
diff --git a/src/librustc_back/target/android_base.rs b/src/librustc_back/target/android_base.rs
new file mode 100644 (file)
index 0000000..2883ffd
--- /dev/null
@@ -0,0 +1,21 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use target::TargetOptions;
+
+pub fn opts() -> TargetOptions {
+    let mut base = super::linux_base::opts();
+    // Many of the symbols defined in compiler-rt are also defined in libgcc.
+    // Android's linker doesn't like that by default.
+    base.pre_link_args.push("-Wl,--allow-multiple-definition".to_string());
+    base.is_like_android = true;
+    base.position_independent_executables = true;
+    base
+}
index fad9344143155628ee92b56fdda2ff0819dfd8af..cbaa2b205b05512c36f660e5d10ec2a989653b86 100644 (file)
 use target::Target;
 
 pub fn target() -> Target {
-    let mut base = super::linux_base::opts();
+    let mut base = super::android_base::opts();
     base.features = "+v7".to_string();
-    // Many of the symbols defined in compiler-rt are also defined in libgcc.  Android
-    // linker doesn't like that by default.
-    base.pre_link_args.push("-Wl,--allow-multiple-definition".to_string());
-    base.is_like_android = true;
-    // FIXME #17437 (and #17448): Android doesn't support position dependent executables anymore.
-    base.position_independent_executables = false;
 
     Target {
-        data_layout: "e-p:32:32:32\
-                      -i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64\
-                      -f32:32:32-f64:64:64\
-                      -v64:64:64-v128:64:128\
-                      -a:0:64-n32".to_string(),
+        data_layout: "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-\
+                      f32:32:32-f64:64:64-v64:64:64-v128:64:128-a:0:64-\
+                      n32".to_string(),
         llvm_target: "arm-linux-androideabi".to_string(),
         target_endian: "little".to_string(),
         target_pointer_width: "32".to_string(),
         arch: "arm".to_string(),
         target_os: "android".to_string(),
+        target_env: "gnu".to_string(),
         options: base,
     }
 }
index 32eccaf54b038816e01c02207fb35e558863f1e1..30015c4a7e6ff0ef1a34a6b04fd36ea956162ffd 100644 (file)
@@ -23,6 +23,7 @@ pub fn target() -> Target {
         target_pointer_width: "32".to_string(),
         arch: "arm".to_string(),
         target_os: "linux".to_string(),
+        target_env: "gnueabi".to_string(),
 
         options: TargetOptions {
             features: "+v6".to_string(),
index eff3601250f875c58e4aaee59261ee4d2ce99c0a..8f8c7114e6effa537c55bdeec16fa3b0ccb3a304 100644 (file)
@@ -23,6 +23,7 @@ pub fn target() -> Target {
         target_pointer_width: "32".to_string(),
         arch: "arm".to_string(),
         target_os: "linux".to_string(),
+        target_env: "gnueabihf".to_string(),
 
         options: TargetOptions {
             features: "+v6,+vfp2".to_string(),
index 4137642188691942df4c855a1d0ea29166582bba..3b55993659de24c132dbbb585b7fb7832b44c9c3 100644 (file)
@@ -19,6 +19,7 @@ pub fn target() -> Target {
         target_pointer_width: "32".to_string(),
         arch: "arm".to_string(),
         target_os: "ios".to_string(),
+        target_env: "".to_string(),
         options: TargetOptions {
             features: "+v7,+vfp3,+neon".to_string(),
             .. opts(Arch::Armv7)
index ef16aefdbd9dd9b8e3f9830703178e64f82a6ebf..5a67e3fe127d6f375bb7018a9ccf7b45da1ddce4 100644 (file)
@@ -19,6 +19,7 @@ pub fn target() -> Target {
         target_pointer_width: "32".to_string(),
         arch: "arm".to_string(),
         target_os: "ios".to_string(),
+        target_env: "".to_string(),
         options: TargetOptions {
             features: "+v7,+vfp4,+neon".to_string(),
             .. opts(Arch::Armv7s)
index afe63d006cf1a04c0600302a42987cc1fa159738..a9a073e2a8c64ae3db1c0394edc549f430b38329 100644 (file)
@@ -23,6 +23,7 @@ pub fn target() -> Target {
         target_pointer_width: "32".to_string(),
         arch: "x86".to_string(),
         target_os: "ios".to_string(),
+        target_env: "".to_string(),
         options: opts(Arch::I386)
     }
 }
index fcea900283d2851d1d785b6661d22e4556fc9bc4..47b329982d43e29383a77083d92c556c7e835a85 100644 (file)
@@ -26,6 +26,7 @@ pub fn target() -> Target {
         target_pointer_width: "32".to_string(),
         arch: "x86".to_string(),
         target_os: "macos".to_string(),
+        target_env: "".to_string(),
         options: base,
     }
 }
index 249f2d440e68155fd01960d9924930cadfe85a6d..9e2aa20085c3634f1dde00f97e1eb0def39a5ecf 100644 (file)
@@ -30,6 +30,7 @@ pub fn target() -> Target {
         target_pointer_width: "32".to_string(),
         arch: "x86".to_string(),
         target_os: "windows".to_string(),
+        target_env: "gnu".to_string(),
         options: options,
     }
 }
index 4450d8d67782d48fc899cdd684d38f447ccd7caf..ecabe71ad4c6c635ef279472ac60868a6cdd38c2 100644 (file)
@@ -22,6 +22,7 @@ pub fn target() -> Target {
         target_pointer_width: "32".to_string(),
         arch: "x86".to_string(),
         target_os: "dragonfly".to_string(),
+        target_env: "".to_string(),
         options: base,
     }
 }
index f21f6adfb4c0c2a03eb28a5e0aed816508b0e59a..21094ad905e90f5c281c8d451fa44fb676b97399 100644 (file)
@@ -22,6 +22,7 @@ pub fn target() -> Target {
         target_pointer_width: "32".to_string(),
         arch: "x86".to_string(),
         target_os: "linux".to_string(),
+        target_env: "gnu".to_string(),
         options: base,
     }
 }
index d267bc77e4975d52aca8dd8a8488aad6b1691aa0..823a4a81fa4c19f98f1cf04834c7640ad9695530 100644 (file)
@@ -19,12 +19,16 @@ pub fn opts() -> TargetOptions {
         morestack: true,
         linker_is_gnu: true,
         has_rpath: true,
-        pre_link_args: vec!(
-            // GNU-style linkers will use this to omit linking to libraries which
-            // don't actually fulfill any relocations, but only for libraries which
-            // follow this flag. Thus, use it before specifying libraries to link to.
+        pre_link_args: vec![
+            // We want to be able to strip as much executable code as possible
+            // from the linker command line, and this flag indicates to the
+            // linker that it can avoid linking in dynamic libraries that don't
+            // actually satisfy any symbols up to that point (as with many other
+            // resolutions the linker does). This option only applies to all
+            // following libraries so we're sure to pass it as one of the first
+            // arguments.
             "-Wl,--as-needed".to_string(),
-        ),
+        ],
         position_independent_executables: true,
         .. Default::default()
     }
index 8acc248e23410105c134612cf65f5822c6804a6d..4662ff1958ba87de61a7d1922324e047f7185f90 100644 (file)
@@ -22,6 +22,7 @@ pub fn target() -> Target {
         target_pointer_width: "32".to_string(),
         arch: "mips".to_string(),
         target_os: "linux".to_string(),
+        target_env: "gnu".to_string(),
         options: super::linux_base::opts()
     }
 }
index 604c62eb69f0f753fffe2e628f29ddbb076d55da..80e38c5ddea98e61cdc65bcdb8d94371b11f4373 100644 (file)
@@ -22,6 +22,7 @@ pub fn target() -> Target {
         target_pointer_width: "32".to_string(),
         arch: "mips".to_string(),
         target_os: "linux".to_string(),
+        target_env: "gnu".to_string(),
 
         options: super::linux_base::opts()
     }
index 07528df97f1334686123652efacf0c9525324fd0..c5f1882fa1dd7d33409db8a850b246e2bbc20efb 100644 (file)
 //! specified by the target, rather than replace.
 
 use serialize::json::Json;
-use syntax::{diagnostic, abi};
 use std::default::Default;
 use std::io::prelude::*;
+use syntax::{diagnostic, abi};
 
-mod windows_base;
-mod linux_base;
+mod android_base;
 mod apple_base;
 mod apple_ios_base;
-mod freebsd_base;
-mod dragonfly_base;
 mod bitrig_base;
+mod dragonfly_base;
+mod freebsd_base;
+mod linux_base;
 mod openbsd_base;
-
-mod armv7_apple_ios;
-mod armv7s_apple_ios;
-mod i386_apple_ios;
-
-mod arm_linux_androideabi;
-mod arm_unknown_linux_gnueabi;
-mod arm_unknown_linux_gnueabihf;
-mod aarch64_apple_ios;
-mod aarch64_linux_android;
-mod aarch64_unknown_linux_gnu;
-mod i686_apple_darwin;
-mod i686_pc_windows_gnu;
-mod i686_unknown_dragonfly;
-mod i686_unknown_linux_gnu;
-mod mips_unknown_linux_gnu;
-mod mipsel_unknown_linux_gnu;
-mod powerpc_unknown_linux_gnu;
-mod x86_64_apple_darwin;
-mod x86_64_apple_ios;
-mod x86_64_pc_windows_gnu;
-mod x86_64_unknown_freebsd;
-mod x86_64_unknown_dragonfly;
-mod x86_64_unknown_bitrig;
-mod x86_64_unknown_linux_gnu;
-mod x86_64_unknown_openbsd;
+mod windows_base;
 
 /// Everything `rustc` knows about how to compile for a specific target.
 ///
@@ -100,6 +75,8 @@ pub struct Target {
     pub target_pointer_width: String,
     /// OS name to use for conditional compilation.
     pub target_os: String,
+    /// Environment name to use for conditional compilation.
+    pub target_env: String,
     /// Architecture to use for ABI considerations. Valid options: "x86", "x86_64", "arm",
     /// "aarch64", "mips", and "powerpc". "mips" includes "mipsel".
     pub arch: String,
@@ -115,14 +92,22 @@ pub struct Target {
 pub struct TargetOptions {
     /// Linker to invoke. Defaults to "cc".
     pub linker: String,
-    /// Linker arguments that are unconditionally passed *before* any user-defined libraries.
+    /// Linker arguments that are unconditionally passed *before* any
+    /// user-defined libraries.
     pub pre_link_args: Vec<String>,
-    /// Linker arguments that are unconditionally passed *after* any user-defined libraries.
+    /// Linker arguments that are unconditionally passed *after* any
+    /// user-defined libraries.
     pub post_link_args: Vec<String>,
-    /// Default CPU to pass to LLVM. Corresponds to `llc -mcpu=$cpu`. Defaults to "default".
+    /// Objects to link before and after all others, always found within the
+    /// sysroot folder.
+    pub pre_link_objects: Vec<String>,
+    pub post_link_objects: Vec<String>,
+    /// Default CPU to pass to LLVM. Corresponds to `llc -mcpu=$cpu`. Defaults
+    /// to "default".
     pub cpu: String,
-    /// Default target features to pass to LLVM. These features will *always* be passed, and cannot
-    /// be disabled even via `-C`. Corresponds to `llc -mattr=$features`.
+    /// Default target features to pass to LLVM. These features will *always* be
+    /// passed, and cannot be disabled even via `-C`. Corresponds to `llc
+    /// -mattr=$features`.
     pub features: String,
     /// Whether dynamic linking is available on this target. Defaults to false.
     pub dynamic_linking: bool,
@@ -207,6 +192,8 @@ fn default() -> TargetOptions {
             has_rpath: false,
             no_compiler_rt: false,
             position_independent_executables: false,
+            pre_link_objects: Vec::new(),
+            post_link_objects: Vec::new(),
         }
     }
 }
@@ -250,6 +237,8 @@ pub fn from_json(obj: Json) -> Target {
             target_pointer_width: get_req_field("target-pointer-width"),
             arch: get_req_field("arch"),
             target_os: get_req_field("os"),
+            target_env: obj.find("env").and_then(|s| s.as_string())
+                           .map(|s| s.to_string()).unwrap_or(String::new()),
             options: Default::default(),
         };
 
@@ -329,6 +318,7 @@ fn load_file(path: &Path) -> Result<Target, String> {
         macro_rules! load_specific {
             ( $($name:ident),+ ) => (
                 {
+                    $(mod $name;)*
                     let target = target.replace("-", "_");
                     if false { }
                     $(
@@ -358,6 +348,7 @@ macro_rules! load_specific {
             arm_unknown_linux_gnueabi,
             arm_unknown_linux_gnueabihf,
             aarch64_unknown_linux_gnu,
+            x86_64_unknown_linux_musl,
 
             arm_linux_androideabi,
             aarch64_linux_android,
index 5e0b7bcf3ef8bc04693ad23ba5a252dbfb95d036..3a2b4bd16065ef38e892a78415b4d0f4cc75b39a 100644 (file)
@@ -21,6 +21,7 @@ pub fn target() -> Target {
         target_pointer_width: "32".to_string(),
         arch: "powerpc".to_string(),
         target_os: "linux".to_string(),
+        target_env: "gnu".to_string(),
         options: base,
     }
 }
index 0b3b2bea62d777cc920f01c2b2776402367de433..89a67da2d8bbcf9b677553c31287036004fd85b2 100644 (file)
@@ -25,6 +25,7 @@ pub fn target() -> Target {
         target_pointer_width: "64".to_string(),
         arch: "x86_64".to_string(),
         target_os: "macos".to_string(),
+        target_env: "".to_string(),
         options: base,
     }
 }
index 9df2ccca50003059062e63524ca1933abb463b21..74491629ed8592faf1e53115f5dbfc7890756f17 100644 (file)
@@ -21,6 +21,7 @@ pub fn target() -> Target {
         target_pointer_width: "64".to_string(),
         arch: "x86_64".to_string(),
         target_os: "ios".to_string(),
+        target_env: "".to_string(),
         options: opts(Arch::X86_64)
     }
 }
index 6b3054656fe9f1fbe49f2536f7895350db7e2da3..bea7d16e9dfadd83897082db1e9218f3ea2e4305 100644 (file)
@@ -27,6 +27,7 @@ pub fn target() -> Target {
         target_pointer_width: "64".to_string(),
         arch: "x86_64".to_string(),
         target_os: "windows".to_string(),
+        target_env: "gnu".to_string(),
         options: base,
     }
 }
index 7b7877c0c6995855c365d86bdb54601d4a8de870..201c56b2e15c682b991738e9306332b331f467e4 100644 (file)
@@ -23,6 +23,7 @@ pub fn target() -> Target {
         target_pointer_width: "64".to_string(),
         arch: "x86_64".to_string(),
         target_os: "bitrig".to_string(),
+        target_env: "".to_string(),
         options: base,
     }
 }
index 676aaecc2fc7db4f16c92cff2c2ef88cc8355379..c590f0297b948a03648ac04b4c482d8ebb8c3935 100644 (file)
@@ -24,6 +24,7 @@ pub fn target() -> Target {
         target_pointer_width: "64".to_string(),
         arch: "x86_64".to_string(),
         target_os: "dragonfly".to_string(),
+        target_env: "".to_string(),
         options: base,
     }
 }
index 3275cb07b5abc3a7b7021d784e79d109d8c9a6e5..0d8ea90a2ab04921d0371cbe94f6244c273b1d15 100644 (file)
@@ -24,6 +24,7 @@ pub fn target() -> Target {
         target_pointer_width: "64".to_string(),
         arch: "x86_64".to_string(),
         target_os: "freebsd".to_string(),
+        target_env: "".to_string(),
         options: base,
     }
 }
index 49c4ad4aea99f60ef8894d188dc265881dd5cef8..ba945afc5649b38f70750eea70bda88479f72aff 100644 (file)
@@ -24,6 +24,7 @@ pub fn target() -> Target {
         target_pointer_width: "64".to_string(),
         arch: "x86_64".to_string(),
         target_os: "linux".to_string(),
+        target_env: "gnu".to_string(),
         options: base,
     }
 }
diff --git a/src/librustc_back/target/x86_64_unknown_linux_musl.rs b/src/librustc_back/target/x86_64_unknown_linux_musl.rs
new file mode 100644 (file)
index 0000000..3debad2
--- /dev/null
@@ -0,0 +1,84 @@
+// 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 target::Target;
+
+pub fn target() -> Target {
+    let mut base = super::linux_base::opts();
+    base.cpu = "x86-64".to_string();
+    base.pre_link_args.push("-m64".to_string());
+
+    // Make sure that the linker/gcc really don't pull in anything, including
+    // default objects, libs, etc.
+    base.pre_link_args.push("-nostdlib".to_string());
+    base.pre_link_args.push("-static".to_string());
+
+    // At least when this was tested, the linker would not add the
+    // `GNU_EH_FRAME` program header to executables generated, which is required
+    // when unwinding to locate the unwinding information. I'm not sure why this
+    // argument is *not* necessary for normal builds, but it can't hurt!
+    base.pre_link_args.push("-Wl,--eh-frame-hdr".to_string());
+
+    // There's a whole bunch of circular dependencies when dealing with MUSL
+    // unfortunately. To put this in perspective libc is statically linked to
+    // liblibc and libunwind is statically linked to libstd:
+    //
+    // * libcore depends on `fmod` which is in libc (transitively in liblibc).
+    //   liblibc, however, depends on libcore.
+    // * compiler-rt has personality symbols that depend on libunwind, but
+    //   libunwind is in libstd which depends on compiler-rt.
+    //
+    // Recall that linkers discard libraries and object files as much as
+    // possible, and with all the static linking and archives flying around with
+    // MUSL the linker is super aggressively stripping out objects. For example
+    // the first case has fmod stripped from liblibc (it's in its own object
+    // file) so it's not there when libcore needs it. In the second example all
+    // the unused symbols from libunwind are stripped (each is in its own object
+    // file in libstd) before we end up linking compiler-rt which depends on
+    // those symbols.
+    //
+    // To deal with these circular dependencies we just force the compiler to
+    // link everything as a group, not stripping anything out until everything
+    // is processed. The linker will still perform a pass to strip out object
+    // files but it won't do so until all objects/archives have been processed.
+    base.pre_link_args.push("-Wl,-(".to_string());
+    base.post_link_args.push("-Wl,-)".to_string());
+
+    // When generating a statically linked executable there's generally some
+    // small setup needed which is listed in these files. These are provided by
+    // a musl toolchain and are linked by default by the `musl-gcc` script. Note
+    // that `gcc` also does this by default, it just uses some different files.
+    //
+    // Each target directory for musl has these object files included in it so
+    // they'll be included from there.
+    base.pre_link_objects.push("crt1.o".to_string());
+    base.pre_link_objects.push("crti.o".to_string());
+    base.post_link_objects.push("crtn.o".to_string());
+
+    // MUSL support doesn't currently include dynamic linking, so there's no
+    // need for dylibs or rpath business. Additionally `-pie` is incompatible
+    // with `-static`, so we can't pass `-pie`.
+    base.dynamic_linking = false;
+    base.has_rpath = false;
+    base.position_independent_executables = false;
+
+    Target {
+        data_layout: "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-\
+                      f32:32:32-f64:64:64-v64:64:64-v128:128:128-a:0:64-\
+                      s0:64:64-f80:128:128-n8:16:32:64-S128".to_string(),
+        llvm_target: "x86_64-unknown-linux-musl".to_string(),
+        target_endian: "little".to_string(),
+        target_pointer_width: "64".to_string(),
+        arch: "x86_64".to_string(),
+        target_os: "linux".to_string(),
+        target_env: "musl".to_string(),
+        options: base,
+    }
+}
index d2667dcd1dd9e8f8bfac358b72f2d4a46f788698..7f64259adf9f8cf0c581a0e50d7a00a014b353a0 100644 (file)
@@ -23,6 +23,7 @@ pub fn target() -> Target {
         target_pointer_width: "64".to_string(),
         arch: "x86_64".to_string(),
         target_os: "openbsd".to_string(),
+        target_env: "".to_string(),
         options: base,
     }
 }
index 93a2a5d125778eeab36329aa661ec2dec366a926..6d23cad26cb37e76d07362fbe3f31b5e1893b1af 100644 (file)
@@ -12,6 +12,7 @@
 // Do not remove on snapshot creation. Needed for bootstrap. (Issue #22364)
 #![cfg_attr(stage0, feature(custom_attribute))]
 #![crate_name = "rustc_bitflags"]
+#![feature(associated_consts)]
 #![feature(staged_api)]
 #![staged_api]
 #![crate_type = "rlib"]
@@ -34,6 +35,7 @@
 ///
 /// ```{.rust}
 /// # #![feature(rustc_private)]
+/// # #![feature(associated_consts)]
 /// #[macro_use] extern crate rustc_bitflags;
 ///
 /// bitflags! {
 ///         const FLAG_A       = 0b00000001,
 ///         const FLAG_B       = 0b00000010,
 ///         const FLAG_C       = 0b00000100,
-///         const FLAG_ABC     = FLAG_A.bits
-///                            | FLAG_B.bits
-///                            | FLAG_C.bits,
+///         const FLAG_ABC     = Flags::FLAG_A.bits
+///                            | Flags::FLAG_B.bits
+///                            | Flags::FLAG_C.bits,
 ///     }
 /// }
 ///
 /// fn main() {
-///     let e1 = FLAG_A | FLAG_C;
-///     let e2 = FLAG_B | FLAG_C;
-///     assert!((e1 | e2) == FLAG_ABC);   // union
-///     assert!((e1 & e2) == FLAG_C);     // intersection
-///     assert!((e1 - e2) == FLAG_A);     // set difference
-///     assert!(!e2 == FLAG_A);           // set complement
+///     let e1 = Flags::FLAG_A | Flags::FLAG_C;
+///     let e2 = Flags::FLAG_B | Flags::FLAG_C;
+///     assert!((e1 | e2) == Flags::FLAG_ABC); // union
+///     assert!((e1 & e2) == Flags::FLAG_C);   // intersection
+///     assert!((e1 - e2) == Flags::FLAG_A);   // set difference
+///     assert!(!e2 == Flags::FLAG_A);         // set complement
 /// }
 /// ```
 ///
@@ -86,7 +88,7 @@
 /// }
 ///
 /// fn main() {
-///     let mut flags = FLAG_A | FLAG_B;
+///     let mut flags = Flags::FLAG_A | Flags::FLAG_B;
 ///     flags.clear();
 ///     assert!(flags.is_empty());
 ///     assert_eq!(format!("{:?}", flags), "hi!");
@@ -144,9 +146,9 @@ pub struct $BitFlags {
             bits: $T,
         }
 
-        $($(#[$Flag_attr])* pub const $Flag: $BitFlags = $BitFlags { bits: $value };)+
-
         impl $BitFlags {
+            $($(#[$Flag_attr])* pub const $Flag: $BitFlags = $BitFlags { bits: $value };)+
+
             /// Returns an empty set of flags.
             #[inline]
             pub fn empty() -> $BitFlags {
@@ -314,9 +316,9 @@ mod tests {
             #[doc = "* cmr bed"]
             #[doc = "* strcat table"]
             #[doc = "<strcat> wait what?"]
-            const FlagABC     = FlagA.bits
-                               | FlagB.bits
-                               | FlagC.bits,
+            const FlagABC     = Flags::FlagA.bits
+                               | Flags::FlagB.bits
+                               | Flags::FlagC.bits,
         }
     }
 
@@ -329,32 +331,32 @@ mod tests {
     #[test]
     fn test_bits(){
         assert_eq!(Flags::empty().bits(), 0b00000000);
-        assert_eq!(FlagA.bits(), 0b00000001);
-        assert_eq!(FlagABC.bits(), 0b00000111);
+        assert_eq!(Flags::FlagA.bits(), 0b00000001);
+        assert_eq!(Flags::FlagABC.bits(), 0b00000111);
 
         assert_eq!(AnotherSetOfFlags::empty().bits(), 0b00);
-        assert_eq!(AnotherFlag.bits(), !0);
+        assert_eq!(AnotherSetOfFlags::AnotherFlag.bits(), !0);
     }
 
     #[test]
     fn test_from_bits() {
         assert!(Flags::from_bits(0) == Some(Flags::empty()));
-        assert!(Flags::from_bits(0b1) == Some(FlagA));
-        assert!(Flags::from_bits(0b10) == Some(FlagB));
-        assert!(Flags::from_bits(0b11) == Some(FlagA | FlagB));
+        assert!(Flags::from_bits(0b1) == Some(Flags::FlagA));
+        assert!(Flags::from_bits(0b10) == Some(Flags::FlagB));
+        assert!(Flags::from_bits(0b11) == Some(Flags::FlagA | Flags::FlagB));
         assert!(Flags::from_bits(0b1000) == None);
 
-        assert!(AnotherSetOfFlags::from_bits(!0) == Some(AnotherFlag));
+        assert!(AnotherSetOfFlags::from_bits(!0) == Some(AnotherSetOfFlags::AnotherFlag));
     }
 
     #[test]
     fn test_from_bits_truncate() {
         assert!(Flags::from_bits_truncate(0) == Flags::empty());
-        assert!(Flags::from_bits_truncate(0b1) == FlagA);
-        assert!(Flags::from_bits_truncate(0b10) == FlagB);
-        assert!(Flags::from_bits_truncate(0b11) == (FlagA | FlagB));
+        assert!(Flags::from_bits_truncate(0b1) == Flags::FlagA);
+        assert!(Flags::from_bits_truncate(0b10) == Flags::FlagB);
+        assert!(Flags::from_bits_truncate(0b11) == (Flags::FlagA | Flags::FlagB));
         assert!(Flags::from_bits_truncate(0b1000) == Flags::empty());
-        assert!(Flags::from_bits_truncate(0b1001) == FlagA);
+        assert!(Flags::from_bits_truncate(0b1001) == Flags::FlagA);
 
         assert!(AnotherSetOfFlags::from_bits_truncate(0) == AnotherSetOfFlags::empty());
     }
@@ -362,19 +364,19 @@ fn test_from_bits_truncate() {
     #[test]
     fn test_is_empty(){
         assert!(Flags::empty().is_empty());
-        assert!(!FlagA.is_empty());
-        assert!(!FlagABC.is_empty());
+        assert!(!Flags::FlagA.is_empty());
+        assert!(!Flags::FlagABC.is_empty());
 
-        assert!(!AnotherFlag.is_empty());
+        assert!(!AnotherSetOfFlags::AnotherFlag.is_empty());
     }
 
     #[test]
     fn test_is_all() {
         assert!(Flags::all().is_all());
-        assert!(!FlagA.is_all());
-        assert!(FlagABC.is_all());
+        assert!(!Flags::FlagA.is_all());
+        assert!(Flags::FlagABC.is_all());
 
-        assert!(AnotherFlag.is_all());
+        assert!(AnotherSetOfFlags::AnotherFlag.is_all());
     }
 
     #[test]
@@ -383,77 +385,77 @@ fn test_two_empties_do_not_intersect() {
         let e2 = Flags::empty();
         assert!(!e1.intersects(e2));
 
-        assert!(AnotherFlag.intersects(AnotherFlag));
+        assert!(AnotherSetOfFlags::AnotherFlag.intersects(AnotherSetOfFlags::AnotherFlag));
     }
 
     #[test]
     fn test_empty_does_not_intersect_with_full() {
         let e1 = Flags::empty();
-        let e2 = FlagABC;
+        let e2 = Flags::FlagABC;
         assert!(!e1.intersects(e2));
     }
 
     #[test]
     fn test_disjoint_intersects() {
-        let e1 = FlagA;
-        let e2 = FlagB;
+        let e1 = Flags::FlagA;
+        let e2 = Flags::FlagB;
         assert!(!e1.intersects(e2));
     }
 
     #[test]
     fn test_overlapping_intersects() {
-        let e1 = FlagA;
-        let e2 = FlagA | FlagB;
+        let e1 = Flags::FlagA;
+        let e2 = Flags::FlagA | Flags::FlagB;
         assert!(e1.intersects(e2));
     }
 
     #[test]
     fn test_contains() {
-        let e1 = FlagA;
-        let e2 = FlagA | FlagB;
+        let e1 = Flags::FlagA;
+        let e2 = Flags::FlagA | Flags::FlagB;
         assert!(!e1.contains(e2));
         assert!(e2.contains(e1));
-        assert!(FlagABC.contains(e2));
+        assert!(Flags::FlagABC.contains(e2));
 
-        assert!(AnotherFlag.contains(AnotherFlag));
+        assert!(AnotherSetOfFlags::AnotherFlag.contains(AnotherSetOfFlags::AnotherFlag));
     }
 
     #[test]
     fn test_insert(){
-        let mut e1 = FlagA;
-        let e2 = FlagA | FlagB;
+        let mut e1 = Flags::FlagA;
+        let e2 = Flags::FlagA | Flags::FlagB;
         e1.insert(e2);
         assert!(e1 == e2);
 
         let mut e3 = AnotherSetOfFlags::empty();
-        e3.insert(AnotherFlag);
-        assert!(e3 == AnotherFlag);
+        e3.insert(AnotherSetOfFlags::AnotherFlag);
+        assert!(e3 == AnotherSetOfFlags::AnotherFlag);
     }
 
     #[test]
     fn test_remove(){
-        let mut e1 = FlagA | FlagB;
-        let e2 = FlagA | FlagC;
+        let mut e1 = Flags::FlagA | Flags::FlagB;
+        let e2 = Flags::FlagA | Flags::FlagC;
         e1.remove(e2);
-        assert!(e1 == FlagB);
+        assert!(e1 == Flags::FlagB);
 
-        let mut e3 = AnotherFlag;
-        e3.remove(AnotherFlag);
+        let mut e3 = AnotherSetOfFlags::AnotherFlag;
+        e3.remove(AnotherSetOfFlags::AnotherFlag);
         assert!(e3 == AnotherSetOfFlags::empty());
     }
 
     #[test]
     fn test_operators() {
-        let e1 = FlagA | FlagC;
-        let e2 = FlagB | FlagC;
-        assert!((e1 | e2) == FlagABC);     // union
-        assert!((e1 & e2) == FlagC);       // intersection
-        assert!((e1 - e2) == FlagA);       // set difference
-        assert!(!e2 == FlagA);             // set complement
-        assert!(e1 ^ e2 == FlagA | FlagB); // toggle
+        let e1 = Flags::FlagA | Flags::FlagC;
+        let e2 = Flags::FlagB | Flags::FlagC;
+        assert!((e1 | e2) == Flags::FlagABC);     // union
+        assert!((e1 & e2) == Flags::FlagC);       // intersection
+        assert!((e1 - e2) == Flags::FlagA);       // set difference
+        assert!(!e2 == Flags::FlagA);             // set complement
+        assert!(e1 ^ e2 == Flags::FlagA | Flags::FlagB); // toggle
         let mut e3 = e1;
         e3.toggle(e2);
-        assert!(e3 == FlagA | FlagB);
+        assert!(e3 == Flags::FlagA | Flags::FlagB);
 
         let mut m4 = AnotherSetOfFlags::empty();
         m4.toggle(AnotherSetOfFlags::empty());
@@ -466,11 +468,11 @@ fn test_lt() {
         let mut b = Flags::empty();
 
         assert!(!(a < b) && !(b < a));
-        b = FlagB;
+        b = Flags::FlagB;
         assert!(a < b);
-        a = FlagC;
+        a = Flags::FlagC;
         assert!(!(a < b) && b < a);
-        b = FlagC | FlagB;
+        b = Flags::FlagC | Flags::FlagB;
         assert!(a < b);
     }
 
@@ -480,10 +482,10 @@ fn test_ord() {
         let mut b = Flags::empty();
 
         assert!(a <= b && a >= b);
-        a = FlagA;
+        a = Flags::FlagA;
         assert!(a > b && a >= b);
         assert!(b < a && b <= a);
-        b = FlagB;
+        b = Flags::FlagB;
         assert!(b > a && b >= a);
         assert!(a < b && a <= b);
     }
@@ -494,7 +496,7 @@ fn test_hash() {
       let mut y = Flags::empty();
       assert!(hash::hash::<Flags, SipHasher>(&x) == hash::hash::<Flags, SipHasher>(&y));
       x = Flags::all();
-      y = FlagABC;
+      y = Flags::FlagABC;
       assert!(hash::hash::<Flags, SipHasher>(&x) == hash::hash::<Flags, SipHasher>(&y));
     }
 }
index 981b28593f9a4d20bba49937fda8b822b6e2bbc2..a43268ff1a8827c1cad97eef5a5f66c481467bb8 100644 (file)
@@ -13,5 +13,3 @@
 register_diagnostics! {
     E0373 // closure may outlive current fn, but it borrows {}, which is owned by current fn
 }
-
-__build_diagnostic_array! { DIAGNOSTICS }
index 647ea3555ba913984c8ed71be606c13e41851c86..50dc08e299a822701eaf28c5fc87b0d223b0861a 100644 (file)
@@ -25,7 +25,6 @@
 #![feature(rustc_diagnostic_macros)]
 #![feature(rustc_private)]
 #![feature(staged_api)]
-#![feature(unsafe_destructor)]
 #![feature(into_cow)]
 
 #[macro_use] extern crate log;
@@ -47,3 +46,8 @@
 mod borrowck;
 
 pub mod graphviz;
+
+#[cfg(stage0)]
+__build_diagnostic_array! { DIAGNOSTICS }
+#[cfg(not(stage0))]
+__build_diagnostic_array! { librustc_borrowck, DIAGNOSTICS }
index 38217f8dad24e900db8341f407855356655d2759..8dff0f1d3f41a61e78589c3027070ebd54a00ffb 100644 (file)
@@ -31,7 +31,6 @@
 #![feature(quote)]
 #![feature(rustc_diagnostic_macros)]
 #![feature(rustc_private)]
-#![feature(unsafe_destructor)]
 #![feature(staged_api)]
 #![feature(exit_status)]
 #![feature(set_stdio)]
@@ -854,9 +853,10 @@ pub fn diagnostics_registry() -> diagnostics::registry::Registry {
     use syntax::diagnostics::registry::Registry;
 
     let all_errors = Vec::new() +
-        &rustc::diagnostics::DIAGNOSTICS[..] +
-        &rustc_typeck::diagnostics::DIAGNOSTICS[..] +
-        &rustc_resolve::diagnostics::DIAGNOSTICS[..];
+        &rustc::DIAGNOSTICS[..] +
+        &rustc_typeck::DIAGNOSTICS[..] +
+        &rustc_borrowck::DIAGNOSTICS[..] +
+        &rustc_resolve::DIAGNOSTICS[..];
 
     Registry::new(&*all_errors)
 }
index 1d5c5fb86cbd5988b783d19c69ac28f5b06ca8b0..cc2c9b735ea44b881aa9d763af3ea37919eb13b7 100644 (file)
@@ -2142,3 +2142,57 @@ fn check_attribute(&mut self, ctx: &Context, attr: &ast::Attribute) {
         }
     }
 }
+
+/// Lints for attempts to impl Drop on types that have `#[repr(C)]`
+/// attribute (see issue #24585).
+#[derive(Copy, Clone)]
+pub struct DropWithReprExtern;
+
+declare_lint! {
+    DROP_WITH_REPR_EXTERN,
+    Warn,
+    "use of #[repr(C)] on a type that implements Drop"
+}
+
+impl LintPass for DropWithReprExtern {
+    fn get_lints(&self) -> LintArray {
+        lint_array!(DROP_WITH_REPR_EXTERN)
+    }
+    fn check_crate(&mut self, ctx: &Context, _: &ast::Crate) {
+        for dtor_did in ctx.tcx.destructors.borrow().iter() {
+            let (drop_impl_did, dtor_self_type) =
+                if dtor_did.krate == ast::LOCAL_CRATE {
+                    let impl_did = ctx.tcx.map.get_parent_did(dtor_did.node);
+                    let ty = ty::lookup_item_type(ctx.tcx, impl_did).ty;
+                    (impl_did, ty)
+                } else {
+                    continue;
+                };
+
+            match dtor_self_type.sty {
+                ty::ty_enum(self_type_did, _) |
+                ty::ty_struct(self_type_did, _) |
+                ty::ty_closure(self_type_did, _) => {
+                    let hints = ty::lookup_repr_hints(ctx.tcx, self_type_did);
+                    if hints.iter().any(|attr| *attr == attr::ReprExtern) &&
+                        ty::ty_dtor(ctx.tcx, self_type_did).has_drop_flag() {
+                        let drop_impl_span = ctx.tcx.map.def_id_span(drop_impl_did,
+                                                                     codemap::DUMMY_SP);
+                        let self_defn_span = ctx.tcx.map.def_id_span(self_type_did,
+                                                                     codemap::DUMMY_SP);
+                        ctx.span_lint(DROP_WITH_REPR_EXTERN,
+                                      drop_impl_span,
+                                      "implementing Drop adds hidden state to types, \
+                                       possibly conflicting with `#[repr(C)]`");
+                        // FIXME #19668: could be span_lint_note instead of manual guard.
+                        if ctx.current_level(DROP_WITH_REPR_EXTERN) != Level::Allow {
+                            ctx.sess().span_note(self_defn_span,
+                                               "the `#[repr(C)]` attribute is attached here");
+                        }
+                    }
+                }
+                _ => {}
+            }
+        }
+    }
+}
index 34f7436d0cd5d8d7cc5ccc9be4e2b88664b1183e..970f9c634a2caad2c4cbe4abb402786486e03c5f 100644 (file)
@@ -37,7 +37,6 @@
 #![feature(quote)]
 #![feature(rustc_diagnostic_macros)]
 #![feature(rustc_private)]
-#![feature(unsafe_destructor)]
 #![feature(staged_api)]
 #![feature(str_char)]
 #![cfg_attr(test, feature(test))]
@@ -109,6 +108,7 @@ macro_rules! add_lint_group {
                  UnconditionalRecursion,
                  InvalidNoMangleItems,
                  PluginAsLibrary,
+                 DropWithReprExtern,
                  );
 
     add_builtin_with_new!(sess,
index c8f3e204c4e10d0488d7e89cac812dd6c8f6ac9c..b591e37f893e254d919441924b5176aefd6f935e 100644 (file)
@@ -105,7 +105,6 @@ fn next(&mut self) -> Option<Child<'a>> {
     }
 }
 
-#[unsafe_destructor]
 impl<'a> Drop for Iter<'a> {
     fn drop(&mut self) {
         unsafe {
index 80e01154655e78ed499961e37d919e7161407c02..db88072150a603f2ef49f5847f51065e7abbd4dc 100644 (file)
        html_favicon_url = "http://www.rust-lang.org/favicon.ico",
        html_root_url = "http://doc.rust-lang.org/nightly/")]
 
+#![feature(associated_consts)]
 #![feature(box_syntax)]
 #![feature(collections)]
 #![feature(libc)]
 #![feature(link_args)]
 #![feature(staged_api)]
-#![feature(unsafe_destructor)]
 
 extern crate libc;
 #[macro_use] #[no_link] extern crate rustc_bitflags;
@@ -43,6 +43,7 @@
 pub use self::TypeKind::*;
 pub use self::AtomicBinOp::*;
 pub use self::AtomicOrdering::*;
+pub use self::SynchronizationScope::*;
 pub use self::FileType::*;
 pub use self::MetadataType::*;
 pub use self::AsmDialect::*;
@@ -124,32 +125,32 @@ pub enum DiagnosticSeverity {
 
 bitflags! {
     flags Attribute : u32 {
-        const ZExtAttribute = 1 << 0,
-        const SExtAttribute = 1 << 1,
-        const NoReturnAttribute = 1 << 2,
-        const InRegAttribute = 1 << 3,
-        const StructRetAttribute = 1 << 4,
-        const NoUnwindAttribute = 1 << 5,
-        const NoAliasAttribute = 1 << 6,
-        const ByValAttribute = 1 << 7,
-        const NestAttribute = 1 << 8,
-        const ReadNoneAttribute = 1 << 9,
-        const ReadOnlyAttribute = 1 << 10,
-        const NoInlineAttribute = 1 << 11,
-        const AlwaysInlineAttribute = 1 << 12,
+        const ZExtAttribute            = 1 << 0,
+        const SExtAttribute            = 1 << 1,
+        const NoReturnAttribute        = 1 << 2,
+        const InRegAttribute           = 1 << 3,
+        const StructRetAttribute       = 1 << 4,
+        const NoUnwindAttribute        = 1 << 5,
+        const NoAliasAttribute         = 1 << 6,
+        const ByValAttribute           = 1 << 7,
+        const NestAttribute            = 1 << 8,
+        const ReadNoneAttribute        = 1 << 9,
+        const ReadOnlyAttribute        = 1 << 10,
+        const NoInlineAttribute        = 1 << 11,
+        const AlwaysInlineAttribute    = 1 << 12,
         const OptimizeForSizeAttribute = 1 << 13,
-        const StackProtectAttribute = 1 << 14,
+        const StackProtectAttribute    = 1 << 14,
         const StackProtectReqAttribute = 1 << 15,
-        const AlignmentAttribute = 31 << 16,
-        const NoCaptureAttribute = 1 << 21,
-        const NoRedZoneAttribute = 1 << 22,
+        const AlignmentAttribute       = 1 << 16,
+        const NoCaptureAttribute       = 1 << 21,
+        const NoRedZoneAttribute       = 1 << 22,
         const NoImplicitFloatAttribute = 1 << 23,
-        const NakedAttribute = 1 << 24,
-        const InlineHintAttribute = 1 << 25,
-        const StackAttribute = 7 << 26,
-        const ReturnsTwiceAttribute = 1 << 29,
-        const UWTableAttribute = 1 << 30,
-        const NonLazyBindAttribute = 1 << 31,
+        const NakedAttribute           = 1 << 24,
+        const InlineHintAttribute      = 1 << 25,
+        const StackAttribute           = 7 << 26,
+        const ReturnsTwiceAttribute    = 1 << 29,
+        const UWTableAttribute         = 1 << 30,
+        const NonLazyBindAttribute     = 1 << 31,
     }
 }
 
@@ -361,6 +362,13 @@ pub enum AtomicOrdering {
     SequentiallyConsistent = 7
 }
 
+#[repr(C)]
+#[derive(Copy, Clone)]
+pub enum SynchronizationScope {
+    SingleThread = 0,
+    CrossThread = 1
+}
+
 // Consts for the LLVMCodeGenFileType type (in include/llvm/c/TargetMachine.h)
 #[repr(C)]
 #[derive(Copy, Clone)]
@@ -1534,7 +1542,9 @@ pub fn LLVMBuildAtomicRMW(B: BuilderRef,
                               SingleThreaded: Bool)
                               -> ValueRef;
 
-    pub fn LLVMBuildAtomicFence(B: BuilderRef, Order: AtomicOrdering);
+    pub fn LLVMBuildAtomicFence(B: BuilderRef,
+                                Order: AtomicOrdering,
+                                Scope: SynchronizationScope);
 
 
     /* Selected entries from the downcasts. */
index 0d25700d2b7f101f69f3ffb7adc7e671ae076b48..4ea18968d43ac218df9fbc3dda33aee3c716ad1e 100644 (file)
@@ -13,7 +13,7 @@
 //! Here we build the "reduced graph": the graph of the module tree without
 //! any imports resolved.
 
-use {DefModifiers, PUBLIC, IMPORTABLE};
+use DefModifiers;
 use resolve_imports::ImportDirective;
 use resolve_imports::ImportDirectiveSubclass::{self, SingleImport, GlobImport};
 use resolve_imports::ImportResolution;
@@ -262,7 +262,11 @@ fn build_reduced_graph_for_item(&mut self, item: &Item, parent: &Rc<Module>) ->
         let name = item.ident.name;
         let sp = item.span;
         let is_public = item.vis == ast::Public;
-        let modifiers = if is_public { PUBLIC } else { DefModifiers::empty() } | IMPORTABLE;
+        let modifiers = if is_public {
+            DefModifiers::PUBLIC
+        } else {
+            DefModifiers::empty()
+        } | DefModifiers::IMPORTABLE;
 
         match item.node {
             ItemUse(ref view_path) => {
@@ -533,20 +537,20 @@ fn build_reduced_graph_for_item(&mut self, item: &Item, parent: &Rc<Module>) ->
                         ast::ConstTraitItem(..) => {
                             let def = DefAssociatedConst(local_def(trait_item.id),
                                                          FromTrait(local_def(item.id)));
-                            // NB: not IMPORTABLE
-                            name_bindings.define_value(def, trait_item.span, PUBLIC);
+                            // NB: not DefModifiers::IMPORTABLE
+                            name_bindings.define_value(def, trait_item.span, DefModifiers::PUBLIC);
                         }
                         ast::MethodTraitItem(..) => {
                             let def = DefMethod(local_def(trait_item.id),
                                                 FromTrait(local_def(item.id)));
-                            // NB: not IMPORTABLE
-                            name_bindings.define_value(def, trait_item.span, PUBLIC);
+                            // NB: not DefModifiers::IMPORTABLE
+                            name_bindings.define_value(def, trait_item.span, DefModifiers::PUBLIC);
                         }
                         ast::TypeTraitItem(..) => {
                             let def = DefAssociatedTy(local_def(item.id),
                                                       local_def(trait_item.id));
-                            // NB: not IMPORTABLE
-                            name_bindings.define_type(def, trait_item.span, PUBLIC);
+                            // NB: not DefModifiers::IMPORTABLE
+                            name_bindings.define_type(def, trait_item.span, DefModifiers::PUBLIC);
                         }
                     }
 
@@ -584,10 +588,10 @@ fn build_reduced_graph_for_variant(&mut self,
         // used
         child.define_value(DefVariant(item_id,
                                       local_def(variant.node.id), is_exported),
-                           variant.span, PUBLIC | IMPORTABLE);
+                           variant.span, DefModifiers::PUBLIC | DefModifiers::IMPORTABLE);
         child.define_type(DefVariant(item_id,
                                      local_def(variant.node.id), is_exported),
-                          variant.span, PUBLIC | IMPORTABLE);
+                          variant.span, DefModifiers::PUBLIC | DefModifiers::IMPORTABLE);
     }
 
     /// Constructs the reduced graph for one foreign item.
@@ -596,7 +600,11 @@ fn build_reduced_graph_for_foreign_item(&mut self,
                                             parent: &Rc<Module>) {
         let name = foreign_item.ident.name;
         let is_public = foreign_item.vis == ast::Public;
-        let modifiers = if is_public { PUBLIC } else { DefModifiers::empty() } | IMPORTABLE;
+        let modifiers = if is_public {
+            DefModifiers::PUBLIC
+        } else {
+            DefModifiers::empty()
+        } | DefModifiers::IMPORTABLE;
         let name_bindings =
             self.add_child(name, parent, ForbidDuplicateValues,
                            foreign_item.span);
@@ -644,7 +652,11 @@ fn handle_external_def(&mut self,
                 external crate) building external def {}, priv {:?}",
                final_ident, vis);
         let is_public = vis == ast::Public;
-        let modifiers = if is_public { PUBLIC } else { DefModifiers::empty() } | IMPORTABLE;
+        let modifiers = if is_public {
+            DefModifiers::PUBLIC
+        } else {
+            DefModifiers::empty()
+        } | DefModifiers::IMPORTABLE;
         let is_exported = is_public && match new_parent.def_id.get() {
             None => true,
             Some(did) => self.external_exports.contains(&did)
@@ -695,7 +707,7 @@ fn handle_external_def(&mut self,
                       final_ident);
               // variants are always treated as importable to allow them to be
               // glob used
-              let modifiers = PUBLIC | IMPORTABLE;
+              let modifiers = DefModifiers::PUBLIC | DefModifiers::IMPORTABLE;
               if is_struct {
                   child_name_bindings.define_type(def, DUMMY_SP, modifiers);
                   // Not adding fields for variants as they are not accessed with a self receiver
@@ -715,11 +727,12 @@ fn handle_external_def(&mut self,
                     crate) building value (fn/static) {}", final_ident);
             // impl methods have already been defined with the correct importability modifier
             let mut modifiers = match *child_name_bindings.value_def.borrow() {
-                Some(ref def) => (modifiers & !IMPORTABLE) | (def.modifiers & IMPORTABLE),
+                Some(ref def) => (modifiers & !DefModifiers::IMPORTABLE) |
+                             (def.modifiers &  DefModifiers::IMPORTABLE),
                 None => modifiers
             };
             if new_parent.kind.get() != NormalModuleKind {
-                modifiers = modifiers & !IMPORTABLE;
+                modifiers = modifiers & !DefModifiers::IMPORTABLE;
             }
             child_name_bindings.define_value(def, DUMMY_SP, modifiers);
           }
index c586faae6e886dd32f5c398085c401904fe3fa41..a896bd311698c3cf55fd8d9a4e146d5bab99e8c3 100644 (file)
@@ -28,5 +28,3 @@
     E0364, // item is private
     E0365  // item is private
 }
-
-__build_diagnostic_array! { DIAGNOSTICS }
index 61eab4ce9b285e0128cfb57b6311bde190ff93be..7abe5a84c5fff80fde3206c6e0987aa91316cb5a 100644 (file)
@@ -20,6 +20,7 @@
       html_root_url = "http://doc.rust-lang.org/nightly/")]
 
 #![feature(alloc)]
+#![feature(associated_consts)]
 #![feature(collections)]
 #![feature(rustc_diagnostic_macros)]
 #![feature(rustc_private)]
@@ -477,8 +478,8 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
 bitflags! {
     #[derive(Debug)]
     flags DefModifiers: u8 {
-        const PUBLIC            = 0b0000_0001,
-        const IMPORTABLE        = 0b0000_0010,
+        const PUBLIC     = 1 << 0,
+        const IMPORTABLE = 1 << 1,
     }
 }
 
@@ -524,7 +525,11 @@ fn define_module(&self,
                      is_public: bool,
                      sp: Span) {
         // Merges the module with the existing type def or creates a new one.
-        let modifiers = if is_public { PUBLIC } else { DefModifiers::empty() } | IMPORTABLE;
+        let modifiers = if is_public {
+            DefModifiers::PUBLIC
+        } else {
+            DefModifiers::empty()
+        } | DefModifiers::IMPORTABLE;
         let module_ = Rc::new(Module::new(parent_link,
                                           def_id,
                                           kind,
@@ -559,7 +564,11 @@ fn set_module_kind(&self,
                        external: bool,
                        is_public: bool,
                        _sp: Span) {
-        let modifiers = if is_public { PUBLIC } else { DefModifiers::empty() } | IMPORTABLE;
+        let modifiers = if is_public {
+            DefModifiers::PUBLIC
+        } else {
+            DefModifiers::empty()
+        } | DefModifiers::IMPORTABLE;
         let type_def = self.type_def.borrow().clone();
         match type_def {
             None => {
@@ -659,7 +668,7 @@ fn defined_in_namespace(&self, namespace: Namespace) -> bool {
     }
 
     fn defined_in_public_namespace(&self, namespace: Namespace) -> bool {
-        self.defined_in_namespace_with(namespace, PUBLIC)
+        self.defined_in_namespace_with(namespace, DefModifiers::PUBLIC)
     }
 
     fn defined_in_namespace_with(&self, namespace: Namespace, modifiers: DefModifiers) -> bool {
@@ -730,11 +739,11 @@ fn is_public(&self, namespace: Namespace) -> bool {
         match namespace {
             TypeNS  => {
                 let type_def = self.type_def.borrow();
-                type_def.as_ref().unwrap().modifiers.contains(PUBLIC)
+                type_def.as_ref().unwrap().modifiers.contains(DefModifiers::PUBLIC)
             }
             ValueNS => {
                 let value_def = self.value_def.borrow();
-                value_def.as_ref().unwrap().modifiers.contains(PUBLIC)
+                value_def.as_ref().unwrap().modifiers.contains(DefModifiers::PUBLIC)
             }
         }
     }
@@ -921,7 +930,7 @@ fn get_trait_name(&self, did: DefId) -> Name {
     fn create_name_bindings_from_module(module: Rc<Module>) -> NameBindings {
         NameBindings {
             type_def: RefCell::new(Some(TypeNsDef {
-                modifiers: IMPORTABLE,
+                modifiers: DefModifiers::IMPORTABLE,
                 module_def: Some(module),
                 type_def: None,
                 type_span: None
@@ -3697,3 +3706,8 @@ pub fn resolve_crate<'a, 'tcx>(session: &'a Session,
                     },
     }
 }
+
+#[cfg(stage0)]
+__build_diagnostic_array! { DIAGNOSTICS }
+#[cfg(not(stage0))]
+__build_diagnostic_array! { librustc_resolve, DIAGNOSTICS }
index 4b488981bfbc6af7297b8322ed0399f838058c13..350f69d30c4e452d8c0779e6798162aa7e257ae9 100644 (file)
@@ -10,7 +10,7 @@
 
 use self::ImportDirectiveSubclass::*;
 
-use {PUBLIC, IMPORTABLE};
+use DefModifiers;
 use Module;
 use Namespace::{self, TypeNS, ValueNS};
 use NameBindings;
@@ -848,7 +848,9 @@ fn merge_import_resolution(&mut self,
         // Merge the child item into the import resolution.
         {
             let mut merge_child_item = |namespace| {
-                if name_bindings.defined_in_namespace_with(namespace, IMPORTABLE | PUBLIC) {
+                let modifier = DefModifiers::IMPORTABLE | DefModifiers::PUBLIC;
+
+                if name_bindings.defined_in_namespace_with(namespace, modifier) {
                     let namespace_name = match namespace {
                         TypeNS => "type",
                         ValueNS => "value",
@@ -914,7 +916,7 @@ fn check_that_import_is_importable(&mut self,
                                        import_span: Span,
                                        name: Name,
                                        namespace: Namespace) {
-        if !name_bindings.defined_in_namespace_with(namespace, IMPORTABLE) {
+        if !name_bindings.defined_in_namespace_with(namespace, DefModifiers::IMPORTABLE) {
             let msg = format!("`{}` is not directly importable",
                               token::get_name(name));
             span_err!(self.resolver.session, import_span, E0253, "{}", &msg[..]);
index b53be98a06cc30198f16c20db0234319c5fde7af..92c9549b37727adbd9263cc95d52120776ef3efd 100644 (file)
@@ -32,7 +32,7 @@
 use std::fs::{self, PathExt};
 use std::io::{self, Read, Write};
 use std::mem;
-use std::path::{Path, PathBuf};
+use std::path::{self, Path, PathBuf};
 use std::process::Command;
 use std::str;
 use flate;
@@ -794,13 +794,21 @@ fn link_natively(sess: &Session, trans: &CrateTranslation, dylib: bool,
     let pname = get_cc_prog(sess);
     let mut cmd = Command::new(&pname[..]);
 
+    let root = sess.target_filesearch(PathKind::Native).get_lib_path();
     cmd.args(&sess.target.target.options.pre_link_args);
+    for obj in &sess.target.target.options.pre_link_objects {
+        cmd.arg(root.join(obj));
+    }
+
     link_args(&mut cmd, sess, dylib, tmpdir.path(),
               trans, obj_filename, out_filename);
-    cmd.args(&sess.target.target.options.post_link_args);
     if !sess.target.target.options.no_compiler_rt {
         cmd.arg("-lcompiler-rt");
     }
+    for obj in &sess.target.target.options.post_link_objects {
+        cmd.arg(root.join(obj));
+    }
+    cmd.args(&sess.target.target.options.post_link_args);
 
     if sess.opts.debugging_opts.print_link_args {
         println!("{:?}", &cmd);
@@ -864,7 +872,7 @@ fn link_args(cmd: &mut Command,
     // target descriptor
     let t = &sess.target.target;
 
-    cmd.arg("-L").arg(&lib_path);
+    cmd.arg("-L").arg(&fix_windows_verbatim_for_gcc(&lib_path));
 
     cmd.arg("-o").arg(out_filename).arg(obj_filename);
 
@@ -916,8 +924,9 @@ fn link_args(cmd: &mut Command,
         // stripped away as much as it could. This has not been seen to impact
         // link times negatively.
         //
-        // -dead_strip can't be part of the pre_link_args because it's also used for partial
-        // linking when using multiple codegen units (-r). So we insert it here.
+        // -dead_strip can't be part of the pre_link_args because it's also used
+        // for partial linking when using multiple codegen units (-r). So we
+        // insert it here.
         cmd.arg("-Wl,-dead_strip");
     }
 
@@ -1043,7 +1052,6 @@ fn link_args(cmd: &mut Command,
             has_rpath: sess.target.target.options.has_rpath,
             is_like_osx: sess.target.target.options.is_like_osx,
             get_install_prefix_lib_path: &mut get_install_prefix_lib_path,
-            realpath: &mut ::util::fs::realpath
         };
         cmd.args(&rpath::get_rpath_flags(&mut rpath_config));
     }
@@ -1258,7 +1266,7 @@ fn add_static_crate(cmd: &mut Command, sess: &Session, tmpdir: &Path,
                 }
             });
         } else {
-            cmd.arg(cratepath);
+            cmd.arg(&fix_windows_verbatim_for_gcc(cratepath));
         }
     }
 
@@ -1271,7 +1279,7 @@ fn add_dynamic_crate(cmd: &mut Command, sess: &Session, cratepath: &Path) {
         // Just need to tell the linker about where the library lives and
         // what its name is
         if let Some(dir) = cratepath.parent() {
-            cmd.arg("-L").arg(dir);
+            cmd.arg("-L").arg(&fix_windows_verbatim_for_gcc(dir));
         }
         let filestem = cratepath.file_stem().unwrap().to_str().unwrap();
         cmd.arg(&format!("-l{}", unlib(&sess.target, filestem)));
@@ -1325,3 +1333,29 @@ fn add_upstream_native_libraries(cmd: &mut Command, sess: &Session) {
         }
     }
 }
+
+// Unfortunately, on windows, gcc cannot accept paths of the form `\\?\C:\...`
+// (a verbatim path). This form of path is generally pretty rare, but the
+// implementation of `fs::canonicalize` currently generates paths of this form,
+// meaning that we're going to be passing quite a few of these down to gcc.
+//
+// For now we just strip the "verbatim prefix" of `\\?\` from the path. This
+// will probably lose information in some cases, but there's not a whole lot
+// more we can do with a buggy gcc...
+fn fix_windows_verbatim_for_gcc(p: &Path) -> PathBuf {
+    if !cfg!(windows) {
+        return p.to_path_buf()
+    }
+    let mut components = p.components();
+    let prefix = match components.next() {
+        Some(path::Component::Prefix(p)) => p,
+        _ => return p.to_path_buf(),
+    };
+    let disk = match prefix.kind() {
+        path::Prefix::VerbatimDisk(disk) => disk,
+        _ => return p.to_path_buf(),
+    };
+    let mut base = OsString::from(format!("{}:", disk as char));
+    base.push(components.as_path());
+    PathBuf::from(base)
+}
index b0eacd1a55d4150221e924c8b3bf390f8d81d9ca..3e2db80a9c556dbe55076575c8e75dd7c916540e 100644 (file)
@@ -34,7 +34,6 @@
 #![feature(quote)]
 #![feature(rustc_diagnostic_macros)]
 #![feature(rustc_private)]
-#![feature(unsafe_destructor)]
 #![feature(staged_api)]
 #![feature(unicode)]
 #![feature(path_ext)]
index 39cfac42011aba8fe8c92d786ca9353c4aa2e15f..d80086da20315af17357c4ee927f8a7d469875d6 100644 (file)
@@ -295,6 +295,8 @@ fn process_method(&mut self, sig: &ast::MethodSig,
             return;
         }
 
+        debug!("process_method: {}:{}", id, token::get_name(name));
+
         let mut scope_id;
         // The qualname for a method is the trait name or name of the struct in an impl in
         // which the method is declared in, followed by the method's name.
@@ -704,7 +706,7 @@ fn process_impl(&mut self,
 
         self.process_generic_params(type_parameters, item.span, "", item.id);
         for impl_item in impl_items {
-            visit::walk_impl_item(self, impl_item);
+            self.visit_impl_item(impl_item);
         }
     }
 
@@ -1258,7 +1260,7 @@ fn visit_impl_item(&mut self, impl_item: &ast::ImplItem) {
         match impl_item.node {
             ast::ConstImplItem(ref ty, ref expr) => {
                 self.process_const(impl_item.id, &impl_item.ident,
-                                   impl_item.span, &*ty, &*expr);
+                                   impl_item.span, &ty, &expr);
             }
             ast::MethodImplItem(ref sig, ref body) => {
                 self.process_method(sig, Some(body), impl_item.id,
index cecf35001c4eb00097b85afead452b719da981d7..001de615fb1eb3c5fea7ad8fb776cf12752d2adf 100644 (file)
@@ -440,6 +440,22 @@ fn find_discr_field_candidate<'tcx>(tcx: &ty::ctxt<'tcx>,
             None
         },
 
+        // Perhaps one of the upvars of this struct is non-zero
+        // Let's recurse and find out!
+        ty::ty_closure(def_id, substs) => {
+            let typer = NormalizingClosureTyper::new(tcx);
+            let upvars = typer.closure_upvars(def_id, substs).unwrap();
+            let upvar_types = upvars.iter().map(|u| u.ty).collect::<Vec<_>>();
+
+            for (j, &ty) in upvar_types.iter().enumerate() {
+                if let Some(mut fpath) = find_discr_field_candidate(tcx, ty, path.clone()) {
+                    fpath.push(j);
+                    return Some(fpath);
+                }
+            }
+            None
+        },
+
         // Can we use one of the fields in this tuple?
         ty::ty_tup(ref tys) => {
             for (j, &ty) in tys.iter().enumerate() {
index 2615490a9fbc5a584b4b0b7f0fe525df9a0323fb..b44ccec0127bd7f864b387e6d24ae216667a933b 100644 (file)
@@ -39,13 +39,13 @@ pub fn split_stack(val: ValueRef, set: bool) {
 pub fn inline(val: ValueRef, inline: InlineAttr) {
     use self::InlineAttr::*;
     match inline {
-        Hint   => llvm::SetFunctionAttribute(val, llvm::InlineHintAttribute),
-        Always => llvm::SetFunctionAttribute(val, llvm::AlwaysInlineAttribute),
-        Never  => llvm::SetFunctionAttribute(val, llvm::NoInlineAttribute),
+        Hint   => llvm::SetFunctionAttribute(val, llvm::Attribute::InlineHintAttribute),
+        Always => llvm::SetFunctionAttribute(val, llvm::Attribute::AlwaysInlineAttribute),
+        Never  => llvm::SetFunctionAttribute(val, llvm::Attribute::NoInlineAttribute),
         None   => {
-            let attr = llvm::InlineHintAttribute |
-                       llvm::AlwaysInlineAttribute |
-                       llvm::NoInlineAttribute;
+            let attr = llvm::Attribute::InlineHintAttribute |
+                       llvm::Attribute::AlwaysInlineAttribute |
+                       llvm::Attribute::NoInlineAttribute;
             unsafe {
                 llvm::LLVMRemoveFunctionAttr(val, attr.bits() as c_ulonglong)
             }
@@ -57,10 +57,13 @@ pub fn inline(val: ValueRef, inline: InlineAttr) {
 #[inline]
 pub fn emit_uwtable(val: ValueRef, emit: bool) {
     if emit {
-        llvm::SetFunctionAttribute(val, llvm::UWTableAttribute);
+        llvm::SetFunctionAttribute(val, llvm::Attribute::UWTableAttribute);
     } else {
         unsafe {
-            llvm::LLVMRemoveFunctionAttr(val, llvm::UWTableAttribute.bits() as c_ulonglong);
+            llvm::LLVMRemoveFunctionAttr(
+                val,
+                llvm::Attribute::UWTableAttribute.bits() as c_ulonglong,
+            );
         }
     }
 }
@@ -71,10 +74,13 @@ pub fn emit_uwtable(val: ValueRef, emit: bool) {
 pub fn unwind(val: ValueRef, can_unwind: bool) {
     if can_unwind {
         unsafe {
-            llvm::LLVMRemoveFunctionAttr(val, llvm::NoUnwindAttribute.bits() as c_ulonglong);
+            llvm::LLVMRemoveFunctionAttr(
+                val,
+                llvm::Attribute::NoUnwindAttribute.bits() as c_ulonglong,
+            );
         }
     } else {
-        llvm::SetFunctionAttribute(val, llvm::NoUnwindAttribute);
+        llvm::SetFunctionAttribute(val, llvm::Attribute::NoUnwindAttribute);
     }
 }
 
@@ -83,10 +89,13 @@ pub fn unwind(val: ValueRef, can_unwind: bool) {
 #[allow(dead_code)] // possibly useful function
 pub fn set_optimize_for_size(val: ValueRef, optimize: bool) {
     if optimize {
-        llvm::SetFunctionAttribute(val, llvm::OptimizeForSizeAttribute);
+        llvm::SetFunctionAttribute(val, llvm::Attribute::OptimizeForSizeAttribute);
     } else {
         unsafe {
-            llvm::LLVMRemoveFunctionAttr(val, llvm::OptimizeForSizeAttribute.bits() as c_ulonglong);
+            llvm::LLVMRemoveFunctionAttr(
+                val,
+                llvm::Attribute::OptimizeForSizeAttribute.bits() as c_ulonglong,
+            );
         }
     }
 }
@@ -107,7 +116,7 @@ pub fn from_fn_attrs(ccx: &CrateContext, attrs: &[ast::Attribute], llfn: ValueRe
                                                llvm::ColdAttribute as u64)
             }
         } else if attr.check_name("allocator") {
-            llvm::NoAliasAttribute.apply_llfn(llvm::ReturnIndex as c_uint, llfn);
+            llvm::Attribute::NoAliasAttribute.apply_llfn(llvm::ReturnIndex as c_uint, llfn);
         }
     }
 }
@@ -176,9 +185,9 @@ pub fn from_fn_type<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, fn_type: ty::Ty<'tcx
             // The outptr can be noalias and nocapture because it's entirely
             // invisible to the program. We also know it's nonnull as well
             // as how many bytes we can dereference
-            attrs.arg(1, llvm::StructRetAttribute)
-                 .arg(1, llvm::NoAliasAttribute)
-                 .arg(1, llvm::NoCaptureAttribute)
+            attrs.arg(1, llvm::Attribute::StructRetAttribute)
+                 .arg(1, llvm::Attribute::NoAliasAttribute)
+                 .arg(1, llvm::Attribute::NoCaptureAttribute)
                  .arg(1, llvm::DereferenceableAttribute(llret_sz));
 
             // Add one more since there's an outptr
@@ -190,7 +199,7 @@ pub fn from_fn_type<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, fn_type: ty::Ty<'tcx
                 // `~` pointer return values never alias because ownership
                 // is transferred
                 ty::ty_uniq(it) if common::type_is_sized(ccx.tcx(), it) => {
-                    attrs.ret(llvm::NoAliasAttribute);
+                    attrs.ret(llvm::Attribute::NoAliasAttribute);
                 }
                 _ => {}
             }
@@ -207,7 +216,7 @@ pub fn from_fn_type<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, fn_type: ty::Ty<'tcx
             }
 
             if let ty::ty_bool = ret_ty.sty {
-                attrs.ret(llvm::ZExtAttribute);
+                attrs.ret(llvm::Attribute::ZExtAttribute);
             }
         }
     }
@@ -221,20 +230,20 @@ pub fn from_fn_type<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, fn_type: ty::Ty<'tcx
                 // For non-immediate arguments the callee gets its own copy of
                 // the value on the stack, so there are no aliases. It's also
                 // program-invisible so can't possibly capture
-                attrs.arg(idx, llvm::NoAliasAttribute)
-                     .arg(idx, llvm::NoCaptureAttribute)
+                attrs.arg(idx, llvm::Attribute::NoAliasAttribute)
+                     .arg(idx, llvm::Attribute::NoCaptureAttribute)
                      .arg(idx, llvm::DereferenceableAttribute(llarg_sz));
             }
 
             ty::ty_bool => {
-                attrs.arg(idx, llvm::ZExtAttribute);
+                attrs.arg(idx, llvm::Attribute::ZExtAttribute);
             }
 
             // `~` pointer parameters never alias because ownership is transferred
             ty::ty_uniq(inner) => {
                 let llsz = machine::llsize_of_real(ccx, type_of::type_of(ccx, inner));
 
-                attrs.arg(idx, llvm::NoAliasAttribute)
+                attrs.arg(idx, llvm::Attribute::NoAliasAttribute)
                      .arg(idx, llvm::DereferenceableAttribute(llsz));
             }
 
@@ -247,15 +256,15 @@ pub fn from_fn_type<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, fn_type: ty::Ty<'tcx
                                   !ty::type_contents(ccx.tcx(), mt.ty).interior_unsafe() => {
 
                 let llsz = machine::llsize_of_real(ccx, type_of::type_of(ccx, mt.ty));
-                attrs.arg(idx, llvm::NoAliasAttribute)
+                attrs.arg(idx, llvm::Attribute::NoAliasAttribute)
                      .arg(idx, llvm::DereferenceableAttribute(llsz));
 
                 if mt.mutbl == ast::MutImmutable {
-                    attrs.arg(idx, llvm::ReadOnlyAttribute);
+                    attrs.arg(idx, llvm::Attribute::ReadOnlyAttribute);
                 }
 
                 if let ReLateBound(_, BrAnon(_)) = *b {
-                    attrs.arg(idx, llvm::NoCaptureAttribute);
+                    attrs.arg(idx, llvm::Attribute::NoCaptureAttribute);
                 }
             }
 
@@ -263,7 +272,7 @@ pub fn from_fn_type<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, fn_type: ty::Ty<'tcx
             // reference to escape this function (returned or stored beyond the call by a closure).
             ty::ty_rptr(&ReLateBound(_, BrAnon(_)), mt) => {
                 let llsz = machine::llsize_of_real(ccx, type_of::type_of(ccx, mt.ty));
-                attrs.arg(idx, llvm::NoCaptureAttribute)
+                attrs.arg(idx, llvm::Attribute::NoCaptureAttribute)
                      .arg(idx, llvm::DereferenceableAttribute(llsz));
             }
 
index 1e5b4d4d5ff333f26491585e5fb2cec52bc4d6bc..4879975dde695c265bd7505b3e1127a0bccebf5c 100644 (file)
@@ -125,7 +125,6 @@ pub struct _InsnCtxt {
     _cannot_construct_outside_of_this_module: ()
 }
 
-#[unsafe_destructor]
 impl Drop for _InsnCtxt {
     fn drop(&mut self) {
         TASK_LOCAL_INSN_KEY.with(|slot| {
@@ -166,7 +165,6 @@ pub fn new(ccx: &'a CrateContext<'a, 'tcx>, name: String)
     }
 }
 
-#[unsafe_destructor]
 impl<'a, 'tcx> Drop for StatRecorder<'a, 'tcx> {
     fn drop(&mut self) {
         if self.ccx.sess().trans_stats() {
@@ -2184,7 +2182,7 @@ fn create_entry_fn(ccx: &CrateContext,
         unsafe {
             llvm::LLVMPositionBuilderAtEnd(bld, llbb);
 
-            debuginfo::insert_reference_to_gdb_debug_scripts_section_global(ccx);
+            debuginfo::gdb::insert_reference_to_gdb_debug_scripts_section_global(ccx);
 
             let (start_fn, args) = if use_start_lang_item {
                 let start_def_id = match ccx.tcx().lang_items.require(StartFnLangItem) {
index 32d73e50e6b6bf1b3cef7a46f21c907be169a5fc..d6ac412a4faead9678cc7711671e87e40a1e78df 100644 (file)
@@ -12,7 +12,7 @@
 #![allow(non_snake_case)]
 
 use llvm;
-use llvm::{CallConv, AtomicBinOp, AtomicOrdering, AsmDialect, AttrBuilder};
+use llvm::{CallConv, AtomicBinOp, AtomicOrdering, SynchronizationScope, AsmDialect, AttrBuilder};
 use llvm::{Opcode, IntPredicate, RealPredicate};
 use llvm::{ValueRef, BasicBlockRef};
 use trans::common::*;
@@ -965,9 +965,9 @@ pub fn CallWithConv(cx: Block,
     B(cx).call_with_conv(fn_, args, conv, attributes)
 }
 
-pub fn AtomicFence(cx: Block, order: AtomicOrdering) {
+pub fn AtomicFence(cx: Block, order: AtomicOrdering, scope: SynchronizationScope) {
     if cx.unreachable.get() { return; }
-    B(cx).atomic_fence(order)
+    B(cx).atomic_fence(order, scope)
 }
 
 pub fn Select(cx: Block, if_: ValueRef, then: ValueRef, else_: ValueRef) -> ValueRef {
index 3febd41bdce2eccbdccf71ff79947fa68e48639c..497e0ae422c1fa3659c17eadb3e0140b518f5956 100644 (file)
@@ -11,7 +11,7 @@
 #![allow(dead_code)] // FFI wrappers
 
 use llvm;
-use llvm::{CallConv, AtomicBinOp, AtomicOrdering, AsmDialect, AttrBuilder};
+use llvm::{CallConv, AtomicBinOp, AtomicOrdering, SynchronizationScope, AsmDialect, AttrBuilder};
 use llvm::{Opcode, IntPredicate, RealPredicate, False};
 use llvm::{ValueRef, BasicBlockRef, BuilderRef, ModuleRef};
 use trans::base;
@@ -989,9 +989,9 @@ pub fn atomic_rmw(&self, op: AtomicBinOp,
         }
     }
 
-    pub fn atomic_fence(&self, order: AtomicOrdering) {
+    pub fn atomic_fence(&self, order: AtomicOrdering, scope: SynchronizationScope) {
         unsafe {
-            llvm::LLVMBuildAtomicFence(self.llbuilder, order);
+            llvm::LLVMBuildAtomicFence(self.llbuilder, order, scope);
         }
     }
 }
index 57dd22233882867a4b32f54aae8c2ee8da8be398..2eef678673987dc8ee28cbfdfa57fe469e776f9b 100644 (file)
@@ -10,8 +10,7 @@
 
 #![allow(non_upper_case_globals)]
 
-use llvm::{Integer, Pointer, Float, Double, Struct, Array, Vector};
-use llvm::{StructRetAttribute, ZExtAttribute};
+use llvm::{Integer, Pointer, Float, Double, Struct, Array, Vector, Attribute};
 use trans::cabi::{FnType, ArgType};
 use trans::context::CrateContext;
 use trans::type_::Type;
@@ -164,7 +163,7 @@ fn check_struct(ty: Type) -> Option<(Type, u64)> {
 
 fn classify_ret_ty(ccx: &CrateContext, ty: Type) -> ArgType {
     if is_reg_ty(ty) {
-        let attr = if ty == Type::i1(ccx) { Some(ZExtAttribute) } else { None };
+        let attr = if ty == Type::i1(ccx) { Some(Attribute::ZExtAttribute) } else { None };
         return ArgType::direct(ty, None, None, attr);
     }
     if let Some((base_ty, members)) = is_homogenous_aggregate_ty(ty) {
@@ -186,12 +185,12 @@ fn classify_ret_ty(ccx: &CrateContext, ty: Type) -> ArgType {
         };
         return ArgType::direct(ty, Some(llty), None, None);
     }
-    ArgType::indirect(ty, Some(StructRetAttribute))
+    ArgType::indirect(ty, Some(Attribute::StructRetAttribute))
 }
 
 fn classify_arg_ty(ccx: &CrateContext, ty: Type) -> ArgType {
     if is_reg_ty(ty) {
-        let attr = if ty == Type::i1(ccx) { Some(ZExtAttribute) } else { None };
+        let attr = if ty == Type::i1(ccx) { Some(Attribute::ZExtAttribute) } else { None };
         return ArgType::direct(ty, None, None, attr);
     }
     if let Some((base_ty, members)) = is_homogenous_aggregate_ty(ty) {
index 941c065e3d5d43b9769ce8bc49bf44c60dd0bf64..689b3b3ad37eef5695cc2f02a75c04b40b1327ba 100644 (file)
@@ -10,8 +10,7 @@
 
 #![allow(non_upper_case_globals)]
 
-use llvm::{Integer, Pointer, Float, Double, Struct, Array, Vector};
-use llvm::{StructRetAttribute, ZExtAttribute};
+use llvm::{Integer, Pointer, Float, Double, Struct, Array, Vector, Attribute};
 use trans::cabi::{FnType, ArgType};
 use trans::context::CrateContext;
 use trans::type_::Type;
@@ -132,7 +131,7 @@ fn ty_size(ty: Type, align_fn: TyAlignFn) -> usize {
 
 fn classify_ret_ty(ccx: &CrateContext, ty: Type, align_fn: TyAlignFn) -> ArgType {
     if is_reg_ty(ty) {
-        let attr = if ty == Type::i1(ccx) { Some(ZExtAttribute) } else { None };
+        let attr = if ty == Type::i1(ccx) { Some(Attribute::ZExtAttribute) } else { None };
         return ArgType::direct(ty, None, None, attr);
     }
     let size = ty_size(ty, align_fn);
@@ -146,12 +145,12 @@ fn classify_ret_ty(ccx: &CrateContext, ty: Type, align_fn: TyAlignFn) -> ArgType
         };
         return ArgType::direct(ty, Some(llty), None, None);
     }
-    ArgType::indirect(ty, Some(StructRetAttribute))
+    ArgType::indirect(ty, Some(Attribute::StructRetAttribute))
 }
 
 fn classify_arg_ty(ccx: &CrateContext, ty: Type, align_fn: TyAlignFn) -> ArgType {
     if is_reg_ty(ty) {
-        let attr = if ty == Type::i1(ccx) { Some(ZExtAttribute) } else { None };
+        let attr = if ty == Type::i1(ccx) { Some(Attribute::ZExtAttribute) } else { None };
         return ArgType::direct(ty, None, None, attr);
     }
     let align = align_fn(ty);
index 2d7fdd2f2eba47a0acdcff06e96804d69bb680e3..2e899f72979d7e491233dbff117ea88e163e624a 100644 (file)
@@ -13,8 +13,7 @@
 use libc::c_uint;
 use std::cmp;
 use llvm;
-use llvm::{Integer, Pointer, Float, Double, Struct, Array, Vector};
-use llvm::{StructRetAttribute, ZExtAttribute};
+use llvm::{Integer, Pointer, Float, Double, Struct, Array, Vector, Attribute};
 use trans::cabi::{ArgType, FnType};
 use trans::context::CrateContext;
 use trans::type_::Type;
@@ -89,10 +88,10 @@ fn ty_size(ty: Type) -> usize {
 
 fn classify_ret_ty(ccx: &CrateContext, ty: Type) -> ArgType {
     if is_reg_ty(ty) {
-        let attr = if ty == Type::i1(ccx) { Some(ZExtAttribute) } else { None };
+        let attr = if ty == Type::i1(ccx) { Some(Attribute::ZExtAttribute) } else { None };
         ArgType::direct(ty, None, None, attr)
     } else {
-        ArgType::indirect(ty, Some(StructRetAttribute))
+        ArgType::indirect(ty, Some(Attribute::StructRetAttribute))
     }
 }
 
@@ -106,7 +105,7 @@ fn classify_arg_ty(ccx: &CrateContext, ty: Type, offset: &mut usize) -> ArgType
     *offset += align_up_to(size, align * 8) / 8;
 
     if is_reg_ty(ty) {
-        let attr = if ty == Type::i1(ccx) { Some(ZExtAttribute) } else { None };
+        let attr = if ty == Type::i1(ccx) { Some(Attribute::ZExtAttribute) } else { None };
         ArgType::direct(ty, None, None, attr)
     } else {
         ArgType::direct(
index 8c30d4fcc2b1f2c35310ee9dd557819f4e1f8842..eae2378a2c518e0fd970a7495ea975bec4d1d4c2 100644 (file)
@@ -10,8 +10,7 @@
 
 use libc::c_uint;
 use llvm;
-use llvm::{Integer, Pointer, Float, Double, Struct, Array};
-use llvm::{StructRetAttribute, ZExtAttribute};
+use llvm::{Integer, Pointer, Float, Double, Struct, Array, Attribute};
 use trans::cabi::{FnType, ArgType};
 use trans::context::CrateContext;
 use trans::type_::Type;
@@ -85,10 +84,10 @@ fn ty_size(ty: Type) -> usize {
 
 fn classify_ret_ty(ccx: &CrateContext, ty: Type) -> ArgType {
     if is_reg_ty(ty) {
-        let attr = if ty == Type::i1(ccx) { Some(ZExtAttribute) } else { None };
+        let attr = if ty == Type::i1(ccx) { Some(Attribute::ZExtAttribute) } else { None };
         ArgType::direct(ty, None, None, attr)
     } else {
-        ArgType::indirect(ty, Some(StructRetAttribute))
+        ArgType::indirect(ty, Some(Attribute::StructRetAttribute))
     }
 }
 
@@ -102,7 +101,7 @@ fn classify_arg_ty(ccx: &CrateContext, ty: Type, offset: &mut usize) -> ArgType
     *offset += align_up_to(size, align * 8) / 8;
 
     if is_reg_ty(ty) {
-        let attr = if ty == Type::i1(ccx) { Some(ZExtAttribute) } else { None };
+        let attr = if ty == Type::i1(ccx) { Some(Attribute::ZExtAttribute) } else { None };
         ArgType::direct(ty, None, None, attr)
     } else {
         ArgType::direct(
index 028d20f308474eea3eed27a71d5059a5edf5a86f..d9c265d94a793e8f92c534e6d334ee2035e8f4e9 100644 (file)
@@ -52,11 +52,11 @@ pub fn compute_abi_info(ccx: &CrateContext,
                 ret_ty = ArgType::direct(rty, Some(t), None, None);
             }
             RetPointer => {
-                ret_ty = ArgType::indirect(rty, Some(StructRetAttribute));
+                ret_ty = ArgType::indirect(rty, Some(Attribute::StructRetAttribute));
             }
         }
     } else {
-        let attr = if rty == Type::i1(ccx) { Some(ZExtAttribute) } else { None };
+        let attr = if rty == Type::i1(ccx) { Some(Attribute::ZExtAttribute) } else { None };
         ret_ty = ArgType::direct(rty, None, None, attr);
     }
 
@@ -67,11 +67,11 @@ pub fn compute_abi_info(ccx: &CrateContext,
                 if size == 0 {
                     ArgType::ignore(t)
                 } else {
-                    ArgType::indirect(t, Some(ByValAttribute))
+                    ArgType::indirect(t, Some(Attribute::ByValAttribute))
                 }
             }
             _ => {
-                let attr = if t == Type::i1(ccx) { Some(ZExtAttribute) } else { None };
+                let attr = if t == Type::i1(ccx) { Some(Attribute::ZExtAttribute) } else { None };
                 ArgType::direct(t, None, None, attr)
             }
         };
index 8d946e2743bdf0d5fe90fc726e3b8fcf02962443..d954a861a7267390256e87685d1abef932e22074 100644 (file)
@@ -16,7 +16,6 @@
 
 use llvm::{Integer, Pointer, Float, Double};
 use llvm::{Struct, Array, Attribute, Vector};
-use llvm::{StructRetAttribute, ByValAttribute, ZExtAttribute};
 use trans::cabi::{ArgType, FnType};
 use trans::context::CrateContext;
 use trans::type_::Type;
@@ -407,19 +406,19 @@ fn x86_64_ty<F>(ccx: &CrateContext,
                                 None)
             }
         } else {
-            let attr = if ty == Type::i1(ccx) { Some(ZExtAttribute) } else { None };
+            let attr = if ty == Type::i1(ccx) { Some(Attribute::ZExtAttribute) } else { None };
             ArgType::direct(ty, None, None, attr)
         }
     }
 
     let mut arg_tys = Vec::new();
     for t in atys {
-        let ty = x86_64_ty(ccx, *t, |cls| cls.is_pass_byval(), ByValAttribute);
+        let ty = x86_64_ty(ccx, *t, |cls| cls.is_pass_byval(), Attribute::ByValAttribute);
         arg_tys.push(ty);
     }
 
     let ret_ty = if ret_def {
-        x86_64_ty(ccx, rty, |cls| cls.is_ret_bysret(), StructRetAttribute)
+        x86_64_ty(ccx, rty, |cls| cls.is_ret_bysret(), Attribute::StructRetAttribute)
     } else {
         ArgType::direct(Type::void(ccx), None, None, None)
     };
index 9b34c3bf26200a7585b52779c3502ca7b5b72c6a..7808b9d27feead1a39005e8bc6e3a2b120719768 100644 (file)
@@ -31,10 +31,10 @@ pub fn compute_abi_info(ccx: &CrateContext,
             2 => ArgType::direct(rty, Some(Type::i16(ccx)), None, None),
             4 => ArgType::direct(rty, Some(Type::i32(ccx)), None, None),
             8 => ArgType::direct(rty, Some(Type::i64(ccx)), None, None),
-            _ => ArgType::indirect(rty, Some(StructRetAttribute))
+            _ => ArgType::indirect(rty, Some(Attribute::StructRetAttribute))
         };
     } else {
-        let attr = if rty == Type::i1(ccx) { Some(ZExtAttribute) } else { None };
+        let attr = if rty == Type::i1(ccx) { Some(Attribute::ZExtAttribute) } else { None };
         ret_ty = ArgType::direct(rty, None, None, attr);
     }
 
@@ -46,11 +46,11 @@ pub fn compute_abi_info(ccx: &CrateContext,
                     2 => ArgType::direct(rty, Some(Type::i16(ccx)), None, None),
                     4 => ArgType::direct(rty, Some(Type::i32(ccx)), None, None),
                     8 => ArgType::direct(rty, Some(Type::i64(ccx)), None, None),
-                    _ => ArgType::indirect(t, Some(ByValAttribute))
+                    _ => ArgType::indirect(t, Some(Attribute::ByValAttribute))
                 }
             }
             _ => {
-                let attr = if t == Type::i1(ccx) { Some(ZExtAttribute) } else { None };
+                let attr = if t == Type::i1(ccx) { Some(Attribute::ZExtAttribute) } else { None };
                 ArgType::direct(t, None, None, attr)
             }
         };
index 3ec73ff8eb9de129ffb1b8afe40b9b98556cc570..637325881436dd8e2e1b1c6ad2b076b017f2773c 100644 (file)
@@ -438,10 +438,10 @@ fn schedule_drop_and_fill_mem(&self,
     /// `ty`. The scheduled code handles extracting the discriminant
     /// and dropping the contents associated with that variant
     /// *without* executing any associated drop implementation.
-    fn schedule_drop_enum_contents(&self,
-                                   cleanup_scope: ScopeId,
-                                   val: ValueRef,
-                                   ty: Ty<'tcx>) {
+    fn schedule_drop_adt_contents(&self,
+                                  cleanup_scope: ScopeId,
+                                  val: ValueRef,
+                                  ty: Ty<'tcx>) {
         // `if` below could be "!contents_needs_drop"; skipping drop
         // is just an optimization, so sound to be conservative.
         if !self.type_needs_drop(ty) { return; }
@@ -455,7 +455,7 @@ fn schedule_drop_enum_contents(&self,
             skip_dtor: true,
         };
 
-        debug!("schedule_drop_enum_contents({:?}, val={}, ty={}) fill_on_drop={} skip_dtor={}",
+        debug!("schedule_drop_adt_contents({:?}, val={}, ty={}) fill_on_drop={} skip_dtor={}",
                cleanup_scope,
                self.ccx.tn().val_to_string(val),
                ty.repr(self.ccx.tcx()),
@@ -1240,10 +1240,10 @@ fn schedule_drop_and_fill_mem(&self,
                                   cleanup_scope: ScopeId,
                                   val: ValueRef,
                                   ty: Ty<'tcx>);
-    fn schedule_drop_enum_contents(&self,
-                                   cleanup_scope: ScopeId,
-                                   val: ValueRef,
-                                   ty: Ty<'tcx>);
+    fn schedule_drop_adt_contents(&self,
+                                  cleanup_scope: ScopeId,
+                                  val: ValueRef,
+                                  ty: Ty<'tcx>);
     fn schedule_drop_immediate(&self,
                                cleanup_scope: ScopeId,
                                val: ValueRef,
index 9932899ed8f0f64da56f4075ceeb3f6553418892..3aaf4addd89626fc8d99540832099e0198fef317 100644 (file)
@@ -186,7 +186,7 @@ fn get_const_val(ccx: &CrateContext,
                  ref_expr: &ast::Expr) -> ValueRef {
     let expr = get_const_expr(ccx, def_id, ref_expr);
     let empty_substs = ccx.tcx().mk_substs(Substs::trans_empty());
-    get_const_expr_as_global(ccx, expr, check_const::PURE_CONST, empty_substs)
+    get_const_expr_as_global(ccx, expr, check_const::ConstQualif::PURE_CONST, empty_substs)
 }
 
 pub fn get_const_expr_as_global<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
@@ -215,7 +215,7 @@ pub fn get_const_expr_as_global<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
         Some(&val) => return val,
         None => {}
     }
-    let val = if qualif.intersects(check_const::NON_STATIC_BORROWS) {
+    let val = if qualif.intersects(check_const::ConstQualif::NON_STATIC_BORROWS) {
         // Avoid autorefs as they would create global instead of stack
         // references, even when only the latter are correct.
         let ty = monomorphize::apply_param_substs(ccx.tcx(), param_substs,
index 1506e5b266981fc5bd11097bad1f2769cc02ffd2..41ef566f2fd7f8e916c7af0039a62e28d91dc9c4 100644 (file)
@@ -735,6 +735,7 @@ pub fn check_drop_flag_for_sanity(&self) -> bool {
     }
 }
 
+/// Declare any llvm intrinsics that you might need
 fn declare_intrinsic(ccx: &CrateContext, key: & &'static str) -> Option<ValueRef> {
     macro_rules! ifn {
         ($name:expr, fn() -> $ret:expr) => (
diff --git a/src/librustc_trans/trans/debuginfo.rs b/src/librustc_trans/trans/debuginfo.rs
deleted file mode 100644 (file)
index 516ff44..0000000
+++ /dev/null
@@ -1,4107 +0,0 @@
-// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-//! # Debug Info Module
-//!
-//! This module serves the purpose of generating debug symbols. We use LLVM's
-//! [source level debugging](http://llvm.org/docs/SourceLevelDebugging.html)
-//! features for generating the debug information. The general principle is this:
-//!
-//! Given the right metadata in the LLVM IR, the LLVM code generator is able to
-//! create DWARF debug symbols for the given code. The
-//! [metadata](http://llvm.org/docs/LangRef.html#metadata-type) is structured much
-//! like DWARF *debugging information entries* (DIE), representing type information
-//! such as datatype layout, function signatures, block layout, variable location
-//! and scope information, etc. It is the purpose of this module to generate correct
-//! metadata and insert it into the LLVM IR.
-//!
-//! As the exact format of metadata trees may change between different LLVM
-//! versions, we now use LLVM
-//! [DIBuilder](http://llvm.org/docs/doxygen/html/classllvm_1_1DIBuilder.html) to
-//! create metadata where possible. This will hopefully ease the adaption of this
-//! module to future LLVM versions.
-//!
-//! The public API of the module is a set of functions that will insert the correct
-//! metadata into the LLVM IR when called with the right parameters. The module is
-//! thus driven from an outside client with functions like
-//! `debuginfo::create_local_var_metadata(bcx: block, local: &ast::local)`.
-//!
-//! Internally the module will try to reuse already created metadata by utilizing a
-//! cache. The way to get a shared metadata node when needed is thus to just call
-//! the corresponding function in this module:
-//!
-//!     let file_metadata = file_metadata(crate_context, path);
-//!
-//! The function will take care of probing the cache for an existing node for that
-//! exact file path.
-//!
-//! All private state used by the module is stored within either the
-//! CrateDebugContext struct (owned by the CrateContext) or the FunctionDebugContext
-//! (owned by the FunctionContext).
-//!
-//! This file consists of three conceptual sections:
-//! 1. The public interface of the module
-//! 2. Module-internal metadata creation functions
-//! 3. Minor utility functions
-//!
-//!
-//! ## Recursive Types
-//!
-//! Some kinds of types, such as structs and enums can be recursive. That means that
-//! the type definition of some type X refers to some other type which in turn
-//! (transitively) refers to X. This introduces cycles into the type referral graph.
-//! A naive algorithm doing an on-demand, depth-first traversal of this graph when
-//! describing types, can get trapped in an endless loop when it reaches such a
-//! cycle.
-//!
-//! For example, the following simple type for a singly-linked list...
-//!
-//! ```
-//! struct List {
-//!     value: int,
-//!     tail: Option<Box<List>>,
-//! }
-//! ```
-//!
-//! will generate the following callstack with a naive DFS algorithm:
-//!
-//! ```
-//! describe(t = List)
-//!   describe(t = int)
-//!   describe(t = Option<Box<List>>)
-//!     describe(t = Box<List>)
-//!       describe(t = List) // at the beginning again...
-//!       ...
-//! ```
-//!
-//! To break cycles like these, we use "forward declarations". That is, when the
-//! algorithm encounters a possibly recursive type (any struct or enum), it
-//! immediately creates a type description node and inserts it into the cache
-//! *before* describing the members of the type. This type description is just a
-//! stub (as type members are not described and added to it yet) but it allows the
-//! algorithm to already refer to the type. After the stub is inserted into the
-//! cache, the algorithm continues as before. If it now encounters a recursive
-//! reference, it will hit the cache and does not try to describe the type anew.
-//!
-//! This behaviour is encapsulated in the 'RecursiveTypeDescription' enum, which
-//! represents a kind of continuation, storing all state needed to continue
-//! traversal at the type members after the type has been registered with the cache.
-//! (This implementation approach might be a tad over-engineered and may change in
-//! the future)
-//!
-//!
-//! ## Source Locations and Line Information
-//!
-//! In addition to data type descriptions the debugging information must also allow
-//! to map machine code locations back to source code locations in order to be useful.
-//! This functionality is also handled in this module. The following functions allow
-//! to control source mappings:
-//!
-//! + set_source_location()
-//! + clear_source_location()
-//! + start_emitting_source_locations()
-//!
-//! `set_source_location()` allows to set the current source location. All IR
-//! instructions created after a call to this function will be linked to the given
-//! source location, until another location is specified with
-//! `set_source_location()` or the source location is cleared with
-//! `clear_source_location()`. In the later case, subsequent IR instruction will not
-//! be linked to any source location. As you can see, this is a stateful API
-//! (mimicking the one in LLVM), so be careful with source locations set by previous
-//! calls. It's probably best to not rely on any specific state being present at a
-//! given point in code.
-//!
-//! One topic that deserves some extra attention is *function prologues*. At the
-//! beginning of a function's machine code there are typically a few instructions
-//! for loading argument values into allocas and checking if there's enough stack
-//! space for the function to execute. This *prologue* is not visible in the source
-//! code and LLVM puts a special PROLOGUE END marker into the line table at the
-//! first non-prologue instruction of the function. In order to find out where the
-//! prologue ends, LLVM looks for the first instruction in the function body that is
-//! linked to a source location. So, when generating prologue instructions we have
-//! to make sure that we don't emit source location information until the 'real'
-//! function body begins. For this reason, source location emission is disabled by
-//! default for any new function being translated and is only activated after a call
-//! to the third function from the list above, `start_emitting_source_locations()`.
-//! This function should be called right before regularly starting to translate the
-//! top-level block of the given function.
-//!
-//! There is one exception to the above rule: `llvm.dbg.declare` instruction must be
-//! linked to the source location of the variable being declared. For function
-//! parameters these `llvm.dbg.declare` instructions typically occur in the middle
-//! of the prologue, however, they are ignored by LLVM's prologue detection. The
-//! `create_argument_metadata()` and related functions take care of linking the
-//! `llvm.dbg.declare` instructions to the correct source locations even while
-//! source location emission is still disabled, so there is no need to do anything
-//! special with source location handling here.
-//!
-//! ## Unique Type Identification
-//!
-//! In order for link-time optimization to work properly, LLVM needs a unique type
-//! identifier that tells it across compilation units which types are the same as
-//! others. This type identifier is created by TypeMap::get_unique_type_id_of_type()
-//! using the following algorithm:
-//!
-//! (1) Primitive types have their name as ID
-//! (2) Structs, enums and traits have a multipart identifier
-//!
-//!     (1) The first part is the SVH (strict version hash) of the crate they were
-//!         originally defined in
-//!
-//!     (2) The second part is the ast::NodeId of the definition in their original
-//!         crate
-//!
-//!     (3) The final part is a concatenation of the type IDs of their concrete type
-//!         arguments if they are generic types.
-//!
-//! (3) Tuple-, pointer and function types are structurally identified, which means
-//!     that they are equivalent if their component types are equivalent (i.e. (int,
-//!     int) is the same regardless in which crate it is used).
-//!
-//! This algorithm also provides a stable ID for types that are defined in one crate
-//! but instantiated from metadata within another crate. We just have to take care
-//! to always map crate and node IDs back to the original crate context.
-//!
-//! As a side-effect these unique type IDs also help to solve a problem arising from
-//! lifetime parameters. Since lifetime parameters are completely omitted in
-//! debuginfo, more than one `Ty` instance may map to the same debuginfo type
-//! metadata, that is, some struct `Struct<'a>` may have N instantiations with
-//! different concrete substitutions for `'a`, and thus there will be N `Ty`
-//! instances for the type `Struct<'a>` even though it is not generic otherwise.
-//! Unfortunately this means that we cannot use `ty::type_id()` as cheap identifier
-//! for type metadata---we have done this in the past, but it led to unnecessary
-//! metadata duplication in the best case and LLVM assertions in the worst. However,
-//! the unique type ID as described above *can* be used as identifier. Since it is
-//! comparatively expensive to construct, though, `ty::type_id()` is still used
-//! additionally as an optimization for cases where the exact same type has been
-//! seen before (which is most of the time).
-use self::VariableAccess::*;
-use self::VariableKind::*;
-use self::MemberOffset::*;
-use self::MemberDescriptionFactory::*;
-use self::RecursiveTypeDescription::*;
-use self::EnumDiscriminantInfo::*;
-use self::InternalDebugLocation::*;
-
-use llvm;
-use llvm::{ModuleRef, ContextRef, ValueRef};
-use llvm::debuginfo::*;
-use metadata::csearch;
-use middle::subst::{self, Substs};
-use trans::{self, adt, machine, type_of};
-use trans::common::{self, NodeIdAndSpan, CrateContext, FunctionContext, Block, C_bytes,
-                    NormalizingClosureTyper};
-use trans::declare;
-use trans::_match::{BindingInfo, TrByCopy, TrByMove, TrByRef};
-use trans::monomorphize;
-use trans::type_::Type;
-use middle::ty::{self, Ty, ClosureTyper};
-use middle::pat_util;
-use session::config::{self, FullDebugInfo, LimitedDebugInfo, NoDebugInfo};
-use util::nodemap::{DefIdMap, NodeMap, FnvHashMap, FnvHashSet};
-use util::ppaux;
-use util::common::path2cstr;
-
-use libc::{c_uint, c_longlong};
-use std::cell::{Cell, RefCell};
-use std::ffi::CString;
-use std::path::Path;
-use std::ptr;
-use std::rc::{Rc, Weak};
-use syntax::util::interner::Interner;
-use syntax::codemap::{Span, Pos};
-use syntax::{ast, codemap, ast_util, ast_map, attr};
-use syntax::parse::token::{self, special_idents};
-
-const DW_LANG_RUST: c_uint = 0x9000;
-
-#[allow(non_upper_case_globals)]
-const DW_TAG_auto_variable: c_uint = 0x100;
-#[allow(non_upper_case_globals)]
-const DW_TAG_arg_variable: c_uint = 0x101;
-
-#[allow(non_upper_case_globals)]
-const DW_ATE_boolean: c_uint = 0x02;
-#[allow(non_upper_case_globals)]
-const DW_ATE_float: c_uint = 0x04;
-#[allow(non_upper_case_globals)]
-const DW_ATE_signed: c_uint = 0x05;
-#[allow(non_upper_case_globals)]
-const DW_ATE_unsigned: c_uint = 0x07;
-#[allow(non_upper_case_globals)]
-const DW_ATE_unsigned_char: c_uint = 0x08;
-
-const UNKNOWN_LINE_NUMBER: c_uint = 0;
-const UNKNOWN_COLUMN_NUMBER: c_uint = 0;
-
-// ptr::null() doesn't work :(
-const UNKNOWN_FILE_METADATA: DIFile = (0 as DIFile);
-const UNKNOWN_SCOPE_METADATA: DIScope = (0 as DIScope);
-
-const FLAGS_NONE: c_uint = 0;
-
-//=-----------------------------------------------------------------------------
-//  Public Interface of debuginfo module
-//=-----------------------------------------------------------------------------
-
-#[derive(Copy, Debug, Hash, Eq, PartialEq, Clone)]
-struct UniqueTypeId(ast::Name);
-
-// The TypeMap is where the CrateDebugContext holds the type metadata nodes
-// created so far. The metadata nodes are indexed by UniqueTypeId, and, for
-// faster lookup, also by Ty. The TypeMap is responsible for creating
-// UniqueTypeIds.
-struct TypeMap<'tcx> {
-    // The UniqueTypeIds created so far
-    unique_id_interner: Interner<Rc<String>>,
-    // A map from UniqueTypeId to debuginfo metadata for that type. This is a 1:1 mapping.
-    unique_id_to_metadata: FnvHashMap<UniqueTypeId, DIType>,
-    // A map from types to debuginfo metadata. This is a N:1 mapping.
-    type_to_metadata: FnvHashMap<Ty<'tcx>, DIType>,
-    // A map from types to UniqueTypeId. This is a N:1 mapping.
-    type_to_unique_id: FnvHashMap<Ty<'tcx>, UniqueTypeId>
-}
-
-impl<'tcx> TypeMap<'tcx> {
-
-    fn new() -> TypeMap<'tcx> {
-        TypeMap {
-            unique_id_interner: Interner::new(),
-            type_to_metadata: FnvHashMap(),
-            unique_id_to_metadata: FnvHashMap(),
-            type_to_unique_id: FnvHashMap(),
-        }
-    }
-
-    // Adds a Ty to metadata mapping to the TypeMap. The method will fail if
-    // the mapping already exists.
-    fn register_type_with_metadata<'a>(&mut self,
-                                       cx: &CrateContext<'a, 'tcx>,
-                                       type_: Ty<'tcx>,
-                                       metadata: DIType) {
-        if self.type_to_metadata.insert(type_, metadata).is_some() {
-            cx.sess().bug(&format!("Type metadata for Ty '{}' is already in the TypeMap!",
-                                   ppaux::ty_to_string(cx.tcx(), type_)));
-        }
-    }
-
-    // Adds a UniqueTypeId to metadata mapping to the TypeMap. The method will
-    // fail if the mapping already exists.
-    fn register_unique_id_with_metadata(&mut self,
-                                        cx: &CrateContext,
-                                        unique_type_id: UniqueTypeId,
-                                        metadata: DIType) {
-        if self.unique_id_to_metadata.insert(unique_type_id, metadata).is_some() {
-            let unique_type_id_str = self.get_unique_type_id_as_string(unique_type_id);
-            cx.sess().bug(&format!("Type metadata for unique id '{}' is already in the TypeMap!",
-                                  &unique_type_id_str[..]));
-        }
-    }
-
-    fn find_metadata_for_type(&self, type_: Ty<'tcx>) -> Option<DIType> {
-        self.type_to_metadata.get(&type_).cloned()
-    }
-
-    fn find_metadata_for_unique_id(&self, unique_type_id: UniqueTypeId) -> Option<DIType> {
-        self.unique_id_to_metadata.get(&unique_type_id).cloned()
-    }
-
-    // Get the string representation of a UniqueTypeId. This method will fail if
-    // the id is unknown.
-    fn get_unique_type_id_as_string(&self, unique_type_id: UniqueTypeId) -> Rc<String> {
-        let UniqueTypeId(interner_key) = unique_type_id;
-        self.unique_id_interner.get(interner_key)
-    }
-
-    // Get the UniqueTypeId for the given type. If the UniqueTypeId for the given
-    // type has been requested before, this is just a table lookup. Otherwise an
-    // ID will be generated and stored for later lookup.
-    fn get_unique_type_id_of_type<'a>(&mut self, cx: &CrateContext<'a, 'tcx>,
-                                      type_: Ty<'tcx>) -> UniqueTypeId {
-
-        // basic type           -> {:name of the type:}
-        // tuple                -> {tuple_(:param-uid:)*}
-        // struct               -> {struct_:svh: / :node-id:_<(:param-uid:),*> }
-        // enum                 -> {enum_:svh: / :node-id:_<(:param-uid:),*> }
-        // enum variant         -> {variant_:variant-name:_:enum-uid:}
-        // reference (&)        -> {& :pointee-uid:}
-        // mut reference (&mut) -> {&mut :pointee-uid:}
-        // ptr (*)              -> {* :pointee-uid:}
-        // mut ptr (*mut)       -> {*mut :pointee-uid:}
-        // unique ptr (~)       -> {~ :pointee-uid:}
-        // @-ptr (@)            -> {@ :pointee-uid:}
-        // sized vec ([T; x])   -> {[:size:] :element-uid:}
-        // unsized vec ([T])    -> {[] :element-uid:}
-        // trait (T)            -> {trait_:svh: / :node-id:_<(:param-uid:),*> }
-        // closure              -> {<unsafe_> <once_> :store-sigil: |(:param-uid:),* <,_...>| -> \
-        //                             :return-type-uid: : (:bounds:)*}
-        // function             -> {<unsafe_> <abi_> fn( (:param-uid:)* <,_...> ) -> \
-        //                             :return-type-uid:}
-        // unique vec box (~[]) -> {HEAP_VEC_BOX<:pointee-uid:>}
-        // gc box               -> {GC_BOX<:pointee-uid:>}
-
-        match self.type_to_unique_id.get(&type_).cloned() {
-            Some(unique_type_id) => return unique_type_id,
-            None => { /* generate one */}
-        };
-
-        let mut unique_type_id = String::with_capacity(256);
-        unique_type_id.push('{');
-
-        match type_.sty {
-            ty::ty_bool     |
-            ty::ty_char     |
-            ty::ty_str      |
-            ty::ty_int(_)   |
-            ty::ty_uint(_)  |
-            ty::ty_float(_) => {
-                push_debuginfo_type_name(cx, type_, false, &mut unique_type_id);
-            },
-            ty::ty_enum(def_id, substs) => {
-                unique_type_id.push_str("enum ");
-                from_def_id_and_substs(self, cx, def_id, substs, &mut unique_type_id);
-            },
-            ty::ty_struct(def_id, substs) => {
-                unique_type_id.push_str("struct ");
-                from_def_id_and_substs(self, cx, def_id, substs, &mut unique_type_id);
-            },
-            ty::ty_tup(ref component_types) if component_types.is_empty() => {
-                push_debuginfo_type_name(cx, type_, false, &mut unique_type_id);
-            },
-            ty::ty_tup(ref component_types) => {
-                unique_type_id.push_str("tuple ");
-                for &component_type in component_types {
-                    let component_type_id =
-                        self.get_unique_type_id_of_type(cx, component_type);
-                    let component_type_id =
-                        self.get_unique_type_id_as_string(component_type_id);
-                    unique_type_id.push_str(&component_type_id[..]);
-                }
-            },
-            ty::ty_uniq(inner_type) => {
-                unique_type_id.push('~');
-                let inner_type_id = self.get_unique_type_id_of_type(cx, inner_type);
-                let inner_type_id = self.get_unique_type_id_as_string(inner_type_id);
-                unique_type_id.push_str(&inner_type_id[..]);
-            },
-            ty::ty_ptr(ty::mt { ty: inner_type, mutbl } ) => {
-                unique_type_id.push('*');
-                if mutbl == ast::MutMutable {
-                    unique_type_id.push_str("mut");
-                }
-
-                let inner_type_id = self.get_unique_type_id_of_type(cx, inner_type);
-                let inner_type_id = self.get_unique_type_id_as_string(inner_type_id);
-                unique_type_id.push_str(&inner_type_id[..]);
-            },
-            ty::ty_rptr(_, ty::mt { ty: inner_type, mutbl }) => {
-                unique_type_id.push('&');
-                if mutbl == ast::MutMutable {
-                    unique_type_id.push_str("mut");
-                }
-
-                let inner_type_id = self.get_unique_type_id_of_type(cx, inner_type);
-                let inner_type_id = self.get_unique_type_id_as_string(inner_type_id);
-                unique_type_id.push_str(&inner_type_id[..]);
-            },
-            ty::ty_vec(inner_type, optional_length) => {
-                match optional_length {
-                    Some(len) => {
-                        unique_type_id.push_str(&format!("[{}]", len));
-                    }
-                    None => {
-                        unique_type_id.push_str("[]");
-                    }
-                };
-
-                let inner_type_id = self.get_unique_type_id_of_type(cx, inner_type);
-                let inner_type_id = self.get_unique_type_id_as_string(inner_type_id);
-                unique_type_id.push_str(&inner_type_id[..]);
-            },
-            ty::ty_trait(ref trait_data) => {
-                unique_type_id.push_str("trait ");
-
-                let principal =
-                    ty::erase_late_bound_regions(cx.tcx(),
-                                                 &trait_data.principal);
-
-                from_def_id_and_substs(self,
-                                       cx,
-                                       principal.def_id,
-                                       principal.substs,
-                                       &mut unique_type_id);
-            },
-            ty::ty_bare_fn(_, &ty::BareFnTy{ unsafety, abi, ref sig } ) => {
-                if unsafety == ast::Unsafety::Unsafe {
-                    unique_type_id.push_str("unsafe ");
-                }
-
-                unique_type_id.push_str(abi.name());
-
-                unique_type_id.push_str(" fn(");
-
-                let sig = ty::erase_late_bound_regions(cx.tcx(), sig);
-
-                for &parameter_type in &sig.inputs {
-                    let parameter_type_id =
-                        self.get_unique_type_id_of_type(cx, parameter_type);
-                    let parameter_type_id =
-                        self.get_unique_type_id_as_string(parameter_type_id);
-                    unique_type_id.push_str(&parameter_type_id[..]);
-                    unique_type_id.push(',');
-                }
-
-                if sig.variadic {
-                    unique_type_id.push_str("...");
-                }
-
-                unique_type_id.push_str(")->");
-                match sig.output {
-                    ty::FnConverging(ret_ty) => {
-                        let return_type_id = self.get_unique_type_id_of_type(cx, ret_ty);
-                        let return_type_id = self.get_unique_type_id_as_string(return_type_id);
-                        unique_type_id.push_str(&return_type_id[..]);
-                    }
-                    ty::FnDiverging => {
-                        unique_type_id.push_str("!");
-                    }
-                }
-            },
-            ty::ty_closure(def_id, substs) => {
-                let typer = NormalizingClosureTyper::new(cx.tcx());
-                let closure_ty = typer.closure_type(def_id, substs);
-                self.get_unique_type_id_of_closure_type(cx,
-                                                        closure_ty,
-                                                        &mut unique_type_id);
-            },
-            _ => {
-                cx.sess().bug(&format!("get_unique_type_id_of_type() - unexpected type: {}, {:?}",
-                                      &ppaux::ty_to_string(cx.tcx(), type_),
-                                      type_.sty))
-            }
-        };
-
-        unique_type_id.push('}');
-
-        // Trim to size before storing permanently
-        unique_type_id.shrink_to_fit();
-
-        let key = self.unique_id_interner.intern(Rc::new(unique_type_id));
-        self.type_to_unique_id.insert(type_, UniqueTypeId(key));
-
-        return UniqueTypeId(key);
-
-        fn from_def_id_and_substs<'a, 'tcx>(type_map: &mut TypeMap<'tcx>,
-                                            cx: &CrateContext<'a, 'tcx>,
-                                            def_id: ast::DefId,
-                                            substs: &subst::Substs<'tcx>,
-                                            output: &mut String) {
-            // First, find out the 'real' def_id of the type. Items inlined from
-            // other crates have to be mapped back to their source.
-            let source_def_id = if def_id.krate == ast::LOCAL_CRATE {
-                match cx.external_srcs().borrow().get(&def_id.node).cloned() {
-                    Some(source_def_id) => {
-                        // The given def_id identifies the inlined copy of a
-                        // type definition, let's take the source of the copy.
-                        source_def_id
-                    }
-                    None => def_id
-                }
-            } else {
-                def_id
-            };
-
-            // Get the crate hash as first part of the identifier.
-            let crate_hash = if source_def_id.krate == ast::LOCAL_CRATE {
-                cx.link_meta().crate_hash.clone()
-            } else {
-                cx.sess().cstore.get_crate_hash(source_def_id.krate)
-            };
-
-            output.push_str(crate_hash.as_str());
-            output.push_str("/");
-            output.push_str(&format!("{:x}", def_id.node));
-
-            // Maybe check that there is no self type here.
-
-            let tps = substs.types.get_slice(subst::TypeSpace);
-            if !tps.is_empty() {
-                output.push('<');
-
-                for &type_parameter in tps {
-                    let param_type_id =
-                        type_map.get_unique_type_id_of_type(cx, type_parameter);
-                    let param_type_id =
-                        type_map.get_unique_type_id_as_string(param_type_id);
-                    output.push_str(&param_type_id[..]);
-                    output.push(',');
-                }
-
-                output.push('>');
-            }
-        }
-    }
-
-    fn get_unique_type_id_of_closure_type<'a>(&mut self,
-                                              cx: &CrateContext<'a, 'tcx>,
-                                              closure_ty: ty::ClosureTy<'tcx>,
-                                              unique_type_id: &mut String) {
-        let ty::ClosureTy { unsafety,
-                            ref sig,
-                            abi: _ } = closure_ty;
-
-        if unsafety == ast::Unsafety::Unsafe {
-            unique_type_id.push_str("unsafe ");
-        }
-
-        unique_type_id.push_str("|");
-
-        let sig = ty::erase_late_bound_regions(cx.tcx(), sig);
-
-        for &parameter_type in &sig.inputs {
-            let parameter_type_id =
-                self.get_unique_type_id_of_type(cx, parameter_type);
-            let parameter_type_id =
-                self.get_unique_type_id_as_string(parameter_type_id);
-            unique_type_id.push_str(&parameter_type_id[..]);
-            unique_type_id.push(',');
-        }
-
-        if sig.variadic {
-            unique_type_id.push_str("...");
-        }
-
-        unique_type_id.push_str("|->");
-
-        match sig.output {
-            ty::FnConverging(ret_ty) => {
-                let return_type_id = self.get_unique_type_id_of_type(cx, ret_ty);
-                let return_type_id = self.get_unique_type_id_as_string(return_type_id);
-                unique_type_id.push_str(&return_type_id[..]);
-            }
-            ty::FnDiverging => {
-                unique_type_id.push_str("!");
-            }
-        }
-    }
-
-    // Get the UniqueTypeId for an enum variant. Enum variants are not really
-    // types of their own, so they need special handling. We still need a
-    // UniqueTypeId for them, since to debuginfo they *are* real types.
-    fn get_unique_type_id_of_enum_variant<'a>(&mut self,
-                                              cx: &CrateContext<'a, 'tcx>,
-                                              enum_type: Ty<'tcx>,
-                                              variant_name: &str)
-                                              -> UniqueTypeId {
-        let enum_type_id = self.get_unique_type_id_of_type(cx, enum_type);
-        let enum_variant_type_id = format!("{}::{}",
-                                           &self.get_unique_type_id_as_string(enum_type_id),
-                                           variant_name);
-        let interner_key = self.unique_id_interner.intern(Rc::new(enum_variant_type_id));
-        UniqueTypeId(interner_key)
-    }
-}
-
-// Returns from the enclosing function if the type metadata with the given
-// unique id can be found in the type map
-macro_rules! return_if_metadata_created_in_meantime {
-    ($cx: expr, $unique_type_id: expr) => (
-        match debug_context($cx).type_map
-                                .borrow()
-                                .find_metadata_for_unique_id($unique_type_id) {
-            Some(metadata) => return MetadataCreationResult::new(metadata, true),
-            None => { /* proceed normally */ }
-        };
-    )
-}
-
-
-/// A context object for maintaining all state needed by the debuginfo module.
-pub struct CrateDebugContext<'tcx> {
-    llcontext: ContextRef,
-    builder: DIBuilderRef,
-    current_debug_location: Cell<InternalDebugLocation>,
-    created_files: RefCell<FnvHashMap<String, DIFile>>,
-    created_enum_disr_types: RefCell<DefIdMap<DIType>>,
-
-    type_map: RefCell<TypeMap<'tcx>>,
-    namespace_map: RefCell<FnvHashMap<Vec<ast::Name>, Rc<NamespaceTreeNode>>>,
-
-    // This collection is used to assert that composite types (structs, enums,
-    // ...) have their members only set once:
-    composite_types_completed: RefCell<FnvHashSet<DIType>>,
-}
-
-impl<'tcx> CrateDebugContext<'tcx> {
-    pub fn new(llmod: ModuleRef) -> CrateDebugContext<'tcx> {
-        debug!("CrateDebugContext::new");
-        let builder = unsafe { llvm::LLVMDIBuilderCreate(llmod) };
-        // DIBuilder inherits context from the module, so we'd better use the same one
-        let llcontext = unsafe { llvm::LLVMGetModuleContext(llmod) };
-        return CrateDebugContext {
-            llcontext: llcontext,
-            builder: builder,
-            current_debug_location: Cell::new(UnknownLocation),
-            created_files: RefCell::new(FnvHashMap()),
-            created_enum_disr_types: RefCell::new(DefIdMap()),
-            type_map: RefCell::new(TypeMap::new()),
-            namespace_map: RefCell::new(FnvHashMap()),
-            composite_types_completed: RefCell::new(FnvHashSet()),
-        };
-    }
-}
-
-pub enum FunctionDebugContext {
-    RegularContext(Box<FunctionDebugContextData>),
-    DebugInfoDisabled,
-    FunctionWithoutDebugInfo,
-}
-
-impl FunctionDebugContext {
-    fn get_ref<'a>(&'a self,
-                   cx: &CrateContext,
-                   span: Span)
-                   -> &'a FunctionDebugContextData {
-        match *self {
-            FunctionDebugContext::RegularContext(box ref data) => data,
-            FunctionDebugContext::DebugInfoDisabled => {
-                cx.sess().span_bug(span,
-                                   FunctionDebugContext::debuginfo_disabled_message());
-            }
-            FunctionDebugContext::FunctionWithoutDebugInfo => {
-                cx.sess().span_bug(span,
-                                   FunctionDebugContext::should_be_ignored_message());
-            }
-        }
-    }
-
-    fn debuginfo_disabled_message() -> &'static str {
-        "debuginfo: Error trying to access FunctionDebugContext although debug info is disabled!"
-    }
-
-    fn should_be_ignored_message() -> &'static str {
-        "debuginfo: Error trying to access FunctionDebugContext for function that should be \
-         ignored by debug info!"
-    }
-}
-
-struct FunctionDebugContextData {
-    scope_map: RefCell<NodeMap<DIScope>>,
-    fn_metadata: DISubprogram,
-    argument_counter: Cell<usize>,
-    source_locations_enabled: Cell<bool>,
-    source_location_override: Cell<bool>,
-}
-
-enum VariableAccess<'a> {
-    // The llptr given is an alloca containing the variable's value
-    DirectVariable { alloca: ValueRef },
-    // The llptr given is an alloca containing the start of some pointer chain
-    // leading to the variable's content.
-    IndirectVariable { alloca: ValueRef, address_operations: &'a [i64] }
-}
-
-enum VariableKind {
-    ArgumentVariable(usize /*index*/),
-    LocalVariable,
-    CapturedVariable,
-}
-
-/// Create any deferred debug metadata nodes
-pub fn finalize(cx: &CrateContext) {
-    if cx.dbg_cx().is_none() {
-        return;
-    }
-
-    debug!("finalize");
-    let _ = compile_unit_metadata(cx);
-
-    if needs_gdb_debug_scripts_section(cx) {
-        // Add a .debug_gdb_scripts section to this compile-unit. This will
-        // cause GDB to try and load the gdb_load_rust_pretty_printers.py file,
-        // which activates the Rust pretty printers for binary this section is
-        // contained in.
-        get_or_insert_gdb_debug_scripts_section_global(cx);
-    }
-
-    unsafe {
-        llvm::LLVMDIBuilderFinalize(DIB(cx));
-        llvm::LLVMDIBuilderDispose(DIB(cx));
-        // Debuginfo generation in LLVM by default uses a higher
-        // version of dwarf than OS X currently understands. We can
-        // instruct LLVM to emit an older version of dwarf, however,
-        // for OS X to understand. For more info see #11352
-        // This can be overridden using --llvm-opts -dwarf-version,N.
-        // Android has the same issue (#22398)
-        if cx.sess().target.target.options.is_like_osx ||
-           cx.sess().target.target.options.is_like_android {
-            llvm::LLVMRustAddModuleFlag(cx.llmod(),
-                                        "Dwarf Version\0".as_ptr() as *const _,
-                                        2)
-        }
-
-        // Prevent bitcode readers from deleting the debug info.
-        let ptr = "Debug Info Version\0".as_ptr();
-        llvm::LLVMRustAddModuleFlag(cx.llmod(), ptr as *const _,
-                                    llvm::LLVMRustDebugMetadataVersion);
-    };
-}
-
-/// Creates debug information for the given global variable.
-///
-/// Adds the created metadata nodes directly to the crate's IR.
-pub fn create_global_var_metadata(cx: &CrateContext,
-                                  node_id: ast::NodeId,
-                                  global: ValueRef) {
-    if cx.dbg_cx().is_none() {
-        return;
-    }
-
-    // Don't create debuginfo for globals inlined from other crates. The other
-    // crate should already contain debuginfo for it. More importantly, the
-    // global might not even exist in un-inlined form anywhere which would lead
-    // to a linker errors.
-    if cx.external_srcs().borrow().contains_key(&node_id) {
-        return;
-    }
-
-    let var_item = cx.tcx().map.get(node_id);
-
-    let (name, span) = match var_item {
-        ast_map::NodeItem(item) => {
-            match item.node {
-                ast::ItemStatic(..) => (item.ident.name, item.span),
-                ast::ItemConst(..) => (item.ident.name, item.span),
-                _ => {
-                    cx.sess()
-                      .span_bug(item.span,
-                                &format!("debuginfo::\
-                                         create_global_var_metadata() -
-                                         Captured var-id refers to \
-                                         unexpected ast_item variant: {:?}",
-                                        var_item))
-                }
-            }
-        },
-        _ => cx.sess().bug(&format!("debuginfo::create_global_var_metadata() \
-                                    - Captured var-id refers to unexpected \
-                                    ast_map variant: {:?}",
-                                   var_item))
-    };
-
-    let (file_metadata, line_number) = if span != codemap::DUMMY_SP {
-        let loc = span_start(cx, span);
-        (file_metadata(cx, &loc.file.name), loc.line as c_uint)
-    } else {
-        (UNKNOWN_FILE_METADATA, UNKNOWN_LINE_NUMBER)
-    };
-
-    let is_local_to_unit = is_node_local_to_unit(cx, node_id);
-    let variable_type = ty::node_id_to_type(cx.tcx(), node_id);
-    let type_metadata = type_metadata(cx, variable_type, span);
-    let namespace_node = namespace_for_item(cx, ast_util::local_def(node_id));
-    let var_name = token::get_name(name).to_string();
-    let linkage_name =
-        namespace_node.mangled_name_of_contained_item(&var_name[..]);
-    let var_scope = namespace_node.scope;
-
-    let var_name = CString::new(var_name).unwrap();
-    let linkage_name = CString::new(linkage_name).unwrap();
-    unsafe {
-        llvm::LLVMDIBuilderCreateStaticVariable(DIB(cx),
-                                                var_scope,
-                                                var_name.as_ptr(),
-                                                linkage_name.as_ptr(),
-                                                file_metadata,
-                                                line_number,
-                                                type_metadata,
-                                                is_local_to_unit,
-                                                global,
-                                                ptr::null_mut());
-    }
-}
-
-/// Creates debug information for the given local variable.
-///
-/// This function assumes that there's a datum for each pattern component of the
-/// local in `bcx.fcx.lllocals`.
-/// Adds the created metadata nodes directly to the crate's IR.
-pub fn create_local_var_metadata(bcx: Block, local: &ast::Local) {
-    if bcx.unreachable.get() ||
-       fn_should_be_ignored(bcx.fcx) ||
-       bcx.sess().opts.debuginfo != FullDebugInfo  {
-        return;
-    }
-
-    let cx = bcx.ccx();
-    let def_map = &cx.tcx().def_map;
-    let locals = bcx.fcx.lllocals.borrow();
-
-    pat_util::pat_bindings(def_map, &*local.pat, |_, node_id, span, var_ident| {
-        let datum = match locals.get(&node_id) {
-            Some(datum) => datum,
-            None => {
-                bcx.sess().span_bug(span,
-                    &format!("no entry in lllocals table for {}",
-                            node_id));
-            }
-        };
-
-        if unsafe { llvm::LLVMIsAAllocaInst(datum.val) } == ptr::null_mut() {
-            cx.sess().span_bug(span, "debuginfo::create_local_var_metadata() - \
-                                      Referenced variable location is not an alloca!");
-        }
-
-        let scope_metadata = scope_metadata(bcx.fcx, node_id, span);
-
-        declare_local(bcx,
-                      var_ident.node.name,
-                      datum.ty,
-                      scope_metadata,
-                      DirectVariable { alloca: datum.val },
-                      LocalVariable,
-                      span);
-    })
-}
-
-/// Creates debug information for a variable captured in a closure.
-///
-/// Adds the created metadata nodes directly to the crate's IR.
-pub fn create_captured_var_metadata<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
-                                                node_id: ast::NodeId,
-                                                env_pointer: ValueRef,
-                                                env_index: usize,
-                                                captured_by_ref: bool,
-                                                span: Span) {
-    if bcx.unreachable.get() ||
-       fn_should_be_ignored(bcx.fcx) ||
-       bcx.sess().opts.debuginfo != FullDebugInfo {
-        return;
-    }
-
-    let cx = bcx.ccx();
-
-    let ast_item = cx.tcx().map.find(node_id);
-
-    let variable_name = match ast_item {
-        None => {
-            cx.sess().span_bug(span, "debuginfo::create_captured_var_metadata: node not found");
-        }
-        Some(ast_map::NodeLocal(pat)) | Some(ast_map::NodeArg(pat)) => {
-            match pat.node {
-                ast::PatIdent(_, ref path1, _) => {
-                    path1.node.name
-                }
-                _ => {
-                    cx.sess()
-                      .span_bug(span,
-                                &format!(
-                                "debuginfo::create_captured_var_metadata() - \
-                                 Captured var-id refers to unexpected \
-                                 ast_map variant: {:?}",
-                                 ast_item));
-                }
-            }
-        }
-        _ => {
-            cx.sess()
-              .span_bug(span,
-                        &format!("debuginfo::create_captured_var_metadata() - \
-                                 Captured var-id refers to unexpected \
-                                 ast_map variant: {:?}",
-                                ast_item));
-        }
-    };
-
-    let variable_type = common::node_id_type(bcx, node_id);
-    let scope_metadata = bcx.fcx.debug_context.get_ref(cx, span).fn_metadata;
-
-    // env_pointer is the alloca containing the pointer to the environment,
-    // so it's type is **EnvironmentType. In order to find out the type of
-    // the environment we have to "dereference" two times.
-    let llvm_env_data_type = common::val_ty(env_pointer).element_type()
-                                                        .element_type();
-    let byte_offset_of_var_in_env = machine::llelement_offset(cx,
-                                                              llvm_env_data_type,
-                                                              env_index);
-
-    let address_operations = unsafe {
-        [llvm::LLVMDIBuilderCreateOpDeref(),
-         llvm::LLVMDIBuilderCreateOpPlus(),
-         byte_offset_of_var_in_env as i64,
-         llvm::LLVMDIBuilderCreateOpDeref()]
-    };
-
-    let address_op_count = if captured_by_ref {
-        address_operations.len()
-    } else {
-        address_operations.len() - 1
-    };
-
-    let variable_access = IndirectVariable {
-        alloca: env_pointer,
-        address_operations: &address_operations[..address_op_count]
-    };
-
-    declare_local(bcx,
-                  variable_name,
-                  variable_type,
-                  scope_metadata,
-                  variable_access,
-                  CapturedVariable,
-                  span);
-}
-
-/// Creates debug information for a local variable introduced in the head of a
-/// match-statement arm.
-///
-/// Adds the created metadata nodes directly to the crate's IR.
-pub fn create_match_binding_metadata<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
-                                                 variable_name: ast::Name,
-                                                 binding: BindingInfo<'tcx>) {
-    if bcx.unreachable.get() ||
-       fn_should_be_ignored(bcx.fcx) ||
-       bcx.sess().opts.debuginfo != FullDebugInfo {
-        return;
-    }
-
-    let scope_metadata = scope_metadata(bcx.fcx, binding.id, binding.span);
-    let aops = unsafe {
-        [llvm::LLVMDIBuilderCreateOpDeref()]
-    };
-    // Regardless of the actual type (`T`) we're always passed the stack slot (alloca)
-    // for the binding. For ByRef bindings that's a `T*` but for ByMove bindings we
-    // actually have `T**`. So to get the actual variable we need to dereference once
-    // more. For ByCopy we just use the stack slot we created for the binding.
-    let var_access = match binding.trmode {
-        TrByCopy(llbinding) => DirectVariable {
-            alloca: llbinding
-        },
-        TrByMove => IndirectVariable {
-            alloca: binding.llmatch,
-            address_operations: &aops
-        },
-        TrByRef => DirectVariable {
-            alloca: binding.llmatch
-        }
-    };
-
-    declare_local(bcx,
-                  variable_name,
-                  binding.ty,
-                  scope_metadata,
-                  var_access,
-                  LocalVariable,
-                  binding.span);
-}
-
-/// Creates debug information for the given function argument.
-///
-/// This function assumes that there's a datum for each pattern component of the
-/// argument in `bcx.fcx.lllocals`.
-/// Adds the created metadata nodes directly to the crate's IR.
-pub fn create_argument_metadata(bcx: Block, arg: &ast::Arg) {
-    if bcx.unreachable.get() ||
-       fn_should_be_ignored(bcx.fcx) ||
-       bcx.sess().opts.debuginfo != FullDebugInfo {
-        return;
-    }
-
-    let def_map = &bcx.tcx().def_map;
-    let scope_metadata = bcx
-                         .fcx
-                         .debug_context
-                         .get_ref(bcx.ccx(), arg.pat.span)
-                         .fn_metadata;
-    let locals = bcx.fcx.lllocals.borrow();
-
-    pat_util::pat_bindings(def_map, &*arg.pat, |_, node_id, span, var_ident| {
-        let datum = match locals.get(&node_id) {
-            Some(v) => v,
-            None => {
-                bcx.sess().span_bug(span,
-                    &format!("no entry in lllocals table for {}",
-                            node_id));
-            }
-        };
-
-        if unsafe { llvm::LLVMIsAAllocaInst(datum.val) } == ptr::null_mut() {
-            bcx.sess().span_bug(span, "debuginfo::create_argument_metadata() - \
-                                       Referenced variable location is not an alloca!");
-        }
-
-        let argument_index = {
-            let counter = &bcx
-                          .fcx
-                          .debug_context
-                          .get_ref(bcx.ccx(), span)
-                          .argument_counter;
-            let argument_index = counter.get();
-            counter.set(argument_index + 1);
-            argument_index
-        };
-
-        declare_local(bcx,
-                      var_ident.node.name,
-                      datum.ty,
-                      scope_metadata,
-                      DirectVariable { alloca: datum.val },
-                      ArgumentVariable(argument_index),
-                      span);
-    })
-}
-
-pub fn get_cleanup_debug_loc_for_ast_node<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
-                                                    node_id: ast::NodeId,
-                                                    node_span: Span,
-                                                    is_block: bool)
-                                                 -> NodeIdAndSpan {
-    // A debug location needs two things:
-    // (1) A span (of which only the beginning will actually be used)
-    // (2) An AST node-id which will be used to look up the lexical scope
-    //     for the location in the functions scope-map
-    //
-    // This function will calculate the debug location for compiler-generated
-    // cleanup calls that are executed when control-flow leaves the
-    // scope identified by `node_id`.
-    //
-    // For everything but block-like things we can simply take id and span of
-    // the given expression, meaning that from a debugger's view cleanup code is
-    // executed at the same source location as the statement/expr itself.
-    //
-    // Blocks are a special case. Here we want the cleanup to be linked to the
-    // closing curly brace of the block. The *scope* the cleanup is executed in
-    // is up to debate: It could either still be *within* the block being
-    // cleaned up, meaning that locals from the block are still visible in the
-    // debugger.
-    // Or it could be in the scope that the block is contained in, so any locals
-    // from within the block are already considered out-of-scope and thus not
-    // accessible in the debugger anymore.
-    //
-    // The current implementation opts for the second option: cleanup of a block
-    // already happens in the parent scope of the block. The main reason for
-    // this decision is that scoping becomes controlflow dependent when variable
-    // shadowing is involved and it's impossible to decide statically which
-    // scope is actually left when the cleanup code is executed.
-    // In practice it shouldn't make much of a difference.
-
-    let mut cleanup_span = node_span;
-
-    if is_block {
-        // Not all blocks actually have curly braces (e.g. simple closure
-        // bodies), in which case we also just want to return the span of the
-        // whole expression.
-        let code_snippet = cx.sess().codemap().span_to_snippet(node_span);
-        if let Ok(code_snippet) = code_snippet {
-            let bytes = code_snippet.as_bytes();
-
-            if !bytes.is_empty() && &bytes[bytes.len()-1..] == b"}" {
-                cleanup_span = Span {
-                    lo: node_span.hi - codemap::BytePos(1),
-                    hi: node_span.hi,
-                    expn_id: node_span.expn_id
-                };
-            }
-        }
-    }
-
-    NodeIdAndSpan {
-        id: node_id,
-        span: cleanup_span
-    }
-}
-
-#[derive(Copy, Clone, PartialEq, Eq, Debug)]
-pub enum DebugLoc {
-    At(ast::NodeId, Span),
-    None
-}
-
-impl DebugLoc {
-    pub fn apply(&self, fcx: &FunctionContext) {
-        match *self {
-            DebugLoc::At(node_id, span) => {
-                set_source_location(fcx, node_id, span);
-            }
-            DebugLoc::None => {
-                clear_source_location(fcx);
-            }
-        }
-    }
-}
-
-pub trait ToDebugLoc {
-    fn debug_loc(&self) -> DebugLoc;
-}
-
-impl ToDebugLoc for ast::Expr {
-    fn debug_loc(&self) -> DebugLoc {
-        DebugLoc::At(self.id, self.span)
-    }
-}
-
-impl ToDebugLoc for NodeIdAndSpan {
-    fn debug_loc(&self) -> DebugLoc {
-        DebugLoc::At(self.id, self.span)
-    }
-}
-
-impl ToDebugLoc for Option<NodeIdAndSpan> {
-    fn debug_loc(&self) -> DebugLoc {
-        match *self {
-            Some(NodeIdAndSpan { id, span }) => DebugLoc::At(id, span),
-            None => DebugLoc::None
-        }
-    }
-}
-
-/// Sets the current debug location at the beginning of the span.
-///
-/// Maps to a call to llvm::LLVMSetCurrentDebugLocation(...). The node_id
-/// parameter is used to reliably find the correct visibility scope for the code
-/// position.
-pub fn set_source_location(fcx: &FunctionContext,
-                           node_id: ast::NodeId,
-                           span: Span) {
-    match fcx.debug_context {
-        FunctionDebugContext::DebugInfoDisabled => return,
-        FunctionDebugContext::FunctionWithoutDebugInfo => {
-            set_debug_location(fcx.ccx, UnknownLocation);
-            return;
-        }
-        FunctionDebugContext::RegularContext(box ref function_debug_context) => {
-            if function_debug_context.source_location_override.get() {
-                // Just ignore any attempts to set a new debug location while
-                // the override is active.
-                return;
-            }
-
-            let cx = fcx.ccx;
-
-            debug!("set_source_location: {}", cx.sess().codemap().span_to_string(span));
-
-            if function_debug_context.source_locations_enabled.get() {
-                let loc = span_start(cx, span);
-                let scope = scope_metadata(fcx, node_id, span);
-
-                set_debug_location(cx, InternalDebugLocation::new(scope,
-                                                                  loc.line,
-                                                                  loc.col.to_usize()));
-            } else {
-                set_debug_location(cx, UnknownLocation);
-            }
-        }
-    }
-}
-
-/// This function makes sure that all debug locations emitted while executing
-/// `wrapped_function` are set to the given `debug_loc`.
-pub fn with_source_location_override<F, R>(fcx: &FunctionContext,
-                                           debug_loc: DebugLoc,
-                                           wrapped_function: F) -> R
-    where F: FnOnce() -> R
-{
-    match fcx.debug_context {
-        FunctionDebugContext::DebugInfoDisabled => {
-            wrapped_function()
-        }
-        FunctionDebugContext::FunctionWithoutDebugInfo => {
-            set_debug_location(fcx.ccx, UnknownLocation);
-            wrapped_function()
-        }
-        FunctionDebugContext::RegularContext(box ref function_debug_context) => {
-            if function_debug_context.source_location_override.get() {
-                wrapped_function()
-            } else {
-                debug_loc.apply(fcx);
-                function_debug_context.source_location_override.set(true);
-                let result = wrapped_function();
-                function_debug_context.source_location_override.set(false);
-                result
-            }
-        }
-    }
-}
-
-/// Clears the current debug location.
-///
-/// Instructions generated hereafter won't be assigned a source location.
-pub fn clear_source_location(fcx: &FunctionContext) {
-    if fn_should_be_ignored(fcx) {
-        return;
-    }
-
-    set_debug_location(fcx.ccx, UnknownLocation);
-}
-
-/// Enables emitting source locations for the given functions.
-///
-/// Since we don't want source locations to be emitted for the function prelude,
-/// they are disabled when beginning to translate a new function. This functions
-/// switches source location emitting on and must therefore be called before the
-/// first real statement/expression of the function is translated.
-pub fn start_emitting_source_locations(fcx: &FunctionContext) {
-    match fcx.debug_context {
-        FunctionDebugContext::RegularContext(box ref data) => {
-            data.source_locations_enabled.set(true)
-        },
-        _ => { /* safe to ignore */ }
-    }
-}
-
-/// Creates the function-specific debug context.
-///
-/// Returns the FunctionDebugContext for the function which holds state needed
-/// for debug info creation. The function may also return another variant of the
-/// FunctionDebugContext enum which indicates why no debuginfo should be created
-/// for the function.
-pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
-                                               fn_ast_id: ast::NodeId,
-                                               param_substs: &Substs<'tcx>,
-                                               llfn: ValueRef) -> FunctionDebugContext {
-    if cx.sess().opts.debuginfo == NoDebugInfo {
-        return FunctionDebugContext::DebugInfoDisabled;
-    }
-
-    // Clear the debug location so we don't assign them in the function prelude.
-    // Do this here already, in case we do an early exit from this function.
-    set_debug_location(cx, UnknownLocation);
-
-    if fn_ast_id == ast::DUMMY_NODE_ID {
-        // This is a function not linked to any source location, so don't
-        // generate debuginfo for it.
-        return FunctionDebugContext::FunctionWithoutDebugInfo;
-    }
-
-    let empty_generics = ast_util::empty_generics();
-
-    let fnitem = cx.tcx().map.get(fn_ast_id);
-
-    let (name, fn_decl, generics, top_level_block, span, has_path) = match fnitem {
-        ast_map::NodeItem(ref item) => {
-            if contains_nodebug_attribute(&item.attrs) {
-                return FunctionDebugContext::FunctionWithoutDebugInfo;
-            }
-
-            match item.node {
-                ast::ItemFn(ref fn_decl, _, _, ref generics, ref top_level_block) => {
-                    (item.ident.name, fn_decl, generics, top_level_block, item.span, true)
-                }
-                _ => {
-                    cx.sess().span_bug(item.span,
-                        "create_function_debug_context: item bound to non-function");
-                }
-            }
-        }
-        ast_map::NodeImplItem(impl_item) => {
-            match impl_item.node {
-                ast::MethodImplItem(ref sig, ref body) => {
-                    if contains_nodebug_attribute(&impl_item.attrs) {
-                        return FunctionDebugContext::FunctionWithoutDebugInfo;
-                    }
-
-                    (impl_item.ident.name,
-                     &sig.decl,
-                     &sig.generics,
-                     body,
-                     impl_item.span,
-                     true)
-                }
-                _ => {
-                    cx.sess().span_bug(impl_item.span,
-                                       "create_function_debug_context() \
-                                        called on non-method impl item?!")
-                }
-            }
-        }
-        ast_map::NodeExpr(ref expr) => {
-            match expr.node {
-                ast::ExprClosure(_, ref fn_decl, ref top_level_block) => {
-                    let name = format!("fn{}", token::gensym("fn"));
-                    let name = token::intern(&name[..]);
-                    (name, fn_decl,
-                        // This is not quite right. It should actually inherit
-                        // the generics of the enclosing function.
-                        &empty_generics,
-                        top_level_block,
-                        expr.span,
-                        // Don't try to lookup the item path:
-                        false)
-                }
-                _ => cx.sess().span_bug(expr.span,
-                        "create_function_debug_context: expected an expr_fn_block here")
-            }
-        }
-        ast_map::NodeTraitItem(trait_item) => {
-            match trait_item.node {
-                ast::MethodTraitItem(ref sig, Some(ref body)) => {
-                    if contains_nodebug_attribute(&trait_item.attrs) {
-                        return FunctionDebugContext::FunctionWithoutDebugInfo;
-                    }
-
-                    (trait_item.ident.name,
-                     &sig.decl,
-                     &sig.generics,
-                     body,
-                     trait_item.span,
-                     true)
-                }
-                _ => {
-                    cx.sess()
-                      .bug(&format!("create_function_debug_context: \
-                                    unexpected sort of node: {:?}",
-                                    fnitem))
-                }
-            }
-        }
-        ast_map::NodeForeignItem(..) |
-        ast_map::NodeVariant(..) |
-        ast_map::NodeStructCtor(..) => {
-            return FunctionDebugContext::FunctionWithoutDebugInfo;
-        }
-        _ => cx.sess().bug(&format!("create_function_debug_context: \
-                                    unexpected sort of node: {:?}",
-                                   fnitem))
-    };
-
-    // This can be the case for functions inlined from another crate
-    if span == codemap::DUMMY_SP {
-        return FunctionDebugContext::FunctionWithoutDebugInfo;
-    }
-
-    let loc = span_start(cx, span);
-    let file_metadata = file_metadata(cx, &loc.file.name);
-
-    let function_type_metadata = unsafe {
-        let fn_signature = get_function_signature(cx,
-                                                  fn_ast_id,
-                                                  &*fn_decl,
-                                                  param_substs,
-                                                  span);
-        llvm::LLVMDIBuilderCreateSubroutineType(DIB(cx), file_metadata, fn_signature)
-    };
-
-    // Get_template_parameters() will append a `<...>` clause to the function
-    // name if necessary.
-    let mut function_name = String::from_str(&token::get_name(name));
-    let template_parameters = get_template_parameters(cx,
-                                                      generics,
-                                                      param_substs,
-                                                      file_metadata,
-                                                      &mut function_name);
-
-    // There is no ast_map::Path for ast::ExprClosure-type functions. For now,
-    // just don't put them into a namespace. In the future this could be improved
-    // somehow (storing a path in the ast_map, or construct a path using the
-    // enclosing function).
-    let (linkage_name, containing_scope) = if has_path {
-        let namespace_node = namespace_for_item(cx, ast_util::local_def(fn_ast_id));
-        let linkage_name = namespace_node.mangled_name_of_contained_item(
-            &function_name[..]);
-        let containing_scope = namespace_node.scope;
-        (linkage_name, containing_scope)
-    } else {
-        (function_name.clone(), file_metadata)
-    };
-
-    // Clang sets this parameter to the opening brace of the function's block,
-    // so let's do this too.
-    let scope_line = span_start(cx, top_level_block.span).line;
-
-    let is_local_to_unit = is_node_local_to_unit(cx, fn_ast_id);
-
-    let function_name = CString::new(function_name).unwrap();
-    let linkage_name = CString::new(linkage_name).unwrap();
-    let fn_metadata = unsafe {
-        llvm::LLVMDIBuilderCreateFunction(
-            DIB(cx),
-            containing_scope,
-            function_name.as_ptr(),
-            linkage_name.as_ptr(),
-            file_metadata,
-            loc.line as c_uint,
-            function_type_metadata,
-            is_local_to_unit,
-            true,
-            scope_line as c_uint,
-            FlagPrototyped as c_uint,
-            cx.sess().opts.optimize != config::No,
-            llfn,
-            template_parameters,
-            ptr::null_mut())
-    };
-
-    let scope_map = create_scope_map(cx,
-                                     &fn_decl.inputs,
-                                     &*top_level_block,
-                                     fn_metadata,
-                                     fn_ast_id);
-
-    // Initialize fn debug context (including scope map and namespace map)
-    let fn_debug_context = box FunctionDebugContextData {
-        scope_map: RefCell::new(scope_map),
-        fn_metadata: fn_metadata,
-        argument_counter: Cell::new(1),
-        source_locations_enabled: Cell::new(false),
-        source_location_override: Cell::new(false),
-    };
-
-
-
-    return FunctionDebugContext::RegularContext(fn_debug_context);
-
-    fn get_function_signature<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
-                                        fn_ast_id: ast::NodeId,
-                                        fn_decl: &ast::FnDecl,
-                                        param_substs: &Substs<'tcx>,
-                                        error_reporting_span: Span) -> DIArray {
-        if cx.sess().opts.debuginfo == LimitedDebugInfo {
-            return create_DIArray(DIB(cx), &[]);
-        }
-
-        let mut signature = Vec::with_capacity(fn_decl.inputs.len() + 1);
-
-        // Return type -- llvm::DIBuilder wants this at index 0
-        assert_type_for_node_id(cx, fn_ast_id, error_reporting_span);
-        let return_type = ty::node_id_to_type(cx.tcx(), fn_ast_id);
-        let return_type = monomorphize::apply_param_substs(cx.tcx(),
-                                                           param_substs,
-                                                           &return_type);
-        if ty::type_is_nil(return_type) {
-            signature.push(ptr::null_mut())
-        } else {
-            signature.push(type_metadata(cx, return_type, codemap::DUMMY_SP));
-        }
-
-        // Arguments types
-        for arg in &fn_decl.inputs {
-            assert_type_for_node_id(cx, arg.pat.id, arg.pat.span);
-            let arg_type = ty::node_id_to_type(cx.tcx(), arg.pat.id);
-            let arg_type = monomorphize::apply_param_substs(cx.tcx(),
-                                                            param_substs,
-                                                            &arg_type);
-            signature.push(type_metadata(cx, arg_type, codemap::DUMMY_SP));
-        }
-
-        return create_DIArray(DIB(cx), &signature[..]);
-    }
-
-    fn get_template_parameters<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
-                                         generics: &ast::Generics,
-                                         param_substs: &Substs<'tcx>,
-                                         file_metadata: DIFile,
-                                         name_to_append_suffix_to: &mut String)
-                                         -> DIArray
-    {
-        let self_type = param_substs.self_ty();
-        let self_type = monomorphize::normalize_associated_type(cx.tcx(), &self_type);
-
-        // Only true for static default methods:
-        let has_self_type = self_type.is_some();
-
-        if !generics.is_type_parameterized() && !has_self_type {
-            return create_DIArray(DIB(cx), &[]);
-        }
-
-        name_to_append_suffix_to.push('<');
-
-        // The list to be filled with template parameters:
-        let mut template_params: Vec<DIDescriptor> =
-            Vec::with_capacity(generics.ty_params.len() + 1);
-
-        // Handle self type
-        if has_self_type {
-            let actual_self_type = self_type.unwrap();
-            // Add self type name to <...> clause of function name
-            let actual_self_type_name = compute_debuginfo_type_name(
-                cx,
-                actual_self_type,
-                true);
-
-            name_to_append_suffix_to.push_str(&actual_self_type_name[..]);
-
-            if generics.is_type_parameterized() {
-                name_to_append_suffix_to.push_str(",");
-            }
-
-            // Only create type information if full debuginfo is enabled
-            if cx.sess().opts.debuginfo == FullDebugInfo {
-                let actual_self_type_metadata = type_metadata(cx,
-                                                              actual_self_type,
-                                                              codemap::DUMMY_SP);
-
-                let name = token::get_name(special_idents::type_self.name);
-
-                let name = CString::new(name.as_bytes()).unwrap();
-                let param_metadata = unsafe {
-                    llvm::LLVMDIBuilderCreateTemplateTypeParameter(
-                        DIB(cx),
-                        file_metadata,
-                        name.as_ptr(),
-                        actual_self_type_metadata,
-                        ptr::null_mut(),
-                        0,
-                        0)
-                };
-
-                template_params.push(param_metadata);
-            }
-        }
-
-        // Handle other generic parameters
-        let actual_types = param_substs.types.get_slice(subst::FnSpace);
-        for (index, &ast::TyParam{ ident, .. }) in generics.ty_params.iter().enumerate() {
-            let actual_type = actual_types[index];
-            // Add actual type name to <...> clause of function name
-            let actual_type_name = compute_debuginfo_type_name(cx,
-                                                               actual_type,
-                                                               true);
-            name_to_append_suffix_to.push_str(&actual_type_name[..]);
-
-            if index != generics.ty_params.len() - 1 {
-                name_to_append_suffix_to.push_str(",");
-            }
-
-            // Again, only create type information if full debuginfo is enabled
-            if cx.sess().opts.debuginfo == FullDebugInfo {
-                let actual_type_metadata = type_metadata(cx, actual_type, codemap::DUMMY_SP);
-                let ident = token::get_ident(ident);
-                let name = CString::new(ident.as_bytes()).unwrap();
-                let param_metadata = unsafe {
-                    llvm::LLVMDIBuilderCreateTemplateTypeParameter(
-                        DIB(cx),
-                        file_metadata,
-                        name.as_ptr(),
-                        actual_type_metadata,
-                        ptr::null_mut(),
-                        0,
-                        0)
-                };
-                template_params.push(param_metadata);
-            }
-        }
-
-        name_to_append_suffix_to.push('>');
-
-        return create_DIArray(DIB(cx), &template_params[..]);
-    }
-}
-
-//=-----------------------------------------------------------------------------
-// Module-Internal debug info creation functions
-//=-----------------------------------------------------------------------------
-
-fn is_node_local_to_unit(cx: &CrateContext, node_id: ast::NodeId) -> bool
-{
-    // The is_local_to_unit flag indicates whether a function is local to the
-    // current compilation unit (i.e. if it is *static* in the C-sense). The
-    // *reachable* set should provide a good approximation of this, as it
-    // contains everything that might leak out of the current crate (by being
-    // externally visible or by being inlined into something externally visible).
-    // It might better to use the `exported_items` set from `driver::CrateAnalysis`
-    // in the future, but (atm) this set is not available in the translation pass.
-    !cx.reachable().contains(&node_id)
-}
-
-#[allow(non_snake_case)]
-fn create_DIArray(builder: DIBuilderRef, arr: &[DIDescriptor]) -> DIArray {
-    return unsafe {
-        llvm::LLVMDIBuilderGetOrCreateArray(builder, arr.as_ptr(), arr.len() as u32)
-    };
-}
-
-fn compile_unit_metadata(cx: &CrateContext) -> DIDescriptor {
-    let work_dir = &cx.sess().working_dir;
-    let compile_unit_name = match cx.sess().local_crate_source_file {
-        None => fallback_path(cx),
-        Some(ref abs_path) => {
-            if abs_path.is_relative() {
-                cx.sess().warn("debuginfo: Invalid path to crate's local root source file!");
-                fallback_path(cx)
-            } else {
-                match abs_path.relative_from(work_dir) {
-                    Some(ref p) if p.is_relative() => {
-                        if p.starts_with(Path::new("./")) {
-                            path2cstr(p)
-                        } else {
-                            path2cstr(&Path::new(".").join(p))
-                        }
-                    }
-                    _ => fallback_path(cx)
-                }
-            }
-        }
-    };
-
-    debug!("compile_unit_metadata: {:?}", compile_unit_name);
-    let producer = format!("rustc version {}",
-                           (option_env!("CFG_VERSION")).expect("CFG_VERSION"));
-
-    let compile_unit_name = compile_unit_name.as_ptr();
-    let work_dir = path2cstr(&work_dir);
-    let producer = CString::new(producer).unwrap();
-    let flags = "\0";
-    let split_name = "\0";
-    return unsafe {
-        llvm::LLVMDIBuilderCreateCompileUnit(
-            debug_context(cx).builder,
-            DW_LANG_RUST,
-            compile_unit_name,
-            work_dir.as_ptr(),
-            producer.as_ptr(),
-            cx.sess().opts.optimize != config::No,
-            flags.as_ptr() as *const _,
-            0,
-            split_name.as_ptr() as *const _)
-    };
-
-    fn fallback_path(cx: &CrateContext) -> CString {
-        CString::new(cx.link_meta().crate_name.clone()).unwrap()
-    }
-}
-
-fn declare_local<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
-                             variable_name: ast::Name,
-                             variable_type: Ty<'tcx>,
-                             scope_metadata: DIScope,
-                             variable_access: VariableAccess,
-                             variable_kind: VariableKind,
-                             span: Span) {
-    let cx: &CrateContext = bcx.ccx();
-
-    let filename = span_start(cx, span).file.name.clone();
-    let file_metadata = file_metadata(cx, &filename[..]);
-
-    let name = token::get_name(variable_name);
-    let loc = span_start(cx, span);
-    let type_metadata = type_metadata(cx, variable_type, span);
-
-    let (argument_index, dwarf_tag) = match variable_kind {
-        ArgumentVariable(index) => (index as c_uint, DW_TAG_arg_variable),
-        LocalVariable    |
-        CapturedVariable => (0, DW_TAG_auto_variable)
-    };
-
-    let name = CString::new(name.as_bytes()).unwrap();
-    match (variable_access, &[][..]) {
-        (DirectVariable { alloca }, address_operations) |
-        (IndirectVariable {alloca, address_operations}, _) => {
-            let metadata = unsafe {
-                llvm::LLVMDIBuilderCreateVariable(
-                    DIB(cx),
-                    dwarf_tag,
-                    scope_metadata,
-                    name.as_ptr(),
-                    file_metadata,
-                    loc.line as c_uint,
-                    type_metadata,
-                    cx.sess().opts.optimize != config::No,
-                    0,
-                    address_operations.as_ptr(),
-                    address_operations.len() as c_uint,
-                    argument_index)
-            };
-            set_debug_location(cx, InternalDebugLocation::new(scope_metadata,
-                                                      loc.line,
-                                                      loc.col.to_usize()));
-            unsafe {
-                let instr = llvm::LLVMDIBuilderInsertDeclareAtEnd(
-                    DIB(cx),
-                    alloca,
-                    metadata,
-                    address_operations.as_ptr(),
-                    address_operations.len() as c_uint,
-                    bcx.llbb);
-
-                llvm::LLVMSetInstDebugLocation(trans::build::B(bcx).llbuilder, instr);
-            }
-        }
-    }
-
-    match variable_kind {
-        ArgumentVariable(_) | CapturedVariable => {
-            assert!(!bcx.fcx
-                        .debug_context
-                        .get_ref(cx, span)
-                        .source_locations_enabled
-                        .get());
-            set_debug_location(cx, UnknownLocation);
-        }
-        _ => { /* nothing to do */ }
-    }
-}
-
-fn file_metadata(cx: &CrateContext, full_path: &str) -> DIFile {
-    match debug_context(cx).created_files.borrow().get(full_path) {
-        Some(file_metadata) => return *file_metadata,
-        None => ()
-    }
-
-    debug!("file_metadata: {}", full_path);
-
-    // FIXME (#9639): This needs to handle non-utf8 paths
-    let work_dir = cx.sess().working_dir.to_str().unwrap();
-    let file_name =
-        if full_path.starts_with(work_dir) {
-            &full_path[work_dir.len() + 1..full_path.len()]
-        } else {
-            full_path
-        };
-
-    let file_name = CString::new(file_name).unwrap();
-    let work_dir = CString::new(work_dir).unwrap();
-    let file_metadata = unsafe {
-        llvm::LLVMDIBuilderCreateFile(DIB(cx), file_name.as_ptr(),
-                                      work_dir.as_ptr())
-    };
-
-    let mut created_files = debug_context(cx).created_files.borrow_mut();
-    created_files.insert(full_path.to_string(), file_metadata);
-    return file_metadata;
-}
-
-/// Finds the scope metadata node for the given AST node.
-fn scope_metadata(fcx: &FunctionContext,
-                  node_id: ast::NodeId,
-                  error_reporting_span: Span)
-               -> DIScope {
-    let scope_map = &fcx.debug_context
-                        .get_ref(fcx.ccx, error_reporting_span)
-                        .scope_map;
-    match scope_map.borrow().get(&node_id).cloned() {
-        Some(scope_metadata) => scope_metadata,
-        None => {
-            let node = fcx.ccx.tcx().map.get(node_id);
-
-            fcx.ccx.sess().span_bug(error_reporting_span,
-                &format!("debuginfo: Could not find scope info for node {:?}",
-                        node));
-        }
-    }
-}
-
-fn diverging_type_metadata(cx: &CrateContext) -> DIType {
-    unsafe {
-        llvm::LLVMDIBuilderCreateBasicType(
-            DIB(cx),
-            "!\0".as_ptr() as *const _,
-            bytes_to_bits(0),
-            bytes_to_bits(0),
-            DW_ATE_unsigned)
-    }
-}
-
-fn basic_type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
-                                 t: Ty<'tcx>) -> DIType {
-
-    debug!("basic_type_metadata: {:?}", t);
-
-    let (name, encoding) = match t.sty {
-        ty::ty_tup(ref elements) if elements.is_empty() =>
-            ("()".to_string(), DW_ATE_unsigned),
-        ty::ty_bool => ("bool".to_string(), DW_ATE_boolean),
-        ty::ty_char => ("char".to_string(), DW_ATE_unsigned_char),
-        ty::ty_int(int_ty) => match int_ty {
-            ast::TyIs => ("isize".to_string(), DW_ATE_signed),
-            ast::TyI8 => ("i8".to_string(), DW_ATE_signed),
-            ast::TyI16 => ("i16".to_string(), DW_ATE_signed),
-            ast::TyI32 => ("i32".to_string(), DW_ATE_signed),
-            ast::TyI64 => ("i64".to_string(), DW_ATE_signed)
-        },
-        ty::ty_uint(uint_ty) => match uint_ty {
-            ast::TyUs => ("usize".to_string(), DW_ATE_unsigned),
-            ast::TyU8 => ("u8".to_string(), DW_ATE_unsigned),
-            ast::TyU16 => ("u16".to_string(), DW_ATE_unsigned),
-            ast::TyU32 => ("u32".to_string(), DW_ATE_unsigned),
-            ast::TyU64 => ("u64".to_string(), DW_ATE_unsigned)
-        },
-        ty::ty_float(float_ty) => match float_ty {
-            ast::TyF32 => ("f32".to_string(), DW_ATE_float),
-            ast::TyF64 => ("f64".to_string(), DW_ATE_float),
-        },
-        _ => cx.sess().bug("debuginfo::basic_type_metadata - t is invalid type")
-    };
-
-    let llvm_type = type_of::type_of(cx, t);
-    let (size, align) = size_and_align_of(cx, llvm_type);
-    let name = CString::new(name).unwrap();
-    let ty_metadata = unsafe {
-        llvm::LLVMDIBuilderCreateBasicType(
-            DIB(cx),
-            name.as_ptr(),
-            bytes_to_bits(size),
-            bytes_to_bits(align),
-            encoding)
-    };
-
-    return ty_metadata;
-}
-
-fn pointer_type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
-                                   pointer_type: Ty<'tcx>,
-                                   pointee_type_metadata: DIType)
-                                   -> DIType {
-    let pointer_llvm_type = type_of::type_of(cx, pointer_type);
-    let (pointer_size, pointer_align) = size_and_align_of(cx, pointer_llvm_type);
-    let name = compute_debuginfo_type_name(cx, pointer_type, false);
-    let name = CString::new(name).unwrap();
-    let ptr_metadata = unsafe {
-        llvm::LLVMDIBuilderCreatePointerType(
-            DIB(cx),
-            pointee_type_metadata,
-            bytes_to_bits(pointer_size),
-            bytes_to_bits(pointer_align),
-            name.as_ptr())
-    };
-    return ptr_metadata;
-}
-
-//=-----------------------------------------------------------------------------
-// Common facilities for record-like types (structs, enums, tuples)
-//=-----------------------------------------------------------------------------
-
-enum MemberOffset {
-    FixedMemberOffset { bytes: usize },
-    // For ComputedMemberOffset, the offset is read from the llvm type definition
-    ComputedMemberOffset
-}
-
-// Description of a type member, which can either be a regular field (as in
-// structs or tuples) or an enum variant
-struct MemberDescription {
-    name: String,
-    llvm_type: Type,
-    type_metadata: DIType,
-    offset: MemberOffset,
-    flags: c_uint
-}
-
-// A factory for MemberDescriptions. It produces a list of member descriptions
-// for some record-like type. MemberDescriptionFactories are used to defer the
-// creation of type member descriptions in order to break cycles arising from
-// recursive type definitions.
-enum MemberDescriptionFactory<'tcx> {
-    StructMDF(StructMemberDescriptionFactory<'tcx>),
-    TupleMDF(TupleMemberDescriptionFactory<'tcx>),
-    EnumMDF(EnumMemberDescriptionFactory<'tcx>),
-    VariantMDF(VariantMemberDescriptionFactory<'tcx>)
-}
-
-impl<'tcx> MemberDescriptionFactory<'tcx> {
-    fn create_member_descriptions<'a>(&self, cx: &CrateContext<'a, 'tcx>)
-                                      -> Vec<MemberDescription> {
-        match *self {
-            StructMDF(ref this) => {
-                this.create_member_descriptions(cx)
-            }
-            TupleMDF(ref this) => {
-                this.create_member_descriptions(cx)
-            }
-            EnumMDF(ref this) => {
-                this.create_member_descriptions(cx)
-            }
-            VariantMDF(ref this) => {
-                this.create_member_descriptions(cx)
-            }
-        }
-    }
-}
-
-// A description of some recursive type. It can either be already finished (as
-// with FinalMetadata) or it is not yet finished, but contains all information
-// needed to generate the missing parts of the description. See the documentation
-// section on Recursive Types at the top of this file for more information.
-enum RecursiveTypeDescription<'tcx> {
-    UnfinishedMetadata {
-        unfinished_type: Ty<'tcx>,
-        unique_type_id: UniqueTypeId,
-        metadata_stub: DICompositeType,
-        llvm_type: Type,
-        member_description_factory: MemberDescriptionFactory<'tcx>,
-    },
-    FinalMetadata(DICompositeType)
-}
-
-fn create_and_register_recursive_type_forward_declaration<'a, 'tcx>(
-    cx: &CrateContext<'a, 'tcx>,
-    unfinished_type: Ty<'tcx>,
-    unique_type_id: UniqueTypeId,
-    metadata_stub: DICompositeType,
-    llvm_type: Type,
-    member_description_factory: MemberDescriptionFactory<'tcx>)
- -> RecursiveTypeDescription<'tcx> {
-
-    // Insert the stub into the TypeMap in order to allow for recursive references
-    let mut type_map = debug_context(cx).type_map.borrow_mut();
-    type_map.register_unique_id_with_metadata(cx, unique_type_id, metadata_stub);
-    type_map.register_type_with_metadata(cx, unfinished_type, metadata_stub);
-
-    UnfinishedMetadata {
-        unfinished_type: unfinished_type,
-        unique_type_id: unique_type_id,
-        metadata_stub: metadata_stub,
-        llvm_type: llvm_type,
-        member_description_factory: member_description_factory,
-    }
-}
-
-impl<'tcx> RecursiveTypeDescription<'tcx> {
-    // Finishes up the description of the type in question (mostly by providing
-    // descriptions of the fields of the given type) and returns the final type metadata.
-    fn finalize<'a>(&self, cx: &CrateContext<'a, 'tcx>) -> MetadataCreationResult {
-        match *self {
-            FinalMetadata(metadata) => MetadataCreationResult::new(metadata, false),
-            UnfinishedMetadata {
-                unfinished_type,
-                unique_type_id,
-                metadata_stub,
-                llvm_type,
-                ref member_description_factory,
-                ..
-            } => {
-                // Make sure that we have a forward declaration of the type in
-                // the TypeMap so that recursive references are possible. This
-                // will always be the case if the RecursiveTypeDescription has
-                // been properly created through the
-                // create_and_register_recursive_type_forward_declaration() function.
-                {
-                    let type_map = debug_context(cx).type_map.borrow();
-                    if type_map.find_metadata_for_unique_id(unique_type_id).is_none() ||
-                       type_map.find_metadata_for_type(unfinished_type).is_none() {
-                        cx.sess().bug(&format!("Forward declaration of potentially recursive type \
-                                              '{}' was not found in TypeMap!",
-                                              ppaux::ty_to_string(cx.tcx(), unfinished_type))
-                                      );
-                    }
-                }
-
-                // ... then create the member descriptions ...
-                let member_descriptions =
-                    member_description_factory.create_member_descriptions(cx);
-
-                // ... and attach them to the stub to complete it.
-                set_members_of_composite_type(cx,
-                                              metadata_stub,
-                                              llvm_type,
-                                              &member_descriptions[..]);
-                return MetadataCreationResult::new(metadata_stub, true);
-            }
-        }
-    }
-}
-
-
-//=-----------------------------------------------------------------------------
-// Structs
-//=-----------------------------------------------------------------------------
-
-// Creates MemberDescriptions for the fields of a struct
-struct StructMemberDescriptionFactory<'tcx> {
-    fields: Vec<ty::field<'tcx>>,
-    is_simd: bool,
-    span: Span,
-}
-
-impl<'tcx> StructMemberDescriptionFactory<'tcx> {
-    fn create_member_descriptions<'a>(&self, cx: &CrateContext<'a, 'tcx>)
-                                      -> Vec<MemberDescription> {
-        if self.fields.is_empty() {
-            return Vec::new();
-        }
-
-        let field_size = if self.is_simd {
-            machine::llsize_of_alloc(cx, type_of::type_of(cx, self.fields[0].mt.ty)) as usize
-        } else {
-            0xdeadbeef
-        };
-
-        self.fields.iter().enumerate().map(|(i, field)| {
-            let name = if field.name == special_idents::unnamed_field.name {
-                format!("__{}", i)
-            } else {
-                token::get_name(field.name).to_string()
-            };
-
-            let offset = if self.is_simd {
-                assert!(field_size != 0xdeadbeef);
-                FixedMemberOffset { bytes: i * field_size }
-            } else {
-                ComputedMemberOffset
-            };
-
-            MemberDescription {
-                name: name,
-                llvm_type: type_of::type_of(cx, field.mt.ty),
-                type_metadata: type_metadata(cx, field.mt.ty, self.span),
-                offset: offset,
-                flags: FLAGS_NONE,
-            }
-        }).collect()
-    }
-}
-
-
-fn prepare_struct_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
-                                     struct_type: Ty<'tcx>,
-                                     def_id: ast::DefId,
-                                     substs: &subst::Substs<'tcx>,
-                                     unique_type_id: UniqueTypeId,
-                                     span: Span)
-                                     -> RecursiveTypeDescription<'tcx> {
-    let struct_name = compute_debuginfo_type_name(cx, struct_type, false);
-    let struct_llvm_type = type_of::type_of(cx, struct_type);
-
-    let (containing_scope, _) = get_namespace_and_span_for_item(cx, def_id);
-
-    let struct_metadata_stub = create_struct_stub(cx,
-                                                  struct_llvm_type,
-                                                  &struct_name[..],
-                                                  unique_type_id,
-                                                  containing_scope);
-
-    let mut fields = ty::struct_fields(cx.tcx(), def_id, substs);
-
-    // The `Ty` values returned by `ty::struct_fields` can still contain
-    // `ty_projection` variants, so normalize those away.
-    for field in &mut fields {
-        field.mt.ty = monomorphize::normalize_associated_type(cx.tcx(), &field.mt.ty);
-    }
-
-    create_and_register_recursive_type_forward_declaration(
-        cx,
-        struct_type,
-        unique_type_id,
-        struct_metadata_stub,
-        struct_llvm_type,
-        StructMDF(StructMemberDescriptionFactory {
-            fields: fields,
-            is_simd: ty::type_is_simd(cx.tcx(), struct_type),
-            span: span,
-        })
-    )
-}
-
-
-//=-----------------------------------------------------------------------------
-// Tuples
-//=-----------------------------------------------------------------------------
-
-// Creates MemberDescriptions for the fields of a tuple
-struct TupleMemberDescriptionFactory<'tcx> {
-    component_types: Vec<Ty<'tcx>>,
-    span: Span,
-}
-
-impl<'tcx> TupleMemberDescriptionFactory<'tcx> {
-    fn create_member_descriptions<'a>(&self, cx: &CrateContext<'a, 'tcx>)
-                                      -> Vec<MemberDescription> {
-        self.component_types
-            .iter()
-            .enumerate()
-            .map(|(i, &component_type)| {
-            MemberDescription {
-                name: format!("__{}", i),
-                llvm_type: type_of::type_of(cx, component_type),
-                type_metadata: type_metadata(cx, component_type, self.span),
-                offset: ComputedMemberOffset,
-                flags: FLAGS_NONE,
-            }
-        }).collect()
-    }
-}
-
-fn prepare_tuple_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
-                                    tuple_type: Ty<'tcx>,
-                                    component_types: &[Ty<'tcx>],
-                                    unique_type_id: UniqueTypeId,
-                                    span: Span)
-                                    -> RecursiveTypeDescription<'tcx> {
-    let tuple_name = compute_debuginfo_type_name(cx, tuple_type, false);
-    let tuple_llvm_type = type_of::type_of(cx, tuple_type);
-
-    create_and_register_recursive_type_forward_declaration(
-        cx,
-        tuple_type,
-        unique_type_id,
-        create_struct_stub(cx,
-                           tuple_llvm_type,
-                           &tuple_name[..],
-                           unique_type_id,
-                           UNKNOWN_SCOPE_METADATA),
-        tuple_llvm_type,
-        TupleMDF(TupleMemberDescriptionFactory {
-            component_types: component_types.to_vec(),
-            span: span,
-        })
-    )
-}
-
-
-//=-----------------------------------------------------------------------------
-// Enums
-//=-----------------------------------------------------------------------------
-
-// Describes the members of an enum value: An enum is described as a union of
-// structs in DWARF. This MemberDescriptionFactory provides the description for
-// the members of this union; so for every variant of the given enum, this factory
-// will produce one MemberDescription (all with no name and a fixed offset of
-// zero bytes).
-struct EnumMemberDescriptionFactory<'tcx> {
-    enum_type: Ty<'tcx>,
-    type_rep: Rc<adt::Repr<'tcx>>,
-    variants: Rc<Vec<Rc<ty::VariantInfo<'tcx>>>>,
-    discriminant_type_metadata: Option<DIType>,
-    containing_scope: DIScope,
-    file_metadata: DIFile,
-    span: Span,
-}
-
-impl<'tcx> EnumMemberDescriptionFactory<'tcx> {
-    fn create_member_descriptions<'a>(&self, cx: &CrateContext<'a, 'tcx>)
-                                      -> Vec<MemberDescription> {
-        match *self.type_rep {
-            adt::General(_, ref struct_defs, _) => {
-                let discriminant_info = RegularDiscriminant(self.discriminant_type_metadata
-                    .expect(""));
-
-                struct_defs
-                    .iter()
-                    .enumerate()
-                    .map(|(i, struct_def)| {
-                        let (variant_type_metadata,
-                             variant_llvm_type,
-                             member_desc_factory) =
-                            describe_enum_variant(cx,
-                                                  self.enum_type,
-                                                  struct_def,
-                                                  &*(*self.variants)[i],
-                                                  discriminant_info,
-                                                  self.containing_scope,
-                                                  self.span);
-
-                        let member_descriptions = member_desc_factory
-                            .create_member_descriptions(cx);
-
-                        set_members_of_composite_type(cx,
-                                                      variant_type_metadata,
-                                                      variant_llvm_type,
-                                                      &member_descriptions[..]);
-                        MemberDescription {
-                            name: "".to_string(),
-                            llvm_type: variant_llvm_type,
-                            type_metadata: variant_type_metadata,
-                            offset: FixedMemberOffset { bytes: 0 },
-                            flags: FLAGS_NONE
-                        }
-                    }).collect()
-            },
-            adt::Univariant(ref struct_def, _) => {
-                assert!(self.variants.len() <= 1);
-
-                if self.variants.is_empty() {
-                    vec![]
-                } else {
-                    let (variant_type_metadata,
-                         variant_llvm_type,
-                         member_description_factory) =
-                        describe_enum_variant(cx,
-                                              self.enum_type,
-                                              struct_def,
-                                              &*(*self.variants)[0],
-                                              NoDiscriminant,
-                                              self.containing_scope,
-                                              self.span);
-
-                    let member_descriptions =
-                        member_description_factory.create_member_descriptions(cx);
-
-                    set_members_of_composite_type(cx,
-                                                  variant_type_metadata,
-                                                  variant_llvm_type,
-                                                  &member_descriptions[..]);
-                    vec![
-                        MemberDescription {
-                            name: "".to_string(),
-                            llvm_type: variant_llvm_type,
-                            type_metadata: variant_type_metadata,
-                            offset: FixedMemberOffset { bytes: 0 },
-                            flags: FLAGS_NONE
-                        }
-                    ]
-                }
-            }
-            adt::RawNullablePointer { nndiscr: non_null_variant_index, nnty, .. } => {
-                // As far as debuginfo is concerned, the pointer this enum
-                // represents is still wrapped in a struct. This is to make the
-                // DWARF representation of enums uniform.
-
-                // First create a description of the artificial wrapper struct:
-                let non_null_variant = &(*self.variants)[non_null_variant_index as usize];
-                let non_null_variant_name = token::get_name(non_null_variant.name);
-
-                // The llvm type and metadata of the pointer
-                let non_null_llvm_type = type_of::type_of(cx, nnty);
-                let non_null_type_metadata = type_metadata(cx, nnty, self.span);
-
-                // The type of the artificial struct wrapping the pointer
-                let artificial_struct_llvm_type = Type::struct_(cx,
-                                                                &[non_null_llvm_type],
-                                                                false);
-
-                // For the metadata of the wrapper struct, we need to create a
-                // MemberDescription of the struct's single field.
-                let sole_struct_member_description = MemberDescription {
-                    name: match non_null_variant.arg_names {
-                        Some(ref names) => token::get_name(names[0]).to_string(),
-                        None => "__0".to_string()
-                    },
-                    llvm_type: non_null_llvm_type,
-                    type_metadata: non_null_type_metadata,
-                    offset: FixedMemberOffset { bytes: 0 },
-                    flags: FLAGS_NONE
-                };
-
-                let unique_type_id = debug_context(cx).type_map
-                                                      .borrow_mut()
-                                                      .get_unique_type_id_of_enum_variant(
-                                                          cx,
-                                                          self.enum_type,
-                                                          &non_null_variant_name);
-
-                // Now we can create the metadata of the artificial struct
-                let artificial_struct_metadata =
-                    composite_type_metadata(cx,
-                                            artificial_struct_llvm_type,
-                                            &non_null_variant_name,
-                                            unique_type_id,
-                                            &[sole_struct_member_description],
-                                            self.containing_scope,
-                                            self.file_metadata,
-                                            codemap::DUMMY_SP);
-
-                // Encode the information about the null variant in the union
-                // member's name.
-                let null_variant_index = (1 - non_null_variant_index) as usize;
-                let null_variant_name = token::get_name((*self.variants)[null_variant_index].name);
-                let union_member_name = format!("RUST$ENCODED$ENUM${}${}",
-                                                0,
-                                                null_variant_name);
-
-                // Finally create the (singleton) list of descriptions of union
-                // members.
-                vec![
-                    MemberDescription {
-                        name: union_member_name,
-                        llvm_type: artificial_struct_llvm_type,
-                        type_metadata: artificial_struct_metadata,
-                        offset: FixedMemberOffset { bytes: 0 },
-                        flags: FLAGS_NONE
-                    }
-                ]
-            },
-            adt::StructWrappedNullablePointer { nonnull: ref struct_def,
-                                                nndiscr,
-                                                ref discrfield, ..} => {
-                // Create a description of the non-null variant
-                let (variant_type_metadata, variant_llvm_type, member_description_factory) =
-                    describe_enum_variant(cx,
-                                          self.enum_type,
-                                          struct_def,
-                                          &*(*self.variants)[nndiscr as usize],
-                                          OptimizedDiscriminant,
-                                          self.containing_scope,
-                                          self.span);
-
-                let variant_member_descriptions =
-                    member_description_factory.create_member_descriptions(cx);
-
-                set_members_of_composite_type(cx,
-                                              variant_type_metadata,
-                                              variant_llvm_type,
-                                              &variant_member_descriptions[..]);
-
-                // Encode the information about the null variant in the union
-                // member's name.
-                let null_variant_index = (1 - nndiscr) as usize;
-                let null_variant_name = token::get_name((*self.variants)[null_variant_index].name);
-                let discrfield = discrfield.iter()
-                                           .skip(1)
-                                           .map(|x| x.to_string())
-                                           .collect::<Vec<_>>().connect("$");
-                let union_member_name = format!("RUST$ENCODED$ENUM${}${}",
-                                                discrfield,
-                                                null_variant_name);
-
-                // Create the (singleton) list of descriptions of union members.
-                vec![
-                    MemberDescription {
-                        name: union_member_name,
-                        llvm_type: variant_llvm_type,
-                        type_metadata: variant_type_metadata,
-                        offset: FixedMemberOffset { bytes: 0 },
-                        flags: FLAGS_NONE
-                    }
-                ]
-            },
-            adt::CEnum(..) => cx.sess().span_bug(self.span, "This should be unreachable.")
-        }
-    }
-}
-
-// Creates MemberDescriptions for the fields of a single enum variant.
-struct VariantMemberDescriptionFactory<'tcx> {
-    args: Vec<(String, Ty<'tcx>)>,
-    discriminant_type_metadata: Option<DIType>,
-    span: Span,
-}
-
-impl<'tcx> VariantMemberDescriptionFactory<'tcx> {
-    fn create_member_descriptions<'a>(&self, cx: &CrateContext<'a, 'tcx>)
-                                      -> Vec<MemberDescription> {
-        self.args.iter().enumerate().map(|(i, &(ref name, ty))| {
-            MemberDescription {
-                name: name.to_string(),
-                llvm_type: type_of::type_of(cx, ty),
-                type_metadata: match self.discriminant_type_metadata {
-                    Some(metadata) if i == 0 => metadata,
-                    _ => type_metadata(cx, ty, self.span)
-                },
-                offset: ComputedMemberOffset,
-                flags: FLAGS_NONE
-            }
-        }).collect()
-    }
-}
-
-#[derive(Copy, Clone)]
-enum EnumDiscriminantInfo {
-    RegularDiscriminant(DIType),
-    OptimizedDiscriminant,
-    NoDiscriminant
-}
-
-// Returns a tuple of (1) type_metadata_stub of the variant, (2) the llvm_type
-// of the variant, and (3) a MemberDescriptionFactory for producing the
-// descriptions of the fields of the variant. This is a rudimentary version of a
-// full RecursiveTypeDescription.
-fn describe_enum_variant<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
-                                   enum_type: Ty<'tcx>,
-                                   struct_def: &adt::Struct<'tcx>,
-                                   variant_info: &ty::VariantInfo<'tcx>,
-                                   discriminant_info: EnumDiscriminantInfo,
-                                   containing_scope: DIScope,
-                                   span: Span)
-                                   -> (DICompositeType, Type, MemberDescriptionFactory<'tcx>) {
-    let variant_llvm_type =
-        Type::struct_(cx, &struct_def.fields
-                                    .iter()
-                                    .map(|&t| type_of::type_of(cx, t))
-                                    .collect::<Vec<_>>()
-                                    ,
-                      struct_def.packed);
-    // Could do some consistency checks here: size, align, field count, discr type
-
-    let variant_name = token::get_name(variant_info.name);
-    let variant_name = &variant_name;
-    let unique_type_id = debug_context(cx).type_map
-                                          .borrow_mut()
-                                          .get_unique_type_id_of_enum_variant(
-                                              cx,
-                                              enum_type,
-                                              variant_name);
-
-    let metadata_stub = create_struct_stub(cx,
-                                           variant_llvm_type,
-                                           variant_name,
-                                           unique_type_id,
-                                           containing_scope);
-
-    // Get the argument names from the enum variant info
-    let mut arg_names: Vec<_> = match variant_info.arg_names {
-        Some(ref names) => {
-            names.iter()
-                 .map(|&name| token::get_name(name).to_string())
-                 .collect()
-        }
-        None => {
-            variant_info.args
-                        .iter()
-                        .enumerate()
-                        .map(|(i, _)| format!("__{}", i))
-                        .collect()
-        }
-    };
-
-    // If this is not a univariant enum, there is also the discriminant field.
-    match discriminant_info {
-        RegularDiscriminant(_) => arg_names.insert(0, "RUST$ENUM$DISR".to_string()),
-        _ => { /* do nothing */ }
-    };
-
-    // Build an array of (field name, field type) pairs to be captured in the factory closure.
-    let args: Vec<(String, Ty)> = arg_names.iter()
-        .zip(struct_def.fields.iter())
-        .map(|(s, &t)| (s.to_string(), t))
-        .collect();
-
-    let member_description_factory =
-        VariantMDF(VariantMemberDescriptionFactory {
-            args: args,
-            discriminant_type_metadata: match discriminant_info {
-                RegularDiscriminant(discriminant_type_metadata) => {
-                    Some(discriminant_type_metadata)
-                }
-                _ => None
-            },
-            span: span,
-        });
-
-    (metadata_stub, variant_llvm_type, member_description_factory)
-}
-
-fn prepare_enum_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
-                                   enum_type: Ty<'tcx>,
-                                   enum_def_id: ast::DefId,
-                                   unique_type_id: UniqueTypeId,
-                                   span: Span)
-                                   -> RecursiveTypeDescription<'tcx> {
-    let enum_name = compute_debuginfo_type_name(cx, enum_type, false);
-
-    let (containing_scope, definition_span) = get_namespace_and_span_for_item(cx, enum_def_id);
-    let loc = span_start(cx, definition_span);
-    let file_metadata = file_metadata(cx, &loc.file.name);
-
-    let variants = ty::enum_variants(cx.tcx(), enum_def_id);
-
-    let enumerators_metadata: Vec<DIDescriptor> = variants
-        .iter()
-        .map(|v| {
-            let token = token::get_name(v.name);
-            let name = CString::new(token.as_bytes()).unwrap();
-            unsafe {
-                llvm::LLVMDIBuilderCreateEnumerator(
-                    DIB(cx),
-                    name.as_ptr(),
-                    v.disr_val as u64)
-            }
-        })
-        .collect();
-
-    let discriminant_type_metadata = |inttype| {
-        // We can reuse the type of the discriminant for all monomorphized
-        // instances of an enum because it doesn't depend on any type parameters.
-        // The def_id, uniquely identifying the enum's polytype acts as key in
-        // this cache.
-        let cached_discriminant_type_metadata = debug_context(cx).created_enum_disr_types
-                                                                 .borrow()
-                                                                 .get(&enum_def_id).cloned();
-        match cached_discriminant_type_metadata {
-            Some(discriminant_type_metadata) => discriminant_type_metadata,
-            None => {
-                let discriminant_llvm_type = adt::ll_inttype(cx, inttype);
-                let (discriminant_size, discriminant_align) =
-                    size_and_align_of(cx, discriminant_llvm_type);
-                let discriminant_base_type_metadata =
-                    type_metadata(cx,
-                                  adt::ty_of_inttype(cx.tcx(), inttype),
-                                  codemap::DUMMY_SP);
-                let discriminant_name = get_enum_discriminant_name(cx, enum_def_id);
-
-                let name = CString::new(discriminant_name.as_bytes()).unwrap();
-                let discriminant_type_metadata = unsafe {
-                    llvm::LLVMDIBuilderCreateEnumerationType(
-                        DIB(cx),
-                        containing_scope,
-                        name.as_ptr(),
-                        UNKNOWN_FILE_METADATA,
-                        UNKNOWN_LINE_NUMBER,
-                        bytes_to_bits(discriminant_size),
-                        bytes_to_bits(discriminant_align),
-                        create_DIArray(DIB(cx), &enumerators_metadata),
-                        discriminant_base_type_metadata)
-                };
-
-                debug_context(cx).created_enum_disr_types
-                                 .borrow_mut()
-                                 .insert(enum_def_id, discriminant_type_metadata);
-
-                discriminant_type_metadata
-            }
-        }
-    };
-
-    let type_rep = adt::represent_type(cx, enum_type);
-
-    let discriminant_type_metadata = match *type_rep {
-        adt::CEnum(inttype, _, _) => {
-            return FinalMetadata(discriminant_type_metadata(inttype))
-        },
-        adt::RawNullablePointer { .. }           |
-        adt::StructWrappedNullablePointer { .. } |
-        adt::Univariant(..)                      => None,
-        adt::General(inttype, _, _) => Some(discriminant_type_metadata(inttype)),
-    };
-
-    let enum_llvm_type = type_of::type_of(cx, enum_type);
-    let (enum_type_size, enum_type_align) = size_and_align_of(cx, enum_llvm_type);
-
-    let unique_type_id_str = debug_context(cx)
-                             .type_map
-                             .borrow()
-                             .get_unique_type_id_as_string(unique_type_id);
-
-    let enum_name = CString::new(enum_name).unwrap();
-    let unique_type_id_str = CString::new(unique_type_id_str.as_bytes()).unwrap();
-    let enum_metadata = unsafe {
-        llvm::LLVMDIBuilderCreateUnionType(
-        DIB(cx),
-        containing_scope,
-        enum_name.as_ptr(),
-        UNKNOWN_FILE_METADATA,
-        UNKNOWN_LINE_NUMBER,
-        bytes_to_bits(enum_type_size),
-        bytes_to_bits(enum_type_align),
-        0, // Flags
-        ptr::null_mut(),
-        0, // RuntimeLang
-        unique_type_id_str.as_ptr())
-    };
-
-    return create_and_register_recursive_type_forward_declaration(
-        cx,
-        enum_type,
-        unique_type_id,
-        enum_metadata,
-        enum_llvm_type,
-        EnumMDF(EnumMemberDescriptionFactory {
-            enum_type: enum_type,
-            type_rep: type_rep.clone(),
-            variants: variants,
-            discriminant_type_metadata: discriminant_type_metadata,
-            containing_scope: containing_scope,
-            file_metadata: file_metadata,
-            span: span,
-        }),
-    );
-
-    fn get_enum_discriminant_name(cx: &CrateContext,
-                                  def_id: ast::DefId)
-                                  -> token::InternedString {
-        let name = if def_id.krate == ast::LOCAL_CRATE {
-            cx.tcx().map.get_path_elem(def_id.node).name()
-        } else {
-            csearch::get_item_path(cx.tcx(), def_id).last().unwrap().name()
-        };
-
-        token::get_name(name)
-    }
-}
-
-/// Creates debug information for a composite type, that is, anything that
-/// results in a LLVM struct.
-///
-/// Examples of Rust types to use this are: structs, tuples, boxes, vecs, and enums.
-fn composite_type_metadata(cx: &CrateContext,
-                           composite_llvm_type: Type,
-                           composite_type_name: &str,
-                           composite_type_unique_id: UniqueTypeId,
-                           member_descriptions: &[MemberDescription],
-                           containing_scope: DIScope,
-
-                           // Ignore source location information as long as it
-                           // can't be reconstructed for non-local crates.
-                           _file_metadata: DIFile,
-                           _definition_span: Span)
-                        -> DICompositeType {
-    // Create the (empty) struct metadata node ...
-    let composite_type_metadata = create_struct_stub(cx,
-                                                     composite_llvm_type,
-                                                     composite_type_name,
-                                                     composite_type_unique_id,
-                                                     containing_scope);
-    // ... and immediately create and add the member descriptions.
-    set_members_of_composite_type(cx,
-                                  composite_type_metadata,
-                                  composite_llvm_type,
-                                  member_descriptions);
-
-    return composite_type_metadata;
-}
-
-fn set_members_of_composite_type(cx: &CrateContext,
-                                 composite_type_metadata: DICompositeType,
-                                 composite_llvm_type: Type,
-                                 member_descriptions: &[MemberDescription]) {
-    // In some rare cases LLVM metadata uniquing would lead to an existing type
-    // description being used instead of a new one created in create_struct_stub.
-    // This would cause a hard to trace assertion in DICompositeType::SetTypeArray().
-    // The following check makes sure that we get a better error message if this
-    // should happen again due to some regression.
-    {
-        let mut composite_types_completed =
-            debug_context(cx).composite_types_completed.borrow_mut();
-        if composite_types_completed.contains(&composite_type_metadata) {
-            cx.sess().bug("debuginfo::set_members_of_composite_type() - \
-                           Already completed forward declaration re-encountered.");
-        } else {
-            composite_types_completed.insert(composite_type_metadata);
-        }
-    }
-
-    let member_metadata: Vec<DIDescriptor> = member_descriptions
-        .iter()
-        .enumerate()
-        .map(|(i, member_description)| {
-            let (member_size, member_align) = size_and_align_of(cx, member_description.llvm_type);
-            let member_offset = match member_description.offset {
-                FixedMemberOffset { bytes } => bytes as u64,
-                ComputedMemberOffset => machine::llelement_offset(cx, composite_llvm_type, i)
-            };
-
-            let member_name = member_description.name.as_bytes();
-            let member_name = CString::new(member_name).unwrap();
-            unsafe {
-                llvm::LLVMDIBuilderCreateMemberType(
-                    DIB(cx),
-                    composite_type_metadata,
-                    member_name.as_ptr(),
-                    UNKNOWN_FILE_METADATA,
-                    UNKNOWN_LINE_NUMBER,
-                    bytes_to_bits(member_size),
-                    bytes_to_bits(member_align),
-                    bytes_to_bits(member_offset),
-                    member_description.flags,
-                    member_description.type_metadata)
-            }
-        })
-        .collect();
-
-    unsafe {
-        let type_array = create_DIArray(DIB(cx), &member_metadata[..]);
-        llvm::LLVMDICompositeTypeSetTypeArray(DIB(cx), composite_type_metadata, type_array);
-    }
-}
-
-// A convenience wrapper around LLVMDIBuilderCreateStructType(). Does not do any
-// caching, does not add any fields to the struct. This can be done later with
-// set_members_of_composite_type().
-fn create_struct_stub(cx: &CrateContext,
-                      struct_llvm_type: Type,
-                      struct_type_name: &str,
-                      unique_type_id: UniqueTypeId,
-                      containing_scope: DIScope)
-                   -> DICompositeType {
-    let (struct_size, struct_align) = size_and_align_of(cx, struct_llvm_type);
-
-    let unique_type_id_str = debug_context(cx).type_map
-                                              .borrow()
-                                              .get_unique_type_id_as_string(unique_type_id);
-    let name = CString::new(struct_type_name).unwrap();
-    let unique_type_id = CString::new(unique_type_id_str.as_bytes()).unwrap();
-    let metadata_stub = unsafe {
-        // LLVMDIBuilderCreateStructType() wants an empty array. A null
-        // pointer will lead to hard to trace and debug LLVM assertions
-        // later on in llvm/lib/IR/Value.cpp.
-        let empty_array = create_DIArray(DIB(cx), &[]);
-
-        llvm::LLVMDIBuilderCreateStructType(
-            DIB(cx),
-            containing_scope,
-            name.as_ptr(),
-            UNKNOWN_FILE_METADATA,
-            UNKNOWN_LINE_NUMBER,
-            bytes_to_bits(struct_size),
-            bytes_to_bits(struct_align),
-            0,
-            ptr::null_mut(),
-            empty_array,
-            0,
-            ptr::null_mut(),
-            unique_type_id.as_ptr())
-    };
-
-    return metadata_stub;
-}
-
-fn fixed_vec_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
-                                unique_type_id: UniqueTypeId,
-                                element_type: Ty<'tcx>,
-                                len: Option<u64>,
-                                span: Span)
-                                -> MetadataCreationResult {
-    let element_type_metadata = type_metadata(cx, element_type, span);
-
-    return_if_metadata_created_in_meantime!(cx, unique_type_id);
-
-    let element_llvm_type = type_of::type_of(cx, element_type);
-    let (element_type_size, element_type_align) = size_and_align_of(cx, element_llvm_type);
-
-    let (array_size_in_bytes, upper_bound) = match len {
-        Some(len) => (element_type_size * len, len as c_longlong),
-        None => (0, -1)
-    };
-
-    let subrange = unsafe {
-        llvm::LLVMDIBuilderGetOrCreateSubrange(DIB(cx), 0, upper_bound)
-    };
-
-    let subscripts = create_DIArray(DIB(cx), &[subrange]);
-    let metadata = unsafe {
-        llvm::LLVMDIBuilderCreateArrayType(
-            DIB(cx),
-            bytes_to_bits(array_size_in_bytes),
-            bytes_to_bits(element_type_align),
-            element_type_metadata,
-            subscripts)
-    };
-
-    return MetadataCreationResult::new(metadata, false);
-}
-
-fn vec_slice_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
-                                vec_type: Ty<'tcx>,
-                                element_type: Ty<'tcx>,
-                                unique_type_id: UniqueTypeId,
-                                span: Span)
-                                -> MetadataCreationResult {
-    let data_ptr_type = ty::mk_ptr(cx.tcx(), ty::mt {
-        ty: element_type,
-        mutbl: ast::MutImmutable
-    });
-
-    let element_type_metadata = type_metadata(cx, data_ptr_type, span);
-
-    return_if_metadata_created_in_meantime!(cx, unique_type_id);
-
-    let slice_llvm_type = type_of::type_of(cx, vec_type);
-    let slice_type_name = compute_debuginfo_type_name(cx, vec_type, true);
-
-    let member_llvm_types = slice_llvm_type.field_types();
-    assert!(slice_layout_is_correct(cx,
-                                    &member_llvm_types[..],
-                                    element_type));
-    let member_descriptions = [
-        MemberDescription {
-            name: "data_ptr".to_string(),
-            llvm_type: member_llvm_types[0],
-            type_metadata: element_type_metadata,
-            offset: ComputedMemberOffset,
-            flags: FLAGS_NONE
-        },
-        MemberDescription {
-            name: "length".to_string(),
-            llvm_type: member_llvm_types[1],
-            type_metadata: type_metadata(cx, cx.tcx().types.usize, span),
-            offset: ComputedMemberOffset,
-            flags: FLAGS_NONE
-        },
-    ];
-
-    assert!(member_descriptions.len() == member_llvm_types.len());
-
-    let loc = span_start(cx, span);
-    let file_metadata = file_metadata(cx, &loc.file.name);
-
-    let metadata = composite_type_metadata(cx,
-                                           slice_llvm_type,
-                                           &slice_type_name[..],
-                                           unique_type_id,
-                                           &member_descriptions,
-                                           UNKNOWN_SCOPE_METADATA,
-                                           file_metadata,
-                                           span);
-    return MetadataCreationResult::new(metadata, false);
-
-    fn slice_layout_is_correct<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
-                                         member_llvm_types: &[Type],
-                                         element_type: Ty<'tcx>)
-                                         -> bool {
-        member_llvm_types.len() == 2 &&
-        member_llvm_types[0] == type_of::type_of(cx, element_type).ptr_to() &&
-        member_llvm_types[1] == cx.int_type()
-    }
-}
-
-fn subroutine_type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
-                                      unique_type_id: UniqueTypeId,
-                                      signature: &ty::PolyFnSig<'tcx>,
-                                      span: Span)
-                                      -> MetadataCreationResult
-{
-    let signature = ty::erase_late_bound_regions(cx.tcx(), signature);
-
-    let mut signature_metadata: Vec<DIType> = Vec::with_capacity(signature.inputs.len() + 1);
-
-    // return type
-    signature_metadata.push(match signature.output {
-        ty::FnConverging(ret_ty) => match ret_ty.sty {
-            ty::ty_tup(ref tys) if tys.is_empty() => ptr::null_mut(),
-            _ => type_metadata(cx, ret_ty, span)
-        },
-        ty::FnDiverging => diverging_type_metadata(cx)
-    });
-
-    // regular arguments
-    for &argument_type in &signature.inputs {
-        signature_metadata.push(type_metadata(cx, argument_type, span));
-    }
-
-    return_if_metadata_created_in_meantime!(cx, unique_type_id);
-
-    return MetadataCreationResult::new(
-        unsafe {
-            llvm::LLVMDIBuilderCreateSubroutineType(
-                DIB(cx),
-                UNKNOWN_FILE_METADATA,
-                create_DIArray(DIB(cx), &signature_metadata[..]))
-        },
-        false);
-}
-
-// FIXME(1563) This is all a bit of a hack because 'trait pointer' is an ill-
-// defined concept. For the case of an actual trait pointer (i.e., Box<Trait>,
-// &Trait), trait_object_type should be the whole thing (e.g, Box<Trait>) and
-// trait_type should be the actual trait (e.g., Trait). Where the trait is part
-// of a DST struct, there is no trait_object_type and the results of this
-// function will be a little bit weird.
-fn trait_pointer_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
-                                    trait_type: Ty<'tcx>,
-                                    trait_object_type: Option<Ty<'tcx>>,
-                                    unique_type_id: UniqueTypeId)
-                                    -> DIType {
-    // The implementation provided here is a stub. It makes sure that the trait
-    // type is assigned the correct name, size, namespace, and source location.
-    // But it does not describe the trait's methods.
-
-    let def_id = match trait_type.sty {
-        ty::ty_trait(ref data) => data.principal_def_id(),
-        _ => {
-            let pp_type_name = ppaux::ty_to_string(cx.tcx(), trait_type);
-            cx.sess().bug(&format!("debuginfo: Unexpected trait-object type in \
-                                   trait_pointer_metadata(): {}",
-                                   &pp_type_name[..]));
-        }
-    };
-
-    let trait_object_type = trait_object_type.unwrap_or(trait_type);
-    let trait_type_name =
-        compute_debuginfo_type_name(cx, trait_object_type, false);
-
-    let (containing_scope, _) = get_namespace_and_span_for_item(cx, def_id);
-
-    let trait_llvm_type = type_of::type_of(cx, trait_object_type);
-
-    composite_type_metadata(cx,
-                            trait_llvm_type,
-                            &trait_type_name[..],
-                            unique_type_id,
-                            &[],
-                            containing_scope,
-                            UNKNOWN_FILE_METADATA,
-                            codemap::DUMMY_SP)
-}
-
-fn type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
-                           t: Ty<'tcx>,
-                           usage_site_span: Span)
-                           -> DIType {
-    // Get the unique type id of this type.
-    let unique_type_id = {
-        let mut type_map = debug_context(cx).type_map.borrow_mut();
-        // First, try to find the type in TypeMap. If we have seen it before, we
-        // can exit early here.
-        match type_map.find_metadata_for_type(t) {
-            Some(metadata) => {
-                return metadata;
-            },
-            None => {
-                // The Ty is not in the TypeMap but maybe we have already seen
-                // an equivalent type (e.g. only differing in region arguments).
-                // In order to find out, generate the unique type id and look
-                // that up.
-                let unique_type_id = type_map.get_unique_type_id_of_type(cx, t);
-                match type_map.find_metadata_for_unique_id(unique_type_id) {
-                    Some(metadata) => {
-                        // There is already an equivalent type in the TypeMap.
-                        // Register this Ty as an alias in the cache and
-                        // return the cached metadata.
-                        type_map.register_type_with_metadata(cx, t, metadata);
-                        return metadata;
-                    },
-                    None => {
-                        // There really is no type metadata for this type, so
-                        // proceed by creating it.
-                        unique_type_id
-                    }
-                }
-            }
-        }
-    };
-
-    debug!("type_metadata: {:?}", t);
-
-    let sty = &t.sty;
-    let MetadataCreationResult { metadata, already_stored_in_typemap } = match *sty {
-        ty::ty_bool     |
-        ty::ty_char     |
-        ty::ty_int(_)   |
-        ty::ty_uint(_)  |
-        ty::ty_float(_) => {
-            MetadataCreationResult::new(basic_type_metadata(cx, t), false)
-        }
-        ty::ty_tup(ref elements) if elements.is_empty() => {
-            MetadataCreationResult::new(basic_type_metadata(cx, t), false)
-        }
-        ty::ty_enum(def_id, _) => {
-            prepare_enum_metadata(cx, t, def_id, unique_type_id, usage_site_span).finalize(cx)
-        }
-        ty::ty_vec(typ, len) => {
-            fixed_vec_metadata(cx, unique_type_id, typ, len.map(|x| x as u64), usage_site_span)
-        }
-        ty::ty_str => {
-            fixed_vec_metadata(cx, unique_type_id, cx.tcx().types.i8, None, usage_site_span)
-        }
-        ty::ty_trait(..) => {
-            MetadataCreationResult::new(
-                        trait_pointer_metadata(cx, t, None, unique_type_id),
-            false)
-        }
-        ty::ty_uniq(ty) | ty::ty_ptr(ty::mt{ty, ..}) | ty::ty_rptr(_, ty::mt{ty, ..}) => {
-            match ty.sty {
-                ty::ty_vec(typ, None) => {
-                    vec_slice_metadata(cx, t, typ, unique_type_id, usage_site_span)
-                }
-                ty::ty_str => {
-                    vec_slice_metadata(cx, t, cx.tcx().types.u8, unique_type_id, usage_site_span)
-                }
-                ty::ty_trait(..) => {
-                    MetadataCreationResult::new(
-                        trait_pointer_metadata(cx, ty, Some(t), unique_type_id),
-                        false)
-                }
-                _ => {
-                    let pointee_metadata = type_metadata(cx, ty, usage_site_span);
-
-                    match debug_context(cx).type_map
-                                           .borrow()
-                                           .find_metadata_for_unique_id(unique_type_id) {
-                        Some(metadata) => return metadata,
-                        None => { /* proceed normally */ }
-                    };
-
-                    MetadataCreationResult::new(pointer_type_metadata(cx, t, pointee_metadata),
-                                                false)
-                }
-            }
-        }
-        ty::ty_bare_fn(_, ref barefnty) => {
-            subroutine_type_metadata(cx, unique_type_id, &barefnty.sig, usage_site_span)
-        }
-        ty::ty_closure(def_id, substs) => {
-            let typer = NormalizingClosureTyper::new(cx.tcx());
-            let sig = typer.closure_type(def_id, substs).sig;
-            subroutine_type_metadata(cx, unique_type_id, &sig, usage_site_span)
-        }
-        ty::ty_struct(def_id, substs) => {
-            prepare_struct_metadata(cx,
-                                    t,
-                                    def_id,
-                                    substs,
-                                    unique_type_id,
-                                    usage_site_span).finalize(cx)
-        }
-        ty::ty_tup(ref elements) => {
-            prepare_tuple_metadata(cx,
-                                   t,
-                                   &elements[..],
-                                   unique_type_id,
-                                   usage_site_span).finalize(cx)
-        }
-        _ => {
-            cx.sess().bug(&format!("debuginfo: unexpected type in type_metadata: {:?}",
-                                  sty))
-        }
-    };
-
-    {
-        let mut type_map = debug_context(cx).type_map.borrow_mut();
-
-        if already_stored_in_typemap {
-            // Also make sure that we already have a TypeMap entry entry for the unique type id.
-            let metadata_for_uid = match type_map.find_metadata_for_unique_id(unique_type_id) {
-                Some(metadata) => metadata,
-                None => {
-                    let unique_type_id_str =
-                        type_map.get_unique_type_id_as_string(unique_type_id);
-                    let error_message = format!("Expected type metadata for unique \
-                                                 type id '{}' to already be in \
-                                                 the debuginfo::TypeMap but it \
-                                                 was not. (Ty = {})",
-                                                &unique_type_id_str[..],
-                                                ppaux::ty_to_string(cx.tcx(), t));
-                    cx.sess().span_bug(usage_site_span, &error_message[..]);
-                }
-            };
-
-            match type_map.find_metadata_for_type(t) {
-                Some(metadata) => {
-                    if metadata != metadata_for_uid {
-                        let unique_type_id_str =
-                            type_map.get_unique_type_id_as_string(unique_type_id);
-                        let error_message = format!("Mismatch between Ty and \
-                                                     UniqueTypeId maps in \
-                                                     debuginfo::TypeMap. \
-                                                     UniqueTypeId={}, Ty={}",
-                            &unique_type_id_str[..],
-                            ppaux::ty_to_string(cx.tcx(), t));
-                        cx.sess().span_bug(usage_site_span, &error_message[..]);
-                    }
-                }
-                None => {
-                    type_map.register_type_with_metadata(cx, t, metadata);
-                }
-            }
-        } else {
-            type_map.register_type_with_metadata(cx, t, metadata);
-            type_map.register_unique_id_with_metadata(cx, unique_type_id, metadata);
-        }
-    }
-
-    metadata
-}
-
-struct MetadataCreationResult {
-    metadata: DIType,
-    already_stored_in_typemap: bool
-}
-
-impl MetadataCreationResult {
-    fn new(metadata: DIType, already_stored_in_typemap: bool) -> MetadataCreationResult {
-        MetadataCreationResult {
-            metadata: metadata,
-            already_stored_in_typemap: already_stored_in_typemap
-        }
-    }
-}
-
-#[derive(Copy, Clone, PartialEq)]
-enum InternalDebugLocation {
-    KnownLocation { scope: DIScope, line: usize, col: usize },
-    UnknownLocation
-}
-
-impl InternalDebugLocation {
-    fn new(scope: DIScope, line: usize, col: usize) -> InternalDebugLocation {
-        KnownLocation {
-            scope: scope,
-            line: line,
-            col: col,
-        }
-    }
-}
-
-fn set_debug_location(cx: &CrateContext, debug_location: InternalDebugLocation) {
-    if debug_location == debug_context(cx).current_debug_location.get() {
-        return;
-    }
-
-    let metadata_node;
-
-    match debug_location {
-        KnownLocation { scope, line, .. } => {
-            // Always set the column to zero like Clang and GCC
-            let col = UNKNOWN_COLUMN_NUMBER;
-            debug!("setting debug location to {} {}", line, col);
-
-            unsafe {
-                metadata_node = llvm::LLVMDIBuilderCreateDebugLocation(
-                    debug_context(cx).llcontext,
-                    line as c_uint,
-                    col as c_uint,
-                    scope,
-                    ptr::null_mut());
-            }
-        }
-        UnknownLocation => {
-            debug!("clearing debug location ");
-            metadata_node = ptr::null_mut();
-        }
-    };
-
-    unsafe {
-        llvm::LLVMSetCurrentDebugLocation(cx.raw_builder(), metadata_node);
-    }
-
-    debug_context(cx).current_debug_location.set(debug_location);
-}
-
-//=-----------------------------------------------------------------------------
-//  Utility Functions
-//=-----------------------------------------------------------------------------
-
-fn contains_nodebug_attribute(attributes: &[ast::Attribute]) -> bool {
-    attributes.iter().any(|attr| {
-        let meta_item: &ast::MetaItem = &*attr.node.value;
-        match meta_item.node {
-            ast::MetaWord(ref value) => &value[..] == "no_debug",
-            _ => false
-        }
-    })
-}
-
-/// Return codemap::Loc corresponding to the beginning of the span
-fn span_start(cx: &CrateContext, span: Span) -> codemap::Loc {
-    cx.sess().codemap().lookup_char_pos(span.lo)
-}
-
-fn size_and_align_of(cx: &CrateContext, llvm_type: Type) -> (u64, u64) {
-    (machine::llsize_of_alloc(cx, llvm_type), machine::llalign_of_min(cx, llvm_type) as u64)
-}
-
-fn bytes_to_bits(bytes: u64) -> u64 {
-    bytes * 8
-}
-
-#[inline]
-fn debug_context<'a, 'tcx>(cx: &'a CrateContext<'a, 'tcx>)
-                           -> &'a CrateDebugContext<'tcx> {
-    let debug_context: &'a CrateDebugContext<'tcx> = cx.dbg_cx().as_ref().unwrap();
-    debug_context
-}
-
-#[inline]
-#[allow(non_snake_case)]
-fn DIB(cx: &CrateContext) -> DIBuilderRef {
-    cx.dbg_cx().as_ref().unwrap().builder
-}
-
-fn fn_should_be_ignored(fcx: &FunctionContext) -> bool {
-    match fcx.debug_context {
-        FunctionDebugContext::RegularContext(_) => false,
-        _ => true
-    }
-}
-
-fn assert_type_for_node_id(cx: &CrateContext,
-                           node_id: ast::NodeId,
-                           error_reporting_span: Span) {
-    if !cx.tcx().node_types().contains_key(&node_id) {
-        cx.sess().span_bug(error_reporting_span,
-                           "debuginfo: Could not find type for node id!");
-    }
-}
-
-fn get_namespace_and_span_for_item(cx: &CrateContext, def_id: ast::DefId)
-                                   -> (DIScope, Span) {
-    let containing_scope = namespace_for_item(cx, def_id).scope;
-    let definition_span = if def_id.krate == ast::LOCAL_CRATE {
-        cx.tcx().map.span(def_id.node)
-    } else {
-        // For external items there is no span information
-        codemap::DUMMY_SP
-    };
-
-    (containing_scope, definition_span)
-}
-
-// This procedure builds the *scope map* for a given function, which maps any
-// given ast::NodeId in the function's AST to the correct DIScope metadata instance.
-//
-// This builder procedure walks the AST in execution order and keeps track of
-// what belongs to which scope, creating DIScope DIEs along the way, and
-// introducing *artificial* lexical scope descriptors where necessary. These
-// artificial scopes allow GDB to correctly handle name shadowing.
-fn create_scope_map(cx: &CrateContext,
-                    args: &[ast::Arg],
-                    fn_entry_block: &ast::Block,
-                    fn_metadata: DISubprogram,
-                    fn_ast_id: ast::NodeId)
-                 -> NodeMap<DIScope> {
-    let mut scope_map = NodeMap();
-
-    let def_map = &cx.tcx().def_map;
-
-    struct ScopeStackEntry {
-        scope_metadata: DIScope,
-        name: Option<ast::Name>
-    }
-
-    let mut scope_stack = vec!(ScopeStackEntry { scope_metadata: fn_metadata, name: None });
-    scope_map.insert(fn_ast_id, fn_metadata);
-
-    // Push argument identifiers onto the stack so arguments integrate nicely
-    // with variable shadowing.
-    for arg in args {
-        pat_util::pat_bindings(def_map, &*arg.pat, |_, node_id, _, path1| {
-            scope_stack.push(ScopeStackEntry { scope_metadata: fn_metadata,
-                                               name: Some(path1.node.name) });
-            scope_map.insert(node_id, fn_metadata);
-        })
-    }
-
-    // Clang creates a separate scope for function bodies, so let's do this too.
-    with_new_scope(cx,
-                   fn_entry_block.span,
-                   &mut scope_stack,
-                   &mut scope_map,
-                   |cx, scope_stack, scope_map| {
-        walk_block(cx, fn_entry_block, scope_stack, scope_map);
-    });
-
-    return scope_map;
-
-
-    // local helper functions for walking the AST.
-    fn with_new_scope<F>(cx: &CrateContext,
-                         scope_span: Span,
-                         scope_stack: &mut Vec<ScopeStackEntry> ,
-                         scope_map: &mut NodeMap<DIScope>,
-                         inner_walk: F) where
-        F: FnOnce(&CrateContext, &mut Vec<ScopeStackEntry>, &mut NodeMap<DIScope>),
-    {
-        // Create a new lexical scope and push it onto the stack
-        let loc = cx.sess().codemap().lookup_char_pos(scope_span.lo);
-        let file_metadata = file_metadata(cx, &loc.file.name);
-        let parent_scope = scope_stack.last().unwrap().scope_metadata;
-
-        let scope_metadata = unsafe {
-            llvm::LLVMDIBuilderCreateLexicalBlock(
-                DIB(cx),
-                parent_scope,
-                file_metadata,
-                loc.line as c_uint,
-                loc.col.to_usize() as c_uint)
-        };
-
-        scope_stack.push(ScopeStackEntry { scope_metadata: scope_metadata, name: None });
-
-        inner_walk(cx, scope_stack, scope_map);
-
-        // pop artificial scopes
-        while scope_stack.last().unwrap().name.is_some() {
-            scope_stack.pop();
-        }
-
-        if scope_stack.last().unwrap().scope_metadata != scope_metadata {
-            cx.sess().span_bug(scope_span, "debuginfo: Inconsistency in scope management.");
-        }
-
-        scope_stack.pop();
-    }
-
-    fn walk_block(cx: &CrateContext,
-                  block: &ast::Block,
-                  scope_stack: &mut Vec<ScopeStackEntry> ,
-                  scope_map: &mut NodeMap<DIScope>) {
-        scope_map.insert(block.id, scope_stack.last().unwrap().scope_metadata);
-
-        // The interesting things here are statements and the concluding expression.
-        for statement in &block.stmts {
-            scope_map.insert(ast_util::stmt_id(&**statement),
-                             scope_stack.last().unwrap().scope_metadata);
-
-            match statement.node {
-                ast::StmtDecl(ref decl, _) =>
-                    walk_decl(cx, &**decl, scope_stack, scope_map),
-                ast::StmtExpr(ref exp, _) |
-                ast::StmtSemi(ref exp, _) =>
-                    walk_expr(cx, &**exp, scope_stack, scope_map),
-                ast::StmtMac(..) => () // Ignore macros (which should be expanded anyway).
-            }
-        }
-
-        if let Some(ref exp) = block.expr {
-            walk_expr(cx, &**exp, scope_stack, scope_map);
-        }
-    }
-
-    fn walk_decl(cx: &CrateContext,
-                 decl: &ast::Decl,
-                 scope_stack: &mut Vec<ScopeStackEntry> ,
-                 scope_map: &mut NodeMap<DIScope>) {
-        match *decl {
-            codemap::Spanned { node: ast::DeclLocal(ref local), .. } => {
-                scope_map.insert(local.id, scope_stack.last().unwrap().scope_metadata);
-
-                walk_pattern(cx, &*local.pat, scope_stack, scope_map);
-
-                if let Some(ref exp) = local.init {
-                    walk_expr(cx, &**exp, scope_stack, scope_map);
-                }
-            }
-            _ => ()
-        }
-    }
-
-    fn walk_pattern(cx: &CrateContext,
-                    pat: &ast::Pat,
-                    scope_stack: &mut Vec<ScopeStackEntry> ,
-                    scope_map: &mut NodeMap<DIScope>) {
-
-        let def_map = &cx.tcx().def_map;
-
-        // Unfortunately, we cannot just use pat_util::pat_bindings() or
-        // ast_util::walk_pat() here because we have to visit *all* nodes in
-        // order to put them into the scope map. The above functions don't do that.
-        match pat.node {
-            ast::PatIdent(_, ref path1, ref sub_pat_opt) => {
-
-                // Check if this is a binding. If so we need to put it on the
-                // scope stack and maybe introduce an artificial scope
-                if pat_util::pat_is_binding(def_map, &*pat) {
-
-                    let name = path1.node.name;
-
-                    // LLVM does not properly generate 'DW_AT_start_scope' fields
-                    // for variable DIEs. For this reason we have to introduce
-                    // an artificial scope at bindings whenever a variable with
-                    // the same name is declared in *any* parent scope.
-                    //
-                    // Otherwise the following error occurs:
-                    //
-                    // let x = 10;
-                    //
-                    // do_something(); // 'gdb print x' correctly prints 10
-                    //
-                    // {
-                    //     do_something(); // 'gdb print x' prints 0, because it
-                    //                     // already reads the uninitialized 'x'
-                    //                     // from the next line...
-                    //     let x = 100;
-                    //     do_something(); // 'gdb print x' correctly prints 100
-                    // }
-
-                    // Is there already a binding with that name?
-                    // N.B.: this comparison must be UNhygienic... because
-                    // gdb knows nothing about the context, so any two
-                    // variables with the same name will cause the problem.
-                    let need_new_scope = scope_stack
-                        .iter()
-                        .any(|entry| entry.name == Some(name));
-
-                    if need_new_scope {
-                        // Create a new lexical scope and push it onto the stack
-                        let loc = cx.sess().codemap().lookup_char_pos(pat.span.lo);
-                        let file_metadata = file_metadata(cx, &loc.file.name);
-                        let parent_scope = scope_stack.last().unwrap().scope_metadata;
-
-                        let scope_metadata = unsafe {
-                            llvm::LLVMDIBuilderCreateLexicalBlock(
-                                DIB(cx),
-                                parent_scope,
-                                file_metadata,
-                                loc.line as c_uint,
-                                loc.col.to_usize() as c_uint)
-                        };
-
-                        scope_stack.push(ScopeStackEntry {
-                            scope_metadata: scope_metadata,
-                            name: Some(name)
-                        });
-
-                    } else {
-                        // Push a new entry anyway so the name can be found
-                        let prev_metadata = scope_stack.last().unwrap().scope_metadata;
-                        scope_stack.push(ScopeStackEntry {
-                            scope_metadata: prev_metadata,
-                            name: Some(name)
-                        });
-                    }
-                }
-
-                scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
-
-                if let Some(ref sub_pat) = *sub_pat_opt {
-                    walk_pattern(cx, &**sub_pat, scope_stack, scope_map);
-                }
-            }
-
-            ast::PatWild(_) => {
-                scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
-            }
-
-            ast::PatEnum(_, ref sub_pats_opt) => {
-                scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
-
-                if let Some(ref sub_pats) = *sub_pats_opt {
-                    for p in sub_pats {
-                        walk_pattern(cx, &**p, scope_stack, scope_map);
-                    }
-                }
-            }
-
-            ast::PatQPath(..) => {
-                scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
-            }
-
-            ast::PatStruct(_, ref field_pats, _) => {
-                scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
-
-                for &codemap::Spanned {
-                    node: ast::FieldPat { pat: ref sub_pat, .. },
-                    ..
-                } in field_pats.iter() {
-                    walk_pattern(cx, &**sub_pat, scope_stack, scope_map);
-                }
-            }
-
-            ast::PatTup(ref sub_pats) => {
-                scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
-
-                for sub_pat in sub_pats {
-                    walk_pattern(cx, &**sub_pat, scope_stack, scope_map);
-                }
-            }
-
-            ast::PatBox(ref sub_pat) | ast::PatRegion(ref sub_pat, _) => {
-                scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
-                walk_pattern(cx, &**sub_pat, scope_stack, scope_map);
-            }
-
-            ast::PatLit(ref exp) => {
-                scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
-                walk_expr(cx, &**exp, scope_stack, scope_map);
-            }
-
-            ast::PatRange(ref exp1, ref exp2) => {
-                scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
-                walk_expr(cx, &**exp1, scope_stack, scope_map);
-                walk_expr(cx, &**exp2, scope_stack, scope_map);
-            }
-
-            ast::PatVec(ref front_sub_pats, ref middle_sub_pats, ref back_sub_pats) => {
-                scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
-
-                for sub_pat in front_sub_pats {
-                    walk_pattern(cx, &**sub_pat, scope_stack, scope_map);
-                }
-
-                if let Some(ref sub_pat) = *middle_sub_pats {
-                    walk_pattern(cx, &**sub_pat, scope_stack, scope_map);
-                }
-
-                for sub_pat in back_sub_pats {
-                    walk_pattern(cx, &**sub_pat, scope_stack, scope_map);
-                }
-            }
-
-            ast::PatMac(_) => {
-                cx.sess().span_bug(pat.span, "debuginfo::create_scope_map() - \
-                                              Found unexpanded macro.");
-            }
-        }
-    }
-
-    fn walk_expr(cx: &CrateContext,
-                 exp: &ast::Expr,
-                 scope_stack: &mut Vec<ScopeStackEntry> ,
-                 scope_map: &mut NodeMap<DIScope>) {
-
-        scope_map.insert(exp.id, scope_stack.last().unwrap().scope_metadata);
-
-        match exp.node {
-            ast::ExprLit(_)   |
-            ast::ExprBreak(_) |
-            ast::ExprAgain(_) |
-            ast::ExprPath(..) => {}
-
-            ast::ExprCast(ref sub_exp, _)     |
-            ast::ExprAddrOf(_, ref sub_exp)  |
-            ast::ExprField(ref sub_exp, _) |
-            ast::ExprTupField(ref sub_exp, _) |
-            ast::ExprParen(ref sub_exp) =>
-                walk_expr(cx, &**sub_exp, scope_stack, scope_map),
-
-            ast::ExprBox(ref place, ref sub_expr) => {
-                place.as_ref().map(
-                    |e| walk_expr(cx, &**e, scope_stack, scope_map));
-                walk_expr(cx, &**sub_expr, scope_stack, scope_map);
-            }
-
-            ast::ExprRet(ref exp_opt) => match *exp_opt {
-                Some(ref sub_exp) => walk_expr(cx, &**sub_exp, scope_stack, scope_map),
-                None => ()
-            },
-
-            ast::ExprUnary(_, ref sub_exp) => {
-                walk_expr(cx, &**sub_exp, scope_stack, scope_map);
-            }
-
-            ast::ExprAssignOp(_, ref lhs, ref rhs) |
-            ast::ExprIndex(ref lhs, ref rhs) |
-            ast::ExprBinary(_, ref lhs, ref rhs)    => {
-                walk_expr(cx, &**lhs, scope_stack, scope_map);
-                walk_expr(cx, &**rhs, scope_stack, scope_map);
-            }
-
-            ast::ExprRange(ref start, ref end) => {
-                start.as_ref().map(|e| walk_expr(cx, &**e, scope_stack, scope_map));
-                end.as_ref().map(|e| walk_expr(cx, &**e, scope_stack, scope_map));
-            }
-
-            ast::ExprVec(ref init_expressions) |
-            ast::ExprTup(ref init_expressions) => {
-                for ie in init_expressions {
-                    walk_expr(cx, &**ie, scope_stack, scope_map);
-                }
-            }
-
-            ast::ExprAssign(ref sub_exp1, ref sub_exp2) |
-            ast::ExprRepeat(ref sub_exp1, ref sub_exp2) => {
-                walk_expr(cx, &**sub_exp1, scope_stack, scope_map);
-                walk_expr(cx, &**sub_exp2, scope_stack, scope_map);
-            }
-
-            ast::ExprIf(ref cond_exp, ref then_block, ref opt_else_exp) => {
-                walk_expr(cx, &**cond_exp, scope_stack, scope_map);
-
-                with_new_scope(cx,
-                               then_block.span,
-                               scope_stack,
-                               scope_map,
-                               |cx, scope_stack, scope_map| {
-                    walk_block(cx, &**then_block, scope_stack, scope_map);
-                });
-
-                match *opt_else_exp {
-                    Some(ref else_exp) =>
-                        walk_expr(cx, &**else_exp, scope_stack, scope_map),
-                    _ => ()
-                }
-            }
-
-            ast::ExprIfLet(..) => {
-                cx.sess().span_bug(exp.span, "debuginfo::create_scope_map() - \
-                                              Found unexpanded if-let.");
-            }
-
-            ast::ExprWhile(ref cond_exp, ref loop_body, _) => {
-                walk_expr(cx, &**cond_exp, scope_stack, scope_map);
-
-                with_new_scope(cx,
-                               loop_body.span,
-                               scope_stack,
-                               scope_map,
-                               |cx, scope_stack, scope_map| {
-                    walk_block(cx, &**loop_body, scope_stack, scope_map);
-                })
-            }
-
-            ast::ExprWhileLet(..) => {
-                cx.sess().span_bug(exp.span, "debuginfo::create_scope_map() - \
-                                              Found unexpanded while-let.");
-            }
-
-            ast::ExprForLoop(..) => {
-                cx.sess().span_bug(exp.span, "debuginfo::create_scope_map() - \
-                                              Found unexpanded for loop.");
-            }
-
-            ast::ExprMac(_) => {
-                cx.sess().span_bug(exp.span, "debuginfo::create_scope_map() - \
-                                              Found unexpanded macro.");
-            }
-
-            ast::ExprLoop(ref block, _) |
-            ast::ExprBlock(ref block)   => {
-                with_new_scope(cx,
-                               block.span,
-                               scope_stack,
-                               scope_map,
-                               |cx, scope_stack, scope_map| {
-                    walk_block(cx, &**block, scope_stack, scope_map);
-                })
-            }
-
-            ast::ExprClosure(_, ref decl, ref block) => {
-                with_new_scope(cx,
-                               block.span,
-                               scope_stack,
-                               scope_map,
-                               |cx, scope_stack, scope_map| {
-                    for &ast::Arg { pat: ref pattern, .. } in &decl.inputs {
-                        walk_pattern(cx, &**pattern, scope_stack, scope_map);
-                    }
-
-                    walk_block(cx, &**block, scope_stack, scope_map);
-                })
-            }
-
-            ast::ExprCall(ref fn_exp, ref args) => {
-                walk_expr(cx, &**fn_exp, scope_stack, scope_map);
-
-                for arg_exp in args {
-                    walk_expr(cx, &**arg_exp, scope_stack, scope_map);
-                }
-            }
-
-            ast::ExprMethodCall(_, _, ref args) => {
-                for arg_exp in args {
-                    walk_expr(cx, &**arg_exp, scope_stack, scope_map);
-                }
-            }
-
-            ast::ExprMatch(ref discriminant_exp, ref arms, _) => {
-                walk_expr(cx, &**discriminant_exp, scope_stack, scope_map);
-
-                // For each arm we have to first walk the pattern as these might
-                // introduce new artificial scopes. It should be sufficient to
-                // walk only one pattern per arm, as they all must contain the
-                // same binding names.
-
-                for arm_ref in arms {
-                    let arm_span = arm_ref.pats[0].span;
-
-                    with_new_scope(cx,
-                                   arm_span,
-                                   scope_stack,
-                                   scope_map,
-                                   |cx, scope_stack, scope_map| {
-                        for pat in &arm_ref.pats {
-                            walk_pattern(cx, &**pat, scope_stack, scope_map);
-                        }
-
-                        if let Some(ref guard_exp) = arm_ref.guard {
-                            walk_expr(cx, &**guard_exp, scope_stack, scope_map)
-                        }
-
-                        walk_expr(cx, &*arm_ref.body, scope_stack, scope_map);
-                    })
-                }
-            }
-
-            ast::ExprStruct(_, ref fields, ref base_exp) => {
-                for &ast::Field { expr: ref exp, .. } in fields {
-                    walk_expr(cx, &**exp, scope_stack, scope_map);
-                }
-
-                match *base_exp {
-                    Some(ref exp) => walk_expr(cx, &**exp, scope_stack, scope_map),
-                    None => ()
-                }
-            }
-
-            ast::ExprInlineAsm(ast::InlineAsm { ref inputs,
-                                                ref outputs,
-                                                .. }) => {
-                // inputs, outputs: Vec<(String, P<Expr>)>
-                for &(_, ref exp) in inputs {
-                    walk_expr(cx, &**exp, scope_stack, scope_map);
-                }
-
-                for &(_, ref exp, _) in outputs {
-                    walk_expr(cx, &**exp, scope_stack, scope_map);
-                }
-            }
-        }
-    }
-}
-
-
-//=-----------------------------------------------------------------------------
-// Type Names for Debug Info
-//=-----------------------------------------------------------------------------
-
-// Compute the name of the type as it should be stored in debuginfo. Does not do
-// any caching, i.e. calling the function twice with the same type will also do
-// the work twice. The `qualified` parameter only affects the first level of the
-// type name, further levels (i.e. type parameters) are always fully qualified.
-fn compute_debuginfo_type_name<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
-                                         t: Ty<'tcx>,
-                                         qualified: bool)
-                                         -> String {
-    let mut result = String::with_capacity(64);
-    push_debuginfo_type_name(cx, t, qualified, &mut result);
-    result
-}
-
-// Pushes the name of the type as it should be stored in debuginfo on the
-// `output` String. See also compute_debuginfo_type_name().
-fn push_debuginfo_type_name<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
-                                      t: Ty<'tcx>,
-                                      qualified: bool,
-                                      output: &mut String) {
-    match t.sty {
-        ty::ty_bool              => output.push_str("bool"),
-        ty::ty_char              => output.push_str("char"),
-        ty::ty_str               => output.push_str("str"),
-        ty::ty_int(ast::TyIs)     => output.push_str("isize"),
-        ty::ty_int(ast::TyI8)    => output.push_str("i8"),
-        ty::ty_int(ast::TyI16)   => output.push_str("i16"),
-        ty::ty_int(ast::TyI32)   => output.push_str("i32"),
-        ty::ty_int(ast::TyI64)   => output.push_str("i64"),
-        ty::ty_uint(ast::TyUs)    => output.push_str("usize"),
-        ty::ty_uint(ast::TyU8)   => output.push_str("u8"),
-        ty::ty_uint(ast::TyU16)  => output.push_str("u16"),
-        ty::ty_uint(ast::TyU32)  => output.push_str("u32"),
-        ty::ty_uint(ast::TyU64)  => output.push_str("u64"),
-        ty::ty_float(ast::TyF32) => output.push_str("f32"),
-        ty::ty_float(ast::TyF64) => output.push_str("f64"),
-        ty::ty_struct(def_id, substs) |
-        ty::ty_enum(def_id, substs) => {
-            push_item_name(cx, def_id, qualified, output);
-            push_type_params(cx, substs, output);
-        },
-        ty::ty_tup(ref component_types) => {
-            output.push('(');
-            for &component_type in component_types {
-                push_debuginfo_type_name(cx, component_type, true, output);
-                output.push_str(", ");
-            }
-            if !component_types.is_empty() {
-                output.pop();
-                output.pop();
-            }
-            output.push(')');
-        },
-        ty::ty_uniq(inner_type) => {
-            output.push_str("Box<");
-            push_debuginfo_type_name(cx, inner_type, true, output);
-            output.push('>');
-        },
-        ty::ty_ptr(ty::mt { ty: inner_type, mutbl } ) => {
-            output.push('*');
-            match mutbl {
-                ast::MutImmutable => output.push_str("const "),
-                ast::MutMutable => output.push_str("mut "),
-            }
-
-            push_debuginfo_type_name(cx, inner_type, true, output);
-        },
-        ty::ty_rptr(_, ty::mt { ty: inner_type, mutbl }) => {
-            output.push('&');
-            if mutbl == ast::MutMutable {
-                output.push_str("mut ");
-            }
-
-            push_debuginfo_type_name(cx, inner_type, true, output);
-        },
-        ty::ty_vec(inner_type, optional_length) => {
-            output.push('[');
-            push_debuginfo_type_name(cx, inner_type, true, output);
-
-            match optional_length {
-                Some(len) => {
-                    output.push_str(&format!("; {}", len));
-                }
-                None => { /* nothing to do */ }
-            };
-
-            output.push(']');
-        },
-        ty::ty_trait(ref trait_data) => {
-            let principal = ty::erase_late_bound_regions(cx.tcx(), &trait_data.principal);
-            push_item_name(cx, principal.def_id, false, output);
-            push_type_params(cx, principal.substs, output);
-        },
-        ty::ty_bare_fn(_, &ty::BareFnTy{ unsafety, abi, ref sig } ) => {
-            if unsafety == ast::Unsafety::Unsafe {
-                output.push_str("unsafe ");
-            }
-
-            if abi != ::syntax::abi::Rust {
-                output.push_str("extern \"");
-                output.push_str(abi.name());
-                output.push_str("\" ");
-            }
-
-            output.push_str("fn(");
-
-            let sig = ty::erase_late_bound_regions(cx.tcx(), sig);
-            if !sig.inputs.is_empty() {
-                for &parameter_type in &sig.inputs {
-                    push_debuginfo_type_name(cx, parameter_type, true, output);
-                    output.push_str(", ");
-                }
-                output.pop();
-                output.pop();
-            }
-
-            if sig.variadic {
-                if !sig.inputs.is_empty() {
-                    output.push_str(", ...");
-                } else {
-                    output.push_str("...");
-                }
-            }
-
-            output.push(')');
-
-            match sig.output {
-                ty::FnConverging(result_type) if ty::type_is_nil(result_type) => {}
-                ty::FnConverging(result_type) => {
-                    output.push_str(" -> ");
-                    push_debuginfo_type_name(cx, result_type, true, output);
-                }
-                ty::FnDiverging => {
-                    output.push_str(" -> !");
-                }
-            }
-        },
-        ty::ty_closure(..) => {
-            output.push_str("closure");
-        }
-        ty::ty_err |
-        ty::ty_infer(_) |
-        ty::ty_projection(..) |
-        ty::ty_param(_) => {
-            cx.sess().bug(&format!("debuginfo: Trying to create type name for \
-                unexpected type: {}", ppaux::ty_to_string(cx.tcx(), t)));
-        }
-    }
-
-    fn push_item_name(cx: &CrateContext,
-                      def_id: ast::DefId,
-                      qualified: bool,
-                      output: &mut String) {
-        ty::with_path(cx.tcx(), def_id, |path| {
-            if qualified {
-                if def_id.krate == ast::LOCAL_CRATE {
-                    output.push_str(crate_root_namespace(cx));
-                    output.push_str("::");
-                }
-
-                let mut path_element_count = 0;
-                for path_element in path {
-                    let name = token::get_name(path_element.name());
-                    output.push_str(&name);
-                    output.push_str("::");
-                    path_element_count += 1;
-                }
-
-                if path_element_count == 0 {
-                    cx.sess().bug("debuginfo: Encountered empty item path!");
-                }
-
-                output.pop();
-                output.pop();
-            } else {
-                let name = token::get_name(path.last()
-                                               .expect("debuginfo: Empty item path?")
-                                               .name());
-                output.push_str(&name);
-            }
-        });
-    }
-
-    // Pushes the type parameters in the given `Substs` to the output string.
-    // This ignores region parameters, since they can't reliably be
-    // reconstructed for items from non-local crates. For local crates, this
-    // would be possible but with inlining and LTO we have to use the least
-    // common denominator - otherwise we would run into conflicts.
-    fn push_type_params<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
-                                  substs: &subst::Substs<'tcx>,
-                                  output: &mut String) {
-        if substs.types.is_empty() {
-            return;
-        }
-
-        output.push('<');
-
-        for &type_parameter in substs.types.iter() {
-            push_debuginfo_type_name(cx, type_parameter, true, output);
-            output.push_str(", ");
-        }
-
-        output.pop();
-        output.pop();
-
-        output.push('>');
-    }
-}
-
-
-//=-----------------------------------------------------------------------------
-// Namespace Handling
-//=-----------------------------------------------------------------------------
-
-struct NamespaceTreeNode {
-    name: ast::Name,
-    scope: DIScope,
-    parent: Option<Weak<NamespaceTreeNode>>,
-}
-
-impl NamespaceTreeNode {
-    fn mangled_name_of_contained_item(&self, item_name: &str) -> String {
-        fn fill_nested(node: &NamespaceTreeNode, output: &mut String) {
-            match node.parent {
-                Some(ref parent) => fill_nested(&*parent.upgrade().unwrap(), output),
-                None => {}
-            }
-            let string = token::get_name(node.name);
-            output.push_str(&format!("{}", string.len()));
-            output.push_str(&string);
-        }
-
-        let mut name = String::from_str("_ZN");
-        fill_nested(self, &mut name);
-        name.push_str(&format!("{}", item_name.len()));
-        name.push_str(item_name);
-        name.push('E');
-        name
-    }
-}
-
-fn crate_root_namespace<'a>(cx: &'a CrateContext) -> &'a str {
-    &cx.link_meta().crate_name
-}
-
-fn namespace_for_item(cx: &CrateContext, def_id: ast::DefId) -> Rc<NamespaceTreeNode> {
-    ty::with_path(cx.tcx(), def_id, |path| {
-        // prepend crate name if not already present
-        let krate = if def_id.krate == ast::LOCAL_CRATE {
-            let crate_namespace_name = token::intern(crate_root_namespace(cx));
-            Some(ast_map::PathMod(crate_namespace_name))
-        } else {
-            None
-        };
-        let mut path = krate.into_iter().chain(path).peekable();
-
-        let mut current_key = Vec::new();
-        let mut parent_node: Option<Rc<NamespaceTreeNode>> = None;
-
-        // Create/Lookup namespace for each element of the path.
-        loop {
-            // Emulate a for loop so we can use peek below.
-            let path_element = match path.next() {
-                Some(e) => e,
-                None => break
-            };
-            // Ignore the name of the item (the last path element).
-            if path.peek().is_none() {
-                break;
-            }
-
-            let name = path_element.name();
-            current_key.push(name);
-
-            let existing_node = debug_context(cx).namespace_map.borrow()
-                                                 .get(&current_key).cloned();
-            let current_node = match existing_node {
-                Some(existing_node) => existing_node,
-                None => {
-                    // create and insert
-                    let parent_scope = match parent_node {
-                        Some(ref node) => node.scope,
-                        None => ptr::null_mut()
-                    };
-                    let namespace_name = token::get_name(name);
-                    let namespace_name = CString::new(namespace_name.as_bytes()).unwrap();
-                    let scope = unsafe {
-                        llvm::LLVMDIBuilderCreateNameSpace(
-                            DIB(cx),
-                            parent_scope,
-                            namespace_name.as_ptr(),
-                            // cannot reconstruct file ...
-                            ptr::null_mut(),
-                            // ... or line information, but that's not so important.
-                            0)
-                    };
-
-                    let node = Rc::new(NamespaceTreeNode {
-                        name: name,
-                        scope: scope,
-                        parent: parent_node.map(|parent| parent.downgrade()),
-                    });
-
-                    debug_context(cx).namespace_map.borrow_mut()
-                                     .insert(current_key.clone(), node.clone());
-
-                    node
-                }
-            };
-
-            parent_node = Some(current_node);
-        }
-
-        match parent_node {
-            Some(node) => node,
-            None => {
-                cx.sess().bug(&format!("debuginfo::namespace_for_item(): \
-                                       path too short for {:?}",
-                                      def_id));
-            }
-        }
-    })
-}
-
-
-//=-----------------------------------------------------------------------------
-// .debug_gdb_scripts binary section
-//=-----------------------------------------------------------------------------
-
-/// Inserts a side-effect free instruction sequence that makes sure that the
-/// .debug_gdb_scripts global is referenced, so it isn't removed by the linker.
-pub fn insert_reference_to_gdb_debug_scripts_section_global(ccx: &CrateContext) {
-    if needs_gdb_debug_scripts_section(ccx) {
-        let empty = CString::new("").unwrap();
-        let gdb_debug_scripts_section_global =
-            get_or_insert_gdb_debug_scripts_section_global(ccx);
-        unsafe {
-            let volative_load_instruction =
-                llvm::LLVMBuildLoad(ccx.raw_builder(),
-                                    gdb_debug_scripts_section_global,
-                                    empty.as_ptr());
-            llvm::LLVMSetVolatile(volative_load_instruction, llvm::True);
-        }
-    }
-}
-
-/// Allocates the global variable responsible for the .debug_gdb_scripts binary
-/// section.
-fn get_or_insert_gdb_debug_scripts_section_global(ccx: &CrateContext)
-                                                  -> llvm::ValueRef {
-    let section_var_name = "__rustc_debug_gdb_scripts_section__";
-
-    let section_var = unsafe {
-        llvm::LLVMGetNamedGlobal(ccx.llmod(),
-                                 section_var_name.as_ptr() as *const _)
-    };
-
-    if section_var == ptr::null_mut() {
-        let section_name = b".debug_gdb_scripts\0";
-        let section_contents = b"\x01gdb_load_rust_pretty_printers.py\0";
-
-        unsafe {
-            let llvm_type = Type::array(&Type::i8(ccx),
-                                        section_contents.len() as u64);
-
-            let section_var = declare::define_global(ccx, section_var_name,
-                                                     llvm_type).unwrap_or_else(||{
-                ccx.sess().bug(&format!("symbol `{}` is already defined", section_var_name))
-            });
-            llvm::LLVMSetSection(section_var, section_name.as_ptr() as *const _);
-            llvm::LLVMSetInitializer(section_var, C_bytes(ccx, section_contents));
-            llvm::LLVMSetGlobalConstant(section_var, llvm::True);
-            llvm::LLVMSetUnnamedAddr(section_var, llvm::True);
-            llvm::SetLinkage(section_var, llvm::Linkage::LinkOnceODRLinkage);
-            // This should make sure that the whole section is not larger than
-            // the string it contains. Otherwise we get a warning from GDB.
-            llvm::LLVMSetAlignment(section_var, 1);
-            section_var
-        }
-    } else {
-        section_var
-    }
-}
-
-fn needs_gdb_debug_scripts_section(ccx: &CrateContext) -> bool {
-    let omit_gdb_pretty_printer_section =
-        attr::contains_name(&ccx.tcx()
-                                .map
-                                .krate()
-                                .attrs,
-                            "omit_gdb_pretty_printer_section");
-
-    !omit_gdb_pretty_printer_section &&
-    !ccx.sess().target.target.options.is_like_osx &&
-    !ccx.sess().target.target.options.is_like_windows &&
-    ccx.sess().opts.debuginfo != NoDebugInfo
-}
diff --git a/src/librustc_trans/trans/debuginfo/create_scope_map.rs b/src/librustc_trans/trans/debuginfo/create_scope_map.rs
new file mode 100644 (file)
index 0000000..9af22b7
--- /dev/null
@@ -0,0 +1,514 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use super::metadata::file_metadata;
+use super::utils::DIB;
+
+use llvm;
+use llvm::debuginfo::{DIScope, DISubprogram};
+use trans::common::CrateContext;
+use middle::pat_util;
+use util::nodemap::NodeMap;
+
+use libc::c_uint;
+use syntax::codemap::{Span, Pos};
+use syntax::{ast, codemap, ast_util};
+
+// This procedure builds the *scope map* for a given function, which maps any
+// given ast::NodeId in the function's AST to the correct DIScope metadata instance.
+//
+// This builder procedure walks the AST in execution order and keeps track of
+// what belongs to which scope, creating DIScope DIEs along the way, and
+// introducing *artificial* lexical scope descriptors where necessary. These
+// artificial scopes allow GDB to correctly handle name shadowing.
+pub fn create_scope_map(cx: &CrateContext,
+                        args: &[ast::Arg],
+                        fn_entry_block: &ast::Block,
+                        fn_metadata: DISubprogram,
+                        fn_ast_id: ast::NodeId)
+                        -> NodeMap<DIScope> {
+    let mut scope_map = NodeMap();
+
+    let def_map = &cx.tcx().def_map;
+
+    let mut scope_stack = vec!(ScopeStackEntry { scope_metadata: fn_metadata, name: None });
+    scope_map.insert(fn_ast_id, fn_metadata);
+
+    // Push argument identifiers onto the stack so arguments integrate nicely
+    // with variable shadowing.
+    for arg in args {
+        pat_util::pat_bindings(def_map, &*arg.pat, |_, node_id, _, path1| {
+            scope_stack.push(ScopeStackEntry { scope_metadata: fn_metadata,
+                                               name: Some(path1.node.name) });
+            scope_map.insert(node_id, fn_metadata);
+        })
+    }
+
+    // Clang creates a separate scope for function bodies, so let's do this too.
+    with_new_scope(cx,
+                   fn_entry_block.span,
+                   &mut scope_stack,
+                   &mut scope_map,
+                   |cx, scope_stack, scope_map| {
+        walk_block(cx, fn_entry_block, scope_stack, scope_map);
+    });
+
+    return scope_map;
+}
+
+// local helper functions for walking the AST.
+fn with_new_scope<F>(cx: &CrateContext,
+                     scope_span: Span,
+                     scope_stack: &mut Vec<ScopeStackEntry> ,
+                     scope_map: &mut NodeMap<DIScope>,
+                     inner_walk: F) where
+    F: FnOnce(&CrateContext, &mut Vec<ScopeStackEntry>, &mut NodeMap<DIScope>),
+{
+    // Create a new lexical scope and push it onto the stack
+    let loc = cx.sess().codemap().lookup_char_pos(scope_span.lo);
+    let file_metadata = file_metadata(cx, &loc.file.name);
+    let parent_scope = scope_stack.last().unwrap().scope_metadata;
+
+    let scope_metadata = unsafe {
+        llvm::LLVMDIBuilderCreateLexicalBlock(
+            DIB(cx),
+            parent_scope,
+            file_metadata,
+            loc.line as c_uint,
+            loc.col.to_usize() as c_uint)
+    };
+
+    scope_stack.push(ScopeStackEntry { scope_metadata: scope_metadata, name: None });
+
+    inner_walk(cx, scope_stack, scope_map);
+
+    // pop artificial scopes
+    while scope_stack.last().unwrap().name.is_some() {
+        scope_stack.pop();
+    }
+
+    if scope_stack.last().unwrap().scope_metadata != scope_metadata {
+        cx.sess().span_bug(scope_span, "debuginfo: Inconsistency in scope management.");
+    }
+
+    scope_stack.pop();
+}
+
+struct ScopeStackEntry {
+    scope_metadata: DIScope,
+    name: Option<ast::Name>
+}
+
+fn walk_block(cx: &CrateContext,
+              block: &ast::Block,
+              scope_stack: &mut Vec<ScopeStackEntry> ,
+              scope_map: &mut NodeMap<DIScope>) {
+    scope_map.insert(block.id, scope_stack.last().unwrap().scope_metadata);
+
+    // The interesting things here are statements and the concluding expression.
+    for statement in &block.stmts {
+        scope_map.insert(ast_util::stmt_id(&**statement),
+                         scope_stack.last().unwrap().scope_metadata);
+
+        match statement.node {
+            ast::StmtDecl(ref decl, _) =>
+                walk_decl(cx, &**decl, scope_stack, scope_map),
+            ast::StmtExpr(ref exp, _) |
+            ast::StmtSemi(ref exp, _) =>
+                walk_expr(cx, &**exp, scope_stack, scope_map),
+            ast::StmtMac(..) => () // Ignore macros (which should be expanded anyway).
+        }
+    }
+
+    if let Some(ref exp) = block.expr {
+        walk_expr(cx, &**exp, scope_stack, scope_map);
+    }
+}
+
+fn walk_decl(cx: &CrateContext,
+             decl: &ast::Decl,
+             scope_stack: &mut Vec<ScopeStackEntry> ,
+             scope_map: &mut NodeMap<DIScope>) {
+    match *decl {
+        codemap::Spanned { node: ast::DeclLocal(ref local), .. } => {
+            scope_map.insert(local.id, scope_stack.last().unwrap().scope_metadata);
+
+            walk_pattern(cx, &*local.pat, scope_stack, scope_map);
+
+            if let Some(ref exp) = local.init {
+                walk_expr(cx, &**exp, scope_stack, scope_map);
+            }
+        }
+        _ => ()
+    }
+}
+
+fn walk_pattern(cx: &CrateContext,
+                pat: &ast::Pat,
+                scope_stack: &mut Vec<ScopeStackEntry> ,
+                scope_map: &mut NodeMap<DIScope>) {
+
+    let def_map = &cx.tcx().def_map;
+
+    // Unfortunately, we cannot just use pat_util::pat_bindings() or
+    // ast_util::walk_pat() here because we have to visit *all* nodes in
+    // order to put them into the scope map. The above functions don't do that.
+    match pat.node {
+        ast::PatIdent(_, ref path1, ref sub_pat_opt) => {
+
+            // Check if this is a binding. If so we need to put it on the
+            // scope stack and maybe introduce an artificial scope
+            if pat_util::pat_is_binding(def_map, &*pat) {
+
+                let name = path1.node.name;
+
+                // LLVM does not properly generate 'DW_AT_start_scope' fields
+                // for variable DIEs. For this reason we have to introduce
+                // an artificial scope at bindings whenever a variable with
+                // the same name is declared in *any* parent scope.
+                //
+                // Otherwise the following error occurs:
+                //
+                // let x = 10;
+                //
+                // do_something(); // 'gdb print x' correctly prints 10
+                //
+                // {
+                //     do_something(); // 'gdb print x' prints 0, because it
+                //                     // already reads the uninitialized 'x'
+                //                     // from the next line...
+                //     let x = 100;
+                //     do_something(); // 'gdb print x' correctly prints 100
+                // }
+
+                // Is there already a binding with that name?
+                // N.B.: this comparison must be UNhygienic... because
+                // gdb knows nothing about the context, so any two
+                // variables with the same name will cause the problem.
+                let need_new_scope = scope_stack
+                    .iter()
+                    .any(|entry| entry.name == Some(name));
+
+                if need_new_scope {
+                    // Create a new lexical scope and push it onto the stack
+                    let loc = cx.sess().codemap().lookup_char_pos(pat.span.lo);
+                    let file_metadata = file_metadata(cx, &loc.file.name);
+                    let parent_scope = scope_stack.last().unwrap().scope_metadata;
+
+                    let scope_metadata = unsafe {
+                        llvm::LLVMDIBuilderCreateLexicalBlock(
+                            DIB(cx),
+                            parent_scope,
+                            file_metadata,
+                            loc.line as c_uint,
+                            loc.col.to_usize() as c_uint)
+                    };
+
+                    scope_stack.push(ScopeStackEntry {
+                        scope_metadata: scope_metadata,
+                        name: Some(name)
+                    });
+
+                } else {
+                    // Push a new entry anyway so the name can be found
+                    let prev_metadata = scope_stack.last().unwrap().scope_metadata;
+                    scope_stack.push(ScopeStackEntry {
+                        scope_metadata: prev_metadata,
+                        name: Some(name)
+                    });
+                }
+            }
+
+            scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
+
+            if let Some(ref sub_pat) = *sub_pat_opt {
+                walk_pattern(cx, &**sub_pat, scope_stack, scope_map);
+            }
+        }
+
+        ast::PatWild(_) => {
+            scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
+        }
+
+        ast::PatEnum(_, ref sub_pats_opt) => {
+            scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
+
+            if let Some(ref sub_pats) = *sub_pats_opt {
+                for p in sub_pats {
+                    walk_pattern(cx, &**p, scope_stack, scope_map);
+                }
+            }
+        }
+
+        ast::PatQPath(..) => {
+            scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
+        }
+
+        ast::PatStruct(_, ref field_pats, _) => {
+            scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
+
+            for &codemap::Spanned {
+                node: ast::FieldPat { pat: ref sub_pat, .. },
+                ..
+            } in field_pats.iter() {
+                walk_pattern(cx, &**sub_pat, scope_stack, scope_map);
+            }
+        }
+
+        ast::PatTup(ref sub_pats) => {
+            scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
+
+            for sub_pat in sub_pats {
+                walk_pattern(cx, &**sub_pat, scope_stack, scope_map);
+            }
+        }
+
+        ast::PatBox(ref sub_pat) | ast::PatRegion(ref sub_pat, _) => {
+            scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
+            walk_pattern(cx, &**sub_pat, scope_stack, scope_map);
+        }
+
+        ast::PatLit(ref exp) => {
+            scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
+            walk_expr(cx, &**exp, scope_stack, scope_map);
+        }
+
+        ast::PatRange(ref exp1, ref exp2) => {
+            scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
+            walk_expr(cx, &**exp1, scope_stack, scope_map);
+            walk_expr(cx, &**exp2, scope_stack, scope_map);
+        }
+
+        ast::PatVec(ref front_sub_pats, ref middle_sub_pats, ref back_sub_pats) => {
+            scope_map.insert(pat.id, scope_stack.last().unwrap().scope_metadata);
+
+            for sub_pat in front_sub_pats {
+                walk_pattern(cx, &**sub_pat, scope_stack, scope_map);
+            }
+
+            if let Some(ref sub_pat) = *middle_sub_pats {
+                walk_pattern(cx, &**sub_pat, scope_stack, scope_map);
+            }
+
+            for sub_pat in back_sub_pats {
+                walk_pattern(cx, &**sub_pat, scope_stack, scope_map);
+            }
+        }
+
+        ast::PatMac(_) => {
+            cx.sess().span_bug(pat.span, "debuginfo::create_scope_map() - \
+                                          Found unexpanded macro.");
+        }
+    }
+}
+
+fn walk_expr(cx: &CrateContext,
+             exp: &ast::Expr,
+             scope_stack: &mut Vec<ScopeStackEntry> ,
+             scope_map: &mut NodeMap<DIScope>) {
+
+    scope_map.insert(exp.id, scope_stack.last().unwrap().scope_metadata);
+
+    match exp.node {
+        ast::ExprLit(_)   |
+        ast::ExprBreak(_) |
+        ast::ExprAgain(_) |
+        ast::ExprPath(..) => {}
+
+        ast::ExprCast(ref sub_exp, _)     |
+        ast::ExprAddrOf(_, ref sub_exp)  |
+        ast::ExprField(ref sub_exp, _) |
+        ast::ExprTupField(ref sub_exp, _) |
+        ast::ExprParen(ref sub_exp) =>
+            walk_expr(cx, &**sub_exp, scope_stack, scope_map),
+
+        ast::ExprBox(ref place, ref sub_expr) => {
+            place.as_ref().map(
+                |e| walk_expr(cx, &**e, scope_stack, scope_map));
+            walk_expr(cx, &**sub_expr, scope_stack, scope_map);
+        }
+
+        ast::ExprRet(ref exp_opt) => match *exp_opt {
+            Some(ref sub_exp) => walk_expr(cx, &**sub_exp, scope_stack, scope_map),
+            None => ()
+        },
+
+        ast::ExprUnary(_, ref sub_exp) => {
+            walk_expr(cx, &**sub_exp, scope_stack, scope_map);
+        }
+
+        ast::ExprAssignOp(_, ref lhs, ref rhs) |
+        ast::ExprIndex(ref lhs, ref rhs) |
+        ast::ExprBinary(_, ref lhs, ref rhs)    => {
+            walk_expr(cx, &**lhs, scope_stack, scope_map);
+            walk_expr(cx, &**rhs, scope_stack, scope_map);
+        }
+
+        ast::ExprRange(ref start, ref end) => {
+            start.as_ref().map(|e| walk_expr(cx, &**e, scope_stack, scope_map));
+            end.as_ref().map(|e| walk_expr(cx, &**e, scope_stack, scope_map));
+        }
+
+        ast::ExprVec(ref init_expressions) |
+        ast::ExprTup(ref init_expressions) => {
+            for ie in init_expressions {
+                walk_expr(cx, &**ie, scope_stack, scope_map);
+            }
+        }
+
+        ast::ExprAssign(ref sub_exp1, ref sub_exp2) |
+        ast::ExprRepeat(ref sub_exp1, ref sub_exp2) => {
+            walk_expr(cx, &**sub_exp1, scope_stack, scope_map);
+            walk_expr(cx, &**sub_exp2, scope_stack, scope_map);
+        }
+
+        ast::ExprIf(ref cond_exp, ref then_block, ref opt_else_exp) => {
+            walk_expr(cx, &**cond_exp, scope_stack, scope_map);
+
+            with_new_scope(cx,
+                           then_block.span,
+                           scope_stack,
+                           scope_map,
+                           |cx, scope_stack, scope_map| {
+                walk_block(cx, &**then_block, scope_stack, scope_map);
+            });
+
+            match *opt_else_exp {
+                Some(ref else_exp) =>
+                    walk_expr(cx, &**else_exp, scope_stack, scope_map),
+                _ => ()
+            }
+        }
+
+        ast::ExprIfLet(..) => {
+            cx.sess().span_bug(exp.span, "debuginfo::create_scope_map() - \
+                                          Found unexpanded if-let.");
+        }
+
+        ast::ExprWhile(ref cond_exp, ref loop_body, _) => {
+            walk_expr(cx, &**cond_exp, scope_stack, scope_map);
+
+            with_new_scope(cx,
+                           loop_body.span,
+                           scope_stack,
+                           scope_map,
+                           |cx, scope_stack, scope_map| {
+                walk_block(cx, &**loop_body, scope_stack, scope_map);
+            })
+        }
+
+        ast::ExprWhileLet(..) => {
+            cx.sess().span_bug(exp.span, "debuginfo::create_scope_map() - \
+                                          Found unexpanded while-let.");
+        }
+
+        ast::ExprForLoop(..) => {
+            cx.sess().span_bug(exp.span, "debuginfo::create_scope_map() - \
+                                          Found unexpanded for loop.");
+        }
+
+        ast::ExprMac(_) => {
+            cx.sess().span_bug(exp.span, "debuginfo::create_scope_map() - \
+                                          Found unexpanded macro.");
+        }
+
+        ast::ExprLoop(ref block, _) |
+        ast::ExprBlock(ref block)   => {
+            with_new_scope(cx,
+                           block.span,
+                           scope_stack,
+                           scope_map,
+                           |cx, scope_stack, scope_map| {
+                walk_block(cx, &**block, scope_stack, scope_map);
+            })
+        }
+
+        ast::ExprClosure(_, ref decl, ref block) => {
+            with_new_scope(cx,
+                           block.span,
+                           scope_stack,
+                           scope_map,
+                           |cx, scope_stack, scope_map| {
+                for &ast::Arg { pat: ref pattern, .. } in &decl.inputs {
+                    walk_pattern(cx, &**pattern, scope_stack, scope_map);
+                }
+
+                walk_block(cx, &**block, scope_stack, scope_map);
+            })
+        }
+
+        ast::ExprCall(ref fn_exp, ref args) => {
+            walk_expr(cx, &**fn_exp, scope_stack, scope_map);
+
+            for arg_exp in args {
+                walk_expr(cx, &**arg_exp, scope_stack, scope_map);
+            }
+        }
+
+        ast::ExprMethodCall(_, _, ref args) => {
+            for arg_exp in args {
+                walk_expr(cx, &**arg_exp, scope_stack, scope_map);
+            }
+        }
+
+        ast::ExprMatch(ref discriminant_exp, ref arms, _) => {
+            walk_expr(cx, &**discriminant_exp, scope_stack, scope_map);
+
+            // For each arm we have to first walk the pattern as these might
+            // introduce new artificial scopes. It should be sufficient to
+            // walk only one pattern per arm, as they all must contain the
+            // same binding names.
+
+            for arm_ref in arms {
+                let arm_span = arm_ref.pats[0].span;
+
+                with_new_scope(cx,
+                               arm_span,
+                               scope_stack,
+                               scope_map,
+                               |cx, scope_stack, scope_map| {
+                    for pat in &arm_ref.pats {
+                        walk_pattern(cx, &**pat, scope_stack, scope_map);
+                    }
+
+                    if let Some(ref guard_exp) = arm_ref.guard {
+                        walk_expr(cx, &**guard_exp, scope_stack, scope_map)
+                    }
+
+                    walk_expr(cx, &*arm_ref.body, scope_stack, scope_map);
+                })
+            }
+        }
+
+        ast::ExprStruct(_, ref fields, ref base_exp) => {
+            for &ast::Field { expr: ref exp, .. } in fields {
+                walk_expr(cx, &**exp, scope_stack, scope_map);
+            }
+
+            match *base_exp {
+                Some(ref exp) => walk_expr(cx, &**exp, scope_stack, scope_map),
+                None => ()
+            }
+        }
+
+        ast::ExprInlineAsm(ast::InlineAsm { ref inputs,
+                                            ref outputs,
+                                            .. }) => {
+            // inputs, outputs: Vec<(String, P<Expr>)>
+            for &(_, ref exp) in inputs {
+                walk_expr(cx, &**exp, scope_stack, scope_map);
+            }
+
+            for &(_, ref exp, _) in outputs {
+                walk_expr(cx, &**exp, scope_stack, scope_map);
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/src/librustc_trans/trans/debuginfo/doc.rs b/src/librustc_trans/trans/debuginfo/doc.rs
new file mode 100644 (file)
index 0000000..a91619b
--- /dev/null
@@ -0,0 +1,189 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! # Debug Info Module
+//!
+//! This module serves the purpose of generating debug symbols. We use LLVM's
+//! [source level debugging](http://!llvm.org/docs/SourceLevelDebugging.html)
+//! features for generating the debug information. The general principle is
+//! this:
+//!
+//! Given the right metadata in the LLVM IR, the LLVM code generator is able to
+//! create DWARF debug symbols for the given code. The
+//! [metadata](http://!llvm.org/docs/LangRef.html#metadata-type) is structured
+//! much like DWARF *debugging information entries* (DIE), representing type
+//! information such as datatype layout, function signatures, block layout,
+//! variable location and scope information, etc. It is the purpose of this
+//! module to generate correct metadata and insert it into the LLVM IR.
+//!
+//! As the exact format of metadata trees may change between different LLVM
+//! versions, we now use LLVM
+//! [DIBuilder](http://!llvm.org/docs/doxygen/html/classllvm_1_1DIBuilder.html)
+//! to create metadata where possible. This will hopefully ease the adaption of
+//! this module to future LLVM versions.
+//!
+//! The public API of the module is a set of functions that will insert the
+//! correct metadata into the LLVM IR when called with the right parameters.
+//! The module is thus driven from an outside client with functions like
+//! `debuginfo::create_local_var_metadata(bcx: block, local: &ast::local)`.
+//!
+//! Internally the module will try to reuse already created metadata by
+//! utilizing a cache. The way to get a shared metadata node when needed is
+//! thus to just call the corresponding function in this module:
+//!
+//!     let file_metadata = file_metadata(crate_context, path);
+//!
+//! The function will take care of probing the cache for an existing node for
+//! that exact file path.
+//!
+//! All private state used by the module is stored within either the
+//! CrateDebugContext struct (owned by the CrateContext) or the
+//! FunctionDebugContext (owned by the FunctionContext).
+//!
+//! This file consists of three conceptual sections:
+//! 1. The public interface of the module
+//! 2. Module-internal metadata creation functions
+//! 3. Minor utility functions
+//!
+//!
+//! ## Recursive Types
+//!
+//! Some kinds of types, such as structs and enums can be recursive. That means
+//! that the type definition of some type X refers to some other type which in
+//! turn (transitively) refers to X. This introduces cycles into the type
+//! referral graph. A naive algorithm doing an on-demand, depth-first traversal
+//! of this graph when describing types, can get trapped in an endless loop
+//! when it reaches such a cycle.
+//!
+//! For example, the following simple type for a singly-linked list...
+//!
+//! ```
+//! struct List {
+//!     value: int,
+//!     tail: Option<Box<List>>,
+//! }
+//! ```
+//!
+//! will generate the following callstack with a naive DFS algorithm:
+//!
+//! ```
+//! describe(t = List)
+//!   describe(t = int)
+//!   describe(t = Option<Box<List>>)
+//!     describe(t = Box<List>)
+//!       describe(t = List) // at the beginning again...
+//!       ...
+//! ```
+//!
+//! To break cycles like these, we use "forward declarations". That is, when
+//! the algorithm encounters a possibly recursive type (any struct or enum), it
+//! immediately creates a type description node and inserts it into the cache
+//! *before* describing the members of the type. This type description is just
+//! a stub (as type members are not described and added to it yet) but it
+//! allows the algorithm to already refer to the type. After the stub is
+//! inserted into the cache, the algorithm continues as before. If it now
+//! encounters a recursive reference, it will hit the cache and does not try to
+//! describe the type anew.
+//!
+//! This behaviour is encapsulated in the 'RecursiveTypeDescription' enum,
+//! which represents a kind of continuation, storing all state needed to
+//! continue traversal at the type members after the type has been registered
+//! with the cache. (This implementation approach might be a tad over-
+//! engineered and may change in the future)
+//!
+//!
+//! ## Source Locations and Line Information
+//!
+//! In addition to data type descriptions the debugging information must also
+//! allow to map machine code locations back to source code locations in order
+//! to be useful. This functionality is also handled in this module. The
+//! following functions allow to control source mappings:
+//!
+//! + set_source_location()
+//! + clear_source_location()
+//! + start_emitting_source_locations()
+//!
+//! `set_source_location()` allows to set the current source location. All IR
+//! instructions created after a call to this function will be linked to the
+//! given source location, until another location is specified with
+//! `set_source_location()` or the source location is cleared with
+//! `clear_source_location()`. In the later case, subsequent IR instruction
+//! will not be linked to any source location. As you can see, this is a
+//! stateful API (mimicking the one in LLVM), so be careful with source
+//! locations set by previous calls. It's probably best to not rely on any
+//! specific state being present at a given point in code.
+//!
+//! One topic that deserves some extra attention is *function prologues*. At
+//! the beginning of a function's machine code there are typically a few
+//! instructions for loading argument values into allocas and checking if
+//! there's enough stack space for the function to execute. This *prologue* is
+//! not visible in the source code and LLVM puts a special PROLOGUE END marker
+//! into the line table at the first non-prologue instruction of the function.
+//! In order to find out where the prologue ends, LLVM looks for the first
+//! instruction in the function body that is linked to a source location. So,
+//! when generating prologue instructions we have to make sure that we don't
+//! emit source location information until the 'real' function body begins. For
+//! this reason, source location emission is disabled by default for any new
+//! function being translated and is only activated after a call to the third
+//! function from the list above, `start_emitting_source_locations()`. This
+//! function should be called right before regularly starting to translate the
+//! top-level block of the given function.
+//!
+//! There is one exception to the above rule: `llvm.dbg.declare` instruction
+//! must be linked to the source location of the variable being declared. For
+//! function parameters these `llvm.dbg.declare` instructions typically occur
+//! in the middle of the prologue, however, they are ignored by LLVM's prologue
+//! detection. The `create_argument_metadata()` and related functions take care
+//! of linking the `llvm.dbg.declare` instructions to the correct source
+//! locations even while source location emission is still disabled, so there
+//! is no need to do anything special with source location handling here.
+//!
+//! ## Unique Type Identification
+//!
+//! In order for link-time optimization to work properly, LLVM needs a unique
+//! type identifier that tells it across compilation units which types are the
+//! same as others. This type identifier is created by
+//! TypeMap::get_unique_type_id_of_type() using the following algorithm:
+//!
+//! (1) Primitive types have their name as ID
+//! (2) Structs, enums and traits have a multipart identifier
+//!
+//!     (1) The first part is the SVH (strict version hash) of the crate they
+//!          wereoriginally defined in
+//!
+//!     (2) The second part is the ast::NodeId of the definition in their
+//!          originalcrate
+//!
+//!     (3) The final part is a concatenation of the type IDs of their concrete
+//!          typearguments if they are generic types.
+//!
+//! (3) Tuple-, pointer and function types are structurally identified, which
+//!     means that they are equivalent if their component types are equivalent
+//!     (i.e. (int, int) is the same regardless in which crate it is used).
+//!
+//! This algorithm also provides a stable ID for types that are defined in one
+//! crate but instantiated from metadata within another crate. We just have to
+//! take care to always map crate and node IDs back to the original crate
+//! context.
+//!
+//! As a side-effect these unique type IDs also help to solve a problem arising
+//! from lifetime parameters. Since lifetime parameters are completely omitted
+//! in debuginfo, more than one `Ty` instance may map to the same debuginfo
+//! type metadata, that is, some struct `Struct<'a>` may have N instantiations
+//! with different concrete substitutions for `'a`, and thus there will be N
+//! `Ty` instances for the type `Struct<'a>` even though it is not generic
+//! otherwise. Unfortunately this means that we cannot use `ty::type_id()` as
+//! cheap identifier for type metadata---we have done this in the past, but it
+//! led to unnecessary metadata duplication in the best case and LLVM
+//! assertions in the worst. However, the unique type ID as described above
+//! *can* be used as identifier. Since it is comparatively expensive to
+//! construct, though, `ty::type_id()` is still used additionally as an
+//! optimization for cases where the exact same type has been seen before
+//! (which is most of the time).
diff --git a/src/librustc_trans/trans/debuginfo/gdb.rs b/src/librustc_trans/trans/debuginfo/gdb.rs
new file mode 100644 (file)
index 0000000..a6f1199
--- /dev/null
@@ -0,0 +1,94 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// .debug_gdb_scripts binary section.
+
+use llvm;
+use llvm::ValueRef;
+
+use trans::common::{C_bytes, CrateContext};
+use trans::declare;
+use trans::type_::Type;
+use middle::ty::ClosureTyper;
+use session::config::NoDebugInfo;
+
+use std::ffi::CString;
+use std::ptr;
+use syntax::attr;
+
+
+/// Inserts a side-effect free instruction sequence that makes sure that the
+/// .debug_gdb_scripts global is referenced, so it isn't removed by the linker.
+pub fn insert_reference_to_gdb_debug_scripts_section_global(ccx: &CrateContext) {
+    if needs_gdb_debug_scripts_section(ccx) {
+        let empty = CString::new("").unwrap();
+        let gdb_debug_scripts_section_global =
+            get_or_insert_gdb_debug_scripts_section_global(ccx);
+        unsafe {
+            let volative_load_instruction =
+                llvm::LLVMBuildLoad(ccx.raw_builder(),
+                                    gdb_debug_scripts_section_global,
+                                    empty.as_ptr());
+            llvm::LLVMSetVolatile(volative_load_instruction, llvm::True);
+        }
+    }
+}
+
+/// Allocates the global variable responsible for the .debug_gdb_scripts binary
+/// section.
+pub fn get_or_insert_gdb_debug_scripts_section_global(ccx: &CrateContext)
+                                                  -> llvm::ValueRef {
+    let section_var_name = "__rustc_debug_gdb_scripts_section__";
+
+    let section_var = unsafe {
+        llvm::LLVMGetNamedGlobal(ccx.llmod(),
+                                 section_var_name.as_ptr() as *const _)
+    };
+
+    if section_var == ptr::null_mut() {
+        let section_name = b".debug_gdb_scripts\0";
+        let section_contents = b"\x01gdb_load_rust_pretty_printers.py\0";
+
+        unsafe {
+            let llvm_type = Type::array(&Type::i8(ccx),
+                                        section_contents.len() as u64);
+
+            let section_var = declare::define_global(ccx, section_var_name,
+                                                     llvm_type).unwrap_or_else(||{
+                ccx.sess().bug(&format!("symbol `{}` is already defined", section_var_name))
+            });
+            llvm::LLVMSetSection(section_var, section_name.as_ptr() as *const _);
+            llvm::LLVMSetInitializer(section_var, C_bytes(ccx, section_contents));
+            llvm::LLVMSetGlobalConstant(section_var, llvm::True);
+            llvm::LLVMSetUnnamedAddr(section_var, llvm::True);
+            llvm::SetLinkage(section_var, llvm::Linkage::LinkOnceODRLinkage);
+            // This should make sure that the whole section is not larger than
+            // the string it contains. Otherwise we get a warning from GDB.
+            llvm::LLVMSetAlignment(section_var, 1);
+            section_var
+        }
+    } else {
+        section_var
+    }
+}
+
+pub fn needs_gdb_debug_scripts_section(ccx: &CrateContext) -> bool {
+    let omit_gdb_pretty_printer_section =
+        attr::contains_name(&ccx.tcx()
+                                .map
+                                .krate()
+                                .attrs,
+                            "omit_gdb_pretty_printer_section");
+
+    !omit_gdb_pretty_printer_section &&
+    !ccx.sess().target.target.options.is_like_osx &&
+    !ccx.sess().target.target.options.is_like_windows &&
+    ccx.sess().opts.debuginfo != NoDebugInfo
+}
diff --git a/src/librustc_trans/trans/debuginfo/metadata.rs b/src/librustc_trans/trans/debuginfo/metadata.rs
new file mode 100644 (file)
index 0000000..9ff69e7
--- /dev/null
@@ -0,0 +1,2146 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use self::RecursiveTypeDescription::*;
+use self::MemberOffset::*;
+use self::MemberDescriptionFactory::*;
+use self::EnumDiscriminantInfo::*;
+
+use super::utils::{debug_context, DIB, span_start, bytes_to_bits, size_and_align_of,
+                   get_namespace_and_span_for_item, create_DIArray,
+                   fn_should_be_ignored, is_node_local_to_unit};
+use super::namespace::namespace_for_item;
+use super::type_names::{compute_debuginfo_type_name, push_debuginfo_type_name};
+use super::{declare_local, VariableKind, VariableAccess};
+
+use llvm::{self, ValueRef};
+use llvm::debuginfo::{DIType, DIFile, DIScope, DIDescriptor, DICompositeType};
+
+use metadata::csearch;
+use middle::pat_util;
+use middle::subst::{self, Substs};
+use trans::{type_of, adt, machine, monomorphize};
+use trans::common::{self, CrateContext, FunctionContext, NormalizingClosureTyper, Block};
+use trans::_match::{BindingInfo, TrByCopy, TrByMove, TrByRef};
+use trans::type_::Type;
+use middle::ty::{self, Ty, ClosureTyper};
+use session::config::{self, FullDebugInfo};
+use util::nodemap::FnvHashMap;
+use util::ppaux;
+use util::common::path2cstr;
+
+use libc::{c_uint, c_longlong};
+use std::ffi::CString;
+use std::path::Path;
+use std::ptr;
+use std::rc::Rc;
+use syntax::util::interner::Interner;
+use syntax::codemap::Span;
+use syntax::{ast, codemap, ast_util, ast_map};
+use syntax::parse::token::{self, special_idents};
+
+
+const DW_LANG_RUST: c_uint = 0x9000;
+#[allow(non_upper_case_globals)]
+const DW_ATE_boolean: c_uint = 0x02;
+#[allow(non_upper_case_globals)]
+const DW_ATE_float: c_uint = 0x04;
+#[allow(non_upper_case_globals)]
+const DW_ATE_signed: c_uint = 0x05;
+#[allow(non_upper_case_globals)]
+const DW_ATE_unsigned: c_uint = 0x07;
+#[allow(non_upper_case_globals)]
+const DW_ATE_unsigned_char: c_uint = 0x08;
+
+pub const UNKNOWN_LINE_NUMBER: c_uint = 0;
+pub const UNKNOWN_COLUMN_NUMBER: c_uint = 0;
+
+// ptr::null() doesn't work :(
+const UNKNOWN_FILE_METADATA: DIFile = (0 as DIFile);
+const UNKNOWN_SCOPE_METADATA: DIScope = (0 as DIScope);
+
+const FLAGS_NONE: c_uint = 0;
+
+#[derive(Copy, Debug, Hash, Eq, PartialEq, Clone)]
+pub struct UniqueTypeId(ast::Name);
+
+// The TypeMap is where the CrateDebugContext holds the type metadata nodes
+// created so far. The metadata nodes are indexed by UniqueTypeId, and, for
+// faster lookup, also by Ty. The TypeMap is responsible for creating
+// UniqueTypeIds.
+pub struct TypeMap<'tcx> {
+    // The UniqueTypeIds created so far
+    unique_id_interner: Interner<Rc<String>>,
+    // A map from UniqueTypeId to debuginfo metadata for that type. This is a 1:1 mapping.
+    unique_id_to_metadata: FnvHashMap<UniqueTypeId, DIType>,
+    // A map from types to debuginfo metadata. This is a N:1 mapping.
+    type_to_metadata: FnvHashMap<Ty<'tcx>, DIType>,
+    // A map from types to UniqueTypeId. This is a N:1 mapping.
+    type_to_unique_id: FnvHashMap<Ty<'tcx>, UniqueTypeId>
+}
+
+impl<'tcx> TypeMap<'tcx> {
+    pub fn new() -> TypeMap<'tcx> {
+        TypeMap {
+            unique_id_interner: Interner::new(),
+            type_to_metadata: FnvHashMap(),
+            unique_id_to_metadata: FnvHashMap(),
+            type_to_unique_id: FnvHashMap(),
+        }
+    }
+
+    // Adds a Ty to metadata mapping to the TypeMap. The method will fail if
+    // the mapping already exists.
+    fn register_type_with_metadata<'a>(&mut self,
+                                       cx: &CrateContext<'a, 'tcx>,
+                                       type_: Ty<'tcx>,
+                                       metadata: DIType) {
+        if self.type_to_metadata.insert(type_, metadata).is_some() {
+            cx.sess().bug(&format!("Type metadata for Ty '{}' is already in the TypeMap!",
+                                   ppaux::ty_to_string(cx.tcx(), type_)));
+        }
+    }
+
+    // Adds a UniqueTypeId to metadata mapping to the TypeMap. The method will
+    // fail if the mapping already exists.
+    fn register_unique_id_with_metadata(&mut self,
+                                        cx: &CrateContext,
+                                        unique_type_id: UniqueTypeId,
+                                        metadata: DIType) {
+        if self.unique_id_to_metadata.insert(unique_type_id, metadata).is_some() {
+            let unique_type_id_str = self.get_unique_type_id_as_string(unique_type_id);
+            cx.sess().bug(&format!("Type metadata for unique id '{}' is already in the TypeMap!",
+                                  &unique_type_id_str[..]));
+        }
+    }
+
+    fn find_metadata_for_type(&self, type_: Ty<'tcx>) -> Option<DIType> {
+        self.type_to_metadata.get(&type_).cloned()
+    }
+
+    fn find_metadata_for_unique_id(&self, unique_type_id: UniqueTypeId) -> Option<DIType> {
+        self.unique_id_to_metadata.get(&unique_type_id).cloned()
+    }
+
+    // Get the string representation of a UniqueTypeId. This method will fail if
+    // the id is unknown.
+    fn get_unique_type_id_as_string(&self, unique_type_id: UniqueTypeId) -> Rc<String> {
+        let UniqueTypeId(interner_key) = unique_type_id;
+        self.unique_id_interner.get(interner_key)
+    }
+
+    // Get the UniqueTypeId for the given type. If the UniqueTypeId for the given
+    // type has been requested before, this is just a table lookup. Otherwise an
+    // ID will be generated and stored for later lookup.
+    fn get_unique_type_id_of_type<'a>(&mut self, cx: &CrateContext<'a, 'tcx>,
+                                      type_: Ty<'tcx>) -> UniqueTypeId {
+
+        // basic type           -> {:name of the type:}
+        // tuple                -> {tuple_(:param-uid:)*}
+        // struct               -> {struct_:svh: / :node-id:_<(:param-uid:),*> }
+        // enum                 -> {enum_:svh: / :node-id:_<(:param-uid:),*> }
+        // enum variant         -> {variant_:variant-name:_:enum-uid:}
+        // reference (&)        -> {& :pointee-uid:}
+        // mut reference (&mut) -> {&mut :pointee-uid:}
+        // ptr (*)              -> {* :pointee-uid:}
+        // mut ptr (*mut)       -> {*mut :pointee-uid:}
+        // unique ptr (~)       -> {~ :pointee-uid:}
+        // @-ptr (@)            -> {@ :pointee-uid:}
+        // sized vec ([T; x])   -> {[:size:] :element-uid:}
+        // unsized vec ([T])    -> {[] :element-uid:}
+        // trait (T)            -> {trait_:svh: / :node-id:_<(:param-uid:),*> }
+        // closure              -> {<unsafe_> <once_> :store-sigil: |(:param-uid:),* <,_...>| -> \
+        //                             :return-type-uid: : (:bounds:)*}
+        // function             -> {<unsafe_> <abi_> fn( (:param-uid:)* <,_...> ) -> \
+        //                             :return-type-uid:}
+        // unique vec box (~[]) -> {HEAP_VEC_BOX<:pointee-uid:>}
+        // gc box               -> {GC_BOX<:pointee-uid:>}
+
+        match self.type_to_unique_id.get(&type_).cloned() {
+            Some(unique_type_id) => return unique_type_id,
+            None => { /* generate one */}
+        };
+
+        let mut unique_type_id = String::with_capacity(256);
+        unique_type_id.push('{');
+
+        match type_.sty {
+            ty::ty_bool     |
+            ty::ty_char     |
+            ty::ty_str      |
+            ty::ty_int(_)   |
+            ty::ty_uint(_)  |
+            ty::ty_float(_) => {
+                push_debuginfo_type_name(cx, type_, false, &mut unique_type_id);
+            },
+            ty::ty_enum(def_id, substs) => {
+                unique_type_id.push_str("enum ");
+                from_def_id_and_substs(self, cx, def_id, substs, &mut unique_type_id);
+            },
+            ty::ty_struct(def_id, substs) => {
+                unique_type_id.push_str("struct ");
+                from_def_id_and_substs(self, cx, def_id, substs, &mut unique_type_id);
+            },
+            ty::ty_tup(ref component_types) if component_types.is_empty() => {
+                push_debuginfo_type_name(cx, type_, false, &mut unique_type_id);
+            },
+            ty::ty_tup(ref component_types) => {
+                unique_type_id.push_str("tuple ");
+                for &component_type in component_types {
+                    let component_type_id =
+                        self.get_unique_type_id_of_type(cx, component_type);
+                    let component_type_id =
+                        self.get_unique_type_id_as_string(component_type_id);
+                    unique_type_id.push_str(&component_type_id[..]);
+                }
+            },
+            ty::ty_uniq(inner_type) => {
+                unique_type_id.push('~');
+                let inner_type_id = self.get_unique_type_id_of_type(cx, inner_type);
+                let inner_type_id = self.get_unique_type_id_as_string(inner_type_id);
+                unique_type_id.push_str(&inner_type_id[..]);
+            },
+            ty::ty_ptr(ty::mt { ty: inner_type, mutbl } ) => {
+                unique_type_id.push('*');
+                if mutbl == ast::MutMutable {
+                    unique_type_id.push_str("mut");
+                }
+
+                let inner_type_id = self.get_unique_type_id_of_type(cx, inner_type);
+                let inner_type_id = self.get_unique_type_id_as_string(inner_type_id);
+                unique_type_id.push_str(&inner_type_id[..]);
+            },
+            ty::ty_rptr(_, ty::mt { ty: inner_type, mutbl }) => {
+                unique_type_id.push('&');
+                if mutbl == ast::MutMutable {
+                    unique_type_id.push_str("mut");
+                }
+
+                let inner_type_id = self.get_unique_type_id_of_type(cx, inner_type);
+                let inner_type_id = self.get_unique_type_id_as_string(inner_type_id);
+                unique_type_id.push_str(&inner_type_id[..]);
+            },
+            ty::ty_vec(inner_type, optional_length) => {
+                match optional_length {
+                    Some(len) => {
+                        unique_type_id.push_str(&format!("[{}]", len));
+                    }
+                    None => {
+                        unique_type_id.push_str("[]");
+                    }
+                };
+
+                let inner_type_id = self.get_unique_type_id_of_type(cx, inner_type);
+                let inner_type_id = self.get_unique_type_id_as_string(inner_type_id);
+                unique_type_id.push_str(&inner_type_id[..]);
+            },
+            ty::ty_trait(ref trait_data) => {
+                unique_type_id.push_str("trait ");
+
+                let principal =
+                    ty::erase_late_bound_regions(cx.tcx(),
+                                                 &trait_data.principal);
+
+                from_def_id_and_substs(self,
+                                       cx,
+                                       principal.def_id,
+                                       principal.substs,
+                                       &mut unique_type_id);
+            },
+            ty::ty_bare_fn(_, &ty::BareFnTy{ unsafety, abi, ref sig } ) => {
+                if unsafety == ast::Unsafety::Unsafe {
+                    unique_type_id.push_str("unsafe ");
+                }
+
+                unique_type_id.push_str(abi.name());
+
+                unique_type_id.push_str(" fn(");
+
+                let sig = ty::erase_late_bound_regions(cx.tcx(), sig);
+
+                for &parameter_type in &sig.inputs {
+                    let parameter_type_id =
+                        self.get_unique_type_id_of_type(cx, parameter_type);
+                    let parameter_type_id =
+                        self.get_unique_type_id_as_string(parameter_type_id);
+                    unique_type_id.push_str(&parameter_type_id[..]);
+                    unique_type_id.push(',');
+                }
+
+                if sig.variadic {
+                    unique_type_id.push_str("...");
+                }
+
+                unique_type_id.push_str(")->");
+                match sig.output {
+                    ty::FnConverging(ret_ty) => {
+                        let return_type_id = self.get_unique_type_id_of_type(cx, ret_ty);
+                        let return_type_id = self.get_unique_type_id_as_string(return_type_id);
+                        unique_type_id.push_str(&return_type_id[..]);
+                    }
+                    ty::FnDiverging => {
+                        unique_type_id.push_str("!");
+                    }
+                }
+            },
+            ty::ty_closure(def_id, substs) => {
+                let typer = NormalizingClosureTyper::new(cx.tcx());
+                let closure_ty = typer.closure_type(def_id, substs);
+                self.get_unique_type_id_of_closure_type(cx,
+                                                        closure_ty,
+                                                        &mut unique_type_id);
+            },
+            _ => {
+                cx.sess().bug(&format!("get_unique_type_id_of_type() - unexpected type: {}, {:?}",
+                                      &ppaux::ty_to_string(cx.tcx(), type_),
+                                      type_.sty))
+            }
+        };
+
+        unique_type_id.push('}');
+
+        // Trim to size before storing permanently
+        unique_type_id.shrink_to_fit();
+
+        let key = self.unique_id_interner.intern(Rc::new(unique_type_id));
+        self.type_to_unique_id.insert(type_, UniqueTypeId(key));
+
+        return UniqueTypeId(key);
+
+        fn from_def_id_and_substs<'a, 'tcx>(type_map: &mut TypeMap<'tcx>,
+                                            cx: &CrateContext<'a, 'tcx>,
+                                            def_id: ast::DefId,
+                                            substs: &subst::Substs<'tcx>,
+                                            output: &mut String) {
+            // First, find out the 'real' def_id of the type. Items inlined from
+            // other crates have to be mapped back to their source.
+            let source_def_id = if def_id.krate == ast::LOCAL_CRATE {
+                match cx.external_srcs().borrow().get(&def_id.node).cloned() {
+                    Some(source_def_id) => {
+                        // The given def_id identifies the inlined copy of a
+                        // type definition, let's take the source of the copy.
+                        source_def_id
+                    }
+                    None => def_id
+                }
+            } else {
+                def_id
+            };
+
+            // Get the crate hash as first part of the identifier.
+            let crate_hash = if source_def_id.krate == ast::LOCAL_CRATE {
+                cx.link_meta().crate_hash.clone()
+            } else {
+                cx.sess().cstore.get_crate_hash(source_def_id.krate)
+            };
+
+            output.push_str(crate_hash.as_str());
+            output.push_str("/");
+            output.push_str(&format!("{:x}", def_id.node));
+
+            // Maybe check that there is no self type here.
+
+            let tps = substs.types.get_slice(subst::TypeSpace);
+            if !tps.is_empty() {
+                output.push('<');
+
+                for &type_parameter in tps {
+                    let param_type_id =
+                        type_map.get_unique_type_id_of_type(cx, type_parameter);
+                    let param_type_id =
+                        type_map.get_unique_type_id_as_string(param_type_id);
+                    output.push_str(&param_type_id[..]);
+                    output.push(',');
+                }
+
+                output.push('>');
+            }
+        }
+    }
+
+    fn get_unique_type_id_of_closure_type<'a>(&mut self,
+                                              cx: &CrateContext<'a, 'tcx>,
+                                              closure_ty: ty::ClosureTy<'tcx>,
+                                              unique_type_id: &mut String) {
+        let ty::ClosureTy { unsafety,
+                            ref sig,
+                            abi: _ } = closure_ty;
+
+        if unsafety == ast::Unsafety::Unsafe {
+            unique_type_id.push_str("unsafe ");
+        }
+
+        unique_type_id.push_str("|");
+
+        let sig = ty::erase_late_bound_regions(cx.tcx(), sig);
+
+        for &parameter_type in &sig.inputs {
+            let parameter_type_id =
+                self.get_unique_type_id_of_type(cx, parameter_type);
+            let parameter_type_id =
+                self.get_unique_type_id_as_string(parameter_type_id);
+            unique_type_id.push_str(&parameter_type_id[..]);
+            unique_type_id.push(',');
+        }
+
+        if sig.variadic {
+            unique_type_id.push_str("...");
+        }
+
+        unique_type_id.push_str("|->");
+
+        match sig.output {
+            ty::FnConverging(ret_ty) => {
+                let return_type_id = self.get_unique_type_id_of_type(cx, ret_ty);
+                let return_type_id = self.get_unique_type_id_as_string(return_type_id);
+                unique_type_id.push_str(&return_type_id[..]);
+            }
+            ty::FnDiverging => {
+                unique_type_id.push_str("!");
+            }
+        }
+    }
+
+    // Get the UniqueTypeId for an enum variant. Enum variants are not really
+    // types of their own, so they need special handling. We still need a
+    // UniqueTypeId for them, since to debuginfo they *are* real types.
+    fn get_unique_type_id_of_enum_variant<'a>(&mut self,
+                                              cx: &CrateContext<'a, 'tcx>,
+                                              enum_type: Ty<'tcx>,
+                                              variant_name: &str)
+                                              -> UniqueTypeId {
+        let enum_type_id = self.get_unique_type_id_of_type(cx, enum_type);
+        let enum_variant_type_id = format!("{}::{}",
+                                           &self.get_unique_type_id_as_string(enum_type_id),
+                                           variant_name);
+        let interner_key = self.unique_id_interner.intern(Rc::new(enum_variant_type_id));
+        UniqueTypeId(interner_key)
+    }
+}
+
+// A description of some recursive type. It can either be already finished (as
+// with FinalMetadata) or it is not yet finished, but contains all information
+// needed to generate the missing parts of the description. See the
+// documentation section on Recursive Types at the top of this file for more
+// information.
+enum RecursiveTypeDescription<'tcx> {
+    UnfinishedMetadata {
+        unfinished_type: Ty<'tcx>,
+        unique_type_id: UniqueTypeId,
+        metadata_stub: DICompositeType,
+        llvm_type: Type,
+        member_description_factory: MemberDescriptionFactory<'tcx>,
+    },
+    FinalMetadata(DICompositeType)
+}
+
+fn create_and_register_recursive_type_forward_declaration<'a, 'tcx>(
+    cx: &CrateContext<'a, 'tcx>,
+    unfinished_type: Ty<'tcx>,
+    unique_type_id: UniqueTypeId,
+    metadata_stub: DICompositeType,
+    llvm_type: Type,
+    member_description_factory: MemberDescriptionFactory<'tcx>)
+ -> RecursiveTypeDescription<'tcx> {
+
+    // Insert the stub into the TypeMap in order to allow for recursive references
+    let mut type_map = debug_context(cx).type_map.borrow_mut();
+    type_map.register_unique_id_with_metadata(cx, unique_type_id, metadata_stub);
+    type_map.register_type_with_metadata(cx, unfinished_type, metadata_stub);
+
+    UnfinishedMetadata {
+        unfinished_type: unfinished_type,
+        unique_type_id: unique_type_id,
+        metadata_stub: metadata_stub,
+        llvm_type: llvm_type,
+        member_description_factory: member_description_factory,
+    }
+}
+
+impl<'tcx> RecursiveTypeDescription<'tcx> {
+    // Finishes up the description of the type in question (mostly by providing
+    // descriptions of the fields of the given type) and returns the final type
+    // metadata.
+    fn finalize<'a>(&self, cx: &CrateContext<'a, 'tcx>) -> MetadataCreationResult {
+        match *self {
+            FinalMetadata(metadata) => MetadataCreationResult::new(metadata, false),
+            UnfinishedMetadata {
+                unfinished_type,
+                unique_type_id,
+                metadata_stub,
+                llvm_type,
+                ref member_description_factory,
+                ..
+            } => {
+                // Make sure that we have a forward declaration of the type in
+                // the TypeMap so that recursive references are possible. This
+                // will always be the case if the RecursiveTypeDescription has
+                // been properly created through the
+                // create_and_register_recursive_type_forward_declaration()
+                // function.
+                {
+                    let type_map = debug_context(cx).type_map.borrow();
+                    if type_map.find_metadata_for_unique_id(unique_type_id).is_none() ||
+                       type_map.find_metadata_for_type(unfinished_type).is_none() {
+                        cx.sess().bug(&format!("Forward declaration of potentially recursive type \
+                                              '{}' was not found in TypeMap!",
+                                              ppaux::ty_to_string(cx.tcx(), unfinished_type))
+                                      );
+                    }
+                }
+
+                // ... then create the member descriptions ...
+                let member_descriptions =
+                    member_description_factory.create_member_descriptions(cx);
+
+                // ... and attach them to the stub to complete it.
+                set_members_of_composite_type(cx,
+                                              metadata_stub,
+                                              llvm_type,
+                                              &member_descriptions[..]);
+                return MetadataCreationResult::new(metadata_stub, true);
+            }
+        }
+    }
+}
+
+// Returns from the enclosing function if the type metadata with the given
+// unique id can be found in the type map
+macro_rules! return_if_metadata_created_in_meantime {
+    ($cx: expr, $unique_type_id: expr) => (
+        match debug_context($cx).type_map
+                                .borrow()
+                                .find_metadata_for_unique_id($unique_type_id) {
+            Some(metadata) => return MetadataCreationResult::new(metadata, true),
+            None => { /* proceed normally */ }
+        };
+    )
+}
+
+fn fixed_vec_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
+                                unique_type_id: UniqueTypeId,
+                                element_type: Ty<'tcx>,
+                                len: Option<u64>,
+                                span: Span)
+                                -> MetadataCreationResult {
+    let element_type_metadata = type_metadata(cx, element_type, span);
+
+    return_if_metadata_created_in_meantime!(cx, unique_type_id);
+
+    let element_llvm_type = type_of::type_of(cx, element_type);
+    let (element_type_size, element_type_align) = size_and_align_of(cx, element_llvm_type);
+
+    let (array_size_in_bytes, upper_bound) = match len {
+        Some(len) => (element_type_size * len, len as c_longlong),
+        None => (0, -1)
+    };
+
+    let subrange = unsafe {
+        llvm::LLVMDIBuilderGetOrCreateSubrange(DIB(cx), 0, upper_bound)
+    };
+
+    let subscripts = create_DIArray(DIB(cx), &[subrange]);
+    let metadata = unsafe {
+        llvm::LLVMDIBuilderCreateArrayType(
+            DIB(cx),
+            bytes_to_bits(array_size_in_bytes),
+            bytes_to_bits(element_type_align),
+            element_type_metadata,
+            subscripts)
+    };
+
+    return MetadataCreationResult::new(metadata, false);
+}
+
+fn vec_slice_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
+                                vec_type: Ty<'tcx>,
+                                element_type: Ty<'tcx>,
+                                unique_type_id: UniqueTypeId,
+                                span: Span)
+                                -> MetadataCreationResult {
+    let data_ptr_type = ty::mk_ptr(cx.tcx(), ty::mt {
+        ty: element_type,
+        mutbl: ast::MutImmutable
+    });
+
+    let element_type_metadata = type_metadata(cx, data_ptr_type, span);
+
+    return_if_metadata_created_in_meantime!(cx, unique_type_id);
+
+    let slice_llvm_type = type_of::type_of(cx, vec_type);
+    let slice_type_name = compute_debuginfo_type_name(cx, vec_type, true);
+
+    let member_llvm_types = slice_llvm_type.field_types();
+    assert!(slice_layout_is_correct(cx,
+                                    &member_llvm_types[..],
+                                    element_type));
+    let member_descriptions = [
+        MemberDescription {
+            name: "data_ptr".to_string(),
+            llvm_type: member_llvm_types[0],
+            type_metadata: element_type_metadata,
+            offset: ComputedMemberOffset,
+            flags: FLAGS_NONE
+        },
+        MemberDescription {
+            name: "length".to_string(),
+            llvm_type: member_llvm_types[1],
+            type_metadata: type_metadata(cx, cx.tcx().types.usize, span),
+            offset: ComputedMemberOffset,
+            flags: FLAGS_NONE
+        },
+    ];
+
+    assert!(member_descriptions.len() == member_llvm_types.len());
+
+    let loc = span_start(cx, span);
+    let file_metadata = file_metadata(cx, &loc.file.name);
+
+    let metadata = composite_type_metadata(cx,
+                                           slice_llvm_type,
+                                           &slice_type_name[..],
+                                           unique_type_id,
+                                           &member_descriptions,
+                                           UNKNOWN_SCOPE_METADATA,
+                                           file_metadata,
+                                           span);
+    return MetadataCreationResult::new(metadata, false);
+
+    fn slice_layout_is_correct<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
+                                         member_llvm_types: &[Type],
+                                         element_type: Ty<'tcx>)
+                                         -> bool {
+        member_llvm_types.len() == 2 &&
+        member_llvm_types[0] == type_of::type_of(cx, element_type).ptr_to() &&
+        member_llvm_types[1] == cx.int_type()
+    }
+}
+
+fn subroutine_type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
+                                      unique_type_id: UniqueTypeId,
+                                      signature: &ty::PolyFnSig<'tcx>,
+                                      span: Span)
+                                      -> MetadataCreationResult
+{
+    let signature = ty::erase_late_bound_regions(cx.tcx(), signature);
+
+    let mut signature_metadata: Vec<DIType> = Vec::with_capacity(signature.inputs.len() + 1);
+
+    // return type
+    signature_metadata.push(match signature.output {
+        ty::FnConverging(ret_ty) => match ret_ty.sty {
+            ty::ty_tup(ref tys) if tys.is_empty() => ptr::null_mut(),
+            _ => type_metadata(cx, ret_ty, span)
+        },
+        ty::FnDiverging => diverging_type_metadata(cx)
+    });
+
+    // regular arguments
+    for &argument_type in &signature.inputs {
+        signature_metadata.push(type_metadata(cx, argument_type, span));
+    }
+
+    return_if_metadata_created_in_meantime!(cx, unique_type_id);
+
+    return MetadataCreationResult::new(
+        unsafe {
+            llvm::LLVMDIBuilderCreateSubroutineType(
+                DIB(cx),
+                UNKNOWN_FILE_METADATA,
+                create_DIArray(DIB(cx), &signature_metadata[..]))
+        },
+        false);
+}
+
+// FIXME(1563) This is all a bit of a hack because 'trait pointer' is an ill-
+// defined concept. For the case of an actual trait pointer (i.e., Box<Trait>,
+// &Trait), trait_object_type should be the whole thing (e.g, Box<Trait>) and
+// trait_type should be the actual trait (e.g., Trait). Where the trait is part
+// of a DST struct, there is no trait_object_type and the results of this
+// function will be a little bit weird.
+fn trait_pointer_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
+                                    trait_type: Ty<'tcx>,
+                                    trait_object_type: Option<Ty<'tcx>>,
+                                    unique_type_id: UniqueTypeId)
+                                    -> DIType {
+    // The implementation provided here is a stub. It makes sure that the trait
+    // type is assigned the correct name, size, namespace, and source location.
+    // But it does not describe the trait's methods.
+
+    let def_id = match trait_type.sty {
+        ty::ty_trait(ref data) => data.principal_def_id(),
+        _ => {
+            let pp_type_name = ppaux::ty_to_string(cx.tcx(), trait_type);
+            cx.sess().bug(&format!("debuginfo: Unexpected trait-object type in \
+                                   trait_pointer_metadata(): {}",
+                                   &pp_type_name[..]));
+        }
+    };
+
+    let trait_object_type = trait_object_type.unwrap_or(trait_type);
+    let trait_type_name =
+        compute_debuginfo_type_name(cx, trait_object_type, false);
+
+    let (containing_scope, _) = get_namespace_and_span_for_item(cx, def_id);
+
+    let trait_llvm_type = type_of::type_of(cx, trait_object_type);
+
+    composite_type_metadata(cx,
+                            trait_llvm_type,
+                            &trait_type_name[..],
+                            unique_type_id,
+                            &[],
+                            containing_scope,
+                            UNKNOWN_FILE_METADATA,
+                            codemap::DUMMY_SP)
+}
+
+pub fn type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
+                               t: Ty<'tcx>,
+                               usage_site_span: Span)
+                               -> DIType {
+    // Get the unique type id of this type.
+    let unique_type_id = {
+        let mut type_map = debug_context(cx).type_map.borrow_mut();
+        // First, try to find the type in TypeMap. If we have seen it before, we
+        // can exit early here.
+        match type_map.find_metadata_for_type(t) {
+            Some(metadata) => {
+                return metadata;
+            },
+            None => {
+                // The Ty is not in the TypeMap but maybe we have already seen
+                // an equivalent type (e.g. only differing in region arguments).
+                // In order to find out, generate the unique type id and look
+                // that up.
+                let unique_type_id = type_map.get_unique_type_id_of_type(cx, t);
+                match type_map.find_metadata_for_unique_id(unique_type_id) {
+                    Some(metadata) => {
+                        // There is already an equivalent type in the TypeMap.
+                        // Register this Ty as an alias in the cache and
+                        // return the cached metadata.
+                        type_map.register_type_with_metadata(cx, t, metadata);
+                        return metadata;
+                    },
+                    None => {
+                        // There really is no type metadata for this type, so
+                        // proceed by creating it.
+                        unique_type_id
+                    }
+                }
+            }
+        }
+    };
+
+    debug!("type_metadata: {:?}", t);
+
+    let sty = &t.sty;
+    let MetadataCreationResult { metadata, already_stored_in_typemap } = match *sty {
+        ty::ty_bool     |
+        ty::ty_char     |
+        ty::ty_int(_)   |
+        ty::ty_uint(_)  |
+        ty::ty_float(_) => {
+            MetadataCreationResult::new(basic_type_metadata(cx, t), false)
+        }
+        ty::ty_tup(ref elements) if elements.is_empty() => {
+            MetadataCreationResult::new(basic_type_metadata(cx, t), false)
+        }
+        ty::ty_enum(def_id, _) => {
+            prepare_enum_metadata(cx, t, def_id, unique_type_id, usage_site_span).finalize(cx)
+        }
+        ty::ty_vec(typ, len) => {
+            fixed_vec_metadata(cx, unique_type_id, typ, len.map(|x| x as u64), usage_site_span)
+        }
+        ty::ty_str => {
+            fixed_vec_metadata(cx, unique_type_id, cx.tcx().types.i8, None, usage_site_span)
+        }
+        ty::ty_trait(..) => {
+            MetadataCreationResult::new(
+                        trait_pointer_metadata(cx, t, None, unique_type_id),
+            false)
+        }
+        ty::ty_uniq(ty) | ty::ty_ptr(ty::mt{ty, ..}) | ty::ty_rptr(_, ty::mt{ty, ..}) => {
+            match ty.sty {
+                ty::ty_vec(typ, None) => {
+                    vec_slice_metadata(cx, t, typ, unique_type_id, usage_site_span)
+                }
+                ty::ty_str => {
+                    vec_slice_metadata(cx, t, cx.tcx().types.u8, unique_type_id, usage_site_span)
+                }
+                ty::ty_trait(..) => {
+                    MetadataCreationResult::new(
+                        trait_pointer_metadata(cx, ty, Some(t), unique_type_id),
+                        false)
+                }
+                _ => {
+                    let pointee_metadata = type_metadata(cx, ty, usage_site_span);
+
+                    match debug_context(cx).type_map
+                                           .borrow()
+                                           .find_metadata_for_unique_id(unique_type_id) {
+                        Some(metadata) => return metadata,
+                        None => { /* proceed normally */ }
+                    };
+
+                    MetadataCreationResult::new(pointer_type_metadata(cx, t, pointee_metadata),
+                                                false)
+                }
+            }
+        }
+        ty::ty_bare_fn(_, ref barefnty) => {
+            subroutine_type_metadata(cx, unique_type_id, &barefnty.sig, usage_site_span)
+        }
+        ty::ty_closure(def_id, substs) => {
+            let typer = NormalizingClosureTyper::new(cx.tcx());
+            let sig = typer.closure_type(def_id, substs).sig;
+            subroutine_type_metadata(cx, unique_type_id, &sig, usage_site_span)
+        }
+        ty::ty_struct(def_id, substs) => {
+            prepare_struct_metadata(cx,
+                                    t,
+                                    def_id,
+                                    substs,
+                                    unique_type_id,
+                                    usage_site_span).finalize(cx)
+        }
+        ty::ty_tup(ref elements) => {
+            prepare_tuple_metadata(cx,
+                                   t,
+                                   &elements[..],
+                                   unique_type_id,
+                                   usage_site_span).finalize(cx)
+        }
+        _ => {
+            cx.sess().bug(&format!("debuginfo: unexpected type in type_metadata: {:?}",
+                                  sty))
+        }
+    };
+
+    {
+        let mut type_map = debug_context(cx).type_map.borrow_mut();
+
+        if already_stored_in_typemap {
+            // Also make sure that we already have a TypeMap entry entry for the unique type id.
+            let metadata_for_uid = match type_map.find_metadata_for_unique_id(unique_type_id) {
+                Some(metadata) => metadata,
+                None => {
+                    let unique_type_id_str =
+                        type_map.get_unique_type_id_as_string(unique_type_id);
+                    let error_message = format!("Expected type metadata for unique \
+                                                 type id '{}' to already be in \
+                                                 the debuginfo::TypeMap but it \
+                                                 was not. (Ty = {})",
+                                                &unique_type_id_str[..],
+                                                ppaux::ty_to_string(cx.tcx(), t));
+                    cx.sess().span_bug(usage_site_span, &error_message[..]);
+                }
+            };
+
+            match type_map.find_metadata_for_type(t) {
+                Some(metadata) => {
+                    if metadata != metadata_for_uid {
+                        let unique_type_id_str =
+                            type_map.get_unique_type_id_as_string(unique_type_id);
+                        let error_message = format!("Mismatch between Ty and \
+                                                     UniqueTypeId maps in \
+                                                     debuginfo::TypeMap. \
+                                                     UniqueTypeId={}, Ty={}",
+                            &unique_type_id_str[..],
+                            ppaux::ty_to_string(cx.tcx(), t));
+                        cx.sess().span_bug(usage_site_span, &error_message[..]);
+                    }
+                }
+                None => {
+                    type_map.register_type_with_metadata(cx, t, metadata);
+                }
+            }
+        } else {
+            type_map.register_type_with_metadata(cx, t, metadata);
+            type_map.register_unique_id_with_metadata(cx, unique_type_id, metadata);
+        }
+    }
+
+    metadata
+}
+
+pub fn file_metadata(cx: &CrateContext, full_path: &str) -> DIFile {
+    match debug_context(cx).created_files.borrow().get(full_path) {
+        Some(file_metadata) => return *file_metadata,
+        None => ()
+    }
+
+    debug!("file_metadata: {}", full_path);
+
+    // FIXME (#9639): This needs to handle non-utf8 paths
+    let work_dir = cx.sess().working_dir.to_str().unwrap();
+    let file_name =
+        if full_path.starts_with(work_dir) {
+            &full_path[work_dir.len() + 1..full_path.len()]
+        } else {
+            full_path
+        };
+
+    let file_name = CString::new(file_name).unwrap();
+    let work_dir = CString::new(work_dir).unwrap();
+    let file_metadata = unsafe {
+        llvm::LLVMDIBuilderCreateFile(DIB(cx), file_name.as_ptr(),
+                                      work_dir.as_ptr())
+    };
+
+    let mut created_files = debug_context(cx).created_files.borrow_mut();
+    created_files.insert(full_path.to_string(), file_metadata);
+    return file_metadata;
+}
+
+/// Finds the scope metadata node for the given AST node.
+pub fn scope_metadata(fcx: &FunctionContext,
+                  node_id: ast::NodeId,
+                  error_reporting_span: Span)
+               -> DIScope {
+    let scope_map = &fcx.debug_context
+                        .get_ref(fcx.ccx, error_reporting_span)
+                        .scope_map;
+    match scope_map.borrow().get(&node_id).cloned() {
+        Some(scope_metadata) => scope_metadata,
+        None => {
+            let node = fcx.ccx.tcx().map.get(node_id);
+
+            fcx.ccx.sess().span_bug(error_reporting_span,
+                &format!("debuginfo: Could not find scope info for node {:?}",
+                        node));
+        }
+    }
+}
+
+fn diverging_type_metadata(cx: &CrateContext) -> DIType {
+    unsafe {
+        llvm::LLVMDIBuilderCreateBasicType(
+            DIB(cx),
+            "!\0".as_ptr() as *const _,
+            bytes_to_bits(0),
+            bytes_to_bits(0),
+            DW_ATE_unsigned)
+    }
+}
+
+fn basic_type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
+                                 t: Ty<'tcx>) -> DIType {
+
+    debug!("basic_type_metadata: {:?}", t);
+
+    let (name, encoding) = match t.sty {
+        ty::ty_tup(ref elements) if elements.is_empty() =>
+            ("()".to_string(), DW_ATE_unsigned),
+        ty::ty_bool => ("bool".to_string(), DW_ATE_boolean),
+        ty::ty_char => ("char".to_string(), DW_ATE_unsigned_char),
+        ty::ty_int(int_ty) => match int_ty {
+            ast::TyIs => ("isize".to_string(), DW_ATE_signed),
+            ast::TyI8 => ("i8".to_string(), DW_ATE_signed),
+            ast::TyI16 => ("i16".to_string(), DW_ATE_signed),
+            ast::TyI32 => ("i32".to_string(), DW_ATE_signed),
+            ast::TyI64 => ("i64".to_string(), DW_ATE_signed)
+        },
+        ty::ty_uint(uint_ty) => match uint_ty {
+            ast::TyUs => ("usize".to_string(), DW_ATE_unsigned),
+            ast::TyU8 => ("u8".to_string(), DW_ATE_unsigned),
+            ast::TyU16 => ("u16".to_string(), DW_ATE_unsigned),
+            ast::TyU32 => ("u32".to_string(), DW_ATE_unsigned),
+            ast::TyU64 => ("u64".to_string(), DW_ATE_unsigned)
+        },
+        ty::ty_float(float_ty) => match float_ty {
+            ast::TyF32 => ("f32".to_string(), DW_ATE_float),
+            ast::TyF64 => ("f64".to_string(), DW_ATE_float),
+        },
+        _ => cx.sess().bug("debuginfo::basic_type_metadata - t is invalid type")
+    };
+
+    let llvm_type = type_of::type_of(cx, t);
+    let (size, align) = size_and_align_of(cx, llvm_type);
+    let name = CString::new(name).unwrap();
+    let ty_metadata = unsafe {
+        llvm::LLVMDIBuilderCreateBasicType(
+            DIB(cx),
+            name.as_ptr(),
+            bytes_to_bits(size),
+            bytes_to_bits(align),
+            encoding)
+    };
+
+    return ty_metadata;
+}
+
+fn pointer_type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
+                                   pointer_type: Ty<'tcx>,
+                                   pointee_type_metadata: DIType)
+                                   -> DIType {
+    let pointer_llvm_type = type_of::type_of(cx, pointer_type);
+    let (pointer_size, pointer_align) = size_and_align_of(cx, pointer_llvm_type);
+    let name = compute_debuginfo_type_name(cx, pointer_type, false);
+    let name = CString::new(name).unwrap();
+    let ptr_metadata = unsafe {
+        llvm::LLVMDIBuilderCreatePointerType(
+            DIB(cx),
+            pointee_type_metadata,
+            bytes_to_bits(pointer_size),
+            bytes_to_bits(pointer_align),
+            name.as_ptr())
+    };
+    return ptr_metadata;
+}
+
+pub fn compile_unit_metadata(cx: &CrateContext) -> DIDescriptor {
+    let work_dir = &cx.sess().working_dir;
+    let compile_unit_name = match cx.sess().local_crate_source_file {
+        None => fallback_path(cx),
+        Some(ref abs_path) => {
+            if abs_path.is_relative() {
+                cx.sess().warn("debuginfo: Invalid path to crate's local root source file!");
+                fallback_path(cx)
+            } else {
+                match abs_path.relative_from(work_dir) {
+                    Some(ref p) if p.is_relative() => {
+                        if p.starts_with(Path::new("./")) {
+                            path2cstr(p)
+                        } else {
+                            path2cstr(&Path::new(".").join(p))
+                        }
+                    }
+                    _ => fallback_path(cx)
+                }
+            }
+        }
+    };
+
+    debug!("compile_unit_metadata: {:?}", compile_unit_name);
+    let producer = format!("rustc version {}",
+                           (option_env!("CFG_VERSION")).expect("CFG_VERSION"));
+
+    let compile_unit_name = compile_unit_name.as_ptr();
+    let work_dir = path2cstr(&work_dir);
+    let producer = CString::new(producer).unwrap();
+    let flags = "\0";
+    let split_name = "\0";
+    return unsafe {
+        llvm::LLVMDIBuilderCreateCompileUnit(
+            debug_context(cx).builder,
+            DW_LANG_RUST,
+            compile_unit_name,
+            work_dir.as_ptr(),
+            producer.as_ptr(),
+            cx.sess().opts.optimize != config::No,
+            flags.as_ptr() as *const _,
+            0,
+            split_name.as_ptr() as *const _)
+    };
+
+    fn fallback_path(cx: &CrateContext) -> CString {
+        CString::new(cx.link_meta().crate_name.clone()).unwrap()
+    }
+}
+
+struct MetadataCreationResult {
+    metadata: DIType,
+    already_stored_in_typemap: bool
+}
+
+impl MetadataCreationResult {
+    fn new(metadata: DIType, already_stored_in_typemap: bool) -> MetadataCreationResult {
+        MetadataCreationResult {
+            metadata: metadata,
+            already_stored_in_typemap: already_stored_in_typemap
+        }
+    }
+}
+
+enum MemberOffset {
+    FixedMemberOffset { bytes: usize },
+    // For ComputedMemberOffset, the offset is read from the llvm type definition.
+    ComputedMemberOffset
+}
+
+// Description of a type member, which can either be a regular field (as in
+// structs or tuples) or an enum variant.
+struct MemberDescription {
+    name: String,
+    llvm_type: Type,
+    type_metadata: DIType,
+    offset: MemberOffset,
+    flags: c_uint
+}
+
+// A factory for MemberDescriptions. It produces a list of member descriptions
+// for some record-like type. MemberDescriptionFactories are used to defer the
+// creation of type member descriptions in order to break cycles arising from
+// recursive type definitions.
+enum MemberDescriptionFactory<'tcx> {
+    StructMDF(StructMemberDescriptionFactory<'tcx>),
+    TupleMDF(TupleMemberDescriptionFactory<'tcx>),
+    EnumMDF(EnumMemberDescriptionFactory<'tcx>),
+    VariantMDF(VariantMemberDescriptionFactory<'tcx>)
+}
+
+impl<'tcx> MemberDescriptionFactory<'tcx> {
+    fn create_member_descriptions<'a>(&self, cx: &CrateContext<'a, 'tcx>)
+                                      -> Vec<MemberDescription> {
+        match *self {
+            StructMDF(ref this) => {
+                this.create_member_descriptions(cx)
+            }
+            TupleMDF(ref this) => {
+                this.create_member_descriptions(cx)
+            }
+            EnumMDF(ref this) => {
+                this.create_member_descriptions(cx)
+            }
+            VariantMDF(ref this) => {
+                this.create_member_descriptions(cx)
+            }
+        }
+    }
+}
+
+//=-----------------------------------------------------------------------------
+// Structs
+//=-----------------------------------------------------------------------------
+
+// Creates MemberDescriptions for the fields of a struct
+struct StructMemberDescriptionFactory<'tcx> {
+    fields: Vec<ty::field<'tcx>>,
+    is_simd: bool,
+    span: Span,
+}
+
+impl<'tcx> StructMemberDescriptionFactory<'tcx> {
+    fn create_member_descriptions<'a>(&self, cx: &CrateContext<'a, 'tcx>)
+                                      -> Vec<MemberDescription> {
+        if self.fields.is_empty() {
+            return Vec::new();
+        }
+
+        let field_size = if self.is_simd {
+            machine::llsize_of_alloc(cx, type_of::type_of(cx, self.fields[0].mt.ty)) as usize
+        } else {
+            0xdeadbeef
+        };
+
+        self.fields.iter().enumerate().map(|(i, field)| {
+            let name = if field.name == special_idents::unnamed_field.name {
+                format!("__{}", i)
+            } else {
+                token::get_name(field.name).to_string()
+            };
+
+            let offset = if self.is_simd {
+                assert!(field_size != 0xdeadbeef);
+                FixedMemberOffset { bytes: i * field_size }
+            } else {
+                ComputedMemberOffset
+            };
+
+            MemberDescription {
+                name: name,
+                llvm_type: type_of::type_of(cx, field.mt.ty),
+                type_metadata: type_metadata(cx, field.mt.ty, self.span),
+                offset: offset,
+                flags: FLAGS_NONE,
+            }
+        }).collect()
+    }
+}
+
+
+fn prepare_struct_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
+                                     struct_type: Ty<'tcx>,
+                                     def_id: ast::DefId,
+                                     substs: &subst::Substs<'tcx>,
+                                     unique_type_id: UniqueTypeId,
+                                     span: Span)
+                                     -> RecursiveTypeDescription<'tcx> {
+    let struct_name = compute_debuginfo_type_name(cx, struct_type, false);
+    let struct_llvm_type = type_of::type_of(cx, struct_type);
+
+    let (containing_scope, _) = get_namespace_and_span_for_item(cx, def_id);
+
+    let struct_metadata_stub = create_struct_stub(cx,
+                                                  struct_llvm_type,
+                                                  &struct_name[..],
+                                                  unique_type_id,
+                                                  containing_scope);
+
+    let mut fields = ty::struct_fields(cx.tcx(), def_id, substs);
+
+    // The `Ty` values returned by `ty::struct_fields` can still contain
+    // `ty_projection` variants, so normalize those away.
+    for field in &mut fields {
+        field.mt.ty = monomorphize::normalize_associated_type(cx.tcx(), &field.mt.ty);
+    }
+
+    create_and_register_recursive_type_forward_declaration(
+        cx,
+        struct_type,
+        unique_type_id,
+        struct_metadata_stub,
+        struct_llvm_type,
+        StructMDF(StructMemberDescriptionFactory {
+            fields: fields,
+            is_simd: ty::type_is_simd(cx.tcx(), struct_type),
+            span: span,
+        })
+    )
+}
+
+
+//=-----------------------------------------------------------------------------
+// Tuples
+//=-----------------------------------------------------------------------------
+
+// Creates MemberDescriptions for the fields of a tuple
+struct TupleMemberDescriptionFactory<'tcx> {
+    component_types: Vec<Ty<'tcx>>,
+    span: Span,
+}
+
+impl<'tcx> TupleMemberDescriptionFactory<'tcx> {
+    fn create_member_descriptions<'a>(&self, cx: &CrateContext<'a, 'tcx>)
+                                      -> Vec<MemberDescription> {
+        self.component_types
+            .iter()
+            .enumerate()
+            .map(|(i, &component_type)| {
+            MemberDescription {
+                name: format!("__{}", i),
+                llvm_type: type_of::type_of(cx, component_type),
+                type_metadata: type_metadata(cx, component_type, self.span),
+                offset: ComputedMemberOffset,
+                flags: FLAGS_NONE,
+            }
+        }).collect()
+    }
+}
+
+fn prepare_tuple_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
+                                    tuple_type: Ty<'tcx>,
+                                    component_types: &[Ty<'tcx>],
+                                    unique_type_id: UniqueTypeId,
+                                    span: Span)
+                                    -> RecursiveTypeDescription<'tcx> {
+    let tuple_name = compute_debuginfo_type_name(cx, tuple_type, false);
+    let tuple_llvm_type = type_of::type_of(cx, tuple_type);
+
+    create_and_register_recursive_type_forward_declaration(
+        cx,
+        tuple_type,
+        unique_type_id,
+        create_struct_stub(cx,
+                           tuple_llvm_type,
+                           &tuple_name[..],
+                           unique_type_id,
+                           UNKNOWN_SCOPE_METADATA),
+        tuple_llvm_type,
+        TupleMDF(TupleMemberDescriptionFactory {
+            component_types: component_types.to_vec(),
+            span: span,
+        })
+    )
+}
+
+
+//=-----------------------------------------------------------------------------
+// Enums
+//=-----------------------------------------------------------------------------
+
+// Describes the members of an enum value: An enum is described as a union of
+// structs in DWARF. This MemberDescriptionFactory provides the description for
+// the members of this union; so for every variant of the given enum, this
+// factory will produce one MemberDescription (all with no name and a fixed
+// offset of zero bytes).
+struct EnumMemberDescriptionFactory<'tcx> {
+    enum_type: Ty<'tcx>,
+    type_rep: Rc<adt::Repr<'tcx>>,
+    variants: Rc<Vec<Rc<ty::VariantInfo<'tcx>>>>,
+    discriminant_type_metadata: Option<DIType>,
+    containing_scope: DIScope,
+    file_metadata: DIFile,
+    span: Span,
+}
+
+impl<'tcx> EnumMemberDescriptionFactory<'tcx> {
+    fn create_member_descriptions<'a>(&self, cx: &CrateContext<'a, 'tcx>)
+                                      -> Vec<MemberDescription> {
+        match *self.type_rep {
+            adt::General(_, ref struct_defs, _) => {
+                let discriminant_info = RegularDiscriminant(self.discriminant_type_metadata
+                    .expect(""));
+
+                struct_defs
+                    .iter()
+                    .enumerate()
+                    .map(|(i, struct_def)| {
+                        let (variant_type_metadata,
+                             variant_llvm_type,
+                             member_desc_factory) =
+                            describe_enum_variant(cx,
+                                                  self.enum_type,
+                                                  struct_def,
+                                                  &*(*self.variants)[i],
+                                                  discriminant_info,
+                                                  self.containing_scope,
+                                                  self.span);
+
+                        let member_descriptions = member_desc_factory
+                            .create_member_descriptions(cx);
+
+                        set_members_of_composite_type(cx,
+                                                      variant_type_metadata,
+                                                      variant_llvm_type,
+                                                      &member_descriptions[..]);
+                        MemberDescription {
+                            name: "".to_string(),
+                            llvm_type: variant_llvm_type,
+                            type_metadata: variant_type_metadata,
+                            offset: FixedMemberOffset { bytes: 0 },
+                            flags: FLAGS_NONE
+                        }
+                    }).collect()
+            },
+            adt::Univariant(ref struct_def, _) => {
+                assert!(self.variants.len() <= 1);
+
+                if self.variants.is_empty() {
+                    vec![]
+                } else {
+                    let (variant_type_metadata,
+                         variant_llvm_type,
+                         member_description_factory) =
+                        describe_enum_variant(cx,
+                                              self.enum_type,
+                                              struct_def,
+                                              &*(*self.variants)[0],
+                                              NoDiscriminant,
+                                              self.containing_scope,
+                                              self.span);
+
+                    let member_descriptions =
+                        member_description_factory.create_member_descriptions(cx);
+
+                    set_members_of_composite_type(cx,
+                                                  variant_type_metadata,
+                                                  variant_llvm_type,
+                                                  &member_descriptions[..]);
+                    vec![
+                        MemberDescription {
+                            name: "".to_string(),
+                            llvm_type: variant_llvm_type,
+                            type_metadata: variant_type_metadata,
+                            offset: FixedMemberOffset { bytes: 0 },
+                            flags: FLAGS_NONE
+                        }
+                    ]
+                }
+            }
+            adt::RawNullablePointer { nndiscr: non_null_variant_index, nnty, .. } => {
+                // As far as debuginfo is concerned, the pointer this enum
+                // represents is still wrapped in a struct. This is to make the
+                // DWARF representation of enums uniform.
+
+                // First create a description of the artificial wrapper struct:
+                let non_null_variant = &(*self.variants)[non_null_variant_index as usize];
+                let non_null_variant_name = token::get_name(non_null_variant.name);
+
+                // The llvm type and metadata of the pointer
+                let non_null_llvm_type = type_of::type_of(cx, nnty);
+                let non_null_type_metadata = type_metadata(cx, nnty, self.span);
+
+                // The type of the artificial struct wrapping the pointer
+                let artificial_struct_llvm_type = Type::struct_(cx,
+                                                                &[non_null_llvm_type],
+                                                                false);
+
+                // For the metadata of the wrapper struct, we need to create a
+                // MemberDescription of the struct's single field.
+                let sole_struct_member_description = MemberDescription {
+                    name: match non_null_variant.arg_names {
+                        Some(ref names) => token::get_name(names[0]).to_string(),
+                        None => "__0".to_string()
+                    },
+                    llvm_type: non_null_llvm_type,
+                    type_metadata: non_null_type_metadata,
+                    offset: FixedMemberOffset { bytes: 0 },
+                    flags: FLAGS_NONE
+                };
+
+                let unique_type_id = debug_context(cx).type_map
+                                                      .borrow_mut()
+                                                      .get_unique_type_id_of_enum_variant(
+                                                          cx,
+                                                          self.enum_type,
+                                                          &non_null_variant_name);
+
+                // Now we can create the metadata of the artificial struct
+                let artificial_struct_metadata =
+                    composite_type_metadata(cx,
+                                            artificial_struct_llvm_type,
+                                            &non_null_variant_name,
+                                            unique_type_id,
+                                            &[sole_struct_member_description],
+                                            self.containing_scope,
+                                            self.file_metadata,
+                                            codemap::DUMMY_SP);
+
+                // Encode the information about the null variant in the union
+                // member's name.
+                let null_variant_index = (1 - non_null_variant_index) as usize;
+                let null_variant_name = token::get_name((*self.variants)[null_variant_index].name);
+                let union_member_name = format!("RUST$ENCODED$ENUM${}${}",
+                                                0,
+                                                null_variant_name);
+
+                // Finally create the (singleton) list of descriptions of union
+                // members.
+                vec![
+                    MemberDescription {
+                        name: union_member_name,
+                        llvm_type: artificial_struct_llvm_type,
+                        type_metadata: artificial_struct_metadata,
+                        offset: FixedMemberOffset { bytes: 0 },
+                        flags: FLAGS_NONE
+                    }
+                ]
+            },
+            adt::StructWrappedNullablePointer { nonnull: ref struct_def,
+                                                nndiscr,
+                                                ref discrfield, ..} => {
+                // Create a description of the non-null variant
+                let (variant_type_metadata, variant_llvm_type, member_description_factory) =
+                    describe_enum_variant(cx,
+                                          self.enum_type,
+                                          struct_def,
+                                          &*(*self.variants)[nndiscr as usize],
+                                          OptimizedDiscriminant,
+                                          self.containing_scope,
+                                          self.span);
+
+                let variant_member_descriptions =
+                    member_description_factory.create_member_descriptions(cx);
+
+                set_members_of_composite_type(cx,
+                                              variant_type_metadata,
+                                              variant_llvm_type,
+                                              &variant_member_descriptions[..]);
+
+                // Encode the information about the null variant in the union
+                // member's name.
+                let null_variant_index = (1 - nndiscr) as usize;
+                let null_variant_name = token::get_name((*self.variants)[null_variant_index].name);
+                let discrfield = discrfield.iter()
+                                           .skip(1)
+                                           .map(|x| x.to_string())
+                                           .collect::<Vec<_>>().connect("$");
+                let union_member_name = format!("RUST$ENCODED$ENUM${}${}",
+                                                discrfield,
+                                                null_variant_name);
+
+                // Create the (singleton) list of descriptions of union members.
+                vec![
+                    MemberDescription {
+                        name: union_member_name,
+                        llvm_type: variant_llvm_type,
+                        type_metadata: variant_type_metadata,
+                        offset: FixedMemberOffset { bytes: 0 },
+                        flags: FLAGS_NONE
+                    }
+                ]
+            },
+            adt::CEnum(..) => cx.sess().span_bug(self.span, "This should be unreachable.")
+        }
+    }
+}
+
+// Creates MemberDescriptions for the fields of a single enum variant.
+struct VariantMemberDescriptionFactory<'tcx> {
+    args: Vec<(String, Ty<'tcx>)>,
+    discriminant_type_metadata: Option<DIType>,
+    span: Span,
+}
+
+impl<'tcx> VariantMemberDescriptionFactory<'tcx> {
+    fn create_member_descriptions<'a>(&self, cx: &CrateContext<'a, 'tcx>)
+                                      -> Vec<MemberDescription> {
+        self.args.iter().enumerate().map(|(i, &(ref name, ty))| {
+            MemberDescription {
+                name: name.to_string(),
+                llvm_type: type_of::type_of(cx, ty),
+                type_metadata: match self.discriminant_type_metadata {
+                    Some(metadata) if i == 0 => metadata,
+                    _ => type_metadata(cx, ty, self.span)
+                },
+                offset: ComputedMemberOffset,
+                flags: FLAGS_NONE
+            }
+        }).collect()
+    }
+}
+
+#[derive(Copy, Clone)]
+enum EnumDiscriminantInfo {
+    RegularDiscriminant(DIType),
+    OptimizedDiscriminant,
+    NoDiscriminant
+}
+
+// Returns a tuple of (1) type_metadata_stub of the variant, (2) the llvm_type
+// of the variant, and (3) a MemberDescriptionFactory for producing the
+// descriptions of the fields of the variant. This is a rudimentary version of a
+// full RecursiveTypeDescription.
+fn describe_enum_variant<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
+                                   enum_type: Ty<'tcx>,
+                                   struct_def: &adt::Struct<'tcx>,
+                                   variant_info: &ty::VariantInfo<'tcx>,
+                                   discriminant_info: EnumDiscriminantInfo,
+                                   containing_scope: DIScope,
+                                   span: Span)
+                                   -> (DICompositeType, Type, MemberDescriptionFactory<'tcx>) {
+    let variant_llvm_type =
+        Type::struct_(cx, &struct_def.fields
+                                    .iter()
+                                    .map(|&t| type_of::type_of(cx, t))
+                                    .collect::<Vec<_>>()
+                                    ,
+                      struct_def.packed);
+    // Could do some consistency checks here: size, align, field count, discr type
+
+    let variant_name = token::get_name(variant_info.name);
+    let variant_name = &variant_name;
+    let unique_type_id = debug_context(cx).type_map
+                                          .borrow_mut()
+                                          .get_unique_type_id_of_enum_variant(
+                                              cx,
+                                              enum_type,
+                                              variant_name);
+
+    let metadata_stub = create_struct_stub(cx,
+                                           variant_llvm_type,
+                                           variant_name,
+                                           unique_type_id,
+                                           containing_scope);
+
+    // Get the argument names from the enum variant info
+    let mut arg_names: Vec<_> = match variant_info.arg_names {
+        Some(ref names) => {
+            names.iter()
+                 .map(|&name| token::get_name(name).to_string())
+                 .collect()
+        }
+        None => {
+            variant_info.args
+                        .iter()
+                        .enumerate()
+                        .map(|(i, _)| format!("__{}", i))
+                        .collect()
+        }
+    };
+
+    // If this is not a univariant enum, there is also the discriminant field.
+    match discriminant_info {
+        RegularDiscriminant(_) => arg_names.insert(0, "RUST$ENUM$DISR".to_string()),
+        _ => { /* do nothing */ }
+    };
+
+    // Build an array of (field name, field type) pairs to be captured in the factory closure.
+    let args: Vec<(String, Ty)> = arg_names.iter()
+        .zip(struct_def.fields.iter())
+        .map(|(s, &t)| (s.to_string(), t))
+        .collect();
+
+    let member_description_factory =
+        VariantMDF(VariantMemberDescriptionFactory {
+            args: args,
+            discriminant_type_metadata: match discriminant_info {
+                RegularDiscriminant(discriminant_type_metadata) => {
+                    Some(discriminant_type_metadata)
+                }
+                _ => None
+            },
+            span: span,
+        });
+
+    (metadata_stub, variant_llvm_type, member_description_factory)
+}
+
+fn prepare_enum_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
+                                   enum_type: Ty<'tcx>,
+                                   enum_def_id: ast::DefId,
+                                   unique_type_id: UniqueTypeId,
+                                   span: Span)
+                                   -> RecursiveTypeDescription<'tcx> {
+    let enum_name = compute_debuginfo_type_name(cx, enum_type, false);
+
+    let (containing_scope, definition_span) = get_namespace_and_span_for_item(cx, enum_def_id);
+    let loc = span_start(cx, definition_span);
+    let file_metadata = file_metadata(cx, &loc.file.name);
+
+    let variants = ty::enum_variants(cx.tcx(), enum_def_id);
+
+    let enumerators_metadata: Vec<DIDescriptor> = variants
+        .iter()
+        .map(|v| {
+            let token = token::get_name(v.name);
+            let name = CString::new(token.as_bytes()).unwrap();
+            unsafe {
+                llvm::LLVMDIBuilderCreateEnumerator(
+                    DIB(cx),
+                    name.as_ptr(),
+                    v.disr_val as u64)
+            }
+        })
+        .collect();
+
+    let discriminant_type_metadata = |inttype| {
+        // We can reuse the type of the discriminant for all monomorphized
+        // instances of an enum because it doesn't depend on any type
+        // parameters. The def_id, uniquely identifying the enum's polytype acts
+        // as key in this cache.
+        let cached_discriminant_type_metadata = debug_context(cx).created_enum_disr_types
+                                                                 .borrow()
+                                                                 .get(&enum_def_id).cloned();
+        match cached_discriminant_type_metadata {
+            Some(discriminant_type_metadata) => discriminant_type_metadata,
+            None => {
+                let discriminant_llvm_type = adt::ll_inttype(cx, inttype);
+                let (discriminant_size, discriminant_align) =
+                    size_and_align_of(cx, discriminant_llvm_type);
+                let discriminant_base_type_metadata =
+                    type_metadata(cx,
+                                  adt::ty_of_inttype(cx.tcx(), inttype),
+                                  codemap::DUMMY_SP);
+                let discriminant_name = get_enum_discriminant_name(cx, enum_def_id);
+
+                let name = CString::new(discriminant_name.as_bytes()).unwrap();
+                let discriminant_type_metadata = unsafe {
+                    llvm::LLVMDIBuilderCreateEnumerationType(
+                        DIB(cx),
+                        containing_scope,
+                        name.as_ptr(),
+                        UNKNOWN_FILE_METADATA,
+                        UNKNOWN_LINE_NUMBER,
+                        bytes_to_bits(discriminant_size),
+                        bytes_to_bits(discriminant_align),
+                        create_DIArray(DIB(cx), &enumerators_metadata),
+                        discriminant_base_type_metadata)
+                };
+
+                debug_context(cx).created_enum_disr_types
+                                 .borrow_mut()
+                                 .insert(enum_def_id, discriminant_type_metadata);
+
+                discriminant_type_metadata
+            }
+        }
+    };
+
+    let type_rep = adt::represent_type(cx, enum_type);
+
+    let discriminant_type_metadata = match *type_rep {
+        adt::CEnum(inttype, _, _) => {
+            return FinalMetadata(discriminant_type_metadata(inttype))
+        },
+        adt::RawNullablePointer { .. }           |
+        adt::StructWrappedNullablePointer { .. } |
+        adt::Univariant(..)                      => None,
+        adt::General(inttype, _, _) => Some(discriminant_type_metadata(inttype)),
+    };
+
+    let enum_llvm_type = type_of::type_of(cx, enum_type);
+    let (enum_type_size, enum_type_align) = size_and_align_of(cx, enum_llvm_type);
+
+    let unique_type_id_str = debug_context(cx)
+                             .type_map
+                             .borrow()
+                             .get_unique_type_id_as_string(unique_type_id);
+
+    let enum_name = CString::new(enum_name).unwrap();
+    let unique_type_id_str = CString::new(unique_type_id_str.as_bytes()).unwrap();
+    let enum_metadata = unsafe {
+        llvm::LLVMDIBuilderCreateUnionType(
+        DIB(cx),
+        containing_scope,
+        enum_name.as_ptr(),
+        UNKNOWN_FILE_METADATA,
+        UNKNOWN_LINE_NUMBER,
+        bytes_to_bits(enum_type_size),
+        bytes_to_bits(enum_type_align),
+        0, // Flags
+        ptr::null_mut(),
+        0, // RuntimeLang
+        unique_type_id_str.as_ptr())
+    };
+
+    return create_and_register_recursive_type_forward_declaration(
+        cx,
+        enum_type,
+        unique_type_id,
+        enum_metadata,
+        enum_llvm_type,
+        EnumMDF(EnumMemberDescriptionFactory {
+            enum_type: enum_type,
+            type_rep: type_rep.clone(),
+            variants: variants,
+            discriminant_type_metadata: discriminant_type_metadata,
+            containing_scope: containing_scope,
+            file_metadata: file_metadata,
+            span: span,
+        }),
+    );
+
+    fn get_enum_discriminant_name(cx: &CrateContext,
+                                  def_id: ast::DefId)
+                                  -> token::InternedString {
+        let name = if def_id.krate == ast::LOCAL_CRATE {
+            cx.tcx().map.get_path_elem(def_id.node).name()
+        } else {
+            csearch::get_item_path(cx.tcx(), def_id).last().unwrap().name()
+        };
+
+        token::get_name(name)
+    }
+}
+
+/// Creates debug information for a composite type, that is, anything that
+/// results in a LLVM struct.
+///
+/// Examples of Rust types to use this are: structs, tuples, boxes, vecs, and enums.
+fn composite_type_metadata(cx: &CrateContext,
+                           composite_llvm_type: Type,
+                           composite_type_name: &str,
+                           composite_type_unique_id: UniqueTypeId,
+                           member_descriptions: &[MemberDescription],
+                           containing_scope: DIScope,
+
+                           // Ignore source location information as long as it
+                           // can't be reconstructed for non-local crates.
+                           _file_metadata: DIFile,
+                           _definition_span: Span)
+                           -> DICompositeType {
+    // Create the (empty) struct metadata node ...
+    let composite_type_metadata = create_struct_stub(cx,
+                                                     composite_llvm_type,
+                                                     composite_type_name,
+                                                     composite_type_unique_id,
+                                                     containing_scope);
+    // ... and immediately create and add the member descriptions.
+    set_members_of_composite_type(cx,
+                                  composite_type_metadata,
+                                  composite_llvm_type,
+                                  member_descriptions);
+
+    return composite_type_metadata;
+}
+
+fn set_members_of_composite_type(cx: &CrateContext,
+                                 composite_type_metadata: DICompositeType,
+                                 composite_llvm_type: Type,
+                                 member_descriptions: &[MemberDescription]) {
+    // In some rare cases LLVM metadata uniquing would lead to an existing type
+    // description being used instead of a new one created in
+    // create_struct_stub. This would cause a hard to trace assertion in
+    // DICompositeType::SetTypeArray(). The following check makes sure that we
+    // get a better error message if this should happen again due to some
+    // regression.
+    {
+        let mut composite_types_completed =
+            debug_context(cx).composite_types_completed.borrow_mut();
+        if composite_types_completed.contains(&composite_type_metadata) {
+            cx.sess().bug("debuginfo::set_members_of_composite_type() - \
+                           Already completed forward declaration re-encountered.");
+        } else {
+            composite_types_completed.insert(composite_type_metadata);
+        }
+    }
+
+    let member_metadata: Vec<DIDescriptor> = member_descriptions
+        .iter()
+        .enumerate()
+        .map(|(i, member_description)| {
+            let (member_size, member_align) = size_and_align_of(cx, member_description.llvm_type);
+            let member_offset = match member_description.offset {
+                FixedMemberOffset { bytes } => bytes as u64,
+                ComputedMemberOffset => machine::llelement_offset(cx, composite_llvm_type, i)
+            };
+
+            let member_name = member_description.name.as_bytes();
+            let member_name = CString::new(member_name).unwrap();
+            unsafe {
+                llvm::LLVMDIBuilderCreateMemberType(
+                    DIB(cx),
+                    composite_type_metadata,
+                    member_name.as_ptr(),
+                    UNKNOWN_FILE_METADATA,
+                    UNKNOWN_LINE_NUMBER,
+                    bytes_to_bits(member_size),
+                    bytes_to_bits(member_align),
+                    bytes_to_bits(member_offset),
+                    member_description.flags,
+                    member_description.type_metadata)
+            }
+        })
+        .collect();
+
+    unsafe {
+        let type_array = create_DIArray(DIB(cx), &member_metadata[..]);
+        llvm::LLVMDICompositeTypeSetTypeArray(DIB(cx), composite_type_metadata, type_array);
+    }
+}
+
+// A convenience wrapper around LLVMDIBuilderCreateStructType(). Does not do any
+// caching, does not add any fields to the struct. This can be done later with
+// set_members_of_composite_type().
+fn create_struct_stub(cx: &CrateContext,
+                      struct_llvm_type: Type,
+                      struct_type_name: &str,
+                      unique_type_id: UniqueTypeId,
+                      containing_scope: DIScope)
+                   -> DICompositeType {
+    let (struct_size, struct_align) = size_and_align_of(cx, struct_llvm_type);
+
+    let unique_type_id_str = debug_context(cx).type_map
+                                              .borrow()
+                                              .get_unique_type_id_as_string(unique_type_id);
+    let name = CString::new(struct_type_name).unwrap();
+    let unique_type_id = CString::new(unique_type_id_str.as_bytes()).unwrap();
+    let metadata_stub = unsafe {
+        // LLVMDIBuilderCreateStructType() wants an empty array. A null
+        // pointer will lead to hard to trace and debug LLVM assertions
+        // later on in llvm/lib/IR/Value.cpp.
+        let empty_array = create_DIArray(DIB(cx), &[]);
+
+        llvm::LLVMDIBuilderCreateStructType(
+            DIB(cx),
+            containing_scope,
+            name.as_ptr(),
+            UNKNOWN_FILE_METADATA,
+            UNKNOWN_LINE_NUMBER,
+            bytes_to_bits(struct_size),
+            bytes_to_bits(struct_align),
+            0,
+            ptr::null_mut(),
+            empty_array,
+            0,
+            ptr::null_mut(),
+            unique_type_id.as_ptr())
+    };
+
+    return metadata_stub;
+}
+
+/// Creates debug information for the given global variable.
+///
+/// Adds the created metadata nodes directly to the crate's IR.
+pub fn create_global_var_metadata(cx: &CrateContext,
+                                  node_id: ast::NodeId,
+                                  global: ValueRef) {
+    if cx.dbg_cx().is_none() {
+        return;
+    }
+
+    // Don't create debuginfo for globals inlined from other crates. The other
+    // crate should already contain debuginfo for it. More importantly, the
+    // global might not even exist in un-inlined form anywhere which would lead
+    // to a linker errors.
+    if cx.external_srcs().borrow().contains_key(&node_id) {
+        return;
+    }
+
+    let var_item = cx.tcx().map.get(node_id);
+
+    let (name, span) = match var_item {
+        ast_map::NodeItem(item) => {
+            match item.node {
+                ast::ItemStatic(..) => (item.ident.name, item.span),
+                ast::ItemConst(..) => (item.ident.name, item.span),
+                _ => {
+                    cx.sess()
+                      .span_bug(item.span,
+                                &format!("debuginfo::\
+                                         create_global_var_metadata() -
+                                         Captured var-id refers to \
+                                         unexpected ast_item variant: {:?}",
+                                        var_item))
+                }
+            }
+        },
+        _ => cx.sess().bug(&format!("debuginfo::create_global_var_metadata() \
+                                    - Captured var-id refers to unexpected \
+                                    ast_map variant: {:?}",
+                                   var_item))
+    };
+
+    let (file_metadata, line_number) = if span != codemap::DUMMY_SP {
+        let loc = span_start(cx, span);
+        (file_metadata(cx, &loc.file.name), loc.line as c_uint)
+    } else {
+        (UNKNOWN_FILE_METADATA, UNKNOWN_LINE_NUMBER)
+    };
+
+    let is_local_to_unit = is_node_local_to_unit(cx, node_id);
+    let variable_type = ty::node_id_to_type(cx.tcx(), node_id);
+    let type_metadata = type_metadata(cx, variable_type, span);
+    let namespace_node = namespace_for_item(cx, ast_util::local_def(node_id));
+    let var_name = token::get_name(name).to_string();
+    let linkage_name =
+        namespace_node.mangled_name_of_contained_item(&var_name[..]);
+    let var_scope = namespace_node.scope;
+
+    let var_name = CString::new(var_name).unwrap();
+    let linkage_name = CString::new(linkage_name).unwrap();
+    unsafe {
+        llvm::LLVMDIBuilderCreateStaticVariable(DIB(cx),
+                                                var_scope,
+                                                var_name.as_ptr(),
+                                                linkage_name.as_ptr(),
+                                                file_metadata,
+                                                line_number,
+                                                type_metadata,
+                                                is_local_to_unit,
+                                                global,
+                                                ptr::null_mut());
+    }
+}
+
+/// Creates debug information for the given local variable.
+///
+/// This function assumes that there's a datum for each pattern component of the
+/// local in `bcx.fcx.lllocals`.
+/// Adds the created metadata nodes directly to the crate's IR.
+pub fn create_local_var_metadata(bcx: Block, local: &ast::Local) {
+    if bcx.unreachable.get() ||
+       fn_should_be_ignored(bcx.fcx) ||
+       bcx.sess().opts.debuginfo != FullDebugInfo  {
+        return;
+    }
+
+    let cx = bcx.ccx();
+    let def_map = &cx.tcx().def_map;
+    let locals = bcx.fcx.lllocals.borrow();
+
+    pat_util::pat_bindings(def_map, &*local.pat, |_, node_id, span, var_ident| {
+        let datum = match locals.get(&node_id) {
+            Some(datum) => datum,
+            None => {
+                bcx.sess().span_bug(span,
+                    &format!("no entry in lllocals table for {}",
+                            node_id));
+            }
+        };
+
+        if unsafe { llvm::LLVMIsAAllocaInst(datum.val) } == ptr::null_mut() {
+            cx.sess().span_bug(span, "debuginfo::create_local_var_metadata() - \
+                                      Referenced variable location is not an alloca!");
+        }
+
+        let scope_metadata = scope_metadata(bcx.fcx, node_id, span);
+
+        declare_local(bcx,
+                      var_ident.node.name,
+                      datum.ty,
+                      scope_metadata,
+                      VariableAccess::DirectVariable { alloca: datum.val },
+                      VariableKind::LocalVariable,
+                      span);
+    })
+}
+
+/// Creates debug information for a variable captured in a closure.
+///
+/// Adds the created metadata nodes directly to the crate's IR.
+pub fn create_captured_var_metadata<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
+                                                node_id: ast::NodeId,
+                                                env_pointer: ValueRef,
+                                                env_index: usize,
+                                                captured_by_ref: bool,
+                                                span: Span) {
+    if bcx.unreachable.get() ||
+       fn_should_be_ignored(bcx.fcx) ||
+       bcx.sess().opts.debuginfo != FullDebugInfo {
+        return;
+    }
+
+    let cx = bcx.ccx();
+
+    let ast_item = cx.tcx().map.find(node_id);
+
+    let variable_name = match ast_item {
+        None => {
+            cx.sess().span_bug(span, "debuginfo::create_captured_var_metadata: node not found");
+        }
+        Some(ast_map::NodeLocal(pat)) | Some(ast_map::NodeArg(pat)) => {
+            match pat.node {
+                ast::PatIdent(_, ref path1, _) => {
+                    path1.node.name
+                }
+                _ => {
+                    cx.sess()
+                      .span_bug(span,
+                                &format!(
+                                "debuginfo::create_captured_var_metadata() - \
+                                 Captured var-id refers to unexpected \
+                                 ast_map variant: {:?}",
+                                 ast_item));
+                }
+            }
+        }
+        _ => {
+            cx.sess()
+              .span_bug(span,
+                        &format!("debuginfo::create_captured_var_metadata() - \
+                                 Captured var-id refers to unexpected \
+                                 ast_map variant: {:?}",
+                                ast_item));
+        }
+    };
+
+    let variable_type = common::node_id_type(bcx, node_id);
+    let scope_metadata = bcx.fcx.debug_context.get_ref(cx, span).fn_metadata;
+
+    // env_pointer is the alloca containing the pointer to the environment,
+    // so it's type is **EnvironmentType. In order to find out the type of
+    // the environment we have to "dereference" two times.
+    let llvm_env_data_type = common::val_ty(env_pointer).element_type()
+                                                        .element_type();
+    let byte_offset_of_var_in_env = machine::llelement_offset(cx,
+                                                              llvm_env_data_type,
+                                                              env_index);
+
+    let address_operations = unsafe {
+        [llvm::LLVMDIBuilderCreateOpDeref(),
+         llvm::LLVMDIBuilderCreateOpPlus(),
+         byte_offset_of_var_in_env as i64,
+         llvm::LLVMDIBuilderCreateOpDeref()]
+    };
+
+    let address_op_count = if captured_by_ref {
+        address_operations.len()
+    } else {
+        address_operations.len() - 1
+    };
+
+    let variable_access = VariableAccess::IndirectVariable {
+        alloca: env_pointer,
+        address_operations: &address_operations[..address_op_count]
+    };
+
+    declare_local(bcx,
+                  variable_name,
+                  variable_type,
+                  scope_metadata,
+                  variable_access,
+                  VariableKind::CapturedVariable,
+                  span);
+}
+
+/// Creates debug information for a local variable introduced in the head of a
+/// match-statement arm.
+///
+/// Adds the created metadata nodes directly to the crate's IR.
+pub fn create_match_binding_metadata<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
+                                                 variable_name: ast::Name,
+                                                 binding: BindingInfo<'tcx>) {
+    if bcx.unreachable.get() ||
+       fn_should_be_ignored(bcx.fcx) ||
+       bcx.sess().opts.debuginfo != FullDebugInfo {
+        return;
+    }
+
+    let scope_metadata = scope_metadata(bcx.fcx, binding.id, binding.span);
+    let aops = unsafe {
+        [llvm::LLVMDIBuilderCreateOpDeref()]
+    };
+    // Regardless of the actual type (`T`) we're always passed the stack slot
+    // (alloca) for the binding. For ByRef bindings that's a `T*` but for ByMove
+    // bindings we actually have `T**`. So to get the actual variable we need to
+    // dereference once more. For ByCopy we just use the stack slot we created
+    // for the binding.
+    let var_access = match binding.trmode {
+        TrByCopy(llbinding) => VariableAccess::DirectVariable {
+            alloca: llbinding
+        },
+        TrByMove => VariableAccess::IndirectVariable {
+            alloca: binding.llmatch,
+            address_operations: &aops
+        },
+        TrByRef => VariableAccess::DirectVariable {
+            alloca: binding.llmatch
+        }
+    };
+
+    declare_local(bcx,
+                  variable_name,
+                  binding.ty,
+                  scope_metadata,
+                  var_access,
+                  VariableKind::LocalVariable,
+                  binding.span);
+}
+
+/// Creates debug information for the given function argument.
+///
+/// This function assumes that there's a datum for each pattern component of the
+/// argument in `bcx.fcx.lllocals`.
+/// Adds the created metadata nodes directly to the crate's IR.
+pub fn create_argument_metadata(bcx: Block, arg: &ast::Arg) {
+    if bcx.unreachable.get() ||
+       fn_should_be_ignored(bcx.fcx) ||
+       bcx.sess().opts.debuginfo != FullDebugInfo {
+        return;
+    }
+
+    let def_map = &bcx.tcx().def_map;
+    let scope_metadata = bcx
+                         .fcx
+                         .debug_context
+                         .get_ref(bcx.ccx(), arg.pat.span)
+                         .fn_metadata;
+    let locals = bcx.fcx.lllocals.borrow();
+
+    pat_util::pat_bindings(def_map, &*arg.pat, |_, node_id, span, var_ident| {
+        let datum = match locals.get(&node_id) {
+            Some(v) => v,
+            None => {
+                bcx.sess().span_bug(span,
+                    &format!("no entry in lllocals table for {}",
+                            node_id));
+            }
+        };
+
+        if unsafe { llvm::LLVMIsAAllocaInst(datum.val) } == ptr::null_mut() {
+            bcx.sess().span_bug(span, "debuginfo::create_argument_metadata() - \
+                                       Referenced variable location is not an alloca!");
+        }
+
+        let argument_index = {
+            let counter = &bcx
+                          .fcx
+                          .debug_context
+                          .get_ref(bcx.ccx(), span)
+                          .argument_counter;
+            let argument_index = counter.get();
+            counter.set(argument_index + 1);
+            argument_index
+        };
+
+        declare_local(bcx,
+                      var_ident.node.name,
+                      datum.ty,
+                      scope_metadata,
+                      VariableAccess::DirectVariable { alloca: datum.val },
+                      VariableKind::ArgumentVariable(argument_index),
+                      span);
+    })
+}
diff --git a/src/librustc_trans/trans/debuginfo/mod.rs b/src/librustc_trans/trans/debuginfo/mod.rs
new file mode 100644 (file)
index 0000000..e4312b6
--- /dev/null
@@ -0,0 +1,651 @@
+// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// See doc.rs for documentation.
+mod doc;
+
+use self::VariableAccess::*;
+use self::VariableKind::*;
+
+use self::utils::{DIB, span_start, assert_type_for_node_id, contains_nodebug_attribute,
+                  create_DIArray, is_node_local_to_unit};
+use self::namespace::{namespace_for_item, NamespaceTreeNode};
+use self::type_names::compute_debuginfo_type_name;
+use self::metadata::{type_metadata, file_metadata, scope_metadata, TypeMap, compile_unit_metadata};
+use self::source_loc::InternalDebugLocation;
+
+use llvm;
+use llvm::{ModuleRef, ContextRef, ValueRef};
+use llvm::debuginfo::{DIFile, DIType, DIScope, DIBuilderRef, DISubprogram, DIArray,
+                      DIDescriptor, FlagPrototyped};
+use middle::subst::{self, Substs};
+use trans::common::{NodeIdAndSpan, CrateContext, FunctionContext, Block};
+use trans;
+use trans::monomorphize;
+use middle::ty::{self, Ty, ClosureTyper};
+use session::config::{self, FullDebugInfo, LimitedDebugInfo, NoDebugInfo};
+use util::nodemap::{DefIdMap, NodeMap, FnvHashMap, FnvHashSet};
+
+use libc::c_uint;
+use std::cell::{Cell, RefCell};
+use std::ffi::CString;
+use std::ptr;
+use std::rc::Rc;
+use syntax::codemap::{Span, Pos};
+use syntax::{ast, codemap, ast_util, ast_map};
+use syntax::parse::token::{self, special_idents};
+
+pub mod gdb;
+mod utils;
+mod namespace;
+mod type_names;
+mod metadata;
+mod create_scope_map;
+mod source_loc;
+
+pub use self::source_loc::set_source_location;
+pub use self::source_loc::clear_source_location;
+pub use self::source_loc::start_emitting_source_locations;
+pub use self::source_loc::get_cleanup_debug_loc_for_ast_node;
+pub use self::source_loc::with_source_location_override;
+pub use self::metadata::create_match_binding_metadata;
+pub use self::metadata::create_argument_metadata;
+pub use self::metadata::create_captured_var_metadata;
+pub use self::metadata::create_global_var_metadata;
+pub use self::metadata::create_local_var_metadata;
+
+#[allow(non_upper_case_globals)]
+const DW_TAG_auto_variable: c_uint = 0x100;
+#[allow(non_upper_case_globals)]
+const DW_TAG_arg_variable: c_uint = 0x101;
+
+/// A context object for maintaining all state needed by the debuginfo module.
+pub struct CrateDebugContext<'tcx> {
+    llcontext: ContextRef,
+    builder: DIBuilderRef,
+    current_debug_location: Cell<InternalDebugLocation>,
+    created_files: RefCell<FnvHashMap<String, DIFile>>,
+    created_enum_disr_types: RefCell<DefIdMap<DIType>>,
+
+    type_map: RefCell<TypeMap<'tcx>>,
+    namespace_map: RefCell<FnvHashMap<Vec<ast::Name>, Rc<NamespaceTreeNode>>>,
+
+    // This collection is used to assert that composite types (structs, enums,
+    // ...) have their members only set once:
+    composite_types_completed: RefCell<FnvHashSet<DIType>>,
+}
+
+impl<'tcx> CrateDebugContext<'tcx> {
+    pub fn new(llmod: ModuleRef) -> CrateDebugContext<'tcx> {
+        debug!("CrateDebugContext::new");
+        let builder = unsafe { llvm::LLVMDIBuilderCreate(llmod) };
+        // DIBuilder inherits context from the module, so we'd better use the same one
+        let llcontext = unsafe { llvm::LLVMGetModuleContext(llmod) };
+        return CrateDebugContext {
+            llcontext: llcontext,
+            builder: builder,
+            current_debug_location: Cell::new(InternalDebugLocation::UnknownLocation),
+            created_files: RefCell::new(FnvHashMap()),
+            created_enum_disr_types: RefCell::new(DefIdMap()),
+            type_map: RefCell::new(TypeMap::new()),
+            namespace_map: RefCell::new(FnvHashMap()),
+            composite_types_completed: RefCell::new(FnvHashSet()),
+        };
+    }
+}
+
+pub enum FunctionDebugContext {
+    RegularContext(Box<FunctionDebugContextData>),
+    DebugInfoDisabled,
+    FunctionWithoutDebugInfo,
+}
+
+impl FunctionDebugContext {
+    fn get_ref<'a>(&'a self,
+                   cx: &CrateContext,
+                   span: Span)
+                   -> &'a FunctionDebugContextData {
+        match *self {
+            FunctionDebugContext::RegularContext(box ref data) => data,
+            FunctionDebugContext::DebugInfoDisabled => {
+                cx.sess().span_bug(span,
+                                   FunctionDebugContext::debuginfo_disabled_message());
+            }
+            FunctionDebugContext::FunctionWithoutDebugInfo => {
+                cx.sess().span_bug(span,
+                                   FunctionDebugContext::should_be_ignored_message());
+            }
+        }
+    }
+
+    fn debuginfo_disabled_message() -> &'static str {
+        "debuginfo: Error trying to access FunctionDebugContext although debug info is disabled!"
+    }
+
+    fn should_be_ignored_message() -> &'static str {
+        "debuginfo: Error trying to access FunctionDebugContext for function that should be \
+         ignored by debug info!"
+    }
+}
+
+struct FunctionDebugContextData {
+    scope_map: RefCell<NodeMap<DIScope>>,
+    fn_metadata: DISubprogram,
+    argument_counter: Cell<usize>,
+    source_locations_enabled: Cell<bool>,
+    source_location_override: Cell<bool>,
+}
+
+pub enum VariableAccess<'a> {
+    // The llptr given is an alloca containing the variable's value
+    DirectVariable { alloca: ValueRef },
+    // The llptr given is an alloca containing the start of some pointer chain
+    // leading to the variable's content.
+    IndirectVariable { alloca: ValueRef, address_operations: &'a [i64] }
+}
+
+pub enum VariableKind {
+    ArgumentVariable(usize /*index*/),
+    LocalVariable,
+    CapturedVariable,
+}
+
+/// Create any deferred debug metadata nodes
+pub fn finalize(cx: &CrateContext) {
+    if cx.dbg_cx().is_none() {
+        return;
+    }
+
+    debug!("finalize");
+    let _ = compile_unit_metadata(cx);
+
+    if gdb::needs_gdb_debug_scripts_section(cx) {
+        // Add a .debug_gdb_scripts section to this compile-unit. This will
+        // cause GDB to try and load the gdb_load_rust_pretty_printers.py file,
+        // which activates the Rust pretty printers for binary this section is
+        // contained in.
+        gdb::get_or_insert_gdb_debug_scripts_section_global(cx);
+    }
+
+    unsafe {
+        llvm::LLVMDIBuilderFinalize(DIB(cx));
+        llvm::LLVMDIBuilderDispose(DIB(cx));
+        // Debuginfo generation in LLVM by default uses a higher
+        // version of dwarf than OS X currently understands. We can
+        // instruct LLVM to emit an older version of dwarf, however,
+        // for OS X to understand. For more info see #11352
+        // This can be overridden using --llvm-opts -dwarf-version,N.
+        // Android has the same issue (#22398)
+        if cx.sess().target.target.options.is_like_osx ||
+           cx.sess().target.target.options.is_like_android {
+            llvm::LLVMRustAddModuleFlag(cx.llmod(),
+                                        "Dwarf Version\0".as_ptr() as *const _,
+                                        2)
+        }
+
+        // Prevent bitcode readers from deleting the debug info.
+        let ptr = "Debug Info Version\0".as_ptr();
+        llvm::LLVMRustAddModuleFlag(cx.llmod(), ptr as *const _,
+                                    llvm::LLVMRustDebugMetadataVersion);
+    };
+}
+
+/// Creates the function-specific debug context.
+///
+/// Returns the FunctionDebugContext for the function which holds state needed
+/// for debug info creation. The function may also return another variant of the
+/// FunctionDebugContext enum which indicates why no debuginfo should be created
+/// for the function.
+pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
+                                               fn_ast_id: ast::NodeId,
+                                               param_substs: &Substs<'tcx>,
+                                               llfn: ValueRef) -> FunctionDebugContext {
+    if cx.sess().opts.debuginfo == NoDebugInfo {
+        return FunctionDebugContext::DebugInfoDisabled;
+    }
+
+    // Clear the debug location so we don't assign them in the function prelude.
+    // Do this here already, in case we do an early exit from this function.
+    source_loc::set_debug_location(cx, InternalDebugLocation::UnknownLocation);
+
+    if fn_ast_id == ast::DUMMY_NODE_ID {
+        // This is a function not linked to any source location, so don't
+        // generate debuginfo for it.
+        return FunctionDebugContext::FunctionWithoutDebugInfo;
+    }
+
+    let empty_generics = ast_util::empty_generics();
+
+    let fnitem = cx.tcx().map.get(fn_ast_id);
+
+    let (name, fn_decl, generics, top_level_block, span, has_path) = match fnitem {
+        ast_map::NodeItem(ref item) => {
+            if contains_nodebug_attribute(&item.attrs) {
+                return FunctionDebugContext::FunctionWithoutDebugInfo;
+            }
+
+            match item.node {
+                ast::ItemFn(ref fn_decl, _, _, ref generics, ref top_level_block) => {
+                    (item.ident.name, fn_decl, generics, top_level_block, item.span, true)
+                }
+                _ => {
+                    cx.sess().span_bug(item.span,
+                        "create_function_debug_context: item bound to non-function");
+                }
+            }
+        }
+        ast_map::NodeImplItem(impl_item) => {
+            match impl_item.node {
+                ast::MethodImplItem(ref sig, ref body) => {
+                    if contains_nodebug_attribute(&impl_item.attrs) {
+                        return FunctionDebugContext::FunctionWithoutDebugInfo;
+                    }
+
+                    (impl_item.ident.name,
+                     &sig.decl,
+                     &sig.generics,
+                     body,
+                     impl_item.span,
+                     true)
+                }
+                _ => {
+                    cx.sess().span_bug(impl_item.span,
+                                       "create_function_debug_context() \
+                                        called on non-method impl item?!")
+                }
+            }
+        }
+        ast_map::NodeExpr(ref expr) => {
+            match expr.node {
+                ast::ExprClosure(_, ref fn_decl, ref top_level_block) => {
+                    let name = format!("fn{}", token::gensym("fn"));
+                    let name = token::intern(&name[..]);
+                    (name, fn_decl,
+                        // This is not quite right. It should actually inherit
+                        // the generics of the enclosing function.
+                        &empty_generics,
+                        top_level_block,
+                        expr.span,
+                        // Don't try to lookup the item path:
+                        false)
+                }
+                _ => cx.sess().span_bug(expr.span,
+                        "create_function_debug_context: expected an expr_fn_block here")
+            }
+        }
+        ast_map::NodeTraitItem(trait_item) => {
+            match trait_item.node {
+                ast::MethodTraitItem(ref sig, Some(ref body)) => {
+                    if contains_nodebug_attribute(&trait_item.attrs) {
+                        return FunctionDebugContext::FunctionWithoutDebugInfo;
+                    }
+
+                    (trait_item.ident.name,
+                     &sig.decl,
+                     &sig.generics,
+                     body,
+                     trait_item.span,
+                     true)
+                }
+                _ => {
+                    cx.sess()
+                      .bug(&format!("create_function_debug_context: \
+                                    unexpected sort of node: {:?}",
+                                    fnitem))
+                }
+            }
+        }
+        ast_map::NodeForeignItem(..) |
+        ast_map::NodeVariant(..) |
+        ast_map::NodeStructCtor(..) => {
+            return FunctionDebugContext::FunctionWithoutDebugInfo;
+        }
+        _ => cx.sess().bug(&format!("create_function_debug_context: \
+                                    unexpected sort of node: {:?}",
+                                   fnitem))
+    };
+
+    // This can be the case for functions inlined from another crate
+    if span == codemap::DUMMY_SP {
+        return FunctionDebugContext::FunctionWithoutDebugInfo;
+    }
+
+    let loc = span_start(cx, span);
+    let file_metadata = file_metadata(cx, &loc.file.name);
+
+    let function_type_metadata = unsafe {
+        let fn_signature = get_function_signature(cx,
+                                                  fn_ast_id,
+                                                  &*fn_decl,
+                                                  param_substs,
+                                                  span);
+        llvm::LLVMDIBuilderCreateSubroutineType(DIB(cx), file_metadata, fn_signature)
+    };
+
+    // Get_template_parameters() will append a `<...>` clause to the function
+    // name if necessary.
+    let mut function_name = String::from_str(&token::get_name(name));
+    let template_parameters = get_template_parameters(cx,
+                                                      generics,
+                                                      param_substs,
+                                                      file_metadata,
+                                                      &mut function_name);
+
+    // There is no ast_map::Path for ast::ExprClosure-type functions. For now,
+    // just don't put them into a namespace. In the future this could be improved
+    // somehow (storing a path in the ast_map, or construct a path using the
+    // enclosing function).
+    let (linkage_name, containing_scope) = if has_path {
+        let namespace_node = namespace_for_item(cx, ast_util::local_def(fn_ast_id));
+        let linkage_name = namespace_node.mangled_name_of_contained_item(
+            &function_name[..]);
+        let containing_scope = namespace_node.scope;
+        (linkage_name, containing_scope)
+    } else {
+        (function_name.clone(), file_metadata)
+    };
+
+    // Clang sets this parameter to the opening brace of the function's block,
+    // so let's do this too.
+    let scope_line = span_start(cx, top_level_block.span).line;
+
+    let is_local_to_unit = is_node_local_to_unit(cx, fn_ast_id);
+
+    let function_name = CString::new(function_name).unwrap();
+    let linkage_name = CString::new(linkage_name).unwrap();
+    let fn_metadata = unsafe {
+        llvm::LLVMDIBuilderCreateFunction(
+            DIB(cx),
+            containing_scope,
+            function_name.as_ptr(),
+            linkage_name.as_ptr(),
+            file_metadata,
+            loc.line as c_uint,
+            function_type_metadata,
+            is_local_to_unit,
+            true,
+            scope_line as c_uint,
+            FlagPrototyped as c_uint,
+            cx.sess().opts.optimize != config::No,
+            llfn,
+            template_parameters,
+            ptr::null_mut())
+    };
+
+    let scope_map = create_scope_map::create_scope_map(cx,
+                                                       &fn_decl.inputs,
+                                                       &*top_level_block,
+                                                       fn_metadata,
+                                                       fn_ast_id);
+
+    // Initialize fn debug context (including scope map and namespace map)
+    let fn_debug_context = box FunctionDebugContextData {
+        scope_map: RefCell::new(scope_map),
+        fn_metadata: fn_metadata,
+        argument_counter: Cell::new(1),
+        source_locations_enabled: Cell::new(false),
+        source_location_override: Cell::new(false),
+    };
+
+
+
+    return FunctionDebugContext::RegularContext(fn_debug_context);
+
+    fn get_function_signature<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
+                                        fn_ast_id: ast::NodeId,
+                                        fn_decl: &ast::FnDecl,
+                                        param_substs: &Substs<'tcx>,
+                                        error_reporting_span: Span) -> DIArray {
+        if cx.sess().opts.debuginfo == LimitedDebugInfo {
+            return create_DIArray(DIB(cx), &[]);
+        }
+
+        let mut signature = Vec::with_capacity(fn_decl.inputs.len() + 1);
+
+        // Return type -- llvm::DIBuilder wants this at index 0
+        assert_type_for_node_id(cx, fn_ast_id, error_reporting_span);
+        let return_type = ty::node_id_to_type(cx.tcx(), fn_ast_id);
+        let return_type = monomorphize::apply_param_substs(cx.tcx(),
+                                                           param_substs,
+                                                           &return_type);
+        if ty::type_is_nil(return_type) {
+            signature.push(ptr::null_mut())
+        } else {
+            signature.push(type_metadata(cx, return_type, codemap::DUMMY_SP));
+        }
+
+        // Arguments types
+        for arg in &fn_decl.inputs {
+            assert_type_for_node_id(cx, arg.pat.id, arg.pat.span);
+            let arg_type = ty::node_id_to_type(cx.tcx(), arg.pat.id);
+            let arg_type = monomorphize::apply_param_substs(cx.tcx(),
+                                                            param_substs,
+                                                            &arg_type);
+            signature.push(type_metadata(cx, arg_type, codemap::DUMMY_SP));
+        }
+
+        return create_DIArray(DIB(cx), &signature[..]);
+    }
+
+    fn get_template_parameters<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
+                                         generics: &ast::Generics,
+                                         param_substs: &Substs<'tcx>,
+                                         file_metadata: DIFile,
+                                         name_to_append_suffix_to: &mut String)
+                                         -> DIArray
+    {
+        let self_type = param_substs.self_ty();
+        let self_type = monomorphize::normalize_associated_type(cx.tcx(), &self_type);
+
+        // Only true for static default methods:
+        let has_self_type = self_type.is_some();
+
+        if !generics.is_type_parameterized() && !has_self_type {
+            return create_DIArray(DIB(cx), &[]);
+        }
+
+        name_to_append_suffix_to.push('<');
+
+        // The list to be filled with template parameters:
+        let mut template_params: Vec<DIDescriptor> =
+            Vec::with_capacity(generics.ty_params.len() + 1);
+
+        // Handle self type
+        if has_self_type {
+            let actual_self_type = self_type.unwrap();
+            // Add self type name to <...> clause of function name
+            let actual_self_type_name = compute_debuginfo_type_name(
+                cx,
+                actual_self_type,
+                true);
+
+            name_to_append_suffix_to.push_str(&actual_self_type_name[..]);
+
+            if generics.is_type_parameterized() {
+                name_to_append_suffix_to.push_str(",");
+            }
+
+            // Only create type information if full debuginfo is enabled
+            if cx.sess().opts.debuginfo == FullDebugInfo {
+                let actual_self_type_metadata = type_metadata(cx,
+                                                              actual_self_type,
+                                                              codemap::DUMMY_SP);
+
+                let name = token::get_name(special_idents::type_self.name);
+
+                let name = CString::new(name.as_bytes()).unwrap();
+                let param_metadata = unsafe {
+                    llvm::LLVMDIBuilderCreateTemplateTypeParameter(
+                        DIB(cx),
+                        file_metadata,
+                        name.as_ptr(),
+                        actual_self_type_metadata,
+                        ptr::null_mut(),
+                        0,
+                        0)
+                };
+
+                template_params.push(param_metadata);
+            }
+        }
+
+        // Handle other generic parameters
+        let actual_types = param_substs.types.get_slice(subst::FnSpace);
+        for (index, &ast::TyParam{ ident, .. }) in generics.ty_params.iter().enumerate() {
+            let actual_type = actual_types[index];
+            // Add actual type name to <...> clause of function name
+            let actual_type_name = compute_debuginfo_type_name(cx,
+                                                               actual_type,
+                                                               true);
+            name_to_append_suffix_to.push_str(&actual_type_name[..]);
+
+            if index != generics.ty_params.len() - 1 {
+                name_to_append_suffix_to.push_str(",");
+            }
+
+            // Again, only create type information if full debuginfo is enabled
+            if cx.sess().opts.debuginfo == FullDebugInfo {
+                let actual_type_metadata = type_metadata(cx, actual_type, codemap::DUMMY_SP);
+                let ident = token::get_ident(ident);
+                let name = CString::new(ident.as_bytes()).unwrap();
+                let param_metadata = unsafe {
+                    llvm::LLVMDIBuilderCreateTemplateTypeParameter(
+                        DIB(cx),
+                        file_metadata,
+                        name.as_ptr(),
+                        actual_type_metadata,
+                        ptr::null_mut(),
+                        0,
+                        0)
+                };
+                template_params.push(param_metadata);
+            }
+        }
+
+        name_to_append_suffix_to.push('>');
+
+        return create_DIArray(DIB(cx), &template_params[..]);
+    }
+}
+
+fn declare_local<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
+                             variable_name: ast::Name,
+                             variable_type: Ty<'tcx>,
+                             scope_metadata: DIScope,
+                             variable_access: VariableAccess,
+                             variable_kind: VariableKind,
+                             span: Span) {
+    let cx: &CrateContext = bcx.ccx();
+
+    let filename = span_start(cx, span).file.name.clone();
+    let file_metadata = file_metadata(cx, &filename[..]);
+
+    let name = token::get_name(variable_name);
+    let loc = span_start(cx, span);
+    let type_metadata = type_metadata(cx, variable_type, span);
+
+    let (argument_index, dwarf_tag) = match variable_kind {
+        ArgumentVariable(index) => (index as c_uint, DW_TAG_arg_variable),
+        LocalVariable    |
+        CapturedVariable => (0, DW_TAG_auto_variable)
+    };
+
+    let name = CString::new(name.as_bytes()).unwrap();
+    match (variable_access, &[][..]) {
+        (DirectVariable { alloca }, address_operations) |
+        (IndirectVariable {alloca, address_operations}, _) => {
+            let metadata = unsafe {
+                llvm::LLVMDIBuilderCreateVariable(
+                    DIB(cx),
+                    dwarf_tag,
+                    scope_metadata,
+                    name.as_ptr(),
+                    file_metadata,
+                    loc.line as c_uint,
+                    type_metadata,
+                    cx.sess().opts.optimize != config::No,
+                    0,
+                    address_operations.as_ptr(),
+                    address_operations.len() as c_uint,
+                    argument_index)
+            };
+            source_loc::set_debug_location(cx, InternalDebugLocation::new(scope_metadata,
+                                                                          loc.line,
+                                                                          loc.col.to_usize()));
+            unsafe {
+                let instr = llvm::LLVMDIBuilderInsertDeclareAtEnd(
+                    DIB(cx),
+                    alloca,
+                    metadata,
+                    address_operations.as_ptr(),
+                    address_operations.len() as c_uint,
+                    bcx.llbb);
+
+                llvm::LLVMSetInstDebugLocation(trans::build::B(bcx).llbuilder, instr);
+            }
+        }
+    }
+
+    match variable_kind {
+        ArgumentVariable(_) | CapturedVariable => {
+            assert!(!bcx.fcx
+                        .debug_context
+                        .get_ref(cx, span)
+                        .source_locations_enabled
+                        .get());
+            source_loc::set_debug_location(cx, InternalDebugLocation::UnknownLocation);
+        }
+        _ => { /* nothing to do */ }
+    }
+}
+
+#[derive(Copy, Clone, PartialEq, Eq, Debug)]
+pub enum DebugLoc {
+    At(ast::NodeId, Span),
+    None
+}
+
+impl DebugLoc {
+    pub fn apply(&self, fcx: &FunctionContext) {
+        match *self {
+            DebugLoc::At(node_id, span) => {
+                source_loc::set_source_location(fcx, node_id, span);
+            }
+            DebugLoc::None => {
+                source_loc::clear_source_location(fcx);
+            }
+        }
+    }
+}
+
+pub trait ToDebugLoc {
+    fn debug_loc(&self) -> DebugLoc;
+}
+
+impl ToDebugLoc for ast::Expr {
+    fn debug_loc(&self) -> DebugLoc {
+        DebugLoc::At(self.id, self.span)
+    }
+}
+
+impl ToDebugLoc for NodeIdAndSpan {
+    fn debug_loc(&self) -> DebugLoc {
+        DebugLoc::At(self.id, self.span)
+    }
+}
+
+impl ToDebugLoc for Option<NodeIdAndSpan> {
+    fn debug_loc(&self) -> DebugLoc {
+        match *self {
+            Some(NodeIdAndSpan { id, span }) => DebugLoc::At(id, span),
+            None => DebugLoc::None
+        }
+    }
+}
diff --git a/src/librustc_trans/trans/debuginfo/namespace.rs b/src/librustc_trans/trans/debuginfo/namespace.rs
new file mode 100644 (file)
index 0000000..0aa0408
--- /dev/null
@@ -0,0 +1,134 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Namespace Handling.
+
+use super::utils::{DIB, debug_context};
+
+use llvm;
+use llvm::debuginfo::DIScope;
+use trans::common::CrateContext;
+use middle::ty::{self, ClosureTyper};
+
+use std::ffi::CString;
+use std::ptr;
+use std::rc::{Rc, Weak};
+use syntax::{ast, ast_map};
+use syntax::parse::token;
+
+pub struct NamespaceTreeNode {
+    pub name: ast::Name,
+    pub scope: DIScope,
+    pub parent: Option<Weak<NamespaceTreeNode>>,
+}
+
+impl NamespaceTreeNode {
+    pub fn mangled_name_of_contained_item(&self, item_name: &str) -> String {
+        fn fill_nested(node: &NamespaceTreeNode, output: &mut String) {
+            match node.parent {
+                Some(ref parent) => fill_nested(&*parent.upgrade().unwrap(), output),
+                None => {}
+            }
+            let string = token::get_name(node.name);
+            output.push_str(&format!("{}", string.len()));
+            output.push_str(&string);
+        }
+
+        let mut name = String::from_str("_ZN");
+        fill_nested(self, &mut name);
+        name.push_str(&format!("{}", item_name.len()));
+        name.push_str(item_name);
+        name.push('E');
+        name
+    }
+}
+
+pub fn crate_root_namespace<'a>(cx: &'a CrateContext) -> &'a str {
+    &cx.link_meta().crate_name
+}
+
+pub fn namespace_for_item(cx: &CrateContext, def_id: ast::DefId) -> Rc<NamespaceTreeNode> {
+    ty::with_path(cx.tcx(), def_id, |path| {
+        // prepend crate name if not already present
+        let krate = if def_id.krate == ast::LOCAL_CRATE {
+            let crate_namespace_name = token::intern(crate_root_namespace(cx));
+            Some(ast_map::PathMod(crate_namespace_name))
+        } else {
+            None
+        };
+        let mut path = krate.into_iter().chain(path).peekable();
+
+        let mut current_key = Vec::new();
+        let mut parent_node: Option<Rc<NamespaceTreeNode>> = None;
+
+        // Create/Lookup namespace for each element of the path.
+        loop {
+            // Emulate a for loop so we can use peek below.
+            let path_element = match path.next() {
+                Some(e) => e,
+                None => break
+            };
+            // Ignore the name of the item (the last path element).
+            if path.peek().is_none() {
+                break;
+            }
+
+            let name = path_element.name();
+            current_key.push(name);
+
+            let existing_node = debug_context(cx).namespace_map.borrow()
+                                                 .get(&current_key).cloned();
+            let current_node = match existing_node {
+                Some(existing_node) => existing_node,
+                None => {
+                    // create and insert
+                    let parent_scope = match parent_node {
+                        Some(ref node) => node.scope,
+                        None => ptr::null_mut()
+                    };
+                    let namespace_name = token::get_name(name);
+                    let namespace_name = CString::new(namespace_name.as_bytes()).unwrap();
+                    let scope = unsafe {
+                        llvm::LLVMDIBuilderCreateNameSpace(
+                            DIB(cx),
+                            parent_scope,
+                            namespace_name.as_ptr(),
+                            // cannot reconstruct file ...
+                            ptr::null_mut(),
+                            // ... or line information, but that's not so important.
+                            0)
+                    };
+
+                    let node = Rc::new(NamespaceTreeNode {
+                        name: name,
+                        scope: scope,
+                        parent: parent_node.map(|parent| parent.downgrade()),
+                    });
+
+                    debug_context(cx).namespace_map.borrow_mut()
+                                     .insert(current_key.clone(), node.clone());
+
+                    node
+                }
+            };
+
+            parent_node = Some(current_node);
+        }
+
+        match parent_node {
+            Some(node) => node,
+            None => {
+                cx.sess().bug(&format!("debuginfo::namespace_for_item(): \
+                                       path too short for {:?}",
+                                      def_id));
+            }
+        }
+    })
+}
diff --git a/src/librustc_trans/trans/debuginfo/source_loc.rs b/src/librustc_trans/trans/debuginfo/source_loc.rs
new file mode 100644 (file)
index 0000000..981a23f
--- /dev/null
@@ -0,0 +1,231 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use self::InternalDebugLocation::*;
+
+use super::utils::{debug_context, span_start, fn_should_be_ignored};
+use super::metadata::{scope_metadata,UNKNOWN_COLUMN_NUMBER};
+use super::{FunctionDebugContext, DebugLoc};
+
+use llvm;
+use llvm::debuginfo::DIScope;
+use trans::common::{NodeIdAndSpan, CrateContext, FunctionContext};
+
+use libc::c_uint;
+use std::ptr;
+use syntax::codemap::{Span, Pos};
+use syntax::{ast, codemap};
+
+pub fn get_cleanup_debug_loc_for_ast_node<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
+                                                    node_id: ast::NodeId,
+                                                    node_span: Span,
+                                                    is_block: bool)
+                                                 -> NodeIdAndSpan {
+    // A debug location needs two things:
+    // (1) A span (of which only the beginning will actually be used)
+    // (2) An AST node-id which will be used to look up the lexical scope
+    //     for the location in the functions scope-map
+    //
+    // This function will calculate the debug location for compiler-generated
+    // cleanup calls that are executed when control-flow leaves the
+    // scope identified by `node_id`.
+    //
+    // For everything but block-like things we can simply take id and span of
+    // the given expression, meaning that from a debugger's view cleanup code is
+    // executed at the same source location as the statement/expr itself.
+    //
+    // Blocks are a special case. Here we want the cleanup to be linked to the
+    // closing curly brace of the block. The *scope* the cleanup is executed in
+    // is up to debate: It could either still be *within* the block being
+    // cleaned up, meaning that locals from the block are still visible in the
+    // debugger.
+    // Or it could be in the scope that the block is contained in, so any locals
+    // from within the block are already considered out-of-scope and thus not
+    // accessible in the debugger anymore.
+    //
+    // The current implementation opts for the second option: cleanup of a block
+    // already happens in the parent scope of the block. The main reason for
+    // this decision is that scoping becomes controlflow dependent when variable
+    // shadowing is involved and it's impossible to decide statically which
+    // scope is actually left when the cleanup code is executed.
+    // In practice it shouldn't make much of a difference.
+
+    let mut cleanup_span = node_span;
+
+    if is_block {
+        // Not all blocks actually have curly braces (e.g. simple closure
+        // bodies), in which case we also just want to return the span of the
+        // whole expression.
+        let code_snippet = cx.sess().codemap().span_to_snippet(node_span);
+        if let Ok(code_snippet) = code_snippet {
+            let bytes = code_snippet.as_bytes();
+
+            if !bytes.is_empty() && &bytes[bytes.len()-1..] == b"}" {
+                cleanup_span = Span {
+                    lo: node_span.hi - codemap::BytePos(1),
+                    hi: node_span.hi,
+                    expn_id: node_span.expn_id
+                };
+            }
+        }
+    }
+
+    NodeIdAndSpan {
+        id: node_id,
+        span: cleanup_span
+    }
+}
+
+
+/// Sets the current debug location at the beginning of the span.
+///
+/// Maps to a call to llvm::LLVMSetCurrentDebugLocation(...). The node_id
+/// parameter is used to reliably find the correct visibility scope for the code
+/// position.
+pub fn set_source_location(fcx: &FunctionContext,
+                           node_id: ast::NodeId,
+                           span: Span) {
+    match fcx.debug_context {
+        FunctionDebugContext::DebugInfoDisabled => return,
+        FunctionDebugContext::FunctionWithoutDebugInfo => {
+            set_debug_location(fcx.ccx, UnknownLocation);
+            return;
+        }
+        FunctionDebugContext::RegularContext(box ref function_debug_context) => {
+            if function_debug_context.source_location_override.get() {
+                // Just ignore any attempts to set a new debug location while
+                // the override is active.
+                return;
+            }
+
+            let cx = fcx.ccx;
+
+            debug!("set_source_location: {}", cx.sess().codemap().span_to_string(span));
+
+            if function_debug_context.source_locations_enabled.get() {
+                let loc = span_start(cx, span);
+                let scope = scope_metadata(fcx, node_id, span);
+
+                set_debug_location(cx, InternalDebugLocation::new(scope,
+                                                                  loc.line,
+                                                                  loc.col.to_usize()));
+            } else {
+                set_debug_location(cx, UnknownLocation);
+            }
+        }
+    }
+}
+
+/// This function makes sure that all debug locations emitted while executing
+/// `wrapped_function` are set to the given `debug_loc`.
+pub fn with_source_location_override<F, R>(fcx: &FunctionContext,
+                                           debug_loc: DebugLoc,
+                                           wrapped_function: F) -> R
+    where F: FnOnce() -> R
+{
+    match fcx.debug_context {
+        FunctionDebugContext::DebugInfoDisabled => {
+            wrapped_function()
+        }
+        FunctionDebugContext::FunctionWithoutDebugInfo => {
+            set_debug_location(fcx.ccx, UnknownLocation);
+            wrapped_function()
+        }
+        FunctionDebugContext::RegularContext(box ref function_debug_context) => {
+            if function_debug_context.source_location_override.get() {
+                wrapped_function()
+            } else {
+                debug_loc.apply(fcx);
+                function_debug_context.source_location_override.set(true);
+                let result = wrapped_function();
+                function_debug_context.source_location_override.set(false);
+                result
+            }
+        }
+    }
+}
+
+/// Clears the current debug location.
+///
+/// Instructions generated hereafter won't be assigned a source location.
+pub fn clear_source_location(fcx: &FunctionContext) {
+    if fn_should_be_ignored(fcx) {
+        return;
+    }
+
+    set_debug_location(fcx.ccx, UnknownLocation);
+}
+
+/// Enables emitting source locations for the given functions.
+///
+/// Since we don't want source locations to be emitted for the function prelude,
+/// they are disabled when beginning to translate a new function. This functions
+/// switches source location emitting on and must therefore be called before the
+/// first real statement/expression of the function is translated.
+pub fn start_emitting_source_locations(fcx: &FunctionContext) {
+    match fcx.debug_context {
+        FunctionDebugContext::RegularContext(box ref data) => {
+            data.source_locations_enabled.set(true)
+        },
+        _ => { /* safe to ignore */ }
+    }
+}
+
+
+#[derive(Copy, Clone, PartialEq)]
+pub enum InternalDebugLocation {
+    KnownLocation { scope: DIScope, line: usize, col: usize },
+    UnknownLocation
+}
+
+impl InternalDebugLocation {
+    pub fn new(scope: DIScope, line: usize, col: usize) -> InternalDebugLocation {
+        KnownLocation {
+            scope: scope,
+            line: line,
+            col: col,
+        }
+    }
+}
+
+pub fn set_debug_location(cx: &CrateContext, debug_location: InternalDebugLocation) {
+    if debug_location == debug_context(cx).current_debug_location.get() {
+        return;
+    }
+
+    let metadata_node;
+
+    match debug_location {
+        KnownLocation { scope, line, .. } => {
+            // Always set the column to zero like Clang and GCC
+            let col = UNKNOWN_COLUMN_NUMBER;
+            debug!("setting debug location to {} {}", line, col);
+
+            unsafe {
+                metadata_node = llvm::LLVMDIBuilderCreateDebugLocation(
+                    debug_context(cx).llcontext,
+                    line as c_uint,
+                    col as c_uint,
+                    scope,
+                    ptr::null_mut());
+            }
+        }
+        UnknownLocation => {
+            debug!("clearing debug location ");
+            metadata_node = ptr::null_mut();
+        }
+    };
+
+    unsafe {
+        llvm::LLVMSetCurrentDebugLocation(cx.raw_builder(), metadata_node);
+    }
+
+    debug_context(cx).current_debug_location.set(debug_location);
+}
diff --git a/src/librustc_trans/trans/debuginfo/type_names.rs b/src/librustc_trans/trans/debuginfo/type_names.rs
new file mode 100644 (file)
index 0000000..2d0003d
--- /dev/null
@@ -0,0 +1,230 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Type Names for Debug Info.
+
+use super::namespace::crate_root_namespace;
+
+use trans::common::CrateContext;
+use middle::subst::{self, Substs};
+use middle::ty::{self, Ty, ClosureTyper};
+use syntax::ast;
+use syntax::parse::token;
+use util::ppaux;
+
+
+// Compute the name of the type as it should be stored in debuginfo. Does not do
+// any caching, i.e. calling the function twice with the same type will also do
+// the work twice. The `qualified` parameter only affects the first level of the
+// type name, further levels (i.e. type parameters) are always fully qualified.
+pub fn compute_debuginfo_type_name<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
+                                             t: Ty<'tcx>,
+                                             qualified: bool)
+                                             -> String {
+    let mut result = String::with_capacity(64);
+    push_debuginfo_type_name(cx, t, qualified, &mut result);
+    result
+}
+
+// Pushes the name of the type as it should be stored in debuginfo on the
+// `output` String. See also compute_debuginfo_type_name().
+pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
+                                          t: Ty<'tcx>,
+                                          qualified: bool,
+                                          output: &mut String) {
+    match t.sty {
+        ty::ty_bool              => output.push_str("bool"),
+        ty::ty_char              => output.push_str("char"),
+        ty::ty_str               => output.push_str("str"),
+        ty::ty_int(ast::TyIs)     => output.push_str("isize"),
+        ty::ty_int(ast::TyI8)    => output.push_str("i8"),
+        ty::ty_int(ast::TyI16)   => output.push_str("i16"),
+        ty::ty_int(ast::TyI32)   => output.push_str("i32"),
+        ty::ty_int(ast::TyI64)   => output.push_str("i64"),
+        ty::ty_uint(ast::TyUs)    => output.push_str("usize"),
+        ty::ty_uint(ast::TyU8)   => output.push_str("u8"),
+        ty::ty_uint(ast::TyU16)  => output.push_str("u16"),
+        ty::ty_uint(ast::TyU32)  => output.push_str("u32"),
+        ty::ty_uint(ast::TyU64)  => output.push_str("u64"),
+        ty::ty_float(ast::TyF32) => output.push_str("f32"),
+        ty::ty_float(ast::TyF64) => output.push_str("f64"),
+        ty::ty_struct(def_id, substs) |
+        ty::ty_enum(def_id, substs) => {
+            push_item_name(cx, def_id, qualified, output);
+            push_type_params(cx, substs, output);
+        },
+        ty::ty_tup(ref component_types) => {
+            output.push('(');
+            for &component_type in component_types {
+                push_debuginfo_type_name(cx, component_type, true, output);
+                output.push_str(", ");
+            }
+            if !component_types.is_empty() {
+                output.pop();
+                output.pop();
+            }
+            output.push(')');
+        },
+        ty::ty_uniq(inner_type) => {
+            output.push_str("Box<");
+            push_debuginfo_type_name(cx, inner_type, true, output);
+            output.push('>');
+        },
+        ty::ty_ptr(ty::mt { ty: inner_type, mutbl } ) => {
+            output.push('*');
+            match mutbl {
+                ast::MutImmutable => output.push_str("const "),
+                ast::MutMutable => output.push_str("mut "),
+            }
+
+            push_debuginfo_type_name(cx, inner_type, true, output);
+        },
+        ty::ty_rptr(_, ty::mt { ty: inner_type, mutbl }) => {
+            output.push('&');
+            if mutbl == ast::MutMutable {
+                output.push_str("mut ");
+            }
+
+            push_debuginfo_type_name(cx, inner_type, true, output);
+        },
+        ty::ty_vec(inner_type, optional_length) => {
+            output.push('[');
+            push_debuginfo_type_name(cx, inner_type, true, output);
+
+            match optional_length {
+                Some(len) => {
+                    output.push_str(&format!("; {}", len));
+                }
+                None => { /* nothing to do */ }
+            };
+
+            output.push(']');
+        },
+        ty::ty_trait(ref trait_data) => {
+            let principal = ty::erase_late_bound_regions(cx.tcx(), &trait_data.principal);
+            push_item_name(cx, principal.def_id, false, output);
+            push_type_params(cx, principal.substs, output);
+        },
+        ty::ty_bare_fn(_, &ty::BareFnTy{ unsafety, abi, ref sig } ) => {
+            if unsafety == ast::Unsafety::Unsafe {
+                output.push_str("unsafe ");
+            }
+
+            if abi != ::syntax::abi::Rust {
+                output.push_str("extern \"");
+                output.push_str(abi.name());
+                output.push_str("\" ");
+            }
+
+            output.push_str("fn(");
+
+            let sig = ty::erase_late_bound_regions(cx.tcx(), sig);
+            if !sig.inputs.is_empty() {
+                for &parameter_type in &sig.inputs {
+                    push_debuginfo_type_name(cx, parameter_type, true, output);
+                    output.push_str(", ");
+                }
+                output.pop();
+                output.pop();
+            }
+
+            if sig.variadic {
+                if !sig.inputs.is_empty() {
+                    output.push_str(", ...");
+                } else {
+                    output.push_str("...");
+                }
+            }
+
+            output.push(')');
+
+            match sig.output {
+                ty::FnConverging(result_type) if ty::type_is_nil(result_type) => {}
+                ty::FnConverging(result_type) => {
+                    output.push_str(" -> ");
+                    push_debuginfo_type_name(cx, result_type, true, output);
+                }
+                ty::FnDiverging => {
+                    output.push_str(" -> !");
+                }
+            }
+        },
+        ty::ty_closure(..) => {
+            output.push_str("closure");
+        }
+        ty::ty_err |
+        ty::ty_infer(_) |
+        ty::ty_projection(..) |
+        ty::ty_param(_) => {
+            cx.sess().bug(&format!("debuginfo: Trying to create type name for \
+                unexpected type: {}", ppaux::ty_to_string(cx.tcx(), t)));
+        }
+    }
+
+    fn push_item_name(cx: &CrateContext,
+                      def_id: ast::DefId,
+                      qualified: bool,
+                      output: &mut String) {
+        ty::with_path(cx.tcx(), def_id, |path| {
+            if qualified {
+                if def_id.krate == ast::LOCAL_CRATE {
+                    output.push_str(crate_root_namespace(cx));
+                    output.push_str("::");
+                }
+
+                let mut path_element_count = 0;
+                for path_element in path {
+                    let name = token::get_name(path_element.name());
+                    output.push_str(&name);
+                    output.push_str("::");
+                    path_element_count += 1;
+                }
+
+                if path_element_count == 0 {
+                    cx.sess().bug("debuginfo: Encountered empty item path!");
+                }
+
+                output.pop();
+                output.pop();
+            } else {
+                let name = token::get_name(path.last()
+                                               .expect("debuginfo: Empty item path?")
+                                               .name());
+                output.push_str(&name);
+            }
+        });
+    }
+
+    // Pushes the type parameters in the given `Substs` to the output string.
+    // This ignores region parameters, since they can't reliably be
+    // reconstructed for items from non-local crates. For local crates, this
+    // would be possible but with inlining and LTO we have to use the least
+    // common denominator - otherwise we would run into conflicts.
+    fn push_type_params<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
+                                  substs: &subst::Substs<'tcx>,
+                                  output: &mut String) {
+        if substs.types.is_empty() {
+            return;
+        }
+
+        output.push('<');
+
+        for &type_parameter in substs.types.iter() {
+            push_debuginfo_type_name(cx, type_parameter, true, output);
+            output.push_str(", ");
+        }
+
+        output.pop();
+        output.pop();
+
+        output.push('>');
+    }
+}
+
diff --git a/src/librustc_trans/trans/debuginfo/utils.rs b/src/librustc_trans/trans/debuginfo/utils.rs
new file mode 100644 (file)
index 0000000..0c12f6e
--- /dev/null
@@ -0,0 +1,108 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Utility Functions.
+
+use super::{FunctionDebugContext, CrateDebugContext};
+use super::namespace::namespace_for_item;
+
+use llvm;
+use llvm::debuginfo::{DIScope, DIBuilderRef, DIDescriptor, DIArray};
+use trans::machine;
+use trans::common::{CrateContext, FunctionContext};
+use trans::type_::Type;
+
+use syntax::codemap::Span;
+use syntax::{ast, codemap};
+
+pub fn is_node_local_to_unit(cx: &CrateContext, node_id: ast::NodeId) -> bool
+{
+    // The is_local_to_unit flag indicates whether a function is local to the
+    // current compilation unit (i.e. if it is *static* in the C-sense). The
+    // *reachable* set should provide a good approximation of this, as it
+    // contains everything that might leak out of the current crate (by being
+    // externally visible or by being inlined into something externally
+    // visible). It might better to use the `exported_items` set from
+    // `driver::CrateAnalysis` in the future, but (atm) this set is not
+    // available in the translation pass.
+    !cx.reachable().contains(&node_id)
+}
+
+#[allow(non_snake_case)]
+pub fn create_DIArray(builder: DIBuilderRef, arr: &[DIDescriptor]) -> DIArray {
+    return unsafe {
+        llvm::LLVMDIBuilderGetOrCreateArray(builder, arr.as_ptr(), arr.len() as u32)
+    };
+}
+
+pub fn contains_nodebug_attribute(attributes: &[ast::Attribute]) -> bool {
+    attributes.iter().any(|attr| {
+        let meta_item: &ast::MetaItem = &*attr.node.value;
+        match meta_item.node {
+            ast::MetaWord(ref value) => &value[..] == "no_debug",
+            _ => false
+        }
+    })
+}
+
+/// Return codemap::Loc corresponding to the beginning of the span
+pub fn span_start(cx: &CrateContext, span: Span) -> codemap::Loc {
+    cx.sess().codemap().lookup_char_pos(span.lo)
+}
+
+pub fn size_and_align_of(cx: &CrateContext, llvm_type: Type) -> (u64, u64) {
+    (machine::llsize_of_alloc(cx, llvm_type), machine::llalign_of_min(cx, llvm_type) as u64)
+}
+
+pub fn bytes_to_bits(bytes: u64) -> u64 {
+    bytes * 8
+}
+
+#[inline]
+pub fn debug_context<'a, 'tcx>(cx: &'a CrateContext<'a, 'tcx>)
+                           -> &'a CrateDebugContext<'tcx> {
+    let debug_context: &'a CrateDebugContext<'tcx> = cx.dbg_cx().as_ref().unwrap();
+    debug_context
+}
+
+#[inline]
+#[allow(non_snake_case)]
+pub fn DIB(cx: &CrateContext) -> DIBuilderRef {
+    cx.dbg_cx().as_ref().unwrap().builder
+}
+
+pub fn fn_should_be_ignored(fcx: &FunctionContext) -> bool {
+    match fcx.debug_context {
+        FunctionDebugContext::RegularContext(_) => false,
+        _ => true
+    }
+}
+
+pub fn assert_type_for_node_id(cx: &CrateContext,
+                           node_id: ast::NodeId,
+                           error_reporting_span: Span) {
+    if !cx.tcx().node_types().contains_key(&node_id) {
+        cx.sess().span_bug(error_reporting_span,
+                           "debuginfo: Could not find type for node id!");
+    }
+}
+
+pub fn get_namespace_and_span_for_item(cx: &CrateContext, def_id: ast::DefId)
+                                   -> (DIScope, Span) {
+    let containing_scope = namespace_for_item(cx, def_id).scope;
+    let definition_span = if def_id.krate == ast::LOCAL_CRATE {
+        cx.tcx().map.span(def_id.node)
+    } else {
+        // For external items there is no span information
+        codemap::DUMMY_SP
+    };
+
+    (containing_scope, definition_span)
+}
index 9e7449f670f0fe398f2c876e383a86186281b047..35946491ba17693f99d66b4d1aca6d87b6c78c10 100644 (file)
@@ -71,12 +71,12 @@ pub fn declare_fn(ccx: &CrateContext, name: &str, callconv: llvm::CallConv, ty:
     llvm::SetUnnamedAddr(llfn, true);
 
     if output == ty::FnDiverging {
-        llvm::SetFunctionAttribute(llfn, llvm::NoReturnAttribute);
+        llvm::SetFunctionAttribute(llfn, llvm::Attribute::NoReturnAttribute);
     }
 
     if ccx.tcx().sess.opts.cg.no_redzone
         .unwrap_or(ccx.tcx().sess.target.target.options.disable_redzone) {
-        llvm::SetFunctionAttribute(llfn, llvm::NoRedZoneAttribute)
+        llvm::SetFunctionAttribute(llfn, llvm::Attribute::NoRedZoneAttribute)
     }
 
     if ccx.is_split_stack_supported() && !ccx.sess().opts.cg.no_stack_check {
index 27919d645b695fa39a259ba786c80f5680d536b9..f5ee44d69cc6353b1cf8e66d29eb89d59f289dc3 100644 (file)
@@ -126,8 +126,11 @@ pub fn trans_into<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
     }
 
     let qualif = *bcx.tcx().const_qualif_map.borrow().get(&expr.id).unwrap();
-    if !qualif.intersects(check_const::NOT_CONST | check_const::NEEDS_DROP) {
-        if !qualif.intersects(check_const::PREFER_IN_PLACE) {
+    if !qualif.intersects(
+        check_const::ConstQualif::NOT_CONST |
+        check_const::ConstQualif::NEEDS_DROP
+    ) {
+        if !qualif.intersects(check_const::ConstQualif::PREFER_IN_PLACE) {
             if let SaveIn(lldest) = dest {
                 let global = consts::get_const_expr_as_global(bcx.ccx(), expr, qualif,
                                                             bcx.fcx.param_substs);
@@ -209,12 +212,15 @@ pub fn trans<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
     let mut bcx = bcx;
     let fcx = bcx.fcx;
     let qualif = *bcx.tcx().const_qualif_map.borrow().get(&expr.id).unwrap();
-    let adjusted_global = !qualif.intersects(check_const::NON_STATIC_BORROWS);
-    let global = if !qualif.intersects(check_const::NOT_CONST | check_const::NEEDS_DROP) {
+    let adjusted_global = !qualif.intersects(check_const::ConstQualif::NON_STATIC_BORROWS);
+    let global = if !qualif.intersects(
+        check_const::ConstQualif::NOT_CONST |
+        check_const::ConstQualif::NEEDS_DROP
+    ) {
         let global = consts::get_const_expr_as_global(bcx.ccx(), expr, qualif,
                                                       bcx.fcx.param_substs);
 
-        if qualif.intersects(check_const::HAS_STATIC_BORROWS) {
+        if qualif.intersects(check_const::ConstQualif::HAS_STATIC_BORROWS) {
             // Is borrowed as 'static, must return lvalue.
 
             // Cast pointer to global, because constants have different types.
index c025be2ee98772eb7241dd565501c90a77bbe757..d760b2c52ca1b0217d14137f00ace8b5488fc193 100644 (file)
@@ -349,8 +349,8 @@ pub fn trans_native_call<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
         // The outptr can be noalias and nocapture because it's entirely
         // invisible to the program. We also know it's nonnull as well
         // as how many bytes we can dereference
-        attrs.arg(1, llvm::NoAliasAttribute)
-             .arg(1, llvm::NoCaptureAttribute)
+        attrs.arg(1, llvm::Attribute::NoAliasAttribute)
+             .arg(1, llvm::Attribute::NoCaptureAttribute)
              .arg(1, llvm::DereferenceableAttribute(llret_sz));
     };
 
index 652f6ad366aaa09604301d0f2a9c7e282598d70f..a2a9e89ff6351cd5a0d8fd05d72ad7f65693c965 100644 (file)
@@ -383,7 +383,7 @@ fn trans_struct_drop<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
 
     // Issue #23611: schedule cleanup of contents, re-inspecting the
     // discriminant (if any) in case of variant swap in drop code.
-    bcx.fcx.schedule_drop_enum_contents(cleanup::CustomScope(contents_scope), v0, t);
+    bcx.fcx.schedule_drop_adt_contents(cleanup::CustomScope(contents_scope), v0, t);
 
     let glue_type = get_drop_glue_type(bcx.ccx(), t);
     let dtor_ty = ty::mk_ctor_fn(bcx.tcx(), class_did, &[glue_type], ty::mk_nil(bcx.tcx()));
index 6bfa80f9c40b360f5dd119494dc7987f60b30680..7188fdebeecf4c170ddb47f2a67f6a4ebb3f654a 100644 (file)
@@ -144,6 +144,9 @@ pub fn check_intrinsics(ccx: &CrateContext) {
     ccx.sess().abort_if_errors();
 }
 
+/// Remember to add all intrinsics here, in librustc_typeck/check/mod.rs,
+/// and in libcore/intrinsics.rs; if you need access to any llvm intrinsics,
+/// add them to librustc_trans/trans/context.rs
 pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
                                             node: ast::NodeId,
                                             callee_ty: Ty<'tcx>,
@@ -676,6 +679,11 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
                                     llargs[1],
                                     call_debug_location),
 
+        (_, "unchecked_udiv") => UDiv(bcx, llargs[0], llargs[1], call_debug_location),
+        (_, "unchecked_sdiv") => SDiv(bcx, llargs[0], llargs[1], call_debug_location),
+        (_, "unchecked_urem") => URem(bcx, llargs[0], llargs[1], call_debug_location),
+        (_, "unchecked_srem") => SRem(bcx, llargs[0], llargs[1], call_debug_location),
+
         (_, "overflowing_add") => Add(bcx, llargs[0], llargs[1], call_debug_location),
         (_, "overflowing_sub") => Sub(bcx, llargs[0], llargs[1], call_debug_location),
         (_, "overflowing_mul") => Mul(bcx, llargs[0], llargs[1], call_debug_location),
@@ -763,7 +771,12 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
                 }
 
                 "fence" => {
-                    AtomicFence(bcx, order);
+                    AtomicFence(bcx, order, llvm::CrossThread);
+                    C_nil(ccx)
+                }
+
+                "singlethreadfence" => {
+                    AtomicFence(bcx, order, llvm::SingleThread);
                     C_nil(ccx)
                 }
 
index 2f7e0073e1751ad0f99ee08fc7714ee5269749ff..008ba1c6bf83e3a3a9b30b1a3275eb8dee1a5bb5 100644 (file)
@@ -464,9 +464,9 @@ fn iterate_over_potentially_unsafe_regions_in_type<'a, 'tcx>(
                     ty::Predicate::Trait(ty::Binder(ref t_pred)) => {
                         let def_id = t_pred.trait_ref.def_id;
                         match rcx.tcx().lang_items.to_builtin_kind(def_id) {
+                            // Issue 24895: deliberately do not include `BoundCopy` here.
                             Some(ty::BoundSend) |
                             Some(ty::BoundSized) |
-                            Some(ty::BoundCopy) |
                             Some(ty::BoundSync) => false,
                             _ => true,
                         }
index f9c78cd36e6ac1d93e3d3093337443363468201f..cb5b569fd79cb284a4ccce936aa6cecfed8ecd32 100644 (file)
@@ -4882,6 +4882,8 @@ pub fn check_bounds_are_used<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
     }
 }
 
+/// Remember to add all intrinsics here, in librustc_trans/trans/intrinsic.rs,
+/// and in libcore/intrinsics.rs
 pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &ast::ForeignItem) {
     fn param<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, n: u32) -> Ty<'tcx> {
         let name = token::intern(&format!("P{}", n));
@@ -4910,7 +4912,7 @@ fn param<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, n: u32) -> Ty<'tcx> {
                 (1, vec!(ty::mk_mut_ptr(tcx, param(ccx, 0)), param(ccx, 0)),
                  param(ccx, 0))
             }
-            "fence" => {
+            "fence" | "singlethreadfence" => {
                 (0, Vec::new(), ty::mk_nil(tcx))
             }
             op => {
@@ -5119,6 +5121,9 @@ fn param<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, n: u32) -> Ty<'tcx> {
                 (0, vec!(tcx.types.u64, tcx.types.u64),
                 ty::mk_tup(tcx, vec!(tcx.types.u64, tcx.types.bool))),
 
+            "unchecked_udiv" | "unchecked_sdiv" | "unchecked_urem" | "unchecked_srem" =>
+                (1, vec![param(ccx, 0), param(ccx, 0)], param(ccx, 0)),
+
             "overflowing_add" | "overflowing_sub" | "overflowing_mul" =>
                 (1, vec![param(ccx, 0), param(ccx, 0)], param(ccx, 0)),
 
index 46cc4628e2eeb36022f7782bd7d89af67c72cee7..0af19e445f26e554eb3129950393de8ce9fb0074 100644 (file)
     E0371, // impl Trait for Trait is illegal
     E0372  // impl Trait for Trait where Trait is not object safe
 }
-
-__build_diagnostic_array! { DIAGNOSTICS }
index be3fc860b2b1239cad25fb50e0667dfc4557113e..e50693ea804b6993a852ea82bbcea5ae054dccb5 100644 (file)
@@ -82,7 +82,6 @@
 #![feature(quote)]
 #![feature(rustc_diagnostic_macros)]
 #![feature(rustc_private)]
-#![feature(unsafe_destructor)]
 #![feature(staged_api)]
 
 #[macro_use] extern crate log;
@@ -344,3 +343,8 @@ pub fn check_crate(tcx: &ty::ctxt, trait_map: ty::TraitMap) {
     check_for_entry_fn(&ccx);
     tcx.sess.abort_if_errors();
 }
+
+#[cfg(stage0)]
+__build_diagnostic_array! { DIAGNOSTICS }
+#[cfg(not(stage0))]
+__build_diagnostic_array! { librustc_typeck, DIAGNOSTICS }
index 3a63e2ab59cc85ed5ddfd4356cac3813eb437c93..4841f36c7f74719d15e0a51fb20209f4399351f5 100644 (file)
@@ -943,7 +943,6 @@ impl<'a, K, V> ExactSizeIterator for Drain<'a, K, V> {
     fn len(&self) -> usize { self.table.size() }
 }
 
-#[unsafe_destructor]
 impl<'a, K: 'a, V: 'a> Drop for Drain<'a, K, V> {
     fn drop(&mut self) {
         for _ in self.by_ref() {}
@@ -986,7 +985,6 @@ fn clone(&self) -> RawTable<K, V> {
     }
 }
 
-#[unsafe_destructor]
 impl<K, V> Drop for RawTable<K, V> {
     fn drop(&mut self) {
         if self.capacity == 0 || self.capacity == mem::POST_DROP_USIZE {
index ef72cbc96e18f54a67652f83bae7e427618304aa..8b90fce6fc4fc075709c354600e9d1daf4b18782 100644 (file)
@@ -125,7 +125,9 @@ mod tests {
     use path::Path;
 
     #[test]
-    #[cfg_attr(any(windows, target_os = "android"), ignore)] // FIXME #8818, #10379
+    #[cfg_attr(any(windows,
+                   target_os = "android",  // FIXME #10379
+                   target_env = "musl"), ignore)]
     fn test_loading_cosine() {
         // The math library does not need to be loaded since it is already
         // statically linked in
index b5dfbf796d3bce212ab4c1053710a8334f27a32a..2b15a4ff83ed13a94939240b68d5c45a44f6e056 100644 (file)
@@ -20,6 +20,7 @@
 use core::prelude::*;
 
 use fmt;
+use ffi::OsString;
 use io::{self, Error, ErrorKind, SeekFrom, Seek, Read, Write};
 use path::{Path, PathBuf};
 use sys::fs2 as fs_imp;
@@ -146,6 +147,20 @@ pub struct WalkDir {
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct Permissions(fs_imp::FilePermissions);
 
+/// An structure representing a type of file with accessors for each file type.
+#[unstable(feature = "file_type", reason = "recently added API")]
+#[derive(Copy, Clone, PartialEq, Eq, Hash)]
+pub struct FileType(fs_imp::FileType);
+
+/// A builder used to create directories in various manners.
+///
+/// This builder also supports platform-specific options.
+#[unstable(feature = "dir_builder", reason = "recently added API")]
+pub struct DirBuilder {
+    inner: fs_imp::DirBuilder,
+    recursive: bool,
+}
+
 impl File {
     /// Attempts to open a file in read-only mode.
     ///
@@ -485,6 +500,12 @@ fn as_inner_mut(&mut self) -> &mut fs_imp::OpenOptions { &mut self.0 }
 }
 
 impl Metadata {
+    /// Returns the file type for this metadata.
+    #[unstable(feature = "file_type", reason = "recently added API")]
+    pub fn file_type(&self) -> FileType {
+        FileType(self.0.file_type())
+    }
+
     /// Returns whether this metadata is for a directory.
     ///
     /// # Examples
@@ -500,7 +521,7 @@ impl Metadata {
     /// # }
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn is_dir(&self) -> bool { self.0.is_dir() }
+    pub fn is_dir(&self) -> bool { self.file_type().is_dir() }
 
     /// Returns whether this metadata is for a regular file.
     ///
@@ -517,7 +538,7 @@ pub fn is_dir(&self) -> bool { self.0.is_dir() }
     /// # }
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn is_file(&self) -> bool { self.0.is_file() }
+    pub fn is_file(&self) -> bool { self.file_type().is_file() }
 
     /// Returns the size of the file, in bytes, this metadata is for.
     ///
@@ -562,7 +583,11 @@ pub fn permissions(&self) -> Permissions {
                reason = "the return type of u64 is not quite appropriate for \
                          this method and may change if the standard library \
                          gains a type to represent a moment in time")]
-    pub fn accessed(&self) -> u64 { self.0.accessed() }
+    #[deprecated(since = "1.1.0",
+                 reason = "use os::platform::fs::MetadataExt extension traits")]
+    pub fn accessed(&self) -> u64 {
+        self.adjust_time(self.0.accessed())
+    }
 
     /// Returns the most recent modification time for a file.
     ///
@@ -571,7 +596,21 @@ pub fn accessed(&self) -> u64 { self.0.accessed() }
                reason = "the return type of u64 is not quite appropriate for \
                          this method and may change if the standard library \
                          gains a type to represent a moment in time")]
-    pub fn modified(&self) -> u64 { self.0.modified() }
+    #[deprecated(since = "1.1.0",
+                 reason = "use os::platform::fs::MetadataExt extension traits")]
+    pub fn modified(&self) -> u64 {
+        self.adjust_time(self.0.modified())
+    }
+
+    fn adjust_time(&self, val: u64) -> u64 {
+        // FILETIME (what `val` represents) is in 100ns intervals and there are
+        // 10000 intervals in a millisecond.
+        if cfg!(windows) {val / 10000} else {val}
+    }
+}
+
+impl AsInner<fs_imp::FileAttr> for Metadata {
+    fn as_inner(&self) -> &fs_imp::FileAttr { &self.0 }
 }
 
 impl Permissions {
@@ -624,6 +663,18 @@ pub fn set_readonly(&mut self, readonly: bool) {
     }
 }
 
+#[unstable(feature = "file_type", reason = "recently added API")]
+impl FileType {
+    /// Test whether this file type represents a directory.
+    pub fn is_dir(&self) -> bool { self.0.is_dir() }
+
+    /// Test whether this file type represents a regular file.
+    pub fn is_file(&self) -> bool { self.0.is_file() }
+
+    /// Test whether this file type represents a symbolic link.
+    pub fn is_symlink(&self) -> bool { self.0.is_symlink() }
+}
+
 impl FromInner<fs_imp::FilePermissions> for Permissions {
     fn from_inner(f: fs_imp::FilePermissions) -> Permissions {
         Permissions(f)
@@ -674,6 +725,47 @@ impl DirEntry {
     /// The exact text, of course, depends on what files you have in `.`.
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn path(&self) -> PathBuf { self.0.path() }
+
+    /// Return the metadata for the file that this entry points at.
+    ///
+    /// This function will not traverse symlinks if this entry points at a
+    /// symlink.
+    ///
+    /// # Platform behavior
+    ///
+    /// 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.
+    #[unstable(feature = "dir_entry_ext", reason = "recently added API")]
+    pub fn metadata(&self) -> io::Result<Metadata> {
+        self.0.metadata().map(Metadata)
+    }
+
+    /// Return the file type for the file that this entry points at.
+    ///
+    /// This function will not traverse symlinks if this entry points at a
+    /// symlink.
+    ///
+    /// # Platform behavior
+    ///
+    /// 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.
+    #[unstable(feature = "dir_entry_ext", reason = "recently added API")]
+    pub fn file_type(&self) -> io::Result<FileType> {
+        self.0.file_type().map(FileType)
+    }
+
+    /// Returns the bare file name of this directory entry without any other
+    /// leading path component.
+    #[unstable(feature = "dir_entry_ext", reason = "recently added API")]
+    pub fn file_name(&self) -> OsString {
+        self.0.file_name()
+    }
+}
+
+impl AsInner<fs_imp::DirEntry> for DirEntry {
+    fn as_inner(&self) -> &fs_imp::DirEntry { &self.0 }
 }
 
 /// Removes a file from the underlying filesystem.
@@ -731,6 +823,25 @@ pub fn metadata<P: AsRef<Path>>(path: P) -> io::Result<Metadata> {
     fs_imp::stat(path.as_ref()).map(Metadata)
 }
 
+/// Query the metadata about a file without following symlinks.
+///
+/// # Examples
+///
+/// ```rust
+/// #![feature(symlink_metadata)]
+/// # fn foo() -> std::io::Result<()> {
+/// use std::fs;
+///
+/// let attr = try!(fs::symlink_metadata("/some/file/path.txt"));
+/// // inspect attr ...
+/// # Ok(())
+/// # }
+/// ```
+#[unstable(feature = "symlink_metadata", reason = "recently added API")]
+pub fn symlink_metadata<P: AsRef<Path>>(path: P) -> io::Result<Metadata> {
+    fs_imp::lstat(path.as_ref()).map(Metadata)
+}
+
 /// Rename a file or directory to a new name.
 ///
 /// # Errors
@@ -869,6 +980,13 @@ pub fn read_link<P: AsRef<Path>>(path: P) -> io::Result<PathBuf> {
     fs_imp::readlink(path.as_ref())
 }
 
+/// Returns the canonical form of a path with all intermediate components
+/// normalized and symbolic links resolved.
+#[unstable(feature = "fs_canonicalize", reason = "recently added API")]
+pub fn canonicalize<P: AsRef<Path>>(path: P) -> io::Result<PathBuf> {
+    fs_imp::canonicalize(path.as_ref())
+}
+
 /// Creates a new, empty directory at the provided path
 ///
 /// # Errors
@@ -888,7 +1006,7 @@ pub fn read_link<P: AsRef<Path>>(path: P) -> io::Result<PathBuf> {
 /// ```
 #[stable(feature = "rust1", since = "1.0.0")]
 pub fn create_dir<P: AsRef<Path>>(path: P) -> io::Result<()> {
-    fs_imp::mkdir(path.as_ref())
+    DirBuilder::new().create(path.as_ref())
 }
 
 /// Recursively create a directory and all of its parent components if they
@@ -913,10 +1031,7 @@ pub fn create_dir<P: AsRef<Path>>(path: P) -> io::Result<()> {
 /// ```
 #[stable(feature = "rust1", since = "1.0.0")]
 pub fn create_dir_all<P: AsRef<Path>>(path: P) -> io::Result<()> {
-    let path = path.as_ref();
-    if path == Path::new("") || path.is_dir() { return Ok(()) }
-    if let Some(p) = path.parent() { try!(create_dir_all(p)) }
-    create_dir(path)
+    DirBuilder::new().recursive(true).create(path.as_ref())
 }
 
 /// Removes an existing, empty directory.
@@ -966,19 +1081,14 @@ pub fn remove_dir_all<P: AsRef<Path>>(path: P) -> io::Result<()> {
     let path = path.as_ref();
     for child in try!(read_dir(path)) {
         let child = try!(child).path();
-        let stat = try!(lstat(&*child));
+        let stat = try!(symlink_metadata(&*child));
         if stat.is_dir() {
             try!(remove_dir_all(&*child));
         } else {
             try!(remove_file(&*child));
         }
     }
-    return remove_dir(path);
-
-    #[cfg(unix)]
-    fn lstat(path: &Path) -> io::Result<fs_imp::FileAttr> { fs_imp::lstat(path) }
-    #[cfg(windows)]
-    fn lstat(path: &Path) -> io::Result<fs_imp::FileAttr> { fs_imp::stat(path) }
+    remove_dir(path)
 }
 
 /// Returns an iterator over the entries within a directory.
@@ -1073,11 +1183,37 @@ fn next(&mut self) -> Option<io::Result<DirEntry>> {
 pub trait PathExt {
     /// Gets information on the file, directory, etc at this path.
     ///
-    /// Consult the `fs::stat` documentation for more info.
+    /// Consult the `fs::metadata` documentation for more info.
     ///
-    /// This call preserves identical runtime/error semantics with `file::stat`.
+    /// This call preserves identical runtime/error semantics with
+    /// `fs::metadata`.
     fn metadata(&self) -> io::Result<Metadata>;
 
+    /// Gets information on the file, directory, etc at this path.
+    ///
+    /// Consult the `fs::symlink_metadata` documentation for more info.
+    ///
+    /// This call preserves identical runtime/error semantics with
+    /// `fs::symlink_metadata`.
+    fn symlink_metadata(&self) -> io::Result<Metadata>;
+
+    /// Returns the canonical form of a path, normalizing all components and
+    /// eliminate all symlinks.
+    ///
+    /// This call preserves identical runtime/error semantics with
+    /// `fs::canonicalize`.
+    fn canonicalize(&self) -> io::Result<PathBuf>;
+
+    /// Reads the symlink at this path.
+    ///
+    /// For more information see `fs::read_link`.
+    fn read_link(&self) -> io::Result<PathBuf>;
+
+    /// Reads the directory at this path.
+    ///
+    /// For more information see `fs::read_dir`.
+    fn read_dir(&self) -> io::Result<ReadDir>;
+
     /// Boolean value indicator whether the underlying file exists on the local
     /// filesystem. Returns false in exactly the cases where `fs::stat` fails.
     fn exists(&self) -> bool;
@@ -1098,12 +1234,16 @@ pub trait PathExt {
 
 impl PathExt for Path {
     fn metadata(&self) -> io::Result<Metadata> { metadata(self) }
-
+    fn symlink_metadata(&self) -> io::Result<Metadata> { symlink_metadata(self) }
+    fn canonicalize(&self) -> io::Result<PathBuf> { canonicalize(self) }
+    fn read_link(&self) -> io::Result<PathBuf> { read_link(self) }
+    fn read_dir(&self) -> io::Result<ReadDir> { read_dir(self) }
     fn exists(&self) -> bool { metadata(self).is_ok() }
 
     fn is_file(&self) -> bool {
         metadata(self).map(|s| s.is_file()).unwrap_or(false)
     }
+
     fn is_dir(&self) -> bool {
         metadata(self).map(|s| s.is_dir()).unwrap_or(false)
     }
@@ -1152,6 +1292,52 @@ pub fn set_permissions<P: AsRef<Path>>(path: P, perm: Permissions) -> io::Result
     fs_imp::set_perm(path.as_ref(), perm.0)
 }
 
+impl DirBuilder {
+    /// Creates a new set of options with default mode/security settings for all
+    /// platforms and also non-recursive.
+    pub fn new() -> DirBuilder {
+        DirBuilder {
+            inner: fs_imp::DirBuilder::new(),
+            recursive: false,
+        }
+    }
+
+    /// Indicate that directories create should be created recursively, creating
+    /// all parent directories if they do not exist with the same security and
+    /// permissions settings.
+    ///
+    /// This option defaults to `false`
+    pub fn recursive(&mut self, recursive: bool) -> &mut Self {
+        self.recursive = recursive;
+        self
+    }
+
+    /// Create the specified directory with the options configured in this
+    /// builder.
+    pub fn create<P: AsRef<Path>>(&self, path: P) -> io::Result<()> {
+        let path = path.as_ref();
+        if self.recursive {
+            self.create_dir_all(path)
+        } else {
+            self.inner.mkdir(path)
+        }
+    }
+
+    fn create_dir_all(&self, path: &Path) -> io::Result<()> {
+        if path == Path::new("") || path.is_dir() { return Ok(()) }
+        if let Some(p) = path.parent() {
+            try!(self.create_dir_all(p))
+        }
+        self.inner.mkdir(path)
+    }
+}
+
+impl AsInnerMut<fs_imp::DirBuilder> for DirBuilder {
+    fn as_inner_mut(&mut self) -> &mut fs_imp::DirBuilder {
+        &mut self.inner
+    }
+}
+
 #[cfg(test)]
 mod tests {
     #![allow(deprecated)] //rand
@@ -1924,4 +2110,74 @@ fn mkdir_trailing_slash() {
         let path = tmpdir.join("file");
         check!(fs::create_dir_all(&path.join("a/")));
     }
+
+    #[test]
+    #[cfg(not(windows))]
+    fn realpath_works() {
+        let tmpdir = tmpdir();
+        let tmpdir = fs::canonicalize(tmpdir.path()).unwrap();
+        let file = tmpdir.join("test");
+        let dir = tmpdir.join("test2");
+        let link = dir.join("link");
+        let linkdir = tmpdir.join("test3");
+
+        File::create(&file).unwrap();
+        fs::create_dir(&dir).unwrap();
+        fs::soft_link(&file, &link).unwrap();
+        fs::soft_link(&dir, &linkdir).unwrap();
+
+        assert!(link.symlink_metadata().unwrap().file_type().is_symlink());
+
+        assert_eq!(fs::canonicalize(&tmpdir).unwrap(), tmpdir);
+        assert_eq!(fs::canonicalize(&file).unwrap(), file);
+        assert_eq!(fs::canonicalize(&link).unwrap(), file);
+        assert_eq!(fs::canonicalize(&linkdir).unwrap(), dir);
+        assert_eq!(fs::canonicalize(&linkdir.join("link")).unwrap(), file);
+    }
+
+    #[test]
+    #[cfg(not(windows))]
+    fn realpath_works_tricky() {
+        let tmpdir = tmpdir();
+        let tmpdir = fs::canonicalize(tmpdir.path()).unwrap();
+
+        let a = tmpdir.join("a");
+        let b = a.join("b");
+        let c = b.join("c");
+        let d = a.join("d");
+        let e = d.join("e");
+        let f = a.join("f");
+
+        fs::create_dir_all(&b).unwrap();
+        fs::create_dir_all(&d).unwrap();
+        File::create(&f).unwrap();
+        fs::soft_link("../d/e", &c).unwrap();
+        fs::soft_link("../f", &e).unwrap();
+
+        assert_eq!(fs::canonicalize(&c).unwrap(), f);
+        assert_eq!(fs::canonicalize(&e).unwrap(), f);
+    }
+
+    #[test]
+    fn dir_entry_methods() {
+        let tmpdir = tmpdir();
+
+        fs::create_dir_all(&tmpdir.join("a")).unwrap();
+        File::create(&tmpdir.join("b")).unwrap();
+
+        for file in tmpdir.path().read_dir().unwrap().map(|f| f.unwrap()) {
+            let fname = file.file_name();
+            match fname.to_str() {
+                Some("a") => {
+                    assert!(file.file_type().unwrap().is_dir());
+                    assert!(file.metadata().unwrap().is_dir());
+                }
+                Some("b") => {
+                    assert!(file.file_type().unwrap().is_file());
+                    assert!(file.metadata().unwrap().is_file());
+                }
+                f => panic!("unknown file name: {:?}", f),
+            }
+        }
+    }
 }
index 67cac42c35ec2d0a5ee22cad0fbdae38b1366442..ed6023b2b81310013bd70277bb02e4cde06441ee 100644 (file)
@@ -292,7 +292,6 @@ fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {
     }
 }
 
-#[unsafe_destructor]
 impl<W: Write> Drop for BufWriter<W> {
     fn drop(&mut self) {
         if self.inner.is_some() {
index e8d15a95b806b1e32721ac83d5b62ef251db02ce..561c37ad950b05708f6e4b6f53472a1fbb1b2504 100644 (file)
@@ -70,8 +70,7 @@ fn append_to_string<F>(buf: &mut String, f: F) -> Result<usize>
     where F: FnOnce(&mut Vec<u8>) -> Result<usize>
 {
     struct Guard<'a> { s: &'a mut Vec<u8>, len: usize }
-    #[unsafe_destructor]
-    impl<'a> Drop for Guard<'a> {
+        impl<'a> Drop for Guard<'a> {
         fn drop(&mut self) {
             unsafe { self.s.set_len(self.len); }
         }
index 96665259a4d0c2d6cbf5328cf7fac00602b3ac13..6a84c6ace47b4d397875b8deab57a042e1196950 100644 (file)
 #![doc(test(attr(allow(dead_code, deprecated, unused_variables, unused_mut))))]
 
 #![feature(alloc)]
+#![feature(allow_internal_unstable)]
+#![feature(associated_consts)]
 #![feature(box_syntax)]
 #![feature(collections)]
 #![feature(core)]
+#![feature(debug_builders)]
+#![feature(into_cow)]
 #![feature(lang_items)]
 #![feature(libc)]
 #![feature(linkage, thread_local, asm)]
+#![feature(macro_reexport)]
 #![feature(optin_builtin_traits)]
 #![feature(rand)]
+#![feature(slice_patterns)]
 #![feature(staged_api)]
+#![feature(std_misc)]
+#![feature(str_char)]
 #![feature(unboxed_closures)]
 #![feature(unicode)]
-#![feature(unsafe_destructor)]
-#![feature(unsafe_no_drop_flag, filling_drop)]
-#![feature(macro_reexport)]
 #![feature(unique)]
-#![feature(allow_internal_unstable)]
-#![feature(str_char)]
-#![feature(into_cow)]
-#![feature(std_misc)]
-#![feature(slice_patterns)]
-#![feature(debug_builders)]
+#![feature(unsafe_no_drop_flag, filling_drop)]
 #![feature(zero_one)]
 #![cfg_attr(test, feature(float_from_str_radix))]
 #![cfg_attr(test, feature(test, rustc_private, std_misc))]
@@ -308,13 +308,12 @@ mod std {
     pub use sync; // used for select!()
     pub use error; // used for try!()
     pub use fmt; // used for any formatting strings
-    pub use option; // used for bitflags!{}
+    pub use option; // used for thread_local!{}
     pub use rt; // used for panic!()
     pub use vec; // used for vec![]
     pub use cell; // used for tls!
     pub use thread; // used for thread_local!
     pub use marker;  // used for tls!
-    pub use ops; // used for bitflags!
 
     // The test runner calls ::std::env::args() but really wants realstd
     #[cfg(test)] pub use realstd::env as env;
index f3e99a8541aaa6348af6cf59b385ccd3796b61bd..fcebe9c5e98d60e7c59c8df0c655267af8e9af8c 100644 (file)
 #[macro_export]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[allow_internal_unstable]
-#[cfg(stage0)]
-macro_rules! panic {
-    () => ({
-        panic!("explicit panic")
-    });
-    ($msg:expr) => ({
-        $crate::rt::begin_unwind($msg, {
-            // static requires less code at runtime, more constant data
-            static _FILE_LINE: (&'static str, usize) = (file!(), line!() as usize);
-            &_FILE_LINE
-        })
-    });
-    ($fmt:expr, $($arg:tt)+) => ({
-        $crate::rt::begin_unwind_fmt(format_args!($fmt, $($arg)+), {
-            // The leading _'s are to avoid dead code warnings if this is
-            // used inside a dead function. Just `#[allow(dead_code)]` is
-            // insufficient, since the user may have
-            // `#[forbid(dead_code)]` and which cannot be overridden.
-            static _FILE_LINE: (&'static str, u32) = (file!(), line!());
-            &_FILE_LINE
-        })
-    });
-}
-
 /// The entry point for panic of Rust tasks.
 ///
 /// This macro is used to inject panic into a Rust task, causing the task to
@@ -84,7 +60,6 @@ macro_rules! panic {
 #[macro_export]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[allow_internal_unstable]
-#[cfg(not(stage0))]
 macro_rules! panic {
     () => ({
         panic!("explicit panic")
index 2e34e46726fb27b84240ce2d3b10d983856137c2..b0bf9d0f8062674785c21a37fdb27c82ca530cfe 100644 (file)
@@ -41,7 +41,7 @@ pub enum SocketAddr {
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct SocketAddrV4 { inner: libc::sockaddr_in }
 
-/// An IPv6 socket address
+/// An IPv6 socket address.
 #[derive(Copy)]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct SocketAddrV6 { inner: libc::sockaddr_in6 }
@@ -56,7 +56,7 @@ pub fn new(ip: IpAddr, port: u16) -> SocketAddr {
         }
     }
 
-    /// Gets the IP address associated with this socket address.
+    /// Returns the IP address associated with this socket address.
     #[unstable(feature = "ip_addr", reason = "recent addition")]
     pub fn ip(&self) -> IpAddr {
         match *self {
@@ -65,7 +65,7 @@ pub fn ip(&self) -> IpAddr {
         }
     }
 
-    /// Gets the port number associated with this socket address
+    /// Returns the port number associated with this socket address.
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn port(&self) -> u16 {
         match *self {
@@ -89,7 +89,7 @@ pub fn new(ip: Ipv4Addr, port: u16) -> SocketAddrV4 {
         }
     }
 
-    /// Gets the IP address associated with this socket address.
+    /// Returns the IP address associated with this socket address.
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn ip(&self) -> &Ipv4Addr {
         unsafe {
@@ -97,7 +97,7 @@ pub fn ip(&self) -> &Ipv4Addr {
         }
     }
 
-    /// Gets the port number associated with this socket address
+    /// Returns the port number associated with this socket address.
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn port(&self) -> u16 { ntoh(self.inner.sin_port) }
 }
@@ -120,7 +120,7 @@ pub fn new(ip: Ipv6Addr, port: u16, flowinfo: u32, scope_id: u32)
         }
     }
 
-    /// Gets the IP address associated with this socket address.
+    /// Returns the IP address associated with this socket address.
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn ip(&self) -> &Ipv6Addr {
         unsafe {
@@ -128,16 +128,16 @@ pub fn ip(&self) -> &Ipv6Addr {
         }
     }
 
-    /// Gets the port number associated with this socket address
+    /// Returns the port number associated with this socket address.
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn port(&self) -> u16 { ntoh(self.inner.sin6_port) }
 
-    /// Gets scope ID associated with this address, corresponding to the
+    /// Returns scope ID associated with this address, corresponding to the
     /// `sin6_flowinfo` field in C.
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn flowinfo(&self) -> u32 { ntoh(self.inner.sin6_flowinfo) }
 
-    /// Gets scope ID associated with this address, corresponding to the
+    /// Returns scope ID associated with this address, corresponding to the
     /// `sin6_scope_id` field in C.
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn scope_id(&self) -> u32 { ntoh(self.inner.sin6_scope_id) }
index 065126c6fdbb564ea0fa30d338f895d2917754f8..9fd69840f7f054ee93927945b2211297bec44463 100644 (file)
@@ -60,7 +60,7 @@ pub enum Ipv6MulticastScope {
 impl Ipv4Addr {
     /// Creates a new IPv4 address from four eight-bit octets.
     ///
-    /// The result will represent the IP address a.b.c.d
+    /// The result will represent the IP address `a`.`b`.`c`.`d`.
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn new(a: u8, b: u8, c: u8, d: u8) -> Ipv4Addr {
         Ipv4Addr {
@@ -73,19 +73,19 @@ pub fn new(a: u8, b: u8, c: u8, d: u8) -> Ipv4Addr {
         }
     }
 
-    /// Returns the four eight-bit integers that make up this address
+    /// Returns the four eight-bit integers that make up this address.
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn octets(&self) -> [u8; 4] {
         let bits = ntoh(self.inner.s_addr);
         [(bits >> 24) as u8, (bits >> 16) as u8, (bits >> 8) as u8, bits as u8]
     }
 
-    /// Returns true for the special 'unspecified' address 0.0.0.0
+    /// Returns true for the special 'unspecified' address 0.0.0.0.
     pub fn is_unspecified(&self) -> bool {
         self.inner.s_addr == 0
     }
 
-    /// Returns true if this is a loopback address (127.0.0.0/8)
+    /// Returns true if this is a loopback address (127.0.0.0/8).
     pub fn is_loopback(&self) -> bool {
         self.octets()[0] == 127
     }
@@ -106,7 +106,7 @@ pub fn is_private(&self) -> bool {
         }
     }
 
-    /// Returns true if the address is link-local (169.254.0.0/16)
+    /// Returns true if the address is link-local (169.254.0.0/16).
     pub fn is_link_local(&self) -> bool {
         self.octets()[0] == 169 && self.octets()[1] == 254
     }
@@ -116,7 +116,7 @@ pub fn is_link_local(&self) -> bool {
     /// Non-globally-routable networks include the private networks (10.0.0.0/8,
     /// 172.16.0.0/12 and 192.168.0.0/16), the loopback network (127.0.0.0/8),
     /// the link-local network (169.254.0.0/16), the broadcast address (255.255.255.255/32) and
-    /// the test networks used for documentation (192.0.2.0/24, 198.51.100.0/24 and 203.0.113.0/24)
+    /// the test networks used for documentation (192.0.2.0/24, 198.51.100.0/24 and 203.0.113.0/24).
     pub fn is_global(&self) -> bool {
         !self.is_private() && !self.is_loopback() && !self.is_link_local() &&
         !self.is_broadcast() && !self.is_documentation()
@@ -131,13 +131,13 @@ pub fn is_multicast(&self) -> bool {
 
     /// Returns true if this is a broadcast address.
     ///
-    /// A broadcast address has all octets set to 255 as defined in RFC 919
+    /// A broadcast address has all octets set to 255 as defined in RFC 919.
     pub fn is_broadcast(&self) -> bool {
         self.octets()[0] == 255 && self.octets()[1] == 255 &&
         self.octets()[2] == 255 && self.octets()[3] == 255
     }
 
-    /// Returns true if this address is in a range designated for documentation
+    /// Returns true if this address is in a range designated for documentation.
     ///
     /// This is defined in RFC 5737
     /// - 192.0.2.0/24 (TEST-NET-1)
@@ -152,7 +152,7 @@ pub fn is_documentation(&self) -> bool {
         }
     }
 
-    /// Converts this address to an IPv4-compatible IPv6 address
+    /// Converts this address to an IPv4-compatible IPv6 address.
     ///
     /// a.b.c.d becomes ::a.b.c.d
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -162,7 +162,7 @@ pub fn to_ipv6_compatible(&self) -> Ipv6Addr {
                       ((self.octets()[2] as u16) << 8) | self.octets()[3] as u16)
     }
 
-    /// Converts this address to an IPv4-mapped IPv6 address
+    /// Converts this address to an IPv4-mapped IPv6 address.
     ///
     /// a.b.c.d becomes ::ffff:a.b.c.d
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -247,7 +247,7 @@ fn from_inner(addr: libc::in_addr) -> Ipv4Addr {
 impl Ipv6Addr {
     /// Creates a new IPv6 address from eight 16-bit segments.
     ///
-    /// The result will represent the IP address a:b:c:d:e:f:g:h
+    /// The result will represent the IP address a:b:c:d:e:f:g:h.
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn new(a: u16, b: u16, c: u16, d: u16, e: u16, f: u16, g: u16,
                h: u16) -> Ipv6Addr {
@@ -259,7 +259,7 @@ pub fn new(a: u16, b: u16, c: u16, d: u16, e: u16, f: u16, g: u16,
         }
     }
 
-    /// Returns the eight 16-bit segments that make up this address
+    /// Returns the eight 16-bit segments that make up this address.
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn segments(&self) -> [u16; 8] {
         [ntoh(self.inner.s6_addr[0]),
@@ -272,12 +272,12 @@ pub fn new(a: u16, b: u16, c: u16, d: u16, e: u16, f: u16, g: u16,
          ntoh(self.inner.s6_addr[7])]
     }
 
-    /// Returns true for the special 'unspecified' address ::
+    /// Returns true for the special 'unspecified' address ::.
     pub fn is_unspecified(&self) -> bool {
         self.segments() == [0, 0, 0, 0, 0, 0, 0, 0]
     }
 
-    /// Returns true if this is a loopback address (::1)
+    /// Returns true if this is a loopback address (::1).
     pub fn is_loopback(&self) -> bool {
         self.segments() == [0, 0, 0, 0, 0, 0, 0, 1]
     }
@@ -295,25 +295,25 @@ pub fn is_global(&self) -> bool {
         }
     }
 
-    /// Returns true if this is a unique local address (IPv6)
+    /// Returns true if this is a unique local address (IPv6).
     ///
-    /// Unique local addresses are defined in RFC4193 and have the form fc00::/7
+    /// Unique local addresses are defined in RFC4193 and have the form fc00::/7.
     pub fn is_unique_local(&self) -> bool {
         (self.segments()[0] & 0xfe00) == 0xfc00
     }
 
-    /// Returns true if the address is unicast and link-local (fe80::/10)
+    /// Returns true if the address is unicast and link-local (fe80::/10).
     pub fn is_unicast_link_local(&self) -> bool {
         (self.segments()[0] & 0xffc0) == 0xfe80
     }
 
     /// Returns true if this is a deprecated unicast site-local address (IPv6
-    /// fec0::/10)
+    /// fec0::/10).
     pub fn is_unicast_site_local(&self) -> bool {
         (self.segments()[0] & 0xffc0) == 0xfec0
     }
 
-    /// Returns true if the address is a globally routable unicast address
+    /// Returns true if the address is a globally routable unicast address.
     ///
     /// Non-globally-routable unicast addresses include the loopback address,
     /// the link-local addresses, the deprecated site-local addresses and the
index 3bfc764e540b21b900f0a95673a4c3c7288dbd03..2e7c0a2c80e59bac54a00eeaf686df2bbe70a169 100644 (file)
@@ -8,10 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-//! Networking primitives for TCP/UDP communication
-//!
-//! > **NOTE**: This module is very much a work in progress and is under active
-//! > development.
+//! Networking primitives for TCP/UDP communication.
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
index e48d0e6008b87f4ab0837b7c112127c293276a96..130e1eee8f924e1a456f93e923da329d186663bd 100644 (file)
@@ -125,7 +125,7 @@ pub fn try_clone(&self) -> io::Result<TcpStream> {
         self.0.duplicate().map(TcpStream)
     }
 
-    /// Sets the nodelay flag on this connection to the boolean specified
+    /// Sets the nodelay flag on this connection to the boolean specified.
     pub fn set_nodelay(&self, nodelay: bool) -> io::Result<()> {
         self.0.set_nodelay(nodelay)
     }
index 1955b895300ead37b634f3e191f32129b284396e..0b04ecb1b7228565577b5a958348922a5e596db6 100644 (file)
@@ -50,8 +50,8 @@
 impl UdpSocket {
     /// Creates a UDP socket from the given address.
     ///
-    /// Address type can be any implementor of `ToSocketAddr` trait. See its
-    /// documentation for concrete examples.
+    /// The address type can be any implementor of `ToSocketAddr` trait. See
+    /// its documentation for concrete examples.
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn bind<A: ToSocketAddrs>(addr: A) -> io::Result<UdpSocket> {
         super::each_addr(addr, net_imp::UdpSocket::bind).map(UdpSocket)
@@ -64,8 +64,8 @@ pub fn recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
         self.0.recv_from(buf)
     }
 
-    /// Sends data on the socket to the given address. Returns nothing on
-    /// success.
+    /// Sends data on the socket to the given address. On success, returns the
+    /// number of bytes written.
     ///
     /// Address type can be any implementor of `ToSocketAddrs` trait. See its
     /// documentation for concrete examples.
@@ -95,34 +95,34 @@ pub fn try_clone(&self) -> io::Result<UdpSocket> {
         self.0.duplicate().map(UdpSocket)
     }
 
-    /// Sets the broadcast flag on or off
+    /// Sets the broadcast flag on or off.
     pub fn set_broadcast(&self, on: bool) -> io::Result<()> {
         self.0.set_broadcast(on)
     }
 
-    /// Sets the multicast loop flag to the specified value
+    /// Sets the multicast loop flag to the specified value.
     ///
     /// This lets multicast packets loop back to local sockets (if enabled)
     pub fn set_multicast_loop(&self, on: bool) -> io::Result<()> {
         self.0.set_multicast_loop(on)
     }
 
-    /// Joins a multicast IP address (becomes a member of it)
+    /// Joins a multicast IP address (becomes a member of it).
     pub fn join_multicast(&self, multi: &IpAddr) -> io::Result<()> {
         self.0.join_multicast(multi)
     }
 
-    /// Leaves a multicast IP address (drops membership from it)
+    /// Leaves a multicast IP address (drops membership from it).
     pub fn leave_multicast(&self, multi: &IpAddr) -> io::Result<()> {
         self.0.leave_multicast(multi)
     }
 
-    /// Sets the multicast TTL
+    /// Sets the multicast TTL.
     pub fn set_multicast_time_to_live(&self, ttl: i32) -> io::Result<()> {
         self.0.multicast_time_to_live(ttl)
     }
 
-    /// Sets this socket's TTL
+    /// Sets this socket's TTL.
     pub fn set_time_to_live(&self, ttl: i32) -> io::Result<()> {
         self.0.time_to_live(ttl)
     }
diff --git a/src/libstd/os.rs b/src/libstd/os.rs
deleted file mode 100644 (file)
index ee0f04c..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-//! OS-specific functionality
-
-#![stable(feature = "os", since = "1.0.0")]
-
-#[cfg(unix)] pub use sys::ext as unix;
-#[cfg(windows)] pub use sys::ext as windows;
diff --git a/src/libstd/os/android/mod.rs b/src/libstd/os/android/mod.rs
new file mode 100644 (file)
index 0000000..346a903
--- /dev/null
@@ -0,0 +1,19 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! Android-specific definitions
+
+#![unstable(feature = "raw_ext", reason = "recently added API")]
+
+pub mod raw;
+
+pub mod fs {
+    pub use sys::fs2::MetadataExt;
+}
diff --git a/src/libstd/os/android/raw.rs b/src/libstd/os/android/raw.rs
new file mode 100644 (file)
index 0000000..538ed7c
--- /dev/null
@@ -0,0 +1,46 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! Android-specific raw type definitions
+
+use os::raw::{c_uint, c_uchar, c_ulonglong, c_longlong, c_ulong};
+use os::unix::raw::{uid_t, gid_t};
+
+pub type blkcnt_t = u32;
+pub type blksize_t = u32;
+pub type dev_t = u32;
+pub type ino_t = u32;
+pub type mode_t = u16;
+pub type nlink_t = u16;
+pub type off_t = i32;
+pub type time_t = i32;
+
+#[repr(C)]
+pub struct stat {
+    pub st_dev: c_ulonglong,
+    pub __pad0: [c_uchar; 4],
+    pub __st_ino: ino_t,
+    pub st_mode: c_uint,
+    pub st_nlink: c_uint,
+    pub st_uid: uid_t,
+    pub st_gid: gid_t,
+    pub st_rdev: c_ulonglong,
+    pub __pad3: [c_uchar; 4],
+    pub st_size: c_longlong,
+    pub st_blksize: blksize_t,
+    pub st_blocks: c_ulonglong,
+    pub st_atime: time_t,
+    pub st_atime_nsec: c_ulong,
+    pub st_mtime: time_t,
+    pub st_mtime_nsec: c_ulong,
+    pub st_ctime: time_t,
+    pub st_ctime_nsec: c_ulong,
+    pub st_ino: c_ulonglong,
+}
diff --git a/src/libstd/os/bitrig/mod.rs b/src/libstd/os/bitrig/mod.rs
new file mode 100644 (file)
index 0000000..01ea542
--- /dev/null
@@ -0,0 +1,19 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! Bitrig-specific definitions
+
+#![unstable(feature = "raw_ext", reason = "recently added API")]
+
+pub mod raw;
+
+pub mod fs {
+    pub use sys::fs2::MetadataExt;
+}
diff --git a/src/libstd/os/bitrig/raw.rs b/src/libstd/os/bitrig/raw.rs
new file mode 100644 (file)
index 0000000..aebc21a
--- /dev/null
@@ -0,0 +1,48 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! Bitrig-specific raw type definitions
+
+use os::raw::c_long;
+use os::unix::raw::{uid_t, gid_t};
+
+pub type blkcnt_t = i64;
+pub type blksize_t = u32;
+pub type dev_t = i32;
+pub type fflags_t = u32; // type not declared, but struct stat have u_int32_t
+pub type ino_t = u64;
+pub type mode_t = u32;
+pub type nlink_t = u32;
+pub type off_t = i64;
+pub type time_t = i64;
+
+#[repr(C)]
+pub struct stat {
+    pub st_mode: mode_t,
+    pub st_dev: dev_t,
+    pub st_ino: ino_t,
+    pub st_nlink: nlink_t,
+    pub st_uid: uid_t,
+    pub st_gid: gid_t,
+    pub st_rdev: dev_t,
+    pub st_atime: time_t,
+    pub st_atime_nsec: c_long,
+    pub st_mtime: time_t,
+    pub st_mtime_nsec: c_long,
+    pub st_ctime: time_t,
+    pub st_ctime_nsec: c_long,
+    pub st_size: off_t,
+    pub st_blocks: blkcnt_t,
+    pub st_blksize: blksize_t,
+    pub st_flags: fflags_t,
+    pub st_gen: u32,
+    pub st_birthtime: time_t,
+    pub st_birthtime_nsec: c_long,
+}
diff --git a/src/libstd/os/dragonfly/mod.rs b/src/libstd/os/dragonfly/mod.rs
new file mode 100644 (file)
index 0000000..677f8b7
--- /dev/null
@@ -0,0 +1,19 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! Dragonfly-specific definitions
+
+#![unstable(feature = "raw_ext", reason = "recently added API")]
+
+pub mod raw;
+
+pub mod fs {
+    pub use sys::fs2::MetadataExt;
+}
diff --git a/src/libstd/os/dragonfly/raw.rs b/src/libstd/os/dragonfly/raw.rs
new file mode 100644 (file)
index 0000000..22c811e
--- /dev/null
@@ -0,0 +1,50 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! Dragonfly-specific raw type definitions
+
+use os::raw::c_long;
+use os::unix::raw::{pid_t, uid_t, gid_t};
+
+pub type blkcnt_t = i64;
+pub type blksize_t = u32;
+pub type dev_t = u32;
+pub type fflags_t = u32;
+pub type ino_t = u64;
+pub type mode_t = u16;
+pub type nlink_t = u16;
+pub type off_t = i64;
+pub type time_t = i64;
+
+#[repr(C)]
+pub struct stat {
+    pub st_ino: ino_t,
+    pub st_nlink: nlink_t,
+    pub st_dev: dev_t,
+    pub st_mode: mode_t,
+    pub st_padding1: u16,
+    pub st_uid: uid_t,
+    pub st_gid: gid_t,
+    pub st_rdev: dev_t,
+    pub st_atime: time_t,
+    pub st_atime_nsec: c_long,
+    pub st_mtime: time_t,
+    pub st_mtime_nsec: c_long,
+    pub st_ctime: time_t,
+    pub st_ctime_nsec: c_long,
+    pub st_size: off_t,
+    pub st_blocks: blkcnt_t,
+    pub st_blksize: blksize_t,
+    pub st_flags: fflags_t,
+    pub st_gen: uint32_t,
+    pub st_lspare: int32_t,
+    pub st_qspare1: int64_t,
+    pub st_qspare2: int64_t,
+}
diff --git a/src/libstd/os/freebsd/mod.rs b/src/libstd/os/freebsd/mod.rs
new file mode 100644 (file)
index 0000000..73b6fd2
--- /dev/null
@@ -0,0 +1,19 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! FreeBSD-specific definitions
+
+#![unstable(feature = "raw_ext", reason = "recently added API")]
+
+pub mod raw;
+
+pub mod fs {
+    pub use sys::fs2::MetadataExt;
+}
diff --git a/src/libstd/os/freebsd/raw.rs b/src/libstd/os/freebsd/raw.rs
new file mode 100644 (file)
index 0000000..a810eff
--- /dev/null
@@ -0,0 +1,50 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! FreeBSD-specific raw type definitions
+
+use os::raw::c_long;
+use os::unix::raw::{uid_t, gid_t, pid_t};
+
+pub type blkcnt_t = i64;
+pub type blksize_t = i64;
+pub type dev_t = u32;
+pub type fflags_t = u32;
+pub type ino_t = u32;
+pub type mode_t = u16;
+pub type nlink_t = u16;
+pub type off_t = i64;
+pub type time_t = i64;
+
+#[repr(C)]
+pub struct stat {
+    pub st_dev: dev_t,
+    pub st_ino: ino_t,
+    pub st_mode: mode_t,
+    pub st_nlink: nlink_t,
+    pub st_uid: uid_t,
+    pub st_gid: gid_t,
+    pub st_rdev: dev_t,
+    pub st_atime: time_t,
+    pub st_atime_nsec: c_long,
+    pub st_mtime: time_t,
+    pub st_mtime_nsec: c_long,
+    pub st_ctime: time_t,
+    pub st_ctime_nsec: c_long,
+    pub st_size: off_t,
+    pub st_blocks: blkcnt_t,
+    pub st_blksize: blksize_t,
+    pub st_flags: fflags_t,
+    pub st_gen: u32,
+    pub st_lspare: i32,
+    pub st_birthtime: time_t,
+    pub st_birthtime_nsec: c_long,
+    pub __unused: [u8; 2],
+}
diff --git a/src/libstd/os/ios/mod.rs b/src/libstd/os/ios/mod.rs
new file mode 100644 (file)
index 0000000..d471cf1
--- /dev/null
@@ -0,0 +1,19 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! iOS-specific definitions
+
+#![unstable(feature = "raw_ext", reason = "recently added API")]
+
+pub mod raw;
+
+pub mod fs {
+    pub use sys::fs2::MetadataExt;
+}
diff --git a/src/libstd/os/ios/raw.rs b/src/libstd/os/ios/raw.rs
new file mode 100644 (file)
index 0000000..3266b38
--- /dev/null
@@ -0,0 +1,49 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! iOS-specific raw type definitions
+
+use os::raw::c_long;
+use os::unix::raw::{uid_t, gid_t, pid_t};
+
+pub type blkcnt_t = i64;
+pub type blksize_t = i32;
+pub type dev_t = i32;
+pub type ino_t = u64;
+pub type mode_t = u16;
+pub type nlink_t = u16;
+pub type off_t = i64;
+pub type time_t = c_long;
+
+#[repr(C)]
+pub struct stat {
+    pub st_dev: dev_t,
+    pub st_mode: mode_t,
+    pub st_nlink: nlink_t,
+    pub st_ino: ino_t,
+    pub st_uid: uid_t,
+    pub st_gid: gid_t,
+    pub st_rdev: dev_t,
+    pub st_atime: time_t,
+    pub st_atime_nsec: c_long,
+    pub st_mtime: time_t,
+    pub st_mtime_nsec: c_long,
+    pub st_ctime: time_t,
+    pub st_ctime_nsec: c_long,
+    pub st_birthtime: time_t,
+    pub st_birthtime_nsec: c_long,
+    pub st_size: off_t,
+    pub st_blocks: blkcnt_t,
+    pub st_blksize: blksize_t,
+    pub st_flags: u32,
+    pub st_gen: u32,
+    pub st_lspare: i32,
+    pub st_qspare: [i64; 2],
+}
diff --git a/src/libstd/os/linux/mod.rs b/src/libstd/os/linux/mod.rs
new file mode 100644 (file)
index 0000000..43376a1
--- /dev/null
@@ -0,0 +1,19 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! Linux-specific definitions
+
+#![unstable(feature = "raw_ext", reason = "recently added API")]
+
+pub mod raw;
+
+pub mod fs {
+    pub use sys::fs2::MetadataExt;
+}
diff --git a/src/libstd/os/linux/raw.rs b/src/libstd/os/linux/raw.rs
new file mode 100644 (file)
index 0000000..adce5f2
--- /dev/null
@@ -0,0 +1,170 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! Linux-specific raw type definitions
+
+pub type dev_t = u64;
+pub type mode_t = u32;
+
+#[doc(inline)]
+pub use self::arch::{off_t, ino_t, nlink_t, blksize_t, blkcnt_t, stat, time_t};
+
+#[cfg(any(target_arch = "x86",
+          target_arch = "le32",
+          target_arch = "powerpc",
+          target_arch = "arm"))]
+mod arch {
+    use super::{dev_t, mode_t};
+    use os::raw::{c_long, c_short};
+    use os::unix::raw::{gid_t, uid_t};
+
+    pub type blkcnt_t = i32;
+    pub type blksize_t = i32;
+    pub type ino_t = u32;
+    pub type nlink_t = u32;
+    pub type off_t = i32;
+    pub type time_t = i32;
+
+    #[repr(C)]
+    pub struct stat {
+        pub st_dev: dev_t,
+        pub __pad1: c_short,
+        pub st_ino: ino_t,
+        pub st_mode: mode_t,
+        pub st_nlink: nlink_t,
+        pub st_uid: uid_t,
+        pub st_gid: gid_t,
+        pub st_rdev: dev_t,
+        pub __pad2: c_short,
+        pub st_size: off_t,
+        pub st_blksize: blksize_t,
+        pub st_blocks: blkcnt_t,
+        pub st_atime: time_t,
+        pub st_atime_nsec: c_long,
+        pub st_mtime: time_t,
+        pub st_mtime_nsec: c_long,
+        pub st_ctime: time_t,
+        pub st_ctime_nsec: c_long,
+        pub __unused4: c_long,
+        pub __unused5: c_long,
+    }
+}
+
+#[cfg(any(target_arch = "mips",
+          target_arch = "mipsel"))]
+mod arch {
+    use super::{dev_t, mode_t};
+    use os::raw::c_long;
+    use os::unix::raw::{gid_t, uid_t};
+
+    pub type blkcnt_t = i32;
+    pub type blksize_t = i32;
+    pub type ino_t = u32;
+    pub type nlink_t = u32;
+    pub type off_t = i32;
+    pub type time_t = i32;
+
+    #[repr(C)]
+    pub struct stat {
+        pub st_dev: c_ulong,
+        pub st_pad1: [c_long; 3],
+        pub st_ino: ino_t,
+        pub st_mode: mode_t,
+        pub st_nlink: nlink_t,
+        pub st_uid: uid_t,
+        pub st_gid: gid_t,
+        pub st_rdev: c_ulong,
+        pub st_pad2: [c_long; 2],
+        pub st_size: off_t,
+        pub st_pad3: c_long,
+        pub st_atime: time_t,
+        pub st_atime_nsec: c_long,
+        pub st_mtime: time_t,
+        pub st_mtime_nsec: c_long,
+        pub st_ctime: time_t,
+        pub st_ctime_nsec: c_long,
+        pub st_blksize: blksize_t,
+        pub st_blocks: blkcnt_t,
+        pub st_pad5: [c_long; 14],
+    }
+}
+
+#[cfg(target_arch = "aarch64")]
+mod arch {
+    use super::{dev_t, mode_t};
+    use os::raw::{c_long, c_int};
+    use os::unix::raw::{gid_t, uid_t};
+
+    pub type blkcnt_t = i64;
+    pub type blksize_t = i32;
+    pub type ino_t = u64;
+    pub type nlink_t = u32;
+    pub type off_t = i64;
+    pub type time_t = i64;
+
+    #[repr(C)]
+    pub struct stat {
+        pub st_dev: dev_t,
+        pub st_ino: ino_t,
+        pub st_mode: mode_t,
+        pub st_nlink: nlink_t,
+        pub st_uid: uid_t,
+        pub st_gid: gid_t,
+        pub st_rdev: dev_t,
+        pub __pad1: dev_t,
+        pub st_size: off_t,
+        pub st_blksize: blksize_t,
+        pub __pad2: c_int,
+        pub st_blocks: blkcnt_t,
+        pub st_atime: time_t,
+        pub st_atime_nsec: c_long,
+        pub st_mtime: time_t,
+        pub st_mtime_nsec: c_long,
+        pub st_ctime: time_t,
+        pub st_ctime_nsec: c_long,
+        pub __unused: [c_int; 2],
+    }
+}
+
+#[cfg(target_arch = "x86_64")]
+mod arch {
+    use super::{dev_t, mode_t};
+    use os::raw::{c_long, c_int};
+    use os::unix::raw::{gid_t, uid_t};
+
+    pub type blkcnt_t = i64;
+    pub type blksize_t = i64;
+    pub type ino_t = u64;
+    pub type nlink_t = u64;
+    pub type off_t = i64;
+    pub type time_t = i64;
+
+    #[repr(C)]
+    pub struct stat {
+        pub st_dev: dev_t,
+        pub st_ino: ino_t,
+        pub st_nlink: nlink_t,
+        pub st_mode: mode_t,
+        pub st_uid: uid_t,
+        pub st_gid: gid_t,
+        pub __pad0: c_int,
+        pub st_rdev: dev_t,
+        pub st_size: off_t,
+        pub st_blksize: blksize_t,
+        pub st_blocks: blkcnt_t,
+        pub st_atime: time_t,
+        pub st_atime_nsec: c_long,
+        pub st_mtime: time_t,
+        pub st_mtime_nsec: c_long,
+        pub st_ctime: time_t,
+        pub st_ctime_nsec: c_long,
+        pub __unused: [c_long; 3],
+    }
+}
diff --git a/src/libstd/os/macos/mod.rs b/src/libstd/os/macos/mod.rs
new file mode 100644 (file)
index 0000000..bc5ff5b
--- /dev/null
@@ -0,0 +1,19 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! MacOS-specific definitions
+
+#![unstable(feature = "raw_ext", reason = "recently added API")]
+
+pub mod raw;
+
+pub mod fs {
+    pub use sys::fs2::MetadataExt;
+}
diff --git a/src/libstd/os/macos/raw.rs b/src/libstd/os/macos/raw.rs
new file mode 100644 (file)
index 0000000..03fcb76
--- /dev/null
@@ -0,0 +1,49 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! MacOS-specific raw type definitions
+
+use os::raw::c_long;
+use os::unix::raw::{uid_t, gid_t};
+
+pub type blkcnt_t = i64;
+pub type blksize_t = i32;
+pub type dev_t = i32;
+pub type ino_t = u64;
+pub type mode_t = u16;
+pub type nlink_t = u16;
+pub type off_t = i64;
+pub type time_t = c_long;
+
+#[repr(C)]
+pub struct stat {
+    pub st_dev: dev_t,
+    pub st_mode: mode_t,
+    pub st_nlink: nlink_t,
+    pub st_ino: ino_t,
+    pub st_uid: uid_t,
+    pub st_gid: gid_t,
+    pub st_rdev: dev_t,
+    pub st_atime: time_t,
+    pub st_atime_nsec: c_long,
+    pub st_mtime: time_t,
+    pub st_mtime_nsec: c_long,
+    pub st_ctime: time_t,
+    pub st_ctime_nsec: c_long,
+    pub st_birthtime: time_t,
+    pub st_birthtime_nsec: c_long,
+    pub st_size: off_t,
+    pub st_blocks: blkcnt_t,
+    pub st_blksize: blksize_t,
+    pub st_flags: u32,
+    pub st_gen: u32,
+    pub st_lspare: i32,
+    pub st_qspare: [i64; 2],
+}
diff --git a/src/libstd/os/mod.rs b/src/libstd/os/mod.rs
new file mode 100644 (file)
index 0000000..cc4b1c9
--- /dev/null
@@ -0,0 +1,29 @@
+// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! OS-specific functionality
+
+#![stable(feature = "os", since = "1.0.0")]
+#![allow(missing_docs, bad_style)]
+
+#[cfg(unix)]    pub use sys::ext as unix;
+#[cfg(windows)] pub use sys::ext as windows;
+
+#[cfg(target_os = "android")]   pub mod android;
+#[cfg(target_os = "bitrig")]    pub mod bitrig;
+#[cfg(target_os = "dragonfly")] pub mod dragonfly;
+#[cfg(target_os = "freebsd")]   pub mod freebsd;
+#[cfg(target_os = "ios")]       pub mod ios;
+#[cfg(target_os = "linux")]     pub mod linux;
+#[cfg(target_os = "macos")]     pub mod macos;
+#[cfg(target_os = "nacl")]      pub mod nacl;
+#[cfg(target_os = "openbsd")]   pub mod openbsd;
+
+pub mod raw;
diff --git a/src/libstd/os/nacl/mod.rs b/src/libstd/os/nacl/mod.rs
new file mode 100644 (file)
index 0000000..6baed03
--- /dev/null
@@ -0,0 +1,19 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! Nacl-specific definitions
+
+#![unstable(feature = "raw_ext", reason = "recently added API")]
+
+pub mod raw;
+
+pub mod fs {
+    pub use sys::fs2::MetadataExt;
+}
diff --git a/src/libstd/os/nacl/raw.rs b/src/libstd/os/nacl/raw.rs
new file mode 100644 (file)
index 0000000..9defa83
--- /dev/null
@@ -0,0 +1,169 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! Nacl-specific raw type definitions
+
+pub type dev_t = u64;
+pub type mode_t = u32;
+
+pub use self::arch::{off_t, ino_t, nlink_t, blksize_t, blkcnt_t, stat, time_t};
+
+#[cfg(any(target_arch = "x86",
+          target_arch = "le32",
+          target_arch = "powerpc",
+          target_arch = "arm"))]
+mod arch {
+    use super::{dev_t, mode_t};
+    use os::raw::{c_long, c_short};
+    use os::unix::raw::{gid_t, uid_t};
+
+    pub type blkcnt_t = i32;
+    pub type blksize_t = i32;
+    pub type ino_t = u32;
+    pub type nlink_t = u32;
+    pub type off_t = i32;
+    pub type time_t = i32;
+
+    #[repr(C)]
+    pub struct stat {
+        pub st_dev: dev_t,
+        pub __pad1: c_short,
+        pub st_ino: ino_t,
+        pub st_mode: mode_t,
+        pub st_nlink: nlink_t,
+        pub st_uid: uid_t,
+        pub st_gid: gid_t,
+        pub st_rdev: dev_t,
+        pub __pad2: c_short,
+        pub st_size: off_t,
+        pub st_blksize: blksize_t,
+        pub st_blocks: blkcnt_t,
+        pub st_atime: time_t,
+        pub st_atime_nsec: c_long,
+        pub st_mtime: time_t,
+        pub st_mtime_nsec: c_long,
+        pub st_ctime: time_t,
+        pub st_ctime_nsec: c_long,
+        pub __unused4: c_long,
+        pub __unused5: c_long,
+    }
+}
+
+#[cfg(any(target_arch = "mips",
+          target_arch = "mipsel"))]
+mod arch {
+    use super::{dev_t, mode_t};
+    use os::raw::c_long;
+    use os::unix::raw::{gid_t, uid_t};
+
+    pub type blkcnt_t = i32;
+    pub type blksize_t = i32;
+    pub type ino_t = u32;
+    pub type nlink_t = u32;
+    pub type off_t = i32;
+    pub type time_t = i32;
+
+    #[repr(C)]
+    pub struct stat {
+        pub st_dev: c_ulong,
+        pub st_pad1: [c_long; 3],
+        pub st_ino: ino_t,
+        pub st_mode: mode_t,
+        pub st_nlink: nlink_t,
+        pub st_uid: uid_t,
+        pub st_gid: gid_t,
+        pub st_rdev: c_ulong,
+        pub st_pad2: [c_long; 2],
+        pub st_size: off_t,
+        pub st_pad3: c_long,
+        pub st_atime: time_t,
+        pub st_atime_nsec: c_long,
+        pub st_mtime: time_t,
+        pub st_mtime_nsec: c_long,
+        pub st_ctime: time_t,
+        pub st_ctime_nsec: c_long,
+        pub st_blksize: blksize_t,
+        pub st_blocks: blkcnt_t,
+        pub st_pad5: [c_long; 14],
+    }
+}
+
+#[cfg(target_arch = "aarch64")]
+mod arch {
+    use super::{dev_t, mode_t};
+    use os::raw::{c_long, c_int};
+    use os::unix::raw::{gid_t, uid_t};
+
+    pub type blkcnt_t = i64;
+    pub type blksize_t = i32;
+    pub type ino_t = u64;
+    pub type nlink_t = u32;
+    pub type off_t = i64;
+    pub type time_t = i64;
+
+    #[repr(C)]
+    pub struct stat {
+        pub st_dev: dev_t,
+        pub st_ino: ino_t,
+        pub st_mode: mode_t,
+        pub st_nlink: nlink_t,
+        pub st_uid: uid_t,
+        pub st_gid: gid_t,
+        pub st_rdev: dev_t,
+        pub __pad1: dev_t,
+        pub st_size: off_t,
+        pub st_blksize: blksize_t,
+        pub __pad2: c_int,
+        pub st_blocks: blkcnt_t,
+        pub st_atime: time_t,
+        pub st_atime_nsec: c_long,
+        pub st_mtime: time_t,
+        pub st_mtime_nsec: c_long,
+        pub st_ctime: time_t,
+        pub st_ctime_nsec: c_long,
+        pub __unused: [c_int; 2],
+    }
+}
+
+#[cfg(target_arch = "x86_64")]
+mod arch {
+    use super::{dev_t, mode_t};
+    use os::raw::{c_long, c_int};
+    use os::unix::raw::{gid_t, uid_t};
+
+    pub type blkcnt_t = i64;
+    pub type blksize_t = i64;
+    pub type ino_t = u64;
+    pub type nlink_t = u64;
+    pub type off_t = i64;
+    pub type time_t = i64;
+
+    #[repr(C)]
+    pub struct stat {
+        pub st_dev: dev_t,
+        pub st_ino: ino_t,
+        pub st_nlink: nlink_t,
+        pub st_mode: mode_t,
+        pub st_uid: uid_t,
+        pub st_gid: gid_t,
+        pub __pad0: c_int,
+        pub st_rdev: dev_t,
+        pub st_size: off_t,
+        pub st_blksize: blksize_t,
+        pub st_blocks: blkcnt_t,
+        pub st_atime: time_t,
+        pub st_atime_nsec: c_long,
+        pub st_mtime: time_t,
+        pub st_mtime_nsec: c_long,
+        pub st_ctime: time_t,
+        pub st_ctime_nsec: c_long,
+        pub __unused: [c_long; 3],
+    }
+}
diff --git a/src/libstd/os/openbsd/mod.rs b/src/libstd/os/openbsd/mod.rs
new file mode 100644 (file)
index 0000000..1b1a100
--- /dev/null
@@ -0,0 +1,19 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! OpenBSD-specific definitions
+
+#![unstable(feature = "raw_ext", reason = "recently added API")]
+
+pub mod raw;
+
+pub mod fs {
+    pub use sys::fs2::MetadataExt;
+}
diff --git a/src/libstd/os/openbsd/raw.rs b/src/libstd/os/openbsd/raw.rs
new file mode 100644 (file)
index 0000000..632a8c3
--- /dev/null
@@ -0,0 +1,48 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! OpenBSD-specific raw type definitions
+
+use os::raw::c_long;
+use os::unix::raw::{uid_t, gid_t, pid_t};
+
+pub type blkcnt_t = i64;
+pub type blksize_t = u32;
+pub type dev_t = i32;
+pub type fflags_t = u32; // type not declared, but struct stat have u_int32_t
+pub type ino_t = u64;
+pub type mode_t = u32;
+pub type nlink_t = u32;
+pub type off_t = i64;
+pub type time_t = i64;
+
+#[repr(C)]
+pub struct stat {
+    pub st_mode: mode_t,
+    pub st_dev: dev_t,
+    pub st_ino: ino_t,
+    pub st_nlink: nlink_t,
+    pub st_uid: uid_t,
+    pub st_gid: gid_t,
+    pub st_rdev: dev_t,
+    pub st_atime: time_t,
+    pub st_atime_nsec: c_long,
+    pub st_mtime: time_t,
+    pub st_mtime_nsec: c_long,
+    pub st_ctime: time_t,
+    pub st_ctime_nsec: c_long,
+    pub st_size: off_t,
+    pub st_blocks: blkcnt_t,
+    pub st_blksize: blksize_t,
+    pub st_flags: fflags_t,
+    pub st_gen: u32,
+    pub st_birthtime: time_t,
+    pub st_birthtime_nsec: c_long,
+}
diff --git a/src/libstd/os/raw.rs b/src/libstd/os/raw.rs
new file mode 100644 (file)
index 0000000..44f4a1c
--- /dev/null
@@ -0,0 +1,92 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! Raw OS-specific types for the current platform/architecture
+
+#![unstable(feature = "raw_os", reason = "recently added API")]
+
+#[cfg(target_arch = "aarch64")]      pub type c_char = u8;
+#[cfg(not(target_arch = "aarch64"))] pub type c_char = i8;
+pub type c_schar = i8;
+pub type c_uchar = u8;
+pub type c_short = i16;
+pub type c_ushort = u16;
+pub type c_int = i32;
+pub type c_uint = u32;
+#[cfg(any(target_pointer_width = "32", windows))] pub type c_long = i32;
+#[cfg(any(target_pointer_width = "32", windows))] pub type c_ulong = u32;
+#[cfg(all(target_pointer_width = "64", not(windows)))] pub type c_long = i64;
+#[cfg(all(target_pointer_width = "64", not(windows)))] pub type c_ulong = u64;
+pub type c_longlong = i64;
+pub type c_ulonglong = u64;
+pub type c_float = f32;
+pub type c_double = f64;
+
+/// Type used to construct void pointers for use with C.
+///
+/// This type is only useful as a pointer target. Do not use it as a
+/// return type for FFI functions which have the `void` return type in
+/// C. Use the unit type `()` or omit the return type instead.
+// NB: For LLVM to recognize the void pointer type and by extension
+//     functions like malloc(), we need to have it represented as i8* in
+//     LLVM bitcode. The enum used here ensures this and prevents misuse
+//     of the "raw" type by only having private variants.. We need two
+//     variants, because the compiler complains about the repr attribute
+//     otherwise.
+#[repr(u8)]
+pub enum c_void {
+    #[doc(hidden)] __variant1,
+    #[doc(hidden)] __variant2,
+}
+
+#[cfg(test)]
+mod tests {
+    use any::TypeId;
+    use libc;
+    use mem;
+
+    macro_rules! ok {
+        ($($t:ident)*) => {$(
+            assert!(TypeId::of::<libc::$t>() == TypeId::of::<raw::$t>(),
+                    "{} is wrong", stringify!($t));
+        )*}
+    }
+
+    macro_rules! ok_size {
+        ($($t:ident)*) => {$(
+            assert!(mem::size_of::<libc::$t>() == mem::size_of::<raw::$t>(),
+                    "{} is wrong", stringify!($t));
+        )*}
+    }
+
+    #[test]
+    fn same() {
+        use os::raw;
+        ok!(c_char c_schar c_uchar c_short c_ushort c_int c_uint c_long c_ulong
+            c_longlong c_ulonglong c_float c_double);
+    }
+
+    #[cfg(unix)]
+    fn unix() {
+        {
+            use os::unix::raw;
+            ok!(uid_t gid_t dev_t ino_t mode_t nlink_t off_t blksize_t blkcnt_t);
+        }
+        {
+            use sys::platform::raw;
+            ok_size!(stat);
+        }
+    }
+
+    #[cfg(windows)]
+    fn windows() {
+        use os::windows::raw;
+    }
+}
index 610b3b3c019d4a45eb847ab4e2b7b1bea7e08c87..8f8699f4b9fea9f29f48a3530286ca1a8059a50f 100644 (file)
 /// ```should_panic
 /// use std::process::Command;
 ///
-/// let output = Command::new("/bin/cat").arg("file.txt").output().unwrap_or_else(|e| {
-///     panic!("failed to execute child: {}", e)
-/// });
-/// let contents = output.stdout;
-/// assert!(output.status.success());
+/// let mut child = Command::new("/bin/cat")
+///                         .arg("file.txt")
+///                         .spawn()
+///                         .unwrap_or_else(|e| { panic!("failed to execute child: {}", e) });
+///
+/// let ecode = child.wait()
+///                  .unwrap_or_else(|e| { panic!("failed to wait on child: {}", e) });
+///
+/// assert!(ecode.success());
 /// ```
 #[stable(feature = "process", since = "1.0.0")]
 pub struct Child {
@@ -118,9 +122,11 @@ fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
 /// ```
 /// use std::process::Command;
 ///
-/// let output = Command::new("sh").arg("-c").arg("echo hello").output().unwrap_or_else(|e| {
-///   panic!("failed to execute process: {}", e)
-/// });
+/// let output = Command::new("sh")
+///                      .arg("-c")
+///                      .arg("echo hello")
+///                      .output()
+///                      .unwrap_or_else(|e| { panic!("failed to execute process: {}", e) });
 /// let hello = output.stdout;
 /// ```
 #[stable(feature = "process", since = "1.0.0")]
@@ -140,7 +146,7 @@ impl Command {
     /// * No arguments to the program
     /// * Inherit the current process's environment
     /// * Inherit the current process's working directory
-    /// * Inherit stdin/stdout/stderr for `run` or `status`, but create pipes for `output`
+    /// * Inherit stdin/stdout/stderr for `spawn` or `status`, but create pipes for `output`
     ///
     /// Builder methods are provided to change these defaults and
     /// otherwise configure the process.
@@ -202,7 +208,6 @@ pub fn current_dir<P: AsRef<path::Path>>(&mut self, dir: P) -> &mut Command {
     }
 
     /// Configuration for the child process's stdin handle (file descriptor 0).
-    /// Defaults to `CreatePipe(true, false)` so the input can be written to.
     #[stable(feature = "process", since = "1.0.0")]
     pub fn stdin(&mut self, cfg: Stdio) -> &mut Command {
         self.stdin = Some(cfg.0);
@@ -210,7 +215,6 @@ pub fn stdin(&mut self, cfg: Stdio) -> &mut Command {
     }
 
     /// Configuration for the child process's stdout handle (file descriptor 1).
-    /// Defaults to `CreatePipe(false, true)` so the output can be collected.
     #[stable(feature = "process", since = "1.0.0")]
     pub fn stdout(&mut self, cfg: Stdio) -> &mut Command {
         self.stdout = Some(cfg.0);
@@ -218,7 +222,6 @@ pub fn stdout(&mut self, cfg: Stdio) -> &mut Command {
     }
 
     /// Configuration for the child process's stderr handle (file descriptor 2).
-    /// Defaults to `CreatePipe(false, true)` so the output can be collected.
     #[stable(feature = "process", since = "1.0.0")]
     pub fn stderr(&mut self, cfg: Stdio) -> &mut Command {
         self.stderr = Some(cfg.0);
@@ -356,7 +359,7 @@ pub struct Output {
     pub stderr: Vec<u8>,
 }
 
-/// Describes what to do with a standard io stream for a child process.
+/// Describes what to do with a standard I/O stream for a child process.
 #[stable(feature = "process", since = "1.0.0")]
 pub struct Stdio(StdioImp);
 
index 4b754bd5f589f22ac3d957986a6fcc536769d9bf..8f75ae5ef5cc8441cd5b3e687a8465687e7928f1 100644 (file)
@@ -97,10 +97,15 @@ pub enum _Unwind_Context {}
         extern "C" fn(unwind_code: _Unwind_Reason_Code,
                       exception: *mut _Unwind_Exception);
 
-#[cfg(any(target_os = "linux", target_os = "freebsd"))]
+#[cfg(any(all(target_os = "linux", not(target_env = "musl")),
+          target_os = "freebsd"))]
 #[link(name = "gcc_s")]
 extern {}
 
+#[cfg(all(target_os = "linux", target_env = "musl", not(test)))]
+#[link(name = "unwind", kind = "static")]
+extern {}
+
 #[cfg(any(target_os = "android", target_os = "openbsd"))]
 #[link(name = "gcc")]
 extern {}
index c880aae80fca749e4e7ba33980a22988dbddd5f6..a764b99e2805d88a3c722258a94687d20b285960 100644 (file)
@@ -510,23 +510,6 @@ pub fn begin_unwind_fmt(msg: fmt::Arguments, file_line: &(&'static str, u32)) ->
 
 /// This is the entry point of unwinding for panic!() and assert!().
 #[inline(never)] #[cold] // avoid code bloat at the call sites as much as possible
-#[cfg(stage0)]
-pub fn begin_unwind<M: Any + Send>(msg: M, file_line: &(&'static str, usize)) -> ! {
-    // Note that this should be the only allocation performed in this code path.
-    // Currently this means that panic!() on OOM will invoke this code path,
-    // but then again we're not really ready for panic on OOM anyway. If
-    // we do start doing this, then we should propagate this allocation to
-    // be performed in the parent of this thread instead of the thread that's
-    // panicking.
-
-    // see below for why we do the `Any` coercion here.
-    let (file, line) = *file_line;
-    begin_unwind_inner(Box::new(msg), &(file, line as u32))
-}
-
-/// This is the entry point of unwinding for panic!() and assert!().
-#[inline(never)] #[cold] // avoid code bloat at the call sites as much as possible
-#[cfg(not(stage0))]
 pub fn begin_unwind<M: Any + Send>(msg: M, file_line: &(&'static str, u32)) -> ! {
     // Note that this should be the only allocation performed in this code path.
     // Currently this means that panic!() on OOM will invoke this code path,
index 96c4bcec853dc28d8d687eae95b3b1e64f9f5a22..a7f3bc2bdc82c3a07d5d9441599f74afc9a0d819 100644 (file)
@@ -24,7 +24,7 @@
 //
 // On Linux, librt and libdl are indirect dependencies via std,
 // and binutils 2.22+ won't add them automatically
-#[cfg(target_os = "linux")]
+#[cfg(all(target_os = "linux", not(target_env = "musl")))]
 #[link(name = "dl")]
 #[link(name = "pthread")]
 extern {}
index 74e85db1a06ff1eba3517292ea35281c167ee984..61932225d79660472bccf97e4748dc0cdb2cb775 100644 (file)
@@ -619,7 +619,6 @@ fn clone(&self) -> Sender<T> {
     }
 }
 
-#[unsafe_destructor]
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T> Drop for Sender<T> {
     fn drop(&mut self) {
@@ -683,7 +682,6 @@ fn clone(&self) -> SyncSender<T> {
     }
 }
 
-#[unsafe_destructor]
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T> Drop for SyncSender<T> {
     fn drop(&mut self) {
@@ -930,7 +928,6 @@ fn into_iter(self) -> IntoIter<T> {
     }
 }
 
-#[unsafe_destructor]
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T> Drop for Receiver<T> {
     fn drop(&mut self) {
index 9b6c8f4dd9775bbabc18c00a3c68a85815fa8235..4ab5a796fcb43e3a0a38b570e987d59fa0cb4050 100644 (file)
@@ -138,7 +138,6 @@ pub fn pop(&self) -> PopResult<T> {
     }
 }
 
-#[unsafe_destructor]
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T> Drop for Queue<T> {
     fn drop(&mut self) {
index c6e8d87a22e71412c234f05de9694b2283779f73..ab45b722c45237dbc6a47d29ed07e69a9687392d 100644 (file)
@@ -367,7 +367,6 @@ pub fn abort_selection(&mut self) -> Result<bool, Receiver<T>> {
     }
 }
 
-#[unsafe_destructor]
 impl<T> Drop for Packet<T> {
     fn drop(&mut self) {
         assert_eq!(self.state.load(Ordering::SeqCst), DISCONNECTED);
index 58f16a83ba9353d164ec01515f5fd52b6ba391d8..fde99e11040d2a69e95171b4e3cc68f9cc8938a2 100644 (file)
@@ -315,7 +315,6 @@ pub unsafe fn remove(&mut self) {
     }
 }
 
-#[unsafe_destructor]
 impl Drop for Select {
     fn drop(&mut self) {
         assert!(self.head.is_null());
@@ -323,7 +322,6 @@ fn drop(&mut self) {
     }
 }
 
-#[unsafe_destructor]
 impl<'rx, T: Send> Drop for Handle<'rx, T> {
     fn drop(&mut self) {
         unsafe { self.remove() }
index 5c1610bdc317566fe49ae6fd0533f21756b2309e..09a02923f140c2727a1f31df39e1447f48dec4ad 100644 (file)
@@ -473,7 +473,6 @@ pub fn abort_selection(&mut self, _was_upgrade: bool) -> bool {
     }
 }
 
-#[unsafe_destructor]
 impl<T> Drop for Packet<T> {
     fn drop(&mut self) {
         // Note that this load is not only an assert for correctness about
index 4dd84364fa80ef0634832e194cf4242e04cd9272..f4b9c7d45fd2eb7afe6deb7aa107c7143af6d173 100644 (file)
@@ -226,7 +226,6 @@ pub fn peek<'a>(&'a self) -> Option<&'a mut T> {
     }
 }
 
-#[unsafe_destructor]
 impl<T> Drop for Queue<T> {
     fn drop(&mut self) {
         unsafe {
index f0363fae84f73f16ecdbf78f13e8006677eab7f3..1200e71d9afed23a3f84f1532fbbd8aa28abe99b 100644 (file)
@@ -471,7 +471,6 @@ pub fn abort_selection(&mut self,
     }
 }
 
-#[unsafe_destructor]
 impl<T> Drop for Packet<T> {
     fn drop(&mut self) {
         // Note that this load is not only an assert for correctness about
index 6221ca59b54f7094e0d47b102bd8ece1e57e30af..4687df107f6b1157e375c3c5149057650a614c87 100644 (file)
@@ -411,7 +411,6 @@ pub fn abort_selection(&self) -> bool {
     }
 }
 
-#[unsafe_destructor]
 impl<T> Drop for Packet<T> {
     fn drop(&mut self) {
         assert_eq!(self.channels.load(Ordering::SeqCst), 0);
index caf011c54f27a1c82b7b766f2a71c5d0bef5441c..30c7407a96d97f161df7f2281f1e3abc446a08c9 100644 (file)
@@ -244,7 +244,6 @@ pub fn is_poisoned(&self) -> bool {
     }
 }
 
-#[unsafe_destructor]
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T> Drop for Mutex<T> {
     fn drop(&mut self) {
@@ -340,7 +339,6 @@ fn deref_mut<'a>(&'a mut self) -> &'a mut T {
     }
 }
 
-#[unsafe_destructor]
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, T> Drop for MutexGuard<'a, T> {
     #[inline]
index 2ce974c1271aad77cb09b89ddb404caa829075d0..2d7123692289d32e17f71c777096fcdd8cac30ad 100644 (file)
@@ -59,7 +59,11 @@ impl Once {
     /// routine is currently running.
     ///
     /// When this function returns, it is guaranteed that some initialization
-    /// has run and completed (it may not be the closure specified).
+    /// has run and completed (it may not be the closure specified). It is also
+    /// guaranteed that any memory writes performed by the executed closure can
+    /// be reliably observed by other tasks at this point (there is a
+    /// happens-before relation between the closure and code executing after the
+    /// return).
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn call_once<F>(&'static self, f: F) where F: FnOnce() {
         // Optimize common path: load is much cheaper than fetch_add.
index 1ea92d5eff7fe92b4e019880ec46360209145ad6..a133bb01b610b9acf50f21287b33bb78c49b334e 100644 (file)
@@ -249,7 +249,6 @@ pub fn is_poisoned(&self) -> bool {
     }
 }
 
-#[unsafe_destructor]
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T> Drop for RwLock<T> {
     fn drop(&mut self) {
@@ -387,7 +386,6 @@ fn deref_mut(&mut self) -> &mut T {
     }
 }
 
-#[unsafe_destructor]
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, T> Drop for RwLockReadGuard<'a, T> {
     fn drop(&mut self) {
@@ -395,7 +393,6 @@ fn drop(&mut self) {
     }
 }
 
-#[unsafe_destructor]
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, T> Drop for RwLockWriteGuard<'a, T> {
     fn drop(&mut self) {
index be521095aa95f9fa1aeaaa46d457eb1dd2c7d584..776b3c5064ced43f905e158b600ed4e9dc06fba1 100644 (file)
@@ -100,7 +100,6 @@ pub fn access(&self) -> SemaphoreGuard {
     }
 }
 
-#[unsafe_destructor]
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<'a> Drop for SemaphoreGuard<'a> {
     fn drop(&mut self) {
index 00238500c3a85ae77b83230edd26fb3e8e89da5d..48c74b8d89effc23c21e861bf5b94099f20b9fb3 100644 (file)
@@ -96,7 +96,6 @@ pub fn try_lock(&self) -> TryLockResult<ReentrantMutexGuard<T>> {
     }
 }
 
-#[unsafe_destructor]
 impl<T> Drop for ReentrantMutex<T> {
     fn drop(&mut self) {
         // This is actually safe b/c we know that there is no further usage of
@@ -138,7 +137,6 @@ fn deref<'a>(&'a self) -> &'a T {
     }
 }
 
-#[unsafe_destructor]
 impl<'a, T> Drop for ReentrantMutexGuard<'a, T> {
     #[inline]
     fn drop(&mut self) {
index aa4bf821207648a3c4fe7cab02c37115bc2bae81..1e68eac5a67354b880b5a7e678a7ae8e67fda3ea 100644 (file)
@@ -161,6 +161,8 @@ pub fn utimes(filename: *const libc::c_char,
     pub fn gai_strerror(errcode: libc::c_int) -> *const libc::c_char;
     pub fn setgroups(ngroups: libc::c_int,
                      ptr: *const libc::c_void) -> libc::c_int;
+    pub fn realpath(pathname: *const libc::c_char, resolved: *mut libc::c_char)
+                    -> *mut libc::c_char;
 }
 
 #[cfg(any(target_os = "macos", target_os = "ios"))]
diff --git a/src/libstd/sys/unix/ext.rs b/src/libstd/sys/unix/ext.rs
deleted file mode 100644 (file)
index 66aaf26..0000000
+++ /dev/null
@@ -1,337 +0,0 @@
-// 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.
-
-//! Experimental extensions to `std` for Unix platforms.
-//!
-//! For now, this module is limited to extracting file descriptors,
-//! but its functionality will grow over time.
-//!
-//! # Example
-//!
-//! ```no_run
-//! use std::fs::File;
-//! use std::os::unix::prelude::*;
-//!
-//! fn main() {
-//!     let f = File::create("foo.txt").unwrap();
-//!     let fd = f.as_raw_fd();
-//!
-//!     // use fd with native unix bindings
-//! }
-//! ```
-
-#![stable(feature = "rust1", since = "1.0.0")]
-
-/// Unix-specific extensions to general I/O primitives
-#[stable(feature = "rust1", since = "1.0.0")]
-pub mod io {
-    use fs;
-    use libc;
-    use net;
-    use sys_common::{net2, AsInner, FromInner};
-    use sys;
-
-    /// Raw file descriptors.
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub type RawFd = libc::c_int;
-
-    /// A trait to extract the raw unix file descriptor from an underlying
-    /// object.
-    ///
-    /// This is only available on unix platforms and must be imported in order
-    /// to call the method. Windows platforms have a corresponding `AsRawHandle`
-    /// and `AsRawSocket` set of traits.
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub trait AsRawFd {
-        /// Extracts the raw file descriptor.
-        ///
-        /// This method does **not** pass ownership of the raw file descriptor
-        /// to the caller. The descriptor is only guarantee to be valid while
-        /// the original object has not yet been destroyed.
-        #[stable(feature = "rust1", since = "1.0.0")]
-        fn as_raw_fd(&self) -> RawFd;
-    }
-
-    /// A trait to express the ability to construct an object from a raw file
-    /// descriptor.
-    #[unstable(feature = "from_raw_os",
-               reason = "recent addition to std::os::unix::io")]
-    pub trait FromRawFd {
-        /// Constructs a new instances of `Self` from the given raw file
-        /// descriptor.
-        ///
-        /// This function **consumes ownership** of the specified file
-        /// descriptor. The returned object will take responsibility for closing
-        /// it when the object goes out of scope.
-        ///
-        /// This function is also unsafe as the primitives currently returned
-        /// have the contract that they are the sole owner of the file
-        /// descriptor they are wrapping. Usage of this function could
-        /// accidentally allow violating this contract which can cause memory
-        /// unsafety in code that relies on it being true.
-        unsafe fn from_raw_fd(fd: RawFd) -> Self;
-    }
-
-    #[stable(feature = "rust1", since = "1.0.0")]
-    impl AsRawFd for fs::File {
-        fn as_raw_fd(&self) -> RawFd {
-            self.as_inner().fd().raw()
-        }
-    }
-    #[unstable(feature = "from_raw_os", reason = "trait is unstable")]
-    impl FromRawFd for fs::File {
-        unsafe fn from_raw_fd(fd: RawFd) -> fs::File {
-            fs::File::from_inner(sys::fs2::File::from_inner(fd))
-        }
-    }
-
-    #[stable(feature = "rust1", since = "1.0.0")]
-    impl AsRawFd for net::TcpStream {
-        fn as_raw_fd(&self) -> RawFd { *self.as_inner().socket().as_inner() }
-    }
-    #[stable(feature = "rust1", since = "1.0.0")]
-    impl AsRawFd for net::TcpListener {
-        fn as_raw_fd(&self) -> RawFd { *self.as_inner().socket().as_inner() }
-    }
-    #[stable(feature = "rust1", since = "1.0.0")]
-    impl AsRawFd for net::UdpSocket {
-        fn as_raw_fd(&self) -> RawFd { *self.as_inner().socket().as_inner() }
-    }
-
-    #[unstable(feature = "from_raw_os", reason = "trait is unstable")]
-    impl FromRawFd for net::TcpStream {
-        unsafe fn from_raw_fd(fd: RawFd) -> net::TcpStream {
-            let socket = sys::net::Socket::from_inner(fd);
-            net::TcpStream::from_inner(net2::TcpStream::from_inner(socket))
-        }
-    }
-    #[unstable(feature = "from_raw_os", reason = "trait is unstable")]
-    impl FromRawFd for net::TcpListener {
-        unsafe fn from_raw_fd(fd: RawFd) -> net::TcpListener {
-            let socket = sys::net::Socket::from_inner(fd);
-            net::TcpListener::from_inner(net2::TcpListener::from_inner(socket))
-        }
-    }
-    #[unstable(feature = "from_raw_os", reason = "trait is unstable")]
-    impl FromRawFd for net::UdpSocket {
-        unsafe fn from_raw_fd(fd: RawFd) -> net::UdpSocket {
-            let socket = sys::net::Socket::from_inner(fd);
-            net::UdpSocket::from_inner(net2::UdpSocket::from_inner(socket))
-        }
-    }
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// OsString and OsStr
-////////////////////////////////////////////////////////////////////////////////
-
-/// Unix-specific extension to the primitives in the `std::ffi` module
-#[stable(feature = "rust1", since = "1.0.0")]
-pub mod ffi {
-    use ffi::{OsStr, OsString};
-    use mem;
-    use prelude::v1::*;
-    use sys::os_str::Buf;
-    use sys_common::{FromInner, IntoInner, AsInner};
-
-    /// Unix-specific extensions to `OsString`.
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub trait OsStringExt {
-        /// Creates an `OsString` from a byte vector.
-        #[stable(feature = "rust1", since = "1.0.0")]
-        fn from_vec(vec: Vec<u8>) -> Self;
-
-        /// Yields the underlying byte vector of this `OsString`.
-        #[stable(feature = "rust1", since = "1.0.0")]
-        fn into_vec(self) -> Vec<u8>;
-    }
-
-    #[stable(feature = "rust1", since = "1.0.0")]
-    impl OsStringExt for OsString {
-        fn from_vec(vec: Vec<u8>) -> OsString {
-            FromInner::from_inner(Buf { inner: vec })
-        }
-        fn into_vec(self) -> Vec<u8> {
-            self.into_inner().inner
-        }
-    }
-
-    /// Unix-specific extensions to `OsStr`.
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub trait OsStrExt {
-        #[stable(feature = "rust1", since = "1.0.0")]
-        fn from_bytes(slice: &[u8]) -> &Self;
-
-        /// Gets the underlying byte view of the `OsStr` slice.
-        #[stable(feature = "rust1", since = "1.0.0")]
-        fn as_bytes(&self) -> &[u8];
-    }
-
-    #[stable(feature = "rust1", since = "1.0.0")]
-    impl OsStrExt for OsStr {
-        fn from_bytes(slice: &[u8]) -> &OsStr {
-            unsafe { mem::transmute(slice) }
-        }
-        fn as_bytes(&self) -> &[u8] {
-            &self.as_inner().inner
-        }
-    }
-}
-
-/// Unix-specific extensions to primitives in the `std::fs` module.
-#[unstable(feature = "fs_ext",
-           reason = "may want a more useful mode abstraction")]
-pub mod fs {
-    use sys;
-    use sys_common::{FromInner, AsInner, AsInnerMut};
-    use fs::{Permissions, OpenOptions};
-    use path::Path;
-    use convert::AsRef;
-    use io;
-
-    /// Unix-specific extensions to `Permissions`
-    pub trait PermissionsExt {
-        fn mode(&self) -> i32;
-        fn set_mode(&mut self, mode: i32);
-    }
-
-    impl PermissionsExt for Permissions {
-        fn mode(&self) -> i32 { self.as_inner().mode() }
-
-        fn set_mode(&mut self, mode: i32) {
-            *self = FromInner::from_inner(FromInner::from_inner(mode));
-        }
-    }
-
-    /// Unix-specific extensions to `OpenOptions`
-    pub trait OpenOptionsExt {
-        /// Sets the mode bits that a new file will be created with.
-        ///
-        /// If a new file is created as part of a `File::open_opts` call then this
-        /// specified `mode` will be used as the permission bits for the new file.
-        fn mode(&mut self, mode: i32) -> &mut Self;
-    }
-
-    impl OpenOptionsExt for OpenOptions {
-        fn mode(&mut self, mode: i32) -> &mut OpenOptions {
-            self.as_inner_mut().mode(mode); self
-        }
-    }
-
-    /// Creates a new symbolic link on the filesystem.
-    ///
-    /// The `dst` path will be a symbolic link pointing to the `src` path.
-    ///
-    /// # Note
-    ///
-    /// On Windows, you must specify whether a symbolic link points to a file
-    /// or directory.  Use `os::windows::fs::symlink_file` to create a
-    /// symbolic link to a file, or `os::windows::fs::symlink_dir` to create a
-    /// symbolic link to a directory.  Additionally, the process must have
-    /// `SeCreateSymbolicLinkPrivilege` in order to be able to create a
-    /// symbolic link.
-    ///
-    /// # Examples
-    ///
-    /// ```
-    /// #![feature(fs_ext)]
-    /// use std::os::unix::fs;
-    ///
-    /// # fn foo() -> std::io::Result<()> {
-    /// try!(fs::symlink("a.txt", "b.txt"));
-    /// # Ok(())
-    /// # }
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn symlink<P: AsRef<Path>, Q: AsRef<Path>>(src: P, dst: Q) -> io::Result<()>
-    {
-        sys::fs2::symlink(src.as_ref(), dst.as_ref())
-    }
-
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Process and Command
-////////////////////////////////////////////////////////////////////////////////
-
-/// Unix-specific extensions to primitives in the `std::process` module.
-#[stable(feature = "rust1", since = "1.0.0")]
-pub mod process {
-    use prelude::v1::*;
-    use libc::{uid_t, gid_t};
-    use process;
-    use sys;
-    use sys_common::{AsInnerMut, AsInner};
-
-    /// Unix-specific extensions to the `std::process::Command` builder
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub trait CommandExt {
-        /// Sets the child process's user id. This translates to a
-        /// `setuid` call in the child process. Failure in the `setuid`
-        /// call will cause the spawn to fail.
-        #[stable(feature = "rust1", since = "1.0.0")]
-        fn uid(&mut self, id: uid_t) -> &mut process::Command;
-
-        /// Similar to `uid`, but sets the group id of the child process. This has
-        /// the same semantics as the `uid` field.
-        #[stable(feature = "rust1", since = "1.0.0")]
-        fn gid(&mut self, id: gid_t) -> &mut process::Command;
-    }
-
-    #[stable(feature = "rust1", since = "1.0.0")]
-    impl CommandExt for process::Command {
-        fn uid(&mut self, id: uid_t) -> &mut process::Command {
-            self.as_inner_mut().uid = Some(id);
-            self
-        }
-
-        fn gid(&mut self, id: gid_t) -> &mut process::Command {
-            self.as_inner_mut().gid = Some(id);
-            self
-        }
-    }
-
-    /// Unix-specific extensions to `std::process::ExitStatus`
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub trait ExitStatusExt {
-        /// If the process was terminated by a signal, returns that signal.
-        #[stable(feature = "rust1", since = "1.0.0")]
-        fn signal(&self) -> Option<i32>;
-    }
-
-    #[stable(feature = "rust1", since = "1.0.0")]
-    impl ExitStatusExt for process::ExitStatus {
-        fn signal(&self) -> Option<i32> {
-            match *self.as_inner() {
-                sys::process2::ExitStatus::Signal(s) => Some(s),
-                _ => None
-            }
-        }
-    }
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// Prelude
-////////////////////////////////////////////////////////////////////////////////
-
-/// A prelude for conveniently writing platform-specific code.
-///
-/// Includes all extension traits, and some important type definitions.
-#[stable(feature = "rust1", since = "1.0.0")]
-pub mod prelude {
-    #[doc(no_inline)]
-    pub use super::io::{RawFd, AsRawFd};
-    #[doc(no_inline)] #[stable(feature = "rust1", since = "1.0.0")]
-    pub use super::ffi::{OsStrExt, OsStringExt};
-    #[doc(no_inline)]
-    pub use super::fs::{PermissionsExt, OpenOptionsExt};
-    #[doc(no_inline)] #[stable(feature = "rust1", since = "1.0.0")]
-    pub use super::process::{CommandExt, ExitStatusExt};
-}
diff --git a/src/libstd/sys/unix/ext/ffi.rs b/src/libstd/sys/unix/ext/ffi.rs
new file mode 100644 (file)
index 0000000..825e74c
--- /dev/null
@@ -0,0 +1,62 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! Unix-specific extension to the primitives in the `std::ffi` module
+
+#![stable(feature = "rust1", since = "1.0.0")]
+
+use ffi::{OsStr, OsString};
+use mem;
+use prelude::v1::*;
+use sys::os_str::Buf;
+use sys_common::{FromInner, IntoInner, AsInner};
+
+/// Unix-specific extensions to `OsString`.
+#[stable(feature = "rust1", since = "1.0.0")]
+pub trait OsStringExt {
+    /// Creates an `OsString` from a byte vector.
+    #[stable(feature = "rust1", since = "1.0.0")]
+    fn from_vec(vec: Vec<u8>) -> Self;
+
+    /// Yields the underlying byte vector of this `OsString`.
+    #[stable(feature = "rust1", since = "1.0.0")]
+    fn into_vec(self) -> Vec<u8>;
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl OsStringExt for OsString {
+    fn from_vec(vec: Vec<u8>) -> OsString {
+        FromInner::from_inner(Buf { inner: vec })
+    }
+    fn into_vec(self) -> Vec<u8> {
+        self.into_inner().inner
+    }
+}
+
+/// Unix-specific extensions to `OsStr`.
+#[stable(feature = "rust1", since = "1.0.0")]
+pub trait OsStrExt {
+    #[stable(feature = "rust1", since = "1.0.0")]
+    fn from_bytes(slice: &[u8]) -> &Self;
+
+    /// Gets the underlying byte view of the `OsStr` slice.
+    #[stable(feature = "rust1", since = "1.0.0")]
+    fn as_bytes(&self) -> &[u8];
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl OsStrExt for OsStr {
+    fn from_bytes(slice: &[u8]) -> &OsStr {
+        unsafe { mem::transmute(slice) }
+    }
+    fn as_bytes(&self) -> &[u8] {
+        &self.as_inner().inner
+    }
+}
diff --git a/src/libstd/sys/unix/ext/fs.rs b/src/libstd/sys/unix/ext/fs.rs
new file mode 100644 (file)
index 0000000..2e4ed38
--- /dev/null
@@ -0,0 +1,207 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! Unix-specific extensions to primitives in the `std::fs` module.
+
+#![stable(feature = "rust1", since = "1.0.0")]
+
+use prelude::v1::*;
+
+use fs::{self, Permissions, OpenOptions};
+use io;
+use mem;
+use os::raw::c_long;
+use os::unix::raw;
+use path::Path;
+use sys::platform;
+use sys;
+use sys_common::{FromInner, AsInner, AsInnerMut};
+
+#[unstable(feature = "fs_mode", reason = "recently added API")]
+pub const USER_READ: raw::mode_t = 0o400;
+#[unstable(feature = "fs_mode", reason = "recently added API")]
+pub const USER_WRITE: raw::mode_t = 0o200;
+#[unstable(feature = "fs_mode", reason = "recently added API")]
+pub const USER_EXECUTE: raw::mode_t = 0o100;
+#[unstable(feature = "fs_mode", reason = "recently added API")]
+pub const USER_RWX: raw::mode_t = 0o700;
+#[unstable(feature = "fs_mode", reason = "recently added API")]
+pub const GROUP_READ: raw::mode_t = 0o040;
+#[unstable(feature = "fs_mode", reason = "recently added API")]
+pub const GROUP_WRITE: raw::mode_t = 0o020;
+#[unstable(feature = "fs_mode", reason = "recently added API")]
+pub const GROUP_EXECUTE: raw::mode_t = 0o010;
+#[unstable(feature = "fs_mode", reason = "recently added API")]
+pub const GROUP_RWX: raw::mode_t = 0o070;
+#[unstable(feature = "fs_mode", reason = "recently added API")]
+pub const OTHER_READ: raw::mode_t = 0o004;
+#[unstable(feature = "fs_mode", reason = "recently added API")]
+pub const OTHER_WRITE: raw::mode_t = 0o002;
+#[unstable(feature = "fs_mode", reason = "recently added API")]
+pub const OTHER_EXECUTE: raw::mode_t = 0o001;
+#[unstable(feature = "fs_mode", reason = "recently added API")]
+pub const OTHER_RWX: raw::mode_t = 0o007;
+#[unstable(feature = "fs_mode", reason = "recently added API")]
+pub const ALL_READ: raw::mode_t = 0o444;
+#[unstable(feature = "fs_mode", reason = "recently added API")]
+pub const ALL_WRITE: raw::mode_t = 0o222;
+#[unstable(feature = "fs_mode", reason = "recently added API")]
+pub const ALL_EXECUTE: raw::mode_t = 0o111;
+#[unstable(feature = "fs_mode", reason = "recently added API")]
+pub const ALL_RWX: raw::mode_t = 0o777;
+#[unstable(feature = "fs_mode", reason = "recently added API")]
+pub const SETUID: raw::mode_t = 0o4000;
+#[unstable(feature = "fs_mode", reason = "recently added API")]
+pub const SETGID: raw::mode_t = 0o2000;
+#[unstable(feature = "fs_mode", reason = "recently added API")]
+pub const STICKY_BIT: raw::mode_t = 0o1000;
+
+/// Unix-specific extensions to `Permissions`
+#[unstable(feature = "fs_ext",
+           reason = "may want a more useful mode abstraction")]
+pub trait PermissionsExt {
+    fn mode(&self) -> raw::mode_t;
+    fn set_mode(&mut self, mode: raw::mode_t);
+    fn from_mode(mode: raw::mode_t) -> Self;
+}
+
+impl PermissionsExt for Permissions {
+    fn mode(&self) -> raw::mode_t { self.as_inner().mode() }
+
+    fn set_mode(&mut self, mode: raw::mode_t) {
+        *self = FromInner::from_inner(FromInner::from_inner(mode));
+    }
+
+    fn from_mode(mode: raw::mode_t) -> Permissions {
+        FromInner::from_inner(FromInner::from_inner(mode))
+    }
+}
+
+/// Unix-specific extensions to `OpenOptions`
+#[unstable(feature = "fs_ext",
+           reason = "may want a more useful mode abstraction")]
+pub trait OpenOptionsExt {
+    /// Sets the mode bits that a new file will be created with.
+    ///
+    /// If a new file is created as part of a `File::open_opts` call then this
+    /// specified `mode` will be used as the permission bits for the new file.
+    fn mode(&mut self, mode: raw::mode_t) -> &mut Self;
+}
+
+impl OpenOptionsExt for OpenOptions {
+    fn mode(&mut self, mode: raw::mode_t) -> &mut OpenOptions {
+        self.as_inner_mut().mode(mode); self
+    }
+}
+
+#[unstable(feature = "metadata_ext", reason = "recently added API")]
+pub struct Metadata(sys::fs2::FileAttr);
+
+#[unstable(feature = "metadata_ext", reason = "recently added API")]
+pub trait MetadataExt {
+    fn as_raw(&self) -> &Metadata;
+}
+
+impl MetadataExt for fs::Metadata {
+    fn as_raw(&self) -> &Metadata {
+        let inner: &sys::fs2::FileAttr = self.as_inner();
+        unsafe { mem::transmute(inner) }
+    }
+}
+
+impl AsInner<platform::raw::stat> for Metadata {
+    fn as_inner(&self) -> &platform::raw::stat { self.0.as_inner() }
+}
+
+// Hm, why are there casts here to the returned type, shouldn't the types always
+// be the same? Right you are! Turns out, however, on android at least the types
+// in the raw `stat` structure are not the same as the types being returned. Who
+// knew!
+//
+// As a result to make sure this compiles for all platforms we do the manual
+// casts and rely on manual lowering to `stat` if the raw type is desired.
+#[unstable(feature = "metadata_ext", reason = "recently added API")]
+impl Metadata {
+    pub fn dev(&self) -> raw::dev_t { self.0.raw().st_dev as raw::dev_t }
+    pub fn ino(&self) -> raw::ino_t { self.0.raw().st_ino as raw::ino_t }
+    pub fn mode(&self) -> raw::mode_t { self.0.raw().st_mode as raw::mode_t }
+    pub fn nlink(&self) -> raw::nlink_t { self.0.raw().st_nlink as raw::nlink_t }
+    pub fn uid(&self) -> raw::uid_t { self.0.raw().st_uid as raw::uid_t }
+    pub fn gid(&self) -> raw::gid_t { self.0.raw().st_gid as raw::gid_t }
+    pub fn rdev(&self) -> raw::dev_t { self.0.raw().st_rdev as raw::dev_t }
+    pub fn size(&self) -> raw::off_t { self.0.raw().st_size as raw::off_t }
+    pub fn atime(&self) -> raw::time_t { self.0.raw().st_atime }
+    pub fn atime_nsec(&self) -> c_long { self.0.raw().st_atime }
+    pub fn mtime(&self) -> raw::time_t { self.0.raw().st_mtime }
+    pub fn mtime_nsec(&self) -> c_long { self.0.raw().st_mtime }
+    pub fn ctime(&self) -> raw::time_t { self.0.raw().st_ctime }
+    pub fn ctime_nsec(&self) -> c_long { self.0.raw().st_ctime }
+
+    pub fn blksize(&self) -> raw::blksize_t {
+        self.0.raw().st_blksize as raw::blksize_t
+    }
+    pub fn blocks(&self) -> raw::blkcnt_t {
+        self.0.raw().st_blocks as raw::blkcnt_t
+    }
+}
+
+#[unstable(feature = "dir_entry_ext", reason = "recently added API")]
+pub trait DirEntryExt {
+    fn ino(&self) -> raw::ino_t;
+}
+
+impl DirEntryExt for fs::DirEntry {
+    fn ino(&self) -> raw::ino_t { self.as_inner().ino() }
+}
+
+/// Creates a new symbolic link on the filesystem.
+///
+/// The `dst` path will be a symbolic link pointing to the `src` path.
+///
+/// # Note
+///
+/// On Windows, you must specify whether a symbolic link points to a file
+/// or directory.  Use `os::windows::fs::symlink_file` to create a
+/// symbolic link to a file, or `os::windows::fs::symlink_dir` to create a
+/// symbolic link to a directory.  Additionally, the process must have
+/// `SeCreateSymbolicLinkPrivilege` in order to be able to create a
+/// symbolic link.
+///
+/// # Examples
+///
+/// ```
+/// use std::os::unix::fs;
+///
+/// # fn foo() -> std::io::Result<()> {
+/// try!(fs::symlink("a.txt", "b.txt"));
+/// # Ok(())
+/// # }
+/// ```
+#[stable(feature = "rust1", since = "1.0.0")]
+pub fn symlink<P: AsRef<Path>, Q: AsRef<Path>>(src: P, dst: Q) -> io::Result<()>
+{
+    sys::fs2::symlink(src.as_ref(), dst.as_ref())
+}
+
+#[unstable(feature = "dir_builder", reason = "recently added API")]
+/// An extension trait for `fs::DirBuilder` for unix-specific options.
+pub trait DirBuilderExt {
+    /// Sets the mode to create new directories with. This option defaults to
+    /// 0o777.
+    fn mode(&mut self, mode: raw::mode_t) -> &mut Self;
+}
+
+impl DirBuilderExt for fs::DirBuilder {
+    fn mode(&mut self, mode: raw::mode_t) -> &mut fs::DirBuilder {
+        self.as_inner_mut().set_mode(mode);
+        self
+    }
+}
+
diff --git a/src/libstd/sys/unix/ext/io.rs b/src/libstd/sys/unix/ext/io.rs
new file mode 100644 (file)
index 0000000..8cb4b49
--- /dev/null
@@ -0,0 +1,108 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! Unix-specific extensions to general I/O primitives
+
+#![stable(feature = "rust1", since = "1.0.0")]
+
+use fs;
+use net;
+use os::raw;
+use sys;
+use sys_common::{net2, AsInner, FromInner};
+
+/// Raw file descriptors.
+#[stable(feature = "rust1", since = "1.0.0")]
+pub type RawFd = raw::c_int;
+
+/// A trait to extract the raw unix file descriptor from an underlying
+/// object.
+///
+/// This is only available on unix platforms and must be imported in order
+/// to call the method. Windows platforms have a corresponding `AsRawHandle`
+/// and `AsRawSocket` set of traits.
+#[stable(feature = "rust1", since = "1.0.0")]
+pub trait AsRawFd {
+    /// Extracts the raw file descriptor.
+    ///
+    /// This method does **not** pass ownership of the raw file descriptor
+    /// to the caller. The descriptor is only guarantee to be valid while
+    /// the original object has not yet been destroyed.
+    #[stable(feature = "rust1", since = "1.0.0")]
+    fn as_raw_fd(&self) -> RawFd;
+}
+
+/// A trait to express the ability to construct an object from a raw file
+/// descriptor.
+#[unstable(feature = "from_raw_os",
+           reason = "recent addition to std::os::unix::io")]
+pub trait FromRawFd {
+    /// Constructs a new instances of `Self` from the given raw file
+    /// descriptor.
+    ///
+    /// This function **consumes ownership** of the specified file
+    /// descriptor. The returned object will take responsibility for closing
+    /// it when the object goes out of scope.
+    ///
+    /// This function is also unsafe as the primitives currently returned
+    /// have the contract that they are the sole owner of the file
+    /// descriptor they are wrapping. Usage of this function could
+    /// accidentally allow violating this contract which can cause memory
+    /// unsafety in code that relies on it being true.
+    unsafe fn from_raw_fd(fd: RawFd) -> Self;
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl AsRawFd for fs::File {
+    fn as_raw_fd(&self) -> RawFd {
+        self.as_inner().fd().raw()
+    }
+}
+#[unstable(feature = "from_raw_os", reason = "trait is unstable")]
+impl FromRawFd for fs::File {
+    unsafe fn from_raw_fd(fd: RawFd) -> fs::File {
+        fs::File::from_inner(sys::fs2::File::from_inner(fd))
+    }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl AsRawFd for net::TcpStream {
+    fn as_raw_fd(&self) -> RawFd { *self.as_inner().socket().as_inner() }
+}
+#[stable(feature = "rust1", since = "1.0.0")]
+impl AsRawFd for net::TcpListener {
+    fn as_raw_fd(&self) -> RawFd { *self.as_inner().socket().as_inner() }
+}
+#[stable(feature = "rust1", since = "1.0.0")]
+impl AsRawFd for net::UdpSocket {
+    fn as_raw_fd(&self) -> RawFd { *self.as_inner().socket().as_inner() }
+}
+
+#[unstable(feature = "from_raw_os", reason = "trait is unstable")]
+impl FromRawFd for net::TcpStream {
+    unsafe fn from_raw_fd(fd: RawFd) -> net::TcpStream {
+        let socket = sys::net::Socket::from_inner(fd);
+        net::TcpStream::from_inner(net2::TcpStream::from_inner(socket))
+    }
+}
+#[unstable(feature = "from_raw_os", reason = "trait is unstable")]
+impl FromRawFd for net::TcpListener {
+    unsafe fn from_raw_fd(fd: RawFd) -> net::TcpListener {
+        let socket = sys::net::Socket::from_inner(fd);
+        net::TcpListener::from_inner(net2::TcpListener::from_inner(socket))
+    }
+}
+#[unstable(feature = "from_raw_os", reason = "trait is unstable")]
+impl FromRawFd for net::UdpSocket {
+    unsafe fn from_raw_fd(fd: RawFd) -> net::UdpSocket {
+        let socket = sys::net::Socket::from_inner(fd);
+        net::UdpSocket::from_inner(net2::UdpSocket::from_inner(socket))
+    }
+}
diff --git a/src/libstd/sys/unix/ext/mod.rs b/src/libstd/sys/unix/ext/mod.rs
new file mode 100644 (file)
index 0000000..6fde45a
--- /dev/null
@@ -0,0 +1,53 @@
+// 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.
+
+//! Experimental extensions to `std` for Unix platforms.
+//!
+//! For now, this module is limited to extracting file descriptors,
+//! but its functionality will grow over time.
+//!
+//! # Example
+//!
+//! ```no_run
+//! use std::fs::File;
+//! use std::os::unix::prelude::*;
+//!
+//! fn main() {
+//!     let f = File::create("foo.txt").unwrap();
+//!     let fd = f.as_raw_fd();
+//!
+//!     // use fd with native unix bindings
+//! }
+//! ```
+
+#![stable(feature = "rust1", since = "1.0.0")]
+
+pub mod io;
+pub mod ffi;
+pub mod fs;
+pub mod process;
+pub mod raw;
+
+/// A prelude for conveniently writing platform-specific code.
+///
+/// Includes all extension traits, and some important type definitions.
+#[stable(feature = "rust1", since = "1.0.0")]
+pub mod prelude {
+    #[doc(no_inline)]
+    pub use super::io::{RawFd, AsRawFd};
+    #[doc(no_inline)] #[stable(feature = "rust1", since = "1.0.0")]
+    pub use super::ffi::{OsStrExt, OsStringExt};
+    #[doc(no_inline)]
+    pub use super::fs::{PermissionsExt, OpenOptionsExt, MetadataExt};
+    #[doc(no_inline)]
+    pub use super::fs::{DirEntryExt};
+    #[doc(no_inline)] #[stable(feature = "rust1", since = "1.0.0")]
+    pub use super::process::{CommandExt, ExitStatusExt};
+}
diff --git a/src/libstd/sys/unix/ext/process.rs b/src/libstd/sys/unix/ext/process.rs
new file mode 100644 (file)
index 0000000..8c9d0a8
--- /dev/null
@@ -0,0 +1,65 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! Unix-specific extensions to primitives in the `std::process` module.
+
+#![stable(feature = "rust1", since = "1.0.0")]
+
+use os::unix::raw::{uid_t, gid_t};
+use prelude::v1::*;
+use process;
+use sys;
+use sys_common::{AsInnerMut, AsInner};
+
+/// Unix-specific extensions to the `std::process::Command` builder
+#[stable(feature = "rust1", since = "1.0.0")]
+pub trait CommandExt {
+    /// Sets the child process's user id. This translates to a
+    /// `setuid` call in the child process. Failure in the `setuid`
+    /// call will cause the spawn to fail.
+    #[stable(feature = "rust1", since = "1.0.0")]
+    fn uid(&mut self, id: uid_t) -> &mut process::Command;
+
+    /// Similar to `uid`, but sets the group id of the child process. This has
+    /// the same semantics as the `uid` field.
+    #[stable(feature = "rust1", since = "1.0.0")]
+    fn gid(&mut self, id: gid_t) -> &mut process::Command;
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl CommandExt for process::Command {
+    fn uid(&mut self, id: uid_t) -> &mut process::Command {
+        self.as_inner_mut().uid = Some(id);
+        self
+    }
+
+    fn gid(&mut self, id: gid_t) -> &mut process::Command {
+        self.as_inner_mut().gid = Some(id);
+        self
+    }
+}
+
+/// Unix-specific extensions to `std::process::ExitStatus`
+#[stable(feature = "rust1", since = "1.0.0")]
+pub trait ExitStatusExt {
+    /// If the process was terminated by a signal, returns that signal.
+    #[stable(feature = "rust1", since = "1.0.0")]
+    fn signal(&self) -> Option<i32>;
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl ExitStatusExt for process::ExitStatus {
+    fn signal(&self) -> Option<i32> {
+        match *self.as_inner() {
+            sys::process2::ExitStatus::Signal(s) => Some(s),
+            _ => None
+        }
+    }
+}
diff --git a/src/libstd/sys/unix/ext/raw.rs b/src/libstd/sys/unix/ext/raw.rs
new file mode 100644 (file)
index 0000000..8fe4b90
--- /dev/null
@@ -0,0 +1,22 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! Unix-specific primitives available on all unix platforms
+
+#![unstable(feature = "raw_ext", reason = "recently added API")]
+
+pub type uid_t = u32;
+pub type gid_t = u32;
+pub type pid_t = i32;
+
+#[doc(inline)]
+pub use sys::platform::raw::{dev_t, ino_t, mode_t, nlink_t, off_t, blksize_t};
+#[doc(inline)]
+pub use sys::platform::raw::{blkcnt_t, time_t};
index 8eb84b26f22f2f33d604b380cd57732b20f2664d..350161c751cb89fa6af78ad8a88cd1f19c880ed9 100644 (file)
 use ptr;
 use sync::Arc;
 use sys::fd::FileDesc;
+use sys::platform::raw;
 use sys::{c, cvt, cvt_r};
-use sys_common::FromInner;
+use sys_common::{AsInner, FromInner};
 use vec::Vec;
 
 pub struct File(FileDesc);
 
 pub struct FileAttr {
-    stat: libc::stat,
+    stat: raw::stat,
 }
 
 pub struct ReadDir {
@@ -57,13 +58,12 @@ pub struct OpenOptions {
 #[derive(Clone, PartialEq, Eq, Debug)]
 pub struct FilePermissions { mode: mode_t }
 
+#[derive(Copy, Clone, PartialEq, Eq, Hash)]
+pub struct FileType { mode: mode_t }
+
+pub struct DirBuilder { mode: mode_t }
+
 impl FileAttr {
-    pub fn is_dir(&self) -> bool {
-        (self.stat.st_mode as mode_t) & libc::S_IFMT == libc::S_IFDIR
-    }
-    pub fn is_file(&self) -> bool {
-        (self.stat.st_mode as mode_t) & libc::S_IFMT == libc::S_IFREG
-    }
     pub fn size(&self) -> u64 { self.stat.st_size as u64 }
     pub fn perm(&self) -> FilePermissions {
         FilePermissions { mode: (self.stat.st_mode as mode_t) & 0o777 }
@@ -76,12 +76,35 @@ pub fn modified(&self) -> u64 {
         self.mktime(self.stat.st_mtime as u64, self.stat.st_mtime_nsec as u64)
     }
 
+    pub fn file_type(&self) -> FileType {
+        FileType { mode: self.stat.st_mode as mode_t }
+    }
+
+    pub fn raw(&self) -> &raw::stat { &self.stat }
+
     // times are in milliseconds (currently)
     fn mktime(&self, secs: u64, nsecs: u64) -> u64 {
         secs * 1000 + nsecs / 1000000
     }
 }
 
+impl AsInner<raw::stat> for FileAttr {
+    fn as_inner(&self) -> &raw::stat { &self.stat }
+}
+
+#[unstable(feature = "metadata_ext", reason = "recently added API")]
+pub trait MetadataExt {
+    fn as_raw_stat(&self) -> &raw::stat;
+}
+
+impl MetadataExt for ::fs::Metadata {
+    fn as_raw_stat(&self) -> &raw::stat { &self.as_inner().stat }
+}
+
+impl MetadataExt for ::os::unix::fs::Metadata {
+    fn as_raw_stat(&self) -> &raw::stat { self.as_inner() }
+}
+
 impl FilePermissions {
     pub fn readonly(&self) -> bool { self.mode & 0o222 == 0 }
     pub fn set_readonly(&mut self, readonly: bool) {
@@ -91,11 +114,19 @@ pub fn set_readonly(&mut self, readonly: bool) {
             self.mode |= 0o222;
         }
     }
-    pub fn mode(&self) -> i32 { self.mode as i32 }
+    pub fn mode(&self) -> raw::mode_t { self.mode }
 }
 
-impl FromInner<i32> for FilePermissions {
-    fn from_inner(mode: i32) -> FilePermissions {
+impl FileType {
+    pub fn is_dir(&self) -> bool { self.is(libc::S_IFDIR) }
+    pub fn is_file(&self) -> bool { self.is(libc::S_IFREG) }
+    pub fn is_symlink(&self) -> bool { self.is(libc::S_IFLNK) }
+
+    fn is(&self, mode: mode_t) -> bool { self.mode & libc::S_IFMT == mode }
+}
+
+impl FromInner<raw::mode_t> for FilePermissions {
+    fn from_inner(mode: raw::mode_t) -> FilePermissions {
         FilePermissions { mode: mode as mode_t }
     }
 }
@@ -147,6 +178,33 @@ pub fn path(&self) -> PathBuf {
         self.root.join(<OsStr as OsStrExt>::from_bytes(self.name_bytes()))
     }
 
+    pub fn file_name(&self) -> OsString {
+        OsStr::from_bytes(self.name_bytes()).to_os_string()
+    }
+
+    pub fn metadata(&self) -> io::Result<FileAttr> {
+        lstat(&self.path())
+    }
+
+    pub fn file_type(&self) -> io::Result<FileType> {
+        extern {
+            fn rust_dir_get_mode(ptr: *mut libc::dirent_t) -> c_int;
+        }
+        unsafe {
+            match rust_dir_get_mode(self.dirent()) {
+                -1 => lstat(&self.path()).map(|m| m.file_type()),
+                n => Ok(FileType { mode: n as mode_t }),
+            }
+        }
+    }
+
+    pub fn ino(&self) -> raw::ino_t {
+        extern {
+            fn rust_dir_get_ino(ptr: *mut libc::dirent_t) -> raw::ino_t;
+        }
+        unsafe { rust_dir_get_ino(self.dirent()) }
+    }
+
     fn name_bytes(&self) -> &[u8] {
         extern {
             fn rust_list_dir_val(ptr: *mut libc::dirent_t) -> *const c_char;
@@ -191,7 +249,7 @@ pub fn create(&mut self, create: bool) {
         self.flag(libc::O_CREAT, create);
     }
 
-    pub fn mode(&mut self, mode: i32) {
+    pub fn mode(&mut self, mode: raw::mode_t) {
         self.mode = mode as mode_t;
     }
 
@@ -228,8 +286,10 @@ pub fn open_c(path: &CStr, opts: &OpenOptions) -> io::Result<File> {
     pub fn into_fd(self) -> FileDesc { self.0 }
 
     pub fn file_attr(&self) -> io::Result<FileAttr> {
-        let mut stat: libc::stat = unsafe { mem::zeroed() };
-        try!(cvt(unsafe { libc::fstat(self.0.raw(), &mut stat) }));
+        let mut stat: raw::stat = unsafe { mem::zeroed() };
+        try!(cvt(unsafe {
+            libc::fstat(self.0.raw(), &mut stat as *mut _ as *mut _)
+        }));
         Ok(FileAttr { stat: stat })
     }
 
@@ -284,6 +344,22 @@ pub fn seek(&self, pos: SeekFrom) -> io::Result<u64> {
     pub fn fd(&self) -> &FileDesc { &self.0 }
 }
 
+impl DirBuilder {
+    pub fn new() -> DirBuilder {
+        DirBuilder { mode: 0o777 }
+    }
+
+    pub fn mkdir(&self, p: &Path) -> io::Result<()> {
+        let p = try!(cstr(p));
+        try!(cvt(unsafe { libc::mkdir(p.as_ptr(), self.mode) }));
+        Ok(())
+    }
+
+    pub fn set_mode(&mut self, mode: mode_t) {
+        self.mode = mode;
+    }
+}
+
 fn cstr(path: &Path) -> io::Result<CString> {
     path.as_os_str().to_cstring().ok_or(
         io::Error::new(io::ErrorKind::InvalidInput, "path contained a null"))
@@ -343,12 +419,6 @@ fn get_mode(_fd: c_int) -> Option<(bool, bool)> {
     }
 }
 
-pub fn mkdir(p: &Path) -> io::Result<()> {
-    let p = try!(cstr(p));
-    try!(cvt(unsafe { libc::mkdir(p.as_ptr(), 0o777) }));
-    Ok(())
-}
-
 pub fn readdir(p: &Path) -> io::Result<ReadDir> {
     let root = Arc::new(p.to_path_buf());
     let p = try!(cstr(p));
@@ -420,15 +490,19 @@ pub fn link(src: &Path, dst: &Path) -> io::Result<()> {
 
 pub fn stat(p: &Path) -> io::Result<FileAttr> {
     let p = try!(cstr(p));
-    let mut stat: libc::stat = unsafe { mem::zeroed() };
-    try!(cvt(unsafe { libc::stat(p.as_ptr(), &mut stat) }));
+    let mut stat: raw::stat = unsafe { mem::zeroed() };
+    try!(cvt(unsafe {
+        libc::stat(p.as_ptr(), &mut stat as *mut _ as *mut _)
+    }));
     Ok(FileAttr { stat: stat })
 }
 
 pub fn lstat(p: &Path) -> io::Result<FileAttr> {
     let p = try!(cstr(p));
-    let mut stat: libc::stat = unsafe { mem::zeroed() };
-    try!(cvt(unsafe { libc::lstat(p.as_ptr(), &mut stat) }));
+    let mut stat: raw::stat = unsafe { mem::zeroed() };
+    try!(cvt(unsafe {
+        libc::lstat(p.as_ptr(), &mut stat as *mut _ as *mut _)
+    }));
     Ok(FileAttr { stat: stat })
 }
 
@@ -438,3 +512,17 @@ pub fn utimes(p: &Path, atime: u64, mtime: u64) -> io::Result<()> {
     try!(cvt(unsafe { c::utimes(p.as_ptr(), buf.as_ptr()) }));
     Ok(())
 }
+
+pub fn canonicalize(p: &Path) -> io::Result<PathBuf> {
+    let path = try!(CString::new(p.as_os_str().as_bytes()));
+    let mut buf = vec![0u8; 16 * 1024];
+    unsafe {
+        let r = c::realpath(path.as_ptr(), buf.as_mut_ptr() as *mut _);
+        if r.is_null() {
+            return Err(io::Error::last_os_error())
+        }
+    }
+    let p = buf.iter().position(|i| *i == 0).unwrap();
+    buf.truncate(p);
+    Ok(PathBuf::from(OsString::from_vec(buf)))
+}
index d99753a6a4c800c47b0237b23fa2b5dfb328d652..78b798d3bffff06f849f2f53b22b71512edc623c 100644 (file)
 use num::One;
 use ops::Neg;
 
+#[cfg(target_os = "android")]   pub use os::android as platform;
+#[cfg(target_os = "bitrig")]    pub use os::bitrig as platform;
+#[cfg(target_os = "dragonfly")] pub use os::dragonfly as platform;
+#[cfg(target_os = "freebsd")]   pub use os::freebsd as platform;
+#[cfg(target_os = "ios")]       pub use os::ios as platform;
+#[cfg(target_os = "linux")]     pub use os::linux as platform;
+#[cfg(target_os = "macos")]     pub use os::macos as platform;
+#[cfg(target_os = "nacl")]      pub use os::nacl as platform;
+#[cfg(target_os = "openbsd")]   pub use os::openbsd as platform;
+
 pub mod backtrace;
 pub mod c;
 pub mod condvar;
index 281ac37e671152845bc3caaddf807f9e4a533133..cfab9d1c51a153d988b926bf16b158629c0856fe 100644 (file)
@@ -342,7 +342,10 @@ fn min_stack_size(attr: *const libc::pthread_attr_t) -> usize {
     static mut __pthread_get_minstack: Option<F> = None;
 
     INIT.call_once(|| {
-        let lib = DynamicLibrary::open(None).unwrap();
+        let lib = match DynamicLibrary::open(None) {
+            Ok(l) => l,
+            Err(..) => return,
+        };
         unsafe {
             if let Ok(f) = lib.symbol("__pthread_get_minstack") {
                 __pthread_get_minstack = Some(mem::transmute::<*const (), F>(f));
index d2f51678d497fa737c463c0089b4729fe63b1a73..f59eb2c03013fd5eaa53c0e5050bf9b9969edf57 100644 (file)
@@ -82,7 +82,8 @@ pub struct SteadyTime {
     // OpenBSD provide it via libc
     #[cfg(not(any(target_os = "android",
                   target_os = "bitrig",
-                  target_os = "openbsd")))]
+                  target_os = "openbsd",
+                  target_env = "musl")))]
     #[link(name = "rt")]
     extern {}
 
index 385834a6226e05ec82d77b760fa897484b2d56d9..d94dfdeeea494fe1d315e441562b7c5c74576989 100644 (file)
@@ -283,7 +283,6 @@ pub fn init_frame(frame: &mut super::STACKFRAME64,
     }
 }
 
-#[repr(C)]
 struct Cleanup {
     handle: libc::HANDLE,
     SymCleanup: SymCleanupFn,
diff --git a/src/libstd/sys/windows/ext.rs b/src/libstd/sys/windows/ext.rs
deleted file mode 100644 (file)
index dd747d2..0000000
+++ /dev/null
@@ -1,301 +0,0 @@
-// 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.
-
-//! Experimental extensions to `std` for Windows.
-//!
-//! For now, this module is limited to extracting handles, file
-//! descriptors, and sockets, but its functionality will grow over
-//! time.
-
-#![stable(feature = "rust1", since = "1.0.0")]
-
-#[stable(feature = "rust1", since = "1.0.0")]
-pub mod io {
-    use fs;
-    use libc;
-    use net;
-    use sys_common::{net2, AsInner, FromInner};
-    use sys;
-
-    /// Raw HANDLEs.
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub type RawHandle = libc::HANDLE;
-
-    /// Raw SOCKETs.
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub type RawSocket = libc::SOCKET;
-
-    /// Extract raw handles.
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub trait AsRawHandle {
-        /// Extracts the raw handle, without taking any ownership.
-        #[stable(feature = "rust1", since = "1.0.0")]
-        fn as_raw_handle(&self) -> RawHandle;
-    }
-
-    /// Construct I/O objects from raw handles.
-    #[unstable(feature = "from_raw_os",
-               reason = "recent addition to the std::os::windows::io module")]
-    pub trait FromRawHandle {
-        /// Constructs a new I/O object from the specified raw handle.
-        ///
-        /// This function will **consume ownership** of the handle given,
-        /// passing responsibility for closing the handle to the returned
-        /// object.
-        ///
-        /// This function is also unsafe as the primitives currently returned
-        /// have the contract that they are the sole owner of the file
-        /// descriptor they are wrapping. Usage of this function could
-        /// accidentally allow violating this contract which can cause memory
-        /// unsafety in code that relies on it being true.
-        unsafe fn from_raw_handle(handle: RawHandle) -> Self;
-    }
-
-    #[stable(feature = "rust1", since = "1.0.0")]
-    impl AsRawHandle for fs::File {
-        fn as_raw_handle(&self) -> RawHandle {
-            self.as_inner().handle().raw()
-        }
-    }
-
-    #[unstable(feature = "from_raw_os", reason = "trait is unstable")]
-    impl FromRawHandle for fs::File {
-        unsafe fn from_raw_handle(handle: RawHandle) -> fs::File {
-            fs::File::from_inner(sys::fs2::File::from_inner(handle))
-        }
-    }
-
-    /// Extract raw sockets.
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub trait AsRawSocket {
-        /// Extracts the underlying raw socket from this object.
-        #[stable(feature = "rust1", since = "1.0.0")]
-        fn as_raw_socket(&self) -> RawSocket;
-    }
-
-    /// Create I/O objects from raw sockets.
-    #[unstable(feature = "from_raw_os", reason = "recent addition to module")]
-    pub trait FromRawSocket {
-        /// Creates a new I/O object from the given raw socket.
-        ///
-        /// This function will **consume ownership** of the socket provided and
-        /// it will be closed when the returned object goes out of scope.
-        ///
-        /// This function is also unsafe as the primitives currently returned
-        /// have the contract that they are the sole owner of the file
-        /// descriptor they are wrapping. Usage of this function could
-        /// accidentally allow violating this contract which can cause memory
-        /// unsafety in code that relies on it being true.
-        unsafe fn from_raw_socket(sock: RawSocket) -> Self;
-    }
-
-    #[stable(feature = "rust1", since = "1.0.0")]
-    impl AsRawSocket for net::TcpStream {
-        fn as_raw_socket(&self) -> RawSocket {
-            *self.as_inner().socket().as_inner()
-        }
-    }
-    #[stable(feature = "rust1", since = "1.0.0")]
-    impl AsRawSocket for net::TcpListener {
-        fn as_raw_socket(&self) -> RawSocket {
-            *self.as_inner().socket().as_inner()
-        }
-    }
-    #[stable(feature = "rust1", since = "1.0.0")]
-    impl AsRawSocket for net::UdpSocket {
-        fn as_raw_socket(&self) -> RawSocket {
-            *self.as_inner().socket().as_inner()
-        }
-    }
-
-    #[unstable(feature = "from_raw_os", reason = "trait is unstable")]
-    impl FromRawSocket for net::TcpStream {
-        unsafe fn from_raw_socket(sock: RawSocket) -> net::TcpStream {
-            let sock = sys::net::Socket::from_inner(sock);
-            net::TcpStream::from_inner(net2::TcpStream::from_inner(sock))
-        }
-    }
-    #[unstable(feature = "from_raw_os", reason = "trait is unstable")]
-    impl FromRawSocket for net::TcpListener {
-        unsafe fn from_raw_socket(sock: RawSocket) -> net::TcpListener {
-            let sock = sys::net::Socket::from_inner(sock);
-            net::TcpListener::from_inner(net2::TcpListener::from_inner(sock))
-        }
-    }
-    #[unstable(feature = "from_raw_os", reason = "trait is unstable")]
-    impl FromRawSocket for net::UdpSocket {
-        unsafe fn from_raw_socket(sock: RawSocket) -> net::UdpSocket {
-            let sock = sys::net::Socket::from_inner(sock);
-            net::UdpSocket::from_inner(net2::UdpSocket::from_inner(sock))
-        }
-    }
-}
-
-/// Windows-specific extensions to the primitives in the `std::ffi` module.
-#[stable(feature = "rust1", since = "1.0.0")]
-pub mod ffi {
-    use ffi::{OsString, OsStr};
-    use sys::os_str::Buf;
-    use sys_common::wtf8::Wtf8Buf;
-    use sys_common::{FromInner, AsInner};
-
-    pub use sys_common::wtf8::EncodeWide;
-
-    /// Windows-specific extensions to `OsString`.
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub trait OsStringExt {
-        /// Creates an `OsString` from a potentially ill-formed UTF-16 slice of
-        /// 16-bit code units.
-        ///
-        /// This is lossless: calling `.encode_wide()` on the resulting string
-        /// will always return the original code units.
-        #[stable(feature = "rust1", since = "1.0.0")]
-        fn from_wide(wide: &[u16]) -> Self;
-    }
-
-    #[stable(feature = "rust1", since = "1.0.0")]
-    impl OsStringExt for OsString {
-        fn from_wide(wide: &[u16]) -> OsString {
-            FromInner::from_inner(Buf { inner: Wtf8Buf::from_wide(wide) })
-        }
-    }
-
-    /// Windows-specific extensions to `OsStr`.
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub trait OsStrExt {
-        /// Re-encodes an `OsStr` as a wide character sequence,
-        /// i.e. potentially ill-formed UTF-16.
-        ///
-        /// This is lossless. Note that the encoding does not include a final
-        /// null.
-        #[stable(feature = "rust1", since = "1.0.0")]
-        fn encode_wide(&self) -> EncodeWide;
-    }
-
-    #[stable(feature = "rust1", since = "1.0.0")]
-    impl OsStrExt for OsStr {
-        fn encode_wide(&self) -> EncodeWide {
-            self.as_inner().inner.encode_wide()
-        }
-    }
-}
-
-/// Windows-specific extensions for the primitives in `std::fs`
-#[unstable(feature = "fs_ext", reason = "may require more thought/methods")]
-pub mod fs {
-    use fs::OpenOptions;
-    use sys;
-    use sys_common::AsInnerMut;
-    use path::Path;
-    use convert::AsRef;
-    use io;
-
-    /// Windows-specific extensions to `OpenOptions`
-    pub trait OpenOptionsExt {
-        /// Overrides the `dwDesiredAccess` argument to the call to `CreateFile`
-        /// with the specified value.
-        fn desired_access(&mut self, access: i32) -> &mut Self;
-
-        /// Overrides the `dwCreationDisposition` argument to the call to
-        /// `CreateFile` with the specified value.
-        ///
-        /// This will override any values of the standard `create` flags, for
-        /// example.
-        fn creation_disposition(&mut self, val: i32) -> &mut Self;
-
-        /// Overrides the `dwFlagsAndAttributes` argument to the call to
-        /// `CreateFile` with the specified value.
-        ///
-        /// This will override any values of the standard flags on the
-        /// `OpenOptions` structure.
-        fn flags_and_attributes(&mut self, val: i32) -> &mut Self;
-
-        /// Overrides the `dwShareMode` argument to the call to `CreateFile` with
-        /// the specified value.
-        ///
-        /// This will override any values of the standard flags on the
-        /// `OpenOptions` structure.
-        fn share_mode(&mut self, val: i32) -> &mut Self;
-    }
-
-    impl OpenOptionsExt for OpenOptions {
-        fn desired_access(&mut self, access: i32) -> &mut OpenOptions {
-            self.as_inner_mut().desired_access(access); self
-        }
-        fn creation_disposition(&mut self, access: i32) -> &mut OpenOptions {
-            self.as_inner_mut().creation_disposition(access); self
-        }
-        fn flags_and_attributes(&mut self, access: i32) -> &mut OpenOptions {
-            self.as_inner_mut().flags_and_attributes(access); self
-        }
-        fn share_mode(&mut self, access: i32) -> &mut OpenOptions {
-            self.as_inner_mut().share_mode(access); self
-        }
-    }
-
-    /// Creates a new file symbolic link on the filesystem.
-    ///
-    /// The `dst` path will be a file symbolic link pointing to the `src`
-    /// path.
-    ///
-    /// # Examples
-    ///
-    /// ```ignore
-    /// #![feature(fs_ext)]
-    /// use std::os::windows::fs;
-    ///
-    /// # fn foo() -> std::io::Result<()> {
-    /// try!(fs::symlink_file("a.txt", "b.txt"));
-    /// # Ok(())
-    /// # }
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn symlink_file<P: AsRef<Path>, Q: AsRef<Path>>(src: P, dst: Q)
-                                                        -> io::Result<()>
-    {
-        sys::fs2::symlink_inner(src.as_ref(), dst.as_ref(), false)
-    }
-
-    /// Creates a new directory symlink on the filesystem.
-    ///
-    /// The `dst` path will be a directory symbolic link pointing to the `src`
-    /// path.
-    ///
-    /// # Examples
-    ///
-    /// ```ignore
-    /// #![feature(fs_ext)]
-    /// use std::os::windows::fs;
-    ///
-    /// # fn foo() -> std::io::Result<()> {
-    /// try!(fs::symlink_file("a", "b"));
-    /// # Ok(())
-    /// # }
-    /// ```
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn symlink_dir<P: AsRef<Path>, Q: AsRef<Path>> (src: P, dst: Q)
-                                                        -> io::Result<()>
-    {
-        sys::fs2::symlink_inner(src.as_ref(), dst.as_ref(), true)
-    }
-}
-
-/// A prelude for conveniently writing platform-specific code.
-///
-/// Includes all extension traits, and some important type definitions.
-#[stable(feature = "rust1", since = "1.0.0")]
-pub mod prelude {
-    #[doc(no_inline)]
-    pub use super::io::{RawSocket, RawHandle, AsRawSocket, AsRawHandle};
-    #[doc(no_inline)] #[stable(feature = "rust1", since = "1.0.0")]
-    pub use super::ffi::{OsStrExt, OsStringExt};
-    #[doc(no_inline)]
-    pub use super::fs::OpenOptionsExt;
-}
diff --git a/src/libstd/sys/windows/ext/ffi.rs b/src/libstd/sys/windows/ext/ffi.rs
new file mode 100644 (file)
index 0000000..3fa96f4
--- /dev/null
@@ -0,0 +1,58 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! Windows-specific extensions to the primitives in the `std::ffi` module.
+
+#![stable(feature = "rust1", since = "1.0.0")]
+
+use ffi::{OsString, OsStr};
+use sys::os_str::Buf;
+use sys_common::wtf8::Wtf8Buf;
+use sys_common::{FromInner, AsInner};
+
+pub use sys_common::wtf8::EncodeWide;
+
+/// Windows-specific extensions to `OsString`.
+#[stable(feature = "rust1", since = "1.0.0")]
+pub trait OsStringExt {
+    /// Creates an `OsString` from a potentially ill-formed UTF-16 slice of
+    /// 16-bit code units.
+    ///
+    /// This is lossless: calling `.encode_wide()` on the resulting string
+    /// will always return the original code units.
+    #[stable(feature = "rust1", since = "1.0.0")]
+    fn from_wide(wide: &[u16]) -> Self;
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl OsStringExt for OsString {
+    fn from_wide(wide: &[u16]) -> OsString {
+        FromInner::from_inner(Buf { inner: Wtf8Buf::from_wide(wide) })
+    }
+}
+
+/// Windows-specific extensions to `OsStr`.
+#[stable(feature = "rust1", since = "1.0.0")]
+pub trait OsStrExt {
+    /// Re-encodes an `OsStr` as a wide character sequence,
+    /// i.e. potentially ill-formed UTF-16.
+    ///
+    /// This is lossless. Note that the encoding does not include a final
+    /// null.
+    #[stable(feature = "rust1", since = "1.0.0")]
+    fn encode_wide(&self) -> EncodeWide;
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl OsStrExt for OsStr {
+    fn encode_wide(&self) -> EncodeWide {
+        self.as_inner().inner.encode_wide()
+    }
+}
diff --git a/src/libstd/sys/windows/ext/fs.rs b/src/libstd/sys/windows/ext/fs.rs
new file mode 100644 (file)
index 0000000..23c1fcf
--- /dev/null
@@ -0,0 +1,150 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! Windows-specific extensions for the primitives in `std::fs`
+
+#![stable(feature = "rust1", since = "1.0.0")]
+
+use prelude::v1::*;
+
+use fs::{OpenOptions, Metadata};
+use io;
+use path::Path;
+use sys;
+use sys_common::{AsInnerMut, AsInner};
+
+/// Windows-specific extensions to `OpenOptions`
+#[unstable(feature = "fs_ext", reason = "may require more thought/methods")]
+pub trait OpenOptionsExt {
+    /// Overrides the `dwDesiredAccess` argument to the call to `CreateFile`
+    /// with the specified value.
+    fn desired_access(&mut self, access: i32) -> &mut Self;
+
+    /// Overrides the `dwCreationDisposition` argument to the call to
+    /// `CreateFile` with the specified value.
+    ///
+    /// This will override any values of the standard `create` flags, for
+    /// example.
+    fn creation_disposition(&mut self, val: i32) -> &mut Self;
+
+    /// Overrides the `dwFlagsAndAttributes` argument to the call to
+    /// `CreateFile` with the specified value.
+    ///
+    /// This will override any values of the standard flags on the
+    /// `OpenOptions` structure.
+    fn flags_and_attributes(&mut self, val: i32) -> &mut Self;
+
+    /// Overrides the `dwShareMode` argument to the call to `CreateFile` with
+    /// the specified value.
+    ///
+    /// This will override any values of the standard flags on the
+    /// `OpenOptions` structure.
+    fn share_mode(&mut self, val: i32) -> &mut Self;
+}
+
+impl OpenOptionsExt for OpenOptions {
+    fn desired_access(&mut self, access: i32) -> &mut OpenOptions {
+        self.as_inner_mut().desired_access(access); self
+    }
+    fn creation_disposition(&mut self, access: i32) -> &mut OpenOptions {
+        self.as_inner_mut().creation_disposition(access); self
+    }
+    fn flags_and_attributes(&mut self, access: i32) -> &mut OpenOptions {
+        self.as_inner_mut().flags_and_attributes(access); self
+    }
+    fn share_mode(&mut self, access: i32) -> &mut OpenOptions {
+        self.as_inner_mut().share_mode(access); self
+    }
+}
+
+/// Extension methods for `fs::Metadata` to access the raw fields contained
+/// within.
+#[unstable(feature = "metadata_ext", reason = "recently added API")]
+pub trait MetadataExt {
+    /// Returns the value of the `dwFileAttributes` field of this metadata.
+    ///
+    /// This field contains the file system attribute information for a file
+    /// or directory.
+    fn file_attributes(&self) -> u32;
+
+    /// Returns the value of the `ftCreationTime` field of this metadata.
+    ///
+    /// The returned 64-bit value represents the number of 100-nanosecond
+    /// intervals since January 1, 1601 (UTC).
+    fn creation_time(&self) -> u64;
+
+    /// Returns the value of the `ftLastAccessTime` field of this metadata.
+    ///
+    /// The returned 64-bit value represents the number of 100-nanosecond
+    /// intervals since January 1, 1601 (UTC).
+    fn last_access_time(&self) -> u64;
+
+    /// Returns the value of the `ftLastWriteTime` field of this metadata.
+    ///
+    /// The returned 64-bit value represents the number of 100-nanosecond
+    /// intervals since January 1, 1601 (UTC).
+    fn last_write_time(&self) -> u64;
+
+    /// Returns the value of the `nFileSize{High,Low}` fields of this
+    /// metadata.
+    ///
+    /// The returned value does not have meaning for directories.
+    fn file_size(&self) -> u64;
+}
+
+impl MetadataExt for Metadata {
+    fn file_attributes(&self) -> u32 { self.as_inner().attrs() }
+    fn creation_time(&self) -> u64 { self.as_inner().created() }
+    fn last_access_time(&self) -> u64 { self.as_inner().accessed() }
+    fn last_write_time(&self) -> u64 { self.as_inner().modified() }
+    fn file_size(&self) -> u64 { self.as_inner().size() }
+}
+
+/// Creates a new file symbolic link on the filesystem.
+///
+/// The `dst` path will be a file symbolic link pointing to the `src`
+/// path.
+///
+/// # Examples
+///
+/// ```ignore
+/// use std::os::windows::fs;
+///
+/// # fn foo() -> std::io::Result<()> {
+/// try!(fs::symlink_file("a.txt", "b.txt"));
+/// # Ok(())
+/// # }
+/// ```
+#[stable(feature = "rust1", since = "1.0.0")]
+pub fn symlink_file<P: AsRef<Path>, Q: AsRef<Path>>(src: P, dst: Q)
+                                                    -> io::Result<()> {
+    sys::fs2::symlink_inner(src.as_ref(), dst.as_ref(), false)
+}
+
+/// Creates a new directory symlink on the filesystem.
+///
+/// The `dst` path will be a directory symbolic link pointing to the `src`
+/// path.
+///
+/// # Examples
+///
+/// ```ignore
+/// use std::os::windows::fs;
+///
+/// # fn foo() -> std::io::Result<()> {
+/// try!(fs::symlink_file("a", "b"));
+/// # Ok(())
+/// # }
+/// ```
+#[stable(feature = "rust1", since = "1.0.0")]
+pub fn symlink_dir<P: AsRef<Path>, Q: AsRef<Path>>(src: P, dst: Q)
+                                                   -> io::Result<()> {
+    sys::fs2::symlink_inner(src.as_ref(), dst.as_ref(), true)
+}
diff --git a/src/libstd/sys/windows/ext/io.rs b/src/libstd/sys/windows/ext/io.rs
new file mode 100644 (file)
index 0000000..b88a631
--- /dev/null
@@ -0,0 +1,131 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![stable(feature = "rust1", since = "1.0.0")]
+
+use fs;
+use os::windows::raw;
+use net;
+use sys_common::{net2, AsInner, FromInner};
+use sys;
+
+/// Raw HANDLEs.
+#[stable(feature = "rust1", since = "1.0.0")]
+pub type RawHandle = raw::HANDLE;
+
+/// Raw SOCKETs.
+#[stable(feature = "rust1", since = "1.0.0")]
+pub type RawSocket = raw::SOCKET;
+
+/// Extract raw handles.
+#[stable(feature = "rust1", since = "1.0.0")]
+pub trait AsRawHandle {
+    /// Extracts the raw handle, without taking any ownership.
+    #[stable(feature = "rust1", since = "1.0.0")]
+    fn as_raw_handle(&self) -> RawHandle;
+}
+
+/// Construct I/O objects from raw handles.
+#[unstable(feature = "from_raw_os",
+           reason = "recent addition to the std::os::windows::io module")]
+pub trait FromRawHandle {
+    /// Constructs a new I/O object from the specified raw handle.
+    ///
+    /// This function will **consume ownership** of the handle given,
+    /// passing responsibility for closing the handle to the returned
+    /// object.
+    ///
+    /// This function is also unsafe as the primitives currently returned
+    /// have the contract that they are the sole owner of the file
+    /// descriptor they are wrapping. Usage of this function could
+    /// accidentally allow violating this contract which can cause memory
+    /// unsafety in code that relies on it being true.
+    unsafe fn from_raw_handle(handle: RawHandle) -> Self;
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl AsRawHandle for fs::File {
+    fn as_raw_handle(&self) -> RawHandle {
+        self.as_inner().handle().raw() as RawHandle
+    }
+}
+
+#[unstable(feature = "from_raw_os", reason = "trait is unstable")]
+impl FromRawHandle for fs::File {
+    unsafe fn from_raw_handle(handle: RawHandle) -> fs::File {
+        let handle = handle as ::libc::HANDLE;
+        fs::File::from_inner(sys::fs2::File::from_inner(handle))
+    }
+}
+
+/// Extract raw sockets.
+#[stable(feature = "rust1", since = "1.0.0")]
+pub trait AsRawSocket {
+    /// Extracts the underlying raw socket from this object.
+    #[stable(feature = "rust1", since = "1.0.0")]
+    fn as_raw_socket(&self) -> RawSocket;
+}
+
+/// Create I/O objects from raw sockets.
+#[unstable(feature = "from_raw_os", reason = "recent addition to module")]
+pub trait FromRawSocket {
+    /// Creates a new I/O object from the given raw socket.
+    ///
+    /// This function will **consume ownership** of the socket provided and
+    /// it will be closed when the returned object goes out of scope.
+    ///
+    /// This function is also unsafe as the primitives currently returned
+    /// have the contract that they are the sole owner of the file
+    /// descriptor they are wrapping. Usage of this function could
+    /// accidentally allow violating this contract which can cause memory
+    /// unsafety in code that relies on it being true.
+    unsafe fn from_raw_socket(sock: RawSocket) -> Self;
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+impl AsRawSocket for net::TcpStream {
+    fn as_raw_socket(&self) -> RawSocket {
+        *self.as_inner().socket().as_inner()
+    }
+}
+#[stable(feature = "rust1", since = "1.0.0")]
+impl AsRawSocket for net::TcpListener {
+    fn as_raw_socket(&self) -> RawSocket {
+        *self.as_inner().socket().as_inner()
+    }
+}
+#[stable(feature = "rust1", since = "1.0.0")]
+impl AsRawSocket for net::UdpSocket {
+    fn as_raw_socket(&self) -> RawSocket {
+        *self.as_inner().socket().as_inner()
+    }
+}
+
+#[unstable(feature = "from_raw_os", reason = "trait is unstable")]
+impl FromRawSocket for net::TcpStream {
+    unsafe fn from_raw_socket(sock: RawSocket) -> net::TcpStream {
+        let sock = sys::net::Socket::from_inner(sock);
+        net::TcpStream::from_inner(net2::TcpStream::from_inner(sock))
+    }
+}
+#[unstable(feature = "from_raw_os", reason = "trait is unstable")]
+impl FromRawSocket for net::TcpListener {
+    unsafe fn from_raw_socket(sock: RawSocket) -> net::TcpListener {
+        let sock = sys::net::Socket::from_inner(sock);
+        net::TcpListener::from_inner(net2::TcpListener::from_inner(sock))
+    }
+}
+#[unstable(feature = "from_raw_os", reason = "trait is unstable")]
+impl FromRawSocket for net::UdpSocket {
+    unsafe fn from_raw_socket(sock: RawSocket) -> net::UdpSocket {
+        let sock = sys::net::Socket::from_inner(sock);
+        net::UdpSocket::from_inner(net2::UdpSocket::from_inner(sock))
+    }
+}
diff --git a/src/libstd/sys/windows/ext/mod.rs b/src/libstd/sys/windows/ext/mod.rs
new file mode 100644 (file)
index 0000000..08dfa4c
--- /dev/null
@@ -0,0 +1,35 @@
+// 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.
+
+//! Experimental extensions to `std` for Windows.
+//!
+//! For now, this module is limited to extracting handles, file
+//! descriptors, and sockets, but its functionality will grow over
+//! time.
+
+#![stable(feature = "rust1", since = "1.0.0")]
+
+pub mod ffi;
+pub mod fs;
+pub mod io;
+pub mod raw;
+
+/// A prelude for conveniently writing platform-specific code.
+///
+/// Includes all extension traits, and some important type definitions.
+#[stable(feature = "rust1", since = "1.0.0")]
+pub mod prelude {
+    #[doc(no_inline)]
+    pub use super::io::{RawSocket, RawHandle, AsRawSocket, AsRawHandle};
+    #[doc(no_inline)] #[stable(feature = "rust1", since = "1.0.0")]
+    pub use super::ffi::{OsStrExt, OsStringExt};
+    #[doc(no_inline)]
+    pub use super::fs::{OpenOptionsExt, MetadataExt};
+}
diff --git a/src/libstd/sys/windows/ext/raw.rs b/src/libstd/sys/windows/ext/raw.rs
new file mode 100644 (file)
index 0000000..656e480
--- /dev/null
@@ -0,0 +1,21 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! Windows-specific primitives
+
+#![unstable(feature = "raw_ext", reason = "recently added API")]
+
+use os::raw;
+
+pub type HANDLE = *mut raw::c_void;
+#[cfg(target_pointer_width = "32")]
+pub type SOCKET = u32;
+#[cfg(target_pointer_width = "64")]
+pub type SOCKET = u64;
index 5ac9a0ace5801ba08d6b914935d5bea27f72792b..03a56e2958a6e9f485b050323ac42274b744b9eb 100644 (file)
 use vec::Vec;
 
 pub struct File { handle: Handle }
-pub struct FileAttr { data: c::WIN32_FILE_ATTRIBUTE_DATA }
+
+pub struct FileAttr {
+    data: c::WIN32_FILE_ATTRIBUTE_DATA,
+    is_symlink: bool,
+}
+
+#[derive(Copy, Clone, PartialEq, Eq, Hash)]
+pub enum FileType {
+    Dir, File, Symlink, ReparsePoint
+}
 
 pub struct ReadDir {
     handle: FindNextFileHandle,
@@ -56,11 +65,14 @@ pub struct OpenOptions {
     share_mode: Option<libc::DWORD>,
     creation_disposition: Option<libc::DWORD>,
     flags_and_attributes: Option<libc::DWORD>,
+    security_attributes: usize, // *mut T doesn't have a Default impl
 }
 
 #[derive(Clone, PartialEq, Eq, Debug)]
 pub struct FilePermissions { attrs: libc::DWORD }
 
+pub struct DirBuilder;
+
 impl Iterator for ReadDir {
     type Item = io::Result<DirEntry>;
     fn next(&mut self) -> Option<io::Result<DirEntry>> {
@@ -111,8 +123,31 @@ fn new(root: &Arc<PathBuf>, wfd: &libc::WIN32_FIND_DATAW) -> Option<DirEntry> {
     }
 
     pub fn path(&self) -> PathBuf {
+        self.root.join(&self.file_name())
+    }
+
+    pub fn file_name(&self) -> OsString {
         let filename = super::truncate_utf16_at_nul(&self.data.cFileName);
-        self.root.join(&<OsString as OsStringExt>::from_wide(filename))
+        OsString::from_wide(filename)
+    }
+
+    pub fn file_type(&self) -> io::Result<FileType> {
+        Ok(FileType::new(self.data.dwFileAttributes,
+                         self.data.dwReserved0 == c::IO_REPARSE_TAG_SYMLINK))
+    }
+
+    pub fn metadata(&self) -> io::Result<FileAttr> {
+        Ok(FileAttr {
+            data: c::WIN32_FILE_ATTRIBUTE_DATA {
+                dwFileAttributes: self.data.dwFileAttributes,
+                ftCreationTime: self.data.ftCreationTime,
+                ftLastAccessTime: self.data.ftLastAccessTime,
+                ftLastWriteTime: self.data.ftLastWriteTime,
+                nFileSizeHigh: self.data.nFileSizeHigh,
+                nFileSizeLow: self.data.nFileSizeLow,
+            },
+            is_symlink: self.data.dwReserved0 == c::IO_REPARSE_TAG_SYMLINK,
+        })
     }
 }
 
@@ -135,6 +170,9 @@ pub fn desired_access(&mut self, val: i32) {
     pub fn share_mode(&mut self, val: i32) {
         self.share_mode = Some(val as libc::DWORD);
     }
+    pub fn security_attributes(&mut self, attrs: libc::LPSECURITY_ATTRIBUTES) {
+        self.security_attributes = attrs as usize;
+    }
 
     fn get_desired_access(&self) -> libc::DWORD {
         self.desired_access.unwrap_or({
@@ -180,13 +218,20 @@ fn get_flags_and_attributes(&self) -> libc::DWORD {
 }
 
 impl File {
+    fn open_reparse_point(path: &Path) -> io::Result<File> {
+        let mut opts = OpenOptions::new();
+        opts.read(true);
+        opts.flags_and_attributes(c::FILE_FLAG_OPEN_REPARSE_POINT as i32);
+        File::open(path, &opts)
+    }
+
     pub fn open(path: &Path, opts: &OpenOptions) -> io::Result<File> {
         let path = to_utf16(path);
         let handle = unsafe {
             libc::CreateFileW(path.as_ptr(),
                               opts.get_desired_access(),
                               opts.get_share_mode(),
-                              ptr::null_mut(),
+                              opts.security_attributes as *mut _,
                               opts.get_creation_disposition(),
                               opts.get_flags_and_attributes(),
                               ptr::null_mut())
@@ -224,7 +269,7 @@ pub fn file_attr(&self) -> io::Result<FileAttr> {
             let mut info: c::BY_HANDLE_FILE_INFORMATION = mem::zeroed();
             try!(cvt(c::GetFileInformationByHandle(self.handle.raw(),
                                                    &mut info)));
-            Ok(FileAttr {
+            let mut attr = FileAttr {
                 data: c::WIN32_FILE_ATTRIBUTE_DATA {
                     dwFileAttributes: info.dwFileAttributes,
                     ftCreationTime: info.ftCreationTime,
@@ -232,8 +277,13 @@ pub fn file_attr(&self) -> io::Result<FileAttr> {
                     ftLastWriteTime: info.ftLastWriteTime,
                     nFileSizeHigh: info.nFileSizeHigh,
                     nFileSizeLow: info.nFileSizeLow,
-                }
-            })
+                },
+                is_symlink: false,
+            };
+            if attr.is_reparse_point() {
+                attr.is_symlink = self.is_symlink();
+            }
+            Ok(attr)
         }
     }
 
@@ -263,6 +313,43 @@ pub fn seek(&self, pos: SeekFrom) -> io::Result<u64> {
     }
 
     pub fn handle(&self) -> &Handle { &self.handle }
+
+    fn is_symlink(&self) -> bool {
+        self.readlink().is_ok()
+    }
+
+    fn readlink(&self) -> io::Result<PathBuf> {
+        let mut space = [0u8; c::MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
+        let mut bytes = 0;
+
+        unsafe {
+            try!(cvt({
+                c::DeviceIoControl(self.handle.raw(),
+                                   c::FSCTL_GET_REPARSE_POINT,
+                                   0 as *mut _,
+                                   0,
+                                   space.as_mut_ptr() as *mut _,
+                                   space.len() as libc::DWORD,
+                                   &mut bytes,
+                                   0 as *mut _)
+            }));
+            let buf: *const c::REPARSE_DATA_BUFFER = space.as_ptr() as *const _;
+            if (*buf).ReparseTag != c::IO_REPARSE_TAG_SYMLINK {
+                return Err(io::Error::new(io::ErrorKind::Other, "not a symlink"))
+            }
+            let info: *const c::SYMBOLIC_LINK_REPARSE_BUFFER =
+                    &(*buf).rest as *const _ as *const _;
+            let path_buffer = &(*info).PathBuffer as *const _ as *const u16;
+            let subst_off = (*info).SubstituteNameOffset / 2;
+            let subst_ptr = path_buffer.offset(subst_off as isize);
+            let subst_len = (*info).SubstituteNameLength / 2;
+            let subst = slice::from_raw_parts(subst_ptr, subst_len as usize);
+
+            Ok(PathBuf::from(OsString::from_wide(subst)))
+        }
+    }
+
+    pub fn into_handle(self) -> Handle { self.handle }
 }
 
 impl FromInner<libc::HANDLE> for File {
@@ -285,27 +372,30 @@ pub fn to_utf16(s: &Path) -> Vec<u16> {
 }
 
 impl FileAttr {
-    pub fn is_dir(&self) -> bool {
-        self.data.dwFileAttributes & c::FILE_ATTRIBUTE_DIRECTORY != 0
-    }
-    pub fn is_file(&self) -> bool {
-        !self.is_dir()
-    }
     pub fn size(&self) -> u64 {
         ((self.data.nFileSizeHigh as u64) << 32) | (self.data.nFileSizeLow as u64)
     }
+
     pub fn perm(&self) -> FilePermissions {
         FilePermissions { attrs: self.data.dwFileAttributes }
     }
 
-    pub fn accessed(&self) -> u64 { self.to_ms(&self.data.ftLastAccessTime) }
-    pub fn modified(&self) -> u64 { self.to_ms(&self.data.ftLastWriteTime) }
+    pub fn attrs(&self) -> u32 { self.data.dwFileAttributes as u32 }
 
-    fn to_ms(&self, ft: &libc::FILETIME) -> u64 {
-        // FILETIME is in 100ns intervals and there are 10000 intervals in a
-        // millisecond.
-        let bits = (ft.dwLowDateTime as u64) | ((ft.dwHighDateTime as u64) << 32);
-        bits / 10000
+    pub fn file_type(&self) -> FileType {
+        FileType::new(self.data.dwFileAttributes, self.is_symlink)
+    }
+
+    pub fn created(&self) -> u64 { self.to_u64(&self.data.ftCreationTime) }
+    pub fn accessed(&self) -> u64 { self.to_u64(&self.data.ftLastAccessTime) }
+    pub fn modified(&self) -> u64 { self.to_u64(&self.data.ftLastWriteTime) }
+
+    fn to_u64(&self, ft: &libc::FILETIME) -> u64 {
+        (ft.dwLowDateTime as u64) | ((ft.dwHighDateTime as u64) << 32)
+    }
+
+    fn is_reparse_point(&self) -> bool {
+        self.data.dwFileAttributes & libc::FILE_ATTRIBUTE_REPARSE_POINT != 0
     }
 }
 
@@ -323,12 +413,36 @@ pub fn set_readonly(&mut self, readonly: bool) {
     }
 }
 
-pub fn mkdir(p: &Path) -> io::Result<()> {
-    let p = to_utf16(p);
-    try!(cvt(unsafe {
-        libc::CreateDirectoryW(p.as_ptr(), ptr::null_mut())
-    }));
-    Ok(())
+impl FileType {
+    fn new(attrs: libc::DWORD, is_symlink: bool) -> FileType {
+        if attrs & libc::FILE_ATTRIBUTE_REPARSE_POINT != 0 {
+            if is_symlink {
+                FileType::Symlink
+            } else {
+                FileType::ReparsePoint
+            }
+        } else if attrs & c::FILE_ATTRIBUTE_DIRECTORY != 0 {
+            FileType::Dir
+        } else {
+            FileType::File
+        }
+    }
+
+    pub fn is_dir(&self) -> bool { *self == FileType::Dir }
+    pub fn is_file(&self) -> bool { *self == FileType::File }
+    pub fn is_symlink(&self) -> bool { *self == FileType::Symlink }
+}
+
+impl DirBuilder {
+    pub fn new() -> DirBuilder { DirBuilder }
+
+    pub fn mkdir(&self, p: &Path) -> io::Result<()> {
+        let p = to_utf16(p);
+        try!(cvt(unsafe {
+            libc::CreateDirectoryW(p.as_ptr(), ptr::null_mut())
+        }));
+        Ok(())
+    }
 }
 
 pub fn readdir(p: &Path) -> io::Result<ReadDir> {
@@ -374,40 +488,8 @@ pub fn rmdir(p: &Path) -> io::Result<()> {
 }
 
 pub fn readlink(p: &Path) -> io::Result<PathBuf> {
-    let mut opts = OpenOptions::new();
-    opts.read(true);
-    opts.flags_and_attributes(c::FILE_FLAG_OPEN_REPARSE_POINT as i32);
-    let file = try!(File::open(p, &opts));
-
-    let mut space = [0u8; c::MAXIMUM_REPARSE_DATA_BUFFER_SIZE];
-    let mut bytes = 0;
-
-    unsafe {
-        try!(cvt({
-            c::DeviceIoControl(file.handle.raw(),
-                               c::FSCTL_GET_REPARSE_POINT,
-                               0 as *mut _,
-                               0,
-                               space.as_mut_ptr() as *mut _,
-                               space.len() as libc::DWORD,
-                               &mut bytes,
-                               0 as *mut _)
-        }));
-        let buf: *const c::REPARSE_DATA_BUFFER = space.as_ptr() as *const _;
-        if (*buf).ReparseTag != c::IO_REPARSE_TAG_SYMLINK {
-            return Err(io::Error::new(io::ErrorKind::Other, "not a symlink"))
-        }
-        let info: *const c::SYMBOLIC_LINK_REPARSE_BUFFER =
-                &(*buf).rest as *const _ as *const _;
-        let path_buffer = &(*info).PathBuffer as *const _ as *const u16;
-        let subst_off = (*info).SubstituteNameOffset / 2;
-        let subst_ptr = path_buffer.offset(subst_off as isize);
-        let subst_len = (*info).SubstituteNameLength / 2;
-        let subst = slice::from_raw_parts(subst_ptr, subst_len as usize);
-
-        Ok(PathBuf::from(OsString::from_wide(subst)))
-    }
-
+    let file = try!(File::open_reparse_point(p));
+    file.readlink()
 }
 
 pub fn symlink(src: &Path, dst: &Path) -> io::Result<()> {
@@ -435,12 +517,28 @@ pub fn link(src: &Path, dst: &Path) -> io::Result<()> {
 }
 
 pub fn stat(p: &Path) -> io::Result<FileAttr> {
-    let p = to_utf16(p);
+    let attr = try!(lstat(p));
+    if attr.data.dwFileAttributes & libc::FILE_ATTRIBUTE_REPARSE_POINT != 0 {
+        let opts = OpenOptions::new();
+        let file = try!(File::open(p, &opts));
+        file.file_attr()
+    } else {
+        Ok(attr)
+    }
+}
+
+pub fn lstat(p: &Path) -> io::Result<FileAttr> {
+    let utf16 = to_utf16(p);
     unsafe {
         let mut attr: FileAttr = mem::zeroed();
-        try!(cvt(c::GetFileAttributesExW(p.as_ptr(),
+        try!(cvt(c::GetFileAttributesExW(utf16.as_ptr(),
                                          c::GetFileExInfoStandard,
                                          &mut attr.data as *mut _ as *mut _)));
+        if attr.is_reparse_point() {
+            attr.is_symlink = File::open_reparse_point(p).map(|f| {
+                f.is_symlink()
+            }).unwrap_or(false);
+        }
         Ok(attr)
     }
 }
@@ -465,3 +563,17 @@ pub fn utimes(p: &Path, atime: u64, mtime: u64) -> io::Result<()> {
     }));
     Ok(())
 }
+
+pub fn canonicalize(p: &Path) -> io::Result<PathBuf> {
+    use sys::c::compat::kernel32::GetFinalPathNameByHandleW;
+
+    let mut opts = OpenOptions::new();
+    opts.read(true);
+    let f = try!(File::open(p, &opts));
+    super::fill_utf16_buf(|buf, sz| unsafe {
+        GetFinalPathNameByHandleW(f.handle.raw(), buf, sz,
+                                  libc::VOLUME_NAME_DOS)
+    }, |buf| {
+        PathBuf::from(OsString::from_wide(buf))
+    })
+}
index c3a30aae9e0e87dd23b5c5630c6d6d4f7a7ddef7..9481e180ce5781a42219c79cd2b79b93ed574c4c 100644 (file)
@@ -12,6 +12,7 @@
 
 use io::ErrorKind;
 use io;
+use libc::funcs::extra::kernel32::{GetCurrentProcess, DuplicateHandle};
 use libc::{self, HANDLE};
 use mem;
 use ptr;
@@ -65,6 +66,18 @@ pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
         }));
         Ok(amt as usize)
     }
+
+    pub fn duplicate(&self, access: libc::DWORD, inherit: bool,
+                     options: libc::DWORD) -> io::Result<Handle> {
+        let mut ret = 0 as libc::HANDLE;
+        try!(cvt(unsafe {
+            let cur_proc = GetCurrentProcess();
+            DuplicateHandle(cur_proc, self.0, cur_proc, &mut ret,
+                            access, inherit as libc::BOOL,
+                            options)
+        }));
+        Ok(Handle::new(ret))
+    }
 }
 
 impl Drop for Handle {
index 2e5585d2f4389a8a51307594c6ecd49062d0a4e9..5aad5f668dd418279642d6f5afd83fc935fabfbf 100644 (file)
 use ascii::*;
 use collections::HashMap;
 use collections;
+use env::split_paths;
 use env;
 use ffi::{OsString, OsStr};
 use fmt;
 use fs;
 use io::{self, Error};
 use libc::{self, c_void};
+use mem;
 use os::windows::ffi::OsStrExt;
+use path::Path;
 use ptr;
 use sync::{StaticMutex, MUTEX_INIT};
+use sys::c;
+use sys::fs2::{OpenOptions, File};
 use sys::handle::Handle;
 use sys::pipe2::AnonPipe;
+use sys::stdio;
 use sys::{self, cvt};
 use sys_common::{AsInner, FromInner};
 
@@ -90,18 +96,12 @@ pub fn cwd(&mut self, dir: &OsStr) {
 // Processes
 ////////////////////////////////////////////////////////////////////////////////
 
-// `CreateProcess` is racy!
-// http://support.microsoft.com/kb/315939
-static CREATE_PROCESS_LOCK: StaticMutex = MUTEX_INIT;
-
 /// A value representing a child process.
 ///
 /// The lifetime of this value is linked to the lifetime of the actual
 /// process - the Process destructor calls self.finish() which waits
 /// for the process to terminate.
 pub struct Process {
-    /// A HANDLE to the process, which will prevent the pid being
-    /// re-used until the handle is closed.
     handle: Handle,
 }
 
@@ -112,32 +112,17 @@ pub enum Stdio {
 }
 
 impl Process {
-    #[allow(deprecated)]
     pub fn spawn(cfg: &Command,
-                 in_fd: Stdio,
-                 out_fd: Stdio,
-                 err_fd: Stdio) -> io::Result<Process>
+                 in_handle: Stdio,
+                 out_handle: Stdio,
+                 err_handle: Stdio) -> io::Result<Process>
     {
-        use libc::types::os::arch::extra::{DWORD, HANDLE, STARTUPINFO};
-        use libc::consts::os::extra::{
-            TRUE, FALSE,
-            STARTF_USESTDHANDLES,
-            INVALID_HANDLE_VALUE,
-            DUPLICATE_SAME_ACCESS
-        };
-        use libc::funcs::extra::kernel32::{
-            GetCurrentProcess,
-            DuplicateHandle,
-            CloseHandle,
-            CreateProcessW
-        };
-
-        use env::split_paths;
-        use mem;
-        use iter::Iterator;
-
-        // To have the spawning semantics of unix/windows stay the same, we need to
-        // read the *child's* PATH if one is provided. See #15149 for more details.
+        use libc::{TRUE, STARTF_USESTDHANDLES};
+        use libc::{DWORD, STARTUPINFO, CreateProcessW};
+
+        // To have the spawning semantics of unix/windows stay the same, we need
+        // to read the *child's* PATH if one is provided. See #15149 for more
+        // details.
         let program = cfg.env.as_ref().and_then(|env| {
             for (key, v) in env {
                 if OsStr::new("PATH") != &**key { continue }
@@ -156,118 +141,51 @@ pub fn spawn(cfg: &Command,
             None
         });
 
-        unsafe {
-            let mut si = zeroed_startupinfo();
-            si.cb = mem::size_of::<STARTUPINFO>() as DWORD;
-            si.dwFlags = STARTF_USESTDHANDLES;
-
-            let cur_proc = GetCurrentProcess();
-
-            let set_fd = |fd: &Stdio, slot: &mut HANDLE,
-                          is_stdin: bool| {
-                match *fd {
-                    Stdio::Inherit => {}
-
-                    // Similarly to unix, we don't actually leave holes for the
-                    // stdio file descriptors, but rather open up /dev/null
-                    // equivalents. These equivalents are drawn from libuv's
-                    // windows process spawning.
-                    Stdio::None => {
-                        let access = if is_stdin {
-                            libc::FILE_GENERIC_READ
-                        } else {
-                            libc::FILE_GENERIC_WRITE | libc::FILE_READ_ATTRIBUTES
-                        };
-                        let size = mem::size_of::<libc::SECURITY_ATTRIBUTES>();
-                        let mut sa = libc::SECURITY_ATTRIBUTES {
-                            nLength: size as libc::DWORD,
-                            lpSecurityDescriptor: ptr::null_mut(),
-                            bInheritHandle: 1,
-                        };
-                        let mut filename: Vec<u16> = "NUL".utf16_units().collect();
-                        filename.push(0);
-                        *slot = libc::CreateFileW(filename.as_ptr(),
-                                                  access,
-                                                  libc::FILE_SHARE_READ |
-                                                      libc::FILE_SHARE_WRITE,
-                                                  &mut sa,
-                                                  libc::OPEN_EXISTING,
-                                                  0,
-                                                  ptr::null_mut());
-                        if *slot == INVALID_HANDLE_VALUE {
-                            return Err(Error::last_os_error())
-                        }
-                    }
-                    Stdio::Piped(ref pipe) => {
-                        let orig = pipe.handle().raw();
-                        if DuplicateHandle(cur_proc, orig, cur_proc, slot,
-                                           0, TRUE, DUPLICATE_SAME_ACCESS) == FALSE {
-                            return Err(Error::last_os_error())
-                        }
-                    }
-                }
-                Ok(())
-            };
-
-            try!(set_fd(&in_fd, &mut si.hStdInput, true));
-            try!(set_fd(&out_fd, &mut si.hStdOutput, false));
-            try!(set_fd(&err_fd, &mut si.hStdError, false));
+        let mut si = zeroed_startupinfo();
+        si.cb = mem::size_of::<STARTUPINFO>() as DWORD;
+        si.dwFlags = STARTF_USESTDHANDLES;
 
-            let mut cmd_str = make_command_line(program.as_ref().unwrap_or(&cfg.program),
-                                            &cfg.args);
-            cmd_str.push(0); // add null terminator
+        let stdin = try!(in_handle.to_handle(c::STD_INPUT_HANDLE));
+        let stdout = try!(out_handle.to_handle(c::STD_OUTPUT_HANDLE));
+        let stderr = try!(err_handle.to_handle(c::STD_ERROR_HANDLE));
 
-            let mut pi = zeroed_process_information();
-            let mut create_err = None;
-
-            // stolen from the libuv code.
-            let mut flags = libc::CREATE_UNICODE_ENVIRONMENT;
-            if cfg.detach {
-                flags |= libc::DETACHED_PROCESS | libc::CREATE_NEW_PROCESS_GROUP;
-            }
+        si.hStdInput = stdin.raw();
+        si.hStdOutput = stdout.raw();
+        si.hStdError = stderr.raw();
 
-            with_envp(cfg.env.as_ref(), |envp| {
-                with_dirp(cfg.cwd.as_ref(), |dirp| {
-                    let _lock = CREATE_PROCESS_LOCK.lock().unwrap();
-                    let created = CreateProcessW(ptr::null(),
-                                                 cmd_str.as_mut_ptr(),
-                                                 ptr::null_mut(),
-                                                 ptr::null_mut(),
-                                                 TRUE,
-                                                 flags, envp, dirp,
-                                                 &mut si, &mut pi);
-                    if created == FALSE {
-                        create_err = Some(Error::last_os_error());
-                    }
-                })
-            });
+        let program = program.as_ref().unwrap_or(&cfg.program);
+        let mut cmd_str = make_command_line(program, &cfg.args);
+        cmd_str.push(0); // add null terminator
 
-            if !in_fd.inherited() {
-                assert!(CloseHandle(si.hStdInput) != 0);
-            }
-            if !out_fd.inherited() {
-                assert!(CloseHandle(si.hStdOutput) != 0);
-            }
-            if !err_fd.inherited() {
-                assert!(CloseHandle(si.hStdError) != 0);
-            }
+        // stolen from the libuv code.
+        let mut flags = libc::CREATE_UNICODE_ENVIRONMENT;
+        if cfg.detach {
+            flags |= libc::DETACHED_PROCESS | libc::CREATE_NEW_PROCESS_GROUP;
+        }
 
-            match create_err {
-                Some(err) => return Err(err),
-                None => {}
-            }
+        let (envp, _data) = make_envp(cfg.env.as_ref());
+        let (dirp, _data) = make_dirp(cfg.cwd.as_ref());
+        let mut pi = zeroed_process_information();
+        try!(unsafe {
+            // `CreateProcess` is racy!
+            // http://support.microsoft.com/kb/315939
+            static CREATE_PROCESS_LOCK: StaticMutex = MUTEX_INIT;
+            let _lock = CREATE_PROCESS_LOCK.lock();
+
+            cvt(CreateProcessW(ptr::null(),
+                               cmd_str.as_mut_ptr(),
+                               ptr::null_mut(),
+                               ptr::null_mut(),
+                               TRUE, flags, envp, dirp,
+                               &mut si, &mut pi))
+        });
 
-            // We close the thread handle because we don't care about keeping the
-            // thread id valid, and we aren't keeping the thread handle around to be
-            // able to close it later. We don't close the process handle however
-            // because std::we want the process id to stay valid at least until the
-            // calling code closes the process handle.
-            assert!(CloseHandle(pi.hThread) != 0);
+        // We close the thread handle because we don't care about keeping
+        // the thread id valid, and we aren't keeping the thread handle
+        // around to be able to close it later.
+        drop(Handle::new(pi.hThread));
 
-            Ok(Process {
-                handle: Handle::new(pi.hProcess)
-            })
-        }
+        Ok(Process { handle: Handle::new(pi.hProcess) })
     }
 
     pub unsafe fn kill(&self) -> io::Result<()> {
@@ -276,45 +194,25 @@ pub unsafe fn kill(&self) -> io::Result<()> {
     }
 
     pub fn wait(&self) -> io::Result<ExitStatus> {
-        use libc::consts::os::extra::{
-            FALSE,
-            STILL_ACTIVE,
-            INFINITE,
-            WAIT_OBJECT_0,
-        };
-        use libc::funcs::extra::kernel32::{
-            GetExitCodeProcess,
-            WaitForSingleObject,
-        };
+        use libc::{STILL_ACTIVE, INFINITE, WAIT_OBJECT_0};
+        use libc::{GetExitCodeProcess, WaitForSingleObject};
 
         unsafe {
             loop {
                 let mut status = 0;
-                if GetExitCodeProcess(self.handle.raw(), &mut status) == FALSE {
-                    let err = Err(Error::last_os_error());
-                    return err;
-                }
+                try!(cvt(GetExitCodeProcess(self.handle.raw(), &mut status)));
                 if status != STILL_ACTIVE {
                     return Ok(ExitStatus(status as i32));
                 }
                 match WaitForSingleObject(self.handle.raw(), INFINITE) {
                     WAIT_OBJECT_0 => {}
-                    _ => {
-                        let err = Err(Error::last_os_error());
-                        return err
-                    }
+                    _ => return Err(Error::last_os_error()),
                 }
             }
         }
     }
 }
 
-impl Stdio {
-    fn inherited(&self) -> bool {
-        match *self { Stdio::Inherit => true, _ => false }
-    }
-}
-
 #[derive(PartialEq, Eq, Clone, Copy, Debug)]
 pub struct ExitStatus(i32);
 
@@ -415,9 +313,8 @@ fn append_arg(cmd: &mut Vec<u16>, arg: &OsStr) {
     }
 }
 
-fn with_envp<F, T>(env: Option<&collections::HashMap<OsString, OsString>>, cb: F) -> T
-    where F: FnOnce(*mut c_void) -> T,
-{
+fn make_envp(env: Option<&collections::HashMap<OsString, OsString>>)
+             -> (*mut c_void, Vec<u16>) {
     // On Windows we pass an "environment block" which is not a char**, but
     // rather a concatenation of null-terminated k=v\0 sequences, with a final
     // \0 to terminate.
@@ -432,22 +329,57 @@ fn with_envp<F, T>(env: Option<&collections::HashMap<OsString, OsString>>, cb: F
                 blk.push(0);
             }
             blk.push(0);
-            cb(blk.as_mut_ptr() as *mut c_void)
+            (blk.as_mut_ptr() as *mut c_void, blk)
         }
-        _ => cb(ptr::null_mut())
+        _ => (ptr::null_mut(), Vec::new())
     }
 }
 
-fn with_dirp<T, F>(d: Option<&OsString>, cb: F) -> T where
-    F: FnOnce(*const u16) -> T,
-{
+fn make_dirp(d: Option<&OsString>) -> (*const u16, Vec<u16>) {
     match d {
-      Some(dir) => {
-          let mut dir_str: Vec<u16> = dir.encode_wide().collect();
-          dir_str.push(0);
-          cb(dir_str.as_ptr())
-      },
-      None => cb(ptr::null())
+        Some(dir) => {
+            let mut dir_str: Vec<u16> = dir.encode_wide().collect();
+            dir_str.push(0);
+            (dir_str.as_ptr(), dir_str)
+        },
+        None => (ptr::null(), Vec::new())
+    }
+}
+
+impl Stdio {
+    fn to_handle(&self, stdio_id: libc::DWORD) -> io::Result<Handle> {
+        use libc::DUPLICATE_SAME_ACCESS;
+
+        match *self {
+            Stdio::Inherit => {
+                stdio::get(stdio_id).and_then(|io| {
+                    io.handle().duplicate(0, true, DUPLICATE_SAME_ACCESS)
+                })
+            }
+            Stdio::Piped(ref pipe) => {
+                pipe.handle().duplicate(0, true, DUPLICATE_SAME_ACCESS)
+            }
+
+            // Similarly to unix, we don't actually leave holes for the
+            // stdio file descriptors, but rather open up /dev/null
+            // equivalents. These equivalents are drawn from libuv's
+            // windows process spawning.
+            Stdio::None => {
+                let size = mem::size_of::<libc::SECURITY_ATTRIBUTES>();
+                let mut sa = libc::SECURITY_ATTRIBUTES {
+                    nLength: size as libc::DWORD,
+                    lpSecurityDescriptor: ptr::null_mut(),
+                    bInheritHandle: 1,
+                };
+                let mut opts = OpenOptions::new();
+                opts.read(stdio_id == c::STD_INPUT_HANDLE);
+                opts.write(stdio_id != c::STD_INPUT_HANDLE);
+                opts.security_attributes(&mut sa);
+                File::open(Path::new("NUL"), &opts).map(|file| {
+                    file.into_handle()
+                })
+            }
+        }
     }
 }
 
index 91f6f328ff6e0a9eb7038dbfe21e7c4babca885a..03547165f5d8700aa3f3939b8511db9cb237724e 100644 (file)
@@ -21,9 +21,9 @@
 use sys::cvt;
 use sys::handle::Handle;
 
-struct NoClose(Option<Handle>);
+pub struct NoClose(Option<Handle>);
 
-enum Output {
+pub enum Output {
     Console(NoClose),
     Pipe(NoClose),
 }
@@ -35,7 +35,7 @@ pub struct Stdin {
 pub struct Stdout(Output);
 pub struct Stderr(Output);
 
-fn get(handle: libc::DWORD) -> io::Result<Output> {
+pub fn get(handle: libc::DWORD) -> io::Result<Output> {
     let handle = unsafe { c::GetStdHandle(handle) };
     if handle == libc::INVALID_HANDLE_VALUE {
         Err(io::Error::last_os_error())
@@ -159,6 +159,16 @@ fn drop(&mut self) {
     }
 }
 
+impl Output {
+    pub fn handle(&self) -> &Handle {
+        let nc = match *self {
+            Output::Console(ref c) => c,
+            Output::Pipe(ref c) => c,
+        };
+        nc.0.as_ref().unwrap()
+    }
+}
+
 fn invalid_encoding() -> io::Error {
     io::Error::new(io::ErrorKind::InvalidInput, "text was not valid unicode")
 }
index d028a169b64b7051a3963cead3c4023aa9f6dc5d..bb2832b874657deb26f0b0dc983e2326e197a40b 100644 (file)
@@ -356,6 +356,7 @@ unsafe fn register_dtor(t: *mut u8, dtor: unsafe extern fn(*mut u8)) {
         use sys_common::thread_local as os;
 
         extern {
+            #[linkage = "extern_weak"]
             static __dso_handle: *mut u8;
             #[linkage = "extern_weak"]
             static __cxa_thread_atexit_impl: *const ();
index ce531fb13812c30db599fef9a42b10e8f3a8aad0..bcc70c2b8163e25479853ae89a2f06e714a0f211 100644 (file)
@@ -263,7 +263,7 @@ pub fn stack_size(mut self, size: usize) -> Builder {
     ///
     /// The child thread may outlive the parent (unless the parent thread
     /// is the main thread; the whole process is terminated when the main
-    /// thread finishes.) The join handle can be used to block on
+    /// thread finishes). The join handle can be used to block on
     /// termination of the child thread, including recovering its panics.
     ///
     /// # Errors
@@ -700,7 +700,6 @@ pub fn join(mut self) -> T {
     }
 }
 
-#[unsafe_destructor]
 #[unstable(feature = "scoped",
            reason = "memory unsafe if destructor is avoided, see #24292")]
 impl<'a, T: Send + 'a> Drop for JoinGuard<'a, T> {
index 9c0b4a5d8337800211d774098f57f81fa9f5a132..35684a1f39095b79df477a194f1a27a31961552b 100644 (file)
@@ -171,8 +171,7 @@ struct Reset<'a, T: 'a> {
             key: &'a __impl::KeyInner<T>,
             val: *mut T,
         }
-        #[unsafe_destructor]
-        impl<'a, T> Drop for Reset<'a, T> {
+                impl<'a, T> Drop for Reset<'a, T> {
             fn drop(&mut self) {
                 unsafe { self.key.set(self.val) }
             }
diff --git a/src/libsyntax/diagnostics/metadata.rs b/src/libsyntax/diagnostics/metadata.rs
new file mode 100644 (file)
index 0000000..6cb4f70
--- /dev/null
@@ -0,0 +1,155 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! This module contains utilities for outputting metadata for diagnostic errors.
+//!
+//! Each set of errors is mapped to a metadata file by a name, which is
+//! currently always a crate name.
+
+use std::collections::BTreeMap;
+use std::env;
+use std::path::PathBuf;
+use std::fs::{read_dir, create_dir_all, OpenOptions, File};
+use std::io::{Read, Write};
+use std::error::Error;
+use rustc_serialize::json::{self, as_json};
+
+use codemap::Span;
+use ext::base::ExtCtxt;
+use diagnostics::plugin::{ErrorMap, ErrorInfo};
+
+pub use self::Uniqueness::*;
+
+// Default metadata directory to use for extended error JSON.
+const ERROR_METADATA_DIR_DEFAULT: &'static str = "tmp/extended-errors";
+
+// The name of the environment variable that sets the metadata dir.
+const ERROR_METADATA_VAR: &'static str = "ERROR_METADATA_DIR";
+
+/// JSON encodable/decodable version of `ErrorInfo`.
+#[derive(PartialEq, RustcDecodable, RustcEncodable)]
+pub struct ErrorMetadata {
+    pub description: Option<String>,
+    pub use_site: Option<ErrorLocation>
+}
+
+/// Mapping from error codes to metadata that can be (de)serialized.
+pub type ErrorMetadataMap = BTreeMap<String, ErrorMetadata>;
+
+/// JSON encodable error location type with filename and line number.
+#[derive(PartialEq, RustcDecodable, RustcEncodable)]
+pub struct ErrorLocation {
+    pub filename: String,
+    pub line: usize
+}
+
+impl ErrorLocation {
+    /// Create an error location from a span.
+    pub fn from_span(ecx: &ExtCtxt, sp: Span) -> ErrorLocation {
+        let loc = ecx.codemap().lookup_char_pos_adj(sp.lo);
+        ErrorLocation {
+            filename: loc.filename,
+            line: loc.line
+        }
+    }
+}
+
+/// Type for describing the uniqueness of a set of error codes, as returned by `check_uniqueness`.
+pub enum Uniqueness {
+    /// All errors in the set checked are unique according to the metadata files checked.
+    Unique,
+    /// One or more errors in the set occur in another metadata file.
+    /// This variant contains the first duplicate error code followed by the name
+    /// of the metadata file where the duplicate appears.
+    Duplicate(String, String)
+}
+
+/// Get the directory where metadata files should be stored.
+pub fn get_metadata_dir() -> PathBuf {
+    match env::var(ERROR_METADATA_VAR) {
+        Ok(v) => From::from(v),
+        Err(_) => From::from(ERROR_METADATA_DIR_DEFAULT)
+    }
+}
+
+/// Get the path where error metadata for the set named by `name` should be stored.
+fn get_metadata_path(name: &str) -> PathBuf {
+    get_metadata_dir().join(format!("{}.json", name))
+}
+
+/// Check that the errors in `err_map` aren't present in any metadata files in the
+/// metadata directory except the metadata file corresponding to `name`.
+pub fn check_uniqueness(name: &str, err_map: &ErrorMap) -> Result<Uniqueness, Box<Error>> {
+    let metadata_dir = get_metadata_dir();
+    let metadata_path = get_metadata_path(name);
+
+    // Create the error directory if it does not exist.
+    try!(create_dir_all(&metadata_dir));
+
+    // Check each file in the metadata directory.
+    for entry in try!(read_dir(&metadata_dir)) {
+        let path = try!(entry).path();
+
+        // Skip any existing file for this set.
+        if path == metadata_path {
+            continue;
+        }
+
+        // Read the metadata file into a string.
+        let mut metadata_str = String::new();
+        try!(
+            File::open(&path).and_then(|mut f|
+            f.read_to_string(&mut metadata_str))
+        );
+
+        // Parse the JSON contents.
+        let metadata: ErrorMetadataMap = try!(json::decode(&metadata_str));
+
+        // Check for duplicates.
+        for err in err_map.keys() {
+            let err_code = err.as_str();
+            if metadata.contains_key(err_code) {
+                return Ok(Duplicate(
+                    err_code.to_string(),
+                    path.to_string_lossy().into_owned()
+                ));
+            }
+        }
+    }
+
+    Ok(Unique)
+}
+
+/// Write metadata for the errors in `err_map` to disk, to a file corresponding to `name`.
+pub fn output_metadata(ecx: &ExtCtxt, name: &str, err_map: &ErrorMap)
+    -> Result<(), Box<Error>>
+{
+    let metadata_path = get_metadata_path(name);
+
+    // Open the dump file.
+    let mut dump_file = try!(OpenOptions::new()
+        .write(true)
+        .create(true)
+        .open(&metadata_path)
+    );
+
+    // Construct a serializable map.
+    let json_map = err_map.iter().map(|(k, &ErrorInfo { description, use_site })| {
+        let key = k.as_str().to_string();
+        let value = ErrorMetadata {
+            description: description.map(|n| n.as_str().to_string()),
+            use_site: use_site.map(|sp| ErrorLocation::from_span(ecx, sp))
+        };
+        (key, value)
+    }).collect::<ErrorMetadataMap>();
+
+    try!(write!(&mut dump_file, "{}", as_json(&json_map)));
+    Ok(())
+}
index 6de4edafa0bf5cafaadd4457d54aeca6d6093bcd..16841bd90398147b9919e1711c9f72c223deb53f 100644 (file)
@@ -14,6 +14,7 @@
 use ast;
 use ast::{Ident, Name, TokenTree};
 use codemap::Span;
+use diagnostics::metadata::{check_uniqueness, output_metadata, Duplicate};
 use ext::base::{ExtCtxt, MacEager, MacResult};
 use ext::build::AstBuilder;
 use parse::token;
 const MAX_DESCRIPTION_WIDTH: usize = 80;
 
 thread_local! {
-    static REGISTERED_DIAGNOSTICS: RefCell<BTreeMap<Name, Option<Name>>> = {
+    static REGISTERED_DIAGNOSTICS: RefCell<ErrorMap> = {
         RefCell::new(BTreeMap::new())
     }
 }
-thread_local! {
-    static USED_DIAGNOSTICS: RefCell<BTreeMap<Name, Span>> = {
-        RefCell::new(BTreeMap::new())
-    }
+
+/// Error information type.
+pub struct ErrorInfo {
+    pub description: Option<Name>,
+    pub use_site: Option<Span>
 }
 
+/// Mapping from error codes to metadata.
+pub type ErrorMap = BTreeMap<Name, ErrorInfo>;
+
 fn with_registered_diagnostics<T, F>(f: F) -> T where
-    F: FnOnce(&mut BTreeMap<Name, Option<Name>>) -> T,
+    F: FnOnce(&mut ErrorMap) -> T,
 {
     REGISTERED_DIAGNOSTICS.with(move |slot| {
         f(&mut *slot.borrow_mut())
     })
 }
 
-fn with_used_diagnostics<T, F>(f: F) -> T where
-    F: FnOnce(&mut BTreeMap<Name, Span>) -> T,
-{
-    USED_DIAGNOSTICS.with(move |slot| {
-        f(&mut *slot.borrow_mut())
-    })
-}
-
 pub fn expand_diagnostic_used<'cx>(ecx: &'cx mut ExtCtxt,
                                    span: Span,
                                    token_tree: &[TokenTree])
@@ -58,23 +55,26 @@ pub fn expand_diagnostic_used<'cx>(ecx: &'cx mut ExtCtxt,
         (1, Some(&ast::TtToken(_, token::Ident(code, _)))) => code,
         _ => unreachable!()
     };
-    with_used_diagnostics(|diagnostics| {
-        match diagnostics.insert(code.name, span) {
-            Some(previous_span) => {
+
+    with_registered_diagnostics(|diagnostics| {
+        match diagnostics.get_mut(&code.name) {
+            // Previously used errors.
+            Some(&mut ErrorInfo { description: _, use_site: Some(previous_span) }) => {
                 ecx.span_warn(span, &format!(
                     "diagnostic code {} already used", &token::get_ident(code)
                 ));
                 ecx.span_note(previous_span, "previous invocation");
-            },
-            None => ()
-        }
-        ()
-    });
-    with_registered_diagnostics(|diagnostics| {
-        if !diagnostics.contains_key(&code.name) {
-            ecx.span_err(span, &format!(
-                "used diagnostic code {} not registered", &token::get_ident(code)
-            ));
+            }
+            // Newly used errors.
+            Some(ref mut info) => {
+                info.use_site = Some(span);
+            }
+            // Unregistered errors.
+            None => {
+                ecx.span_err(span, &format!(
+                    "used diagnostic code {} not registered", &token::get_ident(code)
+                ));
+            }
         }
     });
     MacEager::expr(ecx.expr_tuple(span, Vec::new()))
@@ -116,10 +116,14 @@ pub fn expand_register_diagnostic<'cx>(ecx: &'cx mut ExtCtxt,
                 token::get_ident(*code), MAX_DESCRIPTION_WIDTH
             ));
         }
-        raw_msg
     });
+    // Add the error to the map.
     with_registered_diagnostics(|diagnostics| {
-        if diagnostics.insert(code.name, description).is_some() {
+        let info = ErrorInfo {
+            description: description,
+            use_site: None
+        };
+        if diagnostics.insert(code.name, info).is_some() {
             ecx.span_err(span, &format!(
                 "diagnostic code {} already registered", &token::get_ident(*code)
             ));
@@ -143,19 +147,43 @@ pub fn expand_build_diagnostic_array<'cx>(ecx: &'cx mut ExtCtxt,
                                           span: Span,
                                           token_tree: &[TokenTree])
                                           -> Box<MacResult+'cx> {
-    let name = match (token_tree.len(), token_tree.get(0)) {
-        (1, Some(&ast::TtToken(_, token::Ident(ref name, _)))) => name,
+    assert_eq!(token_tree.len(), 3);
+    let (crate_name, name) = match (&token_tree[0], &token_tree[2]) {
+        (
+            // Crate name.
+            &ast::TtToken(_, token::Ident(ref crate_name, _)),
+            // DIAGNOSTICS ident.
+            &ast::TtToken(_, token::Ident(ref name, _))
+        ) => (crate_name.as_str(), name),
         _ => unreachable!()
     };
 
+    // Check uniqueness of errors and output metadata.
+    with_registered_diagnostics(|diagnostics| {
+        match check_uniqueness(crate_name, &*diagnostics) {
+            Ok(Duplicate(err, location)) => {
+                ecx.span_err(span, &format!(
+                    "error {} from `{}' also found in `{}'",
+                    err, crate_name, location
+                ));
+            },
+            Ok(_) => (),
+            Err(e) => panic!("{}", e.description())
+        }
+
+        output_metadata(&*ecx, crate_name, &*diagnostics).ok().expect("metadata output error");
+    });
+
+    // Construct the output expression.
     let (count, expr) =
         with_registered_diagnostics(|diagnostics| {
             let descriptions: Vec<P<ast::Expr>> =
-                diagnostics.iter().filter_map(|(code, description)| {
-                    description.map(|description| {
+                diagnostics.iter().filter_map(|(code, info)| {
+                    info.description.map(|description| {
                         ecx.expr_tuple(span, vec![
                             ecx.expr_str(span, token::get_name(*code)),
-                            ecx.expr_str(span, token::get_name(description))])
+                            ecx.expr_str(span, token::get_name(description))
+                        ])
                     })
                 }).collect();
             (descriptions.len(), ecx.expr_vec(span, descriptions))
index 60b1d4797d5212ff19c61eeb2fbd6394d845cbe8..28deb4eec3fac2ec14584ffb42e8c96a38742cab 100644 (file)
 
     ("fundamental", "1.0.0", Active),
 
-    // Deprecate after snapshot
-    // SNAP 5520801
-    ("unsafe_destructor", "1.0.0", Active),
-
     // A temporary feature gate used to enable parser extensions needed
     // to bootstrap fix for #5723.
     ("issue_5723_bootstrap", "1.0.0", Accepted),
@@ -209,8 +205,6 @@ enum Status {
     ("link_args", Normal),
     ("macro_escape", Normal),
 
-    ("unsafe_destructor", Gated("unsafe_destructor",
-                                "`#[unsafe_destructor]` does nothing anymore")),
     ("staged_api", Gated("staged_api",
                          "staged_api is for use by rustc only")),
     ("plugin", Gated("plugin",
index d8beeb6a5503b2e9599de4369d7571536a8cb60e..275400009f5aafa4b32c72acd145b421863bd57b 100644 (file)
        html_favicon_url = "http://www.rust-lang.org/favicon.ico",
        html_root_url = "http://doc.rust-lang.org/nightly/")]
 
+#![feature(associated_consts)]
 #![feature(collections)]
 #![feature(core)]
 #![feature(libc)]
 #![feature(rustc_private)]
 #![feature(staged_api)]
-#![feature(unicode)]
 #![feature(str_char)]
+#![feature(unicode)]
 
 extern crate arena;
 extern crate fmt_macros;
@@ -69,6 +70,7 @@ pub mod diagnostics {
     pub mod macros;
     pub mod plugin;
     pub mod registry;
+    pub mod metadata;
 }
 
 pub mod syntax {
index f76de1f04ce2ce2f5517ad2dd2bac5d349727f35..5f76c21492707c30c985fb28bb6160702f4726f4 100644 (file)
@@ -88,9 +88,9 @@
 
 bitflags! {
     flags Restrictions: u8 {
-        const UNRESTRICTED                  = 0b0000,
-        const RESTRICTION_STMT_EXPR         = 0b0001,
-        const RESTRICTION_NO_STRUCT_LITERAL = 0b0010,
+        const UNRESTRICTED                  = 0,
+        const RESTRICTION_STMT_EXPR         = 1 << 0,
+        const RESTRICTION_NO_STRUCT_LITERAL = 1 << 1,
     }
 }
 
@@ -339,7 +339,7 @@ pub fn new(sess: &'a ParseSess,
             buffer_start: 0,
             buffer_end: 0,
             tokens_consumed: 0,
-            restrictions: UNRESTRICTED,
+            restrictions: Restrictions::UNRESTRICTED,
             quote_depth: 0,
             obsolete_set: HashSet::new(),
             mod_path_stack: Vec::new(),
@@ -2198,7 +2198,10 @@ pub fn parse_bottom_expr(&mut self) -> PResult<P<Expr>> {
                     if self.check(&token::OpenDelim(token::Brace)) {
                         // This is a struct literal, unless we're prohibited
                         // from parsing struct literals here.
-                        if !self.restrictions.contains(RESTRICTION_NO_STRUCT_LITERAL) {
+                        let prohibited = self.restrictions.contains(
+                            Restrictions::RESTRICTION_NO_STRUCT_LITERAL
+                        );
+                        if !prohibited {
                             // It's a struct literal.
                             try!(self.bump());
                             let mut fields = Vec::new();
@@ -2759,7 +2762,7 @@ pub fn parse_assign_expr(&mut self) -> PResult<P<Expr>> {
     }
 
     pub fn parse_assign_expr_with(&mut self, lhs: P<Expr>) -> PResult<P<Expr>> {
-        let restrictions = self.restrictions & RESTRICTION_NO_STRUCT_LITERAL;
+        let restrictions = self.restrictions & Restrictions::RESTRICTION_NO_STRUCT_LITERAL;
         let op_span = self.span;
         match self.token {
           token::Eq => {
@@ -2814,7 +2817,7 @@ fn is_at_start_of_range_notation_rhs(&self) -> bool {
         if self.token.can_begin_expr() {
             // parse `for i in 1.. { }` as infinite loop, not as `for i in (1..{})`.
             if self.token == token::OpenDelim(token::Brace) {
-                return !self.restrictions.contains(RESTRICTION_NO_STRUCT_LITERAL);
+                return !self.restrictions.contains(Restrictions::RESTRICTION_NO_STRUCT_LITERAL);
             }
             true
         } else {
@@ -2828,7 +2831,7 @@ pub fn parse_if_expr(&mut self) -> PResult<P<Expr>> {
             return self.parse_if_let_expr();
         }
         let lo = self.last_span.lo;
-        let cond = try!(self.parse_expr_res(RESTRICTION_NO_STRUCT_LITERAL));
+        let cond = try!(self.parse_expr_res(Restrictions::RESTRICTION_NO_STRUCT_LITERAL));
         let thn = try!(self.parse_block());
         let mut els: Option<P<Expr>> = None;
         let mut hi = thn.span.hi;
@@ -2846,7 +2849,7 @@ pub fn parse_if_let_expr(&mut self) -> PResult<P<Expr>> {
         try!(self.expect_keyword(keywords::Let));
         let pat = try!(self.parse_pat_nopanic());
         try!(self.expect(&token::Eq));
-        let expr = try!(self.parse_expr_res(RESTRICTION_NO_STRUCT_LITERAL));
+        let expr = try!(self.parse_expr_res(Restrictions::RESTRICTION_NO_STRUCT_LITERAL));
         let thn = try!(self.parse_block());
         let (hi, els) = if try!(self.eat_keyword(keywords::Else) ){
             let expr = try!(self.parse_else_expr());
@@ -2905,7 +2908,7 @@ pub fn parse_for_expr(&mut self, opt_ident: Option<ast::Ident>) -> PResult<P<Exp
         let lo = self.last_span.lo;
         let pat = try!(self.parse_pat_nopanic());
         try!(self.expect_keyword(keywords::In));
-        let expr = try!(self.parse_expr_res(RESTRICTION_NO_STRUCT_LITERAL));
+        let expr = try!(self.parse_expr_res(Restrictions::RESTRICTION_NO_STRUCT_LITERAL));
         let loop_block = try!(self.parse_block());
         let hi = self.last_span.hi;
 
@@ -2918,7 +2921,7 @@ pub fn parse_while_expr(&mut self, opt_ident: Option<ast::Ident>) -> PResult<P<E
             return self.parse_while_let_expr(opt_ident);
         }
         let lo = self.last_span.lo;
-        let cond = try!(self.parse_expr_res(RESTRICTION_NO_STRUCT_LITERAL));
+        let cond = try!(self.parse_expr_res(Restrictions::RESTRICTION_NO_STRUCT_LITERAL));
         let body = try!(self.parse_block());
         let hi = body.span.hi;
         return Ok(self.mk_expr(lo, hi, ExprWhile(cond, body, opt_ident)));
@@ -2930,7 +2933,7 @@ pub fn parse_while_let_expr(&mut self, opt_ident: Option<ast::Ident>) -> PResult
         try!(self.expect_keyword(keywords::Let));
         let pat = try!(self.parse_pat_nopanic());
         try!(self.expect(&token::Eq));
-        let expr = try!(self.parse_expr_res(RESTRICTION_NO_STRUCT_LITERAL));
+        let expr = try!(self.parse_expr_res(Restrictions::RESTRICTION_NO_STRUCT_LITERAL));
         let body = try!(self.parse_block());
         let hi = body.span.hi;
         return Ok(self.mk_expr(lo, hi, ExprWhileLet(pat, expr, body, opt_ident)));
@@ -2945,7 +2948,7 @@ pub fn parse_loop_expr(&mut self, opt_ident: Option<ast::Ident>) -> PResult<P<Ex
 
     fn parse_match_expr(&mut self) -> PResult<P<Expr>> {
         let lo = self.last_span.lo;
-        let discriminant = try!(self.parse_expr_res(RESTRICTION_NO_STRUCT_LITERAL));
+        let discriminant = try!(self.parse_expr_res(Restrictions::RESTRICTION_NO_STRUCT_LITERAL));
         try!(self.commit_expr_expecting(&*discriminant, token::OpenDelim(token::Brace)));
         let mut arms: Vec<Arm> = Vec::new();
         while self.token != token::CloseDelim(token::Brace) {
@@ -2966,7 +2969,7 @@ pub fn parse_arm_nopanic(&mut self) -> PResult<Arm> {
             guard = Some(try!(self.parse_expr_nopanic()));
         }
         try!(self.expect(&token::FatArrow));
-        let expr = try!(self.parse_expr_res(RESTRICTION_STMT_EXPR));
+        let expr = try!(self.parse_expr_res(Restrictions::RESTRICTION_STMT_EXPR));
 
         let require_comma =
             !classify::expr_is_simple_block(&*expr)
@@ -2988,7 +2991,7 @@ pub fn parse_arm_nopanic(&mut self) -> PResult<Arm> {
 
     /// Parse an expression
     pub fn parse_expr_nopanic(&mut self) -> PResult<P<Expr>> {
-        return self.parse_expr_res(UNRESTRICTED);
+        return self.parse_expr_res(Restrictions::UNRESTRICTED);
     }
 
     /// Parse an expression, subject to the given restrictions
@@ -3564,7 +3567,7 @@ fn check_expected_item(p: &mut Parser, attrs: &[Attribute]) {
                     }
 
                     // Remainder are line-expr stmts.
-                    let e = try!(self.parse_expr_res(RESTRICTION_STMT_EXPR));
+                    let e = try!(self.parse_expr_res(Restrictions::RESTRICTION_STMT_EXPR));
                     spanned(lo, e.span.hi, StmtExpr(e, ast::DUMMY_NODE_ID))
                 }
             }
@@ -3573,7 +3576,7 @@ fn check_expected_item(p: &mut Parser, attrs: &[Attribute]) {
 
     /// Is this expression a successfully-parsed statement?
     fn expr_is_complete(&mut self, e: &Expr) -> bool {
-        self.restrictions.contains(RESTRICTION_STMT_EXPR) &&
+        self.restrictions.contains(Restrictions::RESTRICTION_STMT_EXPR) &&
             !classify::expr_requires_semi_to_be_stmt(e)
     }
 
index db1a602b404f60028282d84073bb3f7a2206dc98..362439c146912dae5f05ebcd51de749e8d90e22d 100644 (file)
 #include <stdlib.h>
 
 #if !defined(__WIN32__)
-#include <sys/time.h>
-#include <sys/types.h>
 #include <dirent.h>
+#include <pthread.h>
 #include <signal.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/types.h>
 #include <unistd.h>
-#include <pthread.h>
 #else
 #include <windows.h>
 #include <wincrypt.h>
 //include valgrind.h after stdint.h so that uintptr_t is defined for msys2 w64
 #include "valgrind/valgrind.h"
 
-#ifdef __APPLE__
-#if (TARGET_OS_IPHONE)
-extern char **environ;
-#endif
-#endif
-
-#if defined(__FreeBSD__) || defined(__linux__) || defined(__ANDROID__) || \
-    defined(__DragonFly__) || defined(__Bitrig__) || defined(__OpenBSD__)
-extern char **environ;
-#endif
-
-#if defined(__WIN32__)
-char**
-rust_env_pairs() {
-    return 0;
-}
-#else
-char**
-rust_env_pairs() {
-#if defined(__APPLE__) && !(TARGET_OS_IPHONE)
-    char **environ = *_NSGetEnviron();
-#endif
-    return environ;
-}
-#endif
-
+#ifndef _WIN32
 char*
-#if defined(__WIN32__)
-rust_list_dir_val(WIN32_FIND_DATA* entry_ptr) {
-    return entry_ptr->cFileName;
-}
-#else
 rust_list_dir_val(struct dirent* entry_ptr) {
     return entry_ptr->d_name;
 }
+
+int
+rust_dir_get_mode(struct dirent* entry_ptr) {
+#if defined(_DIRENT_HAVE_D_TYPE)
+    switch (entry_ptr->d_type) {
+        case DT_BLK: return S_IFBLK;
+        case DT_CHR: return S_IFCHR;
+        case DT_FIFO: return S_IFIFO;
+        case DT_LNK: return S_IFLNK;
+        case DT_REG: return S_IFREG;
+        case DT_SOCK: return S_IFSOCK;
+    }
 #endif
+    return -1;
+}
 
-#ifndef _WIN32
+ino_t
+rust_dir_get_ino(struct dirent* entry_ptr) {
+    return entry_ptr->d_ino;
+}
 
 DIR*
 rust_opendir(char *dirname) {
@@ -94,21 +82,6 @@ int
 rust_dirent_t_size() {
     return sizeof(struct dirent);
 }
-
-#else
-
-void
-rust_opendir() {
-}
-
-void
-rust_readdir() {
-}
-
-void
-rust_dirent_t_size() {
-}
-
 #endif
 
 uintptr_t
@@ -173,26 +146,6 @@ rust_valgrind_stack_deregister(unsigned int id) {
   VALGRIND_STACK_DEREGISTER(id);
 }
 
-#if defined(__WIN32__)
-
-void
-rust_unset_sigprocmask() {
-    // empty stub for windows to keep linker happy
-}
-
-#else
-
-void
-rust_unset_sigprocmask() {
-    // this can't be safely converted to rust code because the
-    // representation of sigset_t is platform-dependent
-    sigset_t sset;
-    sigemptyset(&sset);
-    sigprocmask(SIG_SETMASK, &sset, NULL);
-}
-
-#endif
-
 #if defined(__DragonFly__)
 #include <errno.h>
 // In DragonFly __error() is an inline function and as such
index fe0a7b454c17da8740caf1fe6d4765d0f3467fd2..375c5fc746c5b80843b0d03ccb7c2c9aac447264 100644 (file)
@@ -189,8 +189,10 @@ extern "C" LLVMValueRef LLVMBuildAtomicCmpXchg(LLVMBuilderRef B,
                                                failure_order
                                                ));
 }
-extern "C" LLVMValueRef LLVMBuildAtomicFence(LLVMBuilderRef B, AtomicOrdering order) {
-    return wrap(unwrap(B)->CreateFence(order));
+extern "C" LLVMValueRef LLVMBuildAtomicFence(LLVMBuilderRef B,
+                                             AtomicOrdering order,
+                                             SynchronizationScope scope) {
+    return wrap(unwrap(B)->CreateFence(order, scope));
 }
 
 extern "C" void LLVMSetDebug(int Enabled) {
index 5d265478b64da2575ea1e08427f19a8f3ee56f3f..7c4b3866b2a99dbea1e238dc06d6225013fabd1c 100644 (file)
@@ -1,3 +1,13 @@
+S 2015-04-27 857ef6e
+  bitrig-x86_64 d28e2a5f8b478e69720703e751774f5e728a8edd
+  freebsd-x86_64 18925db56f6298cc190d1f41615ab5871de1dda0
+  linux-i386 0bc8cffdce611fb71fd7d3d8e7cdbfaf748a4f16
+  linux-x86_64 94089740e48167c5975c92c139ae9c286764012f
+  macos-i386 54cc35e76497e6e94fddf38d6e40e9d168491ddb
+  macos-x86_64 43a1c1fba0d1dfee4c2ca310d506f8f5f51b3f6f
+  winnt-i386 3db3adf2eaf37075043ec4ee41a5ea9b88810c44
+  winnt-x86_64 82b6eaea67741517ce6d7901ad2a9fd223c3aaf1
+
 S 2015-03-27 5520801
   bitrig-x86_64 55a69b0ae5481ccda54c2fcfc54025a0945c4f57
   freebsd-x86_64 0910bbad35e213f679d0433884fd51398eb3bc8d
index 91a480ac86bdb6d47c680a79c17e7457d824e2dd..d9be03c094c49da670e9070168a411d17c825b82 100644 (file)
@@ -9,6 +9,8 @@
 // except according to those terms.
 
 #![crate_type = "rlib"]
+
+#![allow(unused_variables)]
 #![omit_gdb_pretty_printer_section]
 
 // no-prefer-dynamic
index e85a0a90aff0fce5d1e4abc3d348f78012e39010..e57c6dc718492239192883f86bdf39186cabb0ed 100644 (file)
@@ -11,8 +11,6 @@
 #![crate_name="issue_2526"]
 #![crate_type = "lib"]
 
-#![feature(unsafe_destructor)]
-
 use std::marker;
 
 struct arc_destruct<T: Sync> {
@@ -20,7 +18,6 @@ struct arc_destruct<T: Sync> {
     _marker: marker::PhantomData<T>
 }
 
-#[unsafe_destructor]
 impl<T: Sync> Drop for arc_destruct<T> {
     fn drop(&mut self) {}
 }
diff --git a/src/test/auxiliary/issue24687_lib.rs b/src/test/auxiliary/issue24687_lib.rs
new file mode 100644 (file)
index 0000000..f1624fd
--- /dev/null
@@ -0,0 +1,20 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![crate_type="lib"]
+
+// This is a file that pulls in a separate file as a submodule, where
+// that separate file has many multi-byte characters, to try to
+// encourage the compiler to trip on them.
+
+mod issue24687_mbcs_in_comments;
+
+pub use issue24687_mbcs_in_comments::D;
+
diff --git a/src/test/auxiliary/issue24687_mbcs_in_comments.rs b/src/test/auxiliary/issue24687_mbcs_in_comments.rs
new file mode 100644 (file)
index 0000000..8dc243a
--- /dev/null
@@ -0,0 +1,37 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+use std::fmt;
+
+// This ia file with many multi-byte characters, to try to encourage
+// the compiler to trip on them.  The Drop implementation below will
+// need to have its source location embedded into the debug info for
+// the output file.
+
+// Î±Î±Î±Î±Î±Î±Î±Î±Î±Î±Î±Î±Î±Î±Î±Î±Î±Î±Î±Î±Î±Î±Î±Î±Î±Î±Î±Î±Î±Î±Î±Î±Î±Î±Î±Î±Î±Î±Î±Î±Î±Î±Î±Î±Î±Î±Î±Î±Î±Î±Î±Î±Î±Î±Î±Î±Î±Î±Î±Î±Î±Î±Î±Î±Î±Î±Î±Î±Î±Î±
+// Î²Î²Î²Î²Î²Î²Î²Î²Î²Î²Î²Î²Î²Î²Î²Î²Î²Î²Î²Î²Î²Î²Î²Î²Î²Î²Î²Î²Î²Î²Î²Î²Î²Î²Î²Î²Î²Î²Î²Î²Î²Î²Î²Î²Î²Î²Î²Î²Î²Î²Î²Î²Î²Î²Î²Î²Î²Î²Î²Î²Î²Î²Î²Î²Î²Î²Î²Î²Î²Î²
+// Î³Î³Î³Î³Î³Î³Î³Î³Î³Î³Î³Î³Î³Î³Î³Î³Î³Î³Î³Î³Î³Î³Î³Î³Î³Î³Î³Î³Î³Î³Î³Î³Î³Î³Î³Î³Î³Î³Î³Î³Î³Î³Î³Î³Î³Î³Î³Î³Î³Î³Î³Î³Î³Î³Î³Î³Î³Î³Î³Î³Î³Î³Î³Î³Î³Î³Î³Î³Î³Î³
+// Î´Î´Î´Î´Î´Î´Î´Î´Î´Î´Î´Î´Î´Î´Î´Î´Î´Î´Î´Î´Î´Î´Î´Î´Î´Î´Î´Î´Î´Î´Î´Î´Î´Î´Î´Î´Î´Î´Î´Î´Î´Î´Î´Î´Î´Î´Î´Î´Î´Î´Î´Î´Î´Î´Î´Î´Î´Î´Î´Î´Î´Î´Î´Î´Î´Î´Î´Î´Î´Î´
+// ÎµÎµÎµÎµÎµÎµÎµÎµÎµÎµÎµÎµÎµÎµÎµÎµÎµÎµÎµÎµÎµÎµÎµÎµÎµÎµÎµÎµÎµÎµÎµÎµÎµÎµÎµÎµÎµÎµÎµÎµÎµÎµÎµÎµÎµÎµÎµÎµÎµÎµÎµÎµÎµÎµÎµÎµÎµÎµÎµÎµÎµÎµÎµÎµÎµÎµÎµÎµÎµÎµ
+
+// Î¶Î¶Î¶Î¶Î¶Î¶Î¶Î¶Î¶Î¶Î¶Î¶Î¶Î¶Î¶Î¶Î¶Î¶Î¶Î¶Î¶Î¶Î¶Î¶Î¶Î¶Î¶Î¶Î¶Î¶Î¶Î¶Î¶Î¶Î¶Î¶Î¶Î¶Î¶Î¶Î¶Î¶Î¶Î¶Î¶Î¶Î¶Î¶Î¶Î¶Î¶Î¶Î¶Î¶Î¶Î¶Î¶Î¶Î¶Î¶Î¶Î¶Î¶Î¶Î¶Î¶Î¶Î¶Î¶Î¶
+// Î·Î·Î·Î·Î·Î·Î·Î·Î·Î·Î·Î·Î·Î·Î·Î·Î·Î·Î·Î·Î·Î·Î·Î·Î·Î·Î·Î·Î·Î·Î·Î·Î·Î·Î·Î·Î·Î·Î·Î·Î·Î·Î·Î·Î·Î·Î·Î·Î·Î·Î·Î·Î·Î·Î·Î·Î·Î·Î·Î·Î·Î·Î·Î·Î·Î·Î·Î·Î·Î·
+// Î¸Î¸Î¸Î¸Î¸Î¸Î¸Î¸Î¸Î¸Î¸Î¸Î¸Î¸Î¸Î¸Î¸Î¸Î¸Î¸Î¸Î¸Î¸Î¸Î¸Î¸Î¸Î¸Î¸Î¸Î¸Î¸Î¸Î¸Î¸Î¸Î¸Î¸Î¸Î¸Î¸Î¸Î¸Î¸Î¸Î¸Î¸Î¸Î¸Î¸Î¸Î¸Î¸Î¸Î¸Î¸Î¸Î¸Î¸Î¸Î¸Î¸Î¸Î¸Î¸Î¸Î¸Î¸Î¸Î¸
+// Î¹Î¹Î¹Î¹Î¹Î¹Î¹Î¹Î¹Î¹Î¹Î¹Î¹Î¹Î¹Î¹Î¹Î¹Î¹Î¹Î¹Î¹Î¹Î¹Î¹Î¹Î¹Î¹Î¹Î¹Î¹Î¹Î¹Î¹Î¹Î¹Î¹Î¹Î¹Î¹Î¹Î¹Î¹Î¹Î¹Î¹Î¹Î¹Î¹Î¹Î¹Î¹Î¹Î¹Î¹Î¹Î¹Î¹Î¹Î¹Î¹Î¹Î¹Î¹Î¹Î¹Î¹Î¹Î¹Î¹
+// ÎºÎºÎºÎºÎºÎºÎºÎºÎºÎºÎºÎºÎºÎºÎºÎºÎºÎºÎºÎºÎºÎºÎºÎºÎºÎºÎºÎºÎºÎºÎºÎºÎºÎºÎºÎºÎºÎºÎºÎºÎºÎºÎºÎºÎºÎºÎºÎºÎºÎºÎºÎºÎºÎºÎºÎºÎºÎºÎºÎºÎºÎºÎºÎºÎºÎºÎºÎºÎºÎº
+
+pub struct D<X:fmt::Debug>(pub X);
+
+impl<X:fmt::Debug> Drop for D<X> {
+    fn drop(&mut self) {
+        // Î»Î»Î»Î»Î»Î»Î»Î»Î»Î»Î»Î»Î»Î»Î»Î»Î»Î»Î»Î»Î»Î»Î»Î»Î»Î»Î»Î»Î»Î»Î»Î»Î»Î»Î»Î»Î»Î»Î»Î»Î»Î»Î»Î»Î»Î»Î»Î»Î»Î»Î»Î»Î»Î»Î»Î»Î»Î»Î»Î»
+        println!("Dropping D({:?})", self.0);
+    }
+}
index 6cc2d427c25dcc6a41cdb3362e94147ad42a483c..9196a156ad1c9e2835c97082420b6f7536785f8d 100644 (file)
 
 #![feature(std_misc)]
 
+// We're testing linkage visibility; the compiler warns us, but we want to
+// do the runtime check that these functions aren't exported.
+#![allow(private_no_mangle_fns)]
+
 use std::dynamic_lib::DynamicLibrary;
 
 #[no_mangle]
@@ -25,6 +29,7 @@ fn bar2() {
 #[no_mangle]
 fn bar() { }
 
+#[allow(dead_code)]
 #[no_mangle]
 fn baz() { }
 
index efbb5dfb5491ebe855be1249909590a2031c055a..81a6fb8ff6debbe064207a60c21b646d9973d258 100644 (file)
@@ -101,8 +101,8 @@ fn get(&self, x: f32, y: f32) -> f32 {
 
 fn main() {
     let symbols = [' ', 'â–‘', 'â–’', 'â–“', 'â–ˆ', 'â–ˆ'];
-    let mut pixels = [0f32; 256*256];
-    let n2d = Noise2DContext::new();
+    let mut pixels = Box::new([0f32; 256*256]);
+    let n2d = Box::new(Noise2DContext::new());
 
     for _ in 0..100 {
         for y in 0..256 {
index b777b25243ba6e8b1b48a778e03b640913982721..17e8f88c5689d8fa71fbad4c48e87d0f10f607b5 100644 (file)
@@ -8,13 +8,11 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// ignore-android: FIXME(#10393)
+// ignore-android: FIXME(#10393) hangs without output
 // ignore-pretty very bad with line comments
 
 // multi tasking k-nucleotide
 
-#![allow(bad_style)]
-
 use std::ascii::AsciiExt;
 use std::cmp::Ordering::{self, Less, Greater, Equal};
 use std::collections::HashMap;
@@ -47,7 +45,7 @@ fn pct(xx: usize, yy: usize) -> f64 {
    }
 
    // sort by key, then by value
-   fn sortKV(mut orig: Vec<(Vec<u8> ,f64)> ) -> Vec<(Vec<u8> ,f64)> {
+   fn sort_kv(mut orig: Vec<(Vec<u8> ,f64)> ) -> Vec<(Vec<u8> ,f64)> {
         orig.sort_by(|&(ref a, _), &(ref b, _)| a.cmp(b));
         orig.sort_by(|&(_, a), &(_, b)| f64_cmp(b, a));
         orig
@@ -60,7 +58,7 @@ fn sortKV(mut orig: Vec<(Vec<u8> ,f64)> ) -> Vec<(Vec<u8> ,f64)> {
       pairs.push(((*key).clone(), pct(val, total)));
    }
 
-   let pairs_sorted = sortKV(pairs);
+   let pairs_sorted = sort_kv(pairs);
 
    let mut buffer = String::new();
    for &(ref k, v) in &pairs_sorted {
index c4af33da50c9462811ca99b143269b0454d5c877..87b9869051cadff2160cf8dc350d9bbc1786f128 100644 (file)
@@ -38,7 +38,7 @@
 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 // OF THE POSSIBILITY OF SUCH DAMAGE.
 
-// ignore-android see #10393 #13206
+// ignore-android: FIXME(#10393) hangs without output
 
 #![feature(box_syntax, std_misc, collections)]
 
index 7c9f33678a39c924fdabdd7849fe75a1bf865f49..523f1549eee900e5927932c63bfd627c68ba0a7e 100644 (file)
@@ -38,7 +38,7 @@
 // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 // OF THE POSSIBILITY OF SUCH DAMAGE.
 
-// ignore-android see #10393 #13206
+// ignore-android: FIXME(#10393) hangs without output
 
 #![feature(libc, scoped)]
 
 use std::thread;
 
 struct Tables {
-    table8: [u8; 1 << 8],
-    table16: [u16; 1 << 16]
+    table8: Box<[u8; 1 << 8]>,
+    table16: Box<[u16; 1 << 16]>,
 }
 
 impl Tables {
     fn new() -> Tables {
-        let mut table8 = [0;1 << 8];
+        let mut table8 = Box::new([0;1 << 8]);
         for (i, v) in table8.iter_mut().enumerate() {
             *v = Tables::computed_cpl8(i as u8);
         }
-        let mut table16 = [0;1 << 16];
+        let mut table16 = Box::new([0;1 << 16]);
         for (i, v) in table16.iter_mut().enumerate() {
             *v = (table8[i & 255] as u16) << 8 |
                  table8[i >> 8]  as u16;
@@ -205,7 +205,7 @@ fn parallel<I: Iterator, F>(iter: I, ref f: F)
 
 fn main() {
     let mut data = Vec::with_capacity(1024 * 1024);
-    io::stdin().read_to_end(&mut data);
+    io::stdin().read_to_end(&mut data).unwrap();
     let tables = &Tables::new();
     parallel(mut_dna_seqs(&mut data), |seq| reverse_complement(seq, tables));
     io::stdout().write_all(&data).unwrap();
index 9eba2c3639039511fec82c445dd02ec900155e5b..e091dbfb00e4b4195e293c86b74df74afa482a8b 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(unsafe_destructor, box_syntax, std_misc, collections)]
+#![feature(box_syntax, std_misc, collections)]
 
 use std::env;
 use std::thread;
@@ -54,7 +54,6 @@ struct r {
   _l: Box<nillist>,
 }
 
-#[unsafe_destructor]
 impl Drop for r {
     fn drop(&mut self) {}
 }
index 99ac86722693ab90716e32784ca9dbfb8007c7f4..309e286f48e509487cb004e3888a5ed87aee6f1a 100644 (file)
@@ -8,13 +8,10 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(unsafe_destructor)]
-
 struct defer<'a> {
     x: &'a [&'a str],
 }
 
-#[unsafe_destructor]
 impl<'a> Drop for defer<'a> {
     fn drop(&mut self) {
         unsafe {
index 40d992fe21f207abe22984110f44735c61fcced7..f3c3f31e4afc629e8cf29c52bd300232abd6e21c 100644 (file)
@@ -13,8 +13,6 @@
 //
 // (Compare against compile-fail/dropck_vec_cycle_checked.rs)
 
-#![feature(unsafe_destructor)]
-
 use std::cell::Cell;
 use id::Id;
 
@@ -69,7 +67,6 @@ struct CheckId<T:HasId> {
 #[allow(non_snake_case)]
 fn CheckId<T:HasId>(t: T) -> CheckId<T> { CheckId{ v: t } }
 
-#[unsafe_destructor]
 impl<T:HasId> Drop for CheckId<T> {
     fn drop(&mut self) {
         assert!(self.v.count() > 0);
index b9df71322ad83a240b2d95ae5a0a2dd6cdf10e0a..5db23721259a05e1365330cd973f43013f349795 100644 (file)
@@ -23,8 +23,6 @@
 //  `'a` in `&'a D<'a>` cannot be satisfied when `D<'a>` implements
 //  `Drop`.)
 
-#![feature(unsafe_destructor)]
-
 use std::cell::Cell;
 
 struct D<'a> {
@@ -36,7 +34,6 @@ impl<'a> D<'a> {
     fn new(name: String) -> D<'a> { D { name: name, p: Cell::new(None) } }
 }
 
-#[unsafe_destructor]
 impl<'a> Drop for D<'a> {
     fn drop(&mut self) {
         println!("dropping {} whose sibling is {:?}",
index 9488882ca94a51421a5bf04d89d7ab0d5eb35df6..10bfe70640ca820ae84c011c8e1b6f066764f087 100644 (file)
@@ -17,7 +17,6 @@
 //  for the error message we see here.)
 
 #![allow(unstable)]
-#![feature(unsafe_destructor)]
 
 extern crate arena;
 
@@ -76,7 +75,6 @@ struct CheckId<T:HasId> {
 #[allow(non_snake_case)]
 fn CheckId<T:HasId>(t: T) -> CheckId<T> { CheckId{ v: t } }
 
-#[unsafe_destructor]
 impl<T:HasId> Drop for CheckId<T> {
     fn drop(&mut self) {
         assert!(self.v.count() > 0);
index 64d77e97fa7f6f2f49def9a47c6a67bf20b54c9f..7a204e6143eeff0556150603406174155f746756 100644 (file)
@@ -20,7 +20,6 @@
 // this was reduced to better understand its error message.)
 
 #![allow(unstable)]
-#![feature(unsafe_destructor)]
 
 extern crate arena;
 
@@ -35,7 +34,6 @@ struct CheckId<T:HasId> { v: T }
 // interface to CheckId does not (and cannot) know that, and therefore
 // when encountering the a value V of type CheckId<S>, we must
 // conservatively force the type S to strictly outlive V.
-#[unsafe_destructor]
 impl<T:HasId> Drop for CheckId<T> {
     fn drop(&mut self) {
         assert!(self.v.count() > 0);
index 9d92552244f28e651f83b1d03a639f68ce11cd32..53a14fd8fac926a5d7069b79c954b52711f2a386 100644 (file)
@@ -12,8 +12,6 @@
 //
 // (Compare against compile-fail/dropck_arr_cycle_checked.rs)
 
-#![feature(unsafe_destructor)]
-
 use std::cell::Cell;
 use id::Id;
 
@@ -68,7 +66,6 @@ struct CheckId<T:HasId> {
 #[allow(non_snake_case)]
 fn CheckId<T:HasId>(t: T) -> CheckId<T> { CheckId{ v: t } }
 
-#[unsafe_destructor]
 impl<T:HasId> Drop for CheckId<T> {
     fn drop(&mut self) {
         assert!(self.v.count() > 0);
index 460c396750ff0b6fda97337e1d46c12824a46822..b4cb2469659788c7f16bb2f9e5af54bd2a754310 100644 (file)
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(unsafe_destructor)]
-
 // issue #20126
 
 #[derive(Copy, Clone)] //~ ERROR the trait `Copy` may not be implemented
@@ -22,7 +20,6 @@ fn drop(&mut self) {}
 #[derive(Copy, Clone)] //~ ERROR the trait `Copy` may not be implemented
 struct Bar<T>(::std::marker::PhantomData<T>);
 
-#[unsafe_destructor]
 impl<T> Drop for Bar<T> {
     fn drop(&mut self) {}
 }
diff --git a/src/test/compile-fail/gated-unsafe-destructor.rs b/src/test/compile-fail/gated-unsafe-destructor.rs
deleted file mode 100644 (file)
index 9dd1e22..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// Test that `#[unsafe_destructor]` attribute is gated by `unsafe_destructor`
-// feature gate.
-//
-// (This test can be removed entirely when we remove the
-// `unsafe_destructor` feature itself.)
-
-struct D<'a>(&'a u32);
-
-#[unsafe_destructor]
-//~^ ERROR `#[unsafe_destructor]` does nothing anymore
-impl<'a> Drop for D<'a> {
-    fn drop(&mut self) { }
-}
-
-pub fn main() { }
diff --git a/src/test/compile-fail/issue-24895-copy-clone-dropck.rs b/src/test/compile-fail/issue-24895-copy-clone-dropck.rs
new file mode 100644 (file)
index 0000000..2883511
--- /dev/null
@@ -0,0 +1,38 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Check that one cannot subvert Drop Check rule via a user-defined
+// Clone implementation.
+
+#![allow(unused_variables, unused_assignments)]
+
+struct D<T:Copy>(T, &'static str);
+
+#[derive(Copy)]
+struct S<'a>(&'a D<i32>, &'static str);
+impl<'a> Clone for S<'a> {
+    fn clone(&self) -> S<'a> {
+        println!("cloning `S(_, {})` and thus accessing: {}", self.1, (self.0).0);
+        S(self.0, self.1)
+    }
+}
+
+impl<T:Copy> Drop for D<T> {
+    fn drop(&mut self) {
+        println!("calling Drop for {}", self.1);
+        let _call = self.0.clone();
+    }
+}
+
+fn main() {
+    let (d2, d1);
+    d1 = D(34, "d1");
+    d2 = D(S(&d1, "inner"), "d2"); //~ ERROR `d1` does not live long enough
+}
diff --git a/src/test/compile-fail/lint-no-drop-on-repr-extern.rs b/src/test/compile-fail/lint-no-drop-on-repr-extern.rs
new file mode 100644 (file)
index 0000000..2df57b0
--- /dev/null
@@ -0,0 +1,59 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Check we reject structs that mix a `Drop` impl with `#[repr(C)]`.
+//
+// As a special case, also check that we do not warn on such structs
+// if they also are declared with `#[unsafe_no_drop_flag]`
+
+#![feature(unsafe_no_drop_flag)]
+#![deny(drop_with_repr_extern)]
+
+#[repr(C)] struct As { x: Box<i8> }
+#[repr(C)] enum Ae { Ae(Box<i8>), _None }
+
+struct Bs { x: Box<i8> }
+enum Be { Be(Box<i8>), _None }
+
+#[repr(C)] struct Cs { x: Box<i8> }
+//~^ NOTE the `#[repr(C)]` attribute is attached here
+
+impl Drop for Cs { fn drop(&mut self) { } }
+//~^ ERROR implementing Drop adds hidden state to types, possibly conflicting with `#[repr(C)]`
+
+#[repr(C)] enum Ce { Ce(Box<i8>), _None }
+//~^ NOTE the `#[repr(C)]` attribute is attached here
+
+impl Drop for Ce { fn drop(&mut self) { } }
+//~^ ERROR implementing Drop adds hidden state to types, possibly conflicting with `#[repr(C)]`
+
+#[unsafe_no_drop_flag]
+#[repr(C)] struct Ds { x: Box<i8> }
+
+impl Drop for Ds { fn drop(&mut self) { } }
+
+#[unsafe_no_drop_flag]
+#[repr(C)] enum De { De(Box<i8>), _None }
+
+impl Drop for De { fn drop(&mut self) { } }
+
+fn main() {
+    let a = As { x: Box::new(3) };
+    let b = Bs { x: Box::new(3) };
+    let c = Cs { x: Box::new(3) };
+    let d = Ds { x: Box::new(3) };
+
+    println!("{:?}", (*a.x, *b.x, *c.x, *d.x));
+
+    let _a = Ae::Ae(Box::new(3));
+    let _b = Be::Be(Box::new(3));
+    let _c = Ce::Ce(Box::new(3));
+    let _d = De::De(Box::new(3));
+}
index 5ebc386109a8bcdf3ce589bf37e840dc0b8757eb..b80d15bb6f3c68d322f6aa9238ed7a052c40470d 100644 (file)
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(unsafe_destructor)]
-
 use std::thread;
 use std::rc::Rc;
 
@@ -22,8 +20,7 @@ struct foo {
       _x: Port<()>,
     }
 
-    #[unsafe_destructor]
-    impl Drop for foo {
+        impl Drop for foo {
         fn drop(&mut self) {}
     }
 
index 30264c9f218a18aed7e7665e46da61df077ab37c..1e189528f18c7714b3b42d334bb929b3894af742 100644 (file)
@@ -11,8 +11,6 @@
 // Issue 8142: Test that Drop impls cannot be specialized beyond the
 // predicates attached to the struct/enum definition itself.
 
-#![feature(unsafe_destructor)]
-
 trait Bound { fn foo(&self) { } }
 struct K<'l1,'l2> { x: &'l1 i8, y: &'l2 u8 }
 struct L<'l1,'l2> { x: &'l1 i8, y: &'l2 u8 }
@@ -28,51 +26,39 @@ struct T<'t,Ts:'t> { x: &'t Ts }
 struct V<Tva, Tvb> { x: *const Tva, y: *const Tvb }
 struct W<'l1, 'l2> { x: &'l1 i8, y: &'l2 u8 }
 
-#[unsafe_destructor]
 impl<'al,'adds_bnd:'al> Drop for K<'al,'adds_bnd> {                        // REJECT
     //~^ ERROR The requirement `'adds_bnd : 'al` is added only by the Drop impl.
     fn drop(&mut self) { } }
 
-#[unsafe_destructor]
 impl<'al,'adds_bnd>     Drop for L<'al,'adds_bnd> where 'adds_bnd:'al {    // REJECT
     //~^ ERROR The requirement `'adds_bnd : 'al` is added only by the Drop impl.
     fn drop(&mut self) { } }
 
-#[unsafe_destructor]
 impl<'ml>               Drop for M<'ml>         { fn drop(&mut self) { } } // ACCEPT
 
-#[unsafe_destructor]
 impl                    Drop for N<'static>     { fn drop(&mut self) { } } // REJECT
 //~^ ERROR Implementations of Drop cannot be specialized
 
-#[unsafe_destructor]
 impl<Cok_nobound> Drop for O<Cok_nobound> { fn drop(&mut self) { } } // ACCEPT
 
-#[unsafe_destructor]
 impl              Drop for P<i8>          { fn drop(&mut self) { } } // REJECT
 //~^ ERROR Implementations of Drop cannot be specialized
 
-#[unsafe_destructor]
 impl<Adds_bnd:Bound> Drop for Q<Adds_bnd> { fn drop(&mut self) { } } // REJECT
 //~^ ERROR The requirement `Adds_bnd : Bound` is added only by the Drop impl.
 
-#[unsafe_destructor]
 impl<'rbnd,Adds_rbnd:'rbnd> Drop for R<Adds_rbnd> { fn drop(&mut self) { } } // REJECT
 //~^ ERROR The requirement `Adds_rbnd : 'rbnd` is added only by the Drop impl.
 
-#[unsafe_destructor]
 impl<Bs:Bound>    Drop for S<Bs>          { fn drop(&mut self) { } } // ACCEPT
 
-#[unsafe_destructor]
 impl<'t,Bt:'t>    Drop for T<'t,Bt>       { fn drop(&mut self) { } } // ACCEPT
 
 impl              Drop for U              { fn drop(&mut self) { } } // ACCEPT
 
-#[unsafe_destructor]
 impl<One>         Drop for V<One,One>     { fn drop(&mut self) { } } // REJECT
 //~^ERROR Implementations of Drop cannot be specialized
 
-#[unsafe_destructor]
 impl<'lw>         Drop for W<'lw,'lw>     { fn drop(&mut self) { } } // REJECT
 //~^ERROR Implementations of Drop cannot be specialized
 
index 938abbf2c2018952a44739b07b3a7c027c866598..6aa0834cb27df563544bc548788f737454940542 100644 (file)
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(unsafe_destructor)]
-
 use std::cell::Cell;
 
 #[derive(Debug)]
@@ -17,7 +15,6 @@ struct r<'a> {
   i: &'a Cell<isize>,
 }
 
-#[unsafe_destructor]
 impl<'a> Drop for r<'a> {
     fn drop(&mut self) {
         unsafe {
index 44a3f716e3eea4a3602cc43a5d8928d8faa9a71e..c30aa7b817bf4fcfce1f7d262a6f7cd21db0dcf0 100644 (file)
@@ -23,8 +23,6 @@
 // conditions above to be satisfied, meaning that if the dropck is
 // sound, it should reject this code.
 
-#![feature(unsafe_destructor)]
-
 use std::cell::Cell;
 use id::Id;
 
@@ -91,7 +89,6 @@ struct CheckId<T:HasId> {
 #[allow(non_snake_case)]
 fn CheckId<T:HasId>(t: T) -> CheckId<T> { CheckId{ v: t } }
 
-#[unsafe_destructor]
 impl<T:HasId> Drop for CheckId<T> {
     fn drop(&mut self) {
         assert!(self.v.count() > 0);
index f150e84b9fdfecb5ded086e2d7ecc2b432b57f3d..5fc580755043d426185fd02a7b656132184e325b 100644 (file)
@@ -8,13 +8,11 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// ignore-android: FIXME(#10381)
 // min-lldb-version: 310
 
 // compile-flags:-g
 
-#![allow(unused_variables)]
-#![allow(dead_code)]
+#![allow(dead_code, unused_variables)]
 #![omit_gdb_pretty_printer_section]
 #![feature(std_misc, core)]
 
index 487c69a85d6acb985756545ec589ab5c7f6793df..785778e62f6eadafbe94c2e77142691450faadc3 100644 (file)
@@ -8,13 +8,11 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// ignore-android: FIXME(#10381)
 // min-lldb-version: 310
 
 // compile-flags:-g
 
-#![allow(unused_variables)]
-#![allow(dead_code)]
+#![allow(dead_code, unused_variables)]
 #![omit_gdb_pretty_printer_section]
 
 // This test makes sure that the compiler doesn't crash when trying to assign
index 85b4e9babebd276fb46ca8b32406b60e11da21bc..ce6ef080c1f11955850346b3daf8a960cabca0b5 100644 (file)
@@ -10,7 +10,6 @@
 
 #![omit_gdb_pretty_printer_section]
 
-// ignore-android: FIXME(#10381)
 // min-lldb-version: 310
 
 // aux-build:cross_crate_spans.rs
@@ -21,7 +20,7 @@
 
 // === GDB TESTS ===================================================================================
 
-// gdb-command:break cross_crate_spans.rs:21
+// gdb-command:break cross_crate_spans.rs:23
 // gdb-command:run
 
 // gdb-command:print result
@@ -44,7 +43,7 @@
 
 // === LLDB TESTS ==================================================================================
 
-// lldb-command:b cross_crate_spans.rs:21
+// lldb-command:b cross_crate_spans.rs:23
 // lldb-command:run
 
 // lldb-command:print result
index 7e959a1e920126bb08e647eaaa45a64a2558e62d..d9cca5eb315177cdae7bfde277d015a4c92fdda1 100644 (file)
 // lldb-check:[...]$31 = 45
 // lldb-command:continue
 
-#![allow(unused_variables)]
+#![allow(dead_code, unused_assignments, unused_variables)]
 #![omit_gdb_pretty_printer_section]
 
 #[no_stack_check]
index 1da9a06b0eea4cea1b3300c13a032168ffa122f0..c42f7f19839fdce2c316b4fd3b2f7df8aeed5dfb 100644 (file)
@@ -35,6 +35,8 @@
 // gdb-command: print none
 // gdb-check:$6 = None
 
+#![allow(unused_variables)]
+
 fn main() {
 
     // &[]
index 0d8b42a9f767214c19871ef683ca0e5143002a5a..fa15e31450f8b114fe264e2f4b355f7395f66e35 100644 (file)
@@ -37,6 +37,8 @@
 // gdb-command: print c_style_enum3
 // gdb-check:$5 = CStyleEnumVar3
 
+#![allow(dead_code, unused_variables)]
+
 struct RegularStruct {
     the_first_field: isize,
     the_second_field: f64,
index 81af9c213a34357cd2b28829ea88febfaa2a7e8b..56a973fa59f668398eff78903937e9d810046630 100644 (file)
@@ -76,6 +76,8 @@
 // gdb-command: print none_check2
 // gdb-check:$18 = None
 
+#![allow(dead_code, unused_variables)]
+
 use self::CStyleEnum::{CStyleEnumVar1, CStyleEnumVar2, CStyleEnumVar3};
 use self::MixedEnum::{MixedEnumCStyleVar, MixedEnumTupleVar, MixedEnumStructVar};
 use self::NestedEnum::{NestedVariant1, NestedVariant2};
index e7ee9e2ccf8188ca431ba29c029955cc6fb81351..4eae074120233fd5e121f8e9c972e031edb6f59e 100644 (file)
@@ -10,7 +10,7 @@
 
 // ignore-tidy-linelength
 // ignore-lldb
-// ignore-android: FIXME(#10381)
+// ignore-android: FIXME(#24958)
 
 // compile-flags:-g
 
@@ -21,7 +21,7 @@
 // gdb-check:type = struct Struct1
 
 // gdb-command:whatis generic_struct1
-// gdb-check:type = struct GenericStruct<type_names::Mod1::Struct2, type_names::Mod1::Mod2::Struct3>
+// gdb-check:type = struct GenericStruct<type_names::mod1::Struct2, type_names::mod1::mod2::Struct3>
 
 // gdb-command:whatis generic_struct2
 // gdb-check:type = struct GenericStruct<type_names::Struct1, extern "fastcall" fn(isize) -> usize>
@@ -41,7 +41,7 @@
 // gdb-check:type = union Enum2
 
 // gdb-command:whatis generic_enum_1
-// gdb-check:type = union Enum3<type_names::Mod1::Struct2>
+// gdb-check:type = union Enum3<type_names::mod1::Struct2>
 
 // gdb-command:whatis generic_enum_2
 // gdb-check:type = union Enum3<type_names::Struct1>
 
 // TUPLES
 // gdb-command:whatis tuple1
-// gdb-check:type = struct (u32, type_names::Struct1, type_names::Mod1::Mod2::Enum3<type_names::Mod1::Struct2>)
+// gdb-check:type = struct (u32, type_names::Struct1, type_names::mod1::mod2::Enum3<type_names::mod1::Struct2>)
 
 // gdb-command:whatis tuple2
-// gdb-check:type = struct ((type_names::Struct1, type_names::Mod1::Mod2::Struct3), type_names::Mod1::Enum2, char)
+// gdb-check:type = struct ((type_names::Struct1, type_names::mod1::mod2::Struct3), type_names::mod1::Enum2, char)
 
 
 // BOX
@@ -60,7 +60,7 @@
 // gdb-check:type = struct (Box<f32>, i32)
 
 // gdb-command:whatis box2
-// gdb-check:type = struct (Box<type_names::Mod1::Mod2::Enum3<f32>>, i32)
+// gdb-check:type = struct (Box<type_names::mod1::mod2::Enum3<f32>>, i32)
 
 
 // REFERENCES
@@ -74,7 +74,7 @@
 // gdb-check:type = struct (&mut type_names::Struct1, i32)
 
 // gdb-command:whatis mut_ref2
-// gdb-check:type = struct (&mut type_names::GenericStruct<type_names::Mod1::Enum2, f64>, i32)
+// gdb-check:type = struct (&mut type_names::GenericStruct<type_names::mod1::Enum2, f64>, i32)
 
 
 // RAW POINTERS
@@ -85,7 +85,7 @@
 // gdb-check:type = struct (*mut isize, isize)
 
 // gdb-command:whatis mut_ptr3
-// gdb-check:type = struct (*mut type_names::Mod1::Mod2::Enum3<type_names::Struct1>, isize)
+// gdb-check:type = struct (*mut type_names::mod1::mod2::Enum3<type_names::Struct1>, isize)
 
 // gdb-command:whatis const_ptr1
 // gdb-check:type = struct (*const type_names::Struct1, isize)
@@ -94,7 +94,7 @@
 // gdb-check:type = struct (*const isize, isize)
 
 // gdb-command:whatis const_ptr3
-// gdb-check:type = struct (*const type_names::Mod1::Mod2::Enum3<type_names::Struct1>, isize)
+// gdb-check:type = struct (*const type_names::mod1::mod2::Enum3<type_names::Struct1>, isize)
 
 
 // VECTORS
 // gdb-check:type = struct &[usize]
 
 // gdb-command:whatis slice2
-// gdb-check:type = struct &[type_names::Mod1::Enum2]
+// gdb-check:type = struct &[type_names::mod1::Enum2]
 
 
 // TRAITS
 // gdb-check:type = struct &mut Trait1
 
 // gdb-command:whatis generic_box_trait
-// gdb-check:type = struct Box<Trait2<i32, type_names::Mod1::Struct2>>
+// gdb-check:type = struct Box<Trait2<i32, type_names::mod1::Struct2>>
 
 // gdb-command:whatis generic_ref_trait
 // gdb-check:type = struct &Trait2<type_names::Struct1, type_names::Struct1>
 
 // gdb-command:whatis generic_mut_ref_trait
-// gdb-check:type = struct &mut Trait2<type_names::Mod1::Mod2::Struct3, type_names::GenericStruct<usize, isize>>
+// gdb-check:type = struct &mut Trait2<type_names::mod1::mod2::Struct3, type_names::GenericStruct<usize, isize>>
 
 
 // BARE FUNCTIONS
 // gdb-command:whatis rust_fn
-// gdb-check:type = struct (fn(core::option::Option<isize>, core::option::Option<&type_names::Mod1::Struct2>), usize)
+// gdb-check:type = struct (fn(core::option::Option<isize>, core::option::Option<&type_names::mod1::Struct2>), usize)
 
 // gdb-command:whatis extern_c_fn
 // gdb-check:type = struct (extern "C" fn(isize), usize)
 // gdb-check:type = struct (extern "C" fn() -> type_names::Struct1, usize)
 
 // gdb-command:whatis unsafe_fn_with_return_value
-// gdb-check:type = struct (unsafe fn(type_names::GenericStruct<u16, u8>) -> type_names::Mod1::Struct2, usize)
+// gdb-check:type = struct (unsafe fn(type_names::GenericStruct<u16, u8>) -> type_names::mod1::Struct2, usize)
 
 // gdb-command:whatis extern_stdcall_fn_with_return_value
 // gdb-check:type = struct (extern "stdcall" fn(Box<isize>) -> usize, usize)
 // gdb-check:type = struct (fn(isize) -> isize, usize)
 
 // gdb-command:whatis generic_function_struct3
-// gdb-check:type = struct (fn(type_names::Mod1::Mod2::Struct3) -> type_names::Mod1::Mod2::Struct3, usize)
+// gdb-check:type = struct (fn(type_names::mod1::mod2::Struct3) -> type_names::mod1::mod2::Struct3, usize)
 
 // gdb-command:whatis variadic_function
 // gdb-check:type = struct (unsafe extern "C" fn(*const u8, ...) -> isize, usize)
 // gdb-check:type = struct (closure, usize)
 
 #![feature(box_syntax)]
+#![allow(unused_variables)]
 #![omit_gdb_pretty_printer_section]
 
-use self::Enum1::{Variant1_1, Variant1_2};
+use self::Enum1::{Variant1, Variant2};
 use std::marker::PhantomData;
 use std::ptr;
 
 struct GenericStruct<T1, T2>(PhantomData<(T1,T2)>);
 
 enum Enum1 {
-    Variant1_1,
-    Variant1_2(isize)
+    Variant1,
+    Variant2(isize),
 }
 
-mod Mod1 {
-    pub use self::Enum2::{Variant2_1, Variant2_2};
+mod mod1 {
+    pub use self::Enum2::{Variant1, Variant2};
     pub struct Struct2;
 
     pub enum Enum2 {
-        Variant2_1,
-        Variant2_2(super::Struct1)
+        Variant1,
+        Variant2(super::Struct1),
     }
 
-    pub mod Mod2 {
-        pub use self::Enum3::{Variant3_1, Variant3_2};
+    pub mod mod2 {
+        pub use self::Enum3::{Variant1, Variant2};
         pub struct Struct3;
 
         pub enum Enum3<T> {
-            Variant3_1,
-            Variant3_2(T),
+            Variant1,
+            Variant2(T),
         }
     }
 }
@@ -214,18 +215,19 @@ trait Trait2<T1, T2> { fn dummy(&self, _: T1, _:T2) { } }
 impl Trait1 for isize {}
 impl<T1, T2> Trait2<T1, T2> for isize {}
 
-fn rust_fn(_: Option<isize>, _: Option<&Mod1::Struct2>) {}
+fn rust_fn(_: Option<isize>, _: Option<&mod1::Struct2>) {}
 extern "C" fn extern_c_fn(_: isize) {}
 unsafe fn unsafe_fn(_: Result<char, f64>) {}
 extern "stdcall" fn extern_stdcall_fn() {}
 
 fn rust_fn_with_return_value(_: f64) -> usize { 4 }
 extern "C" fn extern_c_fn_with_return_value() -> Struct1 { Struct1 }
-unsafe fn unsafe_fn_with_return_value(_: GenericStruct<u16, u8>) -> Mod1::Struct2 { Mod1::Struct2 }
+unsafe fn unsafe_fn_with_return_value(_: GenericStruct<u16, u8>) -> mod1::Struct2 { mod1::Struct2 }
 extern "stdcall" fn extern_stdcall_fn_with_return_value(_: Box<isize>) -> usize { 0 }
 
 fn generic_function<T>(x: T) -> T { x }
 
+#[allow(improper_ctypes)]
 extern {
     fn printf(_:*const u8, ...) -> isize;
 }
@@ -241,45 +243,45 @@ fn main() {
 
     // Structs
     let simple_struct = Struct1;
-    let generic_struct1: GenericStruct<Mod1::Struct2, Mod1::Mod2::Struct3> =
+    let generic_struct1: GenericStruct<mod1::Struct2, mod1::mod2::Struct3> =
         GenericStruct(PhantomData);
     let generic_struct2: GenericStruct<Struct1, extern "fastcall" fn(isize) -> usize> =
         GenericStruct(PhantomData);
-    let mod_struct = Mod1::Struct2;
+    let mod_struct = mod1::Struct2;
 
     // Enums
-    let simple_enum_1 = Variant1_1;
-    let simple_enum_2 = Variant1_2(0);
-    let simple_enum_3 = Mod1::Variant2_2(Struct1);
+    let simple_enum_1 = Variant1;
+    let simple_enum_2 = Variant2(0);
+    let simple_enum_3 = mod1::Variant2(Struct1);
 
-    let generic_enum_1: Mod1::Mod2::Enum3<Mod1::Struct2> = Mod1::Mod2::Variant3_1;
-    let generic_enum_2 = Mod1::Mod2::Variant3_2(Struct1);
+    let generic_enum_1: mod1::mod2::Enum3<mod1::Struct2> = mod1::mod2::Variant1;
+    let generic_enum_2 = mod1::mod2::Variant2(Struct1);
 
     // Tuples
-    let tuple1 = (8u32, Struct1, Mod1::Mod2::Variant3_2(Mod1::Struct2));
-    let tuple2 = ((Struct1, Mod1::Mod2::Struct3), Mod1::Variant2_1, 'x');
+    let tuple1 = (8u32, Struct1, mod1::mod2::Variant2(mod1::Struct2));
+    let tuple2 = ((Struct1, mod1::mod2::Struct3), mod1::Variant1, 'x');
 
     // Box
     let box1 = (box 1f32, 0i32);
-    let box2 = (box Mod1::Mod2::Variant3_2(1f32), 0i32);
+    let box2 = (box mod1::mod2::Variant2(1f32), 0i32);
 
     // References
     let ref1 = (&Struct1, 0i32);
     let ref2 = (&GenericStruct::<char, Struct1>(PhantomData), 0i32);
 
     let mut mut_struct1 = Struct1;
-    let mut mut_generic_struct = GenericStruct::<Mod1::Enum2, f64>(PhantomData);
+    let mut mut_generic_struct = GenericStruct::<mod1::Enum2, f64>(PhantomData);
     let mut_ref1 = (&mut mut_struct1, 0i32);
     let mut_ref2 = (&mut mut_generic_struct, 0i32);
 
     // Raw Pointers
     let mut_ptr1: (*mut Struct1, isize) = (ptr::null_mut(), 0);
     let mut_ptr2: (*mut isize, isize) = (ptr::null_mut(), 0);
-    let mut_ptr3: (*mut Mod1::Mod2::Enum3<Struct1>, isize) = (ptr::null_mut(), 0);
+    let mut_ptr3: (*mut mod1::mod2::Enum3<Struct1>, isize) = (ptr::null_mut(), 0);
 
     let const_ptr1: (*const Struct1, isize) = (ptr::null(), 0);
     let const_ptr2: (*const isize, isize) = (ptr::null(), 0);
-    let const_ptr3: (*const Mod1::Mod2::Enum3<Struct1>, isize) = (ptr::null(), 0);
+    let const_ptr3: (*const mod1::mod2::Enum3<Struct1>, isize) = (ptr::null(), 0);
 
     // Vectors
     let fixed_size_vec1 = ([Struct1, Struct1, Struct1], 0i16);
@@ -287,7 +289,7 @@ fn main() {
 
     let vec1 = vec![0_usize, 2, 3];
     let slice1 = &*vec1;
-    let vec2 = vec![Mod1::Variant2_2(Struct1)];
+    let vec2 = vec![mod1::Variant2(Struct1)];
     let slice2 = &*vec2;
 
     // Trait Objects
@@ -296,12 +298,12 @@ fn main() {
     let mut mut_int1 = 0_isize;
     let mut_ref_trait = (&mut mut_int1) as &mut Trait1;
 
-    let generic_box_trait = (box 0_isize) as Box<Trait2<i32, Mod1::Struct2>>;
+    let generic_box_trait = (box 0_isize) as Box<Trait2<i32, mod1::Struct2>>;
     let generic_ref_trait  = (&0_isize) as &Trait2<Struct1, Struct1>;
 
     let mut generic_mut_ref_trait_impl = 0_isize;
     let generic_mut_ref_trait = (&mut generic_mut_ref_trait_impl) as
-        &mut Trait2<Mod1::Mod2::Struct3, GenericStruct<usize, isize>>;
+        &mut Trait2<mod1::mod2::Struct3, GenericStruct<usize, isize>>;
 
     // Bare Functions
     let rust_fn = (rust_fn, 0_usize);
@@ -315,7 +317,7 @@ fn main() {
     let extern_stdcall_fn_with_return_value = (extern_stdcall_fn_with_return_value, 0_usize);
 
     let generic_function_int = (generic_function::<isize>, 0_usize);
-    let generic_function_struct3 = (generic_function::<Mod1::Mod2::Struct3>, 0_usize);
+    let generic_function_struct3 = (generic_function::<mod1::mod2::Struct3>, 0_usize);
 
     let variadic_function = (printf, 0_usize);
 
index b87a9250f4a7eca41fca0c54d3239c7f5f6aa590..87fd2e9a65d031b3401b5626c15c73274d2bc603 100644 (file)
@@ -8,7 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// ignore-android: FIXME(#10381)
 // ignore-windows
 // min-lldb-version: 310
 
@@ -77,7 +76,7 @@
 // lldb-command:print padded_struct
 // lldb-check:[...]$5 = &[AStruct { x: 10, y: 11, z: 12 }, AStruct { x: 13, y: 14, z: 15 }]
 
-#![allow(unused_variables)]
+#![allow(dead_code, unused_variables)]
 #![omit_gdb_pretty_printer_section]
 
 struct AStruct {
index 0d42e0be58d0702edccef3084d2cd87cc685aa97..8745cbecf913704df7cfa2c17631bb243b79a8a3 100644 (file)
@@ -49,7 +49,7 @@ fn basic_sess(sysroot: PathBuf) -> Session {
     opts.output_types = vec![OutputTypeExe];
     opts.maybe_sysroot = Some(sysroot);
 
-    let descriptions = Registry::new(&rustc::diagnostics::DIAGNOSTICS);
+    let descriptions = Registry::new(&rustc::DIAGNOSTICS);
     let sess = build_session(opts, None, descriptions);
     rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess));
     sess
index 1541e809b6178d24a77c953d764e784c1dfcf023..fc9f241af7f10279671b309896ba0b64bd0ce085 100644 (file)
@@ -12,6 +12,7 @@
 // aux-build:issue-13560-2.rs
 // aux-build:issue-13560-3.rs
 // ignore-stage1
+// ignore-musl
 
 // Regression test for issue #13560, the test itself is all in the dependent
 // libraries. The fail which previously failed to compile is the one numbered 3.
index 893fb85b529a70a91fbce0493627f13920797be7..0c464c9bad728a4c91337890899363554cfcfbff 100644 (file)
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-
-#![feature(unsafe_destructor)]
 #![feature(unsafe_no_drop_flag)]
 
 use std::mem::size_of;
@@ -19,7 +17,6 @@ struct Test<T> {
     a: T
 }
 
-#[unsafe_destructor]
 impl<T> Drop for Test<T> {
     fn drop(&mut self) { }
 }
index f4b62eb2e7c50a4191a540983dbdac96d5e461d9..3f4849dbcb2b17d083b435bbe3abd9055b6bb5fe 100644 (file)
@@ -10,6 +10,7 @@
 
 // no-pretty-expanded FIXME #15189
 // ignore-windows FIXME #13259
+// ignore-android FIXME #17520
 
 use std::env;
 use std::process::{Command, Stdio};
index 4ba3aa70dfcdfbdf04521319e6c5d2edea109245..e55eae1e74fc6804db91cff6f68b974a324390c3 100644 (file)
@@ -8,13 +8,10 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(unsafe_destructor)]
-
 struct S<T> {
     x: T
 }
 
-#[unsafe_destructor]
 impl<T> ::std::ops::Drop for S<T> {
     fn drop(&mut self) {
         println!("bye");
index 6ccf6c2fd644d958b5a1b05229a736416dfe7aa0..b0c4f4ca272a03e52f3656a4c51b8395aca34714 100644 (file)
@@ -16,9 +16,8 @@
 // shows a similar setup, but restricts `f` so that the struct `C<'a>`
 // is force-fed a lifetime equal to that of the borrowed arena.
 
-
 #![allow(unstable)]
-#![feature(unsafe_destructor, rustc_private)]
+#![feature(rustc_private)]
 
 extern crate arena;
 
@@ -33,7 +32,6 @@ struct CheckId<T:HasId> { v: T }
 // interface to CheckId does not (and cannot) know that, and therefore
 // when encountering the a value V of type CheckId<S>, we must
 // conservatively force the type S to strictly outlive V.
-#[unsafe_destructor]
 impl<T:HasId> Drop for CheckId<T> {
     fn drop(&mut self) {
         assert!(self.v.count() > 0);
index 97b32189d0027203c80c719d7f8598b6b26209c8..a270b003981669377b9a28a38d31a48f6f4d0964 100644 (file)
@@ -8,10 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-
-#![allow(unknown_features)]
 #![feature(box_syntax)]
-#![feature(unsafe_destructor)]
 
 use std::cell::Cell;
 
@@ -24,7 +21,6 @@ struct r<'a> {
 
 struct BoxR<'a> { x: r<'a> }
 
-#[unsafe_destructor]
 impl<'a> Drop for r<'a> {
     fn drop(&mut self) {
         self.i.set(self.i.get() + 1)
index f1d731c8b1d7a41bdf29efee05aef7a2d01223ba..8dbe927f06bf14257e7ef7b07f4ae235a13d0dce 100644 (file)
@@ -109,11 +109,6 @@ pub fn main() {
         assert_eq!(cttz32(100), 2);
         assert_eq!(cttz64(100), 2);
 
-        assert_eq!(cttz8(-1), 0);
-        assert_eq!(cttz16(-1), 0);
-        assert_eq!(cttz32(-1), 0);
-        assert_eq!(cttz64(-1), 0);
-
         assert_eq!(bswap16(0x0A0B), 0x0B0A);
         assert_eq!(bswap32(0x0ABBCC0D), 0x0DCCBB0A);
         assert_eq!(bswap64(0x0122334455667708), 0x0877665544332201);
index 79a530785452ac58c1bfa1d0f8694a452aae9594..66201ff901f309ce702e706b0e312be280919d48 100644 (file)
@@ -11,6 +11,7 @@
 // aux-build:issue-12133-rlib.rs
 // aux-build:issue-12133-dylib.rs
 // aux-build:issue-12133-dylib2.rs
+// ignore-musl
 
 // pretty-expanded FIXME #23616
 
index 4f084d7891f37fe37dbee576ccfff022e032425b..a1ada18984e9e7eb95b01752bfde5bdb3868d6bb 100644 (file)
@@ -8,9 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-
-#![feature(unsafe_destructor)]
-
 static mut DROP_RAN: bool = false;
 
 trait Bar {
@@ -26,7 +23,6 @@ fn do_something(&mut self) {}
 
 struct Foo<B: Bar>(B);
 
-#[unsafe_destructor]
 impl<B: Bar> Drop for Foo<B> {
     fn drop(&mut self) {
         unsafe {
index e544585745de3dfc21839f252614879bc2e19d44..0c208773884d4841d57237eadd2c9bc01a1c79a5 100644 (file)
@@ -10,7 +10,7 @@
 
 // pretty-expanded FIXME #23616
 
-#![feature(unsafe_destructor, rustc_private)]
+#![feature(rustc_private)]
 
 extern crate serialize;
 
@@ -22,7 +22,6 @@ struct Foo<T: Encodable> {
     v: T,
 }
 
-#[unsafe_destructor]
 impl<T: Encodable> Drop for Foo<T> {
     fn drop(&mut self) {
         json::encode(&self.v);
index fcb0462766291073da2f2de7c2fe787e56f0ca70..975557726ce8b2a7be680c2b7a3eccbe951aba4f 100644 (file)
@@ -10,8 +10,6 @@
 
 // ignore-pretty
 
-#![feature(unsafe_destructor)]
-
 use std::rc::Rc;
 use std::cell::Cell;
 
@@ -29,7 +27,6 @@ fn new(number: usize, state: Rc<Cell<usize>>) -> Field {
     }
 }
 
-#[unsafe_destructor] // because Field isn't Send
 impl Drop for Field {
     fn drop(&mut self) {
         println!("Dropping field {}", self.number);
@@ -50,7 +47,6 @@ struct HasDropImpl {
     _three: Field
 }
 
-#[unsafe_destructor] // because HasDropImpl isn't Send
 impl Drop for HasDropImpl {
     fn drop(&mut self) {
         println!("HasDropImpl.drop()");
index 6a8f7d992a2929ef732bc2f9c0c4d7e89b1dc8ba..e713bbf127d8c05438607c2ce1af0e6366564624 100644 (file)
@@ -8,14 +8,10 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-
-#![feature(unsafe_destructor)]
-
 struct Leak<'a> {
     dropped: &'a mut bool
 }
 
-#[unsafe_destructor]
 impl<'a> Drop for Leak<'a> {
     fn drop(&mut self) {
         *self.dropped = true;
diff --git a/src/test/run-pass/issue-24945-repeat-dash-opts.rs b/src/test/run-pass/issue-24945-repeat-dash-opts.rs
new file mode 100644 (file)
index 0000000..33ac519
--- /dev/null
@@ -0,0 +1,18 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// This test is just checking that we continue to accept `-g -g -O -O`
+// as options to the compiler.
+
+// compile-flags:-g -g -O -O
+
+fn main() {
+    assert_eq!(1, 1);
+}
index 0df89c72424b46ee484e3e0fb04772865fa12547..a0f18d9f7f1c2b40d00b10ce53bbc12ba12ece1c 100644 (file)
@@ -9,7 +9,7 @@
 // except according to those terms.
 //
 
-#![feature(unsafe_destructor, std_misc)]
+#![feature(std_misc)]
 
 pub type Task = isize;
 
@@ -165,8 +165,7 @@ pub struct send_packet<T:Send> {
         p: Option<*const packet<T>>,
     }
 
-    #[unsafe_destructor]
-    impl<T:Send> Drop for send_packet<T> {
+        impl<T:Send> Drop for send_packet<T> {
         fn drop(&mut self) {
             unsafe {
                 if self.p != None {
@@ -195,8 +194,7 @@ pub struct recv_packet<T:Send> {
         p: Option<*const packet<T>>,
     }
 
-    #[unsafe_destructor]
-    impl<T:Send> Drop for recv_packet<T> {
+        impl<T:Send> Drop for recv_packet<T> {
         fn drop(&mut self) {
             unsafe {
                 if self.p != None {
index 36d7f4583b09f47be4cd0e0a85848b7c413fea43..cdce059ae71f1e99e58f34362ba2bafdcd716744 100644 (file)
@@ -8,9 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-
-#![feature(unsafe_destructor)]
-
 use std::cell::Cell;
 
 // This test should behave exactly like issue-2735-3
@@ -18,7 +15,6 @@ struct defer<'a> {
     b: &'a Cell<bool>,
 }
 
-#[unsafe_destructor]
 impl<'a> Drop for defer<'a> {
     fn drop(&mut self) {
         self.b.set(true);
index f438519b72f3b5c754177d5d86e4733012592ae1..d1e28faba8b5bf154777550d721a946f58b2702e 100644 (file)
@@ -8,9 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-
-#![feature(unsafe_destructor)]
-
 use std::cell::Cell;
 
 // This test should behave exactly like issue-2735-2
@@ -18,7 +15,6 @@ struct defer<'a> {
     b: &'a Cell<bool>,
 }
 
-#[unsafe_destructor]
 impl<'a> Drop for defer<'a> {
     fn drop(&mut self) {
         self.b.set(true);
index 73ef35f0457d8650431cbd286d292c6f4206395e..e604141dab812485fdf6a0b9d98391206f301f4e 100644 (file)
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(unsafe_destructor)]
-
 trait X {
     fn call<T: std::fmt::Debug>(&self, x: &T);
     fn default_method<T: std::fmt::Debug>(&self, x: &T) {
@@ -31,7 +29,6 @@ fn call<T: std::fmt::Debug>(&self, x: &T) {
     }
 }
 
-#[unsafe_destructor]
 impl<T: X + std::fmt::Debug> Drop for Z<T> {
     fn drop(&mut self) {
         // These statements used to cause an ICE.
index 979abcef7b8d2c1dd801765d45ae5b191358151f..43fa98124262a86e20dbd1f6608a0f60de23f715 100644 (file)
@@ -8,16 +8,12 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-
-#![feature(unsafe_destructor)]
-
 use std::cell::Cell;
 
 struct r<'a> {
     b: &'a Cell<isize>,
 }
 
-#[unsafe_destructor]
 impl<'a> Drop for r<'a> {
     fn drop(&mut self) {
         self.b.set(self.b.get() + 1);
diff --git a/src/test/run-pass/issue24687-embed-debuginfo.rs b/src/test/run-pass/issue24687-embed-debuginfo.rs
new file mode 100644 (file)
index 0000000..7754e9c
--- /dev/null
@@ -0,0 +1,22 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// aux-build:issue24687_lib.rs
+// compile-flags:-g
+
+extern crate issue24687_lib as d;
+
+fn main() {
+    // Create a d, which has a destructor whose body will be trans'ed
+    // into the generated code here, and thus the local debuginfo will
+    // need references into the original source locations from
+    // `importer` above.
+    let _d = d::D("Hi");
+}
index 74da4273b6ab0fb9b773425793bed9e05ae5df70..b8ad7162d286811c3b5fc6395ed45b0b4eb5b8f8 100644 (file)
@@ -9,8 +9,9 @@
 // except according to those terms.
 
 // aux-build:linkage-visibility.rs
-// ignore-android: FIXME(#10379)
+// ignore-android: FIXME(#10356)
 // ignore-windows: std::dynamic_lib does not work on Windows well
+// ignore-musl
 
 #![feature(std_misc)]
 
index 4407002aca8d6504abf80dc5c03ee0831f40618f..6a5d86b522ed4fe1ac69c6b4b4005fcb41cc996a 100644 (file)
@@ -8,16 +8,12 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-
-#![feature(unsafe_destructor)]
-
 // Make sure the destructor is run for newtype structs.
 
 use std::cell::Cell;
 
 struct Foo<'a>(&'a Cell<isize>);
 
-#[unsafe_destructor]
 impl<'a> Drop for Foo<'a> {
     fn drop(&mut self) {
         let Foo(i) = *self;
diff --git a/src/test/run-pass/nullable-pointer-opt-closures.rs b/src/test/run-pass/nullable-pointer-opt-closures.rs
new file mode 100644 (file)
index 0000000..ac5634e
--- /dev/null
@@ -0,0 +1,43 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+
+use std::mem;
+
+pub fn main() {
+    // By Ref Capture
+    let a = 10i32;
+    let b = Some(|| println!("{}", a));
+    // When we capture by reference we can use any of the
+    // captures as the discriminant since they're all
+    // behind a pointer.
+    assert_eq!(mem::size_of_val(&b), mem::size_of::<usize>());
+
+    // By Value Capture
+    let a = Box::new(12i32);
+    let b = Some(move || println!("{}", a));
+    // We captured `a` by value and since it's a `Box` we can use it
+    // as the discriminant.
+    assert_eq!(mem::size_of_val(&b), mem::size_of::<Box<i32>>());
+
+    // By Value Capture - Transitive case
+    let a = "Hello".to_string(); // String -> Vec -> Unique -> NonZero
+    let b = Some(move || println!("{}", a));
+    // We captured `a` by value and since down the chain it contains
+    // a `NonZero` field, we can use it as the discriminant.
+    assert_eq!(mem::size_of_val(&b), mem::size_of::<String>());
+
+    // By Value - No Optimization
+    let a = 14i32;
+    let b = Some(move || println!("{}", a));
+    // We captured `a` by value but we can't use it as the discriminant
+    // thus we end up with an extra field for the discriminant
+    assert_eq!(mem::size_of_val(&b), mem::size_of::<(i32, i32)>());
+}
index 44f13a3eb1a52a1f6090628b0c3932e4b1b9e365..e22edb3caede49ea89f1d9ec8c80679bdff05177 100644 (file)
@@ -8,16 +8,12 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-
-#![feature(unsafe_destructor)]
-
 use std::cell::Cell;
 
 struct dtor<'a> {
     x: &'a Cell<isize>,
 }
 
-#[unsafe_destructor]
 impl<'a> Drop for dtor<'a> {
     fn drop(&mut self) {
         self.x.set(self.x.get() - 1);
index 0d0a5bee8a443f879ddc00df20d2bf80d1a153de..2c6e55b57b066a5be9c766243ec93ffff9d5b3a0 100644 (file)
@@ -8,11 +8,12 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-//ignore-android
-//ignore-freebsd
-//ignore-ios
-//ignore-dragonfly
-//ignore-bitrig
+// ignore-android
+// ignore-freebsd
+// ignore-ios
+// ignore-dragonfly
+// ignore-bitrig
+// ignore-musl
 
 #![feature(asm)]
 
index 9a327eb567266bf0da01211ba00f160c4ebb0af1..4b32b881be73868eed9442a63fb2805c5ac5fa32 100644 (file)
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// ignore-android: FIXME(#9116) Bus error
-
 use std::mem;
 
 #[repr(packed)]
index 6cc32301cc46eb6c9bd2cec41e7acd42930ab4ce..cdb58d1ba4c01f1231ab2674feb480f1ff88b6fc 100644 (file)
@@ -10,8 +10,6 @@
 
 // pretty-expanded FIXME #23616
 
-#![feature(unsafe_destructor)]
-
 use std::marker;
 
 pub struct Foo<T>(marker::PhantomData<T>);
@@ -24,7 +22,6 @@ fn next(&mut self) -> Option<T> {
     }
 }
 
-#[unsafe_destructor]
 impl<T> Drop for Foo<T> {
     fn drop(&mut self) {
         self.next();
index ba63c2db7cf59052e690bf1f6fc53c91d067d15e..4d0c2900a0fad5ab14390f02caf7f2abc7fcdb42 100644 (file)
@@ -8,8 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(unsafe_destructor)]
-
 use std::cell::Cell;
 
 #[derive(Debug)]
@@ -17,7 +15,6 @@ struct r<'a> {
     i: &'a Cell<isize>,
 }
 
-#[unsafe_destructor]
 impl<'a> Drop for r<'a> {
     fn drop(&mut self) {
         self.i.set(self.i.get() + 1);
index 229ceba08b0ff3730be40d6134f214796717cdbe..5b2b8655442c892ea5a4ef108b561f3c1c41821d 100644 (file)
@@ -8,15 +8,12 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(unsafe_destructor)]
-
 use std::cell::Cell;
 
 struct shrinky_pointer<'a> {
   i: &'a Cell<isize>,
 }
 
-#[unsafe_destructor]
 impl<'a> Drop for shrinky_pointer<'a> {
     fn drop(&mut self) {
         println!("Hello!"); self.i.set(self.i.get() - 1);
index c1e1ff0658b6e718621f208bb775bb0198c318c6..2914127246a0b8b5b92eac6acac65383aaa8bb22 100644 (file)
@@ -8,9 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-
-#![feature(unsafe_destructor)]
-
 // Ensures that class dtors run if the object is inside an enum
 // variant
 
@@ -23,7 +20,6 @@ struct close_res<'a> {
 
 }
 
-#[unsafe_destructor]
 impl<'a> Drop for close_res<'a> {
     fn drop(&mut self) {
         self.i.set(false);
index 973c61712c3ed719dc88f96aa79e218d84a3774f..f21b787dab72f052c2bee89a6d38d4fe10b7af41 100644 (file)
@@ -14,8 +14,8 @@
 
 // Test accessing external items from multiple compilation units.
 
+extern crate sepcomp_extern_lib;
 
-#[link(name = "sepcomp_extern_lib")]
 extern {
     #[allow(ctypes)]
     fn foo() -> usize;
index 447b4de450bf1097e046d90761b2c287bcd50d5b..d7877bff0cb91ae095c720f26e4ebde039eadb4f 100644 (file)
@@ -12,6 +12,7 @@
 
 #![allow(unused_mut)]
 #![feature(collections)]
+#![feature(collections_drain)]
 
 extern crate collections;
 
@@ -96,5 +97,6 @@ fn from_usize(v: usize) -> Foo {
 
     all_sync_send!(VecMap::<usize>::new(), iter, iter_mut, drain, into_iter, keys, values);
 
-    all_sync_send!(Vec::<usize>::new(), into_iter, drain);
+    all_sync_send!(Vec::<usize>::new(), into_iter);
+    is_sync_send!(Vec::<usize>::new(), drain(..));
 }
index dcda724c7b8fe80d813b7e2276200adacff77858..449f533103a80b10e8f2e8dbccec47c4f8d866cc 100644 (file)
@@ -8,9 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-
-#![feature(unsafe_destructor)]
-
 // Test that we are able to infer a suitable kind for this `move`
 // closure that is just called (`FnOnce`).
 
@@ -18,7 +15,6 @@
 
 struct DropMe<'a>(&'a mut i32);
 
-#[unsafe_destructor]
 impl<'a> Drop for DropMe<'a> {
     fn drop(&mut self) {
         *self.0 += 1;
index 275ba0520c568a0dd2bf99b734e22580512ea59e..79a1aff853524b8b97d5cc6d7061403e002b1e14 100644 (file)
@@ -8,9 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-
-#![feature(unsafe_destructor)]
-
 // Test that we are able to infer a suitable kind for this closure
 // that is just called (`FnOnce`).
 
@@ -18,7 +15,6 @@
 
 struct DropMe<'a>(&'a mut i32);
 
-#[unsafe_destructor]
 impl<'a> Drop for DropMe<'a> {
     fn drop(&mut self) {
         *self.0 += 1;
index f400869682fd2d3bded7042337e10bc07e6ff174..86d34d38f744f50073d0a3e88e6a4eea6ff881b9 100644 (file)
@@ -8,9 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-
-#![feature(unsafe_destructor)]
-
 use std::cell::Cell;
 
 // Make sure that destructors get run on slice literals
@@ -18,7 +15,6 @@ struct foo<'a> {
     x: &'a Cell<isize>,
 }
 
-#[unsafe_destructor]
 impl<'a> Drop for foo<'a> {
     fn drop(&mut self) {
         self.x.set(self.x.get() + 1);