]> git.lizzy.rs Git - rust.git/commitdiff
rollup merge of #24894: bguiz/diagnostic-E0267
authorAlex Crichton <alex@alexcrichton.com>
Wed, 29 Apr 2015 22:45:43 +0000 (15:45 -0700)
committerAlex Crichton <alex@alexcrichton.com>
Wed, 29 Apr 2015 22:45:43 +0000 (15:45 -0700)
This error indicates that a constant references itself.
All 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;
```

260 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
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/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/liblibc/lib.rs
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/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/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_borrowck/lib.rs
src/librustc_driver/lib.rs
src/librustc_lint/lib.rs
src/librustc_llvm/archive_ro.rs
src/librustc_llvm/lib.rs
src/librustc_trans/back/link.rs
src/librustc_trans/lib.rs
src/librustc_trans/trans/base.rs
src/librustc_trans/trans/build.rs
src/librustc_trans/trans/builder.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/intrinsic.rs
src/librustc_typeck/check/dropck.rs
src/librustc_typeck/check/mod.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/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/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/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/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/thread/local.rs
src/libstd/thread/mod.rs
src/libstd/thread/scoped_tls.rs
src/libsyntax/feature_gate.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/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-pass-fulldeps/issue-13560.rs
src/test/run-pass/attr-no-drop-flag-size.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-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/option-unwrap.rs
src/test/run-pass/out-of-stack-new-thread-no-split.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 f32d6cd4fc7b485910db502dcf227eebeb393327..f4e1d41276aa959cfd98e94f64a24ef0bc8c34db 100755 (executable)
--- a/configure
+++ b/configure
@@ -583,6 +583,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 +1059,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 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 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..ad096630127cb366c9cbf78e9c2be65e0a4f875b 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();
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 6b3920f46ee82aefd7cd69597dd4857efd7ba742..92be6ac6be54fe707d8a5fa745945b0e73d6730d 100644 (file)
@@ -168,6 +168,25 @@ struct X { x: (), }
 ```
 "##,
 
+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
@@ -478,7 +497,6 @@ enum Method { GET, POST }
     E0010,
     E0011,
     E0012,
-    E0013,
     E0014,
     E0016,
     E0017,
index d4012f2057b5dac8306e189e3401d6bc9b6a981c..b0b1b4df6e30699ef649fcc99a43556503c64b34 100644 (file)
 #![feature(quote)]
 #![feature(rustc_diagnostic_macros)]
 #![feature(rustc_private)]
-#![feature(unsafe_destructor)]
 #![feature(staged_api)]
 #![feature(std_misc)]
 #![feature(path_ext)]
 #![feature(str_char)]
 #![feature(into_cow)]
+#![feature(fs_canonicalize)]
 #![feature(slice_patterns)]
 #![cfg_attr(test, feature(test))]
 
@@ -139,7 +139,6 @@ pub mod middle {
 pub mod lint;
 
 pub mod util {
-    pub use rustc_back::fs;
     pub use rustc_back::sha2;
 
     pub mod common;
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 050ccd6471288ae759c4570657b68f624eec40ea..072761f2754b3723fed2c29ee2d3f623c314a404 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")));
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..fcc901fc81f576f7da57193785e0cc4f5444168f 100644 (file)
@@ -24,6 +24,7 @@ pub fn target() -> Target {
         target_pointer_width: "64".to_string(),
         arch: "aarch64".to_string(),
         target_os: "android".to_string(),
+        target_env: "".to_string(),
         options: base,
     }
 }
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,
index fad9344143155628ee92b56fdda2ff0819dfd8af..57712d18cbae2fd7568cb59cc67bd2ef71c23697 100644 (file)
@@ -31,6 +31,7 @@ pub fn target() -> Target {
         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..3a79ae3e7c01b6e8116f47904f33b769ff8b917b 100644 (file)
 mod bitrig_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;
-
 /// Everything `rustc` knows about how to compile for a specific target.
 ///
 /// Every field here must be specified, and has no default value.
@@ -100,6 +74,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 +91,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 +191,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 +236,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 +317,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 +347,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 647ea3555ba913984c8ed71be606c13e41851c86..8cecc528d1a1f94747db7113359d13c16fbd916b 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;
index 38217f8dad24e900db8341f407855356655d2759..75673a6b83ab9a399ac0e67acb3fac21a858aa8a 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)]
index 34f7436d0cd5d8d7cc5ccc9be4e2b88664b1183e..544fe7598192cda1397af3f388482522e967ffa1 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))]
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..79757320ade6ff6fca2181887749ec9becd6e218 100644 (file)
@@ -30,7 +30,6 @@
 #![feature(libc)]
 #![feature(link_args)]
 #![feature(staged_api)]
-#![feature(unsafe_destructor)]
 
 extern crate libc;
 #[macro_use] #[no_link] extern crate rustc_bitflags;
@@ -43,6 +42,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::*;
@@ -361,6 +361,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 +1541,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 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 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 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 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 be3fc860b2b1239cad25fb50e0667dfc4557113e..20827f2ddfbf7209ce2a6fd142f7ebb5cd511b72 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;
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..8473b24172edd917035ecb4833d6b795ee8b66fd 100644 (file)
 #![feature(staged_api)]
 #![feature(unboxed_closures)]
 #![feature(unicode)]
-#![feature(unsafe_destructor)]
 #![feature(unsafe_no_drop_flag, filling_drop)]
 #![feature(macro_reexport)]
 #![feature(unique)]
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")
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 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 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 {}
 
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..5b748280986f7258bb4ff1ab64ad03491b4e0c36 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,
@@ -61,6 +70,8 @@ pub struct OpenOptions {
 #[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 +122,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,
+        })
     }
 }
 
@@ -180,6 +214,13 @@ 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 {
@@ -224,7 +265,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 +273,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 +309,41 @@ 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)))
+        }
+    }
 }
 
 impl FromInner<libc::HANDLE> for File {
@@ -285,27 +366,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 }
+
+    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_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
+    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 +407,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 +482,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 +511,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 +557,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 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..ae480380f95eb00710b6e37096b296bfe2f7c468 100644 (file)
@@ -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) }
             }
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 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
+}
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..3d0af686586bd4fa6f0c4951027a32cded1c2eb4 100644 (file)
@@ -13,8 +13,7 @@
 
 // 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..58a1ba06b5452dfb4cc8c00f67486e86dbfaa269 100644 (file)
@@ -13,8 +13,7 @@
 
 // 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..09ab30cbec1a2f8ab62e5582d38e02381f90bd2e 100644 (file)
@@ -21,7 +21,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 +44,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..97b6bfacf80eec149088f6f616ab0e2bde4ce9af 100644 (file)
@@ -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..c806286deadafcaafce9e6df0b2b1d4e4e902ada 100644 (file)
@@ -77,7 +77,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 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 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;
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..ad30d53
--- /dev/null
@@ -0,0 +1,21 @@
+// 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
+
+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;
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 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);