]> git.lizzy.rs Git - rust.git/commitdiff
rollup merge of #24711: alexcrichton/fs2.1
authorAlex Crichton <alex@alexcrichton.com>
Wed, 29 Apr 2015 22:45:34 +0000 (15:45 -0700)
committerAlex Crichton <alex@alexcrichton.com>
Wed, 29 Apr 2015 22:45:34 +0000 (15:45 -0700)
This commit is an implementation of [RFC 1044][rfc] which adds additional
surface area to the `std::fs` module. All new APIs are `#[unstable]` behind
assorted feature names for each one.

[rfc]: https://github.com/rust-lang/rfcs/pull/1044

The new APIs added are:

* `fs::canonicalize` - bindings to `realpath` on unix and
  `GetFinalPathNameByHandle` on windows.
* `fs::symlink_metadata` - similar to `lstat` on unix
* `fs::FileType` and accessor methods as `is_{file,dir,symlink}`
* `fs::Metadata::file_type` - accessor for the raw file type
* `fs::DirEntry::metadata` - acquisition of metadata which is free on Windows
  but requires a syscall on unix.
* `fs::DirEntry::file_type` - access the file type which may not require a
  syscall on most platforms.
* `fs::DirEntry::file_name` - access just the file name without leading
  components.
* `fs::PathExt::symlink_metadata` - convenience method for the top-level
  function.
* `fs::PathExt::canonicalize` - convenience method for the top-level
  function.
* `fs::PathExt::read_link` - convenience method for the top-level
  function.
* `fs::PathExt::read_dir` - convenience method for the top-level
  function.
* `std::os::raw` - type definitions for raw OS/C types available on all
  platforms.
* `std::os::$platform` - new modules have been added for all currently supported
  platforms (e.g. those more specific than just `unix`).
* `std::os::$platform::raw` - platform-specific type definitions. These modules
  are populated with the bare essentials necessary for lowing I/O types into
  their raw representations, and currently largely consist of the `stat`
  definition for unix platforms.

This commit also deprecates `Metadata::{modified, accessed}` in favor of
inspecting the raw representations via the lowering methods of `Metadata`.

Closes https://github.com/rust-lang/rust/issues/24796

305 files changed:
configure
mk/cfg/aarch64-apple-ios.mk
mk/cfg/aarch64-linux-android.mk
mk/cfg/aarch64-unknown-linux-gnu.mk
mk/cfg/arm-linux-androideabi.mk
mk/cfg/arm-unknown-linux-gnueabi.mk
mk/cfg/arm-unknown-linux-gnueabihf.mk
mk/cfg/armv7-apple-ios.mk
mk/cfg/armv7s-apple-ios.mk
mk/cfg/i386-apple-ios.mk
mk/cfg/i686-apple-darwin.mk
mk/cfg/i686-pc-windows-gnu.mk
mk/cfg/i686-unknown-linux-gnu.mk
mk/cfg/mips-unknown-linux-gnu.mk
mk/cfg/mipsel-unknown-linux-gnu.mk
mk/cfg/powerpc-unknown-linux-gnu.mk
mk/cfg/x86_64-apple-darwin.mk
mk/cfg/x86_64-apple-ios.mk
mk/cfg/x86_64-pc-windows-gnu.mk
mk/cfg/x86_64-unknown-bitrig.mk
mk/cfg/x86_64-unknown-dragonfly.mk
mk/cfg/x86_64-unknown-freebsd.mk
mk/cfg/x86_64-unknown-linux-gnu.mk
mk/cfg/x86_64-unknown-linux-musl.mk [new file with mode: 0644]
mk/cfg/x86_64-unknown-openbsd.mk
mk/crates.mk
mk/main.mk
mk/prepare.mk
mk/rt.mk
mk/rustllvm.mk
mk/target.mk
mk/tests.mk
src/compiletest/header.rs
src/compiletest/runtest.rs
src/compiletest/util.rs
src/doc/reference.md
src/doc/trpl/hello-cargo.md
src/doc/trpl/ufcs.md
src/doc/trpl/vectors.md
src/grammar/parser-lalr.y
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/string.rs
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/convert.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/ops.rs
src/libcore/ptr.rs
src/libcore/slice.rs
src/libcoretest/iter.rs
src/libcoretest/lib.rs
src/libcoretest/option.rs
src/libcoretest/slice.rs
src/liblibc/lib.rs
src/librustc/diagnostics.rs
src/librustc/lib.rs
src/librustc/metadata/creader.rs
src/librustc/metadata/csearch.rs
src/librustc/metadata/decoder.rs
src/librustc/metadata/encoder.rs
src/librustc/middle/astencode.rs
src/librustc/middle/cfg/construct.rs
src/librustc/middle/check_const.rs
src/librustc/middle/check_match.rs
src/librustc/middle/check_static_recursion.rs
src/librustc/middle/const_eval.rs
src/librustc/middle/dead.rs
src/librustc/middle/def.rs
src/librustc/middle/expr_use_visitor.rs
src/librustc/middle/infer/error_reporting.rs
src/librustc/middle/mem_categorization.rs
src/librustc/middle/pat_util.rs
src/librustc/middle/reachable.rs
src/librustc/middle/traits/object_safety.rs
src/librustc/middle/traits/project.rs
src/librustc/middle/traits/util.rs
src/librustc/middle/ty.rs
src/librustc/session/config.rs
src/librustc/util/ppaux.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/borrowck/mod.rs
src/librustc_borrowck/lib.rs
src/librustc_driver/lib.rs
src/librustc_driver/pretty.rs
src/librustc_lint/builtin.rs
src/librustc_lint/lib.rs
src/librustc_llvm/archive_ro.rs
src/librustc_llvm/lib.rs
src/librustc_privacy/lib.rs
src/librustc_resolve/build_reduced_graph.rs
src/librustc_resolve/lib.rs
src/librustc_trans/back/link.rs
src/librustc_trans/lib.rs
src/librustc_trans/save/mod.rs
src/librustc_trans/trans/_match.rs
src/librustc_trans/trans/adt.rs
src/librustc_trans/trans/base.rs
src/librustc_trans/trans/callee.rs
src/librustc_trans/trans/cleanup.rs
src/librustc_trans/trans/consts.rs
src/librustc_trans/trans/context.rs
src/librustc_trans/trans/debuginfo.rs
src/librustc_trans/trans/glue.rs
src/librustc_trans/trans/inline.rs
src/librustc_trans/trans/meth.rs
src/librustc_trans/trans/monomorphize.rs
src/librustc_typeck/check/_match.rs
src/librustc_typeck/check/compare_method.rs
src/librustc_typeck/check/dropck.rs
src/librustc_typeck/check/method/confirm.rs
src/librustc_typeck/check/method/mod.rs
src/librustc_typeck/check/method/probe.rs
src/librustc_typeck/check/mod.rs
src/librustc_typeck/coherence/mod.rs
src/librustc_typeck/collect.rs
src/librustc_typeck/diagnostics.rs
src/librustc_typeck/lib.rs
src/librustdoc/clean/inline.rs
src/librustdoc/clean/mod.rs
src/librustdoc/html/item_type.rs
src/librustdoc/html/render.rs
src/librustdoc/html/static/main.css
src/librustdoc/html/static/main.js
src/librustdoc/passes.rs
src/libstd/collections/hash/table.rs
src/libstd/dynamic_lib.rs
src/libstd/io/buffered.rs
src/libstd/io/mod.rs
src/libstd/lib.rs
src/libstd/macros.rs
src/libstd/panicking.rs
src/libstd/rt/libunwind.rs
src/libstd/rt/unwind.rs
src/libstd/rtdeps.rs
src/libstd/sync/mpsc/mod.rs
src/libstd/sync/mpsc/mpsc_queue.rs
src/libstd/sync/mpsc/oneshot.rs
src/libstd/sync/mpsc/select.rs
src/libstd/sync/mpsc/shared.rs
src/libstd/sync/mpsc/spsc_queue.rs
src/libstd/sync/mpsc/stream.rs
src/libstd/sync/mpsc/sync.rs
src/libstd/sync/mutex.rs
src/libstd/sync/rwlock.rs
src/libstd/sync/semaphore.rs
src/libstd/sys/common/remutex.rs
src/libstd/sys/common/thread_info.rs
src/libstd/sys/unix/stack_overflow.rs
src/libstd/sys/unix/thread.rs
src/libstd/sys/unix/time.rs
src/libstd/thread/local.rs
src/libstd/thread/mod.rs
src/libstd/thread/scoped_tls.rs
src/libsyntax/ast.rs
src/libsyntax/ast_map/blocks.rs
src/libsyntax/ast_map/mod.rs
src/libsyntax/ast_util.rs
src/libsyntax/feature_gate.rs
src/libsyntax/fold.rs
src/libsyntax/parse/parser.rs
src/libsyntax/print/pprust.rs
src/libsyntax/visit.rs
src/snapshots.txt
src/test/auxiliary/associated-const-cc-lib.rs [new file with mode: 0644]
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/associated-const-dead-code.rs [new file with mode: 0644]
src/test/compile-fail/associated-const-impl-wrong-type.rs [new file with mode: 0644]
src/test/compile-fail/associated-const-private-impl.rs [new file with mode: 0644]
src/test/compile-fail/associated-const-upper-case-lint.rs [new file with mode: 0644]
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-associated_consts.rs [new file with mode: 0644]
src/test/compile-fail/gated-unsafe-destructor.rs [deleted file]
src/test/compile-fail/impl-wrong-item-for-trait.rs [new file with mode: 0644]
src/test/compile-fail/issue-24895-copy-clone-dropck.rs [new file with mode: 0644]
src/test/compile-fail/method-path-in-pattern.rs [new file with mode: 0644]
src/test/compile-fail/method-resolvable-path-in-pattern.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/parse-fail/brace-after-qualified-path-in-match.rs [new file with mode: 0644]
src/test/parse-fail/issue-20711-2.rs
src/test/parse-fail/issue-20711.rs
src/test/parse-fail/issue-21153.rs
src/test/parse-fail/paren-after-qualified-path-in-match.rs [new file with mode: 0644]
src/test/parse-fail/removed-syntax-static-fn.rs
src/test/parse-fail/trait-pub-assoc-const.rs [new file with mode: 0644]
src/test/parse-fail/trait-pub-assoc-ty.rs
src/test/parse-fail/trait-pub-method.rs
src/test/run-fail-fulldeps/qquote.rs [new file with mode: 0644]
src/test/run-fail/qquote.rs [deleted file]
src/test/run-pass-fulldeps/issue-13560.rs
src/test/run-pass/associated-const-cross-crate-defaults.rs [new file with mode: 0644]
src/test/run-pass/associated-const-cross-crate.rs [new file with mode: 0644]
src/test/run-pass/associated-const-in-global-const.rs [new file with mode: 0644]
src/test/run-pass/associated-const-inherent-impl.rs [new file with mode: 0644]
src/test/run-pass/associated-const-marks-live-code.rs [new file with mode: 0644]
src/test/run-pass/associated-const-match-patterns.rs [new file with mode: 0644]
src/test/run-pass/associated-const-overwrite-default.rs [new file with mode: 0644]
src/test/run-pass/associated-const-public-impl.rs [new file with mode: 0644]
src/test/run-pass/associated-const-resolution-order.rs [new file with mode: 0644]
src/test/run-pass/associated-const-self-type.rs [new file with mode: 0644]
src/test/run-pass/associated-const-ufcs-infer-trait.rs [new file with mode: 0644]
src/test/run-pass/associated-const-use-default.rs [new file with mode: 0644]
src/test/run-pass/associated-const-use-impl-of-same-trait.rs [new file with mode: 0644]
src/test/run-pass/associated-const.rs [new file with mode: 0644]
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/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-23611-enum-swap-in-drop.rs [new file with mode: 0644]
src/test/run-pass/issue-24313.rs [new file with mode: 0644]
src/test/run-pass/issue-2718.rs
src/test/run-pass/issue-2735-2.rs
src/test/run-pass/issue-2735-3.rs
src/test/run-pass/issue-4252.rs
src/test/run-pass/issue-979.rs
src/test/run-pass/issue24687-embed-debuginfo.rs [new file with mode: 0644]
src/test/run-pass/linkage-visibility.rs
src/test/run-pass/newtype-struct-drop-run.rs
src/test/run-pass/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 6d629bf9807e4ff3964552c5d1f2ada1bce6e5d7..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
@@ -1144,6 +1152,7 @@ do
     make_dir $h/test/run-pass-valgrind
     make_dir $h/test/run-pass-fulldeps
     make_dir $h/test/run-fail
+    make_dir $h/test/run-fail-fulldeps
     make_dir $h/test/compile-fail
     make_dir $h/test/parse-fail
     make_dir $h/test/compile-fail-fulldeps
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 5d100958edc92296565b17a382efd439fcfd3fd4..3c4818f65dade1a6335d57105f2456bec484793f 100644 (file)
@@ -304,6 +304,7 @@ check-stage$(1)-T-$(2)-H-$(3)-exec: \
        check-stage$(1)-T-$(2)-H-$(3)-pfail-exec \
     check-stage$(1)-T-$(2)-H-$(3)-rpass-valgrind-exec \
     check-stage$(1)-T-$(2)-H-$(3)-rpass-full-exec \
+    check-stage$(1)-T-$(2)-H-$(3)-rfail-full-exec \
        check-stage$(1)-T-$(2)-H-$(3)-cfail-full-exec \
        check-stage$(1)-T-$(2)-H-$(3)-rmake-exec \
        check-stage$(1)-T-$(2)-H-$(3)-rustdocck-exec \
@@ -345,6 +346,7 @@ check-stage$(1)-T-$(2)-H-$(3)-pretty-exec: \
     check-stage$(1)-T-$(2)-H-$(3)-pretty-rpass-valgrind-exec \
        check-stage$(1)-T-$(2)-H-$(3)-pretty-rpass-full-exec \
        check-stage$(1)-T-$(2)-H-$(3)-pretty-rfail-exec \
+       check-stage$(1)-T-$(2)-H-$(3)-pretty-rfail-full-exec \
        check-stage$(1)-T-$(2)-H-$(3)-pretty-bench-exec \
        check-stage$(1)-T-$(2)-H-$(3)-pretty-pretty-exec
 
@@ -464,6 +466,7 @@ $(foreach host,$(CFG_HOST), \
 RPASS_RS := $(wildcard $(S)src/test/run-pass/*.rs)
 RPASS_VALGRIND_RS := $(wildcard $(S)src/test/run-pass-valgrind/*.rs)
 RPASS_FULL_RS := $(wildcard $(S)src/test/run-pass-fulldeps/*.rs)
+RFAIL_FULL_RS := $(wildcard $(S)src/test/run-fail-fulldeps/*.rs)
 CFAIL_FULL_RS := $(wildcard $(S)src/test/compile-fail-fulldeps/*.rs)
 RFAIL_RS := $(wildcard $(S)src/test/run-fail/*.rs)
 CFAIL_RS := $(wildcard $(S)src/test/compile-fail/*.rs)
@@ -483,6 +486,7 @@ PERF_RS := $(wildcard $(S)src/test/bench/*.rs)
 RPASS_TESTS := $(RPASS_RS)
 RPASS_VALGRIND_TESTS := $(RPASS_VALGRIND_RS)
 RPASS_FULL_TESTS := $(RPASS_FULL_RS)
+RFAIL_FULL_TESTS := $(RFAIL_FULL_RS)
 CFAIL_FULL_TESTS := $(CFAIL_FULL_RS)
 RFAIL_TESTS := $(RFAIL_RS)
 CFAIL_TESTS := $(CFAIL_RS)
@@ -510,6 +514,11 @@ CTEST_BUILD_BASE_rpass-full = run-pass-fulldeps
 CTEST_MODE_rpass-full = run-pass
 CTEST_RUNTOOL_rpass-full = $(CTEST_RUNTOOL)
 
+CTEST_SRC_BASE_rfail-full = run-fail-fulldeps
+CTEST_BUILD_BASE_rfail-full = run-fail-fulldeps
+CTEST_MODE_rfail-full = run-fail
+CTEST_RUNTOOL_rfail-full = $(CTEST_RUNTOOL)
+
 CTEST_SRC_BASE_cfail-full = compile-fail-fulldeps
 CTEST_BUILD_BASE_cfail-full = compile-fail-fulldeps
 CTEST_MODE_cfail-full = compile-fail
@@ -661,6 +670,7 @@ endif
 CTEST_DEPS_rpass_$(1)-T-$(2)-H-$(3) = $$(RPASS_TESTS)
 CTEST_DEPS_rpass-valgrind_$(1)-T-$(2)-H-$(3) = $$(RPASS_VALGRIND_TESTS)
 CTEST_DEPS_rpass-full_$(1)-T-$(2)-H-$(3) = $$(RPASS_FULL_TESTS) $$(CSREQ$(1)_T_$(3)_H_$(3)) $$(SREQ$(1)_T_$(2)_H_$(3))
+CTEST_DEPS_rfail-full_$(1)-T-$(2)-H-$(3) = $$(RFAIL_FULL_TESTS) $$(CSREQ$(1)_T_$(3)_H_$(3)) $$(SREQ$(1)_T_$(2)_H_$(3))
 CTEST_DEPS_cfail-full_$(1)-T-$(2)-H-$(3) = $$(CFAIL_FULL_TESTS) $$(CSREQ$(1)_T_$(3)_H_$(3)) $$(SREQ$(1)_T_$(2)_H_$(3))
 CTEST_DEPS_rfail_$(1)-T-$(2)-H-$(3) = $$(RFAIL_TESTS)
 CTEST_DEPS_cfail_$(1)-T-$(2)-H-$(3) = $$(CFAIL_TESTS)
@@ -737,7 +747,7 @@ endif
 
 endef
 
-CTEST_NAMES = rpass rpass-valgrind rpass-full cfail-full rfail cfail pfail \
+CTEST_NAMES = rpass rpass-valgrind rpass-full rfail-full cfail-full rfail cfail pfail \
        bench perf debuginfo-gdb debuginfo-lldb codegen rustdocck
 
 $(foreach host,$(CFG_HOST), \
@@ -746,22 +756,26 @@ $(foreach host,$(CFG_HOST), \
    $(eval $(foreach name,$(CTEST_NAMES), \
    $(eval $(call DEF_RUN_COMPILETEST,$(stage),$(target),$(host),$(name))))))))))
 
-PRETTY_NAMES = pretty-rpass pretty-rpass-valgrind pretty-rpass-full pretty-rfail pretty-bench pretty-pretty
+PRETTY_NAMES = pretty-rpass pretty-rpass-valgrind pretty-rpass-full pretty-rfail-full pretty-rfail \
+    pretty-bench pretty-pretty
 PRETTY_DEPS_pretty-rpass = $(RPASS_TESTS)
 PRETTY_DEPS_pretty-rpass-valgrind = $(RPASS_VALGRIND_TESTS)
 PRETTY_DEPS_pretty-rpass-full = $(RPASS_FULL_TESTS)
+PRETTY_DEPS_pretty-rfail-full = $(RFAIL_FULL_TESTS)
 PRETTY_DEPS_pretty-rfail = $(RFAIL_TESTS)
 PRETTY_DEPS_pretty-bench = $(BENCH_TESTS)
 PRETTY_DEPS_pretty-pretty = $(PRETTY_TESTS)
 PRETTY_DIRNAME_pretty-rpass = run-pass
 PRETTY_DIRNAME_pretty-rpass-valgrind = run-pass-valgrind
 PRETTY_DIRNAME_pretty-rpass-full = run-pass-fulldeps
+PRETTY_DIRNAME_pretty-rfail-full = run-fail-fulldeps
 PRETTY_DIRNAME_pretty-rfail = run-fail
 PRETTY_DIRNAME_pretty-bench = bench
 PRETTY_DIRNAME_pretty-pretty = pretty
 
 define DEF_PRETTY_FULLDEPS
 PRETTY_DEPS$(1)_T_$(2)_H_$(3)_pretty-rpass-full = $$(CSREQ$(1)_T_$(3)_H_$(3))
+PRETTY_DEPS$(1)_T_$(2)_H_$(3)_pretty-rfail-full = $$(CSREQ$(1)_T_$(3)_H_$(3))
 endef
 
 $(foreach host,$(CFG_HOST), \
@@ -901,6 +915,7 @@ TEST_GROUPS = \
        rpass \
     rpass-valgrind \
        rpass-full \
+       rfail-full \
        cfail-full \
        rfail \
        cfail \
@@ -918,6 +933,7 @@ TEST_GROUPS = \
        pretty-rpass \
     pretty-rpass-valgrind \
        pretty-rpass-full \
+       pretty-rfail-full \
        pretty-rfail \
        pretty-bench \
        pretty-pretty \
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 7c9cca90edda78d1acfa3a95e9cc62e5c896a8a9..a71f8cf4250a6465f5ce6a0799f409a509032f30 100644 (file)
@@ -84,7 +84,7 @@ that does _not_ occur in the set of [keywords](#keywords).
 ## Comments
 
 Comments in Rust code follow the general C++ style of line (`//`) and
-block-comment (`/* ... */`) forms. Nested block comments are supported.
+block (`/* ... */`) comment forms. Nested block comments are supported.
 
 Line comments beginning with exactly _three_ slashes (`///`), and block
 comments beginning with exactly one repeated asterisk in the block-open
@@ -192,13 +192,13 @@ which must be _escaped_ by a preceding `U+005C` character (`\`).
 
 A _string literal_ is a sequence of any Unicode characters enclosed within two
 `U+0022` (double-quote) characters, with the exception of `U+0022` itself,
-which must be _escaped_ by a preceding `U+005C` character (`\`), or a _raw
-string literal_.
+which must be _escaped_ by a preceding `U+005C` character (`\`).
 
-A multi-line string literal may be defined by terminating each line with a
-`U+005C` character (`\`) immediately before the newline. This causes the
-`U+005C` character, the newline, and all whitespace at the beginning of the
-next line to be ignored.
+Line-break characters are allowed in string literals. Normally they represent
+themselves (i.e. no translation), but as a special exception, when a `U+005C`
+character (`\`) occurs immediately before the newline, the `U+005C` character,
+the newline, and all whitespace at the beginning of the next line are ignored.
+Thus `a` and `b` are equal:
 
 ```rust
 let a = "foobar";
@@ -366,11 +366,19 @@ A _floating-point literal_ has one of two forms:
   optionally followed by another decimal literal, with an optional _exponent_.
 * A single _decimal literal_ followed by an _exponent_.
 
-By default, a floating-point literal has a generic type, and, like integer
-literals, the type must be uniquely determined from the context. There are two valid
+Like integer literals, a floating-point literal may be followed by a
+suffix, so long as the pre-suffix part does not end with `U+002E` (`.`).
+The suffix forcibly sets the type of the literal. There are two valid
 _floating-point suffixes_, `f32` and `f64` (the 32-bit and 64-bit floating point
 types), which explicitly determine the type of the literal.
 
+The type of an _unsuffixed_ floating-point literal is determined by type
+inference. If a floating-point type can be _uniquely_ determined from the
+surrounding program context, the unsuffixed floating-point literal has that type.
+If the program context underconstrains the type, it defaults to double-precision `f64`;
+if the program context overconstrains the type, it is considered a static type
+error.
+
 Examples of floating-point literals of various forms:
 
 ```
@@ -2127,7 +2135,10 @@ The currently implemented features of the reference compiler are:
           semantics are likely to change, so this macro usage must be opted
           into.
 
-* `associated_types` - Allows type aliases in traits. Experimental.
+* `associated_consts` - Allows constants to be defined in `impl` and `trait`
+                        blocks, so that they can be associated with a type or
+                        trait in a similar manner to methods and associated
+                        types.
 
 * `box_patterns` - Allows `box` patterns, the exact semantics of which
                    is subject to change.
index 6967532a44735199cbd29c9d532de914ce51b8b4..d547451fccec2e551193a062e906c5da3de7971d 100644 (file)
@@ -32,6 +32,13 @@ $ mkdir src
 $ mv main.rs src/main.rs
 ```
 
+Note that since we're creating an executable, we used `main.rs`. If we
+want to make a library instead, we should use `lib.rs`.
+Custom file locations for the entry point can be specified
+with a [`[[lib]]` or `[[bin]]`][crates-custom] key in the TOML file described below.
+
+[crates-custom]: http://doc.crates.io/manifest.html#configuring-a-target
+
 Cargo expects your source files to live inside a `src` directory. That leaves
 the top level for other things, like READMEs, license information, and anything
 not related to your code. Cargo helps us keep our projects nice and tidy. A
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 28d815c4eb735fdb5ba8b78b5b400051f5082c30..6170bdb86eaa3a7843dc89af9a47260395cdb778 100644 (file)
@@ -1,8 +1,9 @@
 % Vectors
 
 A â€˜vector’ is a dynamic or â€˜growable’ array, implemented as the standard
-library type [`Vec<T>`][vec]. That `<T>` is a [generic][generic], meaning we
-can have vectors of any type. Vectors always allocate their data on the heap.
+library type [`Vec<T>`][vec]. The `T` means that we can have vectors
+of any type (see the chapter on [generics][generic] for more).
+Vectors always allocate their data on the heap.
 You can create them with the `vec!` macro:
 
 ```rust
index 6c3fd186cd423bdea36260cc459fe361602eb0e2..27e15bc2f0eeaa044a8e7a8dd301e232c28e3b3e 100644 (file)
@@ -505,10 +505,20 @@ trait_items
 ;
 
 trait_item
-: trait_type
+: trait_const
+| trait_type
 | trait_method
 ;
 
+trait_const
+: maybe_outer_attrs CONST ident maybe_const_default ';' { $$ = mk_node("ConstTraitItem", 3, $1, $3, $4); }
+;
+
+maybe_const_default
+: '=' expr { $$ = mk_node("ConstDefault", 1, $2); }
+| %empty   { $$ = mk_none(); }
+;
+
 trait_type
 : maybe_outer_attrs TYPE ty_param ';' { $$ = mk_node("TypeTraitItem", 2, $1, $3); }
 ;
@@ -611,7 +621,16 @@ impl_items
 impl_item
 : impl_method
 | item_macro
-| trait_type
+| impl_const
+| impl_type
+;
+
+impl_const
+: attrs_and_vis item_const { $$ = mk_node("ImplConst", 1, $1, $2); }
+;
+
+impl_type
+: attrs_and_vis TYPE ident generic_params '=' ty_sum ';'  { $$ = mk_node("ImplType", 4, $1, $3, $4, $6); }
 ;
 
 item_fn
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 a37a26ef22ac3af2852ebeb9c106fa799a3445cc..be6405dc85a1498fcbffba5194c8397c1754ebd9 100644 (file)
@@ -951,12 +951,13 @@ fn deref<'b>(&'b self) -> &'b String {
 /// # #![feature(collections)]
 /// use std::string::as_string;
 ///
-/// fn string_consumer(s: String) {
-///     assert_eq!(s, "foo".to_string());
+/// // Let's pretend we have a function that requires `&String`
+/// fn string_consumer(s: &String) {
+///     assert_eq!(s, "foo");
 /// }
 ///
-/// let string = as_string("foo").clone();
-/// string_consumer(string);
+/// // Provide a `&String` from a `&str` without allocating
+/// string_consumer(&as_string("foo"));
 /// ```
 #[unstable(feature = "collections")]
 pub fn as_string<'a>(x: &'a str) -> DerefString<'a> {
index c8a8498d2f92923f5f7fd0baefd8b08cc7b83fbb..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;
 
@@ -536,7 +538,7 @@ pub fn insert(&mut self, index: usize, element: T) {
     ///
     /// # Panics
     ///
-    /// Panics if `i` is out of bounds.
+    /// Panics if `index` is out of bounds.
     ///
     /// # Examples
     ///
@@ -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) {
@@ -1915,6 +1920,22 @@ fn drop(&mut self) {
 }
 
 /// Converts a slice to a wrapper type providing a `&Vec<T>` reference.
+///
+/// # Examples
+///
+/// ```
+/// # #![feature(collections)]
+/// use std::vec::as_vec;
+///
+/// // Let's pretend we have a function that requires `&Vec<i32>`
+/// fn vec_consumer(s: &Vec<i32>) {
+///     assert_eq!(s, &[1, 2, 3]);
+/// }
+///
+/// // Provide a `&Vec<i32>` from a `&[i32]` without allocating
+/// let values = [1, 2, 3];
+/// vec_consumer(&as_vec(&values));
+/// ```
 #[unstable(feature = "collections")]
 pub fn as_vec<'a, T>(x: &'a [T]) -> DerefVec<'a, T> {
     unsafe {
@@ -1958,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 {
@@ -1984,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 d9cda58d9ebedd6e364bffe388e4c5979b43c8d6..d3de77a9241e3f7dbab05cbe77f2b89ccba5c647 100644 (file)
@@ -83,10 +83,8 @@ pub trait Into<T>: Sized {
 /// `String` implements `From<&str>`:
 ///
 /// ```
-/// let s = "hello";
 /// let string = "hello".to_string();
-///
-/// let other_string: String = From::from(s);
+/// let other_string = String::from("hello");
 ///
 /// assert_eq!(string, other_string);
 /// ```
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..d6885763b1c94be0a341926060464364ad99a7f8 100644 (file)
     /// 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 +565,5 @@ 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;
 }
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 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 1e96d761d405a948e3db12b02f4f45f18ca27c19..38e66c5a3d6a2460e4e474a41f7e0c78a0ffb287 100644 (file)
@@ -625,6 +625,36 @@ fn into_iter(self) -> IterMut<'a, T> {
     }
 }
 
+#[inline(always)]
+fn size_from_ptr<T>(_: *const T) -> usize {
+    mem::size_of::<T>()
+}
+
+
+// Use macro to be generic over const/mut
+macro_rules! slice_offset {
+    ($ptr:expr, $by:expr) => {{
+        let ptr = $ptr;
+        if size_from_ptr(ptr) == 0 {
+            transmute(ptr as usize + $by)
+        } else {
+            ptr.offset($by)
+        }
+    }};
+}
+
+macro_rules! slice_ref {
+    ($ptr:expr) => {{
+        let ptr = $ptr;
+        if size_from_ptr(ptr) == 0 {
+            // Use a non-null pointer value
+            &mut *(1 as *mut _)
+        } else {
+            transmute(ptr)
+        }
+    }};
+}
+
 // The shared definition of the `Iter` and `IterMut` iterators
 macro_rules! iterator {
     (struct $name:ident -> $ptr:ty, $elem:ty) => {
@@ -641,20 +671,9 @@ fn next(&mut self) -> Option<$elem> {
                     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 = transmute(self.ptr as usize + 1);
-
-                            // Use a non-null pointer value
-                            Some(&mut *(1 as *mut _))
-                        } else {
-                            let old = self.ptr;
-                            self.ptr = self.ptr.offset(1);
-
-                            Some(transmute(old))
-                        }
+                        let old = self.ptr;
+                        self.ptr = slice_offset!(self.ptr, 1);
+                        Some(slice_ref!(old))
                     }
                 }
             }
@@ -666,6 +685,22 @@ fn size_hint(&self) -> (usize, Option<usize>) {
                 let exact = diff / (if size == 0 {1} else {size});
                 (exact, Some(exact))
             }
+
+            #[inline]
+            fn count(self) -> usize {
+                self.size_hint().0
+            }
+
+            #[inline]
+            fn nth(&mut self, n: usize) -> Option<$elem> {
+                // Call helper method. Can't put the definition here because mut versus const.
+                self.iter_nth(n)
+            }
+
+            #[inline]
+            fn last(mut self) -> Option<$elem> {
+                self.next_back()
+            }
         }
 
         #[stable(feature = "rust1", since = "1.0.0")]
@@ -679,17 +714,8 @@ fn next_back(&mut self) -> Option<$elem> {
                     if self.end == self.ptr {
                         None
                     } else {
-                        if mem::size_of::<T>() == 0 {
-                            // See above for why 'ptr.offset' isn't used
-                            self.end = transmute(self.end as usize - 1);
-
-                            // Use a non-null pointer value
-                            Some(&mut *(1 as *mut _))
-                        } else {
-                            self.end = self.end.offset(-1);
-
-                            Some(transmute(self.end))
-                        }
+                        self.end = slice_offset!(self.end, -1);
+                        Some(slice_ref!(self.end))
                     }
                 }
             }
@@ -785,6 +811,20 @@ impl<'a, T> Iter<'a, T> {
     pub fn as_slice(&self) -> &'a [T] {
         make_slice!(T => &'a [T]: self.ptr, self.end)
     }
+
+    // Helper function for Iter::nth
+    fn iter_nth(&mut self, n: usize) -> Option<&'a T> {
+        match self.as_slice().get(n) {
+            Some(elem_ref) => unsafe {
+                self.ptr = slice_offset!(elem_ref as *const _, 1);
+                Some(slice_ref!(elem_ref))
+            },
+            None => {
+                self.ptr = self.end;
+                None
+            }
+        }
+    }
 }
 
 iterator!{struct Iter -> *const T, &'a T}
@@ -914,6 +954,20 @@ impl<'a, T> IterMut<'a, T> {
     pub fn into_slice(self) -> &'a mut [T] {
         make_mut_slice!(T => &'a mut [T]: self.ptr, self.end)
     }
+
+    // Helper function for IterMut::nth
+    fn iter_nth(&mut self, n: usize) -> Option<&'a mut T> {
+        match make_mut_slice!(T => &'a mut [T]: self.ptr, self.end).get_mut(n) {
+            Some(elem_ref) => unsafe {
+                self.ptr = slice_offset!(elem_ref as *mut _, 1);
+                Some(slice_ref!(elem_ref))
+            },
+            None => {
+                self.ptr = self.end;
+                None
+            }
+        }
+    }
 }
 
 iterator!{struct IterMut -> *mut T, &'a mut T}
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 fe73b3b44079503544c6dead2a334b86f0877f99..7c884a73ce05bd4a83e86cc29cb3baef47ad6ba1 100644 (file)
@@ -82,3 +82,34 @@ macro_rules! test {
     test!([1u8,2,3]);
     test!([(),(),()]);
 }
+
+#[test]
+fn test_iterator_nth() {
+    let v: &[_] = &[0, 1, 2, 3, 4];
+    for i in 0..v.len() {
+        assert_eq!(v.iter().nth(i).unwrap(), &v[i]);
+    }
+    assert_eq!(v.iter().nth(v.len()), None);
+
+    let mut iter = v.iter();
+    assert_eq!(iter.nth(2).unwrap(), &v[2]);
+    assert_eq!(iter.nth(1).unwrap(), &v[4]);
+}
+
+#[test]
+fn test_iterator_last() {
+    let v: &[_] = &[0, 1, 2, 3, 4];
+    assert_eq!(v.iter().last().unwrap(), &4);
+    assert_eq!(v[..1].iter().last().unwrap(), &0);
+}
+
+#[test]
+fn test_iterator_count() {
+    let v: &[_] = &[0, 1, 2, 3, 4];
+    assert_eq!(v.iter().count(), 5);
+
+    let mut iter2 = v.iter();
+    iter2.next();
+    iter2.next();
+    assert_eq!(iter2.count(), 3);
+}
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 182405a640dbcfb2d506607c6c6194f355c5c06e..8b43f9ada9a3385a6d00554019d608675278195c 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
@@ -462,7 +481,6 @@ enum Method { GET, POST }
     E0010,
     E0011,
     E0012,
-    E0013,
     E0014,
     E0016,
     E0017,
index 6e8f515c7c2117474b27030295154f625aedfa29..b0b1b4df6e30699ef649fcc99a43556503c64b34 100644 (file)
@@ -34,7 +34,6 @@
 #![feature(quote)]
 #![feature(rustc_diagnostic_macros)]
 #![feature(rustc_private)]
-#![feature(unsafe_destructor)]
 #![feature(staged_api)]
 #![feature(std_misc)]
 #![feature(path_ext)]
index 099a280c4b146b31fb05d41ba48871f7ef6ea946..12112fd45ebe9b2d0911992f79cc1e7bd4c0b38e 100644 (file)
@@ -665,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 d528e38d341cfe099a80acf0f37d039e9bc3c107..93056d949dbb07bfde8188d0823058ae0899c788 100644 (file)
@@ -175,6 +175,13 @@ pub fn get_provided_trait_methods<'tcx>(tcx: &ty::ctxt<'tcx>,
     decoder::get_provided_trait_methods(cstore.intr.clone(), &*cdata, def.node, tcx)
 }
 
+pub fn get_associated_consts<'tcx>(tcx: &ty::ctxt<'tcx>, def: ast::DefId)
+                                   -> Vec<Rc<ty::AssociatedConst<'tcx>>> {
+    let cstore = &tcx.sess.cstore;
+    let cdata = cstore.get_crate_data(def.krate);
+    decoder::get_associated_consts(cstore.intr.clone(), &*cdata, def.node, tcx)
+}
+
 pub fn get_type_name_if_impl(cstore: &cstore::CStore, def: ast::DefId)
                           -> Option<ast::Name> {
     let cdata = cstore.get_crate_data(def.krate);
index cbd542567709c13f9b114d9949b1fc62784de9d3..f03a2d342d7be0d567562ab380070d4f4d3ffc48 100644 (file)
@@ -305,7 +305,25 @@ fn item_to_def_like(item: rbml::Doc, did: ast::DefId, cnum: ast::CrateNum)
     -> DefLike {
     let fam = item_family(item);
     match fam {
-        Constant  => DlDef(def::DefConst(did)),
+        Constant  => {
+            // Check whether we have an associated const item.
+            if item_sort(item) == Some('C') {
+                // Check whether the associated const is from a trait or impl.
+                // See the comment for methods below.
+                let provenance = if reader::maybe_get_doc(
+                      item, tag_item_trait_parent_sort).is_some() {
+                    def::FromTrait(item_reqd_and_translated_parent_item(cnum,
+                                                                        item))
+                } else {
+                    def::FromImpl(item_reqd_and_translated_parent_item(cnum,
+                                                                       item))
+                };
+                DlDef(def::DefAssociatedConst(did, provenance))
+            } else {
+                // Regular const item.
+                DlDef(def::DefConst(did))
+            }
+        }
         ImmStatic => DlDef(def::DefStatic(did, false)),
         MutStatic => DlDef(def::DefStatic(did, true)),
         Struct    => DlDef(def::DefStruct(did)),
@@ -826,6 +844,7 @@ pub fn get_impl_items(cdata: Cmd, impl_id: ast::NodeId)
                         tag_item_impl_item, |doc| {
         let def_id = item_def_id(doc, cdata);
         match item_sort(doc) {
+            Some('C') => impl_items.push(ty::ConstTraitItemId(def_id)),
             Some('r') | Some('p') => {
                 impl_items.push(ty::MethodTraitItemId(def_id))
             }
@@ -877,6 +896,18 @@ pub fn get_impl_or_trait_item<'tcx>(intr: Rc<IdentInterner>,
     let vis = item_visibility(method_doc);
 
     match item_sort(method_doc) {
+        Some('C') => {
+            let ty = doc_type(method_doc, tcx, cdata);
+            let default = get_provided_source(method_doc, cdata);
+            ty::ConstTraitItem(Rc::new(ty::AssociatedConst {
+                name: name,
+                ty: ty,
+                vis: vis,
+                def_id: def_id,
+                container: container,
+                default: default,
+            }))
+        }
         Some('r') | Some('p') => {
             let generics = doc_generics(method_doc, tcx, cdata, tag_method_ty_generics);
             let predicates = doc_predicates(method_doc, tcx, cdata, tag_method_ty_generics);
@@ -914,6 +945,7 @@ pub fn get_trait_item_def_ids(cdata: Cmd, id: ast::NodeId)
     reader::tagged_docs(item, tag_item_trait_item, |mth| {
         let def_id = item_def_id(mth, cdata);
         match item_sort(mth) {
+            Some('C') => result.push(ty::ConstTraitItemId(def_id)),
             Some('r') | Some('p') => {
                 result.push(ty::MethodTraitItemId(def_id));
             }
@@ -951,11 +983,8 @@ pub fn get_provided_trait_methods<'tcx>(intr: Rc<IdentInterner>,
                                                     cdata,
                                                     did.node,
                                                     tcx);
-            match trait_item {
-                ty::MethodTraitItem(ref method) => {
-                    result.push((*method).clone())
-                }
-                ty::TypeTraitItem(_) => {}
+            if let ty::MethodTraitItem(ref method) = trait_item {
+                result.push((*method).clone())
             }
         }
         true
@@ -964,6 +993,36 @@ pub fn get_provided_trait_methods<'tcx>(intr: Rc<IdentInterner>,
     return result;
 }
 
+pub fn get_associated_consts<'tcx>(intr: Rc<IdentInterner>,
+                                   cdata: Cmd,
+                                   id: ast::NodeId,
+                                   tcx: &ty::ctxt<'tcx>)
+                                   -> Vec<Rc<ty::AssociatedConst<'tcx>>> {
+    let data = cdata.data();
+    let item = lookup_item(id, data);
+    let mut result = Vec::new();
+
+    for &tag in &[tag_item_trait_item, tag_item_impl_item] {
+        reader::tagged_docs(item, tag, |ac_id| {
+            let did = item_def_id(ac_id, cdata);
+            let ac_doc = lookup_item(did.node, data);
+
+            if item_sort(ac_doc) == Some('C') {
+                let trait_item = get_impl_or_trait_item(intr.clone(),
+                                                        cdata,
+                                                        did.node,
+                                                        tcx);
+                if let ty::ConstTraitItem(ref ac) = trait_item {
+                    result.push((*ac).clone())
+                }
+            }
+            true
+        });
+    }
+
+    return result;
+}
+
 pub fn get_type_name_if_impl(cdata: Cmd,
                              node_id: ast::NodeId) -> Option<ast::Name> {
     let item = lookup_item(node_id, cdata.data());
index 29270bd6c624bac0aa02705a1526f09742da3be3..bcbb350fc34ee7b12489c9d0ee23dd771865d7a1 100644 (file)
@@ -378,14 +378,11 @@ fn encode_reexported_static_base_methods(ecx: &EncodeContext,
                     let impl_item = ty::impl_or_trait_item(
                         ecx.tcx,
                         method_did.def_id());
-                    match impl_item {
-                        ty::MethodTraitItem(ref m) => {
-                            encode_reexported_static_method(rbml_w,
-                                                            exp,
-                                                            m.def_id,
-                                                            m.name);
-                        }
-                        ty::TypeTraitItem(_) => {}
+                    if let ty::MethodTraitItem(ref m) = impl_item {
+                        encode_reexported_static_method(rbml_w,
+                                                        exp,
+                                                        m.def_id,
+                                                        m.name);
                     }
                 }
             }
@@ -802,6 +799,43 @@ fn encode_method_ty_fields<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
     encode_provided_source(rbml_w, method_ty.provided_source);
 }
 
+fn encode_info_for_associated_const(ecx: &EncodeContext,
+                                    rbml_w: &mut Encoder,
+                                    associated_const: &ty::AssociatedConst,
+                                    impl_path: PathElems,
+                                    parent_id: NodeId,
+                                    impl_item_opt: Option<&ast::ImplItem>) {
+    debug!("encode_info_for_associated_const({:?},{:?})",
+           associated_const.def_id,
+           token::get_name(associated_const.name));
+
+    rbml_w.start_tag(tag_items_data_item);
+
+    encode_def_id(rbml_w, associated_const.def_id);
+    encode_name(rbml_w, associated_const.name);
+    encode_visibility(rbml_w, associated_const.vis);
+    encode_family(rbml_w, 'C');
+    encode_provided_source(rbml_w, associated_const.default);
+
+    encode_parent_item(rbml_w, local_def(parent_id));
+    encode_item_sort(rbml_w, 'C');
+
+    encode_bounds_and_type_for_item(rbml_w, ecx, associated_const.def_id.local_id());
+
+    let stab = stability::lookup(ecx.tcx, associated_const.def_id);
+    encode_stability(rbml_w, stab);
+
+    let elem = ast_map::PathName(associated_const.name);
+    encode_path(rbml_w, impl_path.chain(Some(elem).into_iter()));
+
+    if let Some(ii) = impl_item_opt {
+        encode_attributes(rbml_w, &ii.attrs);
+        encode_inlined_item(ecx, rbml_w, IIImplItemRef(local_def(parent_id), ii));
+    }
+
+    rbml_w.end_tag();
+}
+
 fn encode_info_for_method<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
                                     rbml_w: &mut Encoder,
                                     m: &ty::Method<'tcx>,
@@ -1195,6 +1229,10 @@ fn add_to_index(item: &ast::Item, rbml_w: &mut Encoder,
         for &item_def_id in items {
             rbml_w.start_tag(tag_item_impl_item);
             match item_def_id {
+                ty::ConstTraitItemId(item_def_id) => {
+                    encode_def_id(rbml_w, item_def_id);
+                    encode_item_sort(rbml_w, 'C');
+                }
                 ty::MethodTraitItemId(item_def_id) => {
                     encode_def_id(rbml_w, item_def_id);
                     encode_item_sort(rbml_w, 'r');
@@ -1232,6 +1270,14 @@ fn add_to_index(item: &ast::Item, rbml_w: &mut Encoder,
             });
 
             match ty::impl_or_trait_item(tcx, trait_item_def_id.def_id()) {
+                ty::ConstTraitItem(ref associated_const) => {
+                    encode_info_for_associated_const(ecx,
+                                                     rbml_w,
+                                                     &*associated_const,
+                                                     path.clone(),
+                                                     item.id,
+                                                     ast_item)
+                }
                 ty::MethodTraitItem(ref method_type) => {
                     encode_info_for_method(ecx,
                                            rbml_w,
@@ -1276,6 +1322,10 @@ fn add_to_index(item: &ast::Item, rbml_w: &mut Encoder,
         for &method_def_id in &*ty::trait_item_def_ids(tcx, def_id) {
             rbml_w.start_tag(tag_item_trait_item);
             match method_def_id {
+                ty::ConstTraitItemId(const_def_id) => {
+                    encode_def_id(rbml_w, const_def_id);
+                    encode_item_sort(rbml_w, 'C');
+                }
                 ty::MethodTraitItemId(method_def_id) => {
                     encode_def_id(rbml_w, method_def_id);
                     encode_item_sort(rbml_w, 'r');
@@ -1321,6 +1371,25 @@ fn add_to_index(item: &ast::Item, rbml_w: &mut Encoder,
                 ty::impl_or_trait_item(tcx, item_def_id.def_id());
             let is_nonstatic_method;
             match trait_item_type {
+                ty::ConstTraitItem(associated_const) => {
+                    encode_name(rbml_w, associated_const.name);
+                    encode_def_id(rbml_w, associated_const.def_id);
+                    encode_visibility(rbml_w, associated_const.vis);
+
+                    encode_provided_source(rbml_w, associated_const.default);
+
+                    let elem = ast_map::PathName(associated_const.name);
+                    encode_path(rbml_w,
+                                path.clone().chain(Some(elem).into_iter()));
+
+                    encode_item_sort(rbml_w, 'C');
+                    encode_family(rbml_w, 'C');
+
+                    encode_bounds_and_type_for_item(rbml_w, ecx,
+                                                    associated_const.def_id.local_id());
+
+                    is_nonstatic_method = false;
+                }
                 ty::MethodTraitItem(method_ty) => {
                     let method_def_id = item_def_id.def_id();
 
@@ -1365,6 +1434,10 @@ fn add_to_index(item: &ast::Item, rbml_w: &mut Encoder,
             let trait_item = &*ms[i];
             encode_attributes(rbml_w, &trait_item.attrs);
             match trait_item.node {
+                ast::ConstTraitItem(_, _) => {
+                    encode_inlined_item(ecx, rbml_w,
+                                        IITraitItemRef(def_id, trait_item));
+                }
                 ast::MethodTraitItem(ref sig, ref body) => {
                     // If this is a static method, we've already
                     // encoded this.
@@ -1384,9 +1457,7 @@ fn add_to_index(item: &ast::Item, rbml_w: &mut Encoder,
                     encode_method_argument_names(rbml_w, &sig.decl);
                 }
 
-                ast::TypeTraitItem(..) => {
-                    encode_item_sort(rbml_w, 't');
-                }
+                ast::TypeTraitItem(..) => {}
             }
 
             rbml_w.end_tag();
index cc42bd9b08b80f85120358bb68c044bc819e9e3a..3ef22ba8158b0ce69f93e622627cfcc7591cd59e 100644 (file)
@@ -465,6 +465,9 @@ fn tr(&self, dcx: &DecodeContext) -> def::Def {
           def::DefForeignMod(did) => { def::DefForeignMod(did.tr(dcx)) }
           def::DefStatic(did, m) => { def::DefStatic(did.tr(dcx), m) }
           def::DefConst(did) => { def::DefConst(did.tr(dcx)) }
+          def::DefAssociatedConst(did, p) => {
+              def::DefAssociatedConst(did.tr(dcx), p.map(|did2| did2.tr(dcx)))
+          }
           def::DefLocal(nid) => { def::DefLocal(dcx.tr_id(nid)) }
           def::DefVariant(e_did, v_did, is_s) => {
             def::DefVariant(e_did.tr(dcx), v_did.tr(dcx), is_s)
index 359a1a486c9da7cabb5666f45cbc71de2ba607e5..a7950a701f8c4fce0c96045d6ca81dcfa2c24db2 100644 (file)
@@ -105,6 +105,7 @@ fn pat(&mut self, pat: &ast::Pat, pred: CFGIndex) -> CFGIndex {
         match pat.node {
             ast::PatIdent(_, _, None) |
             ast::PatEnum(_, None) |
+            ast::PatQPath(..) |
             ast::PatLit(..) |
             ast::PatRange(..) |
             ast::PatWild(_) => {
index ee9d1e015539e337a18a19ca066d6ddb197b2610..80326229618c23d05a28312c194c8506cc6675a6 100644 (file)
@@ -223,6 +223,28 @@ fn visit_item(&mut self, i: &ast::Item) {
         }
     }
 
+    fn visit_trait_item(&mut self, t: &'v ast::TraitItem) {
+        match t.node {
+            ast::ConstTraitItem(_, ref default) => {
+                if let Some(ref expr) = *default {
+                    self.global_expr(Mode::Const, &*expr);
+                } else {
+                    visit::walk_trait_item(self, t);
+                }
+            }
+            _ => self.with_mode(Mode::Var, |v| visit::walk_trait_item(v, t)),
+        }
+    }
+
+    fn visit_impl_item(&mut self, i: &'v ast::ImplItem) {
+        match i.node {
+            ast::ConstImplItem(_, ref expr) => {
+                self.global_expr(Mode::Const, &*expr);
+            }
+            _ => self.with_mode(Mode::Var, |v| visit::walk_impl_item(v, i)),
+        }
+    }
+
     fn visit_fn(&mut self,
                 fk: visit::FnKind<'v>,
                 fd: &'v ast::FnDecl,
@@ -468,13 +490,16 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>,
                         Mode::Var => v.add_qualif(NOT_CONST)
                     }
                 }
-                Some(def::DefConst(did)) => {
-                    if let Some(expr) = const_eval::lookup_const_by_id(v.tcx, did) {
+                Some(def::DefConst(did)) |
+                Some(def::DefAssociatedConst(did, _)) => {
+                    if let Some(expr) = const_eval::lookup_const_by_id(v.tcx, did,
+                                                                       Some(e.id)) {
                         let inner = v.global_expr(Mode::Const, expr);
                         v.add_qualif(inner);
                     } else {
-                        v.tcx.sess.span_bug(e.span, "DefConst doesn't point \
-                                                     to an ItemConst");
+                        v.tcx.sess.span_bug(e.span,
+                                            "DefConst or DefAssociatedConst \
+                                             doesn't point to a constant");
                     }
                 }
                 def => {
index 912854a6d7dfbb7470ece68ce8f483da1eefdc0c..a5ea3629abc84ad8fcce386d44764463b80bbd74 100644 (file)
@@ -439,10 +439,11 @@ fn visit_id(&mut self, node_id: NodeId) {
 impl<'a, 'tcx> Folder for StaticInliner<'a, 'tcx> {
     fn fold_pat(&mut self, pat: P<Pat>) -> P<Pat> {
         return match pat.node {
-            ast::PatIdent(..) | ast::PatEnum(..) => {
+            ast::PatIdent(..) | ast::PatEnum(..) | ast::PatQPath(..) => {
                 let def = self.tcx.def_map.borrow().get(&pat.id).map(|d| d.full_def());
                 match def {
-                    Some(DefConst(did)) => match lookup_const_by_id(self.tcx, did) {
+                    Some(DefAssociatedConst(did, _)) |
+                    Some(DefConst(did)) => match lookup_const_by_id(self.tcx, did, Some(pat.id)) {
                         Some(const_expr) => {
                             const_expr_to_pat(self.tcx, const_expr, pat.span).map(|new_pat| {
 
@@ -746,7 +747,7 @@ fn pat_constructors(cx: &MatchCheckCtxt, p: &Pat,
     match pat.node {
         ast::PatIdent(..) =>
             match cx.tcx.def_map.borrow().get(&pat.id).map(|d| d.full_def()) {
-                Some(DefConst(..)) =>
+                Some(DefConst(..)) | Some(DefAssociatedConst(..)) =>
                     cx.tcx.sess.span_bug(pat.span, "const pattern should've \
                                                     been rewritten"),
                 Some(DefStruct(_)) => vec!(Single),
@@ -755,15 +756,18 @@ fn pat_constructors(cx: &MatchCheckCtxt, p: &Pat,
             },
         ast::PatEnum(..) =>
             match cx.tcx.def_map.borrow().get(&pat.id).map(|d| d.full_def()) {
-                Some(DefConst(..)) =>
+                Some(DefConst(..)) | Some(DefAssociatedConst(..)) =>
                     cx.tcx.sess.span_bug(pat.span, "const pattern should've \
                                                     been rewritten"),
                 Some(DefVariant(_, id, _)) => vec!(Variant(id)),
                 _ => vec!(Single)
             },
+        ast::PatQPath(..) =>
+            cx.tcx.sess.span_bug(pat.span, "const pattern should've \
+                                            been rewritten"),
         ast::PatStruct(..) =>
             match cx.tcx.def_map.borrow().get(&pat.id).map(|d| d.full_def()) {
-                Some(DefConst(..)) =>
+                Some(DefConst(..)) | Some(DefAssociatedConst(..)) =>
                     cx.tcx.sess.span_bug(pat.span, "const pattern should've \
                                                     been rewritten"),
                 Some(DefVariant(_, id, _)) => vec!(Variant(id)),
@@ -861,7 +865,7 @@ pub fn specialize<'a>(cx: &MatchCheckCtxt, r: &[&'a Pat],
         ast::PatIdent(_, _, _) => {
             let opt_def = cx.tcx.def_map.borrow().get(&pat_id).map(|d| d.full_def());
             match opt_def {
-                Some(DefConst(..)) =>
+                Some(DefConst(..)) | Some(DefAssociatedConst(..)) =>
                     cx.tcx.sess.span_bug(pat_span, "const pattern should've \
                                                     been rewritten"),
                 Some(DefVariant(_, id, _)) => if *constructor == Variant(id) {
@@ -876,7 +880,7 @@ pub fn specialize<'a>(cx: &MatchCheckCtxt, r: &[&'a Pat],
         ast::PatEnum(_, ref args) => {
             let def = cx.tcx.def_map.borrow().get(&pat_id).unwrap().full_def();
             match def {
-                DefConst(..) =>
+                DefConst(..) | DefAssociatedConst(..) =>
                     cx.tcx.sess.span_bug(pat_span, "const pattern should've \
                                                     been rewritten"),
                 DefVariant(_, id, _) if *constructor != Variant(id) => None,
@@ -890,11 +894,16 @@ pub fn specialize<'a>(cx: &MatchCheckCtxt, r: &[&'a Pat],
             }
         }
 
+        ast::PatQPath(_, _) => {
+            cx.tcx.sess.span_bug(pat_span, "const pattern should've \
+                                            been rewritten")
+        }
+
         ast::PatStruct(_, ref pattern_fields, _) => {
             // Is this a struct or an enum variant?
             let def = cx.tcx.def_map.borrow().get(&pat_id).unwrap().full_def();
             let class_id = match def {
-                DefConst(..) =>
+                DefConst(..) | DefAssociatedConst(..) =>
                     cx.tcx.sess.span_bug(pat_span, "const pattern should've \
                                                     been rewritten"),
                 DefVariant(_, variant_id, _) => if *constructor == Variant(variant_id) {
index b97978fc03fff33ae23e04c0cb05595511f2d380..a521c4531c9a7e50e932eb81596c520754e0618d 100644 (file)
 // recursively.
 
 use session::Session;
-use middle::def::{DefStatic, DefConst, DefMap};
+use middle::def::{DefStatic, DefConst, DefAssociatedConst, DefMap};
 
 use syntax::ast;
 use syntax::{ast_util, ast_map};
+use syntax::codemap::Span;
 use syntax::visit::Visitor;
 use syntax::visit;
 
@@ -26,8 +27,43 @@ struct CheckCrateVisitor<'a, 'ast: 'a> {
 }
 
 impl<'v, 'a, 'ast> Visitor<'v> for CheckCrateVisitor<'a, 'ast> {
-    fn visit_item(&mut self, i: &ast::Item) {
-        check_item(self, i);
+    fn visit_item(&mut self, it: &ast::Item) {
+        match it.node {
+            ast::ItemStatic(_, _, ref expr) |
+            ast::ItemConst(_, ref expr) => {
+                let mut recursion_visitor =
+                    CheckItemRecursionVisitor::new(self, &it.span);
+                recursion_visitor.visit_item(it);
+                visit::walk_expr(self, &*expr)
+            },
+            _ => visit::walk_item(self, it)
+        }
+    }
+
+    fn visit_trait_item(&mut self, ti: &ast::TraitItem) {
+        match ti.node {
+            ast::ConstTraitItem(_, ref default) => {
+                if let Some(ref expr) = *default {
+                    let mut recursion_visitor =
+                        CheckItemRecursionVisitor::new(self, &ti.span);
+                    recursion_visitor.visit_trait_item(ti);
+                    visit::walk_expr(self, &*expr)
+                }
+            }
+            _ => visit::walk_trait_item(self, ti)
+        }
+    }
+
+    fn visit_impl_item(&mut self, ii: &ast::ImplItem) {
+        match ii.node {
+            ast::ConstImplItem(_, ref expr) => {
+                let mut recursion_visitor =
+                    CheckItemRecursionVisitor::new(self, &ii.span);
+                recursion_visitor.visit_impl_item(ii);
+                visit::walk_expr(self, &*expr)
+            }
+            _ => visit::walk_impl_item(self, ii)
+        }
     }
 }
 
@@ -44,51 +80,48 @@ pub fn check_crate<'ast>(sess: &Session,
     sess.abort_if_errors();
 }
 
-fn check_item(v: &mut CheckCrateVisitor, it: &ast::Item) {
-    match it.node {
-        ast::ItemStatic(_, _, ref ex) |
-        ast::ItemConst(_, ref ex) => {
-            check_item_recursion(v.sess, v.ast_map, v.def_map, it);
-            visit::walk_expr(v, &**ex)
-        },
-        _ => visit::walk_item(v, it)
-    }
-}
-
 struct CheckItemRecursionVisitor<'a, 'ast: 'a> {
-    root_it: &'a ast::Item,
+    root_span: &'a Span,
     sess: &'a Session,
     ast_map: &'a ast_map::Map<'ast>,
     def_map: &'a DefMap,
     idstack: Vec<ast::NodeId>
 }
 
-// Make sure a const item doesn't recursively refer to itself
-// FIXME: Should use the dependency graph when it's available (#1356)
-pub fn check_item_recursion<'a>(sess: &'a Session,
-                                ast_map: &'a ast_map::Map,
-                                def_map: &'a DefMap,
-                                it: &'a ast::Item) {
-
-    let mut visitor = CheckItemRecursionVisitor {
-        root_it: it,
-        sess: sess,
-        ast_map: ast_map,
-        def_map: def_map,
-        idstack: Vec::new()
-    };
-    visitor.visit_item(it);
+impl<'a, 'ast: 'a> CheckItemRecursionVisitor<'a, 'ast> {
+    fn new(v: &CheckCrateVisitor<'a, 'ast>, span: &'a Span)
+           -> CheckItemRecursionVisitor<'a, 'ast> {
+        CheckItemRecursionVisitor {
+            root_span: span,
+            sess: v.sess,
+            ast_map: v.ast_map,
+            def_map: v.def_map,
+            idstack: Vec::new()
+        }
+    }
+    fn with_item_id_pushed<F>(&mut self, id: ast::NodeId, f: F)
+          where F: Fn(&mut Self) {
+        if self.idstack.iter().any(|x| x == &(id)) {
+            span_err!(self.sess, *self.root_span, E0265, "recursive constant");
+            return;
+        }
+        self.idstack.push(id);
+        f(self);
+        self.idstack.pop();
+    }
 }
 
 impl<'a, 'ast, 'v> Visitor<'v> for CheckItemRecursionVisitor<'a, 'ast> {
     fn visit_item(&mut self, it: &ast::Item) {
-        if self.idstack.iter().any(|x| x == &(it.id)) {
-            span_err!(self.sess, self.root_it.span, E0265, "recursive constant");
-            return;
-        }
-        self.idstack.push(it.id);
-        visit::walk_item(self, it);
-        self.idstack.pop();
+        self.with_item_id_pushed(it.id, |v| visit::walk_item(v, it));
+    }
+
+    fn visit_trait_item(&mut self, ti: &ast::TraitItem) {
+        self.with_item_id_pushed(ti.id, |v| visit::walk_trait_item(v, ti));
+    }
+
+    fn visit_impl_item(&mut self, ii: &ast::ImplItem) {
+        self.with_item_id_pushed(ii.id, |v| visit::walk_impl_item(v, ii));
     }
 
     fn visit_expr(&mut self, e: &ast::Expr) {
@@ -96,11 +129,16 @@ fn visit_expr(&mut self, e: &ast::Expr) {
             ast::ExprPath(..) => {
                 match self.def_map.borrow().get(&e.id).map(|d| d.base_def) {
                     Some(DefStatic(def_id, _)) |
+                    Some(DefAssociatedConst(def_id, _)) |
                     Some(DefConst(def_id)) if
                             ast_util::is_local(def_id) => {
                         match self.ast_map.get(def_id.node) {
                           ast_map::NodeItem(item) =>
                             self.visit_item(item),
+                          ast_map::NodeTraitItem(item) =>
+                            self.visit_trait_item(item),
+                          ast_map::NodeImplItem(item) =>
+                            self.visit_impl_item(item),
                           ast_map::NodeForeignItem(_) => {},
                           _ => {
                             span_err!(self.sess, e.span, E0266,
index 2c6ffb3281fcb4922cd173710578565938bf65d3..916874f1c51a8ec2eeb24e79ed30e60c89f1b367 100644 (file)
 use self::ErrKind::*;
 
 use metadata::csearch;
-use middle::{astencode, def};
+use middle::{astencode, def, infer, subst, traits};
 use middle::pat_util::def_to_path;
 use middle::ty::{self, Ty};
 use middle::astconv_util::ast_ty_to_prim_ty;
 use util::num::ToPrimitive;
+use util::ppaux::Repr;
 
 use syntax::ast::{self, Expr};
 use syntax::codemap::Span;
@@ -39,8 +40,9 @@
 fn lookup_const<'a>(tcx: &'a ty::ctxt, e: &Expr) -> Option<&'a Expr> {
     let opt_def = tcx.def_map.borrow().get(&e.id).map(|d| d.full_def());
     match opt_def {
-        Some(def::DefConst(def_id)) => {
-            lookup_const_by_id(tcx, def_id)
+        Some(def::DefConst(def_id)) |
+        Some(def::DefAssociatedConst(def_id, _)) => {
+            lookup_const_by_id(tcx, def_id, Some(e.id))
         }
         Some(def::DefVariant(enum_def, variant_def, _)) => {
             lookup_variant_by_id(tcx, enum_def, variant_def)
@@ -101,14 +103,46 @@ fn variant_expr<'a>(variants: &'a [P<ast::Variant>], id: ast::NodeId)
     }
 }
 
-pub fn lookup_const_by_id<'a>(tcx: &'a ty::ctxt, def_id: ast::DefId)
-                          -> Option<&'a Expr> {
+pub fn lookup_const_by_id<'a, 'tcx: 'a>(tcx: &'a ty::ctxt<'tcx>,
+                                        def_id: ast::DefId,
+                                        maybe_ref_id: Option<ast::NodeId>)
+                                        -> Option<&'tcx Expr> {
     if ast_util::is_local(def_id) {
         match tcx.map.find(def_id.node) {
             None => None,
             Some(ast_map::NodeItem(it)) => match it.node {
                 ast::ItemConst(_, ref const_expr) => {
-                    Some(&**const_expr)
+                    Some(&*const_expr)
+                }
+                _ => None
+            },
+            Some(ast_map::NodeTraitItem(ti)) => match ti.node {
+                ast::ConstTraitItem(_, _) => {
+                    match maybe_ref_id {
+                        // If we have a trait item, and we know the expression
+                        // that's the source of the obligation to resolve it,
+                        // `resolve_trait_associated_const` will select an impl
+                        // or the default.
+                        Some(ref_id) => {
+                            let trait_id = ty::trait_of_item(tcx, def_id)
+                                              .unwrap();
+                            resolve_trait_associated_const(tcx, ti, trait_id,
+                                                           ref_id)
+                        }
+                        // Technically, without knowing anything about the
+                        // expression that generates the obligation, we could
+                        // still return the default if there is one. However,
+                        // it's safer to return `None` than to return some value
+                        // that may differ from what you would get from
+                        // correctly selecting an impl.
+                        None => None
+                    }
+                }
+                _ => None
+            },
+            Some(ast_map::NodeImplItem(ii)) => match ii.node {
+                ast::ConstImplItem(_, ref expr) => {
+                    Some(&*expr)
                 }
                 _ => None
             },
@@ -122,16 +156,44 @@ pub fn lookup_const_by_id<'a>(tcx: &'a ty::ctxt, def_id: ast::DefId)
             }
             None => {}
         }
+        let mut used_ref_id = false;
         let expr_id = match csearch::maybe_get_item_ast(tcx, def_id,
             Box::new(|a, b, c, d| astencode::decode_inlined_item(a, b, c, d))) {
             csearch::FoundAst::Found(&ast::IIItem(ref item)) => match item.node {
                 ast::ItemConst(_, ref const_expr) => Some(const_expr.id),
                 _ => None
             },
+            csearch::FoundAst::Found(&ast::IITraitItem(trait_id, ref ti)) => match ti.node {
+                ast::ConstTraitItem(_, _) => {
+                    used_ref_id = true;
+                    match maybe_ref_id {
+                        // As mentioned in the comments above for in-crate
+                        // constants, we only try to find the expression for
+                        // a trait-associated const if the caller gives us
+                        // the expression that refers to it.
+                        Some(ref_id) => {
+                            resolve_trait_associated_const(tcx, ti, trait_id,
+                                                           ref_id).map(|e| e.id)
+                        }
+                        None => None
+                    }
+                }
+                _ => None
+            },
+            csearch::FoundAst::Found(&ast::IIImplItem(_, ref ii)) => match ii.node {
+                ast::ConstImplItem(_, ref expr) => Some(expr.id),
+                _ => None
+            },
             _ => None
         };
-        tcx.extern_const_statics.borrow_mut().insert(def_id,
-                                                     expr_id.unwrap_or(ast::DUMMY_NODE_ID));
+        // If we used the reference expression, particularly to choose an impl
+        // of a trait-associated const, don't cache that, because the next
+        // lookup with the same def_id may yield a different result.
+        if !used_ref_id {
+            tcx.extern_const_statics
+               .borrow_mut().insert(def_id,
+                                    expr_id.unwrap_or(ast::DUMMY_NODE_ID));
+        }
         expr_id.map(|id| tcx.map.expect_expr(id))
     }
 }
@@ -755,7 +817,35 @@ fn fromb(b: bool) -> const_val { const_int(b as i64) }
                           _ => (None, None)
                       }
                   } else {
-                      (lookup_const_by_id(tcx, def_id), None)
+                      (lookup_const_by_id(tcx, def_id, Some(e.id)), None)
+                  }
+              }
+              Some(def::DefAssociatedConst(def_id, provenance)) => {
+                  if ast_util::is_local(def_id) {
+                      match provenance {
+                          def::FromTrait(trait_id) => match tcx.map.find(def_id.node) {
+                              Some(ast_map::NodeTraitItem(ti)) => match ti.node {
+                                  ast::ConstTraitItem(ref ty, _) => {
+                                      (resolve_trait_associated_const(tcx, ti,
+                                                                      trait_id, e.id),
+                                       Some(&**ty))
+                                  }
+                                  _ => (None, None)
+                              },
+                              _ => (None, None)
+                          },
+                          def::FromImpl(_) => match tcx.map.find(def_id.node) {
+                              Some(ast_map::NodeImplItem(ii)) => match ii.node {
+                                  ast::ConstImplItem(ref ty, ref expr) => {
+                                      (Some(&**expr), Some(&**ty))
+                                  }
+                                  _ => (None, None)
+                              },
+                              _ => (None, None)
+                          },
+                      }
+                  } else {
+                      (lookup_const_by_id(tcx, def_id, Some(e.id)), None)
                   }
               }
               Some(def::DefVariant(enum_def, variant_def, _)) => {
@@ -833,6 +923,71 @@ fn fromb(b: bool) -> const_val { const_int(b as i64) }
     Ok(result)
 }
 
+fn resolve_trait_associated_const<'a, 'tcx: 'a>(tcx: &'a ty::ctxt<'tcx>,
+                                                ti: &'tcx ast::TraitItem,
+                                                trait_id: ast::DefId,
+                                                ref_id: ast::NodeId)
+                                                -> Option<&'tcx Expr>
+{
+    let rcvr_substs = ty::node_id_item_substs(tcx, ref_id).substs;
+    let subst::SeparateVecsPerParamSpace {
+        types: rcvr_type,
+        selfs: rcvr_self,
+        fns: _,
+    } = rcvr_substs.types.split();
+    let trait_substs =
+        subst::Substs::erased(subst::VecPerParamSpace::new(rcvr_type,
+                                                           rcvr_self,
+                                                           Vec::new()));
+    let trait_substs = tcx.mk_substs(trait_substs);
+    debug!("resolve_trait_associated_const: trait_substs={}",
+           trait_substs.repr(tcx));
+    let trait_ref = ty::Binder(Rc::new(ty::TraitRef { def_id: trait_id,
+                                                      substs: trait_substs }));
+
+    ty::populate_implementations_for_trait_if_necessary(tcx, trait_ref.def_id());
+    let infcx = infer::new_infer_ctxt(tcx);
+
+    let param_env = ty::empty_parameter_environment(tcx);
+    let mut selcx = traits::SelectionContext::new(&infcx, &param_env);
+    let obligation = traits::Obligation::new(traits::ObligationCause::dummy(),
+                                             trait_ref.to_poly_trait_predicate());
+    let selection = match selcx.select(&obligation) {
+        Ok(Some(vtable)) => vtable,
+        // Still ambiguous, so give up and let the caller decide whether this
+        // expression is really needed yet. Some associated constant values
+        // can't be evaluated until monomorphization is done in trans.
+        Ok(None) => {
+            return None
+        }
+        Err(e) => {
+            tcx.sess.span_bug(ti.span,
+                              &format!("Encountered error `{}` when trying \
+                                        to select an implementation for \
+                                        constant trait item reference.",
+                                       e.repr(tcx)))
+        }
+    };
+
+    match selection {
+        traits::VtableImpl(ref impl_data) => {
+            match ty::associated_consts(tcx, impl_data.impl_def_id)
+                     .iter().find(|ic| ic.name == ti.ident.name) {
+                Some(ic) => lookup_const_by_id(tcx, ic.def_id, None),
+                None => match ti.node {
+                    ast::ConstTraitItem(_, Some(ref expr)) => Some(&*expr),
+                    _ => None,
+                },
+            }
+        }
+        _ => {
+            tcx.sess.span_bug(
+                ti.span,
+                &format!("resolve_trait_associated_const: unexpected vtable type"))
+        }
+    }
+}
+
 fn cast_const<'tcx>(tcx: &ty::ctxt<'tcx>, val: const_val, ty: Ty) -> CastResult {
     macro_rules! convert_val {
         ($intermediate_ty:ty, $const_type:ident, $target_ty:ty) => {
index 2befbf9924577dd7a61905074daa235922e2a2f6..1aa2ca9115d2f61429d3d62b36921c1254138db2 100644 (file)
@@ -72,7 +72,7 @@ fn check_def_id(&mut self, def_id: ast::DefId) {
     fn lookup_and_handle_definition(&mut self, id: &ast::NodeId) {
         self.tcx.def_map.borrow().get(id).map(|def| {
             match def.full_def() {
-                def::DefConst(_) => {
+                def::DefConst(_) | def::DefAssociatedConst(..) => {
                     self.check_def_id(def.def_id())
                 }
                 _ if self.ignore_non_const_paths => (),
@@ -114,14 +114,7 @@ fn lookup_and_handle_method(&mut self, id: ast::NodeId,
                         let trait_item = ty::trait_item(self.tcx,
                                                         trait_ref.def_id,
                                                         index);
-                        match trait_item {
-                            ty::MethodTraitItem(method) => {
-                                self.check_def_id(method.def_id);
-                            }
-                            ty::TypeTraitItem(typedef) => {
-                                self.check_def_id(typedef.def_id);
-                            }
-                        }
+                        self.check_def_id(trait_item.def_id());
                     }
                 }
             }
@@ -353,6 +346,7 @@ fn visit_item(&mut self, item: &ast::Item) {
             ast::ItemTrait(_, _, _, ref trait_items) => {
                 for trait_item in trait_items {
                     match trait_item.node {
+                        ast::ConstTraitItem(_, Some(_)) |
                         ast::MethodTraitItem(_, Some(_)) => {
                             if has_allow_dead_code_or_lang_attr(&trait_item.attrs) {
                                 self.worklist.push(trait_item.id);
@@ -365,6 +359,7 @@ fn visit_item(&mut self, item: &ast::Item) {
             ast::ItemImpl(_, _, _, ref opt_trait, _, ref impl_items) => {
                 for impl_item in impl_items {
                     match impl_item.node {
+                        ast::ConstImplItem(..) |
                         ast::MethodImplItem(..) => {
                             if opt_trait.is_some() ||
                                     has_allow_dead_code_or_lang_attr(&impl_item.attrs) {
@@ -406,7 +401,7 @@ fn create_and_seed_worklist(tcx: &ty::ctxt,
         None => ()
     }
 
-    // Seed implemented trait methods
+    // Seed implemented trait items
     let mut life_seeder = LifeSeeder {
         worklist: worklist
     };
@@ -487,7 +482,7 @@ fn symbol_is_live(&mut self, id: ast::NodeId,
                              |ctor| self.live_symbols.contains(&ctor)) {
             return true;
         }
-        // If it's a type whose methods are live, then it's live, too.
+        // If it's a type whose items are live, then it's live, too.
         // This is done to handle the case where, for example, the static
         // method of a private type is used, but the type itself is never
         // called directly.
@@ -557,21 +552,6 @@ fn visit_foreign_item(&mut self, fi: &ast::ForeignItem) {
         visit::walk_foreign_item(self, fi);
     }
 
-    fn visit_fn(&mut self, fk: visit::FnKind<'v>,
-                _: &'v ast::FnDecl, block: &'v ast::Block,
-                span: codemap::Span, id: ast::NodeId) {
-        // Have to warn method here because methods are not ast::Item
-        match fk {
-            visit::FkMethod(name, _, _) => {
-                if !self.symbol_is_live(id, None) {
-                    self.warn_dead_code(id, span, name.name, "method");
-                }
-            }
-            _ => ()
-        }
-        visit::walk_block(self, block);
-    }
-
     fn visit_struct_field(&mut self, field: &ast::StructField) {
         if self.should_warn_about_field(&field.node) {
             self.warn_dead_code(field.node.id, field.span,
@@ -581,12 +561,37 @@ fn visit_struct_field(&mut self, field: &ast::StructField) {
         visit::walk_struct_field(self, field);
     }
 
-    // Overwrite so that we don't warn the trait method itself.
-    fn visit_trait_item(&mut self, trait_method: &ast::TraitItem) {
-        match trait_method.node {
+    fn visit_impl_item(&mut self, impl_item: &ast::ImplItem) {
+        match impl_item.node {
+            ast::ConstImplItem(_, ref expr) => {
+                if !self.symbol_is_live(impl_item.id, None) {
+                    self.warn_dead_code(impl_item.id, impl_item.span,
+                                        impl_item.ident.name, "associated const");
+                }
+                visit::walk_expr(self, expr)
+            }
+            ast::MethodImplItem(_, ref body) => {
+                if !self.symbol_is_live(impl_item.id, None) {
+                    self.warn_dead_code(impl_item.id, impl_item.span,
+                                        impl_item.ident.name, "method");
+                }
+                visit::walk_block(self, body)
+            }
+            ast::TypeImplItem(..) |
+            ast::MacImplItem(..) => {}
+        }
+    }
+
+    // Overwrite so that we don't warn the trait item itself.
+    fn visit_trait_item(&mut self, trait_item: &ast::TraitItem) {
+        match trait_item.node {
+            ast::ConstTraitItem(_, Some(ref expr)) => {
+                visit::walk_expr(self, expr)
+            }
             ast::MethodTraitItem(_, Some(ref body)) => {
                 visit::walk_block(self, body)
             }
+            ast::ConstTraitItem(_, None) |
             ast::MethodTraitItem(_, None) |
             ast::TypeTraitItem(..) => {}
         }
index f0b359088549b05333b2e01efba7ed1e9c5820ea..bce246fa4af866dbd2ec1f974dbdd4158ee5f0f0 100644 (file)
@@ -28,6 +28,7 @@ pub enum Def {
     DefForeignMod(ast::DefId),
     DefStatic(ast::DefId, bool /* is_mutbl */),
     DefConst(ast::DefId),
+    DefAssociatedConst(ast::DefId /* const */, MethodProvenance),
     DefLocal(ast::NodeId),
     DefVariant(ast::DefId /* enum */, ast::DefId /* variant */, bool /* is_structure */),
     DefTy(ast::DefId, bool /* is_enum */),
@@ -140,7 +141,8 @@ pub fn def_id(&self) -> ast::DefId {
             DefFn(id, _) | DefMod(id) | DefForeignMod(id) | DefStatic(id, _) |
             DefVariant(_, id, _) | DefTy(id, _) | DefAssociatedTy(_, id) |
             DefTyParam(_, _, id, _) | DefUse(id) | DefStruct(id) | DefTrait(id) |
-            DefMethod(id, _) | DefConst(id) | DefSelfTy(Some(id), None)=> {
+            DefMethod(id, _) | DefConst(id) | DefAssociatedConst(id, _) |
+            DefSelfTy(Some(id), None)=> {
                 id
             }
             DefLocal(id) |
index 5235bbdf9cf00f67479357b1752b8824a9a0a03f..d740d24e23672d9016e8c76a9a9f8f60884733e1 100644 (file)
@@ -234,7 +234,7 @@ fn from_method_id(tcx: &ty::ctxt, method_id: ast::DefId)
             ty::MethodTraitItem(ref method_descriptor) => {
                 (*method_descriptor).clone()
             }
-            ty::TypeTraitItem(_) => {
+            _ => {
                 tcx.sess.bug("overloaded call method wasn't in method map")
             }
         };
@@ -1147,7 +1147,8 @@ fn walk_pat(&mut self,
             let tcx = typer.tcx();
 
             match pat.node {
-                ast::PatEnum(_, _) | ast::PatIdent(_, _, None) | ast::PatStruct(..) => {
+                ast::PatEnum(_, _) | ast::PatQPath(..) |
+                ast::PatIdent(_, _, None) | ast::PatStruct(..) => {
                     match def_map.get(&pat.id).map(|d| d.full_def()) {
                         None => {
                             // no definition found: pat is not a
@@ -1183,6 +1184,7 @@ fn walk_pat(&mut self,
                         }
 
                         Some(def::DefConst(..)) |
+                        Some(def::DefAssociatedConst(..)) |
                         Some(def::DefLocal(..)) => {
                             // This is a leaf (i.e. identifier binding
                             // or constant value to match); thus no
index 3dbbcce27b6eac3382a6dce15767ab790dee0a0f..22e3376e09ea8f4a46ba4cd8bcabd84c597b8412 100644 (file)
@@ -843,8 +843,8 @@ fn give_suggestion(&self, same_regions: &[SameRegions]) {
                                   Some(&sig.explicit_self.node),
                                   item.span))
                         }
-                        ast::TypeImplItem(_) => None,
-                        ast::MacImplItem(_) => self.tcx.sess.bug("unexpanded macro")
+                        ast::MacImplItem(_) => self.tcx.sess.bug("unexpanded macro"),
+                        _ => None,
                     }
                 },
                 ast_map::NodeTraitItem(item) => {
@@ -1723,8 +1723,8 @@ fn lifetimes_in_scope(tcx: &ty::ctxt,
                         taken.push_all(&sig.generics.lifetimes);
                         Some(ii.id)
                     }
-                    ast::TypeImplItem(_) => None,
-                    ast::MacImplItem(_) => tcx.sess.bug("unexpanded macro")
+                    ast::MacImplItem(_) => tcx.sess.bug("unexpanded macro"),
+                    _ => None,
                 }
             }
             _ => None
index 003306fe558a1b5d2c9413987f71ab21d1b890f4..587194bafada48acfa17742614d982f44821f933 100644 (file)
@@ -589,7 +589,7 @@ pub fn cat_def(&self,
 
         match def {
           def::DefStruct(..) | def::DefVariant(..) | def::DefConst(..) |
-          def::DefFn(..) | def::DefMethod(..) => {
+          def::DefAssociatedConst(..) | def::DefFn(..) | def::DefMethod(..) => {
                 Ok(self.cat_rvalue_node(id, span, expr_ty))
           }
           def::DefMod(_) | def::DefForeignMod(_) | def::DefUse(_) |
@@ -1286,7 +1286,7 @@ fn cat_pattern_<F>(&self, cmt: cmt<'tcx>, pat: &ast::Pat, op: &mut F)
                         try!(self.cat_pattern_(cmt_field, &**subpat, op));
                     }
                 }
-                Some(def::DefConst(..)) => {
+                Some(def::DefConst(..)) | Some(def::DefAssociatedConst(..)) => {
                     for subpat in subpats {
                         try!(self.cat_pattern_(cmt.clone(), &**subpat, op));
                     }
@@ -1299,6 +1299,10 @@ fn cat_pattern_<F>(&self, cmt: cmt<'tcx>, pat: &ast::Pat, op: &mut F)
             }
           }
 
+          ast::PatQPath(..) => {
+              // Lone constant: ignore
+          }
+
           ast::PatIdent(_, _, Some(ref subpat)) => {
               try!(self.cat_pattern_(cmt, &**subpat, op));
           }
index 12b56562c84d6b825087ef50c0aab5bf4d0caa31..27a30f5cf253cf97da67691b72b29ec2863119cc 100644 (file)
@@ -30,7 +30,7 @@ pub fn pat_id_map(dm: &DefMap, pat: &ast::Pat) -> PatIdMap {
 
 pub fn pat_is_refutable(dm: &DefMap, pat: &ast::Pat) -> bool {
     match pat.node {
-        ast::PatLit(_) | ast::PatRange(_, _) => true,
+        ast::PatLit(_) | ast::PatRange(_, _) | ast::PatQPath(..) => true,
         ast::PatEnum(_, _) |
         ast::PatIdent(_, _, None) |
         ast::PatStruct(..) => {
@@ -60,9 +60,25 @@ pub fn pat_is_variant_or_struct(dm: &DefMap, pat: &ast::Pat) -> bool {
 
 pub fn pat_is_const(dm: &DefMap, pat: &ast::Pat) -> bool {
     match pat.node {
-        ast::PatIdent(_, _, None) | ast::PatEnum(..) => {
+        ast::PatIdent(_, _, None) | ast::PatEnum(..) | ast::PatQPath(..) => {
             match dm.borrow().get(&pat.id).map(|d| d.full_def()) {
-                Some(DefConst(..)) => true,
+                Some(DefConst(..)) | Some(DefAssociatedConst(..)) => true,
+                _ => false
+            }
+        }
+        _ => false
+    }
+}
+
+// Same as above, except that partially-resolved defs cause `false` to be
+// returned instead of a panic.
+pub fn pat_is_resolved_const(dm: &DefMap, pat: &ast::Pat) -> bool {
+    match pat.node {
+        ast::PatIdent(_, _, None) | ast::PatEnum(..) | ast::PatQPath(..) => {
+            match dm.borrow().get(&pat.id)
+                    .and_then(|d| if d.depth == 0 { Some(d.base_def) }
+                                  else { None } ) {
+                Some(DefConst(..)) | Some(DefAssociatedConst(..)) => true,
                 _ => false
             }
         }
index 1bd45b5fc86017cd5a8afea2c994c2e181397d9e..b532dc88df4cb5c939c6935ddd20bd1edbd2fba8 100644 (file)
@@ -113,7 +113,7 @@ fn visit_expr(&mut self, expr: &ast::Expr) {
                             // If this path leads to a constant, then we need to
                             // recurse into the constant to continue finding
                             // items that are reachable.
-                            def::DefConst(..) => {
+                            def::DefConst(..) | def::DefAssociatedConst(..) => {
                                 self.worklist.push(def_id.node);
                             }
 
@@ -183,12 +183,14 @@ fn def_id_represents_local_inlined_item(&self, def_id: ast::DefId) -> bool {
             }
             Some(ast_map::NodeTraitItem(trait_method)) => {
                 match trait_method.node {
+                    ast::ConstTraitItem(_, ref default) => default.is_some(),
                     ast::MethodTraitItem(_, ref body) => body.is_some(),
                     ast::TypeTraitItem(..) => false,
                 }
             }
             Some(ast_map::NodeImplItem(impl_item)) => {
                 match impl_item.node {
+                    ast::ConstImplItem(..) => true,
                     ast::MethodImplItem(ref sig, _) => {
                         if generics_require_inlining(&sig.generics) ||
                                 attr::requests_inline(&impl_item.attrs) {
@@ -303,9 +305,13 @@ fn propagate_node(&mut self, node: &ast_map::Node,
             }
             ast_map::NodeTraitItem(trait_method) => {
                 match trait_method.node {
+                    ast::ConstTraitItem(_, None) |
                     ast::MethodTraitItem(_, None) => {
                         // Keep going, nothing to get exported
                     }
+                    ast::ConstTraitItem(_, Some(ref expr)) => {
+                        self.visit_expr(&*expr);
+                    }
                     ast::MethodTraitItem(_, Some(ref body)) => {
                         visit::walk_block(self, body);
                     }
@@ -314,6 +320,9 @@ fn propagate_node(&mut self, node: &ast_map::Node,
             }
             ast_map::NodeImplItem(impl_item) => {
                 match impl_item.node {
+                    ast::ConstImplItem(_, ref expr) => {
+                        self.visit_expr(&*expr);
+                    }
                     ast::MethodImplItem(ref sig, ref body) => {
                         let did = self.tcx.map.get_parent_did(search_item);
                         if method_might_be_inlined(self.tcx, sig, impl_item, did) {
index a2ff86cd065901d4115458f6a4fb323bde8541cb..3d6ed3c34406118fdea3f0bedfc381d78e7e7c6e 100644 (file)
@@ -100,9 +100,7 @@ fn object_safety_violations_for_trait<'tcx>(tcx: &ty::ctxt<'tcx>,
                         .map(|code| ObjectSafetyViolation::Method(m.clone(), code))
                         .into_iter()
                 }
-                ty::TypeTraitItem(_) => {
-                    None.into_iter()
-                }
+                _ => None.into_iter(),
             }
         })
         .collect();
index 7488b8f046e74eff8215258fe5127b4c99895384..9cdae21868ed3393ec4493ca2c7cb06fce921c80 100644 (file)
@@ -863,7 +863,7 @@ fn confirm_impl_candidate<'cx,'tcx>(
     for impl_item in impl_items {
         let assoc_type = match *impl_or_trait_items_map.get(&impl_item.def_id()).unwrap() {
             ty::TypeTraitItem(ref assoc_type) => assoc_type.clone(),
-            ty::MethodTraitItem(..) => { continue; }
+            ty::ConstTraitItem(..) | ty::MethodTraitItem(..) => { continue; }
         };
 
         if assoc_type.name != obligation.predicate.item_name {
index ddf941198eb0f86ee491e159107efe8e392d8d9b..6ecff3b7faabe9178064a6676be5deaf85124cf5 100644 (file)
@@ -434,7 +434,7 @@ pub fn get_vtable_index_of_object_method<'tcx>(tcx: &ty::ctxt<'tcx>,
         for trait_item in &**trait_items {
             match *trait_item {
                 ty::MethodTraitItem(_) => method_count += 1,
-                ty::TypeTraitItem(_) => {}
+                _ => {}
             }
         }
     }
@@ -445,14 +445,14 @@ pub fn get_vtable_index_of_object_method<'tcx>(tcx: &ty::ctxt<'tcx>,
     for trait_item in trait_items.iter().take(method_offset_in_trait) {
         match *trait_item {
             ty::MethodTraitItem(_) => method_count += 1,
-            ty::TypeTraitItem(_) => {}
+            _ => {}
         }
     }
 
     // the item at the offset we were given really ought to be a method
     assert!(match trait_items[method_offset_in_trait] {
         ty::MethodTraitItem(_) => true,
-        ty::TypeTraitItem(_) => false
+        _ => false
     });
 
     method_count
index 232e962ed4d2372e90d085a5573da718d2203ff1..f172815a4d1437734225dd399aea80ad4c07f16b 100644 (file)
@@ -80,7 +80,7 @@
 use collections::enum_set::{EnumSet, CLike};
 use std::collections::{HashMap, HashSet};
 use syntax::abi;
-use syntax::ast::{CrateNum, DefId, ItemTrait, LOCAL_CRATE};
+use syntax::ast::{CrateNum, DefId, ItemImpl, ItemTrait, LOCAL_CRATE};
 use syntax::ast::{MutImmutable, MutMutable, Name, NamedField, NodeId};
 use syntax::ast::{StmtExpr, StmtSemi, StructField, UnnamedField, Visibility};
 use syntax::ast_util::{self, is_local, lit_is_str, local_def};
@@ -133,6 +133,7 @@ pub fn id(&self) -> ast::DefId {
 
 #[derive(Clone, Debug)]
 pub enum ImplOrTraitItem<'tcx> {
+    ConstTraitItem(Rc<AssociatedConst<'tcx>>),
     MethodTraitItem(Rc<Method<'tcx>>),
     TypeTraitItem(Rc<AssociatedType>),
 }
@@ -140,6 +141,9 @@ pub enum ImplOrTraitItem<'tcx> {
 impl<'tcx> ImplOrTraitItem<'tcx> {
     fn id(&self) -> ImplOrTraitItemId {
         match *self {
+            ConstTraitItem(ref associated_const) => {
+                ConstTraitItemId(associated_const.def_id)
+            }
             MethodTraitItem(ref method) => MethodTraitItemId(method.def_id),
             TypeTraitItem(ref associated_type) => {
                 TypeTraitItemId(associated_type.def_id)
@@ -149,6 +153,7 @@ fn id(&self) -> ImplOrTraitItemId {
 
     pub fn def_id(&self) -> ast::DefId {
         match *self {
+            ConstTraitItem(ref associated_const) => associated_const.def_id,
             MethodTraitItem(ref method) => method.def_id,
             TypeTraitItem(ref associated_type) => associated_type.def_id,
         }
@@ -156,13 +161,23 @@ pub fn def_id(&self) -> ast::DefId {
 
     pub fn name(&self) -> ast::Name {
         match *self {
+            ConstTraitItem(ref associated_const) => associated_const.name,
             MethodTraitItem(ref method) => method.name,
             TypeTraitItem(ref associated_type) => associated_type.name,
         }
     }
 
+    pub fn vis(&self) -> ast::Visibility {
+        match *self {
+            ConstTraitItem(ref associated_const) => associated_const.vis,
+            MethodTraitItem(ref method) => method.vis,
+            TypeTraitItem(ref associated_type) => associated_type.vis,
+        }
+    }
+
     pub fn container(&self) -> ImplOrTraitItemContainer {
         match *self {
+            ConstTraitItem(ref associated_const) => associated_const.container,
             MethodTraitItem(ref method) => method.container,
             TypeTraitItem(ref associated_type) => associated_type.container,
         }
@@ -171,13 +186,14 @@ pub fn container(&self) -> ImplOrTraitItemContainer {
     pub fn as_opt_method(&self) -> Option<Rc<Method<'tcx>>> {
         match *self {
             MethodTraitItem(ref m) => Some((*m).clone()),
-            TypeTraitItem(_) => None
+            _ => None,
         }
     }
 }
 
 #[derive(Clone, Copy, Debug)]
 pub enum ImplOrTraitItemId {
+    ConstTraitItemId(ast::DefId),
     MethodTraitItemId(ast::DefId),
     TypeTraitItemId(ast::DefId),
 }
@@ -185,6 +201,7 @@ pub enum ImplOrTraitItemId {
 impl ImplOrTraitItemId {
     pub fn def_id(&self) -> ast::DefId {
         match *self {
+            ConstTraitItemId(def_id) => def_id,
             MethodTraitItemId(def_id) => def_id,
             TypeTraitItemId(def_id) => def_id,
         }
@@ -238,6 +255,16 @@ pub fn container_id(&self) -> ast::DefId {
     }
 }
 
+#[derive(Clone, Copy, Debug)]
+pub struct AssociatedConst<'tcx> {
+    pub name: ast::Name,
+    pub ty: Ty<'tcx>,
+    pub vis: ast::Visibility,
+    pub def_id: ast::DefId,
+    pub container: ImplOrTraitItemContainer,
+    pub default: Option<ast::DefId>,
+}
+
 #[derive(Clone, Copy, Debug)]
 pub struct AssociatedType {
     pub name: ast::Name,
@@ -2291,6 +2318,16 @@ pub fn for_item(cx: &'a ctxt<'tcx>, id: NodeId) -> ParameterEnvironment<'a, 'tcx
         match cx.map.find(id) {
             Some(ast_map::NodeImplItem(ref impl_item)) => {
                 match impl_item.node {
+                    ast::ConstImplItem(_, _) => {
+                        let def_id = ast_util::local_def(id);
+                        let scheme = lookup_item_type(cx, def_id);
+                        let predicates = lookup_predicates(cx, def_id);
+                        construct_parameter_environment(cx,
+                                                        impl_item.span,
+                                                        &scheme.generics,
+                                                        &predicates,
+                                                        id)
+                    }
                     ast::MethodImplItem(_, ref body) => {
                         let method_def_id = ast_util::local_def(id);
                         match ty::impl_or_trait_item(cx, method_def_id) {
@@ -2304,11 +2341,10 @@ pub fn for_item(cx: &'a ctxt<'tcx>, id: NodeId) -> ParameterEnvironment<'a, 'tcx
                                     method_bounds,
                                     body.id)
                             }
-                            TypeTraitItem(_) => {
+                            _ => {
                                 cx.sess
                                   .bug("ParameterEnvironment::for_item(): \
-                                        can't create a parameter environment \
-                                        for type trait items")
+                                        got non-method item from impl method?!")
                             }
                         }
                     }
@@ -2322,6 +2358,25 @@ pub fn for_item(cx: &'a ctxt<'tcx>, id: NodeId) -> ParameterEnvironment<'a, 'tcx
             }
             Some(ast_map::NodeTraitItem(trait_item)) => {
                 match trait_item.node {
+                    ast::ConstTraitItem(_, ref default) => {
+                        match *default {
+                            Some(_) => {
+                                let def_id = ast_util::local_def(id);
+                                let scheme = lookup_item_type(cx, def_id);
+                                let predicates = lookup_predicates(cx, def_id);
+                                construct_parameter_environment(cx,
+                                                                trait_item.span,
+                                                                &scheme.generics,
+                                                                &predicates,
+                                                                id)
+                            }
+                            None => {
+                                cx.sess.bug("ParameterEnvironment::from_item(): \
+                                             can't create a parameter environment \
+                                             for const trait items without defaults")
+                            }
+                        }
+                    }
                     ast::MethodTraitItem(_, None) => {
                         cx.sess.span_bug(trait_item.span,
                                          "ParameterEnvironment::for_item():
@@ -2342,11 +2397,11 @@ pub fn for_item(cx: &'a ctxt<'tcx>, id: NodeId) -> ParameterEnvironment<'a, 'tcx
                                     method_bounds,
                                     body.id)
                             }
-                            TypeTraitItem(_) => {
+                            _ => {
                                 cx.sess
                                   .bug("ParameterEnvironment::for_item(): \
-                                        can't create a parameter environment \
-                                        for type trait items")
+                                        got non-method item from provided \
+                                        method?!")
                             }
                         }
                     }
@@ -4719,7 +4774,8 @@ pub fn expr_kind(tcx: &ctxt, expr: &ast::Expr) -> ExprKind {
                 def::DefUpvar(..) |
                 def::DefLocal(..) => LvalueExpr,
 
-                def::DefConst(..) => RvalueDatumExpr,
+                def::DefConst(..) |
+                def::DefAssociatedConst(..) => RvalueDatumExpr,
 
                 def => {
                     tcx.sess.span_bug(
@@ -5070,10 +5126,10 @@ pub fn provided_trait_methods<'tcx>(cx: &ctxt<'tcx>, id: ast::DefId)
                 if let ast::MethodTraitItem(_, Some(_)) = ti.node {
                     match impl_or_trait_item(cx, ast_util::local_def(ti.id)) {
                         MethodTraitItem(m) => Some(m),
-                        TypeTraitItem(_) => {
+                        _ => {
                             cx.sess.bug("provided_trait_methods(): \
-                                         associated type found from \
-                                         looking up ProvidedMethod?!")
+                                         non-method item found from \
+                                         looking up provided method?!")
                         }
                     }
                 } else {
@@ -5088,6 +5144,52 @@ pub fn provided_trait_methods<'tcx>(cx: &ctxt<'tcx>, id: ast::DefId)
     }
 }
 
+pub fn associated_consts<'tcx>(cx: &ctxt<'tcx>, id: ast::DefId)
+                               -> Vec<Rc<AssociatedConst<'tcx>>> {
+    if is_local(id) {
+        match cx.map.expect_item(id.node).node {
+            ItemTrait(_, _, _, ref tis) => {
+                tis.iter().filter_map(|ti| {
+                    if let ast::ConstTraitItem(_, _) = ti.node {
+                        match impl_or_trait_item(cx, ast_util::local_def(ti.id)) {
+                            ConstTraitItem(ac) => Some(ac),
+                            _ => {
+                                cx.sess.bug("associated_consts(): \
+                                             non-const item found from \
+                                             looking up a constant?!")
+                            }
+                        }
+                    } else {
+                        None
+                    }
+                }).collect()
+            }
+            ItemImpl(_, _, _, _, _, ref iis) => {
+                iis.iter().filter_map(|ii| {
+                    if let ast::ConstImplItem(_, _) = ii.node {
+                        match impl_or_trait_item(cx, ast_util::local_def(ii.id)) {
+                            ConstTraitItem(ac) => Some(ac),
+                            _ => {
+                                cx.sess.bug("associated_consts(): \
+                                             non-const item found from \
+                                             looking up a constant?!")
+                            }
+                        }
+                    } else {
+                        None
+                    }
+                }).collect()
+            }
+            _ => {
+                cx.sess.bug(&format!("associated_consts: `{:?}` is not a trait \
+                                      or impl", id))
+            }
+        }
+    } else {
+        csearch::get_associated_consts(cx, id)
+    }
+}
+
 /// Helper for looking things up in the various maps that are populated during
 /// typeck::collect (e.g., `cx.impl_or_trait_items`, `cx.tcache`, etc).  All of
 /// these share the pattern that if the id is local, it should have been loaded
@@ -5174,7 +5276,7 @@ pub fn is_associated_type(cx: &ctxt, id: ast::DefId) -> bool {
                 Some(ref item) => {
                     match **item {
                         TypeTraitItem(_) => true,
-                        MethodTraitItem(_) => false,
+                        _ => false,
                     }
                 }
                 None => false,
@@ -6188,7 +6290,7 @@ pub fn populate_implementations_for_type_if_necessary(tcx: &ctxt,
                            .insert(method_def_id, source);
                     }
                 }
-                TypeTraitItem(_) => {}
+                _ => {}
             }
         }
 
@@ -6240,7 +6342,7 @@ pub fn populate_implementations_for_trait_if_necessary(
                             .insert(method_def_id, source);
                     }
                 }
-                TypeTraitItem(_) => {}
+                _ => {}
             }
         }
 
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")));
index 12a6d5848572d7b35660664a3645adccc0cdf36c..3d56371dd52cafc56ae365b786a0b623e1504548 100644 (file)
@@ -830,6 +830,7 @@ fn repr(&self, tcx: &ctxt<'tcx>) -> String {
 impl<'tcx> Repr<'tcx> for ast::TraitItem {
     fn repr(&self, _tcx: &ctxt) -> String {
         let kind = match self.node {
+            ast::ConstTraitItem(..) => "ConstTraitItem",
             ast::MethodTraitItem(..) => "MethodTraitItem",
             ast::TypeTraitItem(..) => "TypeTraitItem",
         };
@@ -1054,9 +1055,39 @@ fn repr(&self, _: &ctxt) -> String {
     }
 }
 
+impl<'tcx> Repr<'tcx> for ty::ImplOrTraitItem<'tcx> {
+    fn repr(&self, tcx: &ctxt<'tcx>) -> String {
+        format!("ImplOrTraitItem({})",
+                match *self {
+                    ty::ImplOrTraitItem::MethodTraitItem(ref i) => i.repr(tcx),
+                    ty::ImplOrTraitItem::ConstTraitItem(ref i) => i.repr(tcx),
+                    ty::ImplOrTraitItem::TypeTraitItem(ref i) => i.repr(tcx),
+                })
+    }
+}
+
+impl<'tcx> Repr<'tcx> for ty::AssociatedConst<'tcx> {
+    fn repr(&self, tcx: &ctxt<'tcx>) -> String {
+        format!("AssociatedConst(name: {}, ty: {}, vis: {}, def_id: {})",
+                self.name.repr(tcx),
+                self.ty.repr(tcx),
+                self.vis.repr(tcx),
+                self.def_id.repr(tcx))
+    }
+}
+
+impl<'tcx> Repr<'tcx> for ty::AssociatedType {
+    fn repr(&self, tcx: &ctxt<'tcx>) -> String {
+        format!("AssociatedType(name: {}, vis: {}, def_id: {})",
+                self.name.repr(tcx),
+                self.vis.repr(tcx),
+                self.def_id.repr(tcx))
+    }
+}
+
 impl<'tcx> Repr<'tcx> for ty::Method<'tcx> {
     fn repr(&self, tcx: &ctxt<'tcx>) -> String {
-        format!("method(name: {}, generics: {}, predicates: {}, fty: {}, \
+        format!("Method(name: {}, generics: {}, predicates: {}, fty: {}, \
                  explicit_self: {}, vis: {}, def_id: {})",
                 self.name.repr(tcx),
                 self.generics.repr(tcx),
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 aedc0d23cfe1ddee4e21deda1fa07dce51be08de..27adf5bf21b63297a5491ba94efd3bea8f50867d 100644 (file)
@@ -77,6 +77,20 @@ fn visit_fn(&mut self, fk: FnKind<'v>, fd: &'v FnDecl,
     fn visit_item(&mut self, item: &ast::Item) {
         borrowck_item(self, item);
     }
+
+    fn visit_trait_item(&mut self, ti: &ast::TraitItem) {
+        if let ast::ConstTraitItem(_, Some(ref expr)) = ti.node {
+            gather_loans::gather_loans_in_static_initializer(self, &*expr);
+        }
+        visit::walk_trait_item(self, ti);
+    }
+
+    fn visit_impl_item(&mut self, ii: &ast::ImplItem) {
+        if let ast::ConstImplItem(_, ref expr) = ii.node {
+            gather_loans::gather_loans_in_static_initializer(self, &*expr);
+        }
+        visit::walk_impl_item(self, ii);
+    }
 }
 
 pub fn check_crate(tcx: &ty::ctxt) {
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 00c3450ebb935ac326ca6e904d05f49f8575c3f0..b8032bda8d070ede99791322e5f2ba00c49abc14 100644 (file)
@@ -35,6 +35,7 @@
 use syntax::fold::{self, Folder};
 use syntax::print::{pp, pprust};
 use syntax::ptr::P;
+use syntax::util::small_vector::SmallVector;
 
 use graphviz as dot;
 
@@ -475,6 +476,29 @@ fn fold_item_underscore(&mut self, i: ast::Item_) -> ast::Item_ {
         }
     }
 
+    fn fold_trait_item(&mut self, i: P<ast::TraitItem>) -> SmallVector<P<ast::TraitItem>> {
+        match i.node {
+            ast::ConstTraitItem(..) => {
+                self.within_static_or_const = true;
+                let ret = fold::noop_fold_trait_item(i, self);
+                self.within_static_or_const = false;
+                return ret;
+            }
+            _ => fold::noop_fold_trait_item(i, self),
+        }
+    }
+
+    fn fold_impl_item(&mut self, i: P<ast::ImplItem>) -> SmallVector<P<ast::ImplItem>> {
+        match i.node {
+            ast::ConstImplItem(..) => {
+                self.within_static_or_const = true;
+                let ret = fold::noop_fold_impl_item(i, self);
+                self.within_static_or_const = false;
+                return ret;
+            }
+            _ => fold::noop_fold_impl_item(i, self),
+        }
+    }
 
     fn fold_block(&mut self, b: P<ast::Block>) -> P<ast::Block> {
         fn expr_to_block(rules: ast::BlockCheckMode,
index c12ac501c45a2a14fb510dcb90462a4b63610a65..1d5c5fb86cbd5988b783d19c69ac28f5b06ca8b0 100644 (file)
@@ -1068,6 +1068,26 @@ fn check_item(&mut self, cx: &Context, it: &ast::Item) {
         }
     }
 
+    fn check_trait_item(&mut self, cx: &Context, ti: &ast::TraitItem) {
+        match ti.node {
+            ast::ConstTraitItem(..) => {
+                NonUpperCaseGlobals::check_upper_case(cx, "associated constant",
+                                                      ti.ident, ti.span);
+            }
+            _ => {}
+        }
+    }
+
+    fn check_impl_item(&mut self, cx: &Context, ii: &ast::ImplItem) {
+        match ii.node {
+            ast::ConstImplItem(..) => {
+                NonUpperCaseGlobals::check_upper_case(cx, "associated constant",
+                                                      ii.ident, ii.span);
+            }
+            _ => {}
+        }
+    }
+
     fn check_pat(&mut self, cx: &Context, p: &ast::Pat) {
         // Lint for constants that look like binding identifiers (#7526)
         match (&p.node, cx.tcx.def_map.borrow().get(&p.id).map(|d| d.full_def())) {
@@ -1584,8 +1604,9 @@ fn check_trait_item(&mut self, cx: &Context, trait_item: &ast::TraitItem) {
         if self.private_traits.contains(&trait_item.id) { return }
 
         let desc = match trait_item.node {
+            ast::ConstTraitItem(..) => "an associated constant",
             ast::MethodTraitItem(..) => "a trait method",
-            ast::TypeTraitItem(..) => "an associated type"
+            ast::TypeTraitItem(..) => "an associated type",
         };
 
         self.check_missing_docs_attrs(cx, Some(trait_item.id),
@@ -1600,9 +1621,10 @@ fn check_impl_item(&mut self, cx: &Context, impl_item: &ast::ImplItem) {
         }
 
         let desc = match impl_item.node {
+            ast::ConstImplItem(..) => "an associated constant",
             ast::MethodImplItem(..) => "a method",
             ast::TypeImplItem(_) => "an associated type",
-            ast::MacImplItem(_) => "an impl item macro"
+            ast::MacImplItem(_) => "an impl item macro",
         };
         self.check_missing_docs_attrs(cx, Some(impl_item.id),
                                       &impl_item.attrs,
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..22f915af00f5fa11a6eae3aa9f4450dec76132e0 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;
index 70c824a67a0efbd6d621c6e4533d390fe3221610..128e29ee76e7d6ec17acc19c8b9216cacef514b2 100644 (file)
@@ -119,6 +119,15 @@ fn visit_fn(&mut self, a: visit::FnKind<'v>, b: &'v ast::FnDecl,
         visit::walk_fn(self, a, b, c, d);
     }
 
+    fn visit_impl_item(&mut self, ii: &'v ast::ImplItem) {
+        // visit_fn handles methods, but associated consts have to be handled
+        // here.
+        if !self.parents.contains_key(&ii.id) {
+            self.parents.insert(ii.id, self.curparent);
+        }
+        visit::walk_impl_item(self, ii);
+    }
+
     fn visit_struct_def(&mut self, s: &ast::StructDef, _: ast::Ident,
                         _: &'v ast::Generics, n: ast::NodeId) {
         // Struct constructors are parented to their struct definitions because
@@ -272,6 +281,12 @@ fn visit_item(&mut self, item: &ast::Item) {
                 if public_ty || public_trait {
                     for impl_item in impl_items {
                         match impl_item.node {
+                            ast::ConstImplItem(..) => {
+                                if (public_ty && impl_item.vis == ast::Public)
+                                    || tr.is_some() {
+                                    self.exported_items.insert(impl_item.id);
+                                }
+                            }
                             ast::MethodImplItem(ref sig, _) => {
                                 let meth_public = match sig.explicit_self.node {
                                     ast::SelfStatic => public_ty,
@@ -399,6 +414,33 @@ fn def_privacy(&self, did: ast::DefId) -> PrivacyResult {
             debug!("privacy - is {:?} a public method", did);
 
             return match self.tcx.impl_or_trait_items.borrow().get(&did) {
+                Some(&ty::ConstTraitItem(ref ac)) => {
+                    debug!("privacy - it's a const: {:?}", *ac);
+                    match ac.container {
+                        ty::TraitContainer(id) => {
+                            debug!("privacy - recursing on trait {:?}", id);
+                            self.def_privacy(id)
+                        }
+                        ty::ImplContainer(id) => {
+                            match ty::impl_trait_ref(self.tcx, id) {
+                                Some(t) => {
+                                    debug!("privacy - impl of trait {:?}", id);
+                                    self.def_privacy(t.def_id)
+                                }
+                                None => {
+                                    debug!("privacy - found inherent \
+                                            associated constant {:?}",
+                                            ac.vis);
+                                    if ac.vis == ast::Public {
+                                        Allowable
+                                    } else {
+                                        ExternallyDenied
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
                 Some(&ty::MethodTraitItem(ref meth)) => {
                     debug!("privacy - well at least it's a method: {:?}",
                            *meth);
@@ -490,6 +532,7 @@ fn def_privacy(&self, did: ast::DefId) -> PrivacyResult {
                 //               where the method was defined?
                 Some(ast_map::NodeImplItem(ii)) => {
                     match ii.node {
+                        ast::ConstImplItem(..) |
                         ast::MethodImplItem(..) => {
                             let imp = self.tcx.map
                                           .get_parent_did(closest_private_id);
@@ -693,7 +736,11 @@ fn check_static_method(&mut self,
             ty::MethodTraitItem(method_type) => {
                 method_type.provided_source.unwrap_or(method_id)
             }
-            ty::TypeTraitItem(_) => method_id,
+            _ => {
+                self.tcx.sess
+                    .span_bug(span,
+                              "got non-method item in check_static_method")
+            }
         };
 
         let string = token::get_name(name);
@@ -787,6 +834,7 @@ fn check_path(&mut self, span: Span, path_id: ast::NodeId, last: ast::Name) {
             def::DefFn(..) => ck("function"),
             def::DefStatic(..) => ck("static"),
             def::DefConst(..) => ck("const"),
+            def::DefAssociatedConst(..) => ck("associated const"),
             def::DefVariant(..) => ck("variant"),
             def::DefTy(_, false) => ck("type"),
             def::DefTy(_, true) => ck("enum"),
@@ -1128,8 +1176,7 @@ fn check_inherited(tcx: &ty::ctxt, sp: Span, vis: ast::Visibility) {
                         ast::MethodImplItem(..) => {
                             check_inherited(tcx, impl_item.span, impl_item.vis);
                         }
-                        ast::TypeImplItem(_) |
-                        ast::MacImplItem(_) => {}
+                        _ => {}
                     }
                 }
             }
@@ -1307,6 +1354,7 @@ fn visit_item(&mut self, item: &ast::Item) {
                     impl_items.iter()
                               .any(|impl_item| {
                                   match impl_item.node {
+                                      ast::ConstImplItem(..) |
                                       ast::MethodImplItem(..) => {
                                           self.exported_items.contains(&impl_item.id)
                                       }
@@ -1330,6 +1378,7 @@ fn visit_item(&mut self, item: &ast::Item) {
                                 // don't erroneously report errors for private
                                 // types in private items.
                                 match impl_item.node {
+                                    ast::ConstImplItem(..) |
                                     ast::MethodImplItem(..)
                                         if self.item_is_public(&impl_item.id, impl_item.vis) =>
                                     {
@@ -1360,12 +1409,8 @@ fn visit_item(&mut self, item: &ast::Item) {
 
                             // Those in 3. are warned with this call.
                             for impl_item in impl_items {
-                                match impl_item.node {
-                                    ast::TypeImplItem(ref ty) => {
-                                        self.visit_ty(ty);
-                                    }
-                                    ast::MethodImplItem(..) |
-                                    ast::MacImplItem(_) => {},
+                                if let ast::TypeImplItem(ref ty) = impl_item.node {
+                                    self.visit_ty(ty);
                                 }
                             }
                         }
@@ -1376,15 +1421,20 @@ fn visit_item(&mut self, item: &ast::Item) {
                     let mut found_pub_static = false;
                     for impl_item in impl_items {
                         match impl_item.node {
+                            ast::ConstImplItem(..) => {
+                                if self.item_is_public(&impl_item.id, impl_item.vis) {
+                                    found_pub_static = true;
+                                    visit::walk_impl_item(self, impl_item);
+                                }
+                            }
                             ast::MethodImplItem(ref sig, _) => {
                                 if sig.explicit_self.node == ast::SelfStatic &&
-                                        self.item_is_public(&impl_item.id, impl_item.vis) {
+                                      self.item_is_public(&impl_item.id, impl_item.vis) {
                                     found_pub_static = true;
                                     visit::walk_impl_item(self, impl_item);
                                 }
                             }
-                            ast::TypeImplItem(_) |
-                            ast::MacImplItem(_) => {}
+                            _ => {}
                         }
                     }
                     if found_pub_static {
index 777154f3c9c3b41881f7b2c3849160402dc32853..0d25700d2b7f101f69f3ffb7adc7e671ae076b48 100644 (file)
@@ -530,6 +530,12 @@ fn build_reduced_graph_for_item(&mut self, item: &Item, parent: &Rc<Module>) ->
                                         trait_item.span);
 
                     match trait_item.node {
+                        ast::ConstTraitItem(..) => {
+                            let def = DefAssociatedConst(local_def(trait_item.id),
+                                                         FromTrait(local_def(item.id)));
+                            // NB: not IMPORTABLE
+                            name_bindings.define_value(def, trait_item.span, PUBLIC);
+                        }
                         ast::MethodTraitItem(..) => {
                             let def = DefMethod(local_def(trait_item.id),
                                                 FromTrait(local_def(item.id)));
@@ -703,7 +709,8 @@ fn handle_external_def(&mut self,
                 csearch::get_tuple_struct_definition_if_ctor(&self.session.cstore, ctor_id)
                     .map_or(def, |_| DefStruct(ctor_id)), DUMMY_SP, modifiers);
           }
-          DefFn(..) | DefStatic(..) | DefConst(..) | DefMethod(..) => {
+          DefFn(..) | DefStatic(..) | DefConst(..) | DefAssociatedConst(..) |
+          DefMethod(..) => {
             debug!("(building reduced graph for external \
                     crate) building value (fn/static) {}", final_ident);
             // impl methods have already been defined with the correct importability modifier
index d300045c0ec01c1444f37cca16681a2ef82d1a5e..61eab4ce9b285e0128cfb57b6311bde190ff93be 100644 (file)
@@ -41,6 +41,7 @@
 use self::RibKind::*;
 use self::UseLexicalScopeFlag::*;
 use self::ModulePrefixResult::*;
+use self::AssocItemResolveResult::*;
 use self::NameSearchType::*;
 use self::BareIdentifierPatternResolution::*;
 use self::ParentLink::*;
@@ -60,7 +61,8 @@
 use rustc::util::nodemap::{NodeMap, NodeSet, DefIdSet, FnvHashMap};
 use rustc::util::lev_distance::lev_distance;
 
-use syntax::ast::{Arm, BindByRef, BindByValue, BindingMode, Block, Crate, CrateNum};
+use syntax::ast::{Arm, BindByRef, BindByValue, BindingMode, Block};
+use syntax::ast::{ConstImplItem, Crate, CrateNum};
 use syntax::ast::{DefId, Expr, ExprAgain, ExprBreak, ExprField};
 use syntax::ast::{ExprLoop, ExprWhile, ExprMethodCall};
 use syntax::ast::{ExprPath, ExprStruct, FnDecl};
@@ -69,7 +71,7 @@
 use syntax::ast::{ItemFn, ItemForeignMod, ItemImpl, ItemMac, ItemMod, ItemStatic, ItemDefaultImpl};
 use syntax::ast::{ItemStruct, ItemTrait, ItemTy, ItemUse};
 use syntax::ast::{Local, MethodImplItem, Name, NodeId};
-use syntax::ast::{Pat, PatEnum, PatIdent, PatLit};
+use syntax::ast::{Pat, PatEnum, PatIdent, PatLit, PatQPath};
 use syntax::ast::{PatRange, PatStruct, Path, PrimTy};
 use syntax::ast::{TraitRef, Ty, TyBool, TyChar, TyF32};
 use syntax::ast::{TyF64, TyFloat, TyIs, TyI8, TyI16, TyI32, TyI64, TyInt};
@@ -330,6 +332,15 @@ enum ModulePrefixResult {
     PrefixFound(Rc<Module>, usize)
 }
 
+#[derive(Copy, Clone)]
+enum AssocItemResolveResult {
+    /// Syntax such as `<T>::item`, which can't be resolved until type
+    /// checking.
+    TypecheckRequired,
+    /// We should have been able to resolve the associated item.
+    ResolveAttempt(Option<PathResolution>),
+}
+
 #[derive(Copy, Clone, PartialEq)]
 enum NameSearchType {
     /// We're doing a name search in order to resolve a `use` directive.
@@ -1830,21 +1841,36 @@ fn resolve_item(&mut self, item: &Item) {
                             //
                             // FIXME #4951: Do we need a node ID here?
 
-                            let type_parameters = match trait_item.node {
+                            match trait_item.node {
+                                ast::ConstTraitItem(_, ref default) => {
+                                    // Only impose the restrictions of
+                                    // ConstRibKind if there's an actual constant
+                                    // expression in a provided default.
+                                    if default.is_some() {
+                                        this.with_constant_rib(|this| {
+                                            visit::walk_trait_item(this, trait_item)
+                                        });
+                                    } else {
+                                        visit::walk_trait_item(this, trait_item)
+                                    }
+                                }
                                 ast::MethodTraitItem(ref sig, _) => {
-                                    HasTypeParameters(&sig.generics,
-                                                      FnSpace,
-                                                      MethodRibKind)
+                                    let type_parameters =
+                                        HasTypeParameters(&sig.generics,
+                                                          FnSpace,
+                                                          MethodRibKind);
+                                    this.with_type_parameter_rib(type_parameters, |this| {
+                                        visit::walk_trait_item(this, trait_item)
+                                    });
                                 }
                                 ast::TypeTraitItem(..) => {
                                     this.check_if_primitive_type_name(trait_item.ident.name,
                                                                       trait_item.span);
-                                    NoTypeParameters
+                                    this.with_type_parameter_rib(NoTypeParameters, |this| {
+                                        visit::walk_trait_item(this, trait_item)
+                                    });
                                 }
                             };
-                            this.with_type_parameter_rib(type_parameters, |this| {
-                                visit::walk_trait_item(this, trait_item)
-                            });
                         }
                     });
                 });
@@ -2094,6 +2120,15 @@ fn resolve_implementation(&mut self,
                     this.with_current_self_type(self_type, |this| {
                         for impl_item in impl_items {
                             match impl_item.node {
+                                ConstImplItem(..) => {
+                                    // If this is a trait impl, ensure the method
+                                    // exists in trait
+                                    this.check_trait_item(impl_item.ident.name,
+                                                          impl_item.span);
+                                    this.with_constant_rib(|this| {
+                                        visit::walk_impl_item(this, impl_item);
+                                    });
+                                }
                                 MethodImplItem(ref sig, _) => {
                                     // If this is a trait impl, ensure the method
                                     // exists in trait
@@ -2280,31 +2315,21 @@ fn resolve_block(&mut self, block: &Block) {
 
     fn resolve_type(&mut self, ty: &Ty) {
         match ty.node {
-            // `<T>::a::b::c` is resolved by typeck alone.
-            TyPath(Some(ast::QSelf { position: 0, .. }), _) => {}
-
             TyPath(ref maybe_qself, ref path) => {
-                let max_assoc_types = if let Some(ref qself) = *maybe_qself {
-                    // Make sure the trait is valid.
-                    let _ = self.resolve_trait_reference(ty.id, path, 1);
-                    path.segments.len() - qself.position
-                } else {
-                    path.segments.len()
-                };
-
-                let mut resolution = None;
-                for depth in 0..max_assoc_types {
-                    self.with_no_errors(|this| {
-                        resolution = this.resolve_path(ty.id, path, depth, TypeNS, true);
-                    });
-                    if resolution.is_some() {
-                        break;
-                    }
-                }
-                if let Some(DefMod(_)) = resolution.map(|r| r.base_def) {
-                    // A module is not a valid type.
-                    resolution = None;
-                }
+                let resolution =
+                    match self.resolve_possibly_assoc_item(ty.id,
+                                                           maybe_qself.as_ref(),
+                                                           path,
+                                                           TypeNS,
+                                                           true) {
+                        // `<T>::a::b::c` is resolved by typeck alone.
+                        TypecheckRequired => {
+                            // Resolve embedded types.
+                            visit::walk_ty(self, ty);
+                            return;
+                        }
+                        ResolveAttempt(resolution) => resolution,
+                    };
 
                 // This is a path in the type namespace. Walk through scopes
                 // looking for it.
@@ -2464,7 +2489,22 @@ struct or enum variant",
 
                 PatEnum(ref path, _) => {
                     // This must be an enum variant, struct or const.
-                    if let Some(path_res) = self.resolve_path(pat_id, path, 0, ValueNS, false) {
+                    let resolution =
+                        match self.resolve_possibly_assoc_item(pat_id, None,
+                                                               path, ValueNS,
+                                                               false) {
+                            // The below shouldn't happen because all
+                            // qualified paths should be in PatQPath.
+                            TypecheckRequired =>
+                                self.session.span_bug(
+                                    path.span,
+                                    "resolve_possibly_assoc_item claimed
+                                     that a path in PatEnum requires typecheck
+                                     to resolve, but qualified paths should be
+                                     PatQPath"),
+                            ResolveAttempt(resolution) => resolution,
+                        };
+                    if let Some(path_res) = resolution {
                         match path_res.base_def {
                             DefVariant(..) | DefStruct(..) | DefConst(..) => {
                                 self.record_def(pattern.id, path_res);
@@ -2475,19 +2515,70 @@ struct or enum variant",
                                                     referenced in a pattern, \
                                                     use a `const` instead");
                             }
+                            _ => {
+                                // If anything ends up here entirely resolved,
+                                // it's an error. If anything ends up here
+                                // partially resolved, that's OK, because it may
+                                // be a `T::CONST` that typeck will resolve to
+                                // an inherent impl.
+                                if path_res.depth == 0 {
+                                    self.resolve_error(
+                                        path.span,
+                                        &format!("`{}` is not an enum variant, struct or const",
+                                                 token::get_ident(
+                                                     path.segments.last().unwrap().identifier)));
+                                } else {
+                                    self.record_def(pattern.id, path_res);
+                                }
+                            }
+                        }
+                    } else {
+                        self.resolve_error(path.span,
+                            &format!("unresolved enum variant, struct or const `{}`",
+                                token::get_ident(path.segments.last().unwrap().identifier)));
+                    }
+                    visit::walk_path(self, path);
+                }
+
+                PatQPath(ref qself, ref path) => {
+                    // Associated constants only.
+                    let resolution =
+                        match self.resolve_possibly_assoc_item(pat_id, Some(qself),
+                                                               path, ValueNS,
+                                                               false) {
+                            TypecheckRequired => {
+                                // All `<T>::CONST` should end up here, and will
+                                // require use of the trait map to resolve
+                                // during typechecking.
+                                let const_name = path.segments.last().unwrap()
+                                                     .identifier.name;
+                                let traits = self.get_traits_containing_item(const_name);
+                                self.trait_map.insert(pattern.id, traits);
+                                visit::walk_pat(self, pattern);
+                                return true;
+                            }
+                            ResolveAttempt(resolution) => resolution,
+                        };
+                    if let Some(path_res) = resolution {
+                        match path_res.base_def {
+                            // All `<T as Trait>::CONST` should end up here, and
+                            // have the trait already selected.
+                            DefAssociatedConst(..) => {
+                                self.record_def(pattern.id, path_res);
+                            }
                             _ => {
                                 self.resolve_error(path.span,
-                                    &format!("`{}` is not an enum variant, struct or const",
+                                    &format!("`{}` is not an associated const",
                                         token::get_ident(
                                             path.segments.last().unwrap().identifier)));
                             }
                         }
                     } else {
                         self.resolve_error(path.span,
-                            &format!("unresolved enum variant, struct or const `{}`",
+                            &format!("unresolved associated const `{}`",
                                 token::get_ident(path.segments.last().unwrap().identifier)));
                     }
-                    visit::walk_path(self, path);
+                    visit::walk_pat(self, pattern);
                 }
 
                 PatStruct(ref path, _, _) => {
@@ -2542,7 +2633,7 @@ fn resolve_bare_identifier_pattern(&mut self, name: Name, span: Span)
                             def @ DefVariant(..) | def @ DefStruct(..) => {
                                 return FoundStructOrEnumVariant(def, LastMod(AllPublic));
                             }
-                            def @ DefConst(..) => {
+                            def @ DefConst(..) | def @ DefAssociatedConst(..) => {
                                 return FoundConst(def, LastMod(AllPublic));
                             }
                             DefStatic(..) => {
@@ -2579,6 +2670,47 @@ fn resolve_bare_identifier_pattern(&mut self, name: Name, span: Span)
         }
     }
 
+    /// Handles paths that may refer to associated items
+    fn resolve_possibly_assoc_item(&mut self,
+                                   id: NodeId,
+                                   maybe_qself: Option<&ast::QSelf>,
+                                   path: &Path,
+                                   namespace: Namespace,
+                                   check_ribs: bool)
+                                   -> AssocItemResolveResult
+    {
+        match maybe_qself {
+            Some(&ast::QSelf { position: 0, .. }) =>
+                return TypecheckRequired,
+            _ => {}
+        }
+        let max_assoc_types = if let Some(qself) = maybe_qself {
+            // Make sure the trait is valid.
+            let _ = self.resolve_trait_reference(id, path, 1);
+            path.segments.len() - qself.position
+        } else {
+            path.segments.len()
+        };
+
+        let mut resolution = self.with_no_errors(|this| {
+            this.resolve_path(id, path, 0, namespace, check_ribs)
+        });
+        for depth in 1..max_assoc_types {
+            if resolution.is_some() {
+                break;
+            }
+            self.with_no_errors(|this| {
+                resolution = this.resolve_path(id, path, depth,
+                                               TypeNS, true);
+            });
+        }
+        if let Some(DefMod(_)) = resolution.map(|r| r.base_def) {
+            // A module is not a valid type or value.
+            resolution = None;
+        }
+        ResolveAttempt(resolution)
+    }
+
     /// If `check_ribs` is true, checks the local definitions first; i.e.
     /// doesn't skip straight to the containing module.
     /// Skips `path_depth` trailing segments, which is also reflected in the
@@ -3093,38 +3225,23 @@ fn resolve_expr(&mut self, expr: &Expr) {
 
         // Next, resolve the node.
         match expr.node {
-            // `<T>::a::b::c` is resolved by typeck alone.
-            ExprPath(Some(ast::QSelf { position: 0, .. }), ref path) => {
-                let method_name = path.segments.last().unwrap().identifier.name;
-                let traits = self.search_for_traits_containing_method(method_name);
-                self.trait_map.insert(expr.id, traits);
-                visit::walk_expr(self, expr);
-            }
-
             ExprPath(ref maybe_qself, ref path) => {
-                let max_assoc_types = if let Some(ref qself) = *maybe_qself {
-                    // Make sure the trait is valid.
-                    let _ = self.resolve_trait_reference(expr.id, path, 1);
-                    path.segments.len() - qself.position
-                } else {
-                    path.segments.len()
-                };
-
-                let mut resolution = self.with_no_errors(|this| {
-                    this.resolve_path(expr.id, path, 0, ValueNS, true)
-                });
-                for depth in 1..max_assoc_types {
-                    if resolution.is_some() {
-                        break;
-                    }
-                    self.with_no_errors(|this| {
-                        resolution = this.resolve_path(expr.id, path, depth, TypeNS, true);
-                    });
-                }
-                if let Some(DefMod(_)) = resolution.map(|r| r.base_def) {
-                    // A module is not a valid type or value.
-                    resolution = None;
-                }
+                let resolution =
+                    match self.resolve_possibly_assoc_item(expr.id,
+                                                           maybe_qself.as_ref(),
+                                                           path,
+                                                           ValueNS,
+                                                           true) {
+                        // `<T>::a::b::c` is resolved by typeck alone.
+                        TypecheckRequired => {
+                            let method_name = path.segments.last().unwrap().identifier.name;
+                            let traits = self.get_traits_containing_item(method_name);
+                            self.trait_map.insert(expr.id, traits);
+                            visit::walk_expr(self, expr);
+                            return;
+                        }
+                        ResolveAttempt(resolution) => resolution,
+                    };
 
                 // This is a local path in the value namespace. Walk through
                 // scopes looking for it.
@@ -3155,7 +3272,7 @@ fn resolve_expr(&mut self, expr: &Expr) {
                         // so they can be completed during typeck.
                         if path_res.depth != 0 {
                             let method_name = path.segments.last().unwrap().identifier.name;
-                            let traits = self.search_for_traits_containing_method(method_name);
+                            let traits = self.get_traits_containing_item(method_name);
                             self.trait_map.insert(expr.id, traits);
                         }
 
@@ -3313,14 +3430,14 @@ fn record_candidate_traits_for_expr_if_necessary(&mut self, expr: &Expr) {
                 // field, we need to add any trait methods we find that match
                 // the field name so that we can do some nice error reporting
                 // later on in typeck.
-                let traits = self.search_for_traits_containing_method(ident.node.name);
+                let traits = self.get_traits_containing_item(ident.node.name);
                 self.trait_map.insert(expr.id, traits);
             }
             ExprMethodCall(ident, _, _) => {
                 debug!("(recording candidate traits for expr) recording \
                         traits for {}",
                        expr.id);
-                let traits = self.search_for_traits_containing_method(ident.node.name);
+                let traits = self.get_traits_containing_item(ident.node.name);
                 self.trait_map.insert(expr.id, traits);
             }
             _ => {
@@ -3329,8 +3446,8 @@ fn record_candidate_traits_for_expr_if_necessary(&mut self, expr: &Expr) {
         }
     }
 
-    fn search_for_traits_containing_method(&mut self, name: Name) -> Vec<DefId> {
-        debug!("(searching for traits containing method) looking for '{}'",
+    fn get_traits_containing_item(&mut self, name: Name) -> Vec<DefId> {
+        debug!("(getting traits containing item) looking for '{}'",
                token::get_name(name));
 
         fn add_trait_info(found_traits: &mut Vec<DefId>,
index 4dd92b04da5dcc39c389f86056e7fe8caee1fad1..92c9549b37727adbd9263cc95d52120776ef3efd 100644 (file)
@@ -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);
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 57dba30723f9cfeada05c0827494de10bf7160f7..39cfac42011aba8fe8c92d786ca9353c4aa2e15f 100644 (file)
@@ -242,6 +242,7 @@ fn lookup_def_kind(&self, ref_id: NodeId, span: Span) -> Option<recorder::Row> {
             def::DefTrait(_) => Some(recorder::TypeRef),
             def::DefStatic(_, _) |
             def::DefConst(_) |
+            def::DefAssociatedConst(..) |
             def::DefLocal(_) |
             def::DefVariant(_, _, _) |
             def::DefUpvar(..) => Some(recorder::VarRef),
@@ -359,14 +360,10 @@ fn process_method(&mut self, sig: &ast::MethodSig,
         // record the decl for this def (if it has one)
         let decl_id = ty::trait_item_of_item(&self.analysis.ty_cx,
                                              ast_util::local_def(id))
-            .and_then(|def_id| {
-                if match def_id {
-                    ty::MethodTraitItemId(def_id) => {
-                        def_id.node != 0 && def_id != ast_util::local_def(id)
-                    }
-                    ty::TypeTraitItemId(_) => false,
-                } {
-                    Some(def_id.def_id())
+            .and_then(|new_id| {
+                let def_id = new_id.def_id();
+                if def_id.node != 0 && def_id != ast_util::local_def(id) {
+                    Some(def_id)
                 } else {
                     None
                 }
@@ -542,25 +539,27 @@ fn process_static(&mut self,
     }
 
     fn process_const(&mut self,
-                      item: &ast::Item,
-                      typ: &ast::Ty,
-                      expr: &ast::Expr)
+                     id: ast::NodeId,
+                     ident: &ast::Ident,
+                     span: Span,
+                     typ: &ast::Ty,
+                     expr: &ast::Expr)
     {
-        let qualname = format!("::{}", self.analysis.ty_cx.map.path_to_string(item.id));
+        let qualname = format!("::{}", self.analysis.ty_cx.map.path_to_string(id));
 
-        let sub_span = self.span.sub_span_after_keyword(item.span,
+        let sub_span = self.span.sub_span_after_keyword(span,
                                                         keywords::Const);
-        self.fmt.static_str(item.span,
+        self.fmt.static_str(span,
                             sub_span,
-                            item.id,
-                            &get_ident(item.ident),
+                            id,
+                            &get_ident((*ident).clone()),
                             &qualname[..],
                             "",
                             &ty_to_string(&*typ),
                             self.cur_scope);
 
         // walk type and init value
-        self.visit_ty(&*typ);
+        self.visit_ty(typ);
         self.visit_expr(expr);
     }
 
@@ -800,6 +799,7 @@ fn process_path(&mut self,
             def::DefLocal(..) |
             def::DefStatic(..) |
             def::DefConst(..) |
+            def::DefAssociatedConst(..) |
             def::DefVariant(..) => self.fmt.ref_str(ref_kind.unwrap_or(recorder::VarRef),
                                                     span,
                                                     sub_span,
@@ -883,6 +883,7 @@ fn process_path(&mut self,
             def::DefLocal(_) |
             def::DefStatic(_,_) |
             def::DefConst(..) |
+            def::DefAssociatedConst(..) |
             def::DefStruct(_) |
             def::DefVariant(..) |
             def::DefFn(..) => self.write_sub_paths_truncated(path, false),
@@ -966,7 +967,10 @@ fn process_method_call(&mut self,
                     ty::MethodTraitItem(method) => {
                         method.provided_source.unwrap_or(def_id)
                     }
-                    ty::TypeTraitItem(_) => def_id,
+                    _ => self.sess
+                             .span_bug(ex.span,
+                                       "save::process_method_call: non-method \
+                                        DefId in MethodStatic or MethodStaticClosure"),
                 };
                 (Some(def_id), decl_id)
             }
@@ -1008,7 +1012,7 @@ fn process_pat(&mut self, p:&ast::Pat) {
 
                 let def = self.analysis.ty_cx.def_map.borrow().get(&p.id).unwrap().full_def();
                 let struct_def = match def {
-                    def::DefConst(..) => None,
+                    def::DefConst(..) | def::DefAssociatedConst(..) => None,
                     def::DefVariant(_, variant_id, _) => Some(variant_id),
                     _ => {
                         match ty::ty_to_def_id(ty::node_id_to_type(&self.analysis.ty_cx, p.id)) {
@@ -1040,7 +1044,8 @@ fn process_pat(&mut self, p:&ast::Pat) {
                     }
                 }
             }
-            ast::PatEnum(ref path, _) => {
+            ast::PatEnum(ref path, _) |
+            ast::PatQPath(_, ref path) => {
                 self.collected_paths.push((p.id, path.clone(), false, recorder::VarRef));
                 visit::walk_pat(self, p);
             }
@@ -1186,7 +1191,7 @@ fn visit_item(&mut self, item: &ast::Item) {
             ast::ItemStatic(ref typ, mt, ref expr) =>
                 self.process_static(item, &**typ, mt, &**expr),
             ast::ItemConst(ref typ, ref expr) =>
-                self.process_const(item, &**typ, &**expr),
+                self.process_const(item.id, &item.ident, item.span, &*typ, &*expr),
             ast::ItemStruct(ref def, ref ty_params) => self.process_struct(item, &**def, ty_params),
             ast::ItemEnum(ref def, ref ty_params) => self.process_enum(item, def, ty_params),
             ast::ItemImpl(_, _,
@@ -1236,16 +1241,25 @@ fn visit_generics(&mut self, generics: &ast::Generics) {
 
     fn visit_trait_item(&mut self, trait_item: &ast::TraitItem) {
         match trait_item.node {
+            ast::ConstTraitItem(ref ty, Some(ref expr)) => {
+                self.process_const(trait_item.id, &trait_item.ident,
+                                   trait_item.span, &*ty, &*expr);
+            }
             ast::MethodTraitItem(ref sig, ref body) => {
                 self.process_method(sig, body.as_ref().map(|x| &**x),
                                     trait_item.id, trait_item.ident.name, trait_item.span);
             }
+            ast::ConstTraitItem(_, None) |
             ast::TypeTraitItem(..) => {}
         }
     }
 
     fn visit_impl_item(&mut self, impl_item: &ast::ImplItem) {
         match impl_item.node {
+            ast::ConstImplItem(ref ty, ref expr) => {
+                self.process_const(impl_item.id, &impl_item.ident,
+                                   impl_item.span, &*ty, &*expr);
+            }
             ast::MethodImplItem(ref sig, ref body) => {
                 self.process_method(sig, Some(body), impl_item.id,
                                     impl_item.ident.name, impl_item.span);
@@ -1432,8 +1446,9 @@ fn visit_arm(&mut self, arm: &ast::Arm) {
                     paths_to_process.push((id, p.clone(), Some(ref_kind)))
                 }
                 // FIXME(nrc) what are these doing here?
-                def::DefStatic(_, _) => {}
-                def::DefConst(..) => {}
+                def::DefStatic(_, _) |
+                def::DefConst(..) |
+                def::DefAssociatedConst(..) => {}
                 _ => error!("unexpected definition kind when processing collected paths: {:?}",
                             def)
             }
index 744ec5a616841eae4706f156b00f2ba5514725d6..060dde02c2d12269b38fb724153f363f24ac3759 100644 (file)
@@ -916,8 +916,8 @@ fn insert_lllocals<'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
 
         let datum = Datum::new(llval, binding_info.ty, Lvalue);
         if let Some(cs) = cs {
-            bcx.fcx.schedule_drop_and_zero_mem(cs, llval, binding_info.ty);
             bcx.fcx.schedule_lifetime_end(cs, binding_info.llmatch);
+            bcx.fcx.schedule_drop_and_fill_mem(cs, llval, binding_info.ty);
         }
 
         debug!("binding {} to {}", binding_info.id, bcx.val_to_string(llval));
@@ -1809,7 +1809,8 @@ fn bind_irrefutable_pat<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
         ast::PatMac(..) => {
             bcx.sess().span_bug(pat.span, "unexpanded macro");
         }
-        ast::PatWild(_) | ast::PatLit(_) | ast::PatRange(_, _) => ()
+        ast::PatQPath(..) | ast::PatWild(_) | ast::PatLit(_) |
+        ast::PatRange(_, _) => ()
     }
     return bcx;
 }
index d0cbd3370cf9807b5b5540833eba1b1a147ffe6d..cecf35001c4eb00097b85afead452b719da981d7 100644 (file)
@@ -771,6 +771,7 @@ pub fn trans_switch<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
             (_match::Switch, Some(trans_get_discr(bcx, r, scrutinee, None)))
         }
         Univariant(..) => {
+            // N.B.: Univariant means <= 1 enum variants (*not* == 1 variants).
             (_match::Single, None)
         }
     }
@@ -1062,7 +1063,7 @@ pub fn trans_drop_flag_ptr<'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, r: &Repr<'tcx
             ));
             bcx = fold_variants(bcx, r, val, |variant_cx, st, value| {
                 let ptr = struct_field_ptr(variant_cx, st, value, (st.fields.len() - 1), false);
-                datum::Datum::new(ptr, ptr_ty, datum::Rvalue::new(datum::ByRef))
+                datum::Datum::new(ptr, ptr_ty, datum::Lvalue)
                     .store_to(variant_cx, scratch.val)
             });
             let expr_datum = scratch.to_expr_datum();
index 59f3ff72602616f0dfe246234a55fd94f501b385..a049b9a4e49ff8879cf14f4f077de4b5f10e6f0b 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() {
@@ -471,8 +469,11 @@ fn iter_variant<'blk, 'tcx, F>(cx: Block<'blk, 'tcx>,
 
           match adt::trans_switch(cx, &*repr, av) {
               (_match::Single, None) => {
-                  cx = iter_variant(cx, &*repr, av, &*(*variants)[0],
-                                    substs, &mut f);
+                  if n_variants != 0 {
+                      assert!(n_variants == 1);
+                      cx = iter_variant(cx, &*repr, av, &*(*variants)[0],
+                                        substs, &mut f);
+                  }
               }
               (_match::Switch, Some(lldiscrim_a)) => {
                   cx = f(cx, lldiscrim_a, cx.tcx().types.isize);
@@ -1078,25 +1079,17 @@ fn build_cfg(tcx: &ty::ctxt, id: ast::NodeId) -> (ast::NodeId, Option<cfg::CFG>)
         Some(ast_map::NodeTraitItem(trait_item)) => {
             match trait_item.node {
                 ast::MethodTraitItem(_, Some(ref body)) => body,
-                ast::MethodTraitItem(_, None) => {
-                    tcx.sess.bug("unexpected variant: required trait method \
-                                  in has_nested_returns")
-                }
-                ast::TypeTraitItem(..) => {
-                    tcx.sess.bug("unexpected variant: associated type trait item in \
-                                  has_nested_returns")
+                _ => {
+                    tcx.sess.bug("unexpected variant: trait item other than a \
+                                  provided method in has_nested_returns")
                 }
             }
         }
         Some(ast_map::NodeImplItem(impl_item)) => {
             match impl_item.node {
                 ast::MethodImplItem(_, ref body) => body,
-                ast::TypeImplItem(_) => {
-                    tcx.sess.bug("unexpected variant: associated type impl item in \
-                                  has_nested_returns")
-                }
-                ast::MacImplItem(_) => {
-                    tcx.sess.bug("unexpected variant: unexpanded macro impl item in \
+                _ => {
+                    tcx.sess.bug("unexpected variant: non-method impl item in \
                                   has_nested_returns")
                 }
             }
@@ -2363,13 +2356,14 @@ pub fn get_item_val(ccx: &CrateContext, id: ast::NodeId) -> ValueRef {
         ast_map::NodeTraitItem(trait_item) => {
             debug!("get_item_val(): processing a NodeTraitItem");
             match trait_item.node {
-                ast::MethodTraitItem(_, None) | ast::TypeTraitItem(..) => {
-                    ccx.sess().span_bug(trait_item.span,
-                        "unexpected variant: required trait method in get_item_val()");
-                }
                 ast::MethodTraitItem(_, Some(_)) => {
                     register_method(ccx, id, &trait_item.attrs, trait_item.span)
                 }
+                _ => {
+                    ccx.sess().span_bug(trait_item.span,
+                        "unexpected variant: trait item other than a provided \
+                         method in get_item_val()");
+                }
             }
         }
 
@@ -2378,13 +2372,10 @@ pub fn get_item_val(ccx: &CrateContext, id: ast::NodeId) -> ValueRef {
                 ast::MethodImplItem(..) => {
                     register_method(ccx, id, &impl_item.attrs, impl_item.span)
                 }
-                ast::TypeImplItem(_) => {
-                    ccx.sess().span_bug(impl_item.span,
-                        "unexpected variant: associated type in get_item_val()")
-                }
-                ast::MacImplItem(_) => {
+                _ => {
                     ccx.sess().span_bug(impl_item.span,
-                        "unexpected variant: unexpanded macro in get_item_val()")
+                        "unexpected variant: non-method impl item in \
+                         get_item_val()");
                 }
             }
         }
index 0e8c33cd93a5b36e36aa126413960af23eb55aec..0e4680723073f50881e8a0b0b0389ea221996d1a 100644 (file)
@@ -202,6 +202,7 @@ fn trans_def<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
             }
             def::DefStatic(..) |
             def::DefConst(..) |
+            def::DefAssociatedConst(..) |
             def::DefLocal(..) |
             def::DefUpvar(..) => {
                 datum_callee(bcx, ref_expr)
@@ -465,9 +466,9 @@ pub fn trans_fn_ref_with_substs<'a, 'tcx>(
 
                     (true, source_id, new_substs)
                 }
-                ty::TypeTraitItem(_) => {
+                _ => {
                     tcx.sess.bug("trans_fn_ref_with_vtables() tried \
-                                  to translate an associated type?!")
+                                  to translate a non-method?!")
                 }
             }
         }
index 61af5bfaef8dee5db3da83e9ff959fad99ab1963..3ec73ff8eb9de129ffb1b8afe40b9b98556cc570 100644 (file)
@@ -393,19 +393,22 @@ fn schedule_drop_mem(&self,
             must_unwind: common::type_needs_unwind_cleanup(self.ccx, ty),
             val: val,
             ty: ty,
-            zero: false
+            fill_on_drop: false,
+            skip_dtor: false,
         };
 
-        debug!("schedule_drop_mem({:?}, val={}, ty={})",
+        debug!("schedule_drop_mem({:?}, val={}, ty={}) fill_on_drop={} skip_dtor={}",
                cleanup_scope,
                self.ccx.tn().val_to_string(val),
-               ty.repr(self.ccx.tcx()));
+               ty.repr(self.ccx.tcx()),
+               drop.fill_on_drop,
+               drop.skip_dtor);
 
         self.schedule_clean(cleanup_scope, drop as CleanupObj);
     }
 
-    /// Schedules a (deep) drop and zero-ing of `val`, which is a pointer to an instance of `ty`
-    fn schedule_drop_and_zero_mem(&self,
+    /// Schedules a (deep) drop and filling of `val`, which is a pointer to an instance of `ty`
+    fn schedule_drop_and_fill_mem(&self,
                                   cleanup_scope: ScopeId,
                                   val: ValueRef,
                                   ty: Ty<'tcx>) {
@@ -416,14 +419,48 @@ fn schedule_drop_and_zero_mem(&self,
             must_unwind: common::type_needs_unwind_cleanup(self.ccx, ty),
             val: val,
             ty: ty,
-            zero: true
+            fill_on_drop: true,
+            skip_dtor: false,
+        };
+
+        debug!("schedule_drop_and_fill_mem({:?}, val={}, ty={}, fill_on_drop={}, skip_dtor={})",
+               cleanup_scope,
+               self.ccx.tn().val_to_string(val),
+               ty.repr(self.ccx.tcx()),
+               drop.fill_on_drop,
+               drop.skip_dtor);
+
+        self.schedule_clean(cleanup_scope, drop as CleanupObj);
+    }
+
+    /// Issue #23611: Schedules a (deep) drop of the contents of
+    /// `val`, which is a pointer to an instance of struct/enum type
+    /// `ty`. The scheduled code handles extracting the discriminant
+    /// and dropping the contents associated with that variant
+    /// *without* executing any associated drop implementation.
+    fn schedule_drop_enum_contents(&self,
+                                   cleanup_scope: ScopeId,
+                                   val: ValueRef,
+                                   ty: Ty<'tcx>) {
+        // `if` below could be "!contents_needs_drop"; skipping drop
+        // is just an optimization, so sound to be conservative.
+        if !self.type_needs_drop(ty) { return; }
+
+        let drop = box DropValue {
+            is_immediate: false,
+            must_unwind: common::type_needs_unwind_cleanup(self.ccx, ty),
+            val: val,
+            ty: ty,
+            fill_on_drop: false,
+            skip_dtor: true,
         };
 
-        debug!("schedule_drop_and_zero_mem({:?}, val={}, ty={}, zero={})",
+        debug!("schedule_drop_enum_contents({:?}, val={}, ty={}) fill_on_drop={} skip_dtor={}",
                cleanup_scope,
                self.ccx.tn().val_to_string(val),
                ty.repr(self.ccx.tcx()),
-               true);
+               drop.fill_on_drop,
+               drop.skip_dtor);
 
         self.schedule_clean(cleanup_scope, drop as CleanupObj);
     }
@@ -440,13 +477,16 @@ fn schedule_drop_immediate(&self,
             must_unwind: common::type_needs_unwind_cleanup(self.ccx, ty),
             val: val,
             ty: ty,
-            zero: false
+            fill_on_drop: false,
+            skip_dtor: false,
         };
 
-        debug!("schedule_drop_immediate({:?}, val={}, ty={:?})",
+        debug!("schedule_drop_immediate({:?}, val={}, ty={:?}) fill_on_drop={} skip_dtor={}",
                cleanup_scope,
                self.ccx.tn().val_to_string(val),
-               ty.repr(self.ccx.tcx()));
+               ty.repr(self.ccx.tcx()),
+               drop.fill_on_drop,
+               drop.skip_dtor);
 
         self.schedule_clean(cleanup_scope, drop as CleanupObj);
     }
@@ -987,7 +1027,8 @@ pub struct DropValue<'tcx> {
     must_unwind: bool,
     val: ValueRef,
     ty: Ty<'tcx>,
-    zero: bool
+    fill_on_drop: bool,
+    skip_dtor: bool,
 }
 
 impl<'tcx> Cleanup<'tcx> for DropValue<'tcx> {
@@ -1007,13 +1048,18 @@ fn trans<'blk>(&self,
                    bcx: Block<'blk, 'tcx>,
                    debug_loc: DebugLoc)
                    -> Block<'blk, 'tcx> {
-        let _icx = base::push_ctxt("<DropValue as Cleanup>::trans");
+        let skip_dtor = self.skip_dtor;
+        let _icx = if skip_dtor {
+            base::push_ctxt("<DropValue as Cleanup>::trans skip_dtor=true")
+        } else {
+            base::push_ctxt("<DropValue as Cleanup>::trans skip_dtor=false")
+        };
         let bcx = if self.is_immediate {
-            glue::drop_ty_immediate(bcx, self.val, self.ty, debug_loc)
+            glue::drop_ty_immediate(bcx, self.val, self.ty, debug_loc, self.skip_dtor)
         } else {
-            glue::drop_ty(bcx, self.val, self.ty, debug_loc)
+            glue::drop_ty_core(bcx, self.val, self.ty, debug_loc, self.skip_dtor)
         };
-        if self.zero {
+        if self.fill_on_drop {
             base::drop_done_fill_mem(bcx, self.val, self.ty);
         }
         bcx
@@ -1190,10 +1236,14 @@ fn schedule_drop_mem(&self,
                          cleanup_scope: ScopeId,
                          val: ValueRef,
                          ty: Ty<'tcx>);
-    fn schedule_drop_and_zero_mem(&self,
+    fn schedule_drop_and_fill_mem(&self,
                                   cleanup_scope: ScopeId,
                                   val: ValueRef,
                                   ty: Ty<'tcx>);
+    fn schedule_drop_enum_contents(&self,
+                                   cleanup_scope: ScopeId,
+                                   val: ValueRef,
+                                   ty: Ty<'tcx>);
     fn schedule_drop_immediate(&self,
                                cleanup_scope: ScopeId,
                                val: ValueRef,
index 38136b03a214191122270774087afcbf2394333c..9932899ed8f0f64da56f4075ceeb3f6553418892 100644 (file)
@@ -173,13 +173,11 @@ pub fn get_const_expr<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
                             "cross crate constant could not be inlined");
     }
 
-    let item = ccx.tcx().map.expect_item(def_id.node);
-    if let ast::ItemConst(_, ref expr) = item.node {
-        &**expr
-    } else {
-        ccx.sess().span_bug(ref_expr.span,
-                            &format!("get_const_expr given non-constant item {}",
-                                     item.repr(ccx.tcx())));
+    match const_eval::lookup_const_by_id(ccx.tcx(), def_id, Some(ref_expr.id)) {
+        Some(ref expr) => expr,
+        None => {
+            ccx.sess().span_bug(ref_expr.span, "constant item not found")
+        }
     }
 }
 
@@ -201,7 +199,7 @@ pub fn get_const_expr_as_global<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
         ast::ExprPath(..) => {
             let def = ccx.tcx().def_map.borrow().get(&expr.id).unwrap().full_def();
             match def {
-                def::DefConst(def_id) => {
+                def::DefConst(def_id) | def::DefAssociatedConst(def_id, _) => {
                     if !ccx.tcx().adjustments.borrow().contains_key(&expr.id) {
                         return get_const_val(ccx, def_id, expr);
                     }
@@ -774,7 +772,7 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                 def::DefFn(..) | def::DefMethod(..) => {
                     expr::trans_def_fn_unadjusted(cx, e, def, param_substs).val
                 }
-                def::DefConst(def_id) => {
+                def::DefConst(def_id) | def::DefAssociatedConst(def_id, _) => {
                     const_deref_ptr(cx, get_const_val(cx, def_id, e))
                 }
                 def::DefVariant(enum_did, variant_did, _) => {
index b8c45d4751ef8894022e26b28a800420b7e17f92..1506e5b266981fc5bd11097bad1f2769cc02ffd2 100644 (file)
@@ -21,6 +21,7 @@
 use trans::common::{ExternMap,BuilderRef_res};
 use trans::debuginfo;
 use trans::declare;
+use trans::glue::DropGlueKind;
 use trans::monomorphize::MonoId;
 use trans::type_::{Type, TypeNames};
 use middle::subst::Substs;
@@ -73,7 +74,7 @@ pub struct SharedCrateContext<'tcx> {
     check_drop_flag_for_sanity: bool,
 
     available_monomorphizations: RefCell<FnvHashSet<String>>,
-    available_drop_glues: RefCell<FnvHashMap<Ty<'tcx>, String>>,
+    available_drop_glues: RefCell<FnvHashMap<DropGlueKind<'tcx>, String>>,
 }
 
 /// The local portion of a `CrateContext`.  There is one `LocalCrateContext`
@@ -89,7 +90,7 @@ pub struct LocalCrateContext<'tcx> {
     item_vals: RefCell<NodeMap<ValueRef>>,
     needs_unwind_cleanup_cache: RefCell<FnvHashMap<Ty<'tcx>, bool>>,
     fn_pointer_shims: RefCell<FnvHashMap<Ty<'tcx>, ValueRef>>,
-    drop_glues: RefCell<FnvHashMap<Ty<'tcx>, ValueRef>>,
+    drop_glues: RefCell<FnvHashMap<DropGlueKind<'tcx>, ValueRef>>,
     /// Track mapping of external ids to local items imported for inlining
     external: RefCell<DefIdMap<Option<ast::NodeId>>>,
     /// Backwards version of the `external` map (inlined items to where they
@@ -574,7 +575,7 @@ pub fn fn_pointer_shims(&self) -> &RefCell<FnvHashMap<Ty<'tcx>, ValueRef>> {
         &self.local.fn_pointer_shims
     }
 
-    pub fn drop_glues<'a>(&'a self) -> &'a RefCell<FnvHashMap<Ty<'tcx>, ValueRef>> {
+    pub fn drop_glues<'a>(&'a self) -> &'a RefCell<FnvHashMap<DropGlueKind<'tcx>, ValueRef>> {
         &self.local.drop_glues
     }
 
@@ -660,7 +661,7 @@ pub fn available_monomorphizations<'a>(&'a self) -> &'a RefCell<FnvHashSet<Strin
         &self.shared.available_monomorphizations
     }
 
-    pub fn available_drop_glues<'a>(&'a self) -> &'a RefCell<FnvHashMap<Ty<'tcx>, String>> {
+    pub fn available_drop_glues(&self) -> &RefCell<FnvHashMap<DropGlueKind<'tcx>, String>> {
         &self.shared.available_drop_glues
     }
 
index 7c769eca74aabe71669823c41cf0febe067acdc4..516ff443dacb94d87514417f7a6a8ff9ad198fd3 100644 (file)
@@ -1314,15 +1314,10 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                      impl_item.span,
                      true)
                 }
-                ast::TypeImplItem(_) => {
-                    cx.sess().span_bug(impl_item.span,
-                                       "create_function_debug_context() \
-                                        called on associated type?!")
-                }
-                ast::MacImplItem(_) => {
+                _ => {
                     cx.sess().span_bug(impl_item.span,
                                        "create_function_debug_context() \
-                                        called on unexpanded macro?!")
+                                        called on non-method impl item?!")
                 }
             }
         }
@@ -3442,6 +3437,10 @@ fn walk_pattern(cx: &CrateContext,
                 }
             }
 
+            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);
 
index f974796e69cadb7462957d30a81cc67f107e010d..652f6ad366aaa09604301d0f2a9c7e282598d70f 100644 (file)
@@ -30,7 +30,6 @@
 use trans::cleanup;
 use trans::cleanup::CleanupMethods;
 use trans::common::*;
-use trans::datum;
 use trans::debuginfo::DebugLoc;
 use trans::declare;
 use trans::expr;
@@ -132,14 +131,26 @@ pub fn get_drop_glue_type<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
 pub fn drop_ty<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                            v: ValueRef,
                            t: Ty<'tcx>,
-                           debug_loc: DebugLoc)
-                           -> Block<'blk, 'tcx> {
+                           debug_loc: DebugLoc) -> Block<'blk, 'tcx> {
+    drop_ty_core(bcx, v, t, debug_loc, false)
+}
+
+pub fn drop_ty_core<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
+                                v: ValueRef,
+                                t: Ty<'tcx>,
+                                debug_loc: DebugLoc,
+                                skip_dtor: bool) -> Block<'blk, 'tcx> {
     // NB: v is an *alias* of type t here, not a direct value.
-    debug!("drop_ty(t={})", t.repr(bcx.tcx()));
+    debug!("drop_ty_core(t={}, skip_dtor={})", t.repr(bcx.tcx()), skip_dtor);
     let _icx = push_ctxt("drop_ty");
     if bcx.fcx.type_needs_drop(t) {
         let ccx = bcx.ccx();
-        let glue = get_drop_glue(ccx, t);
+        let g = if skip_dtor {
+            DropGlueKind::TyContents(t)
+        } else {
+            DropGlueKind::Ty(t)
+        };
+        let glue = get_drop_glue_core(ccx, g);
         let glue_type = get_drop_glue_type(ccx, t);
         let ptr = if glue_type != t {
             PointerCast(bcx, v, type_of(ccx, glue_type).ptr_to())
@@ -155,22 +166,64 @@ pub fn drop_ty<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
 pub fn drop_ty_immediate<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                                      v: ValueRef,
                                      t: Ty<'tcx>,
-                                     debug_loc: DebugLoc)
+                                     debug_loc: DebugLoc,
+                                     skip_dtor: bool)
                                      -> Block<'blk, 'tcx> {
     let _icx = push_ctxt("drop_ty_immediate");
     let vp = alloca(bcx, type_of(bcx.ccx(), t), "");
     store_ty(bcx, v, vp, t);
-    drop_ty(bcx, vp, t, debug_loc)
+    drop_ty_core(bcx, vp, t, debug_loc, skip_dtor)
 }
 
 pub fn get_drop_glue<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> ValueRef {
-    debug!("make drop glue for {}", ppaux::ty_to_string(ccx.tcx(), t));
-    let t = get_drop_glue_type(ccx, t);
-    debug!("drop glue type {}", ppaux::ty_to_string(ccx.tcx(), t));
-    match ccx.drop_glues().borrow().get(&t) {
+    get_drop_glue_core(ccx, DropGlueKind::Ty(t))
+}
+
+#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
+pub enum DropGlueKind<'tcx> {
+    /// The normal path; runs the dtor, and then recurs on the contents
+    Ty(Ty<'tcx>),
+    /// Skips the dtor, if any, for ty; drops the contents directly.
+    /// Note that the dtor is only skipped at the most *shallow*
+    /// level, namely, an `impl Drop for Ty` itself. So, for example,
+    /// if Ty is Newtype(S) then only the Drop impl for for Newtype
+    /// itself will be skipped, while the Drop impl for S, if any,
+    /// will be invoked.
+    TyContents(Ty<'tcx>),
+}
+
+impl<'tcx> DropGlueKind<'tcx> {
+    fn ty(&self) -> Ty<'tcx> {
+        match *self { DropGlueKind::Ty(t) | DropGlueKind::TyContents(t) => t }
+    }
+
+    fn map_ty<F>(&self, mut f: F) -> DropGlueKind<'tcx> where F: FnMut(Ty<'tcx>) -> Ty<'tcx>
+    {
+        match *self {
+            DropGlueKind::Ty(t) => DropGlueKind::Ty(f(t)),
+            DropGlueKind::TyContents(t) => DropGlueKind::TyContents(f(t)),
+        }
+    }
+
+    fn to_string<'a>(&self, ccx: &CrateContext<'a, 'tcx>) -> String {
+        let t_str = ppaux::ty_to_string(ccx.tcx(), self.ty());
+        match *self {
+            DropGlueKind::Ty(_) => format!("DropGlueKind::Ty({})", t_str),
+            DropGlueKind::TyContents(_) => format!("DropGlueKind::TyContents({})", t_str),
+        }
+    }
+}
+
+fn get_drop_glue_core<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
+                                g: DropGlueKind<'tcx>) -> ValueRef {
+    debug!("make drop glue for {}", g.to_string(ccx));
+    let g = g.map_ty(|t| get_drop_glue_type(ccx, t));
+    debug!("drop glue type {}", g.to_string(ccx));
+    match ccx.drop_glues().borrow().get(&g) {
         Some(&glue) => return glue,
         _ => { }
     }
+    let t = g.ty();
 
     let llty = if type_is_sized(ccx.tcx(), t) {
         type_of(ccx, t).ptr_to()
@@ -182,9 +235,9 @@ pub fn get_drop_glue<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Val
 
     // To avoid infinite recursion, don't `make_drop_glue` until after we've
     // added the entry to the `drop_glues` cache.
-    if let Some(old_sym) = ccx.available_drop_glues().borrow().get(&t) {
+    if let Some(old_sym) = ccx.available_drop_glues().borrow().get(&g) {
         let llfn = declare::declare_cfn(ccx, &old_sym, llfnty, ty::mk_nil(ccx.tcx()));
-        ccx.drop_glues().borrow_mut().insert(t, llfn);
+        ccx.drop_glues().borrow_mut().insert(g, llfn);
         return llfn;
     };
 
@@ -192,7 +245,7 @@ pub fn get_drop_glue<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Val
     let llfn = declare::define_cfn(ccx, &fn_nm, llfnty, ty::mk_nil(ccx.tcx())).unwrap_or_else(||{
        ccx.sess().bug(&format!("symbol `{}` already defined", fn_nm));
     });
-    ccx.available_drop_glues().borrow_mut().insert(t, fn_nm);
+    ccx.available_drop_glues().borrow_mut().insert(g, fn_nm);
 
     let _s = StatRecorder::new(ccx, format!("drop {}", ty_to_short_str(ccx.tcx(), t)));
 
@@ -217,7 +270,7 @@ pub fn get_drop_glue<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Val
     // type, so we don't need to explicitly cast the function parameter.
 
     let llrawptr0 = get_param(llfn, fcx.arg_pos(0) as c_uint);
-    let bcx = make_drop_glue(bcx, llrawptr0, t);
+    let bcx = make_drop_glue(bcx, llrawptr0, g);
     finish_fn(&fcx, bcx, ty::FnConverging(ty::mk_nil(ccx.tcx())), DebugLoc::None);
 
     llfn
@@ -307,88 +360,36 @@ fn trans_struct_drop<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                                  substs: &subst::Substs<'tcx>)
                                  -> Block<'blk, 'tcx>
 {
-    let repr = adt::represent_type(bcx.ccx(), t);
+    debug!("trans_struct_drop t: {}", bcx.ty_to_string(t));
 
     // Find and call the actual destructor
-    let dtor_addr = get_res_dtor(bcx.ccx(), dtor_did, t,
-                                 class_did, substs);
+    let dtor_addr = get_res_dtor(bcx.ccx(), dtor_did, t, class_did, substs);
 
-    // The first argument is the "self" argument for drop
+    // Class dtors have no explicit args, so the params should
+    // just consist of the environment (self).
     let params = unsafe {
         let ty = Type::from_ref(llvm::LLVMTypeOf(dtor_addr));
         ty.element_type().func_params()
     };
+    assert_eq!(params.len(), 1);
 
-    let fty = ty::lookup_item_type(bcx.tcx(), dtor_did).ty.subst(bcx.tcx(), substs);
-    let self_ty = match fty.sty {
-        ty::ty_bare_fn(_, ref f) => {
-            let sig = ty::erase_late_bound_regions(bcx.tcx(), &f.sig);
-            assert!(sig.inputs.len() == 1);
-            sig.inputs[0]
-        }
-        _ => bcx.sess().bug(&format!("Expected function type, found {}",
-                                    bcx.ty_to_string(fty)))
-    };
-
-    let (struct_data, info) = if type_is_sized(bcx.tcx(), t) {
-        (v0, None)
-    } else {
-        let data = GEPi(bcx, v0, &[0, abi::FAT_PTR_ADDR]);
-        let info = GEPi(bcx, v0, &[0, abi::FAT_PTR_EXTRA]);
-        (Load(bcx, data), Some(Load(bcx, info)))
-    };
-
-    adt::fold_variants(bcx, &*repr, struct_data, |variant_cx, st, value| {
-        // Be sure to put all of the fields into a scope so we can use an invoke
-        // instruction to call the user destructor but still call the field
-        // destructors if the user destructor panics.
-        let field_scope = variant_cx.fcx.push_custom_cleanup_scope();
-
-        // Class dtors have no explicit args, so the params should
-        // just consist of the environment (self).
-        assert_eq!(params.len(), 1);
-        let self_arg = if type_is_fat_ptr(bcx.tcx(), self_ty) {
-            // The dtor expects a fat pointer, so make one, even if we have to fake it.
-            let scratch = datum::rvalue_scratch_datum(bcx, t, "__fat_ptr_drop_self");
-            Store(bcx, value, GEPi(bcx, scratch.val, &[0, abi::FAT_PTR_ADDR]));
-            Store(bcx,
-                  // If we just had a thin pointer, make a fat pointer by sticking
-                  // null where we put the unsizing info. This works because t
-                  // is a sized type, so we will only unpack the fat pointer, never
-                  // use the fake info.
-                  info.unwrap_or(C_null(Type::i8p(bcx.ccx()))),
-                  GEPi(bcx, scratch.val, &[0, abi::FAT_PTR_EXTRA]));
-            PointerCast(variant_cx, scratch.val, params[0])
-        } else {
-            PointerCast(variant_cx, value, params[0])
-        };
-        let args = vec!(self_arg);
+    // Be sure to put the contents into a scope so we can use an invoke
+    // instruction to call the user destructor but still call the field
+    // destructors if the user destructor panics.
+    //
+    // FIXME (#14875) panic-in-drop semantics might be unsupported; we
+    // might well consider changing below to more direct code.
+    let contents_scope = bcx.fcx.push_custom_cleanup_scope();
 
-        // Add all the fields as a value which needs to be cleaned at the end of
-        // this scope. Iterate in reverse order so a Drop impl doesn't reverse
-        // the order in which fields get dropped.
-        for (i, &ty) in st.fields.iter().enumerate().rev() {
-            let llfld_a = adt::struct_field_ptr(variant_cx, &*st, value, i, false);
+    // Issue #23611: schedule cleanup of contents, re-inspecting the
+    // discriminant (if any) in case of variant swap in drop code.
+    bcx.fcx.schedule_drop_enum_contents(cleanup::CustomScope(contents_scope), v0, t);
 
-            let val = if type_is_sized(bcx.tcx(), ty) {
-                llfld_a
-            } else {
-                let scratch = datum::rvalue_scratch_datum(bcx, ty, "__fat_ptr_drop_field");
-                Store(bcx, llfld_a, GEPi(bcx, scratch.val, &[0, abi::FAT_PTR_ADDR]));
-                Store(bcx, info.unwrap(), GEPi(bcx, scratch.val, &[0, abi::FAT_PTR_EXTRA]));
-                scratch.val
-            };
-            variant_cx.fcx.schedule_drop_mem(cleanup::CustomScope(field_scope), val, ty);
-        }
-
-        let dtor_ty = ty::mk_ctor_fn(bcx.tcx(),
-                                     class_did,
-                                     &[get_drop_glue_type(bcx.ccx(), t)],
-                                     ty::mk_nil(bcx.tcx()));
-        let (_, variant_cx) = invoke(variant_cx, dtor_addr, &args[..], dtor_ty, DebugLoc::None);
+    let glue_type = get_drop_glue_type(bcx.ccx(), t);
+    let dtor_ty = ty::mk_ctor_fn(bcx.tcx(), class_did, &[glue_type], ty::mk_nil(bcx.tcx()));
+    let (_, bcx) = invoke(bcx, dtor_addr, &[v0], dtor_ty, DebugLoc::None);
 
-        variant_cx.fcx.pop_and_trans_custom_cleanup_scope(variant_cx, field_scope)
-    })
+    bcx.fcx.pop_and_trans_custom_cleanup_scope(bcx, contents_scope)
 }
 
 fn size_and_align_of_dst<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, t: Ty<'tcx>, info: ValueRef)
@@ -454,8 +455,10 @@ fn size_and_align_of_dst<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, t: Ty<'tcx>, info:
     }
 }
 
-fn make_drop_glue<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, v0: ValueRef, t: Ty<'tcx>)
+fn make_drop_glue<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, v0: ValueRef, g: DropGlueKind<'tcx>)
                               -> Block<'blk, 'tcx> {
+    let t = g.ty();
+    let skip_dtor = match g { DropGlueKind::Ty(_) => false, DropGlueKind::TyContents(_) => true };
     // NB: v0 is an *alias* of type t here, not a direct value.
     let _icx = push_ctxt("make_drop_glue");
 
@@ -469,6 +472,10 @@ fn make_drop_glue<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, v0: ValueRef, t: Ty<'tcx>)
 
     match t.sty {
         ty::ty_uniq(content_ty) => {
+            // Support for ty_uniq is built-in and its drop glue is
+            // special. It may move to library and have Drop impl. As
+            // a safe-guard, assert ty_uniq not used with TyContents.
+            assert!(!skip_dtor);
             if !type_is_sized(bcx.tcx(), content_ty) {
                 let llval = GEPi(bcx, v0, &[0, abi::FAT_PTR_ADDR]);
                 let llbox = Load(bcx, llval);
@@ -505,8 +512,8 @@ fn make_drop_glue<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, v0: ValueRef, t: Ty<'tcx>)
         }
         ty::ty_struct(did, substs) | ty::ty_enum(did, substs) => {
             let tcx = bcx.tcx();
-            match ty::ty_dtor(tcx, did) {
-                ty::TraitDtor(dtor, true) => {
+            match (ty::ty_dtor(tcx, did), skip_dtor) {
+                (ty::TraitDtor(dtor, true), false) => {
                     // FIXME(16758) Since the struct is unsized, it is hard to
                     // find the drop flag (which is at the end of the struct).
                     // Lets just ignore the flag and pretend everything will be
@@ -523,16 +530,20 @@ fn make_drop_glue<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, v0: ValueRef, t: Ty<'tcx>)
                         trans_struct_drop(bcx, t, v0, dtor, did, substs)
                     }
                 }
-                ty::TraitDtor(dtor, false) => {
+                (ty::TraitDtor(dtor, false), false) => {
                     trans_struct_drop(bcx, t, v0, dtor, did, substs)
                 }
-                ty::NoDtor => {
+                (ty::NoDtor, _) | (_, true) => {
                     // No dtor? Just the default case
                     iter_structural_ty(bcx, v0, t, |bb, vv, tt| drop_ty(bb, vv, tt, DebugLoc::None))
                 }
             }
         }
         ty::ty_trait(..) => {
+            // No support in vtable for distinguishing destroying with
+            // versus without calling Drop::drop. Assert caller is
+            // okay with always calling the Drop impl, if any.
+            assert!(!skip_dtor);
             let data_ptr = GEPi(bcx, v0, &[0, abi::FAT_PTR_ADDR]);
             let vtable_ptr = Load(bcx, GEPi(bcx, v0, &[0, abi::FAT_PTR_EXTRA]));
             let dtor = Load(bcx, vtable_ptr);
index 2034c6223c13410d0d77b964d1043cda27309b86..3f44bc40f356b7f51362525272d4123adade4c39 100644 (file)
@@ -134,6 +134,14 @@ fn instantiate_inline(ccx: &CrateContext, fn_id: ast::DefId)
 
             ccx.stats().n_inlines.set(ccx.stats().n_inlines.get() + 1);
 
+            // Associated consts already have to be evaluated in `typeck`, so
+            // the logic to do that already exists in `middle`. In order to
+            // reuse that code, it needs to be able to look up the traits for
+            // inlined items.
+            let ty_trait_item = ty::impl_or_trait_item(ccx.tcx(), fn_id).clone();
+            ccx.tcx().impl_or_trait_items.borrow_mut()
+                     .insert(local_def(trait_item.id), ty_trait_item);
+
             // If this is a default method, we can't look up the
             // impl type. But we aren't going to translate anyways, so
             // don't.
index e346fb0d93189a1b52ea245d54a6441b89df82c8..fda931fde6e6c8b14a03acf55092f3ea5cbfdea5 100644 (file)
@@ -74,8 +74,7 @@ pub fn trans_impl(ccx: &CrateContext,
                 ast::MethodImplItem(..) => {
                     visit::walk_impl_item(&mut v, impl_item);
                 }
-                ast::TypeImplItem(_) |
-                ast::MacImplItem(_) => {}
+                _ => {}
             }
         }
         return;
@@ -98,8 +97,7 @@ pub fn trans_impl(ccx: &CrateContext,
                 }
                 visit::walk_impl_item(&mut v, impl_item);
             }
-            ast::TypeImplItem(_) |
-            ast::MacImplItem(_) => {}
+            _ => {}
         }
     }
 }
@@ -336,9 +334,9 @@ fn trans_monomorphized_callee<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
             let impl_did = vtable_impl.impl_def_id;
             let mname = match ty::trait_item(ccx.tcx(), trait_id, n_method) {
                 ty::MethodTraitItem(method) => method.name,
-                ty::TypeTraitItem(_) => {
-                    bcx.tcx().sess.bug("can't monomorphize an associated \
-                                        type")
+                _ => {
+                    bcx.tcx().sess.bug("can't monomorphize a non-method trait \
+                                        item")
                 }
             };
             let mth_id = method_with_name(bcx.ccx(), impl_did, mname);
@@ -579,8 +577,8 @@ pub fn trans_object_shim<'a, 'tcx>(
     // Lookup the type of this method as declared in the trait and apply substitutions.
     let method_ty = match ty::trait_item(tcx, trait_id, method_offset_in_trait) {
         ty::MethodTraitItem(method) => method,
-        ty::TypeTraitItem(_) => {
-            tcx.sess.bug("can't create a method shim for an associated type")
+        _ => {
+            tcx.sess.bug("can't create a method shim for a non-method item")
         }
     };
     let fty = monomorphize::apply_param_substs(tcx, &object_substs, &method_ty.fty);
@@ -789,11 +787,11 @@ fn emit_vtable_methods<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
     trait_item_def_ids
         .iter()
 
-        // Filter out the associated types.
+        // Filter out non-method items.
         .filter_map(|item_def_id| {
             match *item_def_id {
                 ty::MethodTraitItemId(def_id) => Some(def_id),
-                ty::TypeTraitItemId(_) => None,
+                _ => None,
             }
         })
 
@@ -806,7 +804,7 @@ fn emit_vtable_methods<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
 
             let trait_method_type = match ty::impl_or_trait_item(tcx, trait_method_def_id) {
                 ty::MethodTraitItem(m) => m,
-                ty::TypeTraitItem(_) => ccx.sess().bug("should be a method, not assoc type")
+                _ => ccx.sess().bug("should be a method, not other assoc item"),
             };
             let name = trait_method_type.name;
 
@@ -824,7 +822,7 @@ fn emit_vtable_methods<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
             let impl_method_def_id = method_with_name(ccx, impl_id, name);
             let impl_method_type = match ty::impl_or_trait_item(tcx, impl_method_def_id) {
                 ty::MethodTraitItem(m) => m,
-                ty::TypeTraitItem(_) => ccx.sess().bug("should be a method, not assoc type")
+                _ => ccx.sess().bug("should be a method, not other assoc item"),
             };
 
             debug!("emit_vtable_methods: impl_method_type={}",
index 1c8d020494fabfa0788d0c053d3ea0a37d38c3bb..03fdd0c45c16ae6aa37d19e01b8673ca26956ed5 100644 (file)
@@ -236,11 +236,9 @@ pub fn monomorphic_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
                     }
                     d
                 }
-                ast::TypeImplItem(_) => {
-                    ccx.sess().bug("can't monomorphize an associated type")
-                }
-                ast::MacImplItem(_) => {
-                    ccx.sess().bug("can't monomorphize an unexpanded macro")
+                _ => {
+                    ccx.sess().bug(&format!("can't monomorphize a {:?}",
+                                           map_node))
                 }
             }
         }
index 0959f9d1b9154e4e2df4dcb30d1424e68b339938..1f4d6cc2fd471b4b8e04539edcb12438dedc6c36 100644 (file)
 use middle::const_eval;
 use middle::def;
 use middle::infer;
-use middle::pat_util::{PatIdMap, pat_id_map, pat_is_binding, pat_is_const};
+use middle::pat_util::{PatIdMap, pat_id_map, pat_is_binding};
+use middle::pat_util::pat_is_resolved_const;
+use middle::privacy::{AllPublic, LastMod};
 use middle::subst::Substs;
 use middle::ty::{self, Ty};
 use check::{check_expr, check_expr_has_type, check_expr_with_expectation};
 use check::{check_expr_coercable_to_type, demand, FnCtxt, Expectation};
-use check::{instantiate_path, structurally_resolved_type};
+use check::{instantiate_path, resolve_ty_and_def_ufcs, structurally_resolved_type};
 use require_same_types;
 use util::nodemap::FnvHashMap;
 use util::ppaux::Repr;
@@ -118,7 +120,7 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
             // subtyping doesn't matter here, as the value is some kind of scalar
             demand::eqtype(fcx, pat.span, expected, lhs_ty);
         }
-        ast::PatEnum(..) | ast::PatIdent(..) if pat_is_const(&tcx.def_map, pat) => {
+        ast::PatEnum(..) | ast::PatIdent(..) if pat_is_resolved_const(&tcx.def_map, pat) => {
             let const_did = tcx.def_map.borrow().get(&pat.id).unwrap().def_id();
             let const_scheme = ty::lookup_item_type(tcx, const_did);
             assert!(const_scheme.generics.is_empty());
@@ -181,6 +183,37 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
             let subpats = subpats.as_ref().map(|v| &v[..]);
             check_pat_enum(pcx, pat, path, subpats, expected);
         }
+        ast::PatQPath(ref qself, ref path) => {
+            let self_ty = fcx.to_ty(&qself.ty);
+            let path_res = if let Some(&d) = tcx.def_map.borrow().get(&pat.id) {
+                d
+            } else if qself.position == 0 {
+                def::PathResolution {
+                    // This is just a sentinel for finish_resolving_def_to_ty.
+                    base_def: def::DefMod(ast_util::local_def(ast::CRATE_NODE_ID)),
+                    last_private: LastMod(AllPublic),
+                    depth: path.segments.len()
+                }
+            } else {
+                tcx.sess.span_bug(pat.span,
+                                  &format!("unbound path {}", pat.repr(tcx)))
+            };
+            if let Some((opt_ty, segments, def)) =
+                    resolve_ty_and_def_ufcs(fcx, path_res, Some(self_ty),
+                                            path, pat.span, pat.id) {
+                if check_assoc_item_is_const(pcx, def, pat.span) {
+                    let scheme = ty::lookup_item_type(tcx, def.def_id());
+                    let predicates = ty::lookup_predicates(tcx, def.def_id());
+                    instantiate_path(fcx, segments,
+                                     scheme, &predicates,
+                                     opt_ty, def, pat.span, pat.id);
+                    let const_ty = fcx.node_ty(pat.id);
+                    demand::suptype(fcx, pat.span, expected, const_ty);
+                } else {
+                    fcx.write_error(pat.id)
+                }
+            }
+        }
         ast::PatStruct(ref path, ref fields, etc) => {
             check_pat_struct(pcx, pat, path, fields, etc, expected);
         }
@@ -331,6 +364,21 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
     // subtyping.
 }
 
+fn check_assoc_item_is_const(pcx: &pat_ctxt, def: def::Def, span: Span) -> bool {
+    match def {
+        def::DefAssociatedConst(..) => true,
+        def::DefMethod(..) => {
+            span_err!(pcx.fcx.ccx.tcx.sess, span, E0327,
+                      "associated items in match patterns must be constants");
+            false
+        }
+        _ => {
+            pcx.fcx.ccx.tcx.sess.span_bug(span, "non-associated item in
+                                                 check_assoc_item_is_const");
+        }
+    }
+}
+
 pub fn check_dereferencable<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
                                       span: Span, expected: Ty<'tcx>,
                                       inner: &ast::Pat) -> bool {
@@ -532,7 +580,24 @@ pub fn check_pat_enum<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
     let fcx = pcx.fcx;
     let tcx = pcx.fcx.ccx.tcx;
 
-    let def = tcx.def_map.borrow().get(&pat.id).unwrap().full_def();
+    let path_res = *tcx.def_map.borrow().get(&pat.id).unwrap();
+
+    let (opt_ty, segments, def) = match resolve_ty_and_def_ufcs(fcx, path_res,
+                                                                None, path,
+                                                                pat.span, pat.id) {
+        Some(resolution) => resolution,
+        // Error handling done inside resolve_ty_and_def_ufcs, so if
+        // resolution fails just return.
+        None => {return;}
+    };
+
+    // Items that were partially resolved before should have been resolved to
+    // associated constants (i.e. not methods).
+    if path_res.depth != 0 && !check_assoc_item_is_const(pcx, def, pat.span) {
+        fcx.write_error(pat.id);
+        return;
+    }
+
     let enum_def = def.variant_def_ids()
         .map_or_else(|| def.def_id(), |(enum_def, _)| enum_def);
 
@@ -547,13 +612,23 @@ pub fn check_pat_enum<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
     } else {
         ctor_scheme
     };
-    instantiate_path(pcx.fcx, &path.segments,
+    instantiate_path(pcx.fcx, segments,
                      path_scheme, &ctor_predicates,
-                     None, def, pat.span, pat.id);
+                     opt_ty, def, pat.span, pat.id);
+
+    // If we didn't have a fully resolved path to start with, we had an
+    // associated const, and we should quit now, since the rest of this
+    // function uses checks specific to structs and enums.
+    if path_res.depth != 0 {
+        let pat_ty = fcx.node_ty(pat.id);
+        demand::suptype(fcx, pat.span, expected, pat_ty);
+        return;
+    }
 
     let pat_ty = fcx.node_ty(pat.id);
     demand::eqtype(fcx, pat.span, expected, pat_ty);
 
+
     let real_path_ty = fcx.node_ty(pat.id);
     let (arg_tys, kind_name): (Vec<_>, &'static str) = match real_path_ty.sty {
         ty::ty_enum(enum_def_id, expected_substs)
index c4ee7e79570da570d57deabf1d08e16e42c52ddc..b3267a5be495b4df92f5157913b5ff93bee04b76 100644 (file)
@@ -412,3 +412,85 @@ fn check_region_bounds_on_impl_method<'tcx>(tcx: &ty::ctxt<'tcx>,
         return true;
     }
 }
+
+pub fn compare_const_impl<'tcx>(tcx: &ty::ctxt<'tcx>,
+                                impl_c: &ty::AssociatedConst<'tcx>,
+                                impl_c_span: Span,
+                                trait_c: &ty::AssociatedConst<'tcx>,
+                                impl_trait_ref: &ty::TraitRef<'tcx>) {
+    debug!("compare_const_impl(impl_trait_ref={})",
+           impl_trait_ref.repr(tcx));
+
+    let infcx = infer::new_infer_ctxt(tcx);
+    let mut fulfillment_cx = traits::FulfillmentContext::new();
+
+    // The below is for the most part highly similar to the procedure
+    // for methods above. It is simpler in many respects, especially
+    // because we shouldn't really have to deal with lifetimes or
+    // predicates. In fact some of this should probably be put into
+    // shared functions because of DRY violations...
+    let trait_to_impl_substs = &impl_trait_ref.substs;
+
+    // Create a parameter environment that represents the implementation's
+    // method.
+    let impl_param_env =
+        ty::ParameterEnvironment::for_item(tcx, impl_c.def_id.node);
+
+    // Create mapping from impl to skolemized.
+    let impl_to_skol_substs = &impl_param_env.free_substs;
+
+    // Create mapping from trait to skolemized.
+    let trait_to_skol_substs =
+        trait_to_impl_substs
+        .subst(tcx, impl_to_skol_substs)
+        .with_method(impl_to_skol_substs.types.get_slice(subst::FnSpace).to_vec(),
+                     impl_to_skol_substs.regions().get_slice(subst::FnSpace).to_vec());
+    debug!("compare_const_impl: trait_to_skol_substs={}",
+           trait_to_skol_substs.repr(tcx));
+
+    // Compute skolemized form of impl and trait const tys.
+    let impl_ty = impl_c.ty.subst(tcx, impl_to_skol_substs);
+    let trait_ty = trait_c.ty.subst(tcx, &trait_to_skol_substs);
+
+    let err = infcx.commit_if_ok(|_| {
+        let origin = infer::Misc(impl_c_span);
+
+        // There is no "body" here, so just pass dummy id.
+        let impl_ty =
+            assoc::normalize_associated_types_in(&infcx,
+                                                 &impl_param_env,
+                                                 &mut fulfillment_cx,
+                                                 impl_c_span,
+                                                 0,
+                                                 &impl_ty);
+        debug!("compare_const_impl: impl_ty={}",
+               impl_ty.repr(tcx));
+
+        let trait_ty =
+            assoc::normalize_associated_types_in(&infcx,
+                                                 &impl_param_env,
+                                                 &mut fulfillment_cx,
+                                                 impl_c_span,
+                                                 0,
+                                                 &trait_ty);
+        debug!("compare_const_impl: trait_ty={}",
+               trait_ty.repr(tcx));
+
+        infer::mk_subty(&infcx, false, origin, impl_ty, trait_ty)
+    });
+
+    match err {
+        Ok(()) => { }
+        Err(terr) => {
+            debug!("checking associated const for compatibility: impl ty {}, trait ty {}",
+                   impl_ty.repr(tcx),
+                   trait_ty.repr(tcx));
+            span_err!(tcx.sess, impl_c_span, E0326,
+                      "implemented const `{}` has an incompatible type for \
+                      trait: {}",
+                      token::get_name(trait_c.name),
+                      ty::type_err_to_str(tcx, &terr));
+            return;
+        }
+    }
+}
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 7eb15a147963477a002de0e89c3443f51ea87ed3..cf1323e71bd0e94806d8ab03db4b9ff273af31db 100644 (file)
@@ -109,10 +109,11 @@ fn confirm(&mut self,
         self.add_obligations(&pick, &all_substs, &method_predicates);
 
         // Create the final `MethodCallee`.
+        let method_ty = pick.item.as_opt_method().unwrap();
         let fty = ty::mk_bare_fn(self.tcx(), None, self.tcx().mk_bare_fn(ty::BareFnTy {
             sig: ty::Binder(method_sig),
-            unsafety: pick.method_ty.fty.unsafety,
-            abi: pick.method_ty.fty.abi.clone(),
+            unsafety: method_ty.fty.unsafety,
+            abi: method_ty.fty.abi.clone(),
         }));
         let callee = MethodCallee {
             origin: method_origin,
@@ -204,7 +205,7 @@ fn fresh_receiver_substs(&mut self,
                         "impl {:?} is not an inherent impl", impl_def_id);
                 let impl_polytype = check::impl_self_ty(self.fcx, self.span, impl_def_id);
 
-                (impl_polytype.substs, MethodStatic(pick.method_ty.def_id))
+                (impl_polytype.substs, MethodStatic(pick.item.def_id()))
             }
 
             probe::ObjectPick(trait_def_id, method_num, vtable_index) => {
@@ -336,7 +337,8 @@ fn instantiate_method_substs(&mut self,
         // If they were not explicitly supplied, just construct fresh
         // variables.
         let num_supplied_types = supplied_method_types.len();
-        let num_method_types = pick.method_ty.generics.types.len(subst::FnSpace);
+        let num_method_types = pick.item.as_opt_method().unwrap()
+                                   .generics.types.len(subst::FnSpace);
         let method_types = {
             if num_supplied_types == 0 {
                 self.fcx.infcx().next_ty_vars(num_method_types)
@@ -360,7 +362,8 @@ fn instantiate_method_substs(&mut self,
         let method_regions =
             self.fcx.infcx().region_vars_for_defs(
                 self.span,
-                pick.method_ty.generics.regions.get_slice(subst::FnSpace));
+                pick.item.as_opt_method().unwrap()
+                    .generics.regions.get_slice(subst::FnSpace));
 
         (method_types, method_regions)
     }
@@ -397,7 +400,8 @@ fn instantiate_method_sig(&mut self,
         // Instantiate the bounds on the method with the
         // type/early-bound-regions substitutions performed. There can
         // be no late-bound regions appearing here.
-        let method_predicates = pick.method_ty.predicates.instantiate(self.tcx(), &all_substs);
+        let method_predicates = pick.item.as_opt_method().unwrap()
+                                    .predicates.instantiate(self.tcx(), &all_substs);
         let method_predicates = self.fcx.normalize_associated_types_in(self.span,
                                                                        &method_predicates);
 
@@ -410,7 +414,8 @@ fn instantiate_method_sig(&mut self,
         // NB: Instantiate late-bound regions first so that
         // `instantiate_type_scheme` can normalize associated types that
         // may reference those regions.
-        let method_sig = self.replace_late_bound_regions_with_fresh_var(&pick.method_ty.fty.sig);
+        let method_sig = self.replace_late_bound_regions_with_fresh_var(
+            &pick.item.as_opt_method().unwrap().fty.sig);
         debug!("late-bound lifetimes from method instantiated, method_sig={}",
                method_sig.repr(self.tcx()));
 
@@ -616,7 +621,7 @@ fn infcx(&self) -> &'a InferCtxt<'a, 'tcx> {
 
     fn enforce_illegal_method_limitations(&self, pick: &probe::Pick) {
         // Disallow calls to the method `drop` defined in the `Drop` trait.
-        match pick.method_ty.container {
+        match pick.item.container() {
             ty::TraitContainer(trait_def_id) => {
                 callee::check_legal_trait_for_method_call(self.fcx.ccx, self.span, trait_def_id)
             }
@@ -625,7 +630,7 @@ fn enforce_illegal_method_limitations(&self, pick: &probe::Pick) {
                 // potential calls to it will wind up in the other
                 // arm. But just to be sure, check that the method id
                 // does not appear in the list of destructors.
-                assert!(!self.tcx().destructors.borrow().contains(&pick.method_ty.def_id));
+                assert!(!self.tcx().destructors.borrow().contains(&pick.item.def_id()));
             }
         }
     }
index f1a4dbf7cd52881c7ceb1d88463f0161c51cccbc..c5d8e2758ba5c6a9c3538538862bc261c6646470 100644 (file)
@@ -58,7 +58,7 @@ pub enum CandidateSource {
     TraitSource(/* trait id */ ast::DefId),
 }
 
-type MethodIndex = usize; // just for doc purposes
+type ItemIndex = usize; // just for doc purposes
 
 /// Determines whether the type `self_ty` supports a method name `method_name` or not.
 pub fn exists<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
@@ -312,18 +312,25 @@ pub fn resolve_ufcs<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
 {
     let mode = probe::Mode::Path;
     let pick = try!(probe::probe(fcx, span, mode, method_name, self_ty, expr_id));
-    let def_id = pick.method_ty.def_id;
+    let def_id = pick.item.def_id();
     let mut lp = LastMod(AllPublic);
     let provenance = match pick.kind {
         probe::InherentImplPick(impl_def_id) => {
-            if pick.method_ty.vis != ast::Public {
+            if pick.item.vis() != ast::Public {
                 lp = LastMod(DependsOn(def_id));
             }
             def::FromImpl(impl_def_id)
         }
-        _ => def::FromTrait(pick.method_ty.container.id())
+        _ => def::FromTrait(pick.item.container().id())
     };
-    Ok((def::DefMethod(def_id, provenance), lp))
+    let def_result = match pick.item {
+        ImplOrTraitItem::MethodTraitItem(..) => def::DefMethod(def_id, provenance),
+        ImplOrTraitItem::ConstTraitItem(..) => def::DefAssociatedConst(def_id, provenance),
+        ImplOrTraitItem::TypeTraitItem(..) => {
+            fcx.tcx().sess.span_bug(span, "resolve_ufcs: probe picked associated type");
+        }
+    };
+    Ok((def_result, lp))
 }
 
 
index 08e2f47c5a67583157ff010c4b7204247cedad51..7ff1355184b56ade0e49fc903c3b849dc06e7cdb 100644 (file)
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 use super::MethodError;
-use super::MethodIndex;
+use super::ItemIndex;
 use super::{CandidateSource,ImplSource,TraitSource};
 use super::suggest;
 
@@ -37,7 +37,7 @@ struct ProbeContext<'a, 'tcx:'a> {
     fcx: &'a FnCtxt<'a, 'tcx>,
     span: Span,
     mode: Mode,
-    method_name: ast::Name,
+    item_name: ast::Name,
     steps: Rc<Vec<CandidateStep<'tcx>>>,
     opt_simplified_steps: Option<Vec<fast_reject::SimplifiedType>>,
     inherent_candidates: Vec<Candidate<'tcx>>,
@@ -54,7 +54,7 @@ struct CandidateStep<'tcx> {
 
 struct Candidate<'tcx> {
     xform_self_ty: Ty<'tcx>,
-    method_ty: Rc<ty::Method<'tcx>>,
+    item: ty::ImplOrTraitItem<'tcx>,
     kind: CandidateKind<'tcx>,
 }
 
@@ -62,14 +62,14 @@ enum CandidateKind<'tcx> {
     InherentImplCandidate(/* Impl */ ast::DefId, subst::Substs<'tcx>),
     ObjectCandidate(/* Trait */ ast::DefId, /* method_num */ usize, /* vtable index */ usize),
     ExtensionImplCandidate(/* Impl */ ast::DefId, Rc<ty::TraitRef<'tcx>>,
-                           subst::Substs<'tcx>, MethodIndex),
-    ClosureCandidate(/* Trait */ ast::DefId, MethodIndex),
-    WhereClauseCandidate(ty::PolyTraitRef<'tcx>, MethodIndex),
-    ProjectionCandidate(ast::DefId, MethodIndex),
+                           subst::Substs<'tcx>, ItemIndex),
+    ClosureCandidate(/* Trait */ ast::DefId, ItemIndex),
+    WhereClauseCandidate(ty::PolyTraitRef<'tcx>, ItemIndex),
+    ProjectionCandidate(ast::DefId, ItemIndex),
 }
 
 pub struct Pick<'tcx> {
-    pub method_ty: Rc<ty::Method<'tcx>>,
+    pub item: ty::ImplOrTraitItem<'tcx>,
     pub kind: PickKind<'tcx>,
 
     // Indicates that the source expression should be autoderef'd N times
@@ -94,20 +94,20 @@ pub struct Pick<'tcx> {
 pub enum PickKind<'tcx> {
     InherentImplPick(/* Impl */ ast::DefId),
     ObjectPick(/* Trait */ ast::DefId, /* method_num */ usize, /* real_index */ usize),
-    ExtensionImplPick(/* Impl */ ast::DefId, MethodIndex),
-    TraitPick(/* Trait */ ast::DefId, MethodIndex),
-    WhereClausePick(/* Trait */ ty::PolyTraitRef<'tcx>, MethodIndex),
+    ExtensionImplPick(/* Impl */ ast::DefId, ItemIndex),
+    TraitPick(/* Trait */ ast::DefId, ItemIndex),
+    WhereClausePick(/* Trait */ ty::PolyTraitRef<'tcx>, ItemIndex),
 }
 
 pub type PickResult<'tcx> = Result<Pick<'tcx>, MethodError>;
 
-#[derive(PartialEq, Eq, Copy, Clone)]
+#[derive(PartialEq, Eq, Copy, Clone, Debug)]
 pub enum Mode {
     // An expression of the form `receiver.method_name(...)`.
     // Autoderefs are performed on `receiver`, lookup is done based on the
     // `self` argument  of the method, and static methods aren't considered.
     MethodCall,
-    // An expression of the form `Type::method` or `<T>::method`.
+    // An expression of the form `Type::item` or `<T>::item`.
     // No autoderefs are performed, lookup is done based on the type each
     // implementation is for, and static methods are included.
     Path
@@ -116,14 +116,14 @@ pub enum Mode {
 pub fn probe<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                        span: Span,
                        mode: Mode,
-                       method_name: ast::Name,
+                       item_name: ast::Name,
                        self_ty: Ty<'tcx>,
                        scope_expr_id: ast::NodeId)
                        -> PickResult<'tcx>
 {
-    debug!("probe(self_ty={}, method_name={}, scope_expr_id={})",
+    debug!("probe(self_ty={}, item_name={}, scope_expr_id={})",
            self_ty.repr(fcx.tcx()),
-           method_name,
+           item_name,
            scope_expr_id);
 
     // FIXME(#18741) -- right now, creating the steps involves evaluating the
@@ -171,7 +171,7 @@ pub fn probe<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
         let mut probe_cx = ProbeContext::new(fcx,
                                              span,
                                              mode,
-                                             method_name,
+                                             item_name,
                                              steps,
                                              opt_simplified_steps);
         probe_cx.assemble_inherent_candidates();
@@ -221,7 +221,7 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
     fn new(fcx: &'a FnCtxt<'a,'tcx>,
            span: Span,
            mode: Mode,
-           method_name: ast::Name,
+           item_name: ast::Name,
            steps: Vec<CandidateStep<'tcx>>,
            opt_simplified_steps: Option<Vec<fast_reject::SimplifiedType>>)
            -> ProbeContext<'a,'tcx>
@@ -230,7 +230,7 @@ fn new(fcx: &'a FnCtxt<'a,'tcx>,
             fcx: fcx,
             span: span,
             mode: mode,
-            method_name: method_name,
+            item_name: item_name,
             inherent_candidates: Vec::new(),
             extension_candidates: Vec::new(),
             impl_dups: HashSet::new(),
@@ -387,12 +387,12 @@ fn assemble_inherent_impl_probe(&mut self, impl_def_id: ast::DefId) {
 
         debug!("assemble_inherent_impl_probe {:?}", impl_def_id);
 
-        let method = match impl_method(self.tcx(), impl_def_id, self.method_name) {
+        let item = match impl_item(self.tcx(), impl_def_id, self.item_name) {
             Some(m) => m,
             None => { return; } // No method with correct name on this impl
         };
 
-        if !self.has_applicable_self(&*method) {
+        if !self.has_applicable_self(&item) {
             // No receiver declared. Not a candidate.
             return self.record_static_candidate(ImplSource(impl_def_id));
         }
@@ -402,11 +402,11 @@ fn assemble_inherent_impl_probe(&mut self, impl_def_id: ast::DefId) {
 
         // Determine the receiver type that the method itself expects.
         let xform_self_ty =
-            self.xform_self_ty(&method, impl_ty, &impl_substs);
+            self.xform_self_ty(&item, impl_ty, &impl_substs);
 
         self.inherent_candidates.push(Candidate {
             xform_self_ty: xform_self_ty,
-            method_ty: method,
+            item: item,
             kind: InherentImplCandidate(impl_def_id, impl_substs)
         });
     }
@@ -427,23 +427,23 @@ fn assemble_inherent_candidates_from_object(&mut self,
         // itself. Hence, a `&self` method will wind up with an
         // argument type like `&Trait`.
         let trait_ref = data.principal_trait_ref_with_self_ty(self.tcx(), self_ty);
-        self.elaborate_bounds(&[trait_ref.clone()], |this, new_trait_ref, m, method_num| {
+        self.elaborate_bounds(&[trait_ref.clone()], |this, new_trait_ref, item, item_num| {
             let new_trait_ref = this.erase_late_bound_regions(&new_trait_ref);
 
             let vtable_index =
                 traits::get_vtable_index_of_object_method(tcx,
                                                           trait_ref.clone(),
                                                           new_trait_ref.def_id,
-                                                          method_num);
+                                                          item_num);
 
-            let xform_self_ty = this.xform_self_ty(&m,
+            let xform_self_ty = this.xform_self_ty(&item,
                                                    new_trait_ref.self_ty(),
                                                    new_trait_ref.substs);
 
             this.inherent_candidates.push(Candidate {
                 xform_self_ty: xform_self_ty,
-                method_ty: m,
-                kind: ObjectCandidate(new_trait_ref.def_id, method_num, vtable_index)
+                item: item,
+                kind: ObjectCandidate(new_trait_ref.def_id, item_num, vtable_index)
             });
         });
     }
@@ -476,27 +476,29 @@ fn assemble_inherent_candidates_from_param(&mut self,
             })
             .collect();
 
-        self.elaborate_bounds(&bounds, |this, poly_trait_ref, m, method_num| {
+        self.elaborate_bounds(&bounds, |this, poly_trait_ref, item, item_num| {
             let trait_ref =
                 this.erase_late_bound_regions(&poly_trait_ref);
 
             let xform_self_ty =
-                this.xform_self_ty(&m,
+                this.xform_self_ty(&item,
                                    trait_ref.self_ty(),
                                    trait_ref.substs);
 
-            debug!("found match: trait_ref={} substs={} m={}",
-                   trait_ref.repr(this.tcx()),
-                   trait_ref.substs.repr(this.tcx()),
-                   m.repr(this.tcx()));
-            assert_eq!(m.generics.types.get_slice(subst::TypeSpace).len(),
-                       trait_ref.substs.types.get_slice(subst::TypeSpace).len());
-            assert_eq!(m.generics.regions.get_slice(subst::TypeSpace).len(),
-                       trait_ref.substs.regions().get_slice(subst::TypeSpace).len());
-            assert_eq!(m.generics.types.get_slice(subst::SelfSpace).len(),
-                       trait_ref.substs.types.get_slice(subst::SelfSpace).len());
-            assert_eq!(m.generics.regions.get_slice(subst::SelfSpace).len(),
-                       trait_ref.substs.regions().get_slice(subst::SelfSpace).len());
+            if let Some(ref m) = item.as_opt_method() {
+                debug!("found match: trait_ref={} substs={} m={}",
+                       trait_ref.repr(this.tcx()),
+                       trait_ref.substs.repr(this.tcx()),
+                       m.repr(this.tcx()));
+                assert_eq!(m.generics.types.get_slice(subst::TypeSpace).len(),
+                           trait_ref.substs.types.get_slice(subst::TypeSpace).len());
+                assert_eq!(m.generics.regions.get_slice(subst::TypeSpace).len(),
+                           trait_ref.substs.regions().get_slice(subst::TypeSpace).len());
+                assert_eq!(m.generics.types.get_slice(subst::SelfSpace).len(),
+                           trait_ref.substs.types.get_slice(subst::SelfSpace).len());
+                assert_eq!(m.generics.regions.get_slice(subst::SelfSpace).len(),
+                           trait_ref.substs.regions().get_slice(subst::SelfSpace).len());
+            }
 
             // Because this trait derives from a where-clause, it
             // should not contain any inference variables or other
@@ -507,8 +509,8 @@ fn assemble_inherent_candidates_from_param(&mut self,
 
             this.inherent_candidates.push(Candidate {
                 xform_self_ty: xform_self_ty,
-                method_ty: m,
-                kind: WhereClauseCandidate(poly_trait_ref, method_num)
+                item: item,
+                kind: WhereClauseCandidate(poly_trait_ref, item_num)
             });
         });
     }
@@ -523,7 +525,7 @@ fn elaborate_bounds<F>(
         F: for<'b> FnMut(
             &mut ProbeContext<'b, 'tcx>,
             ty::PolyTraitRef<'tcx>,
-            Rc<ty::Method<'tcx>>,
+            ty::ImplOrTraitItem<'tcx>,
             usize,
         ),
     {
@@ -531,17 +533,17 @@ fn elaborate_bounds<F>(
 
         let tcx = self.tcx();
         for bound_trait_ref in traits::transitive_bounds(tcx, bounds) {
-            let (pos, method) = match trait_method(tcx,
-                                                   bound_trait_ref.def_id(),
-                                                   self.method_name) {
+            let (pos, item) = match trait_item(tcx,
+                                               bound_trait_ref.def_id(),
+                                               self.item_name) {
                 Some(v) => v,
                 None => { continue; }
             };
 
-            if !self.has_applicable_self(&*method) {
+            if !self.has_applicable_self(&item) {
                 self.record_static_candidate(TraitSource(bound_trait_ref.def_id()));
             } else {
-                mk_cand(self, bound_trait_ref, method, pos);
+                mk_cand(self, bound_trait_ref, item, pos);
             }
         }
     }
@@ -584,37 +586,34 @@ fn assemble_extension_candidates_for_trait(&mut self,
             ty::trait_items(self.tcx(), trait_def_id);
         let matching_index =
             trait_items.iter()
-                       .position(|item| item.name() == self.method_name);
+                       .position(|item| item.name() == self.item_name);
         let matching_index = match matching_index {
             Some(i) => i,
             None => { return Ok(()); }
         };
-        let method = match (&*trait_items)[matching_index].as_opt_method() {
-            Some(m) => m,
-            None => { return Ok(()); }
-        };
+        let ref item = (&*trait_items)[matching_index];
 
         // Check whether `trait_def_id` defines a method with suitable name:
-        if !self.has_applicable_self(&*method) {
+        if !self.has_applicable_self(item) {
             debug!("method has inapplicable self");
             self.record_static_candidate(TraitSource(trait_def_id));
             return Ok(());
         }
 
         self.assemble_extension_candidates_for_trait_impls(trait_def_id,
-                                                           method.clone(),
+                                                           item.clone(),
                                                            matching_index);
 
         try!(self.assemble_closure_candidates(trait_def_id,
-                                              method.clone(),
+                                              item.clone(),
                                               matching_index));
 
         self.assemble_projection_candidates(trait_def_id,
-                                            method.clone(),
+                                            item.clone(),
                                             matching_index);
 
         self.assemble_where_clause_candidates(trait_def_id,
-                                              method,
+                                              item.clone(),
                                               matching_index);
 
         Ok(())
@@ -622,8 +621,8 @@ fn assemble_extension_candidates_for_trait(&mut self,
 
     fn assemble_extension_candidates_for_trait_impls(&mut self,
                                                      trait_def_id: ast::DefId,
-                                                     method: Rc<ty::Method<'tcx>>,
-                                                     method_index: usize)
+                                                     item: ty::ImplOrTraitItem<'tcx>,
+                                                     item_index: usize)
     {
         ty::populate_implementations_for_trait_if_necessary(self.tcx(),
                                                             trait_def_id);
@@ -657,7 +656,7 @@ fn assemble_extension_candidates_for_trait_impls(&mut self,
 
             // Determine the receiver type that the method itself expects.
             let xform_self_ty =
-                self.xform_self_ty(&method,
+                self.xform_self_ty(&item,
                                    impl_trait_ref.self_ty(),
                                    impl_trait_ref.substs);
 
@@ -665,8 +664,8 @@ fn assemble_extension_candidates_for_trait_impls(&mut self,
 
             self.extension_candidates.push(Candidate {
                 xform_self_ty: xform_self_ty,
-                method_ty: method.clone(),
-                kind: ExtensionImplCandidate(impl_def_id, impl_trait_ref, impl_substs, method_index)
+                item: item.clone(),
+                kind: ExtensionImplCandidate(impl_def_id, impl_trait_ref, impl_substs, item_index)
             });
         }
     }
@@ -689,8 +688,8 @@ fn impl_can_possibly_match(&self, impl_def_id: ast::DefId) -> bool {
 
     fn assemble_closure_candidates(&mut self,
                                    trait_def_id: ast::DefId,
-                                   method_ty: Rc<ty::Method<'tcx>>,
-                                   method_index: usize)
+                                   item: ty::ImplOrTraitItem<'tcx>,
+                                   item_index: usize)
                                    -> Result<(),MethodError>
     {
         // Check if this is one of the Fn,FnMut,FnOnce traits.
@@ -736,13 +735,13 @@ fn assemble_closure_candidates(&mut self,
                                                              &trait_def.generics,
                                                              step.self_ty);
 
-            let xform_self_ty = self.xform_self_ty(&method_ty,
+            let xform_self_ty = self.xform_self_ty(&item,
                                                    step.self_ty,
                                                    &substs);
             self.inherent_candidates.push(Candidate {
                 xform_self_ty: xform_self_ty,
-                method_ty: method_ty.clone(),
-                kind: ClosureCandidate(trait_def_id, method_index)
+                item: item.clone(),
+                kind: ClosureCandidate(trait_def_id, item_index)
             });
         }
 
@@ -751,16 +750,16 @@ fn assemble_closure_candidates(&mut self,
 
     fn assemble_projection_candidates(&mut self,
                                       trait_def_id: ast::DefId,
-                                      method: Rc<ty::Method<'tcx>>,
-                                      method_index: usize)
+                                      item: ty::ImplOrTraitItem<'tcx>,
+                                      item_index: usize)
     {
         debug!("assemble_projection_candidates(\
                trait_def_id={}, \
-               method={}, \
-               method_index={})",
+               item={}, \
+               item_index={})",
                trait_def_id.repr(self.tcx()),
-               method.repr(self.tcx()),
-               method_index);
+               item.repr(self.tcx()),
+               item_index);
 
         for step in &*self.steps {
             debug!("assemble_projection_candidates: step={}",
@@ -792,7 +791,7 @@ fn assemble_projection_candidates(&mut self,
                        bound.repr(self.tcx()));
 
                 if self.infcx().can_equate(&step.self_ty, &bound.self_ty()).is_ok() {
-                    let xform_self_ty = self.xform_self_ty(&method,
+                    let xform_self_ty = self.xform_self_ty(&item,
                                                            bound.self_ty(),
                                                            bound.substs);
 
@@ -802,8 +801,8 @@ fn assemble_projection_candidates(&mut self,
 
                     self.extension_candidates.push(Candidate {
                         xform_self_ty: xform_self_ty,
-                        method_ty: method.clone(),
-                        kind: ProjectionCandidate(trait_def_id, method_index)
+                        item: item.clone(),
+                        kind: ProjectionCandidate(trait_def_id, item_index)
                     });
                 }
             }
@@ -812,8 +811,8 @@ fn assemble_projection_candidates(&mut self,
 
     fn assemble_where_clause_candidates(&mut self,
                                         trait_def_id: ast::DefId,
-                                        method_ty: Rc<ty::Method<'tcx>>,
-                                        method_index: usize)
+                                        item: ty::ImplOrTraitItem<'tcx>,
+                                        item_index: usize)
     {
         debug!("assemble_where_clause_candidates(trait_def_id={})",
                trait_def_id.repr(self.tcx()));
@@ -824,7 +823,7 @@ fn assemble_where_clause_candidates(&mut self,
                           .filter(|b| b.def_id() == trait_def_id)
         {
             let bound = self.erase_late_bound_regions(&poly_bound);
-            let xform_self_ty = self.xform_self_ty(&method_ty,
+            let xform_self_ty = self.xform_self_ty(&item,
                                                    bound.self_ty(),
                                                    bound.substs);
 
@@ -834,8 +833,8 @@ fn assemble_where_clause_candidates(&mut self,
 
             self.extension_candidates.push(Candidate {
                 xform_self_ty: xform_self_ty,
-                method_ty: method_ty.clone(),
-                kind: WhereClauseCandidate(poly_bound, method_index)
+                item: item.clone(),
+                kind: WhereClauseCandidate(poly_bound, item_index)
             });
         }
     }
@@ -860,7 +859,7 @@ fn pick(mut self) -> PickResult<'tcx> {
         try!(self.assemble_extension_candidates_for_all_traits());
 
         let out_of_scope_traits = match self.pick_core() {
-            Some(Ok(p)) => vec![p.method_ty.container.id()],
+            Some(Ok(p)) => vec![p.item.container().id()],
             Some(Err(MethodError::Ambiguity(v))) => v.into_iter().map(|source| {
                 match source {
                     TraitSource(id) => id,
@@ -1099,11 +1098,11 @@ fn collapse_candidates_to_trait_pick(&self,
         }
 
         // If so, just use this trait and call it a day.
-        let (trait_def_id, method_num) = trait_data;
-        let method_ty = probes[0].method_ty.clone();
+        let (trait_def_id, item_num) = trait_data;
+        let item = probes[0].item.clone();
         Some(Pick {
-            method_ty: method_ty,
-            kind: TraitPick(trait_def_id, method_num),
+            item: item,
+            kind: TraitPick(trait_def_id, item_num),
             autoderefs: 0,
             autoref: None,
             unsize: None
@@ -1117,28 +1116,25 @@ fn make_sub_ty(&self, sub: Ty<'tcx>, sup: Ty<'tcx>) -> infer::UnitResult<'tcx> {
         self.infcx().sub_types(false, infer::Misc(DUMMY_SP), sub, sup)
     }
 
-    fn has_applicable_self(&self, method: &ty::Method) -> bool {
+    fn has_applicable_self(&self, item: &ty::ImplOrTraitItem) -> bool {
         // "fast track" -- check for usage of sugar
-        match method.explicit_self {
-            ty::StaticExplicitSelfCategory => {
-                if self.mode == Mode::Path {
-                    return true;
-                }
-            }
-            ty::ByValueExplicitSelfCategory |
-            ty::ByReferenceExplicitSelfCategory(..) |
-            ty::ByBoxExplicitSelfCategory => {
-                return true;
-            }
+        match *item {
+            ty::ImplOrTraitItem::MethodTraitItem(ref method) =>
+                match method.explicit_self {
+                    ty::StaticExplicitSelfCategory => self.mode == Mode::Path,
+                    ty::ByValueExplicitSelfCategory |
+                    ty::ByReferenceExplicitSelfCategory(..) |
+                    ty::ByBoxExplicitSelfCategory => true,
+                },
+            ty::ImplOrTraitItem::ConstTraitItem(..) => self.mode == Mode::Path,
+            _ => false,
         }
-
         // FIXME -- check for types that deref to `Self`,
         // like `Rc<Self>` and so on.
         //
         // Note also that the current code will break if this type
         // includes any of the type parameters defined on the method
         // -- but this could be overcome.
-        return false;
     }
 
     fn record_static_candidate(&mut self, source: CandidateSource) {
@@ -1146,10 +1142,23 @@ fn record_static_candidate(&mut self, source: CandidateSource) {
     }
 
     fn xform_self_ty(&self,
-                     method: &Rc<ty::Method<'tcx>>,
+                     item: &ty::ImplOrTraitItem<'tcx>,
                      impl_ty: Ty<'tcx>,
                      substs: &subst::Substs<'tcx>)
                      -> Ty<'tcx>
+    {
+        match item.as_opt_method() {
+            Some(ref method) => self.xform_method_self_ty(method, impl_ty,
+                                                          substs),
+            None => impl_ty,
+        }
+    }
+
+    fn xform_method_self_ty(&self,
+                            method: &Rc<ty::Method<'tcx>>,
+                            impl_ty: Ty<'tcx>,
+                            substs: &subst::Substs<'tcx>)
+                            -> Ty<'tcx>
     {
         debug!("xform_self_ty(impl_ty={}, self_ty={}, substs={})",
                impl_ty.repr(self.tcx()),
@@ -1245,46 +1254,45 @@ fn erase_late_bound_regions<T>(&self, value: &ty::Binder<T>) -> T
     }
 }
 
-fn impl_method<'tcx>(tcx: &ty::ctxt<'tcx>,
-                     impl_def_id: ast::DefId,
-                     method_name: ast::Name)
-                     -> Option<Rc<ty::Method<'tcx>>>
+fn impl_item<'tcx>(tcx: &ty::ctxt<'tcx>,
+                   impl_def_id: ast::DefId,
+                   item_name: ast::Name)
+                   -> Option<ty::ImplOrTraitItem<'tcx>>
 {
     let impl_items = tcx.impl_items.borrow();
     let impl_items = impl_items.get(&impl_def_id).unwrap();
     impl_items
         .iter()
         .map(|&did| ty::impl_or_trait_item(tcx, did.def_id()))
-        .find(|m| m.name() == method_name)
-        .and_then(|item| item.as_opt_method())
+        .find(|item| item.name() == item_name)
 }
 
-/// Find method with name `method_name` defined in `trait_def_id` and return it, along with its
-/// index (or `None`, if no such method).
-fn trait_method<'tcx>(tcx: &ty::ctxt<'tcx>,
-                      trait_def_id: ast::DefId,
-                      method_name: ast::Name)
-                      -> Option<(usize, Rc<ty::Method<'tcx>>)>
+/// Find item with name `item_name` defined in `trait_def_id` and return it,
+/// along with its index (or `None`, if no such item).
+fn trait_item<'tcx>(tcx: &ty::ctxt<'tcx>,
+                    trait_def_id: ast::DefId,
+                    item_name: ast::Name)
+                    -> Option<(usize, ty::ImplOrTraitItem<'tcx>)>
 {
     let trait_items = ty::trait_items(tcx, trait_def_id);
     debug!("trait_method; items: {:?}", trait_items);
     trait_items
         .iter()
         .enumerate()
-        .find(|&(_, ref item)| item.name() == method_name)
-        .and_then(|(idx, item)| item.as_opt_method().map(|m| (idx, m)))
+        .find(|&(_, ref item)| item.name() == item_name)
+        .map(|(num, ref item)| (num, (*item).clone()))
 }
 
 impl<'tcx> Candidate<'tcx> {
     fn to_unadjusted_pick(&self) -> Pick<'tcx> {
         Pick {
-            method_ty: self.method_ty.clone(),
+            item: self.item.clone(),
             kind: match self.kind {
                 InherentImplCandidate(def_id, _) => {
                     InherentImplPick(def_id)
                 }
-                ObjectCandidate(def_id, method_num, real_index) => {
-                    ObjectPick(def_id, method_num, real_index)
+                ObjectCandidate(def_id, item_num, real_index) => {
+                    ObjectPick(def_id, item_num, real_index)
                 }
                 ExtensionImplCandidate(def_id, _, _, index) => {
                     ExtensionImplPick(def_id, index)
@@ -1323,25 +1331,25 @@ fn to_source(&self) -> CandidateSource {
         }
     }
 
-    fn to_trait_data(&self) -> Option<(ast::DefId,MethodIndex)> {
+    fn to_trait_data(&self) -> Option<(ast::DefId, ItemIndex)> {
         match self.kind {
             InherentImplCandidate(..) => {
                 None
             }
-            ObjectCandidate(trait_def_id, method_num, _) => {
-                Some((trait_def_id, method_num))
+            ObjectCandidate(trait_def_id, item_num, _) => {
+                Some((trait_def_id, item_num))
             }
-            ClosureCandidate(trait_def_id, method_num) => {
-                Some((trait_def_id, method_num))
+            ClosureCandidate(trait_def_id, item_num) => {
+                Some((trait_def_id, item_num))
             }
-            ExtensionImplCandidate(_, ref trait_ref, _, method_num) => {
-                Some((trait_ref.def_id, method_num))
+            ExtensionImplCandidate(_, ref trait_ref, _, item_num) => {
+                Some((trait_ref.def_id, item_num))
             }
-            WhereClauseCandidate(ref trait_ref, method_num) => {
-                Some((trait_ref.def_id(), method_num))
+            WhereClauseCandidate(ref trait_ref, item_num) => {
+                Some((trait_ref.def_id(), item_num))
             }
-            ProjectionCandidate(trait_def_id, method_num) => {
-                Some((trait_def_id, method_num))
+            ProjectionCandidate(trait_def_id, item_num) => {
+                Some((trait_def_id, item_num))
             }
         }
     }
@@ -1392,9 +1400,9 @@ fn repr(&self, _tcx: &ty::ctxt) -> String {
 
 impl<'tcx> Repr<'tcx> for Pick<'tcx> {
     fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
-        format!("Pick(method_ty={}, autoderefs={},
+        format!("Pick(item={}, autoderefs={},
                  autoref={}, unsize={}, kind={:?})",
-                self.method_ty.repr(tcx),
+                self.item.repr(tcx),
                 self.autoderefs,
                 self.autoref.repr(tcx),
                 self.unsize.repr(tcx),
index e87deba280804b5ce889cf0d92190485bafef32e..f9c78cd36e6ac1d93e3d3093337443363468201f 100644 (file)
@@ -78,7 +78,7 @@
 
 pub use self::LvaluePreference::*;
 pub use self::Expectation::*;
-pub use self::compare_method::compare_impl_method;
+pub use self::compare_method::{compare_impl_method, compare_const_impl};
 use self::TupleArgumentsFlag::*;
 
 use astconv::{self, ast_region_to_region, ast_ty_to_ty, AstConv, PathParamMode};
@@ -807,6 +807,9 @@ pub fn check_item_body<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, it: &'tcx ast::Item) {
 
         for impl_item in impl_items {
             match impl_item.node {
+                ast::ConstImplItem(_, ref expr) => {
+                    check_const(ccx, impl_item.span, &*expr, impl_item.id)
+                }
                 ast::MethodImplItem(ref sig, ref body) => {
                     check_method_body(ccx, &impl_pty.generics, sig, body,
                                       impl_item.id, impl_item.span);
@@ -822,14 +825,15 @@ pub fn check_item_body<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, it: &'tcx ast::Item) {
         let trait_def = ty::lookup_trait_def(ccx.tcx, local_def(it.id));
         for trait_item in trait_items {
             match trait_item.node {
-                ast::MethodTraitItem(_, None) => {
-                    // Nothing to do, since required methods don't have
-                    // bodies to check.
+                ast::ConstTraitItem(_, Some(ref expr)) => {
+                    check_const(ccx, trait_item.span, &*expr, trait_item.id)
                 }
                 ast::MethodTraitItem(ref sig, Some(ref body)) => {
                     check_method_body(ccx, &trait_def.generics, sig, body,
                                       trait_item.id, trait_item.span);
                 }
+                ast::ConstTraitItem(_, None) |
+                ast::MethodTraitItem(_, None) |
                 ast::TypeTraitItem(..) => {
                     // Nothing to do.
                 }
@@ -919,6 +923,48 @@ fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
     // and compatible with trait signature
     for impl_item in impl_items {
         match impl_item.node {
+            ast::ConstImplItem(..) => {
+                let impl_const_def_id = local_def(impl_item.id);
+                let impl_const_ty = ty::impl_or_trait_item(ccx.tcx,
+                                                           impl_const_def_id);
+
+                // Find associated const definition.
+                let opt_associated_const =
+                    trait_items.iter()
+                               .find(|ac| ac.name() == impl_const_ty.name());
+                match opt_associated_const {
+                    Some(associated_const) => {
+                        match (associated_const, &impl_const_ty) {
+                            (&ty::ConstTraitItem(ref const_trait),
+                             &ty::ConstTraitItem(ref const_impl)) => {
+                                compare_const_impl(ccx.tcx,
+                                                   &const_impl,
+                                                   impl_item.span,
+                                                   &const_trait,
+                                                   &*impl_trait_ref);
+                            }
+                            _ => {
+                                span_err!(tcx.sess, impl_item.span, E0323,
+                                          "item `{}` is an associated const, \
+                                          which doesn't match its trait `{}`",
+                                          token::get_name(impl_const_ty.name()),
+                                          impl_trait_ref.repr(tcx))
+                            }
+                        }
+                    }
+                    None => {
+                        // This is `span_bug` as it should have already been
+                        // caught in resolve.
+                        tcx.sess.span_bug(
+                            impl_item.span,
+                            &format!(
+                                "associated const `{}` is not a member of \
+                                 trait `{}`",
+                                token::get_name(impl_const_ty.name()),
+                                impl_trait_ref.repr(tcx)));
+                    }
+                }
+            }
             ast::MethodImplItem(_, ref body) => {
                 let impl_method_def_id = local_def(impl_item.id);
                 let impl_item_ty = ty::impl_or_trait_item(ccx.tcx,
@@ -942,13 +988,11 @@ fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                                                     &*impl_trait_ref);
                             }
                             _ => {
-                                // This is span_bug as it should have already been
-                                // caught in resolve.
-                                tcx.sess.span_bug(
-                                    impl_item.span,
-                                    &format!("item `{}` is of a different kind from its trait `{}`",
-                                             token::get_name(impl_item_ty.name()),
-                                             impl_trait_ref.repr(tcx)));
+                                span_err!(tcx.sess, impl_item.span, E0324,
+                                          "item `{}` is an associated method, \
+                                          which doesn't match its trait `{}`",
+                                          token::get_name(impl_item_ty.name()),
+                                          impl_trait_ref.repr(tcx))
                             }
                         }
                     }
@@ -978,13 +1022,11 @@ fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                         match (associated_type, &typedef_ty) {
                             (&ty::TypeTraitItem(_), &ty::TypeTraitItem(_)) => {}
                             _ => {
-                                // This is `span_bug` as it should have
-                                // already been caught in resolve.
-                                tcx.sess.span_bug(
-                                    impl_item.span,
-                                    &format!("item `{}` is of a different kind from its trait `{}`",
-                                             token::get_name(typedef_ty.name()),
-                                             impl_trait_ref.repr(tcx)));
+                                span_err!(tcx.sess, impl_item.span, E0325,
+                                          "item `{}` is an associated type, \
+                                          which doesn't match its trait `{}`",
+                                          token::get_name(typedef_ty.name()),
+                                          impl_trait_ref.repr(tcx))
                             }
                         }
                     }
@@ -1008,9 +1050,27 @@ trait `{}`",
 
     // Check for missing items from trait
     let provided_methods = ty::provided_trait_methods(tcx, impl_trait_ref.def_id);
+    let associated_consts = ty::associated_consts(tcx, impl_trait_ref.def_id);
     let mut missing_methods = Vec::new();
     for trait_item in &*trait_items {
         match *trait_item {
+            ty::ConstTraitItem(ref associated_const) => {
+                let is_implemented = impl_items.iter().any(|ii| {
+                    match ii.node {
+                        ast::ConstImplItem(..) => {
+                            ii.ident.name == associated_const.name
+                        }
+                        _ => false,
+                    }
+                });
+                let is_provided =
+                    associated_consts.iter().any(|ac| ac.default.is_some() &&
+                                                 ac.name == associated_const.name);
+                if !is_implemented && !is_provided {
+                    missing_methods.push(format!("`{}`",
+                                                 token::get_name(associated_const.name)));
+                }
+            }
             ty::MethodTraitItem(ref trait_method) => {
                 let is_implemented =
                     impl_items.iter().any(|ii| {
@@ -1018,8 +1078,7 @@ trait `{}`",
                             ast::MethodImplItem(..) => {
                                 ii.ident.name == trait_method.name
                             }
-                            ast::TypeImplItem(_) |
-                            ast::MacImplItem(_) => false,
+                            _ => false,
                         }
                     });
                 let is_provided =
@@ -1034,8 +1093,7 @@ trait `{}`",
                         ast::TypeImplItem(_) => {
                             ii.ident.name == associated_type.name
                         }
-                        ast::MethodImplItem(..) |
-                        ast::MacImplItem(_) => false,
+                        _ => false,
                     }
                 });
                 if !is_implemented {
@@ -3171,53 +3229,20 @@ fn check_struct_fields_on_error<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
                                 &format!("unbound path {}", expr.repr(tcx)))
           };
 
-          let def = path_res.base_def;
-          if path_res.depth == 0 {
+          if let Some((opt_ty, segments, def)) =
+                  resolve_ty_and_def_ufcs(fcx, path_res, opt_self_ty, path,
+                                          expr.span, expr.id) {
               let (scheme, predicates) = type_scheme_and_predicates_for_def(fcx,
                                                                             expr.span,
                                                                             def);
               instantiate_path(fcx,
-                               &path.segments,
+                               segments,
                                scheme,
                                &predicates,
-                               opt_self_ty,
+                               opt_ty,
                                def,
                                expr.span,
                                id);
-          } else {
-              let ty_segments = path.segments.init();
-              let base_ty_end = path.segments.len() - path_res.depth;
-              let ty = astconv::finish_resolving_def_to_ty(fcx,
-                                                           fcx,
-                                                           expr.span,
-                                                           PathParamMode::Optional,
-                                                           &def,
-                                                           opt_self_ty,
-                                                           &ty_segments[..base_ty_end],
-                                                           &ty_segments[base_ty_end..]);
-              let method_segment = path.segments.last().unwrap();
-              let method_name = method_segment.identifier.name;
-              match method::resolve_ufcs(fcx, expr.span, method_name, ty, id) {
-                  Ok((def, lp)) => {
-                      // Write back the new resolution.
-                      tcx.def_map.borrow_mut().insert(id, def::PathResolution {
-                          base_def: def,
-                          last_private: path_res.last_private.or(lp),
-                          depth: 0
-                      });
-
-                      let (scheme, predicates) =
-                          type_scheme_and_predicates_for_def(fcx, expr.span, def);
-                      instantiate_path(fcx, slice::ref_slice(method_segment),
-                                       scheme, &predicates,
-                                       Some(ty), def, expr.span, id);
-                  }
-                  Err(error) => {
-                      method::report_error(fcx, expr.span, ty,
-                                           method_name, None, error);
-                      fcx.write_error(id);
-                  }
-              }
           }
 
           // We always require that the type provided as the value for
@@ -3679,6 +3704,52 @@ fn check_struct_fields_on_error<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
     unifier();
 }
 
+pub fn resolve_ty_and_def_ufcs<'a, 'b, 'tcx>(fcx: &FnCtxt<'b, 'tcx>,
+                                             path_res: def::PathResolution,
+                                             opt_self_ty: Option<Ty<'tcx>>,
+                                             path: &'a ast::Path,
+                                             span: Span,
+                                             node_id: ast::NodeId)
+                                             -> Option<(Option<Ty<'tcx>>,
+                                                        &'a [ast::PathSegment],
+                                                        def::Def)>
+{
+    // If fully resolved already, we don't have to do anything.
+    if path_res.depth == 0 {
+        Some((opt_self_ty, &path.segments, path_res.base_def))
+    } else {
+        let mut def = path_res.base_def;
+        let ty_segments = path.segments.init();
+        let base_ty_end = path.segments.len() - path_res.depth;
+        let ty = astconv::finish_resolving_def_to_ty(fcx, fcx, span,
+                                                     PathParamMode::Optional,
+                                                     &mut def,
+                                                     opt_self_ty,
+                                                     &ty_segments[..base_ty_end],
+                                                     &ty_segments[base_ty_end..]);
+        let item_segment = path.segments.last().unwrap();
+        let item_name = item_segment.identifier.name;
+        match method::resolve_ufcs(fcx, span, item_name, ty, node_id) {
+            Ok((def, lp)) => {
+                // Write back the new resolution.
+                fcx.ccx.tcx.def_map.borrow_mut()
+                       .insert(node_id, def::PathResolution {
+                   base_def: def,
+                   last_private: path_res.last_private.or(lp),
+                   depth: 0
+                });
+                Some((Some(ty), slice::ref_slice(item_segment), def))
+            }
+            Err(error) => {
+                method::report_error(fcx, span, ty,
+                                     item_name, None, error);
+                fcx.write_error(node_id);
+                None
+            }
+        }
+    }
+}
+
 fn constrain_path_type_parameters(fcx: &FnCtxt,
                                   expr: &ast::Expr)
 {
@@ -4207,7 +4278,7 @@ fn type_scheme_and_predicates_for_def<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
         }
         def::DefFn(id, _) | def::DefMethod(id, _) |
         def::DefStatic(id, _) | def::DefVariant(_, id, _) |
-        def::DefStruct(id) | def::DefConst(id) => {
+        def::DefStruct(id) | def::DefConst(id) | def::DefAssociatedConst(id, _) => {
             (ty::lookup_item_type(fcx.tcx(), id), ty::lookup_predicates(fcx.tcx(), id))
         }
         def::DefTrait(_) |
@@ -4249,7 +4320,7 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
     // Luckily, we can (at least for now) deduce the intermediate steps
     // just from the end-point.
     //
-    // There are basically three cases to consider:
+    // There are basically four cases to consider:
     //
     // 1. Reference to a *type*, such as a struct or enum:
     //
@@ -4299,6 +4370,16 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
     //    `SomeStruct::<A>`, contains parameters in TypeSpace, and the
     //    final segment, `foo::<B>` contains parameters in fn space.
     //
+    // 4. Reference to an *associated const*:
+    //
+    // impl<A> AnotherStruct<A> {
+    // const FOO: B = BAR;
+    // }
+    //
+    // The path in this case will look like
+    // `a::b::AnotherStruct::<A>::FOO`, so the penultimate segment
+    // only will have parameters in TypeSpace.
+    //
     // The first step then is to categorize the segments appropriately.
 
     assert!(!segments.is_empty());
@@ -4350,6 +4431,23 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
             }
         }
 
+        def::DefAssociatedConst(_, provenance) => {
+            match provenance {
+                def::FromTrait(trait_did) => {
+                    callee::check_legal_trait_for_method_call(fcx.ccx, span, trait_did)
+                }
+                def::FromImpl(_) => {}
+            }
+
+            if segments.len() >= 2 {
+                segment_spaces = repeat(None).take(segments.len() - 2).collect();
+                segment_spaces.push(Some(subst::TypeSpace));
+                segment_spaces.push(None);
+            } else {
+                segment_spaces = vec![None];
+            }
+        }
+
         // Other cases. Various nonsense that really shouldn't show up
         // here. If they do, an error will have been reported
         // elsewhere. (I hope)
index b0c994f7f6405500a582a480510210dcbfc923d4..fbfe73674e16088eb95388debd7338ffe97c53d9 100644 (file)
@@ -20,8 +20,9 @@
 use metadata::csearch;
 use middle::subst::{self, Subst};
 use middle::ty::RegionEscape;
-use middle::ty::{ImplContainer, ImplOrTraitItemId, MethodTraitItemId};
-use middle::ty::{ParameterEnvironment, TypeTraitItemId, lookup_item_type};
+use middle::ty::{ImplContainer, ImplOrTraitItemId, ConstTraitItemId};
+use middle::ty::{MethodTraitItemId, TypeTraitItemId};
+use middle::ty::{ParameterEnvironment, lookup_item_type};
 use middle::ty::{Ty, ty_bool, ty_char, ty_enum, ty_err};
 use middle::ty::{ty_param, TypeScheme, ty_ptr};
 use middle::ty::{ty_rptr, ty_struct, ty_trait, ty_tup};
@@ -278,6 +279,9 @@ fn create_impl_from_item(&self, item: &Item) -> Vec<ImplOrTraitItemId> {
                 let mut items: Vec<ImplOrTraitItemId> =
                         impl_items.iter().map(|impl_item| {
                     match impl_item.node {
+                        ast::ConstImplItem(..) => {
+                            ConstTraitItemId(local_def(impl_item.id))
+                        }
                         ast::MethodImplItem(..) => {
                             MethodTraitItemId(local_def(impl_item.id))
                         }
@@ -348,7 +352,7 @@ fn add_external_impl(&self,
                            .insert(item_def_id.def_id(), source);
                     }
                 }
-                ty::TypeTraitItem(_) => {}
+                _ => {}
             }
         }
 
index 23959d578bf0320a2013f979e88c8cb8536a15d8..6cb6df008c1cf7e505ae8c8616809a5dcf37dd8b 100644 (file)
@@ -197,7 +197,7 @@ fn method_ty(&self, method_id: ast::NodeId) -> Rc<ty::Method<'tcx>> {
         let def_id = local_def(method_id);
         match *self.tcx.impl_or_trait_items.borrow().get(&def_id).unwrap() {
             ty::MethodTraitItem(ref mty) => mty.clone(),
-            ty::TypeTraitItem(..) => {
+            _ => {
                 self.tcx.sess.bug(&format!("method with id {} has the wrong type", method_id));
             }
         }
@@ -692,11 +692,37 @@ fn convert_field<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
     }
 }
 
+fn convert_associated_const<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
+                                      container: ImplOrTraitItemContainer,
+                                      ident: ast::Ident,
+                                      id: ast::NodeId,
+                                      vis: ast::Visibility,
+                                      ty: ty::Ty<'tcx>,
+                                      default: Option<&ast::Expr>)
+{
+    ccx.tcx.predicates.borrow_mut().insert(local_def(id),
+                                           ty::GenericPredicates::empty());
+
+    write_ty_to_tcx(ccx.tcx, id, ty);
+    let default_id = default.map(|expr| local_def(expr.id));
+
+    let associated_const = Rc::new(ty::AssociatedConst {
+        name: ident.name,
+        vis: vis,
+        def_id: local_def(id),
+        container: container,
+        ty: ty,
+        default: default_id,
+    });
+    ccx.tcx.impl_or_trait_items.borrow_mut()
+       .insert(local_def(id), ty::ConstTraitItem(associated_const));
+}
+
 fn as_refsociated_type<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
-                                     container: ImplOrTraitItemContainer,
-                                     ident: ast::Ident,
-                                     id: ast::NodeId,
-                                     vis: ast::Visibility)
+                                 container: ImplOrTraitItemContainer,
+                                 ident: ast::Ident,
+                                 id: ast::NodeId,
+                                 vis: ast::Visibility)
 {
     let associated_type = Rc::new(ty::AssociatedType {
         name: ident.name,
@@ -829,45 +855,56 @@ fn convert_item(ccx: &CrateCtxt, it: &ast::Item) {
                 it.vis
             };
 
-            // Convert all the associated types.
+            // Convert all the associated consts.
             for impl_item in impl_items {
-                match impl_item.node {
-                    ast::TypeImplItem(ref ty) => {
-                        if opt_trait_ref.is_none() {
-                            span_err!(tcx.sess, impl_item.span, E0202,
-                                              "associated items are not allowed in inherent impls");
-                        }
-
-                        as_refsociated_type(ccx, ImplContainer(local_def(it.id)),
-                                                impl_item.ident, impl_item.id, impl_item.vis);
+                if let ast::ConstImplItem(ref ty, ref expr) = impl_item.node {
+                    let ty = ccx.icx(&ty_predicates)
+                                .to_ty(&ExplicitRscope, &*ty);
+                    tcx.tcache.borrow_mut().insert(local_def(impl_item.id),
+                                                   TypeScheme {
+                                                       generics: ty_generics.clone(),
+                                                       ty: ty,
+                                                   });
+                    convert_associated_const(ccx, ImplContainer(local_def(it.id)),
+                                             impl_item.ident, impl_item.id,
+                                             impl_item.vis.inherit_from(parent_visibility),
+                                             ty, Some(&*expr));
+                }
+            }
 
-                        let typ = ccx.icx(&ty_predicates).to_ty(&ExplicitRscope, ty);
-                        tcx.tcache.borrow_mut().insert(local_def(impl_item.id),
-                                                       TypeScheme {
-                                                           generics: ty::Generics::empty(),
-                                                           ty: typ,
-                                                       });
-                        tcx.predicates.borrow_mut().insert(local_def(impl_item.id),
-                                                           ty::GenericPredicates::empty());
-                        write_ty_to_tcx(tcx, impl_item.id, typ);
+            // Convert all the associated types.
+            for impl_item in impl_items {
+                if let ast::TypeImplItem(ref ty) = impl_item.node {
+                    if opt_trait_ref.is_none() {
+                        span_err!(tcx.sess, impl_item.span, E0202,
+                                  "associated items are not allowed in inherent impls");
                     }
-                    ast::MethodImplItem(..) |
-                    ast::MacImplItem(_) => {}
+
+                    as_refsociated_type(ccx, ImplContainer(local_def(it.id)),
+                                        impl_item.ident, impl_item.id, impl_item.vis);
+
+                    let typ = ccx.icx(&ty_predicates).to_ty(&ExplicitRscope, ty);
+                    tcx.tcache.borrow_mut().insert(local_def(impl_item.id),
+                                                   TypeScheme {
+                                                       generics: ty::Generics::empty(),
+                                                       ty: typ,
+                                                   });
+                    tcx.predicates.borrow_mut().insert(local_def(impl_item.id),
+                                                       ty::GenericPredicates::empty());
+                    write_ty_to_tcx(tcx, impl_item.id, typ);
                 }
             }
 
             let methods = impl_items.iter().filter_map(|ii| {
-                match ii.node {
-                    ast::MethodImplItem(ref sig, _) => {
-                        // if the method specifies a visibility, use that, otherwise
-                        // inherit the visibility from the impl (so `foo` in `pub impl
-                        // { fn foo(); }` is public, but private in `priv impl { fn
-                        // foo(); }`).
-                        let method_vis = ii.vis.inherit_from(parent_visibility);
-                        Some((sig, ii.id, ii.ident, method_vis, ii.span))
-                    }
-                    ast::TypeImplItem(_) |
-                    ast::MacImplItem(_) => None
+                if let ast::MethodImplItem(ref sig, _) = ii.node {
+                    // if the method specifies a visibility, use that, otherwise
+                    // inherit the visibility from the impl (so `foo` in `pub impl
+                    // { fn foo(); }` is public, but private in `priv impl { fn
+                    // foo(); }`).
+                    let method_vis = ii.vis.inherit_from(parent_visibility);
+                    Some((sig, ii.id, ii.ident, method_vis, ii.span))
+                } else {
+                    None
                 }
             });
             convert_methods(ccx,
@@ -878,18 +915,14 @@ fn convert_item(ccx: &CrateCtxt, it: &ast::Item) {
                             &ty_predicates);
 
             for impl_item in impl_items {
-                match impl_item.node {
-                    ast::MethodImplItem(ref sig, ref body) => {
-                        let body_id = body.id;
-                        check_method_self_type(ccx,
-                                               &BindingRscope::new(),
-                                               ccx.method_ty(impl_item.id),
-                                               selfty,
-                                               &sig.explicit_self,
-                                               body_id);
-                    }
-                    ast::TypeImplItem(_) |
-                    ast::MacImplItem(_) => {}
+                if let ast::MethodImplItem(ref sig, ref body) = impl_item.node {
+                    let body_id = body.id;
+                    check_method_self_type(ccx,
+                                           &BindingRscope::new(),
+                                           ccx.method_ty(impl_item.id),
+                                           selfty,
+                                           &sig.explicit_self,
+                                           body_id);
                 }
             }
 
@@ -920,18 +953,37 @@ fn convert_item(ccx: &CrateCtxt, it: &ast::Item) {
             // Convert all the associated types.
             for trait_item in trait_items {
                 match trait_item.node {
-                    ast::MethodTraitItem(..) => {}
+                    ast::ConstTraitItem(ref ty, ref default) => {
+                        let ty = ccx.icx(&trait_predicates)
+                                    .to_ty(&ExplicitRscope, ty);
+                        tcx.tcache.borrow_mut().insert(local_def(trait_item.id),
+                                                       TypeScheme {
+                                                           generics: trait_def.generics.clone(),
+                                                           ty: ty,
+                                                       });
+                        convert_associated_const(ccx, TraitContainer(local_def(it.id)),
+                                                 trait_item.ident, trait_item.id,
+                                                 ast::Public, ty, default.as_ref().map(|d| &**d));
+                    }
+                    _ => {}
+                }
+            };
+
+            // Convert all the associated types.
+            for trait_item in trait_items {
+                match trait_item.node {
                     ast::TypeTraitItem(..) => {
                         as_refsociated_type(ccx, TraitContainer(local_def(it.id)),
                                                 trait_item.ident, trait_item.id, ast::Public);
                     }
+                    _ => {}
                 }
             };
 
             let methods = trait_items.iter().filter_map(|ti| {
                 let sig = match ti.node {
                     ast::MethodTraitItem(ref sig, _) => sig,
-                    ast::TypeTraitItem(..) => return None,
+                    _ => return None,
                 };
                 Some((sig, ti.id, ti.ident, ast::Inherited, ti.span))
             });
@@ -948,6 +1000,9 @@ fn convert_item(ccx: &CrateCtxt, it: &ast::Item) {
             let trait_item_def_ids = Rc::new(trait_items.iter().map(|trait_item| {
                 let def_id = local_def(trait_item.id);
                 match trait_item.node {
+                    ast::ConstTraitItem(..) => {
+                        ty::ConstTraitItemId(def_id)
+                    }
                     ast::MethodTraitItem(..) => {
                         ty::MethodTraitItemId(def_id)
                     }
@@ -963,7 +1018,7 @@ fn convert_item(ccx: &CrateCtxt, it: &ast::Item) {
             for trait_item in trait_items {
                 let sig = match trait_item.node {
                     ast::MethodTraitItem(ref sig, _) => sig,
-                    ast::TypeTraitItem(..) => continue
+                    _ => continue
                 };
                 check_method_self_type(ccx,
                                        &BindingRscope::new(),
@@ -1186,8 +1241,8 @@ fn trait_def_of_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
 
     let associated_type_names: Vec<_> = items.iter().filter_map(|trait_item| {
         match trait_item.node {
-            ast::MethodTraitItem(..) => None,
             ast::TypeTraitItem(..) => Some(trait_item.ident.name),
+            _ => None,
         }
     }).collect();
 
@@ -1261,7 +1316,7 @@ fn trait_defines_associated_type_named(ccx: &CrateCtxt,
     trait_items.iter().any(|trait_item| {
         match trait_item.node {
             ast::TypeTraitItem(..) => trait_item.ident.name == assoc_name,
-            ast::MethodTraitItem(..) => false,
+            _ => false,
         }
     })
 }
@@ -1321,7 +1376,7 @@ fn predicates_for_associated_types<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
         trait_items.iter().flat_map(|trait_item| {
             let bounds = match trait_item.node {
                 ast::TypeTraitItem(ref bounds, _) => bounds,
-                ast::MethodTraitItem(..) => {
+                _ => {
                     return vec!().into_iter();
                 }
             };
@@ -2237,7 +2292,8 @@ fn enforce_impl_params_are_constrained<'tcx>(tcx: &ty::ctxt<'tcx>,
         impl_items.iter()
                   .filter_map(|item| match item.node {
                       ast::TypeImplItem(..) => Some(ty::node_id_to_type(tcx, item.id)),
-                      ast::MethodImplItem(..) | ast::MacImplItem(..) => None,
+                      ast::ConstImplItem(..) | ast::MethodImplItem(..) |
+                      ast::MacImplItem(..) => None,
                   })
                   .flat_map(|ty| ctp::parameters_for_type(ty).into_iter())
                   .filter_map(|p| match p {
index b17702cfb8cb5c58d6b9bf907f3491affe892040..46cc4628e2eeb36022f7782bd7d89af67c72cee7 100644 (file)
     E0320, // recursive overflow during dropck
     E0321, // extended coherence rules for defaulted traits violated
     E0322, // cannot implement Sized explicitly
+    E0323, // implemented an associated const when another trait item expected
+    E0324, // implemented a method when another trait item expected
+    E0325, // implemented an associated type when another trait item expected
+    E0326, // associated const implemented with different type from trait
+    E0327, // referred to method instead of constant in match pattern
     E0366, // dropck forbid specialization to concrete type or region
     E0367, // dropck forbid specialization to predicate not in struct/enum
     E0368, // binary operation `<op>=` cannot be applied to types
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 4fc86cf181b8daf361d8756e527cbe25279b5e3f..0d59577a6d802ce1552cd45cf9267dad1c06f9f5 100644 (file)
 use rustc::middle::ty;
 use rustc::middle::subst;
 use rustc::middle::stability;
+use rustc::middle::const_eval;
 
 use core::DocContext;
 use doctree;
 use clean;
 
-use super::Clean;
+use super::{Clean, ToSource};
 
 /// Attempt to inline the definition of a local node id into this AST.
 ///
@@ -106,7 +107,7 @@ fn try_inline_def(cx: &DocContext, tcx: &ty::ctxt,
             record_extern_fqn(cx, did, clean::TypeStatic);
             clean::StaticItem(build_static(cx, tcx, did, mtbl))
         }
-        def::DefConst(did) => {
+        def::DefConst(did) | def::DefAssociatedConst(did, _) => {
             record_extern_fqn(cx, did, clean::TypeConst);
             clean::ConstantItem(build_const(cx, tcx, did))
         }
@@ -312,6 +313,27 @@ pub fn build_impl(cx: &DocContext,
         let did = did.def_id();
         let impl_item = ty::impl_or_trait_item(tcx, did);
         match impl_item {
+            ty::ConstTraitItem(ref assoc_const) => {
+                let did = assoc_const.def_id;
+                let type_scheme = ty::lookup_item_type(tcx, did);
+                let default = match assoc_const.default {
+                    Some(_) => Some(const_eval::lookup_const_by_id(tcx, did, None)
+                                               .unwrap().span.to_src(cx)),
+                    None => None,
+                };
+                Some(clean::Item {
+                    name: Some(assoc_const.name.clean(cx)),
+                    inner: clean::AssociatedConstItem(
+                        type_scheme.ty.clean(cx),
+                        default,
+                    ),
+                    source: clean::Span::empty(),
+                    attrs: vec![],
+                    visibility: None,
+                    stability: stability::lookup(tcx, did).clean(cx),
+                    def_id: did
+                })
+            }
             ty::MethodTraitItem(method) => {
                 if method.vis != ast::Public && associated_trait.is_none() {
                     return None
@@ -443,7 +465,7 @@ fn build_const(cx: &DocContext, tcx: &ty::ctxt,
     use rustc::middle::const_eval;
     use syntax::print::pprust;
 
-    let expr = const_eval::lookup_const_by_id(tcx, did).unwrap_or_else(|| {
+    let expr = const_eval::lookup_const_by_id(tcx, did, None).unwrap_or_else(|| {
         panic!("expected lookup_const_by_id to succeed for {:?}", did);
     });
     debug!("converting constant expr {:?} to snippet", expr);
index 23c9edde77c33ea423a1f26fde6fd932c13ea3bf..1e6e9a7562a7c1be287fe5e69e42ff7f49dce460 100644 (file)
@@ -361,6 +361,7 @@ pub enum ItemEnum {
     ForeignStaticItem(Static),
     MacroItem(Macro),
     PrimitiveItem(PrimitiveType),
+    AssociatedConstItem(Type, Option<String>),
     AssociatedTypeItem(Vec<TyParamBound>, Option<Type>),
     DefaultImplItem(DefaultImpl),
 }
@@ -1235,6 +1236,11 @@ fn clean(&self, cx: &DocContext) -> PolyTrait {
 impl Clean<Item> for ast::TraitItem {
     fn clean(&self, cx: &DocContext) -> Item {
         let inner = match self.node {
+            ast::ConstTraitItem(ref ty, ref default) => {
+                AssociatedConstItem(ty.clean(cx),
+                                    default.as_ref().map(|expr|
+                                                         expr.span.to_src(cx)))
+            }
             ast::MethodTraitItem(ref sig, Some(_)) => {
                 MethodItem(sig.clean(cx))
             }
@@ -1260,6 +1266,12 @@ fn clean(&self, cx: &DocContext) -> Item {
 impl Clean<Item> for ast::ImplItem {
     fn clean(&self, cx: &DocContext) -> Item {
         let inner = match self.node {
+            ast::ConstImplItem(ref ty, ref expr) => {
+                ConstantItem(Constant{
+                    type_: ty.clean(cx),
+                    expr: expr.span.to_src(cx),
+                })
+            }
             ast::MethodImplItem(ref sig, _) => {
                 MethodItem(sig.clean(cx))
             }
@@ -1363,6 +1375,7 @@ fn clean(&self, cx: &DocContext) -> Item {
 impl<'tcx> Clean<Item> for ty::ImplOrTraitItem<'tcx> {
     fn clean(&self, cx: &DocContext) -> Item {
         match *self {
+            ty::ConstTraitItem(ref cti) => cti.clean(cx),
             ty::MethodTraitItem(ref mti) => mti.clean(cx),
             ty::TypeTraitItem(ref tti) => tti.clean(cx),
         }
@@ -2509,6 +2522,8 @@ fn name_from_pat(p: &ast::Pat) -> String {
         PatWild(PatWildMulti) => "..".to_string(),
         PatIdent(_, ref p, _) => token::get_ident(p.node).to_string(),
         PatEnum(ref p, _) => path_to_string(p),
+        PatQPath(..) => panic!("tried to get argument name from PatQPath, \
+                                which is not allowed in function arguments"),
         PatStruct(ref name, ref fields, etc) => {
             format!("{} {{ {}{} }}", path_to_string(name),
                 fields.iter().map(|&Spanned { node: ref fp, .. }|
@@ -2672,6 +2687,20 @@ fn clean(&self, _: &DocContext) -> Stability {
     }
 }
 
+impl<'tcx> Clean<Item> for ty::AssociatedConst<'tcx> {
+    fn clean(&self, cx: &DocContext) -> Item {
+        Item {
+            source: DUMMY_SP.clean(cx),
+            name: Some(self.name.clean(cx)),
+            attrs: Vec::new(),
+            inner: AssociatedConstItem(self.ty.clean(cx), None),
+            visibility: None,
+            def_id: self.def_id,
+            stability: None,
+        }
+    }
+}
+
 impl Clean<Item> for ty::AssociatedType {
     fn clean(&self, cx: &DocContext) -> Item {
         // When loading a cross-crate associated type, the bounds for this type
index d2385702a73d2c2c35fc85453890a3c56f7be2c5..afc93f41172e84498729ceece2adebcc6845022d 100644 (file)
@@ -39,6 +39,7 @@ pub enum ItemType {
     Primitive       = 15,
     AssociatedType  = 16,
     Constant        = 17,
+    AssociatedConst = 18,
 }
 
 impl ItemType {
@@ -63,6 +64,7 @@ pub fn from_item(item: &clean::Item) -> ItemType {
             clean::ForeignStaticItem(..)   => ItemType::Static, // no ForeignStatic
             clean::MacroItem(..)           => ItemType::Macro,
             clean::PrimitiveItem(..)       => ItemType::Primitive,
+            clean::AssociatedConstItem(..) => ItemType::AssociatedConst,
             clean::AssociatedTypeItem(..)  => ItemType::AssociatedType,
             clean::DefaultImplItem(..)     => ItemType::Impl,
         }
@@ -102,6 +104,7 @@ pub fn to_static_str(&self) -> &'static str {
             ItemType::Primitive       => "primitive",
             ItemType::AssociatedType  => "associatedtype",
             ItemType::Constant        => "constant",
+            ItemType::AssociatedConst => "associatedconstant",
         }
     }
 }
index 1993f03efd1fabbc8e7539be2ec4b93f57fe9e55..9a26a925847e41dbb045b32b809ce24f4009b537 100644 (file)
@@ -1460,7 +1460,7 @@ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
         try!(write!(fmt, "<span class='out-of-band'>"));
         try!(write!(fmt,
         r##"<span id='render-detail'>
-            <a id="toggle-all-docs" href="#" title="collapse all docs">[-]</a>
+            <a id="toggle-all-docs" href="#" title="collapse all docs">[&minus;]</a>
         </span>"##));
 
         // Write `src` tag
@@ -1629,6 +1629,7 @@ fn cmp(i1: &clean::Item, i2: &clean::Item, idx1: usize, idx2: usize) -> Ordering
                 ItemType::Macro           => ("macros", "Macros"),
                 ItemType::Primitive       => ("primitives", "Primitive Types"),
                 ItemType::AssociatedType  => ("associated-types", "Associated Types"),
+                ItemType::AssociatedConst => ("associated-consts", "Associated Constants"),
             };
             try!(write!(w,
                         "<h2 id='{id}' class='section-header'>\
@@ -1799,7 +1800,7 @@ fn item_trait(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
         try!(write!(w, "{{\n"));
         for t in &types {
             try!(write!(w, "    "));
-            try!(render_method(w, t, MethodLink::Anchor));
+            try!(render_assoc_item(w, t, AssocItemLink::Anchor));
             try!(write!(w, ";\n"));
         }
         if !types.is_empty() && !required.is_empty() {
@@ -1807,7 +1808,7 @@ fn item_trait(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
         }
         for m in &required {
             try!(write!(w, "    "));
-            try!(render_method(w, m, MethodLink::Anchor));
+            try!(render_assoc_item(w, m, AssocItemLink::Anchor));
             try!(write!(w, ";\n"));
         }
         if !required.is_empty() && !provided.is_empty() {
@@ -1815,7 +1816,7 @@ fn item_trait(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
         }
         for m in &provided {
             try!(write!(w, "    "));
-            try!(render_method(w, m, MethodLink::Anchor));
+            try!(render_assoc_item(w, m, AssocItemLink::Anchor));
             try!(write!(w, " {{ ... }}\n"));
         }
         try!(write!(w, "}}"));
@@ -1831,7 +1832,7 @@ fn trait_item(w: &mut fmt::Formatter, m: &clean::Item)
                     ty = shortty(m),
                     name = *m.name.as_ref().unwrap(),
                     stab = m.stability_class()));
-        try!(render_method(w, m, MethodLink::Anchor));
+        try!(render_assoc_item(w, m, AssocItemLink::Anchor));
         try!(write!(w, "</code></h3>"));
         try!(document(w, m));
         Ok(())
@@ -1871,7 +1872,7 @@ fn trait_item(w: &mut fmt::Formatter, m: &clean::Item)
     }
 
     // If there are methods directly on this trait object, render them here.
-    try!(render_methods(w, it.def_id, MethodRender::All));
+    try!(render_assoc_items(w, it.def_id, AssocItemRender::All));
 
     let cache = cache();
     try!(write!(w, "
@@ -1903,6 +1904,17 @@ fn trait_item(w: &mut fmt::Formatter, m: &clean::Item)
     Ok(())
 }
 
+fn assoc_const(w: &mut fmt::Formatter, it: &clean::Item,
+               ty: &clean::Type, default: &Option<String>)
+               -> fmt::Result {
+    try!(write!(w, "const {}", it.name.as_ref().unwrap()));
+    try!(write!(w, ": {}", ty));
+    if let Some(ref default) = *default {
+        try!(write!(w, " = {}", default));
+    }
+    Ok(())
+}
+
 fn assoc_type(w: &mut fmt::Formatter, it: &clean::Item,
               bounds: &Vec<clean::TyParamBound>,
               default: &Option<clean::Type>)
@@ -1917,19 +1929,19 @@ fn assoc_type(w: &mut fmt::Formatter, it: &clean::Item,
     Ok(())
 }
 
-fn render_method(w: &mut fmt::Formatter, meth: &clean::Item,
-                 link: MethodLink) -> fmt::Result {
+fn render_assoc_item(w: &mut fmt::Formatter, meth: &clean::Item,
+                     link: AssocItemLink) -> fmt::Result {
     fn method(w: &mut fmt::Formatter, it: &clean::Item,
               unsafety: ast::Unsafety, abi: abi::Abi,
               g: &clean::Generics, selfty: &clean::SelfTy,
-              d: &clean::FnDecl, link: MethodLink) -> fmt::Result {
+              d: &clean::FnDecl, link: AssocItemLink) -> fmt::Result {
         use syntax::abi::Abi;
 
         let name = it.name.as_ref().unwrap();
         let anchor = format!("#{}.{}", shortty(it), name);
         let href = match link {
-            MethodLink::Anchor => anchor,
-            MethodLink::GotoSource(did) => {
+            AssocItemLink::Anchor => anchor,
+            AssocItemLink::GotoSource(did) => {
                 href(did).map(|p| format!("{}{}", p.0, anchor)).unwrap_or(anchor)
             }
         };
@@ -1958,10 +1970,13 @@ fn method(w: &mut fmt::Formatter, it: &clean::Item,
             method(w, meth, m.unsafety, m.abi, &m.generics, &m.self_, &m.decl,
                    link)
         }
+        clean::AssociatedConstItem(ref ty, ref default) => {
+            assoc_const(w, meth, ty, default)
+        }
         clean::AssociatedTypeItem(ref bounds, ref default) => {
             assoc_type(w, meth, bounds, default)
         }
-        _ => panic!("render_method called on non-method")
+        _ => panic!("render_assoc_item called on non-associated-item")
     }
 }
 
@@ -2001,7 +2016,7 @@ fn item_struct(w: &mut fmt::Formatter, it: &clean::Item,
             try!(write!(w, "</table>"));
         }
     }
-    render_methods(w, it.def_id, MethodRender::All)
+    render_assoc_items(w, it.def_id, AssocItemRender::All)
 }
 
 fn item_enum(w: &mut fmt::Formatter, it: &clean::Item,
@@ -2100,7 +2115,7 @@ fn item_enum(w: &mut fmt::Formatter, it: &clean::Item,
         try!(write!(w, "</table>"));
 
     }
-    try!(render_methods(w, it.def_id, MethodRender::All));
+    try!(render_assoc_items(w, it.def_id, AssocItemRender::All));
     Ok(())
 }
 
@@ -2184,19 +2199,19 @@ fn render_struct(w: &mut fmt::Formatter, it: &clean::Item,
 }
 
 #[derive(Copy, Clone)]
-enum MethodLink {
+enum AssocItemLink {
     Anchor,
     GotoSource(ast::DefId),
 }
 
-enum MethodRender<'a> {
+enum AssocItemRender<'a> {
     All,
     DerefFor { trait_: &'a clean::Type, type_: &'a clean::Type },
 }
 
-fn render_methods(w: &mut fmt::Formatter,
-                  it: ast::DefId,
-                  what: MethodRender) -> fmt::Result {
+fn render_assoc_items(w: &mut fmt::Formatter,
+                      it: ast::DefId,
+                      what: AssocItemRender) -> fmt::Result {
     let c = cache();
     let v = match c.impls.get(&it) {
         Some(v) => v,
@@ -2207,21 +2222,21 @@ fn render_methods(w: &mut fmt::Formatter,
     });
     if !non_trait.is_empty() {
         let render_header = match what {
-            MethodRender::All => {
+            AssocItemRender::All => {
                 try!(write!(w, "<h2 id='methods'>Methods</h2>"));
                 true
             }
-            MethodRender::DerefFor { trait_, type_ } => {
+            AssocItemRender::DerefFor { trait_, type_ } => {
                 try!(write!(w, "<h2 id='deref-methods'>Methods from \
                                     {}&lt;Target={}&gt;</h2>", trait_, type_));
                 false
             }
         };
         for i in &non_trait {
-            try!(render_impl(w, i, MethodLink::Anchor, render_header));
+            try!(render_impl(w, i, AssocItemLink::Anchor, render_header));
         }
     }
-    if let MethodRender::DerefFor { .. } = what {
+    if let AssocItemRender::DerefFor { .. } = what {
         return Ok(())
     }
     if !traits.is_empty() {
@@ -2243,7 +2258,7 @@ fn render_methods(w: &mut fmt::Formatter,
         });
         for i in &manual {
             let did = i.trait_did().unwrap();
-            try!(render_impl(w, i, MethodLink::GotoSource(did), true));
+            try!(render_impl(w, i, AssocItemLink::GotoSource(did), true));
         }
         if !derived.is_empty() {
             try!(write!(w, "<h3 id='derived_implementations'>\
@@ -2251,7 +2266,7 @@ fn render_methods(w: &mut fmt::Formatter,
             </h3>"));
             for i in &derived {
                 let did = i.trait_did().unwrap();
-                try!(render_impl(w, i, MethodLink::GotoSource(did), true));
+                try!(render_impl(w, i, AssocItemLink::GotoSource(did), true));
             }
         }
     }
@@ -2266,14 +2281,14 @@ fn render_deref_methods(w: &mut fmt::Formatter, impl_: &Impl) -> fmt::Result {
             _ => None,
         }
     }).next().unwrap();
-    let what = MethodRender::DerefFor { trait_: deref_type, type_: target };
+    let what = AssocItemRender::DerefFor { trait_: deref_type, type_: target };
     match *target {
-        clean::ResolvedPath { did, .. } => render_methods(w, did, what),
+        clean::ResolvedPath { did, .. } => render_assoc_items(w, did, what),
         _ => {
             if let Some(prim) = target.primitive_type() {
                 if let Some(c) = cache().primitive_locations.get(&prim) {
                     let did = ast::DefId { krate: *c, node: prim.to_node_id() };
-                    try!(render_methods(w, did, what));
+                    try!(render_assoc_items(w, did, what));
                 }
             }
             Ok(())
@@ -2281,7 +2296,7 @@ fn render_deref_methods(w: &mut fmt::Formatter, impl_: &Impl) -> fmt::Result {
     }
 }
 
-fn render_impl(w: &mut fmt::Formatter, i: &Impl, link: MethodLink,
+fn render_impl(w: &mut fmt::Formatter, i: &Impl, link: AssocItemLink,
                render_header: bool) -> fmt::Result {
     if render_header {
         try!(write!(w, "<h3 class='impl'><code>impl{} ",
@@ -2300,13 +2315,13 @@ fn render_impl(w: &mut fmt::Formatter, i: &Impl, link: MethodLink,
     }
 
     fn doctraititem(w: &mut fmt::Formatter, item: &clean::Item,
-                    link: MethodLink) -> fmt::Result {
+                    link: AssocItemLink) -> fmt::Result {
         match item.inner {
             clean::MethodItem(..) | clean::TyMethodItem(..) => {
                 try!(write!(w, "<h4 id='method.{}' class='{}'><code>",
                             *item.name.as_ref().unwrap(),
                             shortty(item)));
-                try!(render_method(w, item, link));
+                try!(render_assoc_item(w, item, link));
                 try!(write!(w, "</code></h4>\n"));
             }
             clean::TypedefItem(ref tydef) => {
@@ -2317,6 +2332,14 @@ fn doctraititem(w: &mut fmt::Formatter, item: &clean::Item,
                 try!(write!(w, "type {} = {}", name, tydef.type_));
                 try!(write!(w, "</code></h4>\n"));
             }
+            clean::AssociatedConstItem(ref ty, ref default) => {
+                let name = item.name.as_ref().unwrap();
+                try!(write!(w, "<h4 id='assoc_const.{}' class='{}'><code>",
+                            *name,
+                            shortty(item)));
+                try!(assoc_const(w, item, ty, default));
+                try!(write!(w, "</code></h4>\n"));
+            }
             clean::AssociatedTypeItem(ref bounds, ref default) => {
                 let name = item.name.as_ref().unwrap();
                 try!(write!(w, "<h4 id='assoc_type.{}' class='{}'><code>",
@@ -2327,7 +2350,7 @@ fn doctraititem(w: &mut fmt::Formatter, item: &clean::Item,
             }
             _ => panic!("can't make docs for trait item with name {:?}", item.name)
         }
-        if let MethodLink::Anchor = link {
+        if let AssocItemLink::Anchor = link {
             document(w, item)
         } else {
             Ok(())
@@ -2339,10 +2362,10 @@ fn doctraititem(w: &mut fmt::Formatter, item: &clean::Item,
         try!(doctraititem(w, trait_item, link));
     }
 
-    fn render_default_methods(w: &mut fmt::Formatter,
-                              did: ast::DefId,
-                              t: &clean::Trait,
-                              i: &clean::Impl) -> fmt::Result {
+    fn render_default_items(w: &mut fmt::Formatter,
+                            did: ast::DefId,
+                            t: &clean::Trait,
+                            i: &clean::Impl) -> fmt::Result {
         for trait_item in &t.items {
             let n = trait_item.name.clone();
             match i.items.iter().find(|m| { m.name == n }) {
@@ -2350,7 +2373,7 @@ fn render_default_methods(w: &mut fmt::Formatter,
                 None => {}
             }
 
-            try!(doctraititem(w, trait_item, MethodLink::GotoSource(did)));
+            try!(doctraititem(w, trait_item, AssocItemLink::GotoSource(did)));
         }
         Ok(())
     }
@@ -2361,7 +2384,7 @@ fn render_default_methods(w: &mut fmt::Formatter,
     // for them work.
     if let Some(clean::ResolvedPath { did, .. }) = i.impl_.trait_ {
         if let Some(t) = cache().traits.get(&did) {
-            try!(render_default_methods(w, did, t, &i.impl_));
+            try!(render_default_items(w, did, t, &i.impl_));
         }
     }
     try!(write!(w, "</div>"));
@@ -2458,7 +2481,7 @@ fn item_primitive(w: &mut fmt::Formatter,
                   it: &clean::Item,
                   _p: &clean::PrimitiveType) -> fmt::Result {
     try!(document(w, it));
-    render_methods(w, it.def_id, MethodRender::All)
+    render_assoc_items(w, it.def_id, AssocItemRender::All)
 }
 
 fn get_basic_keywords() -> &'static str {
index c94dbc15103321f031d33a8ed0d587484d239530..b907e9e20b69867df2040215fb2b2ad68f8158cf 100644 (file)
@@ -392,7 +392,7 @@ a {
     text-decoration: underline;
 }
 
-.content span.trait, .content a.trait, .block a.current.trait { color: #ed9603; }
+.content span.trait, .content a.trait, .block a.current.trait { color: #8866ff; }
 .content span.mod, .content a.mod, block a.current.mod { color: #4d76ae; }
 .content span.enum, .content a.enum, .block a.current.enum { color: #5e9766; }
 .content span.struct, .content a.struct, .block a.current.struct { color: #e53700; }
index 56cea50a502399cae7e4279f07eff6d2852b3c3f..c2a59278a86dc79dbaff558c130461602299871f 100644 (file)
 
     $("#toggle-all-docs").on("click", function() {
         var toggle = $("#toggle-all-docs");
-        if (toggle.html() == "[-]") {
-            toggle.html("[+]");
+        if (toggle.html() == "[&minus;]") {
+            toggle.html("[&plus;]");
             toggle.attr("title", "expand all docs");
             $(".docblock").hide();
             $(".toggle-label").show();
             $(".toggle-wrapper").addClass("collapsed");
-            $(".collapse-toggle").children(".inner").html("+");
+            $(".collapse-toggle").children(".inner").html("&plus;");
         } else {
-            toggle.html("[-]");
+            toggle.html("[&minus;]");
             toggle.attr("title", "collapse all docs");
             $(".docblock").show();
             $(".toggle-label").hide();
             $(".toggle-wrapper").removeClass("collapsed");
-            $(".collapse-toggle").children(".inner").html("-");
+            $(".collapse-toggle").children(".inner").html("&minus;");
         }
     });
 
             if (relatedDoc.is(":visible")) {
                 relatedDoc.slideUp({duration:'fast', easing:'linear'});
                 toggle.parent(".toggle-wrapper").addClass("collapsed");
-                toggle.children(".inner").html("+");
+                toggle.children(".inner").html("&plus;");
                 toggle.children(".toggle-label").fadeIn();
             } else {
                 relatedDoc.slideDown({duration:'fast', easing:'linear'});
                 toggle.parent(".toggle-wrapper").removeClass("collapsed");
-                toggle.children(".inner").html("-");
+                toggle.children(".inner").html("&minus;");
                 toggle.children(".toggle-label").hide();
             }
         }
 
     $(function() {
         var toggle = $("<a/>", {'href': 'javascript:void(0)', 'class': 'collapse-toggle'})
-            .html("[<span class='inner'>-</span>]");
+            .html("[<span class='inner'>&minus;</span>]");
 
         $(".method").each(function() {
             if ($(this).next().is(".docblock") ||
index 53cfbb3efdda528aa39ca1a45b390ba0e7724542..74c16127f41ccac87c3bf3aba6d2acb37b644c7e 100644 (file)
@@ -184,7 +184,8 @@ fn fold_item(&mut self, i: Item) -> Option<Item> {
             // Primitives are never stripped
             clean::PrimitiveItem(..) => {}
 
-            // Associated types are never stripped
+            // Associated consts and types are never stripped
+            clean::AssociatedConstItem(..) |
             clean::AssociatedTypeItem(..) => {}
         }
 
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 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")
index 11b057d0094ae1d0674b22db405f03307eb35a47..7366524fd7ea82f1729f67578920b5e0ac2adc41 100644 (file)
@@ -17,7 +17,7 @@
 use cell::RefCell;
 use rt::{backtrace, unwind};
 use sys::stdio::Stderr;
-use thread;
+use sys_common::thread_info;
 
 thread_local! {
     pub static LOCAL_STDERR: RefCell<Option<Box<Write + Send>>> = {
@@ -34,8 +34,8 @@ pub fn on_panic(obj: &(Any+Send), file: &'static str, line: u32) {
         }
     };
     let mut err = Stderr::new();
-    let thread = thread::current();
-    let name = thread.name().unwrap_or("<unnamed>");
+    let thread = thread_info::current_thread();
+    let name = thread.as_ref().and_then(|t| t.name()).unwrap_or("<unnamed>");
     let prev = LOCAL_STDERR.with(|s| s.borrow_mut().take());
     match prev {
         Some(mut stderr) => {
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 22cb59433713043dbaf2a3409072e147e13901c5..ae55bae37aa884e3870e7b43315f745e425a927d 100644 (file)
@@ -25,10 +25,9 @@ struct ThreadInfo {
 thread_local! { static THREAD_INFO: RefCell<Option<ThreadInfo>> = RefCell::new(None) }
 
 impl ThreadInfo {
-    fn with<R, F>(f: F) -> R where F: FnOnce(&mut ThreadInfo) -> R {
+    fn with<R, F>(f: F) -> Option<R> where F: FnOnce(&mut ThreadInfo) -> R {
         if THREAD_INFO.state() == LocalKeyState::Destroyed {
-            panic!("Use of std::thread::current() is not possible after \
-                    the thread's local data has been destroyed");
+            return None
         }
 
         THREAD_INFO.with(move |c| {
@@ -38,16 +37,16 @@ fn with<R, F>(f: F) -> R where F: FnOnce(&mut ThreadInfo) -> R {
                     thread: NewThread::new(None),
                 })
             }
-            f(c.borrow_mut().as_mut().unwrap())
+            Some(f(c.borrow_mut().as_mut().unwrap()))
         })
     }
 }
 
-pub fn current_thread() -> Thread {
+pub fn current_thread() -> Option<Thread> {
     ThreadInfo::with(|info| info.thread.clone())
 }
 
-pub fn stack_guard() -> usize {
+pub fn stack_guard() -> Option<usize> {
     ThreadInfo::with(|info| info.stack_guard)
 }
 
index 6887095c53a7d1cdc24a5a7cf7d1acfe5b9a8baf..2bc280d12743958fbe5a1ff36b9c96960a27b223 100644 (file)
@@ -81,7 +81,7 @@ unsafe fn term(signum: libc::c_int) -> ! {
         // We're calling into functions with stack checks
         stack::record_sp_limit(0);
 
-        let guard = thread_info::stack_guard();
+        let guard = thread_info::stack_guard().unwrap_or(0);
         let addr = (*info).si_addr as usize;
 
         if guard == 0 || addr < guard - PAGE_SIZE || addr >= guard {
index 281ac37e671152845bc3caaddf807f9e4a533133..cfab9d1c51a153d988b926bf16b158629c0856fe 100644 (file)
@@ -342,7 +342,10 @@ fn min_stack_size(attr: *const libc::pthread_attr_t) -> usize {
     static mut __pthread_get_minstack: Option<F> = None;
 
     INIT.call_once(|| {
-        let lib = DynamicLibrary::open(None).unwrap();
+        let lib = match DynamicLibrary::open(None) {
+            Ok(l) => l,
+            Err(..) => return,
+        };
         unsafe {
             if let Ok(f) = lib.symbol("__pthread_get_minstack") {
                 __pthread_get_minstack = Some(mem::transmute::<*const (), F>(f));
index d2f51678d497fa737c463c0089b4729fe63b1a73..f59eb2c03013fd5eaa53c0e5050bf9b9969edf57 100644 (file)
@@ -82,7 +82,8 @@ pub struct SteadyTime {
     // OpenBSD provide it via libc
     #[cfg(not(any(target_os = "android",
                   target_os = "bitrig",
-                  target_os = "openbsd")))]
+                  target_os = "openbsd",
+                  target_env = "musl")))]
     #[link(name = "rt")]
     extern {}
 
index 6d8f1cba7091f0b3dbf2f567e56c9c55e9aaa69b..bb2832b874657deb26f0b0dc983e2326e197a40b 100644 (file)
@@ -18,7 +18,6 @@
 
 // Sure wish we had macro hygiene, no?
 #[doc(hidden)]
-#[unstable(feature = "thread_local_internals")]
 pub mod __impl {
     pub use super::imp::Key as KeyInner;
     pub use super::imp::destroy_value;
@@ -78,12 +77,10 @@ pub struct LocalKey<T> {
     // This is trivially devirtualizable by LLVM because we never store anything
     // to this field and rustc can declare the `static` as constant as well.
     #[doc(hidden)]
-    #[unstable(feature = "thread_local_internals")]
     pub inner: fn() -> &'static __impl::KeyInner<UnsafeCell<Option<T>>>,
 
     // initialization routine to invoke to create a value
     #[doc(hidden)]
-    #[unstable(feature = "thread_local_internals")]
     pub init: fn() -> T,
 }
 
@@ -297,6 +294,7 @@ pub fn state(&'static self) -> LocalKeyState {
 }
 
 #[cfg(all(any(target_os = "macos", target_os = "linux"), not(target_arch = "aarch64")))]
+#[doc(hidden)]
 mod imp {
     use prelude::v1::*;
 
@@ -304,8 +302,6 @@ mod imp {
     use intrinsics;
     use ptr;
 
-    #[doc(hidden)]
-    #[unstable(feature = "thread_local_internals")]
     pub struct Key<T> {
         // Place the inner bits in an `UnsafeCell` to currently get around the
         // "only Sync statics" restriction. This allows any type to be placed in
@@ -313,20 +309,16 @@ pub struct Key<T> {
         //
         // Note that all access requires `T: 'static` so it can't be a type with
         // any borrowed pointers still.
-        #[unstable(feature = "thread_local_internals")]
         pub inner: UnsafeCell<T>,
 
         // Metadata to keep track of the state of the destructor. Remember that
         // these variables are thread-local, not global.
-        #[unstable(feature = "thread_local_internals")]
         pub dtor_registered: UnsafeCell<bool>, // should be Cell
-        #[unstable(feature = "thread_local_internals")]
         pub dtor_running: UnsafeCell<bool>, // should be Cell
     }
 
     unsafe impl<T> ::marker::Sync for Key<T> { }
 
-    #[doc(hidden)]
     impl<T> Key<T> {
         pub unsafe fn get(&'static self) -> Option<&'static T> {
             if intrinsics::needs_drop::<T>() && *self.dtor_running.get() {
@@ -364,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 ();
@@ -422,8 +415,6 @@ fn _tlv_atexit(dtor: unsafe extern fn(*mut u8),
         _tlv_atexit(dtor, t);
     }
 
-    #[doc(hidden)]
-    #[unstable(feature = "thread_local_internals")]
     pub unsafe extern fn destroy_value<T>(ptr: *mut u8) {
         let ptr = ptr as *mut Key<T>;
         // Right before we run the user destructor be sure to flag the
@@ -435,6 +426,7 @@ fn _tlv_atexit(dtor: unsafe extern fn(*mut u8),
 }
 
 #[cfg(any(not(any(target_os = "macos", target_os = "linux")), target_arch = "aarch64"))]
+#[doc(hidden)]
 mod imp {
     use prelude::v1::*;
 
@@ -444,16 +436,12 @@ mod imp {
     use ptr;
     use sys_common::thread_local::StaticKey as OsStaticKey;
 
-    #[doc(hidden)]
-    #[unstable(feature = "thread_local_internals")]
     pub struct Key<T> {
         // Statically allocated initialization expression, using an `UnsafeCell`
         // for the same reasons as above.
-        #[unstable(feature = "thread_local_internals")]
         pub inner: UnsafeCell<T>,
 
         // OS-TLS key that we'll use to key off.
-        #[unstable(feature = "thread_local_internals")]
         pub os: OsStaticKey,
     }
 
@@ -464,7 +452,6 @@ struct Value<T: 'static> {
         value: T,
     }
 
-    #[doc(hidden)]
     impl<T> Key<T> {
         pub unsafe fn get(&'static self) -> Option<&'static T> {
             self.ptr().map(|p| &*p)
@@ -489,14 +476,12 @@ unsafe fn ptr(&'static self) -> Option<*mut T> {
                 key: self,
                 value: mem::transmute_copy(&self.inner),
             };
-            let ptr: *mut Value<T> = boxed::into_raw(ptr);
+            let ptr = boxed::into_raw(ptr);
             self.os.set(ptr as *mut u8);
             Some(&mut (*ptr).value as *mut T)
         }
     }
 
-    #[doc(hidden)]
-    #[unstable(feature = "thread_local_internals")]
     pub unsafe extern fn destroy_value<T: 'static>(ptr: *mut u8) {
         // The OS TLS ensures that this key contains a NULL value when this
         // destructor starts to run. We set it back to a sentinel value of 1 to
@@ -505,7 +490,7 @@ unsafe fn ptr(&'static self) -> Option<*mut T> {
         //
         // Note that to prevent an infinite loop we reset it back to null right
         // before we return from the destructor ourselves.
-        let ptr: Box<Value<T>> = Box::from_raw(ptr as *mut Value<T>);
+        let ptr = Box::from_raw(ptr as *mut Value<T>);
         let key = ptr.key;
         key.os.set(1 as *mut u8);
         drop(ptr);
index 9168a716d43801a4304287a81018c18bbb0c48ea..ae480380f95eb00710b6e37096b296bfe2f7c468 100644 (file)
 //! ## Configuring threads
 //!
 //! A new thread can be configured before it is spawned via the `Builder` type,
-//! which currently allows you to set the name, stack size, and writers for
-//! `println!` and `panic!` for the child thread:
+//! which currently allows you to set the name and stack size for the child thread:
 //!
 //! ```rust
 //! # #![allow(unused_must_use)]
@@ -408,7 +407,9 @@ pub fn scoped<'a, T, F>(f: F) -> JoinGuard<'a, T> where
 /// Gets a handle to the thread that invokes it.
 #[stable(feature = "rust1", since = "1.0.0")]
 pub fn current() -> Thread {
-    thread_info::current_thread()
+    thread_info::current_thread().expect("use of std::thread::current() is not \
+                                          possible after the thread's local \
+                                          data has been destroyed")
 }
 
 /// Cooperatively gives up a timeslice to the OS scheduler.
@@ -699,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 07fb6cbe5c6af4db5c7ff5aa7e2eac943969a3b5..3b7bfb1043a35acc543fb9851df9422d8c45d1f3 100644 (file)
@@ -593,6 +593,12 @@ pub enum Pat_ {
     /// "None" means a * pattern where we don't bind the fields to names.
     PatEnum(Path, Option<Vec<P<Pat>>>),
 
+    /// An associated const named using the qualified path `<T>::CONST` or
+    /// `<T as Trait>::CONST`. Associated consts from inherent impls can be
+    /// refered to as simply `T::CONST`, in which case they will end up as
+    /// PatEnum, and the resolver will have to sort that out.
+    PatQPath(QSelf, Path),
+
     /// Destructuring of a struct, e.g. `Foo {x, y, ..}`
     /// The `bool` is `true` in the presence of a `..`
     PatStruct(Path, Vec<Spanned<FieldPat>>, bool),
@@ -1230,6 +1236,7 @@ pub struct TraitItem {
 
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
 pub enum TraitItem_ {
+    ConstTraitItem(P<Ty>, Option<P<Expr>>),
     MethodTraitItem(MethodSig, Option<P<Block>>),
     TypeTraitItem(TyParamBounds, Option<P<Ty>>),
 }
@@ -1246,6 +1253,7 @@ pub struct ImplItem {
 
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
 pub enum ImplItem_ {
+    ConstImplItem(P<Ty>, P<Expr>),
     MethodImplItem(MethodSig, P<Block>),
     TypeImplItem(P<Ty>),
     MacImplItem(Mac),
index 1505d1e91b8206a9e44b8b4b5b938b16f35b6d06..36a7f3a93817c127b966e56ea6099ee55446e08e 100644 (file)
@@ -222,8 +222,7 @@ fn handle<A, I, M, C>(self, item_fn: I, method: M, closure: C) -> A where
                     ast::MethodImplItem(ref sig, ref body) => {
                         method(ii.id, ii.ident, sig, Some(ii.vis), body, ii.span)
                     }
-                    ast::TypeImplItem(_) |
-                    ast::MacImplItem(_) => {
+                    _ => {
                         panic!("impl method FnLikeNode that is not fn-like")
                     }
                 }
index 2a9a609ecd1e9dcbc89278eb04806f1c88dd77c0..795391d4009144cea3a2682086d5497b725a50a7 100644 (file)
@@ -940,6 +940,12 @@ fn node_id_to_string(map: &Map, id: NodeId, include_id: bool) -> String {
         }
         Some(NodeImplItem(ii)) => {
             match ii.node {
+                ConstImplItem(..) => {
+                    format!("assoc const {} in {}{}",
+                            token::get_ident(ii.ident),
+                            map.path_to_string(id),
+                            id_str)
+                }
                 MethodImplItem(..) => {
                     format!("method {} in {}{}",
                             token::get_ident(ii.ident),
@@ -959,9 +965,9 @@ fn node_id_to_string(map: &Map, id: NodeId, include_id: bool) -> String {
         }
         Some(NodeTraitItem(ti)) => {
             let kind = match ti.node {
+                ConstTraitItem(..) => "assoc constant",
                 MethodTraitItem(..) => "trait method",
                 TypeTraitItem(..) => "assoc type",
-//                 ConstTraitItem(..) => "assoc constant"
             };
 
             format!("{} {} in {}{}",
index 720b2095a908af8274da5de043e156d8e589d88d..8471fef3487e62f53af6d48d68eaab0fa040d444 100644 (file)
@@ -579,7 +579,7 @@ fn walk_pat_<G>(pat: &Pat, it: &mut G) -> bool where G: FnMut(&Pat) -> bool {
             }
             PatMac(_) => panic!("attempted to analyze unexpanded pattern"),
             PatWild(_) | PatLit(_) | PatRange(_, _) | PatIdent(_, _, _) |
-            PatEnum(_, _) => {
+            PatEnum(_, _) | PatQPath(_, _) => {
                 true
             }
         }
index fa95f667c15afc1d1119bf49b1ee19abd7ef8b03..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),
 
     // Allows use of unary negate on unsigned integers, e.g. -e for e: u8
     ("negate_unsigned", "1.0.0", Active),
+
+    // Allows the definition of associated constants in `trait` or `impl`
+    // blocks.
+    ("associated_consts", "1.0.0", Active),
 ];
 // (changing above list without updating src/doc/reference.md makes @cmr sad)
 
@@ -205,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",
@@ -659,6 +657,30 @@ fn visit_fn(&mut self,
         }
         visit::walk_fn(self, fn_kind, fn_decl, block, span);
     }
+
+    fn visit_trait_item(&mut self, ti: &'v ast::TraitItem) {
+        match ti.node {
+            ast::ConstTraitItem(..) => {
+                self.gate_feature("associated_consts",
+                                  ti.span,
+                                  "associated constants are experimental")
+            }
+            _ => {}
+        }
+        visit::walk_trait_item(self, ti);
+    }
+
+    fn visit_impl_item(&mut self, ii: &'v ast::ImplItem) {
+        match ii.node {
+            ast::ConstImplItem(..) => {
+                self.gate_feature("associated_consts",
+                                  ii.span,
+                                  "associated constants are experimental")
+            }
+            _ => {}
+        }
+        visit::walk_impl_item(self, ii);
+    }
 }
 
 fn check_crate_inner<F>(cm: &CodeMap, span_handler: &SpanHandler,
index 5352a191b095fcb015b21c7e9ff7664b3822de6d..adfda988b23b747a05c13329b097e2f4af80f8b7 100644 (file)
@@ -980,6 +980,10 @@ pub fn noop_fold_trait_item<T: Folder>(i: P<TraitItem>, folder: &mut T)
         ident: folder.fold_ident(ident),
         attrs: fold_attrs(attrs, folder),
         node: match node {
+            ConstTraitItem(ty, default) => {
+                ConstTraitItem(folder.fold_ty(ty),
+                               default.map(|x| folder.fold_expr(x)))
+            }
             MethodTraitItem(sig, body) => {
                 MethodTraitItem(noop_fold_method_sig(sig, folder),
                                 body.map(|x| folder.fold_block(x)))
@@ -1001,6 +1005,9 @@ pub fn noop_fold_impl_item<T: Folder>(i: P<ImplItem>, folder: &mut T)
         attrs: fold_attrs(attrs, folder),
         vis: vis,
         node: match node  {
+            ConstImplItem(ty, expr) => {
+                ConstImplItem(folder.fold_ty(ty), folder.fold_expr(expr))
+            }
             MethodImplItem(sig, body) => {
                 MethodImplItem(noop_fold_method_sig(sig, folder),
                                folder.fold_block(body))
@@ -1134,6 +1141,10 @@ pub fn noop_fold_pat<T: Folder>(p: P<Pat>, folder: &mut T) -> P<Pat> {
                 PatEnum(folder.fold_path(pth),
                         pats.map(|pats| pats.move_map(|x| folder.fold_pat(x))))
             }
+            PatQPath(qself, pth) => {
+                let qself = QSelf {ty: folder.fold_ty(qself.ty), .. qself};
+                PatQPath(qself, folder.fold_path(pth))
+            }
             PatStruct(pth, fields, etc) => {
                 let pth = folder.fold_path(pth);
                 let fs = fields.move_map(|f| {
index 5f097256318c0afdac6c30229ef741312888709c..f76de1f04ce2ce2f5517ad2dd2bac5d349727f35 100644 (file)
@@ -17,8 +17,8 @@
 use ast::{Mod, BiAdd, Arg, Arm, Attribute, BindByRef, BindByValue};
 use ast::{BiBitAnd, BiBitOr, BiBitXor, BiRem, BiLt, BiGt, Block};
 use ast::{BlockCheckMode, CaptureByRef, CaptureByValue, CaptureClause};
-use ast::{Crate, CrateConfig, Decl, DeclItem};
-use ast::{DeclLocal, DefaultBlock, DefaultReturn};
+use ast::{ConstImplItem, ConstTraitItem, Crate, CrateConfig};
+use ast::{Decl, DeclItem, DeclLocal, DefaultBlock, DefaultReturn};
 use ast::{UnDeref, BiDiv, EMPTY_CTXT, EnumDef, ExplicitSelf};
 use ast::{Expr, Expr_, ExprAddrOf, ExprMatch, ExprAgain};
 use ast::{ExprAssign, ExprAssignOp, ExprBinary, ExprBlock, ExprBox};
@@ -40,8 +40,9 @@
 use ast::{MutImmutable, MutMutable, Mac_, MacInvocTT, MatchSource};
 use ast::{MutTy, BiMul, Mutability};
 use ast::{MethodImplItem, NamedField, UnNeg, NoReturn, UnNot};
-use ast::{Pat, PatBox, PatEnum, PatIdent, PatLit, PatMac, PatRange, PatRegion};
-use ast::{PatStruct, PatTup, PatVec, PatWild, PatWildMulti, PatWildSingle};
+use ast::{Pat, PatBox, PatEnum, PatIdent, PatLit, PatQPath, PatMac, PatRange};
+use ast::{PatRegion, PatStruct, PatTup, PatVec, PatWild, PatWildMulti};
+use ast::PatWildSingle;
 use ast::{PolyTraitRef, QSelf};
 use ast::{Return, BiShl, BiShr, Stmt, StmtDecl};
 use ast::{StmtExpr, StmtSemi, StmtMac, StructDef, StructField};
@@ -109,6 +110,15 @@ pub enum PathParsingMode {
     LifetimeAndTypesWithColons,
 }
 
+/// How to parse a qualified path, whether to allow trailing parameters.
+#[derive(Copy, Clone, PartialEq)]
+pub enum QPathParsingMode {
+    /// No trailing parameters, e.g. `<T as Trait>::Item`
+    NoParameters,
+    /// Optional parameters, e.g. `<T as Trait>::item::<'a, U>`
+    MaybeParameters,
+}
+
 /// How to parse a bound, whether to allow bound modifiers such as `?`.
 #[derive(Copy, Clone, PartialEq)]
 pub enum BoundParsingMode {
@@ -1161,6 +1171,20 @@ pub fn parse_trait_items(&mut self) -> PResult<Vec<P<TraitItem>>> {
                 let TyParam {ident, bounds, default, ..} = try!(p.parse_ty_param());
                 try!(p.expect(&token::Semi));
                 (ident, TypeTraitItem(bounds, default))
+            } else if try!(p.eat_keyword(keywords::Const)) {
+                let ident = try!(p.parse_ident());
+                try!(p.expect(&token::Colon));
+                let ty = try!(p.parse_ty_sum());
+                let default = if p.check(&token::Eq) {
+                    try!(p.bump());
+                    let expr = try!(p.parse_expr_nopanic());
+                    try!(p.commit_expr_expecting(&expr, token::Semi));
+                    Some(expr)
+                } else {
+                    try!(p.expect(&token::Semi));
+                    None
+                };
+                (ident, ConstTraitItem(ty, default))
             } else {
                 let style = try!(p.parse_unsafety());
                 let abi = if try!(p.eat_keyword(keywords::Extern)) {
@@ -1334,36 +1358,9 @@ pub fn parse_ty_nopanic(&mut self) -> PResult<P<Ty>> {
             try!(self.expect(&token::CloseDelim(token::Paren)));
             TyTypeof(e)
         } else if try!(self.eat_lt()) {
-            // QUALIFIED PATH `<TYPE as TRAIT_REF>::item`
-            let self_type = try!(self.parse_ty_sum());
 
-            let mut path = if try!(self.eat_keyword(keywords::As) ){
-                try!(self.parse_path(LifetimeAndTypesWithoutColons))
-            } else {
-                ast::Path {
-                    span: self.span,
-                    global: false,
-                    segments: vec![]
-                }
-            };
-
-            let qself = QSelf {
-                ty: self_type,
-                position: path.segments.len()
-            };
-
-            try!(self.expect(&token::Gt));
-            try!(self.expect(&token::ModSep));
-
-            path.segments.push(ast::PathSegment {
-                identifier: try!(self.parse_ident()),
-                parameters: ast::PathParameters::none()
-            });
-
-            if path.segments.len() == 1 {
-                path.span.lo = self.last_span.lo;
-            }
-            path.span.hi = self.last_span.hi;
+            let (qself, path) =
+                 try!(self.parse_qualified_path(QPathParsingMode::NoParameters));
 
             TyPath(Some(qself), path)
         } else if self.check(&token::ModSep) ||
@@ -1580,6 +1577,61 @@ pub fn parse_literal_maybe_minus(&mut self) -> PResult<P<Expr>> {
         }
     }
 
+    // QUALIFIED PATH `<TYPE [as TRAIT_REF]>::IDENT[::<PARAMS>]`
+    // Assumes that the leading `<` has been parsed already.
+    pub fn parse_qualified_path(&mut self, mode: QPathParsingMode)
+                                -> PResult<(QSelf, ast::Path)> {
+        let self_type = try!(self.parse_ty_sum());
+        let mut path = if try!(self.eat_keyword(keywords::As)) {
+            try!(self.parse_path(LifetimeAndTypesWithoutColons))
+        } else {
+            ast::Path {
+                span: self.span,
+                global: false,
+                segments: vec![]
+            }
+        };
+
+        let qself = QSelf {
+            ty: self_type,
+            position: path.segments.len()
+        };
+
+        try!(self.expect(&token::Gt));
+        try!(self.expect(&token::ModSep));
+
+        let item_name = try!(self.parse_ident());
+        let parameters = match mode {
+            QPathParsingMode::NoParameters => ast::PathParameters::none(),
+            QPathParsingMode::MaybeParameters => {
+                if try!(self.eat(&token::ModSep)) {
+                    try!(self.expect_lt());
+                    // Consumed `item::<`, go look for types
+                    let (lifetimes, types, bindings) =
+                        try!(self.parse_generic_values_after_lt());
+                    ast::AngleBracketedParameters(ast::AngleBracketedParameterData {
+                        lifetimes: lifetimes,
+                        types: OwnedSlice::from_vec(types),
+                        bindings: OwnedSlice::from_vec(bindings),
+                    })
+                } else {
+                    ast::PathParameters::none()
+                }
+            }
+        };
+        path.segments.push(ast::PathSegment {
+            identifier: item_name,
+            parameters: parameters
+        });
+
+        if path.segments.len() == 1 {
+            path.span.lo = self.last_span.lo;
+        }
+        path.span.hi = self.last_span.hi;
+
+        Ok((qself, path))
+    }
+
     /// Parses a path and optional type parameter bounds, depending on the
     /// mode. The `mode` parameter determines whether lifetimes, types, and/or
     /// bounds are permitted and whether `::` must precede type parameter
@@ -2043,49 +2095,10 @@ pub fn parse_bottom_expr(&mut self) -> PResult<P<Expr>> {
             }
             _ => {
                 if try!(self.eat_lt()){
-                    // QUALIFIED PATH `<TYPE as TRAIT_REF>::item::<'a, T>`
-                    let self_type = try!(self.parse_ty_sum());
-                    let mut path = if try!(self.eat_keyword(keywords::As) ){
-                        try!(self.parse_path(LifetimeAndTypesWithoutColons))
-                    } else {
-                        ast::Path {
-                            span: self.span,
-                            global: false,
-                            segments: vec![]
-                        }
-                    };
-                    let qself = QSelf {
-                        ty: self_type,
-                        position: path.segments.len()
-                    };
-                    try!(self.expect(&token::Gt));
-                    try!(self.expect(&token::ModSep));
-
-                    let item_name = try!(self.parse_ident());
-                    let parameters = if try!(self.eat(&token::ModSep) ){
-                        try!(self.expect_lt());
-                        // Consumed `item::<`, go look for types
-                        let (lifetimes, types, bindings) =
-                            try!(self.parse_generic_values_after_lt());
-                        ast::AngleBracketedParameters(ast::AngleBracketedParameterData {
-                            lifetimes: lifetimes,
-                            types: OwnedSlice::from_vec(types),
-                            bindings: OwnedSlice::from_vec(bindings),
-                        })
-                    } else {
-                        ast::PathParameters::none()
-                    };
-                    path.segments.push(ast::PathSegment {
-                        identifier: item_name,
-                        parameters: parameters
-                    });
 
-                    if path.segments.len() == 1 {
-                        path.span.lo = self.last_span.lo;
-                    }
-                    path.span.hi = self.last_span.hi;
+                    let (qself, path) =
+                        try!(self.parse_qualified_path(QPathParsingMode::MaybeParameters));
 
-                    let hi = self.span.hi;
                     return Ok(self.mk_expr(lo, hi, ExprPath(Some(qself), path)));
                 }
                 if try!(self.eat_keyword(keywords::Move) ){
@@ -3158,16 +3171,25 @@ fn parse_pat_fields(&mut self) -> PResult<(Vec<codemap::Spanned<ast::FieldPat>>
     fn parse_pat_range_end(&mut self) -> PResult<P<Expr>> {
         if self.is_path_start() {
             let lo = self.span.lo;
-            let path = try!(self.parse_path(LifetimeAndTypesWithColons));
+            let (qself, path) = if try!(self.eat_lt()) {
+                // Parse a qualified path
+                let (qself, path) =
+                    try!(self.parse_qualified_path(QPathParsingMode::NoParameters));
+                (Some(qself), path)
+            } else {
+                // Parse an unqualified path
+                (None, try!(self.parse_path(LifetimeAndTypesWithColons)))
+            };
             let hi = self.last_span.hi;
-            Ok(self.mk_expr(lo, hi, ExprPath(None, path)))
+            Ok(self.mk_expr(lo, hi, ExprPath(qself, path)))
         } else {
             self.parse_literal_maybe_minus()
         }
     }
 
     fn is_path_start(&self) -> bool {
-        (self.token == token::ModSep || self.token.is_ident() || self.token.is_path())
+        (self.token == token::Lt || self.token == token::ModSep
+            || self.token.is_ident() || self.token.is_path())
             && !self.token.is_keyword(keywords::True) && !self.token.is_keyword(keywords::False)
     }
 
@@ -3243,25 +3265,44 @@ pub fn parse_pat_nopanic(&mut self) -> PResult<P<Pat>> {
                         pat = try!(self.parse_pat_ident(BindByValue(MutImmutable)));
                     }
                 } else {
-                    // Parse as a general path
-                    let path = try!(self.parse_path(LifetimeAndTypesWithColons));
+                    let (qself, path) = if try!(self.eat_lt()) {
+                        // Parse a qualified path
+                        let (qself, path) =
+                            try!(self.parse_qualified_path(QPathParsingMode::NoParameters));
+                        (Some(qself), path)
+                    } else {
+                        // Parse an unqualified path
+                        (None, try!(self.parse_path(LifetimeAndTypesWithColons)))
+                    };
                     match self.token {
                       token::DotDotDot => {
                         // Parse range
                         let hi = self.last_span.hi;
-                        let begin = self.mk_expr(lo, hi, ExprPath(None, path));
+                        let begin = self.mk_expr(lo, hi, ExprPath(qself, path));
                         try!(self.bump());
                         let end = try!(self.parse_pat_range_end());
                         pat = PatRange(begin, end);
                       }
                       token::OpenDelim(token::Brace) => {
-                        // Parse struct pattern
+                         if qself.is_some() {
+                            let span = self.span;
+                            self.span_err(span,
+                                          "unexpected `{` after qualified path");
+                            self.abort_if_errors();
+                        }
+                       // Parse struct pattern
                         try!(self.bump());
                         let (fields, etc) = try!(self.parse_pat_fields());
                         try!(self.bump());
                         pat = PatStruct(path, fields, etc);
                       }
                       token::OpenDelim(token::Paren) => {
+                        if qself.is_some() {
+                            let span = self.span;
+                            self.span_err(span,
+                                          "unexpected `(` after qualified path");
+                            self.abort_if_errors();
+                        }
                         // Parse tuple struct or enum pattern
                         if self.look_ahead(1, |t| *t == token::DotDot) {
                             // This is a "top constructor only" pat
@@ -3278,6 +3319,10 @@ pub fn parse_pat_nopanic(&mut self) -> PResult<P<Pat>> {
                             pat = PatEnum(path, Some(args));
                         }
                       }
+                      _ if qself.is_some() => {
+                        // Parse qualified path
+                        pat = PatQPath(qself.unwrap(), path);
+                      }
                       _ => {
                         // Parse nullary enum
                         pat = PatEnum(path, Some(vec![]));
@@ -4349,6 +4394,14 @@ pub fn parse_impl_item(&mut self) -> PResult<P<ImplItem>> {
             let typ = try!(self.parse_ty_sum());
             try!(self.expect(&token::Semi));
             (name, TypeImplItem(typ))
+        } else if try!(self.eat_keyword(keywords::Const)) {
+            let name = try!(self.parse_ident());
+            try!(self.expect(&token::Colon));
+            let typ = try!(self.parse_ty_sum());
+            try!(self.expect(&token::Eq));
+            let expr = try!(self.parse_expr_nopanic());
+            try!(self.commit_expr_expecting(&expr, token::Semi));
+            (name, ConstImplItem(typ, expr))
         } else {
             let (name, inner_attrs, node) = try!(self.parse_impl_method(vis));
             attrs.extend(inner_attrs.into_iter());
index 36364eb9bf3d5901bc9e1fc095d4d2e02d80c252..87c164f7550f9a5e56b3a3f3918af47dc0ac43ec 100644 (file)
@@ -761,6 +761,26 @@ pub fn print_foreign_item(&mut self,
         }
     }
 
+    fn print_associated_const(&mut self,
+                              ident: ast::Ident,
+                              ty: &ast::Ty,
+                              default: Option<&ast::Expr>,
+                              vis: ast::Visibility)
+                              -> io::Result<()>
+    {
+        try!(word(&mut self.s, &visibility_qualified(vis, "")));
+        try!(self.word_space("const"));
+        try!(self.print_ident(ident));
+        try!(self.word_space(":"));
+        try!(self.print_type(ty));
+        if let Some(expr) = default {
+            try!(space(&mut self.s));
+            try!(self.word_space("="));
+            try!(self.print_expr(expr));
+        }
+        word(&mut self.s, ";")
+    }
+
     fn print_associated_type(&mut self,
                              ident: ast::Ident,
                              bounds: Option<&ast::TyParamBounds>,
@@ -1234,6 +1254,11 @@ pub fn print_trait_item(&mut self, ti: &ast::TraitItem)
         try!(self.maybe_print_comment(ti.span.lo));
         try!(self.print_outer_attributes(&ti.attrs));
         match ti.node {
+            ast::ConstTraitItem(ref ty, ref default) => {
+                try!(self.print_associated_const(ti.ident, &ty,
+                                                 default.as_ref().map(|expr| &**expr),
+                                                 ast::Inherited));
+            }
             ast::MethodTraitItem(ref sig, ref body) => {
                 if body.is_some() {
                     try!(self.head(""));
@@ -1260,6 +1285,9 @@ pub fn print_impl_item(&mut self, ii: &ast::ImplItem) -> io::Result<()> {
         try!(self.maybe_print_comment(ii.span.lo));
         try!(self.print_outer_attributes(&ii.attrs));
         match ii.node {
+            ast::ConstImplItem(ref ty, ref expr) => {
+                try!(self.print_associated_const(ii.ident, &ty, Some(&expr), ii.vis));
+            }
             ast::MethodImplItem(ref sig, ref body) => {
                 try!(self.head(""));
                 try!(self.print_method_sig(ii.ident, sig, ii.vis));
@@ -2152,6 +2180,9 @@ pub fn print_pat(&mut self, pat: &ast::Pat) -> io::Result<()> {
                     }
                 }
             }
+            ast::PatQPath(ref qself, ref path) => {
+                try!(self.print_qpath(path, qself, false));
+            }
             ast::PatStruct(ref path, ref fields, etc) => {
                 try!(self.print_path(path, true, 0));
                 try!(self.nbsp());
index 4c70fc9f81fb93ce267563a3253b1fe0614e51cc..6cf791b10be67612eaa75ad146d630fafb1a5602 100644 (file)
@@ -464,6 +464,10 @@ pub fn walk_pat<'v, V: Visitor<'v>>(visitor: &mut V, pattern: &'v Pat) {
                 }
             }
         }
+        PatQPath(ref qself, ref path) => {
+            visitor.visit_ty(&qself.ty);
+            visitor.visit_path(path, pattern.id)
+        }
         PatStruct(ref path, ref fields, _) => {
             visitor.visit_path(path, pattern.id);
             for field in fields {
@@ -619,6 +623,12 @@ pub fn walk_trait_item<'v, V: Visitor<'v>>(visitor: &mut V, trait_item: &'v Trai
         visitor.visit_attribute(attr);
     }
     match trait_item.node {
+        ConstTraitItem(ref ty, ref default) => {
+            visitor.visit_ty(ty);
+            if let Some(ref expr) = *default {
+                visitor.visit_expr(expr);
+            }
+        }
         MethodTraitItem(ref sig, None) => {
             visitor.visit_explicit_self(&sig.explicit_self);
             visitor.visit_generics(&sig.generics);
@@ -641,6 +651,10 @@ pub fn walk_impl_item<'v, V: Visitor<'v>>(visitor: &mut V, impl_item: &'v ImplIt
         visitor.visit_attribute(attr);
     }
     match impl_item.node {
+        ConstImplItem(ref ty, ref expr) => {
+            visitor.visit_ty(ty);
+            visitor.visit_expr(expr);
+        }
         MethodImplItem(ref sig, ref body) => {
             visitor.visit_fn(FkMethod(impl_item.ident, sig, Some(impl_item.vis)), &sig.decl,
                              body, impl_item.span, impl_item.id);
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
diff --git a/src/test/auxiliary/associated-const-cc-lib.rs b/src/test/auxiliary/associated-const-cc-lib.rs
new file mode 100644 (file)
index 0000000..1fd8fee
--- /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.
+
+#![feature(associated_consts)]
+
+#![crate_type="lib"]
+
+// These items are for testing that associated consts work cross-crate.
+pub trait Foo {
+    const BAR: usize;
+}
+
+pub struct FooNoDefault;
+
+impl Foo for FooNoDefault {
+    const BAR: usize = 0;
+}
+
+// These test that defaults and default resolution work cross-crate.
+pub trait FooDefault {
+    const BAR: usize = 1;
+}
+
+pub struct FooOverwriteDefault;
+
+impl FooDefault for FooOverwriteDefault {
+    const BAR: usize = 2;
+}
+
+pub struct FooUseDefault;
+
+impl FooDefault for FooUseDefault {}
+
+// Test inherent impls.
+pub struct InherentBar;
+
+impl InherentBar {
+    pub const BAR: usize = 3;
+}
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) {}
 }
diff --git a/src/test/compile-fail/associated-const-dead-code.rs b/src/test/compile-fail/associated-const-dead-code.rs
new file mode 100644 (file)
index 0000000..1ed156d
--- /dev/null
@@ -0,0 +1,23 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(associated_consts)]
+#![deny(dead_code)]
+
+struct MyFoo;
+
+impl MyFoo {
+    const BAR: u32 = 1;
+    //~^ ERROR associated const is never used: `BAR`
+}
+
+fn main() {
+    let _: MyFoo = MyFoo;
+}
diff --git a/src/test/compile-fail/associated-const-impl-wrong-type.rs b/src/test/compile-fail/associated-const-impl-wrong-type.rs
new file mode 100644 (file)
index 0000000..4f20d9e
--- /dev/null
@@ -0,0 +1,24 @@
+// 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.
+
+#![feature(associated_consts)]
+
+trait Foo {
+    const BAR: u32;
+}
+
+struct SignedBar;
+
+impl Foo for SignedBar {
+    const BAR: i32 = -1;
+    //~^ ERROR E0326
+}
+
+fn main() {}
diff --git a/src/test/compile-fail/associated-const-private-impl.rs b/src/test/compile-fail/associated-const-private-impl.rs
new file mode 100644 (file)
index 0000000..be949db
--- /dev/null
@@ -0,0 +1,27 @@
+// 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.
+
+#![feature(associated_consts)]
+
+mod bar1 {
+    pub use self::bar2::Foo;
+    mod bar2 {
+        pub struct Foo;
+
+        impl Foo {
+            const ID: i32 = 1;
+        }
+    }
+}
+
+fn main() {
+    assert_eq!(1, bar1::Foo::ID);
+    //~^ERROR associated const `ID` is private
+}
diff --git a/src/test/compile-fail/associated-const-upper-case-lint.rs b/src/test/compile-fail/associated-const-upper-case-lint.rs
new file mode 100644 (file)
index 0000000..752691f
--- /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.
+
+#![feature(associated_consts)]
+#![deny(non_upper_case_globals)]
+#![allow(dead_code)]
+
+struct Foo;
+
+impl Foo {
+    const not_upper: bool = true;
+}
+//~^^ ERROR associated constant `not_upper` should have an upper case name such as `NOT_UPPER`
+
+fn main() {}
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-associated_consts.rs b/src/test/compile-fail/gated-associated_consts.rs
new file mode 100644 (file)
index 0000000..21672b1
--- /dev/null
@@ -0,0 +1,23 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+trait MyTrait {
+    const C: bool;
+    //~^ associated constants are experimental
+    //~| add #![feature(associated_consts)] to the crate attributes to enable
+}
+
+struct Foo;
+
+impl Foo {
+    const C: bool = true;
+    //~^ associated constants are experimental
+    //~| add #![feature(associated_consts)] to the crate attributes to enable
+}
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/impl-wrong-item-for-trait.rs b/src/test/compile-fail/impl-wrong-item-for-trait.rs
new file mode 100644 (file)
index 0000000..9b3e28c
--- /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.
+
+#![feature(associated_consts)]
+
+trait Foo {
+    fn bar(&self);
+    const MY_CONST: u32;
+}
+
+pub struct FooConstForMethod;
+
+impl Foo for FooConstForMethod {
+    //~^ ERROR E0046
+    const bar: u64 = 1;
+    //~^ ERROR E0323
+    const MY_CONST: u32 = 1;
+}
+
+pub struct FooMethodForConst;
+
+impl Foo for FooMethodForConst {
+    //~^ ERROR E0046
+    fn bar(&self) {}
+    fn MY_CONST() {}
+    //~^ ERROR E0324
+}
+
+pub struct FooTypeForMethod;
+
+impl Foo for FooTypeForMethod {
+    //~^ ERROR E0046
+    type bar = u64;
+    //~^ ERROR E0325
+    const MY_CONST: u32 = 1;
+}
+
+fn main () {}
diff --git a/src/test/compile-fail/issue-24895-copy-clone-dropck.rs b/src/test/compile-fail/issue-24895-copy-clone-dropck.rs
new file mode 100644 (file)
index 0000000..2883511
--- /dev/null
@@ -0,0 +1,38 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Check that one cannot subvert Drop Check rule via a user-defined
+// Clone implementation.
+
+#![allow(unused_variables, unused_assignments)]
+
+struct D<T:Copy>(T, &'static str);
+
+#[derive(Copy)]
+struct S<'a>(&'a D<i32>, &'static str);
+impl<'a> Clone for S<'a> {
+    fn clone(&self) -> S<'a> {
+        println!("cloning `S(_, {})` and thus accessing: {}", self.1, (self.0).0);
+        S(self.0, self.1)
+    }
+}
+
+impl<T:Copy> Drop for D<T> {
+    fn drop(&mut self) {
+        println!("calling Drop for {}", self.1);
+        let _call = self.0.clone();
+    }
+}
+
+fn main() {
+    let (d2, d1);
+    d1 = D(34, "d1");
+    d2 = D(S(&d1, "inner"), "d2"); //~ ERROR `d1` does not live long enough
+}
diff --git a/src/test/compile-fail/method-path-in-pattern.rs b/src/test/compile-fail/method-path-in-pattern.rs
new file mode 100644 (file)
index 0000000..faf6d25
--- /dev/null
@@ -0,0 +1,33 @@
+// 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.
+
+struct Foo;
+
+impl Foo {
+    fn bar(&self) {}
+}
+
+trait MyTrait {
+    fn trait_bar() {}
+}
+
+impl MyTrait for Foo {}
+
+fn main() {
+    match 0u32 {
+        Foo::bar => {} //~ ERROR E0327
+    }
+    match 0u32 {
+        <Foo>::bar => {} //~ ERROR E0327
+    }
+    match 0u32 {
+        <Foo>::trait_bar => {} //~ ERROR E0327
+    }
+}
diff --git a/src/test/compile-fail/method-resolvable-path-in-pattern.rs b/src/test/compile-fail/method-resolvable-path-in-pattern.rs
new file mode 100644 (file)
index 0000000..0df824e
--- /dev/null
@@ -0,0 +1,24 @@
+// 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.
+
+struct Foo;
+
+trait MyTrait {
+    fn trait_bar() {}
+}
+
+impl MyTrait for Foo {}
+
+fn main() {
+    match 0u32 {
+        <Foo as MyTrait>::trait_bar => {}
+        //~^ ERROR `trait_bar` is not an associated const
+    }
+}
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 {
diff --git a/src/test/parse-fail/brace-after-qualified-path-in-match.rs b/src/test/parse-fail/brace-after-qualified-path-in-match.rs
new file mode 100644 (file)
index 0000000..66f462d
--- /dev/null
@@ -0,0 +1,17 @@
+// 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.
+
+fn foo() {
+    match x {
+        <T as Trait>::Type{key: value} => (),
+        //~^ ERROR unexpected `{` after qualified path
+        _ => (),
+    }
+}
index 2c993b7654e677e7d7f5f6d3947ec3b5007214b2..be6bd516d6fe439388160260d61fc3c4f824d302 100644 (file)
@@ -16,6 +16,6 @@ impl Foo {
     fn foo() {}
 
     #[stable(feature = "rust1", since = "1.0.0")]
-} //~ ERROR expected one of `extern`, `fn`, `pub`, `type`, or `unsafe`, found `}`
+} //~ ERROR expected one of `const`, `extern`, `fn`, `pub`, `type`, or `unsafe`, found `}`
 
 fn main() {}
index 8462bd8fd016a14b50879dcddefc4a7e9326e943..d1d8d3acf91871bc581d3799380a47aca6d1126f 100644 (file)
@@ -14,6 +14,6 @@
 
 impl Foo {
     #[stable(feature = "rust1", since = "1.0.0")]
-} //~ ERROR expected one of `extern`, `fn`, `pub`, `type`, or `unsafe`, found `}`
+} //~ ERROR expected one of `const`, `extern`, `fn`, `pub`, `type`, or `unsafe`, found `}`
 
 fn main() {}
index 44d979ba9798b21cb2d9d85f77e19639edf44420..76a4687f544da3578a553d654818dd5783e9506e 100644 (file)
@@ -11,5 +11,5 @@
 // compile-flags: -Z parse-only
 
 trait MyTrait<T>: Iterator {
-    Item = T; //~ ERROR expected one of `extern`, `fn`, `type`, or `unsafe`, found `Item`
+    Item = T; //~ ERROR expected one of `const`, `extern`, `fn`, `type`, or `unsafe`, found `Item`
 }
diff --git a/src/test/parse-fail/paren-after-qualified-path-in-match.rs b/src/test/parse-fail/paren-after-qualified-path-in-match.rs
new file mode 100644 (file)
index 0000000..d06fd2b
--- /dev/null
@@ -0,0 +1,17 @@
+// 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.
+
+fn foo() {
+    match x {
+        <T as Trait>::Type(2) => (),
+        //~^ ERROR unexpected `(` after qualified path
+        _ => (),
+    }
+}
index be1e89dd71799ff5d66165477fed81197631ffbd..7b6caad86b6ccc0b6005dc41c869648a065650ec 100644 (file)
@@ -14,5 +14,5 @@
 
 impl S {
     static fn f() {}
-    //~^ ERROR expected one of `extern`, `fn`, `pub`, `type`, `unsafe`, or `}`, found `static`
 }
+//~^^ ERROR expected one of `const`, `extern`, `fn`, `pub`, `type`, `unsafe`, or `}`, found `static`
diff --git a/src/test/parse-fail/trait-pub-assoc-const.rs b/src/test/parse-fail/trait-pub-assoc-const.rs
new file mode 100644 (file)
index 0000000..adce0d7
--- /dev/null
@@ -0,0 +1,16 @@
+// 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.
+
+trait Foo {
+    pub const Foo: u32;
+     //~^ ERROR expected one of `const`, `extern`, `fn`, `type`, or `unsafe`, found `pub`
+}
+
+fn main() {}
index 02d76234d4e57d97d73d98ee1745b7f6cca84305..dab6c433aba4c187fac25a0323d0438332d4af96 100644 (file)
@@ -9,7 +9,8 @@
 // except according to those terms.
 
 trait Foo {
-    pub type Foo; //~ ERROR expected one of `extern`, `fn`, `type`, or `unsafe`, found `pub`
+    pub type Foo;
+    //~^ ERROR expected one of `const`, `extern`, `fn`, `type`, or `unsafe`, found `pub`
 }
 
 fn main() {}
index e76802d2ea0f7bdeb1d5976c8ac10d83368de6ba..7cb9363830c43ab28b3d9f3089ba3b86d583d0b4 100644 (file)
@@ -9,7 +9,8 @@
 // except according to those terms.
 
 trait Foo {
-    pub fn foo(); //~ ERROR expected one of `extern`, `fn`, `type`, or `unsafe`, found `pub`
+    pub fn foo();
+    //~^ ERROR expected one of `const`, `extern`, `fn`, `type`, or `unsafe`, found `pub`
 }
 
 fn main() {}
diff --git a/src/test/run-fail-fulldeps/qquote.rs b/src/test/run-fail-fulldeps/qquote.rs
new file mode 100644 (file)
index 0000000..6ae2239
--- /dev/null
@@ -0,0 +1,44 @@
+// 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.
+
+// ignore-cross-compile
+
+// error-pattern:expected identifier, found keyword `let`
+
+#![feature(quote, rustc_private)]
+
+extern crate syntax;
+
+use syntax::ast;
+use syntax::codemap::{self, DUMMY_SP};
+use syntax::parse;
+use syntax::print::pprust;
+
+fn main() {
+    let ps = syntax::parse::new_parse_sess();
+    let mut cx = syntax::ext::base::ExtCtxt::new(
+        &ps, vec![],
+        syntax::ext::expand::ExpansionConfig::default("qquote".to_string()));
+    cx.bt_push(syntax::codemap::ExpnInfo {
+        call_site: DUMMY_SP,
+        callee: syntax::codemap::NameAndSpan {
+            name: "".to_string(),
+            format: syntax::codemap::MacroBang,
+            allow_internal_unstable: false,
+            span: None,
+        }
+    });
+    let cx = &mut cx;
+
+    assert_eq!(pprust::expr_to_string(&*quote_expr!(&cx, 23)), "23");
+
+    let expr = quote_expr!(&cx, let x isize = 20;);
+    assert_eq!(pprust::expr_to_string(&*expr), "let x isize = 20;");
+}
diff --git a/src/test/run-fail/qquote.rs b/src/test/run-fail/qquote.rs
deleted file mode 100644 (file)
index 6ae2239..0000000
+++ /dev/null
@@ -1,44 +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.
-
-// ignore-cross-compile
-
-// error-pattern:expected identifier, found keyword `let`
-
-#![feature(quote, rustc_private)]
-
-extern crate syntax;
-
-use syntax::ast;
-use syntax::codemap::{self, DUMMY_SP};
-use syntax::parse;
-use syntax::print::pprust;
-
-fn main() {
-    let ps = syntax::parse::new_parse_sess();
-    let mut cx = syntax::ext::base::ExtCtxt::new(
-        &ps, vec![],
-        syntax::ext::expand::ExpansionConfig::default("qquote".to_string()));
-    cx.bt_push(syntax::codemap::ExpnInfo {
-        call_site: DUMMY_SP,
-        callee: syntax::codemap::NameAndSpan {
-            name: "".to_string(),
-            format: syntax::codemap::MacroBang,
-            allow_internal_unstable: false,
-            span: None,
-        }
-    });
-    let cx = &mut cx;
-
-    assert_eq!(pprust::expr_to_string(&*quote_expr!(&cx, 23)), "23");
-
-    let expr = quote_expr!(&cx, let x isize = 20;);
-    assert_eq!(pprust::expr_to_string(&*expr), "let x isize = 20;");
-}
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.
diff --git a/src/test/run-pass/associated-const-cross-crate-defaults.rs b/src/test/run-pass/associated-const-cross-crate-defaults.rs
new file mode 100644 (file)
index 0000000..92d2aae
--- /dev/null
@@ -0,0 +1,32 @@
+// 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:associated-const-cc-lib.rs
+
+#![feature(associated_consts)]
+
+extern crate associated_const_cc_lib as foolib;
+
+pub struct LocalFooUseDefault;
+
+impl foolib::FooDefault for LocalFooUseDefault {}
+
+pub struct LocalFooOverwriteDefault;
+
+impl foolib::FooDefault for LocalFooOverwriteDefault {
+    const BAR: usize = 4;
+}
+
+fn main() {
+    assert_eq!(1, <foolib::FooUseDefault as foolib::FooDefault>::BAR);
+    assert_eq!(2, <foolib::FooOverwriteDefault as foolib::FooDefault>::BAR);
+    assert_eq!(1, <LocalFooUseDefault as foolib::FooDefault>::BAR);
+    assert_eq!(4, <LocalFooOverwriteDefault as foolib::FooDefault>::BAR);
+}
diff --git a/src/test/run-pass/associated-const-cross-crate.rs b/src/test/run-pass/associated-const-cross-crate.rs
new file mode 100644 (file)
index 0000000..73d5dc5
--- /dev/null
@@ -0,0 +1,27 @@
+// 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:associated-const-cc-lib.rs
+
+#![feature(associated_consts)]
+
+extern crate associated_const_cc_lib as foolib;
+
+pub struct LocalFoo;
+
+impl foolib::Foo for LocalFoo {
+    const BAR: usize = 1;
+}
+
+fn main() {
+    assert_eq!(0, <foolib::FooNoDefault as foolib::Foo>::BAR);
+    assert_eq!(1, <LocalFoo as foolib::Foo>::BAR);
+    assert_eq!(3, foolib::InherentBar::BAR);
+}
diff --git a/src/test/run-pass/associated-const-in-global-const.rs b/src/test/run-pass/associated-const-in-global-const.rs
new file mode 100644 (file)
index 0000000..e3a1e29
--- /dev/null
@@ -0,0 +1,23 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(associated_consts)]
+
+struct Foo;
+
+impl Foo {
+    const BAR: f32 = 1.5;
+}
+
+const FOOBAR: f32 = <Foo>::BAR;
+
+fn main() {
+    assert_eq!(1.5f32, FOOBAR);
+}
diff --git a/src/test/run-pass/associated-const-inherent-impl.rs b/src/test/run-pass/associated-const-inherent-impl.rs
new file mode 100644 (file)
index 0000000..5c9abf9
--- /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.
+
+#![feature(associated_consts)]
+
+struct Foo;
+
+impl Foo {
+    const ID: i32 = 1;
+}
+
+fn main() {
+    assert_eq!(1, Foo::ID);
+}
diff --git a/src/test/run-pass/associated-const-marks-live-code.rs b/src/test/run-pass/associated-const-marks-live-code.rs
new file mode 100644 (file)
index 0000000..ea91a95
--- /dev/null
@@ -0,0 +1,25 @@
+// 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.
+
+#![feature(associated_consts)]
+
+#![deny(dead_code)]
+
+const GLOBAL_BAR: u32 = 1;
+
+struct Foo;
+
+impl Foo {
+    const BAR: u32 = GLOBAL_BAR;
+}
+
+pub fn main() {
+    let _: u32 = Foo::BAR;
+}
diff --git a/src/test/run-pass/associated-const-match-patterns.rs b/src/test/run-pass/associated-const-match-patterns.rs
new file mode 100644 (file)
index 0000000..eeaacbf
--- /dev/null
@@ -0,0 +1,52 @@
+// 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.
+
+#![feature(associated_consts)]
+
+struct Foo;
+
+enum Bar {
+    Var1,
+    Var2,
+}
+
+// Use inherent and trait impls to test UFCS syntax.
+impl Foo {
+    const MYBAR: Bar = Bar::Var2;
+}
+
+trait HasBar {
+    const THEBAR: Bar;
+}
+
+impl HasBar for Foo {
+    const THEBAR: Bar = Bar::Var1;
+}
+
+fn main() {
+    // Inherent impl
+    assert!(match Bar::Var2 {
+        Foo::MYBAR => true,
+        _ => false,
+    });
+    assert!(match Bar::Var2 {
+        <Foo>::MYBAR => true,
+        _ => false,
+    });
+    // Trait impl
+    assert!(match Bar::Var1 {
+        <Foo>::THEBAR => true,
+        _ => false,
+    });
+    assert!(match Bar::Var1 {
+        <Foo as HasBar>::THEBAR => true,
+        _ => false,
+    });
+}
diff --git a/src/test/run-pass/associated-const-overwrite-default.rs b/src/test/run-pass/associated-const-overwrite-default.rs
new file mode 100644 (file)
index 0000000..0846ad9
--- /dev/null
@@ -0,0 +1,23 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(associated_consts)]
+
+trait Foo {
+    const ID: i32 = 2;
+}
+
+impl Foo for i32 {
+    const ID: i32 = 1;
+}
+
+fn main() {
+    assert_eq!(1, <i32 as Foo>::ID);
+}
diff --git a/src/test/run-pass/associated-const-public-impl.rs b/src/test/run-pass/associated-const-public-impl.rs
new file mode 100644 (file)
index 0000000..b1d0717
--- /dev/null
@@ -0,0 +1,26 @@
+// 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.
+
+#![feature(associated_consts)]
+
+mod bar1 {
+    pub use self::bar2::Foo;
+    mod bar2 {
+        pub struct Foo;
+
+        impl Foo {
+            pub const ID: i32 = 1;
+        }
+    }
+}
+
+fn main() {
+    assert_eq!(1, bar1::Foo::ID);
+}
diff --git a/src/test/run-pass/associated-const-resolution-order.rs b/src/test/run-pass/associated-const-resolution-order.rs
new file mode 100644 (file)
index 0000000..98b7164
--- /dev/null
@@ -0,0 +1,35 @@
+// 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.
+
+#![feature(associated_consts)]
+
+struct MyType;
+
+impl MyType {
+    const IMPL_IS_INHERENT: bool = true;
+}
+
+trait MyTrait {
+    const IMPL_IS_INHERENT: bool;
+    const IMPL_IS_ON_TRAIT: bool;
+}
+
+impl MyTrait for MyType {
+    const IMPL_IS_INHERENT: bool = false;
+    const IMPL_IS_ON_TRAIT: bool = true;
+}
+
+fn main() {
+    // Check that the inherent impl is used before the trait, but that the trait
+    // can still be accessed.
+    assert!(<MyType>::IMPL_IS_INHERENT);
+    assert!(!<MyType as MyTrait>::IMPL_IS_INHERENT);
+    assert!(<MyType>::IMPL_IS_ON_TRAIT);
+}
diff --git a/src/test/run-pass/associated-const-self-type.rs b/src/test/run-pass/associated-const-self-type.rs
new file mode 100644 (file)
index 0000000..d3add97
--- /dev/null
@@ -0,0 +1,23 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(associated_consts)]
+
+trait MyInt {
+    const ONE: Self;
+}
+
+impl MyInt for i32 {
+    const ONE: i32 = 1;
+}
+
+fn main() {
+    assert_eq!(1, <i32>::ONE);
+}
diff --git a/src/test/run-pass/associated-const-ufcs-infer-trait.rs b/src/test/run-pass/associated-const-ufcs-infer-trait.rs
new file mode 100644 (file)
index 0000000..aa3e14a
--- /dev/null
@@ -0,0 +1,23 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(associated_consts)]
+
+trait Foo {
+    const ID: i32;
+}
+
+impl Foo for i32 {
+    const ID: i32 = 1;
+}
+
+fn main() {
+    assert_eq!(1, <i32>::ID);
+}
diff --git a/src/test/run-pass/associated-const-use-default.rs b/src/test/run-pass/associated-const-use-default.rs
new file mode 100644 (file)
index 0000000..5813d86
--- /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.
+
+#![feature(associated_consts)]
+
+trait Foo {
+    const ID: i32 = 1;
+}
+
+impl Foo for i32 {}
+
+fn main() {
+    assert_eq!(1, <i32 as Foo>::ID);
+}
diff --git a/src/test/run-pass/associated-const-use-impl-of-same-trait.rs b/src/test/run-pass/associated-const-use-impl-of-same-trait.rs
new file mode 100644 (file)
index 0000000..6265847
--- /dev/null
@@ -0,0 +1,35 @@
+// 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.
+
+#![feature(associated_consts)]
+
+// The main purpose of this test is to ensure that different impls of the same
+// trait can refer to each other without setting off the static recursion check
+// (as long as there's no actual recursion).
+
+trait Foo {
+    const BAR: u32;
+}
+
+struct IsFoo1;
+
+impl Foo for IsFoo1 {
+    const BAR: u32 = 1;
+}
+
+struct IsFoo2;
+
+impl Foo for IsFoo2 {
+    const BAR: u32 = <IsFoo1 as Foo>::BAR;
+}
+
+fn main() {
+    assert_eq!(<IsFoo1>::BAR, <IsFoo2 as Foo>::BAR);
+}
diff --git a/src/test/run-pass/associated-const.rs b/src/test/run-pass/associated-const.rs
new file mode 100644 (file)
index 0000000..d906544
--- /dev/null
@@ -0,0 +1,23 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(associated_consts)]
+
+trait Foo {
+    const ID: i32;
+}
+
+impl Foo for i32 {
+    const ID: i32 = 1;
+}
+
+fn main() {
+    assert_eq!(1, <i32 as Foo>::ID);
+}
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 79a530785452ac58c1bfa1d0f8694a452aae9594..66201ff901f309ce702e706b0e312be280919d48 100644 (file)
@@ -11,6 +11,7 @@
 // aux-build:issue-12133-rlib.rs
 // aux-build:issue-12133-dylib.rs
 // aux-build:issue-12133-dylib2.rs
+// ignore-musl
 
 // pretty-expanded FIXME #23616
 
index 4f084d7891f37fe37dbee576ccfff022e032425b..a1ada18984e9e7eb95b01752bfde5bdb3868d6bb 100644 (file)
@@ -8,9 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-
-#![feature(unsafe_destructor)]
-
 static mut DROP_RAN: bool = false;
 
 trait Bar {
@@ -26,7 +23,6 @@ fn do_something(&mut self) {}
 
 struct Foo<B: Bar>(B);
 
-#[unsafe_destructor]
 impl<B: Bar> Drop for Foo<B> {
     fn drop(&mut self) {
         unsafe {
index e544585745de3dfc21839f252614879bc2e19d44..0c208773884d4841d57237eadd2c9bc01a1c79a5 100644 (file)
@@ -10,7 +10,7 @@
 
 // pretty-expanded FIXME #23616
 
-#![feature(unsafe_destructor, rustc_private)]
+#![feature(rustc_private)]
 
 extern crate serialize;
 
@@ -22,7 +22,6 @@ struct Foo<T: Encodable> {
     v: T,
 }
 
-#[unsafe_destructor]
 impl<T: Encodable> Drop for Foo<T> {
     fn drop(&mut self) {
         json::encode(&self.v);
index fcb0462766291073da2f2de7c2fe787e56f0ca70..975557726ce8b2a7be680c2b7a3eccbe951aba4f 100644 (file)
@@ -10,8 +10,6 @@
 
 // ignore-pretty
 
-#![feature(unsafe_destructor)]
-
 use std::rc::Rc;
 use std::cell::Cell;
 
@@ -29,7 +27,6 @@ fn new(number: usize, state: Rc<Cell<usize>>) -> Field {
     }
 }
 
-#[unsafe_destructor] // because Field isn't Send
 impl Drop for Field {
     fn drop(&mut self) {
         println!("Dropping field {}", self.number);
@@ -50,7 +47,6 @@ struct HasDropImpl {
     _three: Field
 }
 
-#[unsafe_destructor] // because HasDropImpl isn't Send
 impl Drop for HasDropImpl {
     fn drop(&mut self) {
         println!("HasDropImpl.drop()");
index 6a8f7d992a2929ef732bc2f9c0c4d7e89b1dc8ba..e713bbf127d8c05438607c2ce1af0e6366564624 100644 (file)
@@ -8,14 +8,10 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-
-#![feature(unsafe_destructor)]
-
 struct Leak<'a> {
     dropped: &'a mut bool
 }
 
-#[unsafe_destructor]
 impl<'a> Drop for Leak<'a> {
     fn drop(&mut self) {
         *self.dropped = true;
diff --git a/src/test/run-pass/issue-23611-enum-swap-in-drop.rs b/src/test/run-pass/issue-23611-enum-swap-in-drop.rs
new file mode 100644 (file)
index 0000000..540cbd5
--- /dev/null
@@ -0,0 +1,265 @@
+// 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.
+
+// Issue 23611: this test is ensuring that, for an instance `X` of the
+// enum `E`, if you swap in a different variant during the execution
+// of the `<E as Drop>::drop`, then the appropriate substructure will
+// be torn down after the `<E as Drop>::drop` method returns.
+
+use std::cell::RefCell;
+use std::mem;
+
+use self::d::D;
+
+pub fn main() {
+    let log = RefCell::new(vec![]);
+    d::println(&format!("created empty log"));
+    test(&log);
+
+    // println!("log: {:?}", &log.borrow()[..]);
+    assert_eq!(
+        &log.borrow()[..],
+        [
+            //                                         created empty log
+            // +-- Make D(test_1, 10000000)
+            // | +-- Make D(g_b_5, 50000001)
+            // | |                                     in g_B(b2b0) from E::drop, b=b4b0
+            // | +-- Drop D(g_b_5, 50000001)
+            50000001,
+            // |
+            // | +-- Make D(drop_6, 60000002)
+            // | | +-- Make D(g_b_5, 50000003)
+            // | | |                                   in g_B(b2b0) from E::drop, b=b4b1
+            // | | +-- Drop D(g_b_5, 50000003)
+            50000003,
+            // | |
+            // | | +-- Make D(GaspB::drop_3, 30000004)
+            // | | | +-- Make D(g_b_5, 50000005)
+            // | | | |                                 in g_B(b4b2) from GaspB::drop
+            // | | | +-- Drop D(g_b_5, 50000005)
+            50000005,
+            // | | |
+            // | | +-- Drop D(GaspB::drop_3, 30000004)
+            30000004,
+            // | |
+            // +-- Drop D(test_1, 10000000)
+            10000000,
+            //   |
+            // +-- Make D(GaspA::drop_2, 20000006)
+            // | | +-- Make D(f_a_4, 40000007)
+            // | | |                                   in f_A(a3a0) from GaspA::drop
+            // | | +-- Drop D(f_a_4, 40000007)
+            40000007,
+            // | |
+            // +-- Drop D(GaspA::drop_2, 20000006)
+            20000006,
+            //   |
+            //   +-- Drop D(drop_6, 60000002)
+            60000002
+            //
+                ]);
+
+    // For reference purposes, the old (incorrect) behavior would produce the following
+    // output, which you can compare to the above:
+    //
+    //                                             created empty log
+    // +-- Make D(test_1, 10000000)
+    // | +-- Make D(g_b_5, 50000001)
+    // | |                                     in g_B(b2b0) from E::drop, b=b4b0
+    // | +-- Drop D(g_b_5, 50000001)
+    // |
+    // | +-- Make D(drop_6, 60000002)
+    // | | +-- Make D(g_b_5, 50000003)
+    // | | |                                   in g_B(b2b0) from E::drop, b=b4b1
+    // | | +-- Drop D(g_b_5, 50000003)
+    // | |
+    // | | +-- Make D(GaspB::drop_3, 30000004)
+    // | | | +-- Make D(g_b_5, 50000005)
+    // | | | |                                 in g_B(b4b2) from GaspB::drop
+    // | | | +-- Drop D(g_b_5, 50000005)
+    // | | |
+    // | | +-- Drop D(GaspB::drop_3, 30000004)
+    // | |
+    // +-- Drop D(test_1, 10000000)
+    //   |
+    // +-- Make D(GaspB::drop_3, 30000006)
+    // | | +-- Make D(f_a_4, 40000007)
+    // | | |                                   in f_A(a3a0) from GaspB::drop
+    // | | +-- Drop D(f_a_4, 40000007)
+    // | |
+    // +-- Drop D(GaspB::drop_3, 30000006)
+    //   |
+    //   +-- Drop D(drop_6, 60000002)
+
+    // Note that this calls f_A from GaspB::drop (and thus creates a D
+    // with a uid incorporating the origin of GaspB's drop that
+    // surrounds the f_A invocation), but the code as written only
+    // ever hands f_A off to instances of GaspA, and thus one should
+    // be able to prove the invariant that f_A is *only* invoked from
+    // from an instance of GaspA (either via the GaspA drop
+    // implementation or the E drop implementaton). Yet the old (bad)
+    // behavior allowed a call to f_A to leak in while we are tearing
+    // down a value of type GaspB.
+}
+
+fn test<'a>(log: d::Log<'a>) {
+    let _e = E::B(GaspB(g_b, 0xB4B0, log, D::new("test", 1, log)), true);
+}
+
+struct GaspA<'a>(for <'b> fn(u32, &'b str, d::Log<'a>), u32, d::Log<'a>, d::D<'a>);
+struct GaspB<'a>(for <'b> fn(u32, &'b str, d::Log<'a>), u32, d::Log<'a>, d::D<'a>);
+
+impl<'a> Drop for GaspA<'a> {
+    fn drop(&mut self) {
+        let _d = d::D::new("GaspA::drop", 2, self.2);
+        (self.0)(self.1, "GaspA::drop", self.2);
+    }
+}
+
+impl<'a> Drop for GaspB<'a> {
+    fn drop(&mut self) {
+        let _d = d::D::new("GaspB::drop", 3, self.2);
+        (self.0)(self.1, "GaspB::drop", self.2);
+    }
+}
+
+enum E<'a> {
+    A(GaspA<'a>, bool), B(GaspB<'a>, bool),
+}
+
+fn f_a(x: u32, ctxt: &str, log: d::Log) {
+    let _d = d::D::new("f_a", 4, log);
+    d::println(&format!("in f_A({:x}) from {}", x, ctxt));
+}
+fn g_b(y: u32, ctxt: &str, log: d::Log) {
+    let _d = d::D::new("g_b", 5, log);
+    d::println(&format!("in g_B({:x}) from {}", y, ctxt));
+}
+
+impl<'a> Drop for E<'a> {
+    fn drop(&mut self) {
+        let (do_drop, log) = match *self {
+            E::A(GaspA(ref f, ref mut val_a, log, ref _d_a), ref mut do_drop) => {
+                f(0xA1A0, &format!("E::drop, a={:x}", val_a), log);
+                *val_a += 1;
+                // swap in do_drop := false to avoid infinite dtor regress
+                (mem::replace(do_drop, false), log)
+            }
+            E::B(GaspB(ref g, ref mut val_b, log, ref _d_b), ref mut do_drop) => {
+                g(0xB2B0, &format!("E::drop, b={:x}", val_b), log);
+                *val_b += 1;
+                // swap in do_drop := false to avoid infinite dtor regress
+                (mem::replace(do_drop, false), log)
+            }
+        };
+
+        if do_drop {
+            mem::replace(self, E::A(GaspA(f_a, 0xA3A0, log, D::new("drop", 6, log)), true));
+        }
+    }
+}
+
+// This module provides simultaneous printouts of the dynamic extents
+// of all of the D values, in addition to logging the order that each
+// is dropped.
+//
+// This code is similar to a support code module embedded within
+// test/run-pass/issue-123338-ensure-param-drop-order.rs; however,
+// that (slightly simpler) code only identifies objects in the log via
+// (creation) time-stamps; this incorporates both timestamping and the
+// point of origin within the source code into the unique ID (uid).
+
+const PREF_INDENT: u32 = 20;
+
+pub mod d {
+    #![allow(unused_parens)]
+    use std::fmt;
+    use std::mem;
+    use std::cell::RefCell;
+
+    static mut counter: u16 = 0;
+    static mut trails: u64 = 0;
+
+    pub type Log<'a> = &'a RefCell<Vec<u32>>;
+
+    pub fn current_width() -> u32 {
+        unsafe { max_width() - trails.leading_zeros() }
+    }
+
+    pub fn max_width() -> u32 {
+        unsafe {
+            (mem::size_of_val(&trails)*8) as u32
+        }
+    }
+
+    pub fn indent_println(my_trails: u32, s: &str) {
+        let mut indent: String = String::new();
+        for i in 0..my_trails {
+            unsafe {
+                if trails & (1 << i) != 0 {
+                    indent = indent + "| ";
+                } else {
+                    indent = indent + "  ";
+                }
+            }
+        }
+        println!("{}{}", indent, s);
+    }
+
+    pub fn println(s: &str) {
+        indent_println(super::PREF_INDENT, s);
+    }
+
+    fn first_avail() -> u32 {
+        unsafe {
+            for i in 0..64 {
+                if trails & (1 << i) == 0 {
+                    return i;
+                }
+            }
+        }
+        panic!("exhausted trails");
+    }
+
+    pub struct D<'a> {
+        name: &'static str, i: u8, uid: u32, trail: u32, log: Log<'a>
+    }
+
+    impl<'a> fmt::Display for D<'a> {
+        fn fmt(&self, w: &mut fmt::Formatter) -> fmt::Result {
+            write!(w, "D({}_{}, {})", self.name, self.i, self.uid)
+        }
+    }
+
+    impl<'a> D<'a> {
+        pub fn new(name: &'static str, i: u8, log: Log<'a>) -> D<'a> {
+            unsafe {
+                let trail = first_avail();
+                let ctr = ((i as u32) * 10_000_000) + (counter as u32);
+                counter += 1;
+                trails |= (1 << trail);
+                let ret = D {
+                    name: name, i: i, log: log, uid: ctr, trail: trail
+                };
+                indent_println(trail, &format!("+-- Make {}", ret));
+                ret
+            }
+        }
+    }
+
+    impl<'a> Drop for D<'a> {
+        fn drop(&mut self) {
+            unsafe { trails &= !(1 << self.trail); };
+            self.log.borrow_mut().push(self.uid);
+            indent_println(self.trail, &format!("+-- Drop {}", self));
+            indent_println(::PREF_INDENT, "");
+        }
+    }
+}
diff --git a/src/test/run-pass/issue-24313.rs b/src/test/run-pass/issue-24313.rs
new file mode 100644 (file)
index 0000000..9acfb04
--- /dev/null
@@ -0,0 +1,39 @@
+// 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::thread;
+use std::env;
+use std::process::Command;
+
+struct Handle(i32);
+
+impl Drop for Handle {
+    fn drop(&mut self) { panic!(); }
+}
+
+thread_local!(static HANDLE: Handle = Handle(0));
+
+fn main() {
+    let args = env::args().collect::<Vec<_>>();
+    if args.len() == 1 {
+        let out = Command::new(&args[0]).arg("test").output().unwrap();
+        let stderr = std::str::from_utf8(&out.stderr).unwrap();
+        assert!(stderr.contains("panicked at 'explicit panic'"),
+                "bad failure message:\n{}\n", stderr);
+    } else {
+        // TLS dtors are not always run on process exit
+        thread::spawn(|| {
+            HANDLE.with(|h| {
+                println!("{}", h.0);
+            });
+        }).join().unwrap();
+    }
+}
+
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);