]> git.lizzy.rs Git - rust.git/commitdiff
Auto merge of #22839 - lifthrasiir:better-backtrace, r=alexcrichton
authorbors <bors@rust-lang.org>
Sat, 28 Feb 2015 08:30:19 +0000 (08:30 +0000)
committerbors <bors@rust-lang.org>
Sat, 28 Feb 2015 08:30:19 +0000 (08:30 +0000)
Fixes #20978 for supported platforms (i.e. non-Android POSIX).

This uses `backtrace_pcinfo` to inspect the DWARF debug info and list the file and line pairs for given stack frame. Such pair is not unique due to the presence of inlined functions and the updated routine correctly handles this case. The code is modelled after libbacktrace's `backtrace_full` routine.

There is one known issue with this approach. Macros, when invoked, take over the current frame and shadows the file and line pair which has invoked a macro. In particular, this makes many panicking
macros a bit harder to inspect. This really is a debuginfo problem, and the backtrace routine should print them correctly with a correct debuginfo.

Some example trace:

```
thread '<main>' panicked at 'explicit panic', /home/arachneng/Works/git/rust/src/test/run-pass/backtrace-debuginfo.rs:74
stack backtrace:
   1:         0xd964702f - sys::backtrace::write::h32d93fffb64131b2yxC
   2:         0xd9670202 - panicking::on_panic::h3a4fcb37b873aefeooM
   3:         0xd95b396a - rt::unwind::begin_unwind_inner::h576b3df5f626902dJ2L
   4:         0xd9eb88df - rt::unwind::begin_unwind::h16852273847167740350
   5:         0xd9eb8afb - aux::callback::h15056955655605709172
                        at /home/arachneng/Works/git/rust/<std macros>:3
                        at src/test/run-pass/backtrace-debuginfo-aux.rs:15
   6:         0xd9eb8caa - outer::h2cf96412459fceb6ema
                        at src/test/run-pass/backtrace-debuginfo.rs:73
                        at src/test/run-pass/backtrace-debuginfo.rs:88
   7:         0xd9ebab24 - main::h3f701287441442edasa
                        at src/test/run-pass/backtrace-debuginfo.rs:134
   8:         0xd96daba8 - rust_try_inner
   9:         0xd96dab95 - rust_try
  10:         0xd9671af4 - rt::lang_start::h7da0de9529b4c394liM
  11:         0xd8f3aec4 - __libc_start_main
  12:         0xd9eb8148 - <unknown>
  13:         0xffffffff - <unknown>
```

322 files changed:
mk/crates.mk
mk/tests.mk
src/doc/index.md
src/doc/reference.md
src/doc/trpl/advanced-macros.md
src/doc/trpl/error-handling.md
src/doc/trpl/hello-cargo.md
src/doc/trpl/macros.md
src/doc/trpl/plugins.md
src/etc/htmldocck.py
src/liballoc/arc.rs
src/liballoc/heap.rs
src/liballoc/lib.rs
src/libcollections/binary_heap.rs
src/libcollections/bit.rs
src/libcollections/btree/map.rs
src/libcollections/btree/node.rs
src/libcollections/btree/set.rs
src/libcollections/enum_set.rs
src/libcollections/lib.rs
src/libcollections/linked_list.rs
src/libcollections/macros.rs
src/libcollections/slice.rs
src/libcollections/str.rs
src/libcollections/string.rs
src/libcollections/vec.rs
src/libcollections/vec_deque.rs
src/libcollections/vec_map.rs
src/libcore/fmt/mod.rs
src/libcore/fmt/rt/v1.rs
src/libcore/intrinsics.rs
src/libcore/iter.rs
src/libcore/macros.rs
src/libcore/marker.rs
src/libcore/mem.rs
src/libcore/num/mod.rs
src/libcore/option.rs
src/libcore/panicking.rs
src/libcore/ptr.rs
src/libcore/result.rs
src/libcore/slice.rs
src/libcore/str/mod.rs
src/libcoretest/iter.rs
src/libcoretest/mem.rs
src/libcoretest/nonzero.rs
src/libcoretest/num/mod.rs
src/libcoretest/ptr.rs
src/libcoretest/result.rs
src/libcoretest/slice.rs
src/libcoretest/str.rs
src/libflate/lib.rs
src/liblibc/lib.rs
src/liblog/macros.rs
src/librand/reseeding.rs
src/librbml/io.rs
src/librustc/lib.rs
src/librustc/lint/builtin.rs
src/librustc/lint/context.rs
src/librustc/lint/mod.rs
src/librustc/metadata/csearch.rs
src/librustc/metadata/decoder.rs
src/librustc/metadata/encoder.rs
src/librustc/metadata/filesearch.rs
src/librustc/metadata/loader.rs
src/librustc/metadata/tydecode.rs
src/librustc/metadata/tyencode.rs
src/librustc/middle/astconv_util.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/effect.rs
src/librustc/middle/expr_use_visitor.rs
src/librustc/middle/infer/combine.rs
src/librustc/middle/infer/error_reporting.rs
src/librustc/middle/infer/region_inference/mod.rs
src/librustc/middle/liveness.rs
src/librustc/middle/mem_categorization.rs
src/librustc/middle/pat_util.rs
src/librustc/middle/privacy.rs
src/librustc/middle/reachable.rs
src/librustc/middle/resolve_lifetime.rs
src/librustc/middle/stability.rs
src/librustc/middle/traits/coherence.rs
src/librustc/middle/traits/mod.rs
src/librustc/middle/traits/select.rs
src/librustc/middle/ty.rs
src/librustc/middle/ty_fold.rs
src/librustc/plugin/load.rs
src/librustc/session/config.rs
src/librustc/session/mod.rs
src/librustc_back/archive.rs
src/librustc_back/fs.rs
src/librustc_back/lib.rs
src/librustc_back/rpath.rs
src/librustc_back/svh.rs
src/librustc_back/target/mod.rs
src/librustc_borrowck/borrowck/mod.rs
src/librustc_driver/driver.rs
src/librustc_driver/lib.rs
src/librustc_driver/test.rs
src/librustc_lint/builtin.rs [new file with mode: 0644]
src/librustc_lint/lib.rs [new file with mode: 0644]
src/librustc_privacy/lib.rs
src/librustc_resolve/build_reduced_graph.rs
src/librustc_resolve/check_unused.rs
src/librustc_resolve/lib.rs
src/librustc_trans/back/lto.rs
src/librustc_trans/save/mod.rs
src/librustc_trans/save/span_utils.rs
src/librustc_trans/trans/_match.rs
src/librustc_trans/trans/callee.rs
src/librustc_trans/trans/cleanup.rs
src/librustc_trans/trans/common.rs
src/librustc_trans/trans/consts.rs
src/librustc_trans/trans/controlflow.rs
src/librustc_trans/trans/datum.rs
src/librustc_trans/trans/debuginfo.rs
src/librustc_trans/trans/expr.rs
src/librustc_trans/trans/glue.rs
src/librustc_trans/trans/intrinsic.rs
src/librustc_trans/trans/meth.rs
src/librustc_trans/trans/tvec.rs
src/librustc_typeck/astconv.rs
src/librustc_typeck/check/_match.rs
src/librustc_typeck/check/method/mod.rs
src/librustc_typeck/check/method/probe.rs
src/librustc_typeck/check/method/suggest.rs
src/librustc_typeck/check/mod.rs
src/librustc_typeck/check/regionck.rs
src/librustc_typeck/check/wf.rs
src/librustc_typeck/coherence/impls.rs
src/librustc_typeck/coherence/mod.rs
src/librustc_typeck/coherence/orphan.rs
src/librustc_typeck/coherence/overlap.rs
src/librustc_typeck/collect.rs
src/librustc_typeck/diagnostics.rs
src/librustc_typeck/lib.rs
src/librustc_typeck/variance.rs
src/librustdoc/clean/inline.rs
src/librustdoc/clean/mod.rs
src/librustdoc/core.rs
src/librustdoc/html/format.rs
src/librustdoc/lib.rs
src/librustdoc/test.rs
src/librustdoc/visit_ast.rs
src/libserialize/json.rs
src/libstd/collections/hash/map.rs
src/libstd/collections/hash/set.rs
src/libstd/collections/hash/table.rs
src/libstd/dynamic_lib.rs
src/libstd/env.rs
src/libstd/fs.rs [deleted file]
src/libstd/fs/mod.rs [new file with mode: 0644]
src/libstd/fs/tempdir.rs [new file with mode: 0644]
src/libstd/io/buffered.rs
src/libstd/io/cursor.rs
src/libstd/lib.rs
src/libstd/net/test.rs
src/libstd/old_io/extensions.rs
src/libstd/old_io/mem.rs
src/libstd/old_io/result.rs
src/libstd/old_io/tempfile.rs
src/libstd/old_io/test.rs
src/libstd/old_io/util.rs
src/libstd/os.rs
src/libstd/path.rs
src/libstd/process.rs
src/libstd/rand/os.rs
src/libstd/sync/condvar.rs
src/libstd/sync/mod.rs
src/libstd/sync/mpsc/mod.rs
src/libstd/sync/mutex.rs
src/libstd/sync/once.rs
src/libstd/sync/poison.rs
src/libstd/sync/rwlock.rs
src/libstd/sync/task_pool.rs
src/libstd/sys/common/net.rs
src/libstd/sys/common/wtf8.rs
src/libstd/sys/unix/backtrace.rs
src/libstd/sys/unix/condvar.rs
src/libstd/sys/unix/ext.rs
src/libstd/sys/unix/fs.rs
src/libstd/sys/unix/fs2.rs
src/libstd/sys/unix/mod.rs
src/libstd/sys/unix/mutex.rs
src/libstd/sys/unix/os.rs
src/libstd/sys/unix/pipe.rs
src/libstd/sys/unix/process.rs
src/libstd/sys/unix/process2.rs
src/libstd/sys/unix/rwlock.rs
src/libstd/sys/unix/tcp.rs
src/libstd/sys/windows/condvar.rs
src/libstd/sys/windows/fs.rs
src/libstd/sys/windows/mod.rs
src/libstd/sys/windows/mutex.rs
src/libstd/sys/windows/net.rs
src/libstd/sys/windows/os.rs
src/libstd/sys/windows/process2.rs
src/libstd/sys/windows/rwlock.rs
src/libstd/sys/windows/tcp.rs
src/libstd/sys/windows/time.rs
src/libstd/sys/windows/tty.rs
src/libstd/thread_local/mod.rs
src/libsyntax/ast.rs
src/libsyntax/ast_util.rs
src/libsyntax/ext/build.rs
src/libsyntax/ext/concat_idents.rs
src/libsyntax/ext/deriving/cmp/eq.rs
src/libsyntax/ext/deriving/cmp/ord.rs
src/libsyntax/ext/deriving/mod.rs
src/libsyntax/ext/deriving/primitive.rs
src/libsyntax/ext/expand.rs
src/libsyntax/ext/mtwt.rs
src/libsyntax/ext/tt/macro_rules.rs
src/libsyntax/feature_gate.rs
src/libsyntax/fold.rs
src/libsyntax/parse/mod.rs
src/libsyntax/parse/parser.rs
src/libsyntax/print/pprust.rs
src/libsyntax/util/small_vector.rs
src/libsyntax/visit.rs
src/libterm/lib.rs
src/libterm/terminfo/parm.rs
src/libterm/terminfo/searcher.rs
src/libtest/lib.rs
src/rustbook/book.rs
src/rustbook/build.rs
src/rustbook/main.rs
src/rustbook/test.rs
src/snapshots.txt
src/test/auxiliary/lint_stability.rs
src/test/auxiliary/lint_stability_fields.rs [new file with mode: 0644]
src/test/auxiliary/static-methods-crate.rs
src/test/bench/task-perf-alloc-unwind.rs
src/test/compile-fail/associated-type-projection-ambig-between-bound-and-where-clause.rs [new file with mode: 0644]
src/test/compile-fail/associated-types-in-ambiguous-context.rs
src/test/compile-fail/bad-mid-path-type-params.rs
src/test/compile-fail/borrowck-fn-in-const-a.rs [new file with mode: 0644]
src/test/compile-fail/borrowck-fn-in-const-b.rs [new file with mode: 0644]
src/test/compile-fail/borrowck-fn-in-const-c.rs [new file with mode: 0644]
src/test/compile-fail/cycle-projection-based-on-where-clause.rs [new file with mode: 0644]
src/test/compile-fail/cycle-trait-supertrait-direct.rs [new file with mode: 0644]
src/test/compile-fail/cycle-trait-supertrait-indirect.rs [new file with mode: 0644]
src/test/compile-fail/extern-with-type-bounds.rs
src/test/compile-fail/generic-impl-less-params-with-defaults.rs
src/test/compile-fail/generic-impl-more-params-with-defaults.rs
src/test/compile-fail/glob-resolve1.rs
src/test/compile-fail/impl-duplicate-methods.rs
src/test/compile-fail/impl-not-adjacent-to-type.rs [deleted file]
src/test/compile-fail/inner-static-type-parameter.rs
src/test/compile-fail/issue-12729.rs [deleted file]
src/test/compile-fail/issue-13641.rs
src/test/compile-fail/issue-14254.rs
src/test/compile-fail/issue-19883.rs
src/test/compile-fail/issue-21202.rs
src/test/compile-fail/issue-2356.rs
src/test/compile-fail/issue-3521-2.rs
src/test/compile-fail/issue-3521.rs
src/test/compile-fail/issue-3668-2.rs
src/test/compile-fail/issue-3668.rs
src/test/compile-fail/issue-3973.rs
src/test/compile-fail/issue-4265.rs
src/test/compile-fail/issue-7607-1.rs
src/test/compile-fail/issue-7607-2.rs [deleted file]
src/test/compile-fail/issue-8767.rs
src/test/compile-fail/lint-stability-fields.rs [new file with mode: 0644]
src/test/compile-fail/lint-stability.rs
src/test/compile-fail/lint-unsafe-code.rs
src/test/compile-fail/method-macro-backtrace.rs
src/test/compile-fail/no-implicit-prelude-nested.rs
src/test/compile-fail/no-implicit-prelude.rs
src/test/compile-fail/resolve-unknown-trait.rs
src/test/compile-fail/trait-impl-2.rs [deleted file]
src/test/compile-fail/trait-impl-for-module.rs
src/test/compile-fail/trait-or-new-type-instead.rs
src/test/compile-fail/ufcs-qpath-missing-params.rs
src/test/compile-fail/unboxed-closure-sugar-nonexistent-trait.rs
src/test/compile-fail/unsafe_no_drop_flag-gate.rs [new file with mode: 0644]
src/test/compile-fail/unused-macro-with-bad-frag-spec.rs [new file with mode: 0644]
src/test/compile-fail/unused-macro-with-follow-violation.rs [new file with mode: 0644]
src/test/compile-fail/use-from-trait.rs
src/test/run-make/issue-19371/foo.rs
src/test/run-make/rustdoc-extern-default-method/Makefile [new file with mode: 0644]
src/test/run-make/rustdoc-extern-default-method/ext.rs [new file with mode: 0644]
src/test/run-make/rustdoc-extern-default-method/lib.rs [new file with mode: 0644]
src/test/run-pass/associated-types-project-from-type-param-via-bound-in-where-clause.rs [new file with mode: 0644]
src/test/run-pass/auto-ref-sliceable.rs
src/test/run-pass/coerce-reborrow-mut-vec-arg.rs
src/test/run-pass/coerce-reborrow-mut-vec-rcvr.rs
src/test/run-pass/const-polymorphic-paths.rs [deleted file]
src/test/run-pass/cycle-generic-bound.rs [new file with mode: 0644]
src/test/run-pass/cycle-trait-type-trait.rs [new file with mode: 0644]
src/test/run-pass/deriving-primitive.rs
src/test/run-pass/env-home-dir.rs
src/test/run-pass/generic-static-methods.rs
src/test/run-pass/impl-inherent-non-conflict.rs [new file with mode: 0644]
src/test/run-pass/impl-inherent-prefer-over-trait.rs [new file with mode: 0644]
src/test/run-pass/impl-not-adjacent-to-type.rs [new file with mode: 0644]
src/test/run-pass/issue-12729.rs [new file with mode: 0644]
src/test/run-pass/issue-15149.rs
src/test/run-pass/issue-16272.rs
src/test/run-pass/issue-17216.rs
src/test/run-pass/issue-20091.rs
src/test/run-pass/issue-21721.rs [new file with mode: 0644]
src/test/run-pass/issue-22536-copy-mustnt-zero.rs [new file with mode: 0644]
src/test/run-pass/issue-3559.rs
src/test/run-pass/issue-7607-2.rs [new file with mode: 0644]
src/test/run-pass/match-with-ret-arm.rs
src/test/run-pass/monad.rs
src/test/run-pass/sepcomp-lib-lto.rs
src/test/run-pass/std-sync-right-kind-impls.rs [new file with mode: 0644]
src/test/run-pass/sync-send-iterators-in-libcollections.rs [new file with mode: 0644]
src/test/run-pass/trait-generic.rs
src/test/run-pass/trait-impl-2.rs [new file with mode: 0644]
src/test/run-pass/traits-issue-22655.rs [new file with mode: 0644]
src/test/run-pass/ufcs-polymorphic-paths.rs [new file with mode: 0644]
src/test/run-pass/unboxed-closures-infer-upvar.rs

index be1965b7edadddd6358ab898816e33828121d57e..13e4d8cdeb824af3b5b831cd30418dc27c6f0eb9 100644 (file)
@@ -54,7 +54,7 @@ TARGET_CRATES := libc std flate arena term \
                  log graphviz core rbml alloc \
                  unicode rustc_bitflags
 RUSTC_CRATES := rustc rustc_typeck rustc_borrowck rustc_resolve rustc_driver \
-                rustc_trans rustc_back rustc_llvm rustc_privacy
+                rustc_trans rustc_back rustc_llvm rustc_privacy rustc_lint
 HOST_CRATES := syntax $(RUSTC_CRATES) rustdoc fmt_macros
 CRATES := $(TARGET_CRATES) $(HOST_CRATES)
 TOOLS := compiletest rustdoc rustc rustbook
@@ -70,7 +70,7 @@ DEPS_graphviz := std
 DEPS_syntax := std term serialize log fmt_macros arena libc
 DEPS_rustc_driver := arena flate getopts graphviz libc rustc rustc_back rustc_borrowck \
                      rustc_typeck rustc_resolve log syntax serialize rustc_llvm \
-                    rustc_trans rustc_privacy
+                    rustc_trans rustc_privacy rustc_lint
 
 DEPS_rustc_trans := arena flate getopts graphviz libc rustc rustc_back \
                        log syntax serialize rustc_llvm
@@ -78,12 +78,13 @@ DEPS_rustc_typeck := rustc syntax
 DEPS_rustc_borrowck := rustc log graphviz syntax
 DEPS_rustc_resolve := rustc log syntax
 DEPS_rustc_privacy := rustc log syntax
+DEPS_rustc_lint := rustc log syntax
 DEPS_rustc := syntax flate arena serialize getopts rbml \
               log graphviz rustc_llvm rustc_back
 DEPS_rustc_llvm := native:rustllvm libc std
 DEPS_rustc_back := std syntax rustc_llvm flate log libc
 DEPS_rustdoc := rustc rustc_driver native:hoedown serialize getopts \
-                test
+                test rustc_lint
 DEPS_rustc_bitflags := core
 DEPS_flate := std native:miniz
 DEPS_arena := std
@@ -128,11 +129,13 @@ DOC_CRATES := $(filter-out rustc, \
               $(filter-out rustc_resolve, \
               $(filter-out rustc_driver, \
               $(filter-out rustc_privacy, \
+              $(filter-out rustc_lint, \
               $(filter-out log, \
               $(filter-out getopts, \
-              $(filter-out syntax, $(CRATES)))))))))))
+              $(filter-out syntax, $(CRATES))))))))))))
 COMPILER_DOC_CRATES := rustc rustc_trans rustc_borrowck rustc_resolve \
-                       rustc_typeck rustc_driver syntax rustc_privacy
+                       rustc_typeck rustc_driver syntax rustc_privacy \
+                       rustc_lint
 
 # This macro creates some simple definitions for each crate being built, just
 # some munging of all of the parameters above.
index 692d28bfad3d56c5e5cba49ea9489b7268bb45b1..ca2d1a45d571f3a0317ebfe6268a6dbb971a115c 100644 (file)
@@ -21,7 +21,7 @@ $(eval $(call RUST_CRATE,coretest))
 
 TEST_TARGET_CRATES = $(filter-out core unicode,$(TARGET_CRATES)) coretest
 TEST_DOC_CRATES = $(DOC_CRATES)
-TEST_HOST_CRATES = $(filter-out rustc_typeck rustc_borrowck rustc_resolve rustc_trans,\
+TEST_HOST_CRATES = $(filter-out rustc_typeck rustc_borrowck rustc_resolve rustc_trans rustc_lint,\
                      $(HOST_CRATES))
 TEST_CRATES = $(TEST_TARGET_CRATES) $(TEST_HOST_CRATES)
 
index a4f79412220189436fb3ad850210a4a28dcf66d1..f6b0a18824a0253327356b9eeb169b2a1e7f3bf2 100644 (file)
@@ -68,7 +68,7 @@ There are questions that are asked quite often, and so we've made FAQs for them:
 * [Language Design FAQ](complement-design-faq.html)
 * [Language FAQ](complement-lang-faq.html)
 * [Project FAQ](complement-project-faq.html)
-* [How to submit a bug report](complement-bugreport.html)
+* [How to submit a bug report](https://github.com/rust-lang/rust/blob/master/CONTRIBUTING.md#bug-reports)
 
 # The standard library
 
index 31524579df7c0c1fef4a509e0e909aa819eb4ef1..87130c08991c02625246014e04d53063b19b6b41 100644 (file)
@@ -302,7 +302,7 @@ nonzero_dec: '1' | '2' | '3' | '4'
 
 A _character literal_ is a single Unicode character enclosed within two
 `U+0027` (single-quote) characters, with the exception of `U+0027` itself,
-which must be _escaped_ by a preceding U+005C character (`\`).
+which must be _escaped_ by a preceding `U+005C` character (`\`).
 
 ##### String literals
 
@@ -311,6 +311,19 @@ A _string literal_ is a sequence of any Unicode characters enclosed within two
 which must be _escaped_ by a preceding `U+005C` character (`\`), or a _raw
 string literal_.
 
+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.
+
+```rust
+let a = "foobar";
+let b = "foo\
+         bar";
+
+assert_eq!(a,b);
+```
+
 ##### Character escapes
 
 Some additional _escapes_ are available in either character or non-raw string
@@ -731,15 +744,20 @@ Rust syntax is restricted in two ways:
    pairs when they occur at the beginning of, or immediately after, a `$(...)*`;
    requiring a distinctive token in front can solve the problem.
 
-## Syntax extensions useful for the macro author
+## Syntax extensions useful in macros
 
-* `log_syntax!` : print out the arguments at compile time
-* `trace_macros!` : supply `true` or `false` to enable or disable macro expansion logging
 * `stringify!` : turn the identifier argument into a string literal
 * `concat!` : concatenates a comma-separated list of literals
-* `concat_idents!` : create a new identifier by concatenating the arguments
 
-The following attributes are used for quasiquoting in procedural macros:
+## Syntax extensions for macro debugging
+
+* `log_syntax!` : print out the arguments at compile time
+* `trace_macros!` : supply `true` or `false` to enable or disable macro expansion logging
+
+## Quasiquoting
+
+The following syntax extensions are used for quasiquoting Rust syntax trees,
+usually in [procedural macros](book/plugins.html#syntax-extensions):
 
 * `quote_expr!`
 * `quote_item!`
@@ -748,6 +766,8 @@ The following attributes are used for quasiquoting in procedural macros:
 * `quote_tokens!`
 * `quote_ty!`
 
+Documentation is very limited at the moment.
+
 # Crates and source files
 
 Rust is a *compiled* language. Its semantics obey a *phase distinction*
index aff365051a4eadfc67819f0e9c45487abd1b70ad..a226e4d0bf911ac97b57c420129c3ff515bb53aa 100644 (file)
@@ -192,19 +192,58 @@ To keep this system simple and correct, `#[macro_use] extern crate ...` may
 only appear at the root of your crate, not inside `mod`. This ensures that
 `$crate` is a single identifier.
 
-# A final note
+# The deep end
 
-Macros, as currently implemented, are not for the faint of heart. Even
-ordinary syntax errors can be more difficult to debug when they occur inside a
-macro, and errors caused by parse problems in generated code can be very
-tricky. Invoking the `log_syntax!` macro can help elucidate intermediate
-states, invoking `trace_macros!(true)` will automatically print those
-intermediate states out, and passing the flag `--pretty expanded` as a
-command-line argument to the compiler will show the result of expansion.
+The introductory chapter mentioned recursive macros, but it did not give the
+full story. Recursive macros are useful for another reason: Each recursive
+invocation gives you another opportunity to pattern-match the macro's
+arguments.
+
+As an extreme example, it is possible, though hardly advisable, to implement
+the [Bitwise Cyclic Tag](http://esolangs.org/wiki/Bitwise_Cyclic_Tag) automaton
+within Rust's macro system.
+
+```rust
+#![feature(trace_macros)]
+
+macro_rules! bct {
+    // cmd 0:  d ... => ...
+    (0, $($ps:tt),* ; $_d:tt)
+        => (bct!($($ps),*, 0 ; ));
+    (0, $($ps:tt),* ; $_d:tt, $($ds:tt),*)
+        => (bct!($($ps),*, 0 ; $($ds),*));
+
+    // cmd 1p:  1 ... => 1 ... p
+    (1, $p:tt, $($ps:tt),* ; 1)
+        => (bct!($($ps),*, 1, $p ; 1, $p));
+    (1, $p:tt, $($ps:tt),* ; 1, $($ds:tt),*)
+        => (bct!($($ps),*, 1, $p ; 1, $($ds),*, $p));
+
+    // cmd 1p:  0 ... => 0 ...
+    (1, $p:tt, $($ps:tt),* ; $($ds:tt),*)
+        => (bct!($($ps),*, 1, $p ; $($ds),*));
+
+    // halt on empty data string
+    ( $($ps:tt),* ; )
+        => (());
+}
+
+fn main() {
+    trace_macros!(true);
+# /* just check the definition
+    bct!(0, 0, 1, 1, 1 ; 1, 0, 1);
+# */
+}
+```
+
+Exercise: use macros to reduce duplication in the above definition of the
+`bct!` macro.
+
+# Procedural macros
 
 If Rust's macro system can't do what you need, you may want to write a
 [compiler plugin](plugins.html) instead. Compared to `macro_rules!`
 macros, this is significantly more work, the interfaces are much less stable,
-and the warnings about debugging apply ten-fold. In exchange you get the
+and bugs can be much harder to track down. In exchange you get the
 flexibility of running arbitrary Rust code within the compiler. Syntax
 extension plugins are sometimes called *procedural macros* for this reason.
index 68b36e7a4b7ca225573b1accd19cf31c2534cc91..cf60bd88c542be85ff5f6c90d20c5cd599a9827d 100644 (file)
@@ -223,6 +223,78 @@ let input = io::stdin().read_line()
                        .ok()
                        .expect("Failed to read line");
 ```
+
 `ok()` converts the `IoResult` into an `Option`, and `expect()` does the same
 thing as `unwrap()`, but takes a message. This message is passed along to the
 underlying `panic!`, providing a better error message if the code errors.
+
+# Using `try!`
+
+When writing code that calls many functions that return the `Result` type, the
+error handling can be tedious. The `try!` macro hides some of the boilerplate
+of propagating errors up the call stack.
+
+It replaces this:
+
+```rust
+use std::fs::File;
+use std::io;
+use std::io::prelude::*;
+
+struct Info {
+    name: String,
+    age: i32,
+    rating: i32,
+}
+
+fn write_info(info: &Info) -> io::Result<()> {
+    let mut file = File::open("my_best_friends.txt").unwrap();
+
+    if let Err(e) = writeln!(&mut file, "name: {}", info.name) {
+        return Err(e)
+    }
+    if let Err(e) = writeln!(&mut file, "age: {}", info.age) {
+        return Err(e)
+    }
+    if let Err(e) = writeln!(&mut file, "rating: {}", info.rating) {
+        return Err(e)
+    }
+
+    return Ok(());
+}
+```
+
+With this:
+
+```rust
+use std::fs::File;
+use std::io;
+use std::io::prelude::*;
+
+struct Info {
+    name: String,
+    age: i32,
+    rating: i32,
+}
+
+fn write_info(info: &Info) -> io::Result<()> {
+    let mut file = try!(File::open("my_best_friends.txt"));
+
+    try!(writeln!(&mut file, "name: {}", info.name));
+    try!(writeln!(&mut file, "age: {}", info.age));
+    try!(writeln!(&mut file, "rating: {}", info.rating));
+
+    return Ok(());
+}
+```
+
+Wrapping an expression in `try!` will result in the unwrapped success (`Ok`)
+value, unless the result is `Err`, in which case `Err` is returned early from
+the enclosing function.
+
+It's worth noting that you can only use `try!` from a function that returns a
+`Result`, which means that you cannot use `try!` inside of `main()`, because
+`main()` doesn't return anything.
+
+`try!` makes use of [`FromError`](../std/error/#the-fromerror-trait) to determine
+what to return in the error case.
index 5eb6cd7c5cd3ae4667d6c54d322bb176ed35037f..587da69d4a6f7a0fc8c8fb6c5d16cb9606ac31e4 100644 (file)
@@ -18,13 +18,15 @@ the Cargo
 README](https://github.com/rust-lang/cargo#installing-cargo-from-nightlies)
 for specific instructions about installing it.
 
+## Converting to Cargo
+
 Let's convert Hello World to Cargo.
 
 To Cargo-ify our project, we need to do two things: Make a `Cargo.toml`
 configuration file, and put our source file in the right place. Let's
 do that part first:
 
-```{bash}
+```bash
 $ mkdir src
 $ mv main.rs src/main.rs
 ```
@@ -36,7 +38,7 @@ place for everything, and everything in its place.
 
 Next, our configuration file:
 
-```{bash}
+```bash
 $ editor Cargo.toml
 ```
 
@@ -73,7 +75,7 @@ well as what it is named.
 
 Once you have this file in place, we should be ready to build! Try this:
 
-```{bash}
+```bash
 $ cargo build
    Compiling hello_world v0.0.1 (file:///home/yourname/projects/hello_world)
 $ ./target/hello_world
@@ -103,6 +105,62 @@ That's it! We've successfully built `hello_world` with Cargo. Even though our
 program is simple, it's using much of the real tooling that you'll use for the
 rest of your Rust career.
 
+## A New Project
+
+You don't have to go through this whole process every time you want to start a new
+project! Cargo has the ability to make a bare-bones project directory in which you
+can start developing right away.
+
+To start a new project with Cargo, use `cargo new`:
+
+```bash
+$ cargo new hello_world --bin
+```
+
+We're passing `--bin` because we're making a binary program: if we
+were making a library, we'd leave it off.
+
+Let's check out what Cargo has generated for us:
+
+```bash
+$ cd hello_world
+$ tree .
+.
+├── Cargo.toml
+└── src
+    └── main.rs
+
+1 directory, 2 files
+```
+
+If you don't have the `tree` command, you can probably get it from your distro's package
+manager. It's not necessary, but it's certainly useful.
+
+This is all we need to get started. First, let's check out `Cargo.toml`:
+
+```toml
+[package]
+
+name = "hello_world"
+version = "0.0.1"
+authors = ["Your Name <you@example.com>"]
+```
+
+Cargo has populated this file with reasonable defaults based off the arguments you gave
+it and your `git` global configuration. You may notice that Cargo has also initialized
+the `hello_world` directory as a `git` repository.
+
+Here's what's in `src/main.rs`:
+
+```rust
+fn main() {
+    println!("Hello, world!");
+}
+```
+
+Cargo has generated a "Hello World!" for us, and you're ready to start coding! A
+much more in-depth guide to Cargo can be found [here](http://doc.crates.io/guide.html).
+
 Now that you've got the tools down, let's actually learn more about the Rust
 language itself. These are the basics that will serve you well through the rest
-of your time with Rust.
+of your time with Rust.
\ No newline at end of file
index ce6fa3ce949cd7a1f0878ca79bf20358a5127ba1..7da36043f6cf17726a3641bab0381564aeb1ada1 100644 (file)
@@ -73,7 +73,7 @@ macro_rules! vec {
     };
 }
 # fn main() {
-#     assert_eq!(&[1,2,3], &vec![1,2,3]);
+#     assert_eq!([1,2,3], vec![1,2,3]);
 # }
 ```
 
@@ -189,14 +189,12 @@ shorthand for a data type could be valid as either an expression or a pattern.
 
 ## Repetition
 
-The repetition behavior can seem somewhat magical, especially when multiple
-names are bound at multiple nested levels of repetition. The two rules to keep
-in mind are:
+The repetition operator follows two principal rules:
 
-1. the behavior of `$(...)*` is to walk through one "layer" of repetitions, for
-all of the `$name`s it contains, in lockstep, and
+1. `$(...)*` walks through one "layer" of repetitions, for all of the `$name`s
+   it contains, in lockstep, and
 2. each `$name` must be under at least as many `$(...)*`s as it was matched
-against. If it is under more, it'll be duplicated, as appropriate.
+   against. If it is under more, it'll be duplicated, as appropriate.
 
 This baroque macro illustrates the duplication of variables from outer
 repetition levels.
@@ -226,6 +224,10 @@ That's most of the matcher syntax. These examples use `$(...)*`, which is a
 more" match. Both forms optionally include a separator, which can be any token
 except `+` or `*`.
 
+This system is based on
+"[Macro-by-Example](http://www.cs.indiana.edu/ftp/techreports/TR206.pdf)"
+(PDF link).
+
 # Hygiene
 
 Some languages implement macros using simple text substitution, which leads to
@@ -273,19 +275,26 @@ macro, using [a GNU C extension] to emulate Rust's expression blocks.
 })
 ```
 
-This looks reasonable, but watch what happens in this example:
+Here's a simple use case that goes terribly wrong:
 
 ```text
 const char *state = "reticulating splines";
-LOG(state);
+LOG(state)
 ```
 
-The program will likely segfault, after it tries to execute
+This expands to
 
 ```text
-printf("log(%d): %s\n", state, state);
+const char *state = "reticulating splines";
+int state = get_log_state();
+if (state > 0) {
+    printf("log(%d): %s\n", state, state);
+}
 ```
 
+The second variable named `state` shadows the first one.  This is a problem
+because the print statement should refer to both of them.
+
 The equivalent Rust macro has the desired behavior.
 
 ```rust
@@ -357,6 +366,64 @@ fn main() {
 
 [items]: ../reference.html#items
 
+# Recursive macros
+
+A macro's expansion can include more macro invocations, including invocations
+of the very same macro being expanded.  These recursive macros are useful for
+processing tree-structured input, as illustrated by this (simplistic) HTML
+shorthand:
+
+```rust
+# #![allow(unused_must_use)]
+macro_rules! write_html {
+    ($w:expr, ) => (());
+
+    ($w:expr, $e:tt) => (write!($w, "{}", $e));
+
+    ($w:expr, $tag:ident [ $($inner:tt)* ] $($rest:tt)*) => {{
+        write!($w, "<{}>", stringify!($tag));
+        write_html!($w, $($inner)*);
+        write!($w, "</{}>", stringify!($tag));
+        write_html!($w, $($rest)*);
+    }};
+}
+
+fn main() {
+#   // FIXME(#21826)
+    use std::fmt::Write;
+    let mut out = String::new();
+
+    write_html!(&mut out,
+        html[
+            head[title["Macros guide"]]
+            body[h1["Macros are the best!"]]
+        ]);
+
+    assert_eq!(out,
+        "<html><head><title>Macros guide</title></head>\
+         <body><h1>Macros are the best!</h1></body></html>");
+}
+```
+
+# Debugging macro code
+
+To see the results of expanding macros, run `rustc --pretty expanded`. The
+output represents a whole crate, so you can also feed it back in to `rustc`,
+which will sometimes produce better error messages than the original
+compilation. Note that the `--pretty expanded` output may have a different
+meaning if multiple variables of the same name (but different syntax contexts)
+are in play in the same scope. In this case `--pretty expanded,hygiene` will
+tell you about the syntax contexts.
+
+`rustc` provides two syntax extensions that help with macro debugging. For now,
+they are unstable and require feature gates.
+
+* `log_syntax!(...)` will print its arguments to standard output, at compile
+  time, and "expand" to nothing.
+
+* `trace_macros!(true)` will enable a compiler message every time a macro is
+  expanded. Use `trace_macros!(false)` later in expansion to turn it off.
+
 # Further reading
 
 The [advanced macros chapter][] goes into more detail about macro syntax. It
index 79502f3cd17f755768cabac2c00c36c2f594f03a..f609a0a918aa7628a6dc05372da67c168dd7335f 100644 (file)
@@ -146,14 +146,7 @@ a more involved macro example, see
 
 ## Tips and tricks
 
-To see the results of expanding syntax extensions, run
-`rustc --pretty expanded`. The output represents a whole crate, so you
-can also feed it back in to `rustc`, which will sometimes produce better
-error messages than the original compilation. Note that the
-`--pretty expanded` output may have a different meaning if multiple
-variables of the same name (but different syntax contexts) are in play
-in the same scope. In this case `--pretty expanded,hygiene` will tell
-you about the syntax contexts.
+Some of the [macro debugging tips](macros.html#debugging-macro-code) are applicable.
 
 You can use [`syntax::parse`](../syntax/parse/index.html) to turn token trees into
 higher-level syntax elements like expressions:
@@ -184,6 +177,11 @@ and return
 [`DummyResult`](../syntax/ext/base/struct.DummyResult.html),
 so that the compiler can continue and find further errors.
 
+To print syntax fragments for debugging, you can use
+[`span_note`](../syntax/ext/base/struct.ExtCtxt.html#method.span_note) together
+with
+[`syntax::print::pprust::*_to_string`](http://doc.rust-lang.org/syntax/print/pprust/index.html#functions).
+
 The example above produced an integer literal using
 [`AstBuilder::expr_uint`](../syntax/ext/build/trait.AstBuilder.html#tymethod.expr_uint).
 As an alternative to the `AstBuilder` trait, `libsyntax` provides a set of
index 22792ff76355149b4ee8eb006fba37618b094caf..a212e3a04357eccc564097ab90b203d1afc38a8f 100644 (file)
@@ -96,6 +96,9 @@ There are a number of supported commands:
   highlights for example. If you want to simply check the presence of
   given node or attribute, use an empty string (`""`) as a `PATTERN`.
 
+* `@count PATH XPATH COUNT' checks for the occurrence of given XPath
+  in the given file. The number of occurrences must match the given count.
+
 All conditions can be negated with `!`. `@!has foo/type.NoSuch.html`
 checks if the given file does not exist, for example.
 
@@ -333,6 +336,11 @@ def check_tree_text(tree, path, pat, regexp):
     return ret
 
 
+def check_tree_count(tree, path, count):
+    path = normalize_xpath(path)
+    return len(tree.findall(path)) == count
+
+
 def check(target, commands):
     cache = CachedFiles(target)
     for c in commands:
@@ -360,6 +368,13 @@ def check(target, commands):
                 raise RuntimeError('Invalid number of @{} arguments \
                                     at line {}'.format(c.cmd, c.lineno))
 
+        elif c.cmd == 'count': # count test
+            if len(c.args) == 3: # @count <path> <pat> <count> = count test
+                ret = check_tree_count(cache.get_tree(c.args[0]), c.args[1], int(c.args[2]))
+            else:
+                raise RuntimeError('Invalid number of @{} arguments \
+                                    at line {}'.format(c.cmd, c.lineno))
+
         elif c.cmd == 'valid-html':
             raise RuntimeError('Unimplemented @valid-html at line {}'.format(c.lineno))
 
index cc49164ef91b349f78e716bf3b7c6962392ad9c8..88a3752c88a1d6774b8b288a2a12f2af0e566e61 100644 (file)
@@ -139,6 +139,13 @@ pub struct Weak<T> {
 unsafe impl<T: Sync + Send> Send for Weak<T> { }
 unsafe impl<T: Sync + Send> Sync for Weak<T> { }
 
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<T: fmt::Debug> fmt::Debug for Weak<T> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        write!(f, "(Weak)")
+    }
+}
+
 struct ArcInner<T> {
     strong: atomic::AtomicUsize,
     weak: atomic::AtomicUsize,
index d3d86270d1e9fdea6a4bb02149f6cfbc2a554c0a..726d5c8a23b739c179c22701b9628a4a450ae11a 100644 (file)
@@ -300,7 +300,7 @@ pub unsafe fn reallocate(ptr: *mut u8, old_size: usize, size: usize, align: usiz
             libc::realloc(ptr as *mut libc::c_void, size as libc::size_t) as *mut u8
         } else {
             let new_ptr = allocate(size, align);
-            ptr::copy_memory(new_ptr, ptr, cmp::min(size, old_size));
+            ptr::copy(new_ptr, ptr, cmp::min(size, old_size));
             deallocate(ptr, old_size, align);
             new_ptr
         }
index 0cdc71b6f604f68bf88e988af72988a9aa8c9ca9..82bd13475c74eabb6f106112edd5434c7411cc70 100644 (file)
@@ -73,6 +73,7 @@
 #![feature(unboxed_closures)]
 #![feature(unsafe_no_drop_flag)]
 #![feature(core)]
+#![feature(unique)]
 #![cfg_attr(test, feature(test, alloc, rustc_private))]
 #![cfg_attr(all(not(feature = "external_funcs"), not(feature = "external_crate")),
             feature(libc))]
index 9f549fd7237711dce941f7ef0d37e0eec9e8db73..36c76dbad14aefcb20076f4d9c63613aa80fe221 100644 (file)
@@ -480,7 +480,7 @@ pub fn into_vec(self) -> Vec<T> { self.data }
     /// heap.push(3);
     ///
     /// let vec = heap.into_sorted_vec();
-    /// assert_eq!(vec, vec![1, 2, 3, 4, 5, 6, 7]);
+    /// assert_eq!(vec, [1, 2, 3, 4, 5, 6, 7]);
     /// ```
     pub fn into_sorted_vec(mut self) -> Vec<T> {
         let mut end = self.len();
index f28f9976f0c5dae9373c54a806522a63bff58a26..5b19de42ac919240167e67892b48ba519dd55b63 100644 (file)
@@ -640,13 +640,13 @@ pub fn any(&self) -> bool {
     /// let mut bv = BitVec::from_elem(3, true);
     /// bv.set(1, false);
     ///
-    /// assert_eq!(bv.to_bytes(), vec!(0b10100000));
+    /// assert_eq!(bv.to_bytes(), [0b10100000]);
     ///
     /// let mut bv = BitVec::from_elem(9, false);
     /// bv.set(2, true);
     /// bv.set(8, true);
     ///
-    /// assert_eq!(bv.to_bytes(), vec!(0b00100000, 0b10000000));
+    /// assert_eq!(bv.to_bytes(), [0b00100000, 0b10000000]);
     /// ```
     pub fn to_bytes(&self) -> Vec<u8> {
         fn bit(bit_vec: &BitVec, byte: usize, bit: usize) -> u8 {
@@ -806,7 +806,7 @@ pub fn capacity(&self) -> usize {
     /// let mut bv = BitVec::from_bytes(&[0b01001011]);
     /// bv.grow(2, true);
     /// assert_eq!(bv.len(), 10);
-    /// assert_eq!(bv.to_bytes(), vec!(0b01001011, 0b11000000));
+    /// assert_eq!(bv.to_bytes(), [0b01001011, 0b11000000]);
     /// ```
     pub fn grow(&mut self, n: usize, value: bool) {
         // Note: we just bulk set all the bits in the last word in this fn in multiple places
@@ -978,7 +978,7 @@ fn cmp(&self, other: &BitVec) -> Ordering {
 impl fmt::Debug for BitVec {
     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
         for bit in self {
-            try!(write!(fmt, "{}", if bit { 1u32 } else { 0u32 }));
+            try!(write!(fmt, "{}", if bit { 1 } else { 0 }));
         }
         Ok(())
     }
@@ -1752,7 +1752,7 @@ pub fn remove(&mut self, value: &usize) -> bool {
 #[stable(feature = "rust1", since = "1.0.0")]
 impl fmt::Debug for BitSet {
     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
-        try!(write!(fmt, "BitSet {{"));
+        try!(write!(fmt, "{{"));
         let mut first = true;
         for n in self {
             if !first {
@@ -2285,12 +2285,12 @@ fn test_from_bytes() {
     fn test_to_bytes() {
         let mut bv = BitVec::from_elem(3, true);
         bv.set(1, false);
-        assert_eq!(bv.to_bytes(), vec!(0b10100000));
+        assert_eq!(bv.to_bytes(), [0b10100000]);
 
         let mut bv = BitVec::from_elem(9, false);
         bv.set(2, true);
         bv.set(8, true);
-        assert_eq!(bv.to_bytes(), vec!(0b00100000, 0b10000000));
+        assert_eq!(bv.to_bytes(), [0b00100000, 0b10000000]);
     }
 
     #[test]
@@ -2655,7 +2655,7 @@ fn test_bit_set_show() {
         s.insert(10);
         s.insert(50);
         s.insert(2);
-        assert_eq!("BitSet {1, 2, 10, 50}", format!("{:?}", s));
+        assert_eq!("{1, 2, 10, 50}", format!("{:?}", s));
     }
 
     #[test]
@@ -2675,7 +2675,7 @@ fn test_bit_set_iterator() {
         let bit_vec: BitSet = usizes.into_iter().collect();
 
         let idxs: Vec<_> = bit_vec.iter().collect();
-        assert_eq!(idxs, vec![0, 2, 3]);
+        assert_eq!(idxs, [0, 2, 3]);
 
         let long: BitSet = (0..10000).filter(|&n| n % 2 == 0).collect();
         let real: Vec<_> = range_step(0, 10000, 2).collect();
index 1b456eec830b14d84015d392cd8cc397ea6c40ee..8a3a1fcb9f387a8bc060a4f29eb0983a2ae9372c 100644 (file)
@@ -347,7 +347,7 @@ pub fn insert(&mut self, mut key: K, mut value: V) -> Option<V> {
             let result = stack.with(move |pusher, node| {
                 // Same basic logic as found in `find`, but with PartialSearchStack mediating the
                 // actual nodes for us
-                return match Node::search(node, &key) {
+                match Node::search(node, &key) {
                     Found(mut handle) => {
                         // Perfect match, swap the values and return the old one
                         mem::swap(handle.val_mut(), &mut value);
@@ -372,7 +372,7 @@ pub fn insert(&mut self, mut key: K, mut value: V) -> Option<V> {
                 }
             });
             match result {
-                Finished(ret) => { return ret; },
+                Finished(ret) => return ret,
                 Continue((new_stack, renewed_key, renewed_val)) => {
                     stack = new_stack;
                     key = renewed_key;
@@ -439,7 +439,7 @@ pub fn remove<Q: ?Sized>(&mut self, key: &Q) -> Option<V> where K: Borrow<Q>, Q:
         let mut stack = stack::PartialSearchStack::new(self);
         loop {
             let result = stack.with(move |pusher, node| {
-                return match Node::search(node, key) {
+                match Node::search(node, key) {
                     Found(handle) => {
                         // Perfect match. Terminate the stack here, and remove the entry
                         Finished(Some(pusher.seal(handle).remove()))
@@ -899,7 +899,7 @@ fn cmp(&self, other: &BTreeMap<K, V>) -> Ordering {
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<K: Debug, V: Debug> Debug for BTreeMap<K, V> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        try!(write!(f, "BTreeMap {{"));
+        try!(write!(f, "{{"));
 
         for (i, (k, v)) in self.iter().enumerate() {
             if i != 0 { try!(write!(f, ", ")); }
@@ -1281,7 +1281,7 @@ pub fn into_iter(self) -> IntoIter<K, V> {
     /// a.insert(2, "b");
     ///
     /// let keys: Vec<usize> = a.keys().cloned().collect();
-    /// assert_eq!(keys, vec![1,2,]);
+    /// assert_eq!(keys, [1, 2]);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn keys<'a>(&'a self) -> Keys<'a, K, V> {
@@ -1303,7 +1303,7 @@ fn first<A, B>((a, _): (A, B)) -> A { a }
     /// a.insert(2, "b");
     ///
     /// let values: Vec<&str> = a.values().cloned().collect();
-    /// assert_eq!(values, vec!["a","b"]);
+    /// assert_eq!(values, ["a", "b"]);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn values<'a>(&'a self) -> Values<'a, K, V> {
@@ -1560,7 +1560,7 @@ pub fn entry(&mut self, mut key: K) -> Entry<K, V> {
         let mut stack = stack::PartialSearchStack::new(self);
         loop {
             let result = stack.with(move |pusher, node| {
-                return match Node::search(node, &key) {
+                match Node::search(node, &key) {
                     Found(handle) => {
                         // Perfect match
                         Finished(Occupied(OccupiedEntry {
index f0fc12da7275e000d814d796db75a0f58c2a48f2..4a80d75575e6db431b400987e05bf0b4c4d9d383 100644 (file)
@@ -1085,7 +1085,7 @@ pub fn into_iter(self) -> MoveTraversal<K, V> {
                     vals: RawItems::from_slice(self.vals()),
                     edges: RawItems::from_slice(self.edges()),
 
-                    ptr: *self.keys as *mut u8,
+                    ptr: Unique::new(*self.keys as *mut u8),
                     capacity: self.capacity(),
                     is_leaf: self.is_leaf()
                 },
@@ -1136,12 +1136,12 @@ unsafe fn push_edge(&mut self, edge: Node<K, V>) {
     // This must be followed by insert_edge on an internal node.
     #[inline]
     unsafe fn insert_kv(&mut self, index: usize, key: K, val: V) -> &mut V {
-        ptr::copy_memory(
+        ptr::copy(
             self.keys_mut().as_mut_ptr().offset(index as isize + 1),
             self.keys().as_ptr().offset(index as isize),
             self.len() - index
         );
-        ptr::copy_memory(
+        ptr::copy(
             self.vals_mut().as_mut_ptr().offset(index as isize + 1),
             self.vals().as_ptr().offset(index as isize),
             self.len() - index
@@ -1158,7 +1158,7 @@ unsafe fn insert_kv(&mut self, index: usize, key: K, val: V) -> &mut V {
     // This can only be called immediately after a call to insert_kv.
     #[inline]
     unsafe fn insert_edge(&mut self, index: usize, edge: Node<K, V>) {
-        ptr::copy_memory(
+        ptr::copy(
             self.edges_mut().as_mut_ptr().offset(index as isize + 1),
             self.edges().as_ptr().offset(index as isize),
             self.len() - index
@@ -1191,12 +1191,12 @@ unsafe fn remove_kv(&mut self, index: usize) -> (K, V) {
         let key = ptr::read(self.keys().get_unchecked(index));
         let val = ptr::read(self.vals().get_unchecked(index));
 
-        ptr::copy_memory(
+        ptr::copy(
             self.keys_mut().as_mut_ptr().offset(index as isize),
             self.keys().as_ptr().offset(index as isize + 1),
             self.len() - index - 1
         );
-        ptr::copy_memory(
+        ptr::copy(
             self.vals_mut().as_mut_ptr().offset(index as isize),
             self.vals().as_ptr().offset(index as isize + 1),
             self.len() - index - 1
@@ -1212,7 +1212,7 @@ unsafe fn remove_kv(&mut self, index: usize) -> (K, V) {
     unsafe fn remove_edge(&mut self, index: usize) -> Node<K, V> {
         let edge = ptr::read(self.edges().get_unchecked(index));
 
-        ptr::copy_memory(
+        ptr::copy(
             self.edges_mut().as_mut_ptr().offset(index as isize),
             self.edges().as_ptr().offset(index as isize + 1),
             self.len() - index + 1
@@ -1239,18 +1239,18 @@ fn split(&mut self) -> (K, V, Node<K, V>) {
         unsafe {
             right._len = self.len() / 2;
             let right_offset = self.len() - right.len();
-            ptr::copy_nonoverlapping_memory(
+            ptr::copy_nonoverlapping(
                 right.keys_mut().as_mut_ptr(),
                 self.keys().as_ptr().offset(right_offset as isize),
                 right.len()
             );
-            ptr::copy_nonoverlapping_memory(
+            ptr::copy_nonoverlapping(
                 right.vals_mut().as_mut_ptr(),
                 self.vals().as_ptr().offset(right_offset as isize),
                 right.len()
             );
             if !self.is_leaf() {
-                ptr::copy_nonoverlapping_memory(
+                ptr::copy_nonoverlapping(
                     right.edges_mut().as_mut_ptr(),
                     self.edges().as_ptr().offset(right_offset as isize),
                     right.len() + 1
@@ -1280,18 +1280,18 @@ fn absorb(&mut self, key: K, val: V, mut right: Node<K, V>) {
             ptr::write(self.keys_mut().get_unchecked_mut(old_len), key);
             ptr::write(self.vals_mut().get_unchecked_mut(old_len), val);
 
-            ptr::copy_nonoverlapping_memory(
+            ptr::copy_nonoverlapping(
                 self.keys_mut().as_mut_ptr().offset(old_len as isize + 1),
                 right.keys().as_ptr(),
                 right.len()
             );
-            ptr::copy_nonoverlapping_memory(
+            ptr::copy_nonoverlapping(
                 self.vals_mut().as_mut_ptr().offset(old_len as isize + 1),
                 right.vals().as_ptr(),
                 right.len()
             );
             if !self.is_leaf() {
-                ptr::copy_nonoverlapping_memory(
+                ptr::copy_nonoverlapping(
                     self.edges_mut().as_mut_ptr().offset(old_len as isize + 1),
                     right.edges().as_ptr(),
                     right.len() + 1
@@ -1354,11 +1354,14 @@ struct MoveTraversalImpl<K, V> {
     edges: RawItems<Node<K, V>>,
 
     // For deallocation when we are done iterating.
-    ptr: *mut u8,
+    ptr: Unique<u8>,
     capacity: usize,
     is_leaf: bool
 }
 
+unsafe impl<K: Sync, V: Sync> Sync for MoveTraversalImpl<K, V> {}
+unsafe impl<K: Send, V: Send> Send for MoveTraversalImpl<K, V> {}
+
 impl<K, V> TraversalImpl for MoveTraversalImpl<K, V> {
     type Item = (K, V);
     type Edge = Node<K, V>;
@@ -1401,7 +1404,7 @@ fn drop(&mut self) {
 
         let (alignment, size) =
                 calculate_allocation_generic::<K, V>(self.capacity, self.is_leaf);
-        unsafe { heap::deallocate(self.ptr, size, alignment) };
+        unsafe { heap::deallocate(*self.ptr, size, alignment) };
     }
 }
 
@@ -1425,12 +1428,12 @@ pub enum TraversalItem<K, V, E> {
 /// A traversal over a node's entries and edges
 pub type Traversal<'a, K, V> = AbsTraversal<ElemsAndEdges<Zip<slice::Iter<'a, K>,
                                                               slice::Iter<'a, V>>,
-                                                              slice::Iter<'a, Node<K, V>>>>;
+                                                          slice::Iter<'a, Node<K, V>>>>;
 
 /// A mutable traversal over a node's entries and edges
 pub type MutTraversal<'a, K, V> = AbsTraversal<ElemsAndEdges<Zip<slice::Iter<'a, K>,
                                                                  slice::IterMut<'a, V>>,
-                                                                 slice::IterMut<'a, Node<K, V>>>>;
+                                                             slice::IterMut<'a, Node<K, V>>>>;
 
 /// An owning traversal over a node's entries and edges
 pub type MoveTraversal<K, V> = AbsTraversal<MoveTraversalImpl<K, V>>;
index 929b2f58043035105097de82e38a1702575f2477..bc2e68b999a55e29ce02c218e60d3e7003e28da3 100644 (file)
@@ -121,7 +121,7 @@ impl<T> BTreeSet<T> {
     /// }
     ///
     /// let v: Vec<usize> = set.iter().cloned().collect();
-    /// assert_eq!(v, vec![1,2,3,4]);
+    /// assert_eq!(v, [1, 2, 3, 4]);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn iter(&self) -> Iter<T> {
@@ -138,7 +138,7 @@ pub fn iter(&self) -> Iter<T> {
     /// let set: BTreeSet<usize> = [1, 2, 3, 4].iter().cloned().collect();
     ///
     /// let v: Vec<usize> = set.into_iter().collect();
-    /// assert_eq!(v, vec![1,2,3,4]);
+    /// assert_eq!(v, [1, 2, 3, 4]);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn into_iter(self) -> IntoIter<T> {
@@ -197,7 +197,7 @@ impl<T: Ord> BTreeSet<T> {
     /// b.insert(3);
     ///
     /// let diff: Vec<usize> = a.difference(&b).cloned().collect();
-    /// assert_eq!(diff, vec![1]);
+    /// assert_eq!(diff, [1]);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn difference<'a>(&'a self, other: &'a BTreeSet<T>) -> Difference<'a, T> {
@@ -220,7 +220,7 @@ pub fn difference<'a>(&'a self, other: &'a BTreeSet<T>) -> Difference<'a, T> {
     /// b.insert(3);
     ///
     /// let sym_diff: Vec<usize> = a.symmetric_difference(&b).cloned().collect();
-    /// assert_eq!(sym_diff, vec![1,3]);
+    /// assert_eq!(sym_diff, [1, 3]);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn symmetric_difference<'a>(&'a self, other: &'a BTreeSet<T>)
@@ -244,7 +244,7 @@ pub fn symmetric_difference<'a>(&'a self, other: &'a BTreeSet<T>)
     /// b.insert(3);
     ///
     /// let intersection: Vec<usize> = a.intersection(&b).cloned().collect();
-    /// assert_eq!(intersection, vec![2]);
+    /// assert_eq!(intersection, [2]);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn intersection<'a>(&'a self, other: &'a BTreeSet<T>)
@@ -266,7 +266,7 @@ pub fn intersection<'a>(&'a self, other: &'a BTreeSet<T>)
     /// b.insert(2);
     ///
     /// let union: Vec<usize> = a.union(&b).cloned().collect();
-    /// assert_eq!(union, vec![1,2]);
+    /// assert_eq!(union, [1, 2]);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn union<'a>(&'a self, other: &'a BTreeSet<T>) -> Union<'a, T> {
@@ -534,7 +534,7 @@ impl<'a, 'b, T: Ord + Clone> Sub<&'b BTreeSet<T>> for &'a BTreeSet<T> {
     ///
     /// let result = &a - &b;
     /// let result_vec: Vec<_> = result.into_iter().collect();
-    /// assert_eq!(result_vec, vec![1, 2]);
+    /// assert_eq!(result_vec, [1, 2]);
     /// ```
     fn sub(self, rhs: &BTreeSet<T>) -> BTreeSet<T> {
         self.difference(rhs).cloned().collect()
@@ -557,7 +557,7 @@ impl<'a, 'b, T: Ord + Clone> BitXor<&'b BTreeSet<T>> for &'a BTreeSet<T> {
     ///
     /// let result = &a ^ &b;
     /// let result_vec: Vec<_> = result.into_iter().collect();
-    /// assert_eq!(result_vec, vec![1, 4]);
+    /// assert_eq!(result_vec, [1, 4]);
     /// ```
     fn bitxor(self, rhs: &BTreeSet<T>) -> BTreeSet<T> {
         self.symmetric_difference(rhs).cloned().collect()
@@ -580,7 +580,7 @@ impl<'a, 'b, T: Ord + Clone> BitAnd<&'b BTreeSet<T>> for &'a BTreeSet<T> {
     ///
     /// let result = &a & &b;
     /// let result_vec: Vec<_> = result.into_iter().collect();
-    /// assert_eq!(result_vec, vec![2, 3]);
+    /// assert_eq!(result_vec, [2, 3]);
     /// ```
     fn bitand(self, rhs: &BTreeSet<T>) -> BTreeSet<T> {
         self.intersection(rhs).cloned().collect()
@@ -603,7 +603,7 @@ impl<'a, 'b, T: Ord + Clone> BitOr<&'b BTreeSet<T>> for &'a BTreeSet<T> {
     ///
     /// let result = &a | &b;
     /// let result_vec: Vec<_> = result.into_iter().collect();
-    /// assert_eq!(result_vec, vec![1, 2, 3, 4, 5]);
+    /// assert_eq!(result_vec, [1, 2, 3, 4, 5]);
     /// ```
     fn bitor(self, rhs: &BTreeSet<T>) -> BTreeSet<T> {
         self.union(rhs).cloned().collect()
@@ -613,7 +613,7 @@ fn bitor(self, rhs: &BTreeSet<T>) -> BTreeSet<T> {
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T: Debug> Debug for BTreeSet<T> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        try!(write!(f, "BTreeSet {{"));
+        try!(write!(f, "{{"));
 
         for (i, x) in self.iter().enumerate() {
             if i != 0 { try!(write!(f, ", ")); }
@@ -911,7 +911,7 @@ fn test_show() {
 
         let set_str = format!("{:?}", set);
 
-        assert_eq!(set_str, "BTreeSet {1, 2}");
-        assert_eq!(format!("{:?}", empty), "BTreeSet {}");
+        assert_eq!(set_str, "{1, 2}");
+        assert_eq!(format!("{:?}", empty), "{}");
     }
 }
index 0c95742606083fbe33402ca667d840ed620c406c..62dd91915211b85a37aa1295c52ffa6b4439e6b8 100644 (file)
@@ -36,7 +36,7 @@ impl<E> Copy for EnumSet<E> {}
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<E:CLike + fmt::Debug> fmt::Debug for EnumSet<E> {
     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
-        try!(write!(fmt, "EnumSet {{"));
+        try!(write!(fmt, "{{"));
         let mut first = true;
         for e in self {
             if !first {
@@ -314,11 +314,11 @@ fn test_new() {
     #[test]
     fn test_show() {
         let mut e = EnumSet::new();
-        assert!(format!("{:?}", e) == "EnumSet {}");
+        assert!(format!("{:?}", e) == "{}");
         e.insert(A);
-        assert!(format!("{:?}", e) == "EnumSet {A}");
+        assert!(format!("{:?}", e) == "{A}");
         e.insert(C);
-        assert!(format!("{:?}", e) == "EnumSet {A, C}");
+        assert!(format!("{:?}", e) == "{A, C}");
     }
 
     #[test]
@@ -428,19 +428,19 @@ fn test_iterator() {
 
         e1.insert(A);
         let elems: ::vec::Vec<_> = e1.iter().collect();
-        assert_eq!(vec![A], elems);
+        assert_eq!([A], elems);
 
         e1.insert(C);
         let elems: ::vec::Vec<_> = e1.iter().collect();
-        assert_eq!(vec![A,C], elems);
+        assert_eq!([A,C], elems);
 
         e1.insert(C);
         let elems: ::vec::Vec<_> = e1.iter().collect();
-        assert_eq!(vec![A,C], elems);
+        assert_eq!([A,C], elems);
 
         e1.insert(B);
         let elems: ::vec::Vec<_> = e1.iter().collect();
-        assert_eq!(vec![A,B,C], elems);
+        assert_eq!([A,B,C], elems);
     }
 
     ///////////////////////////////////////////////////////////////////////////
@@ -458,35 +458,35 @@ fn test_operators() {
 
         let e_union = e1 | e2;
         let elems: ::vec::Vec<_> = e_union.iter().collect();
-        assert_eq!(vec![A,B,C], elems);
+        assert_eq!([A,B,C], elems);
 
         let e_intersection = e1 & e2;
         let elems: ::vec::Vec<_> = e_intersection.iter().collect();
-        assert_eq!(vec![C], elems);
+        assert_eq!([C], elems);
 
         // Another way to express intersection
         let e_intersection = e1 - (e1 - e2);
         let elems: ::vec::Vec<_> = e_intersection.iter().collect();
-        assert_eq!(vec![C], elems);
+        assert_eq!([C], elems);
 
         let e_subtract = e1 - e2;
         let elems: ::vec::Vec<_> = e_subtract.iter().collect();
-        assert_eq!(vec![A], elems);
+        assert_eq!([A], elems);
 
         // Bitwise XOR of two sets, aka symmetric difference
         let e_symmetric_diff = e1 ^ e2;
         let elems: ::vec::Vec<_> = e_symmetric_diff.iter().collect();
-        assert_eq!(vec![A,B], elems);
+        assert_eq!([A,B], elems);
 
         // Another way to express symmetric difference
         let e_symmetric_diff = (e1 - e2) | (e2 - e1);
         let elems: ::vec::Vec<_> = e_symmetric_diff.iter().collect();
-        assert_eq!(vec![A,B], elems);
+        assert_eq!([A,B], elems);
 
         // Yet another way to express symmetric difference
         let e_symmetric_diff = (e1 | e2) - (e1 & e2);
         let elems: ::vec::Vec<_> = e_symmetric_diff.iter().collect();
-        assert_eq!(vec![A,B], elems);
+        assert_eq!([A,B], elems);
     }
 
     #[test]
index 1f3c54a4cb53fd496fa8b58df7d98f020989e16f..7b66bfee34f2121b15f4e06ae47e832ed4a7edcf 100644 (file)
@@ -30,6 +30,7 @@
 #![feature(unboxed_closures)]
 #![feature(unicode)]
 #![feature(unsafe_destructor)]
+#![feature(unique)]
 #![feature(unsafe_no_drop_flag)]
 #![cfg_attr(test, feature(rand, rustc_private, test))]
 #![cfg_attr(test, allow(deprecated))] // rand
index 3c61fc3da90e3dd706a83ed0d73bcae9ace17880..9b5fbfc25114c046012f4f7e2e2748c004017146 100644 (file)
@@ -51,8 +51,8 @@ struct Rawlink<T> {
 }
 
 impl<T> Copy for Rawlink<T> {}
-unsafe impl<T:'static+Send> Send for Rawlink<T> {}
-unsafe impl<T:Send+Sync> Sync for Rawlink<T> {}
+unsafe impl<T:Send> Send for Rawlink<T> {}
+unsafe impl<T:Sync> Sync for Rawlink<T> {}
 
 struct Node<T> {
     next: Link<T>,
@@ -777,7 +777,7 @@ impl<'a, A> IterMut<'a, A> {
     /// }
     /// {
     ///     let vec: Vec<_> = list.into_iter().collect();
-    ///     assert_eq!(vec, vec![1, 2, 3, 4]);
+    ///     assert_eq!(vec, [1, 2, 3, 4]);
     /// }
     /// ```
     #[inline]
@@ -918,7 +918,7 @@ fn clone(&self) -> LinkedList<A> {
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<A: fmt::Debug> fmt::Debug for LinkedList<A> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        try!(write!(f, "LinkedList ["));
+        try!(write!(f, "["));
 
         for (i, e) in self.iter().enumerate() {
             if i != 0 { try!(write!(f, ", ")); }
@@ -1273,7 +1273,7 @@ fn test_insert_prev() {
         }
         check_links(&m);
         assert_eq!(m.len(), 3 + len * 2);
-        assert_eq!(m.into_iter().collect::<Vec<_>>(), vec![-2,0,1,2,3,4,5,6,7,8,9,0,1]);
+        assert_eq!(m.into_iter().collect::<Vec<_>>(), [-2,0,1,2,3,4,5,6,7,8,9,0,1]);
     }
 
     #[test]
@@ -1387,10 +1387,10 @@ fn test_fuzz() {
     #[test]
     fn test_show() {
         let list: LinkedList<_> = (0..10).collect();
-        assert_eq!(format!("{:?}", list), "LinkedList [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]");
+        assert_eq!(format!("{:?}", list), "[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]");
 
         let list: LinkedList<_> = vec!["just", "one", "test", "more"].iter().cloned().collect();
-        assert_eq!(format!("{:?}", list), "LinkedList [\"just\", \"one\", \"test\", \"more\"]");
+        assert_eq!(format!("{:?}", list), "[\"just\", \"one\", \"test\", \"more\"]");
     }
 
     #[cfg(test)]
index ebcfb8d1cf84e2a4d421e2fc000c2cf767e8e559..e9764547628c052cd22db69dbf5424e619881db4 100644 (file)
@@ -26,7 +26,7 @@
 ///
 /// ```
 /// let v = vec![1; 3];
-/// assert_eq!(v, vec![1, 1, 1]);
+/// assert_eq!(v, [1, 1, 1]);
 /// ```
 ///
 /// Note that unlike array expressions this syntax supports all elements
index 776b8b3af147c262b31fafccd74c9b376f070279..a2924f8fe53082bb2b6ff4843f20abd07a61c57a 100644 (file)
@@ -790,7 +790,7 @@ fn binary_search_elem(&self, x: &Self::Item) -> Result<usize, usize> where Self:
     fn ends_with(&self, needle: &[Self::Item]) -> bool where Self::Item: PartialEq;
 
     /// Convert `self` into a vector without clones or allocation.
-    #[unstable(feature = "collections")]
+    #[stable(feature = "rust1", since = "1.0.0")]
     fn into_vec(self: Box<Self>) -> Vec<Self::Item>;
 }
 
@@ -1331,12 +1331,10 @@ fn insertion_sort<T, F>(v: &mut [T], mut compare: F) where F: FnMut(&T, &T) -> O
 
             if i != j {
                 let tmp = ptr::read(read_ptr);
-                ptr::copy_memory(buf_v.offset(j + 1),
-                                 &*buf_v.offset(j),
-                                 (i - j) as usize);
-                ptr::copy_nonoverlapping_memory(buf_v.offset(j),
-                                                &tmp,
-                                                1);
+                ptr::copy(buf_v.offset(j + 1),
+                          &*buf_v.offset(j),
+                          (i - j) as usize);
+                ptr::copy_nonoverlapping(buf_v.offset(j), &tmp, 1);
                 mem::forget(tmp);
             }
         }
@@ -1409,10 +1407,10 @@ fn merge_sort<T, F>(v: &mut [T], mut compare: F) where F: FnMut(&T, &T) -> Order
                 // j + 1 could be `len` (for the last `i`), but in
                 // that case, `i == j` so we don't copy. The
                 // `.offset(j)` is always in bounds.
-                ptr::copy_memory(buf_dat.offset(j + 1),
-                                 &*buf_dat.offset(j),
-                                 i - j as usize);
-                ptr::copy_nonoverlapping_memory(buf_dat.offset(j), read_ptr, 1);
+                ptr::copy(buf_dat.offset(j + 1),
+                          &*buf_dat.offset(j),
+                          i - j as usize);
+                ptr::copy_nonoverlapping(buf_dat.offset(j), read_ptr, 1);
             }
         }
     }
@@ -1460,11 +1458,11 @@ fn merge_sort<T, F>(v: &mut [T], mut compare: F) where F: FnMut(&T, &T) -> Order
                     if left == right_start {
                         // the number remaining in this run.
                         let elems = (right_end as usize - right as usize) / mem::size_of::<T>();
-                        ptr::copy_nonoverlapping_memory(out, &*right, elems);
+                        ptr::copy_nonoverlapping(out, &*right, elems);
                         break;
                     } else if right == right_end {
                         let elems = (right_start as usize - left as usize) / mem::size_of::<T>();
-                        ptr::copy_nonoverlapping_memory(out, &*left, elems);
+                        ptr::copy_nonoverlapping(out, &*left, elems);
                         break;
                     }
 
@@ -1478,7 +1476,7 @@ fn merge_sort<T, F>(v: &mut [T], mut compare: F) where F: FnMut(&T, &T) -> Order
                     } else {
                         step(&mut left)
                     };
-                    ptr::copy_nonoverlapping_memory(out, &*to_copy, 1);
+                    ptr::copy_nonoverlapping(out, &*to_copy, 1);
                     step(&mut out);
                 }
             }
@@ -1492,7 +1490,7 @@ fn merge_sort<T, F>(v: &mut [T], mut compare: F) where F: FnMut(&T, &T) -> Order
     // write the result to `v` in one go, so that there are never two copies
     // of the same object in `v`.
     unsafe {
-        ptr::copy_nonoverlapping_memory(v.as_mut_ptr(), &*buf_dat, len);
+        ptr::copy_nonoverlapping(v.as_mut_ptr(), &*buf_dat, len);
     }
 
     // increment the pointer, returning the old pointer.
@@ -1779,10 +1777,10 @@ fn test_swap_remove() {
         let mut v = vec![1, 2, 3, 4, 5];
         let mut e = v.swap_remove(0);
         assert_eq!(e, 1);
-        assert_eq!(v, vec![5, 2, 3, 4]);
+        assert_eq!(v, [5, 2, 3, 4]);
         e = v.swap_remove(3);
         assert_eq!(e, 4);
-        assert_eq!(v, vec![5, 2, 3]);
+        assert_eq!(v, [5, 2, 3]);
     }
 
     #[test]
@@ -1890,7 +1888,7 @@ fn test_dedup_shared() {
     fn test_retain() {
         let mut v = vec![1, 2, 3, 4, 5];
         v.retain(is_odd);
-        assert_eq!(v, vec![1, 3, 5]);
+        assert_eq!(v, [1, 3, 5]);
     }
 
     #[test]
@@ -2159,45 +2157,45 @@ fn test_concat() {
         let v: [Vec<i32>; 0] = [];
         let c = v.concat();
         assert_eq!(c, []);
-        let d = [vec![1], vec![2,3]].concat();
-        assert_eq!(d, vec![1, 2, 3]);
+        let d = [vec![1], vec![2, 3]].concat();
+        assert_eq!(d, [1, 2, 3]);
 
         let v: &[&[_]] = &[&[1], &[2, 3]];
-        assert_eq!(v.connect(&0), vec![1, 0, 2, 3]);
+        assert_eq!(v.connect(&0), [1, 0, 2, 3]);
         let v: &[&[_]] = &[&[1], &[2], &[3]];
-        assert_eq!(v.connect(&0), vec![1, 0, 2, 0, 3]);
+        assert_eq!(v.connect(&0), [1, 0, 2, 0, 3]);
     }
 
     #[test]
     fn test_connect() {
         let v: [Vec<i32>; 0] = [];
-        assert_eq!(v.connect(&0), vec![]);
-        assert_eq!([vec![1], vec![2, 3]].connect(&0), vec![1, 0, 2, 3]);
-        assert_eq!([vec![1], vec![2], vec![3]].connect(&0), vec![1, 0, 2, 0, 3]);
+        assert_eq!(v.connect(&0), []);
+        assert_eq!([vec![1i], vec![2, 3]].connect(&0), [1, 0, 2, 3]);
+        assert_eq!([vec![1i], vec![2], vec![3]].connect(&0), [1, 0, 2, 0, 3]);
 
         let v: [&[_]; 2] = [&[1], &[2, 3]];
-        assert_eq!(v.connect(&0), vec![1, 0, 2, 3]);
+        assert_eq!(v.connect(&0), [1, 0, 2, 3]);
         let v: [&[_]; 3] = [&[1], &[2], &[3]];
-        assert_eq!(v.connect(&0), vec![1, 0, 2, 0, 3]);
+        assert_eq!(v.connect(&0), [1, 0, 2, 0, 3]);
     }
 
     #[test]
     fn test_insert() {
         let mut a = vec![1, 2, 4];
         a.insert(2, 3);
-        assert_eq!(a, vec![1, 2, 3, 4]);
+        assert_eq!(a, [1, 2, 3, 4]);
 
         let mut a = vec![1, 2, 3];
         a.insert(0, 0);
-        assert_eq!(a, vec![0, 1, 2, 3]);
+        assert_eq!(a, [0, 1, 2, 3]);
 
         let mut a = vec![1, 2, 3];
         a.insert(3, 4);
-        assert_eq!(a, vec![1, 2, 3, 4]);
+        assert_eq!(a, [1, 2, 3, 4]);
 
         let mut a = vec![];
         a.insert(0, 1);
-        assert_eq!(a, vec![1]);
+        assert_eq!(a, [1]);
     }
 
     #[test]
@@ -2212,16 +2210,16 @@ fn test_remove() {
         let mut a = vec![1, 2, 3, 4];
 
         assert_eq!(a.remove(2), 3);
-        assert_eq!(a, vec![1, 2, 4]);
+        assert_eq!(a, [1, 2, 4]);
 
         assert_eq!(a.remove(2), 4);
-        assert_eq!(a, vec![1, 2]);
+        assert_eq!(a, [1, 2]);
 
         assert_eq!(a.remove(0), 1);
-        assert_eq!(a, vec![2]);
+        assert_eq!(a, [2]);
 
         assert_eq!(a.remove(0), 2);
-        assert_eq!(a, vec![]);
+        assert_eq!(a, []);
     }
 
     #[test]
@@ -2665,7 +2663,7 @@ fn test_mut_split_at() {
             let (left, right) = values.split_at_mut(2);
             {
                 let left: &[_] = left;
-                assert!(left[..left.len()] == [1, 2][]);
+                assert!(left[..left.len()] == [1, 2]);
             }
             for p in left {
                 *p += 1;
@@ -2673,7 +2671,7 @@ fn test_mut_split_at() {
 
             {
                 let right: &[_] = right;
-                assert!(right[..right.len()] == [3, 4, 5][]);
+                assert!(right[..right.len()] == [3, 4, 5]);
             }
             for p in right {
                 *p += 2;
index f3b2e9738979c8c2a6022912b2e0eae2986b48c9..c58cca828d8c39a04c9fc542aa7b0ff3ec54a8ad 100644 (file)
@@ -552,7 +552,7 @@ fn contains_char<'a, P: Pattern<'a>>(&'a self, pat: P) -> bool {
     /// ```
     /// let v: Vec<char> = "abc åäö".chars().collect();
     ///
-    /// assert_eq!(v, vec!['a', 'b', 'c', ' ', 'å', 'ä', 'ö']);
+    /// assert_eq!(v, ['a', 'b', 'c', ' ', 'å', 'ä', 'ö']);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     fn chars(&self) -> Chars {
@@ -600,20 +600,20 @@ fn char_indices(&self) -> CharIndices {
     ///
     /// ```
     /// let v: Vec<&str> = "Mary had a little lamb".split(' ').collect();
-    /// assert_eq!(v, vec!["Mary", "had", "a", "little", "lamb"]);
+    /// assert_eq!(v, ["Mary", "had", "a", "little", "lamb"]);
     ///
     /// let v: Vec<&str> = "".split('X').collect();
-    /// assert_eq!(v, vec![""]);
+    /// assert_eq!(v, [""]);
     /// ```
     ///
     /// More complex patterns with a lambda:
     ///
     /// ```
     /// let v: Vec<&str> = "abc1def2ghi".split(|c: char| c.is_numeric()).collect();
-    /// assert_eq!(v, vec!["abc", "def", "ghi"]);
+    /// assert_eq!(v, ["abc", "def", "ghi"]);
     ///
     /// let v: Vec<&str> = "lionXXtigerXleopard".split('X').collect();
-    /// assert_eq!(v, vec!["lion", "", "tiger", "leopard"]);
+    /// assert_eq!(v, ["lion", "", "tiger", "leopard"]);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     fn split<'a, P: Pattern<'a>>(&'a self, pat: P) -> Split<'a, P> {
@@ -632,23 +632,23 @@ fn split<'a, P: Pattern<'a>>(&'a self, pat: P) -> Split<'a, P> {
     ///
     /// ```
     /// let v: Vec<&str> = "Mary had a little lambda".splitn(2, ' ').collect();
-    /// assert_eq!(v, vec!["Mary", "had", "a little lambda"]);
+    /// assert_eq!(v, ["Mary", "had", "a little lambda"]);
     ///
     /// let v: Vec<&str> = "lionXXtigerXleopard".splitn(2, 'X').collect();
-    /// assert_eq!(v, vec!["lion", "", "tigerXleopard"]);
+    /// assert_eq!(v, ["lion", "", "tigerXleopard"]);
     ///
     /// let v: Vec<&str> = "abcXdef".splitn(0, 'X').collect();
-    /// assert_eq!(v, vec!["abcXdef"]);
+    /// assert_eq!(v, ["abcXdef"]);
     ///
     /// let v: Vec<&str> = "".splitn(1, 'X').collect();
-    /// assert_eq!(v, vec![""]);
+    /// assert_eq!(v, [""]);
     /// ```
     ///
     /// More complex patterns with a lambda:
     ///
     /// ```
     /// let v: Vec<&str> = "abc1def2ghi".splitn(1, |c: char| c.is_numeric()).collect();
-    /// assert_eq!(v, vec!["abc", "def2ghi"]);
+    /// assert_eq!(v, ["abc", "def2ghi"]);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     fn splitn<'a, P: Pattern<'a>>(&'a self, count: usize, pat: P) -> SplitN<'a, P> {
@@ -669,17 +669,17 @@ fn splitn<'a, P: Pattern<'a>>(&'a self, count: usize, pat: P) -> SplitN<'a, P> {
     ///
     /// ```
     /// let v: Vec<&str> = "A.B.".split_terminator('.').collect();
-    /// assert_eq!(v, vec!["A", "B"]);
+    /// assert_eq!(v, ["A", "B"]);
     ///
     /// let v: Vec<&str> = "A..B..".split_terminator('.').collect();
-    /// assert_eq!(v, vec!["A", "", "B", ""]);
+    /// assert_eq!(v, ["A", "", "B", ""]);
     /// ```
     ///
     /// More complex patterns with a lambda:
     ///
     /// ```
     /// let v: Vec<&str> = "abc1def2ghi3".split_terminator(|c: char| c.is_numeric()).collect();
-    /// assert_eq!(v, vec!["abc", "def", "ghi"]);
+    /// assert_eq!(v, ["abc", "def", "ghi"]);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     fn split_terminator<'a, P: Pattern<'a>>(&'a self, pat: P) -> SplitTerminator<'a, P> {
@@ -699,17 +699,17 @@ fn split_terminator<'a, P: Pattern<'a>>(&'a self, pat: P) -> SplitTerminator<'a,
     ///
     /// ```
     /// let v: Vec<&str> = "Mary had a little lamb".rsplitn(2, ' ').collect();
-    /// assert_eq!(v, vec!["lamb", "little", "Mary had a"]);
+    /// assert_eq!(v, ["lamb", "little", "Mary had a"]);
     ///
     /// let v: Vec<&str> = "lionXXtigerXleopard".rsplitn(2, 'X').collect();
-    /// assert_eq!(v, vec!["leopard", "tiger", "lionX"]);
+    /// assert_eq!(v, ["leopard", "tiger", "lionX"]);
     /// ```
     ///
     /// More complex patterns with a lambda:
     ///
     /// ```
     /// let v: Vec<&str> = "abc1def2ghi".rsplitn(1, |c: char| c.is_numeric()).collect();
-    /// assert_eq!(v, vec!["ghi", "abc1def"]);
+    /// assert_eq!(v, ["ghi", "abc1def"]);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     fn rsplitn<'a, P: Pattern<'a>>(&'a self, count: usize, pat: P) -> RSplitN<'a, P> {
@@ -727,13 +727,13 @@ fn rsplitn<'a, P: Pattern<'a>>(&'a self, count: usize, pat: P) -> RSplitN<'a, P>
     ///
     /// ```
     /// let v: Vec<(usize, usize)> = "abcXXXabcYYYabc".match_indices("abc").collect();
-    /// assert_eq!(v, vec![(0,3), (6,9), (12,15)]);
+    /// assert_eq!(v, [(0,3), (6,9), (12,15)]);
     ///
     /// let v: Vec<(usize, usize)> = "1abcabc2".match_indices("abc").collect();
-    /// assert_eq!(v, vec![(1,4), (4,7)]);
+    /// assert_eq!(v, [(1,4), (4,7)]);
     ///
     /// let v: Vec<(usize, usize)> = "ababa".match_indices("aba").collect();
-    /// assert_eq!(v, vec![(0, 3)]); // only the first `aba`
+    /// assert_eq!(v, [(0, 3)]); // only the first `aba`
     /// ```
     #[unstable(feature = "collections",
                reason = "might have its iterator type changed")]
@@ -749,10 +749,10 @@ fn match_indices<'a, P: Pattern<'a>>(&'a self, pat: P) -> MatchIndices<'a, P> {
     ///
     /// ```
     /// let v: Vec<&str> = "abcXXXabcYYYabc".split_str("abc").collect();
-    /// assert_eq!(v, vec!["", "XXX", "YYY", ""]);
+    /// assert_eq!(v, ["", "XXX", "YYY", ""]);
     ///
     /// let v: Vec<&str> = "1abcabc2".split_str("abc").collect();
-    /// assert_eq!(v, vec!["1", "", "2"]);
+    /// assert_eq!(v, ["1", "", "2"]);
     /// ```
     #[unstable(feature = "collections")]
     #[deprecated(since = "1.0.0", reason = "use `split()` with a `&str`")]
@@ -770,7 +770,7 @@ fn split_str<'a, P: Pattern<'a>>(&'a self, pat: P) -> SplitStr<'a, P> {
     /// let four_lines = "foo\nbar\n\nbaz";
     /// let v: Vec<&str> = four_lines.lines().collect();
     ///
-    /// assert_eq!(v, vec!["foo", "bar", "", "baz"]);
+    /// assert_eq!(v, ["foo", "bar", "", "baz"]);
     /// ```
     ///
     /// Leaving off the trailing character:
@@ -779,7 +779,7 @@ fn split_str<'a, P: Pattern<'a>>(&'a self, pat: P) -> SplitStr<'a, P> {
     /// let four_lines = "foo\nbar\n\nbaz\n";
     /// let v: Vec<&str> = four_lines.lines().collect();
     ///
-    /// assert_eq!(v, vec!["foo", "bar", "", "baz"]);
+    /// assert_eq!(v, ["foo", "bar", "", "baz"]);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     fn lines(&self) -> Lines {
@@ -796,7 +796,7 @@ fn lines(&self) -> Lines {
     /// let four_lines = "foo\r\nbar\n\r\nbaz";
     /// let v: Vec<&str> = four_lines.lines_any().collect();
     ///
-    /// assert_eq!(v, vec!["foo", "bar", "", "baz"]);
+    /// assert_eq!(v, ["foo", "bar", "", "baz"]);
     /// ```
     ///
     /// Leaving off the trailing character:
@@ -805,7 +805,7 @@ fn lines(&self) -> Lines {
     /// let four_lines = "foo\r\nbar\n\r\nbaz\n";
     /// let v: Vec<&str> = four_lines.lines_any().collect();
     ///
-    /// assert_eq!(v, vec!["foo", "bar", "", "baz"]);
+    /// assert_eq!(v, ["foo", "bar", "", "baz"]);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     fn lines_any(&self) -> LinesAny {
@@ -1441,7 +1441,7 @@ fn grapheme_indices(&self, is_extended: bool) -> GraphemeIndices {
     /// let some_words = " Mary   had\ta little  \n\t lamb";
     /// let v: Vec<&str> = some_words.words().collect();
     ///
-    /// assert_eq!(v, vec!["Mary", "had", "a", "little", "lamb"]);
+    /// assert_eq!(v, ["Mary", "had", "a", "little", "lamb"]);
     /// ```
     #[unstable(feature = "str_words",
                reason = "the precise algorithm to use is unclear")]
@@ -2400,17 +2400,17 @@ fn test_splitn_char_iterator() {
         let data = "\nMäry häd ä little lämb\nLittle lämb\n";
 
         let split: Vec<&str> = data.splitn(3, ' ').collect();
-        assert_eq!(split, vec!["\nMäry", "häd", "ä", "little lämb\nLittle lämb\n"]);
+        assert_eq!(split, ["\nMäry", "häd", "ä", "little lämb\nLittle lämb\n"]);
 
         let split: Vec<&str> = data.splitn(3, |c: char| c == ' ').collect();
-        assert_eq!(split, vec!["\nMäry", "häd", "ä", "little lämb\nLittle lämb\n"]);
+        assert_eq!(split, ["\nMäry", "häd", "ä", "little lämb\nLittle lämb\n"]);
 
         // Unicode
         let split: Vec<&str> = data.splitn(3, 'ä').collect();
-        assert_eq!(split, vec!["\nM", "ry h", "d ", " little lämb\nLittle lämb\n"]);
+        assert_eq!(split, ["\nM", "ry h", "d ", " little lämb\nLittle lämb\n"]);
 
         let split: Vec<&str> = data.splitn(3, |c: char| c == 'ä').collect();
-        assert_eq!(split, vec!["\nM", "ry h", "d ", " little lämb\nLittle lämb\n"]);
+        assert_eq!(split, ["\nM", "ry h", "d ", " little lämb\nLittle lämb\n"]);
     }
 
     #[test]
@@ -2418,17 +2418,17 @@ fn test_split_char_iterator_no_trailing() {
         let data = "\nMäry häd ä little lämb\nLittle lämb\n";
 
         let split: Vec<&str> = data.split('\n').collect();
-        assert_eq!(split, vec!["", "Märy häd ä little lämb", "Little lämb", ""]);
+        assert_eq!(split, ["", "Märy häd ä little lämb", "Little lämb", ""]);
 
         let split: Vec<&str> = data.split_terminator('\n').collect();
-        assert_eq!(split, vec!["", "Märy häd ä little lämb", "Little lämb"]);
+        assert_eq!(split, ["", "Märy häd ä little lämb", "Little lämb"]);
     }
 
     #[test]
     fn test_words() {
         let data = "\n \tMäry   häd\tä  little lämb\nLittle lämb\n";
         let words: Vec<&str> = data.words().collect();
-        assert_eq!(words, vec!["Märy", "häd", "ä", "little", "lämb", "Little", "lämb"])
+        assert_eq!(words, ["Märy", "häd", "ä", "little", "lämb", "Little", "lämb"])
     }
 
     #[test]
@@ -2513,11 +2513,11 @@ macro_rules! t {
     fn test_lines() {
         let data = "\nMäry häd ä little lämb\n\nLittle lämb\n";
         let lines: Vec<&str> = data.lines().collect();
-        assert_eq!(lines, vec!["", "Märy häd ä little lämb", "", "Little lämb"]);
+        assert_eq!(lines, ["", "Märy häd ä little lämb", "", "Little lämb"]);
 
         let data = "\nMäry häd ä little lämb\n\nLittle lämb"; // no trailing \n
         let lines: Vec<&str> = data.lines().collect();
-        assert_eq!(lines, vec!["", "Märy häd ä little lämb", "", "Little lämb"]);
+        assert_eq!(lines, ["", "Märy häd ä little lämb", "", "Little lämb"]);
     }
 
     #[test]
index 6c2624cd204de1711879cc5b78a16c345e4bdc84..94abffa3db61cf6c33d24e87807af67e419fe1a1 100644 (file)
@@ -120,7 +120,7 @@ pub fn from_str(string: &str) -> String {
     /// let invalid_vec = vec![240, 144, 128];
     /// let s = String::from_utf8(invalid_vec).err().unwrap();
     /// assert_eq!(s.utf8_error(), Utf8Error::TooShort);
-    /// assert_eq!(s.into_bytes(), vec![240, 144, 128]);
+    /// assert_eq!(s.into_bytes(), [240, 144, 128]);
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -340,7 +340,7 @@ pub unsafe fn from_utf8_unchecked(bytes: Vec<u8>) -> String {
     /// ```
     /// let s = String::from_str("hello");
     /// let bytes = s.into_bytes();
-    /// assert_eq!(bytes, vec![104, 101, 108, 108, 111]);
+    /// assert_eq!(bytes, [104, 101, 108, 108, 111]);
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -568,9 +568,9 @@ pub fn remove(&mut self, idx: usize) -> char {
 
         let CharRange { ch, next } = self.char_range_at(idx);
         unsafe {
-            ptr::copy_memory(self.vec.as_mut_ptr().offset(idx as isize),
-                             self.vec.as_ptr().offset(next as isize),
-                             len - next);
+            ptr::copy(self.vec.as_mut_ptr().offset(idx as isize),
+                      self.vec.as_ptr().offset(next as isize),
+                      len - next);
             self.vec.set_len(len - (next - idx));
         }
         ch
@@ -598,12 +598,12 @@ pub fn insert(&mut self, idx: usize, ch: char) {
         let amt = ch.encode_utf8(&mut bits).unwrap();
 
         unsafe {
-            ptr::copy_memory(self.vec.as_mut_ptr().offset((idx + amt) as isize),
-                             self.vec.as_ptr().offset(idx as isize),
-                             len - idx);
-            ptr::copy_memory(self.vec.as_mut_ptr().offset(idx as isize),
-                             bits.as_ptr(),
-                             amt);
+            ptr::copy(self.vec.as_mut_ptr().offset((idx + amt) as isize),
+                      self.vec.as_ptr().offset(idx as isize),
+                      len - idx);
+            ptr::copy(self.vec.as_mut_ptr().offset(idx as isize),
+                      bits.as_ptr(),
+                      amt);
             self.vec.set_len(len + amt);
         }
     }
@@ -619,7 +619,7 @@ pub fn insert(&mut self, idx: usize, ch: char) {
     /// let mut s = String::from_str("hello");
     /// unsafe {
     ///     let vec = s.as_mut_vec();
-    ///     assert!(vec == &mut vec![104, 101, 108, 108, 111]);
+    ///     assert!(vec == &[104, 101, 108, 108, 111]);
     ///     vec.reverse();
     /// }
     /// assert_eq!(s.as_slice(), "olleh");
index 3f5f92889166fd544b33cd9d5e001be63b157dc1..805e4623396b849b22041fc1281d42b3406f7067 100644 (file)
@@ -93,7 +93,7 @@
 /// for x in vec.iter() {
 ///     println!("{}", x);
 /// }
-/// assert_eq!(vec, vec![7, 1, 2, 3]);
+/// assert_eq!(vec, [7, 1, 2, 3]);
 /// ```
 ///
 /// The `vec!` macro is provided to make initialization more convenient:
 /// ```
 /// let mut vec = vec![1, 2, 3];
 /// vec.push(4);
-/// assert_eq!(vec, vec![1, 2, 3, 4]);
+/// assert_eq!(vec, [1, 2, 3, 4]);
 /// ```
 ///
 /// Use a `Vec<T>` as an efficient stack:
@@ -242,7 +242,7 @@ pub fn with_capacity(capacity: usize) -> Vec<T> {
     ///
     ///         // Put everything back together into a Vec
     ///         let rebuilt = Vec::from_raw_parts(p, len, cap);
-    ///         assert_eq!(rebuilt, vec![4, 5, 6]);
+    ///         assert_eq!(rebuilt, [4, 5, 6]);
     ///     }
     /// }
     /// ```
@@ -267,7 +267,7 @@ pub unsafe fn from_raw_parts(ptr: *mut T, length: usize,
     pub unsafe fn from_raw_buf(ptr: *const T, elts: usize) -> Vec<T> {
         let mut dst = Vec::with_capacity(elts);
         dst.set_len(elts);
-        ptr::copy_nonoverlapping_memory(dst.as_mut_ptr(), ptr, elts);
+        ptr::copy_nonoverlapping(dst.as_mut_ptr(), ptr, elts);
         dst
     }
 
@@ -404,7 +404,7 @@ pub fn into_boxed_slice(mut self) -> Box<[T]> {
     /// ```
     /// let mut vec = vec![1, 2, 3, 4];
     /// vec.truncate(2);
-    /// assert_eq!(vec, vec![1, 2]);
+    /// assert_eq!(vec, [1, 2]);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn truncate(&mut self, len: usize) {
@@ -433,8 +433,10 @@ pub fn truncate(&mut self, len: usize) {
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn as_mut_slice(&mut self) -> &mut [T] {
         unsafe {
+            let ptr = *self.ptr;
+            assume(!ptr.is_null());
             mem::transmute(RawSlice {
-                data: *self.ptr,
+                data: ptr,
                 len: self.len,
             })
         }
@@ -458,6 +460,7 @@ pub fn as_mut_slice(&mut self) -> &mut [T] {
     pub fn into_iter(self) -> IntoIter<T> {
         unsafe {
             let ptr = *self.ptr;
+            assume(!ptr.is_null());
             let cap = self.cap;
             let begin = ptr as *const T;
             let end = if mem::size_of::<T>() == 0 {
@@ -505,10 +508,10 @@ pub unsafe fn set_len(&mut self, len: usize) {
     /// let mut v = vec!["foo", "bar", "baz", "qux"];
     ///
     /// assert_eq!(v.swap_remove(1), "bar");
-    /// assert_eq!(v, vec!["foo", "qux", "baz"]);
+    /// assert_eq!(v, ["foo", "qux", "baz"]);
     ///
     /// assert_eq!(v.swap_remove(0), "foo");
-    /// assert_eq!(v, vec!["baz", "qux"]);
+    /// assert_eq!(v, ["baz", "qux"]);
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -531,9 +534,9 @@ pub fn swap_remove(&mut self, index: usize) -> T {
     /// ```
     /// let mut vec = vec![1, 2, 3];
     /// vec.insert(1, 4);
-    /// assert_eq!(vec, vec![1, 4, 2, 3]);
+    /// assert_eq!(vec, [1, 4, 2, 3]);
     /// vec.insert(4, 5);
-    /// assert_eq!(vec, vec![1, 4, 2, 3, 5]);
+    /// assert_eq!(vec, [1, 4, 2, 3, 5]);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn insert(&mut self, index: usize, element: T) {
@@ -548,7 +551,7 @@ pub fn insert(&mut self, index: usize, element: T) {
                 let p = self.as_mut_ptr().offset(index as isize);
                 // Shift everything over to make space. (Duplicating the
                 // `index`th element into two consecutive places.)
-                ptr::copy_memory(p.offset(1), &*p, len - index);
+                ptr::copy(p.offset(1), &*p, len - index);
                 // Write it in, overwriting the first copy of the `index`th
                 // element.
                 ptr::write(&mut *p, element);
@@ -569,7 +572,7 @@ pub fn insert(&mut self, index: usize, element: T) {
     /// ```
     /// let mut v = vec![1, 2, 3];
     /// assert_eq!(v.remove(1), 2);
-    /// assert_eq!(v, vec![1, 3]);
+    /// assert_eq!(v, [1, 3]);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn remove(&mut self, index: usize) -> T {
@@ -585,7 +588,7 @@ pub fn remove(&mut self, index: usize) -> T {
                 ret = ptr::read(ptr);
 
                 // Shift everything down to fill in that spot.
-                ptr::copy_memory(ptr, &*ptr.offset(1), len - index - 1);
+                ptr::copy(ptr, &*ptr.offset(1), len - index - 1);
             }
             self.set_len(len - 1);
             ret
@@ -603,7 +606,7 @@ pub fn remove(&mut self, index: usize) -> T {
     /// ```
     /// let mut vec = vec![1, 2, 3, 4];
     /// vec.retain(|&x| x%2 == 0);
-    /// assert_eq!(vec, vec![2, 4]);
+    /// assert_eq!(vec, [2, 4]);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn retain<F>(&mut self, mut f: F) where F: FnMut(&T) -> bool {
@@ -636,7 +639,7 @@ pub fn retain<F>(&mut self, mut f: F) where F: FnMut(&T) -> bool {
     /// ```rust
     /// let mut vec = vec!(1, 2);
     /// vec.push(3);
-    /// assert_eq!(vec, vec!(1, 2, 3));
+    /// assert_eq!(vec, [1, 2, 3]);
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -674,7 +677,7 @@ pub fn push(&mut self, value: T) {
     /// ```rust
     /// let mut vec = vec![1, 2, 3];
     /// assert_eq!(vec.pop(), Some(3));
-    /// assert_eq!(vec, vec![1, 2]);
+    /// assert_eq!(vec, [1, 2]);
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -701,8 +704,8 @@ pub fn pop(&mut self) -> Option<T> {
     /// let mut vec = vec![1, 2, 3];
     /// let mut vec2 = vec![4, 5, 6];
     /// vec.append(&mut vec2);
-    /// assert_eq!(vec, vec![1, 2, 3, 4, 5, 6]);
-    /// assert_eq!(vec2, vec![]);
+    /// assert_eq!(vec, [1, 2, 3, 4, 5, 6]);
+    /// assert_eq!(vec2, []);
     /// ```
     #[inline]
     #[unstable(feature = "collections",
@@ -718,7 +721,7 @@ pub fn append(&mut self, other: &mut Self) {
         self.reserve(other.len());
         let len = self.len();
         unsafe {
-            ptr::copy_nonoverlapping_memory(
+            ptr::copy_nonoverlapping(
                 self.get_unchecked_mut(len),
                 other.as_ptr(),
                 other.len());
@@ -1019,8 +1022,8 @@ pub fn map_in_place<U, F>(self, mut f: F) -> Vec<U> where F: FnMut(T) -> U {
     /// ```
     /// let mut vec = vec![1,2,3];
     /// let vec2 = vec.split_off(1);
-    /// assert_eq!(vec, vec![1]);
-    /// assert_eq!(vec2, vec![2, 3]);
+    /// assert_eq!(vec, [1]);
+    /// assert_eq!(vec2, [2, 3]);
     /// ```
     #[inline]
     #[unstable(feature = "collections",
@@ -1036,7 +1039,7 @@ pub fn split_off(&mut self, at: usize) -> Self {
             self.set_len(at);
             other.set_len(other_len);
 
-            ptr::copy_nonoverlapping_memory(
+            ptr::copy_nonoverlapping(
                 other.as_mut_ptr(),
                 self.as_ptr().offset(at as isize),
                 other.len());
@@ -1057,11 +1060,11 @@ impl<T: Clone> Vec<T> {
     /// ```
     /// let mut vec = vec!["hello"];
     /// vec.resize(3, "world");
-    /// assert_eq!(vec, vec!["hello", "world", "world"]);
+    /// assert_eq!(vec, ["hello", "world", "world"]);
     ///
     /// let mut vec = vec![1, 2, 3, 4];
     /// vec.resize(2, 0);
-    /// assert_eq!(vec, vec![1, 2]);
+    /// assert_eq!(vec, [1, 2]);
     /// ```
     #[unstable(feature = "collections",
                reason = "matches collection reform specification; waiting for dust to settle")]
@@ -1085,7 +1088,7 @@ pub fn resize(&mut self, new_len: usize, value: T) {
     /// ```
     /// let mut vec = vec![1];
     /// vec.push_all(&[2, 3, 4]);
-    /// assert_eq!(vec, vec![1, 2, 3, 4]);
+    /// assert_eq!(vec, [1, 2, 3, 4]);
     /// ```
     #[inline]
     #[unstable(feature = "collections",
@@ -1121,7 +1124,7 @@ impl<T: PartialEq> Vec<T> {
     ///
     /// vec.dedup();
     ///
-    /// assert_eq!(vec, vec![1, 2, 3, 2]);
+    /// assert_eq!(vec, [1, 2, 3, 2]);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn dedup(&mut self) {
@@ -1755,6 +1758,9 @@ pub struct Drain<'a, T:'a> {
     marker: PhantomData<&'a T>,
 }
 
+unsafe impl<'a, T: Sync> Sync for Drain<'a, T> {}
+unsafe impl<'a, T: Send> Send for Drain<'a, T> {}
+
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, T> Iterator for Drain<'a, T> {
     type Item = T;
@@ -2090,7 +2096,7 @@ fn test_split_at_mut() {
             let (left, right) = values.split_at_mut(2);
             {
                 let left: &[_] = left;
-                assert!(&left[..left.len()] == &[1, 2][]);
+                assert!(&left[..left.len()] == &[1, 2]);
             }
             for p in left {
                 *p += 1;
@@ -2098,14 +2104,14 @@ fn test_split_at_mut() {
 
             {
                 let right: &[_] = right;
-                assert!(&right[..right.len()] == &[3, 4, 5][]);
+                assert!(&right[..right.len()] == &[3, 4, 5]);
             }
             for p in right {
                 *p += 2;
             }
         }
 
-        assert!(values == vec![2, 3, 5, 6, 7]);
+        assert_eq!(values, [2, 3, 5, 6, 7]);
     }
 
     #[test]
@@ -2147,7 +2153,7 @@ fn test_clone_from() {
     fn test_retain() {
         let mut vec = vec![1, 2, 3, 4];
         vec.retain(|&x| x % 2 == 0);
-        assert!(vec == vec![2, 4]);
+        assert_eq!(vec, [2, 4]);
     }
 
     #[test]
@@ -2207,13 +2213,13 @@ fn test_unsafe_ptrs() {
             let a = [1, 2, 3];
             let ptr = a.as_ptr();
             let b = Vec::from_raw_buf(ptr, 3);
-            assert_eq!(b, vec![1, 2, 3]);
+            assert_eq!(b, [1, 2, 3]);
 
             // Test on-heap copy-from-buf.
             let c = vec![1, 2, 3, 4, 5];
             let ptr = c.as_ptr();
             let d = Vec::from_raw_buf(ptr, 5);
-            assert_eq!(d, vec![1, 2, 3, 4, 5]);
+            assert_eq!(d, [1, 2, 3, 4, 5]);
         }
     }
 
@@ -2375,7 +2381,7 @@ fn test_move_items() {
         for i in vec {
             vec2.push(i);
         }
-        assert!(vec2 == vec![1, 2, 3]);
+        assert_eq!(vec2, [1, 2, 3]);
     }
 
     #[test]
@@ -2385,7 +2391,7 @@ fn test_move_items_reverse() {
         for i in vec.into_iter().rev() {
             vec2.push(i);
         }
-        assert!(vec2 == vec![3, 2, 1]);
+        assert_eq!(vec2, [3, 2, 1]);
     }
 
     #[test]
@@ -2395,7 +2401,7 @@ fn test_move_items_zero_sized() {
         for i in vec {
             vec2.push(i);
         }
-        assert!(vec2 == vec![(), (), ()]);
+        assert_eq!(vec2, [(), (), ()]);
     }
 
     #[test]
@@ -2443,16 +2449,16 @@ fn test_append() {
         let mut vec = vec![1, 2, 3];
         let mut vec2 = vec![4, 5, 6];
         vec.append(&mut vec2);
-        assert_eq!(vec, vec![1, 2, 3, 4, 5, 6]);
-        assert_eq!(vec2, vec![]);
+        assert_eq!(vec, [1, 2, 3, 4, 5, 6]);
+        assert_eq!(vec2, []);
     }
 
     #[test]
     fn test_split_off() {
         let mut vec = vec![1, 2, 3, 4, 5, 6];
         let vec2 = vec.split_off(4);
-        assert_eq!(vec, vec![1, 2, 3, 4]);
-        assert_eq!(vec2, vec![5, 6]);
+        assert_eq!(vec, [1, 2, 3, 4]);
+        assert_eq!(vec2, [5, 6]);
     }
 
     #[bench]
index f65e644fa52842f7325ee1d0ac3a1bf76a53af20..abcc0cef9f1feae7ad86e659f1475133de50a471 100644 (file)
@@ -24,7 +24,6 @@
 use core::default::Default;
 use core::fmt;
 use core::iter::{self, repeat, FromIterator, IntoIterator, RandomAccessIterator};
-use core::marker;
 use core::mem;
 use core::num::{Int, UnsignedInt};
 use core::ops::{Index, IndexMut};
@@ -59,12 +58,6 @@ pub struct VecDeque<T> {
     ptr: Unique<T>,
 }
 
-#[stable(feature = "rust1", since = "1.0.0")]
-unsafe impl<T: Send> Send for VecDeque<T> {}
-
-#[stable(feature = "rust1", since = "1.0.0")]
-unsafe impl<T: Sync> Sync for VecDeque<T> {}
-
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T: Clone> Clone for VecDeque<T> {
     fn clone(&self) -> VecDeque<T> {
@@ -134,7 +127,7 @@ unsafe fn copy(&self, dst: usize, src: usize, len: usize) {
                       self.cap);
         debug_assert!(src + len <= self.cap, "dst={} src={} len={} cap={}", dst, src, len,
                       self.cap);
-        ptr::copy_memory(
+        ptr::copy(
             self.ptr.offset(dst as isize),
             self.ptr.offset(src as isize),
             len);
@@ -147,7 +140,7 @@ unsafe fn copy_nonoverlapping(&self, dst: usize, src: usize, len: usize) {
                       self.cap);
         debug_assert!(src + len <= self.cap, "dst={} src={} len={} cap={}", dst, src, len,
                       self.cap);
-        ptr::copy_nonoverlapping_memory(
+        ptr::copy_nonoverlapping(
             self.ptr.offset(dst as isize),
             self.ptr.offset(src as isize),
             len);
@@ -545,9 +538,7 @@ pub fn iter_mut(&mut self) -> IterMut<T> {
         IterMut {
             tail: self.tail,
             head: self.head,
-            cap: self.cap,
-            ptr: *self.ptr,
-            marker: marker::PhantomData,
+            ring: unsafe { self.buffer_as_mut_slice() },
         }
     }
 
@@ -1343,22 +1334,22 @@ pub fn split_off(&mut self, at: usize) -> Self {
                 // `at` lies in the first half.
                 let amount_in_first = first_len - at;
 
-                ptr::copy_nonoverlapping_memory(*other.ptr,
-                                                first_half.as_ptr().offset(at as isize),
-                                                amount_in_first);
+                ptr::copy_nonoverlapping(*other.ptr,
+                                         first_half.as_ptr().offset(at as isize),
+                                         amount_in_first);
 
                 // just take all of the second half.
-                ptr::copy_nonoverlapping_memory(other.ptr.offset(amount_in_first as isize),
-                                                second_half.as_ptr(),
-                                                second_len);
+                ptr::copy_nonoverlapping(other.ptr.offset(amount_in_first as isize),
+                                         second_half.as_ptr(),
+                                         second_len);
             } else {
                 // `at` lies in the second half, need to factor in the elements we skipped
                 // in the first half.
                 let offset = at - first_len;
                 let amount_in_second = second_len - offset;
-                ptr::copy_nonoverlapping_memory(*other.ptr,
-                                                second_half.as_ptr().offset(offset as isize),
-                                                amount_in_second);
+                ptr::copy_nonoverlapping(*other.ptr,
+                                         second_half.as_ptr().offset(offset as isize),
+                                         amount_in_second);
             }
         }
 
@@ -1515,17 +1506,12 @@ fn idx(&mut self, j: usize) -> Option<&'a T> {
     }
 }
 
-// FIXME This was implemented differently from Iter because of a problem
-//       with returning the mutable reference. I couldn't find a way to
-//       make the lifetime checker happy so, but there should be a way.
 /// `VecDeque` mutable iterator.
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct IterMut<'a, T:'a> {
-    ptr: *mut T,
+    ring: &'a mut [T],
     tail: usize,
     head: usize,
-    cap: usize,
-    marker: marker::PhantomData<&'a mut T>,
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -1538,16 +1524,17 @@ fn next(&mut self) -> Option<&'a mut T> {
             return None;
         }
         let tail = self.tail;
-        self.tail = wrap_index(self.tail + 1, self.cap);
+        self.tail = wrap_index(self.tail + 1, self.ring.len());
 
         unsafe {
-            Some(&mut *self.ptr.offset(tail as isize))
+            let elem = self.ring.get_unchecked_mut(tail);
+            Some(&mut *(elem as *mut _))
         }
     }
 
     #[inline]
     fn size_hint(&self) -> (usize, Option<usize>) {
-        let len = count(self.tail, self.head, self.cap);
+        let len = count(self.tail, self.head, self.ring.len());
         (len, Some(len))
     }
 }
@@ -1559,10 +1546,11 @@ fn next_back(&mut self) -> Option<&'a mut T> {
         if self.tail == self.head {
             return None;
         }
-        self.head = wrap_index(self.head - 1, self.cap);
+        self.head = wrap_index(self.head - 1, self.ring.len());
 
         unsafe {
-            Some(&mut *self.ptr.offset(self.head as isize))
+            let elem = self.ring.get_unchecked_mut(self.head);
+            Some(&mut *(elem as *mut _))
         }
     }
 }
@@ -1754,7 +1742,7 @@ fn extend<T: IntoIterator<Item=A>>(&mut self, iter: T) {
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T: fmt::Debug> fmt::Debug for VecDeque<T> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        try!(write!(f, "VecDeque ["));
+        try!(write!(f, "["));
 
         for (i, e) in self.iter().enumerate() {
             if i != 0 { try!(write!(f, ", ")); }
@@ -2105,7 +2093,7 @@ fn test_swap() {
         let mut d: VecDeque<_> = (0..5).collect();
         d.pop_front();
         d.swap(0, 3);
-        assert_eq!(d.iter().cloned().collect::<Vec<_>>(), vec!(4, 2, 3, 1));
+        assert_eq!(d.iter().cloned().collect::<Vec<_>>(), [4, 2, 3, 1]);
     }
 
     #[test]
@@ -2435,12 +2423,12 @@ fn test_ord() {
     #[test]
     fn test_show() {
         let ringbuf: VecDeque<_> = (0..10).collect();
-        assert_eq!(format!("{:?}", ringbuf), "VecDeque [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]");
+        assert_eq!(format!("{:?}", ringbuf), "[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]");
 
         let ringbuf: VecDeque<_> = vec!["just", "one", "test", "more"].iter()
                                                                         .cloned()
                                                                         .collect();
-        assert_eq!(format!("{:?}", ringbuf), "VecDeque [\"just\", \"one\", \"test\", \"more\"]");
+        assert_eq!(format!("{:?}", ringbuf), "[\"just\", \"one\", \"test\", \"more\"]");
     }
 
     #[test]
@@ -2868,17 +2856,17 @@ fn test_append() {
 
         // normal append
         a.append(&mut b);
-        assert_eq!(a.iter().cloned().collect(), vec![1, 2, 3, 4, 5, 6]);
-        assert_eq!(b.iter().cloned().collect(), vec![]);
+        assert_eq!(a.iter().cloned().collect::<Vec<_>>(), [1, 2, 3, 4, 5, 6]);
+        assert_eq!(b.iter().cloned().collect::<Vec<_>>(), []);
 
         // append nothing to something
         a.append(&mut b);
-        assert_eq!(a.iter().cloned().collect(), vec![1, 2, 3, 4, 5, 6]);
-        assert_eq!(b.iter().cloned().collect(), vec![]);
+        assert_eq!(a.iter().cloned().collect::<Vec<_>>(), [1, 2, 3, 4, 5, 6]);
+        assert_eq!(b.iter().cloned().collect::<Vec<_>>(), []);
 
         // append something to nothing
         b.append(&mut a);
-        assert_eq!(b.iter().cloned().collect(), vec![1, 2, 3, 4, 5, 6]);
-        assert_eq!(a.iter().cloned().collect(), vec![]);
+        assert_eq!(b.iter().cloned().collect::<Vec<_>>(), [1, 2, 3, 4, 5, 6]);
+        assert_eq!(a.iter().cloned().collect::<Vec<_>>(), []);
     }
 }
index d92249379fa8fc36adf9100163b368069495eb20..5a0aa750bf5670dc1a569ca9f9c5e9715c17c884 100644 (file)
@@ -308,7 +308,7 @@ pub fn iter_mut<'r>(&'r mut self) -> IterMut<'r, V> {
     ///
     /// let vec: Vec<(usize, &str)> = map.into_iter().collect();
     ///
-    /// assert_eq!(vec, vec![(1, "a"), (2, "b"), (3, "c")]);
+    /// assert_eq!(vec, [(1, "a"), (2, "b"), (3, "c")]);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn into_iter(self) -> IntoIter<V> {
@@ -425,7 +425,7 @@ pub fn split_off(&mut self, at: usize) -> Self {
     ///
     /// let vec: Vec<(usize, &str)> = map.drain().collect();
     ///
-    /// assert_eq!(vec, vec![(1, "a"), (2, "b"), (3, "c")]);
+    /// assert_eq!(vec, [(1, "a"), (2, "b"), (3, "c")]);
     /// ```
     #[unstable(feature = "collections",
                reason = "matches collection reform specification, waiting for dust to settle")]
@@ -739,7 +739,7 @@ fn cmp(&self, other: &VecMap<V>) -> Ordering {
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<V: fmt::Debug> fmt::Debug for VecMap<V> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        try!(write!(f, "VecMap {{"));
+        try!(write!(f, "{{"));
 
         for (i, (k, v)) in self.iter().enumerate() {
             if i != 0 { try!(write!(f, ", ")); }
@@ -1226,7 +1226,7 @@ fn test_drain_iterator() {
 
         let vec: Vec<_> = map.drain().collect();
 
-        assert_eq!(vec, vec![(1, "a"), (2, "b"), (3, "c")]);
+        assert_eq!(vec, [(1, "a"), (2, "b"), (3, "c")]);
         assert_eq!(map.len(), 0);
     }
 
@@ -1318,8 +1318,8 @@ fn test_show() {
         map.insert(3, 4);
 
         let map_str = format!("{:?}", map);
-        assert!(map_str == "VecMap {1: 2, 3: 4}" || map_str == "{3: 4, 1: 2}");
-        assert_eq!(format!("{:?}", empty), "VecMap {}");
+        assert!(map_str == "{1: 2, 3: 4}" || map_str == "{3: 4, 1: 2}");
+        assert_eq!(format!("{:?}", empty), "{}");
     }
 
     #[test]
index 0bf44dd77aaa199a939a505974232b581f54aee6..117b829fdff9b5bf79ed6e4d686cfa45239b21b4 100644 (file)
@@ -110,10 +110,7 @@ fn write_fmt(&mut self, args: Arguments) -> Result {
 /// traits.
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct Formatter<'a> {
-    #[cfg(not(stage0))]
     flags: u32,
-    #[cfg(stage0)]
-    flags: usize,
     fill: char,
     align: rt::v1::Alignment,
     width: Option<usize>,
@@ -159,13 +156,6 @@ pub fn new<'b, T>(x: &'b T,
         }
     }
 
-    #[cfg(stage0)]
-    #[doc(hidden)]
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn from_uint(x: &uint) -> ArgumentV1 {
-        ArgumentV1::new(x, ArgumentV1::show_usize)
-    }
-    #[cfg(not(stage0))]
     #[doc(hidden)]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn from_usize(x: &usize) -> ArgumentV1 {
@@ -605,14 +595,9 @@ pub fn write_fmt(&mut self, fmt: Arguments) -> Result {
         write(self.buf, fmt)
     }
 
-    #[cfg(not(stage0))]
     /// Flags for formatting (packed version of rt::Flag)
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn flags(&self) -> u32 { self.flags }
-    #[cfg(stage0)]
-    /// Flags for formatting (packed version of rt::Flag)
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn flags(&self) -> usize { self.flags }
 
     /// Character used as 'fill' whenever there is alignment
     #[unstable(feature = "core", reason = "method was just created")]
index c35611acb81428561ccb4634f72889588e534ec6..7f6dea905dafd45ec351f20d8e1a21de91356e29 100644 (file)
@@ -32,10 +32,6 @@ pub struct FormatSpec {
     pub fill: char,
     #[stable(feature = "rust1", since = "1.0.0")]
     pub align: Alignment,
-    #[cfg(stage0)]
-    #[stable(feature = "rust1", since = "1.0.0")]
-    pub flags: usize,
-    #[cfg(not(stage0))]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub flags: u32,
     #[stable(feature = "rust1", since = "1.0.0")]
index b2ee95963878edb13af4a4b99c9cf529377b13f4..1ca243134cc6c6d985ca7f6b107c935c2d9ace58 100644 (file)
@@ -241,7 +241,12 @@ pub struct TyDesc {
     /// will trigger a compiler error.
     pub fn return_address() -> *const u8;
 
-    /// Returns `true` if a type requires drop glue.
+    /// Returns `true` if the actual type given as `T` requires drop
+    /// glue; returns `false` if the actual type provided for `T`
+    /// implements `Copy`.
+    ///
+    /// If the actual type neither requires drop glue nor implements
+    /// `Copy`, then may return `true` or `false`.
     pub fn needs_drop<T>() -> bool;
 
     /// Returns `true` if a type is managed (will be allocated on the local heap)
@@ -293,7 +298,7 @@ pub struct TyDesc {
     ///     }
     /// }
     /// ```
-    #[unstable(feature = "core")]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn copy_nonoverlapping_memory<T>(dst: *mut T, src: *const T, count: usize);
 
     /// Copies `count * size_of<T>` bytes from `src` to `dst`. The source
@@ -323,13 +328,12 @@ pub struct TyDesc {
     /// }
     /// ```
     ///
-    #[unstable(feature = "core")]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn copy_memory<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`.
-    #[unstable(feature = "core",
-               reason = "uncertain about naming and semantics")]
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub fn set_memory<T>(dst: *mut T, val: u8, count: usize);
 
     /// Equivalent to the appropriate `llvm.memcpy.p0i8.0i8.*` intrinsic, with
index 09089f2d04c5f8f3ec3f8110a5b23eeeb7a707d3..94cc933d844f370b6bbf5b8f9ac41b5b24352968 100644 (file)
@@ -68,7 +68,7 @@
 use ops::{Add, Deref, FnMut};
 use option::Option;
 use option::Option::{Some, None};
-use marker::Sized;
+use marker::{Send, Sized, Sync};
 use usize;
 
 /// An interface for dealing with "external iterators". These types of iterators
@@ -171,8 +171,7 @@ fn count(self) -> usize {
         self.fold(0, |cnt, _x| cnt + 1)
     }
 
-    /// Loops through the entire iterator, returning the last element of the
-    /// iterator.
+    /// Loops through the entire iterator, returning the last element.
     ///
     /// # Examples
     ///
@@ -582,8 +581,8 @@ fn collect<B: FromIterator<Self::Item>>(self) -> B {
     /// ```
     /// let vec = vec![1, 2, 3, 4];
     /// let (even, odd): (Vec<_>, Vec<_>) = vec.into_iter().partition(|&n| n % 2 == 0);
-    /// assert_eq!(even, vec![2, 4]);
-    /// assert_eq!(odd, vec![1, 3]);
+    /// assert_eq!(even, [2, 4]);
+    /// assert_eq!(odd, [1, 3]);
     /// ```
     #[unstable(feature = "core",
                reason = "recently added as part of collections reform")]
@@ -637,8 +636,8 @@ fn fold<B, F>(self, init: B, mut f: F) -> B where
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
-    fn all<F>(self, mut f: F) -> bool where F: FnMut(Self::Item) -> bool {
-        for x in self { if !f(x) { return false; } }
+    fn all<F>(&mut self, mut f: F) -> bool where F: FnMut(Self::Item) -> bool {
+        for x in self.by_ref() { if !f(x) { return false; } }
         true
     }
 
@@ -981,7 +980,7 @@ fn size_hint(&self) -> (usize, Option<usize>) {
     #[unstable(feature = "core", reason = "recent addition")]
     fn cloned(self) -> Cloned<Self> where
         Self::Item: Deref,
-        <Self::Item as Deref>::Output: Clone,
+        <Self::Item as Deref>::Target: Clone,
     {
         Cloned { it: self }
     }
@@ -1637,8 +1636,6 @@ fn next(&mut self) -> Option<I::Item> {
         for x in self.iter.by_ref() {
             if (self.predicate)(&x) {
                 return Some(x);
-            } else {
-                continue
             }
         }
         None
@@ -1786,6 +1783,10 @@ pub struct Peekable<I: Iterator> {
     peeked: Option<I::Item>,
 }
 
+// FIXME: after #22828 being fixed, the following unsafe impl should be removed
+unsafe impl<I: Iterator> Sync for Peekable<I> where I: Sync, I::Item: Sync {}
+unsafe impl<I: Iterator> Send for Peekable<I> where I: Send, I::Item: Send {}
+
 impl<I: Iterator + Clone> Clone for Peekable<I> where I::Item: Clone {
     fn clone(&self) -> Peekable<I> {
         Peekable {
index 92d50821592c62b0aa99e618a30995bb50e9441c..94ca9ec37b49b515523e2e6ed713e1df3c6074cb 100644 (file)
@@ -15,9 +15,6 @@ macro_rules! panic {
         panic!("explicit panic")
     );
     ($msg:expr) => ({
-        #[cfg(stage0)]
-        static _MSG_FILE_LINE: (&'static str, &'static str, usize) = ($msg, file!(), line!());
-        #[cfg(not(stage0))]
         static _MSG_FILE_LINE: (&'static str, &'static str, u32) = ($msg, file!(), line!());
         ::core::panicking::panic(&_MSG_FILE_LINE)
     });
@@ -26,9 +23,6 @@ macro_rules! panic {
         // used inside a dead function. Just `#[allow(dead_code)]` is
         // insufficient, since the user may have
         // `#[forbid(dead_code)]` and which cannot be overridden.
-        #[cfg(stage0)]
-        static _FILE_LINE: (&'static str, usize) = (file!(), line!());
-        #[cfg(not(stage0))]
         static _FILE_LINE: (&'static str, u32) = (file!(), line!());
         ::core::panicking::panic_fmt(format_args!($fmt, $($arg)*), &_FILE_LINE)
     });
index 6c934a998de2d4cb5d64ce35d135ce12f312bc0d..868a671b9560e2985188874f3b333463af95143d 100644 (file)
@@ -275,7 +275,13 @@ fn clone(&self) -> $t<T> {
 /// any methods, but instead is used to gate access to data.
 ///
 /// FIXME. Better documentation needed here!
-pub trait MarkerTrait : PhantomFn<Self> { }
+pub trait MarkerTrait : PhantomFn<Self,Self> { }
+//                                    ~~~~~ <-- FIXME(#22806)?
+//
+// Marker trait has been made invariant so as to avoid inf recursion,
+// but we should ideally solve the underlying problem. That's a bit
+// complicated.
+
 impl<T:?Sized> MarkerTrait for T { }
 
 /// `PhantomFn` is a marker trait for use with traits that contain
index 740997b7a249d5a6fcdf472c2e5c277f472a0327..2aa8ec0c548d958b4c20eeb8b57ca68908b469fb 100644 (file)
@@ -203,9 +203,9 @@ pub fn swap<T>(x: &mut T, y: &mut T) {
         let mut t: T = uninitialized();
 
         // Perform the swap, `&mut` pointers never alias
-        ptr::copy_nonoverlapping_memory(&mut t, &*x, 1);
-        ptr::copy_nonoverlapping_memory(x, &*y, 1);
-        ptr::copy_nonoverlapping_memory(y, &t, 1);
+        ptr::copy_nonoverlapping(&mut t, &*x, 1);
+        ptr::copy_nonoverlapping(x, &*y, 1);
+        ptr::copy_nonoverlapping(y, &t, 1);
 
         // y and t now point to the same thing, but we need to completely forget `t`
         // because it's no longer relevant.
index 7612469c8088bbfe3c30579d02e28f48aa4482fd..b1039f79f23de1989343683d2d4cc99cd528a906 100644 (file)
@@ -1672,6 +1672,7 @@ fn from_str_radix(src: &str, radix: u32)
                 let is_signed_ty = (0 as $T) > Int::min_value();
 
                 match src.slice_shift_char() {
+                    Some(('-', "")) => Err(PIE { kind: Empty }),
                     Some(('-', src)) if is_signed_ty => {
                         // The number is negative
                         let mut result = 0;
index abfef72a5dbc33b735a67416a191f2e1b093600c..1ecbd8fae8cdb664b5f9549a358ea6c7cb7b7b01 100644 (file)
@@ -556,7 +556,7 @@ pub fn iter_mut(&mut self) -> IterMut<T> {
     /// ```
     /// let x = Some("string");
     /// let v: Vec<&str> = x.into_iter().collect();
-    /// assert_eq!(v, vec!["string"]);
+    /// assert_eq!(v, ["string"]);
     ///
     /// let x = None;
     /// let v: Vec<&str> = x.into_iter().collect();
index 168dcf4978c4634f9e81993a46047ab2778db618..c1c8ac9cc1fa789441485d917af8e5b558c59f2d 100644 (file)
 
 #[cold] #[inline(never)] // this is the slow path, always
 #[lang="panic"]
-#[cfg(stage0)]
-pub fn panic(expr_file_line: &(&'static str, &'static str, usize)) -> ! {
-    let (expr, file, line) = *expr_file_line;
-    panic_fmt(format_args!("{}", expr), &(file, line))
-}
-#[cold] #[inline(never)] // this is the slow path, always
-#[lang="panic"]
-#[cfg(not(stage0))]
 pub fn panic(expr_file_line: &(&'static str, &'static str, u32)) -> ! {
     let (expr, file, line) = *expr_file_line;
     panic_fmt(format_args!("{}", expr), &(file, line))
@@ -49,15 +41,6 @@ pub fn panic(expr_file_line: &(&'static str, &'static str, u32)) -> ! {
 
 #[cold] #[inline(never)]
 #[lang="panic_bounds_check"]
-#[cfg(stage0)]
-fn panic_bounds_check(file_line: &(&'static str, usize),
-                     index: usize, len: usize) -> ! {
-    panic_fmt(format_args!("index out of bounds: the len is {} but the index is {}",
-                           len, index), file_line)
-}
-#[cold] #[inline(never)]
-#[lang="panic_bounds_check"]
-#[cfg(not(stage0))]
 fn panic_bounds_check(file_line: &(&'static str, u32),
                      index: usize, len: usize) -> ! {
     panic_fmt(format_args!("index out of bounds: the len is {} but the index is {}",
@@ -65,18 +48,6 @@ fn panic_bounds_check(file_line: &(&'static str, u32),
 }
 
 #[cold] #[inline(never)]
-#[cfg(stage0)]
-pub fn panic_fmt(fmt: fmt::Arguments, file_line: &(&'static str, usize)) -> ! {
-    #[allow(improper_ctypes)]
-    extern {
-        #[lang = "panic_fmt"]
-        fn panic_impl(fmt: fmt::Arguments, file: &'static str, line: uint) -> !;
-    }
-    let (file, line) = *file_line;
-    unsafe { panic_impl(fmt, file, line as uint) }
-}
-#[cold] #[inline(never)]
-#[cfg(not(stage0))]
 pub fn panic_fmt(fmt: fmt::Arguments, file_line: &(&'static str, u32)) -> ! {
     #[allow(improper_ctypes)]
     extern {
index b44cc899787f54cc7c29001de7e8018e231daf08..0625c3c7d6018e26d4e36f2c0a43246cd6794d88 100644 (file)
 
 // FIXME #19649: intrinsic docs don't render, so these have no docs :(
 
-#[unstable(feature = "core")]
-pub use intrinsics::copy_nonoverlapping_memory;
+#[stable(feature = "rust1", since = "1.0.0")]
+pub use intrinsics::copy_nonoverlapping_memory as copy_nonoverlapping;
 
-#[unstable(feature = "core")]
-pub use intrinsics::copy_memory;
+#[stable(feature = "rust1", since = "1.0.0")]
+pub use intrinsics::copy_memory as copy;
 
-#[unstable(feature = "core",
-           reason = "uncertain about naming and semantics")]
-pub use intrinsics::set_memory;
+#[stable(feature = "rust1", since = "1.0.0")]
+pub use intrinsics::set_memory as write_bytes;
 
+extern "rust-intrinsic" {
+    #[unstable(feature = "core")]
+    #[deprecated(since = "1.0.0", reason = "renamed to `copy_nonoverlapping`")]
+    pub fn copy_nonoverlapping_memory<T>(dst: *mut T, src: *const T, count: usize);
+    #[unstable(feature = "core")]
+    #[deprecated(since = "1.0.0", reason = "renamed to `copy`")]
+    pub fn copy_memory<T>(dst: *mut T, src: *const T, count: usize);
+
+    #[unstable(feature = "core",
+               reason = "uncertain about naming and semantics")]
+    #[deprecated(since = "1.0.0", reason = "renamed to `write_bytes`")]
+    pub fn set_memory<T>(dst: *mut T, val: u8, count: usize);
+}
 
 /// Creates a null raw pointer.
 ///
@@ -150,8 +162,9 @@ pub fn null_mut<T>() -> *mut T { 0 as *mut T }
 #[inline]
 #[unstable(feature = "core",
            reason = "may play a larger role in std::ptr future extensions")]
+#[deprecated(since = "1.0.0", reason = "use `write_bytes` instead")]
 pub unsafe fn zero_memory<T>(dst: *mut T, count: usize) {
-    set_memory(dst, 0, count);
+    write_bytes(dst, 0, count);
 }
 
 /// Swaps the values at two mutable locations of the same type, without
@@ -169,9 +182,9 @@ pub unsafe fn swap<T>(x: *mut T, y: *mut T) {
     let t: *mut T = &mut tmp;
 
     // Perform the swap
-    copy_nonoverlapping_memory(t, &*x, 1);
-    copy_memory(x, &*y, 1); // `x` and `y` may overlap
-    copy_nonoverlapping_memory(y, &*t, 1);
+    copy_nonoverlapping(t, &*x, 1);
+    copy(x, &*y, 1); // `x` and `y` may overlap
+    copy_nonoverlapping(y, &*t, 1);
 
     // y and t now point to the same thing, but we need to completely forget `tmp`
     // because it's no longer relevant.
@@ -207,7 +220,7 @@ pub unsafe fn replace<T>(dest: *mut T, mut src: T) -> T {
 #[stable(feature = "rust1", since = "1.0.0")]
 pub unsafe fn read<T>(src: *const T) -> T {
     let mut tmp: T = mem::uninitialized();
-    copy_nonoverlapping_memory(&mut tmp, src, 1);
+    copy_nonoverlapping(&mut tmp, src, 1);
     tmp
 }
 
@@ -224,7 +237,7 @@ pub unsafe fn read_and_zero<T>(dest: *mut T) -> T {
     let tmp = read(&*dest);
 
     // Now zero out `dest`:
-    zero_memory(dest, 1);
+    write_bytes(dest, 0, 1);
 
     tmp
 }
@@ -248,9 +261,9 @@ pub unsafe fn write<T>(dst: *mut T, src: T) {
 
 /// Methods on raw pointers
 #[stable(feature = "rust1", since = "1.0.0")]
-pub trait PtrExt: Sized {
+pub trait PtrExt {
     /// The type which is being pointed at
-    type Target;
+    type Target: ?Sized;
 
     /// Returns true if the pointer is null.
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -279,14 +292,14 @@ pub trait PtrExt: Sized {
     /// Otherwise `offset` invokes Undefined Behaviour, regardless of whether
     /// the pointer is used.
     #[stable(feature = "rust1", since = "1.0.0")]
-    unsafe fn offset(self, count: isize) -> Self;
+    unsafe fn offset(self, count: isize) -> Self where Self::Target: Sized;
 }
 
 /// Methods on mutable raw pointers
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait MutPtrExt {
     /// The type which is being pointed at
-    type Target;
+    type Target: ?Sized;
 
     /// Returns `None` if the pointer is null, or else returns a mutable
     /// reference to the value wrapped in `Some`.
@@ -302,7 +315,7 @@ pub trait MutPtrExt {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<T> PtrExt for *const T {
+impl<T: ?Sized> PtrExt for *const T {
     type Target = T;
 
     #[inline]
@@ -311,7 +324,7 @@ fn is_null(self) -> bool { self == 0 as *const T }
 
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
-    unsafe fn offset(self, count: isize) -> *const T {
+    unsafe fn offset(self, count: isize) -> *const T where T: Sized {
         intrinsics::offset(self, count)
     }
 
@@ -329,7 +342,7 @@ unsafe fn as_ref<'a>(&self) -> Option<&'a T> {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<T> PtrExt for *mut T {
+impl<T: ?Sized> PtrExt for *mut T {
     type Target = T;
 
     #[inline]
@@ -338,7 +351,7 @@ fn is_null(self) -> bool { self == 0 as *mut T }
 
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
-    unsafe fn offset(self, count: isize) -> *mut T {
+    unsafe fn offset(self, count: isize) -> *mut T where T: Sized {
         intrinsics::offset(self, count) as *mut T
     }
 
@@ -356,7 +369,7 @@ unsafe fn as_ref<'a>(&self) -> Option<&'a T> {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<T> MutPtrExt for *mut T {
+impl<T: ?Sized> MutPtrExt for *mut T {
     type Target = T;
 
     #[inline]
@@ -374,33 +387,25 @@ unsafe fn as_mut<'a>(&self) -> Option<&'a mut T> {
 
 // Equality for pointers
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<T> PartialEq for *const T {
+impl<T: ?Sized> PartialEq for *const T {
     #[inline]
-    fn eq(&self, other: &*const T) -> bool {
-        *self == *other
-    }
-    #[inline]
-    fn ne(&self, other: &*const T) -> bool { !self.eq(other) }
+    fn eq(&self, other: &*const T) -> bool { *self == *other }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<T> Eq for *const T {}
+impl<T: ?Sized> Eq for *const T {}
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<T> PartialEq for *mut T {
-    #[inline]
-    fn eq(&self, other: &*mut T) -> bool {
-        *self == *other
-    }
+impl<T: ?Sized> PartialEq for *mut T {
     #[inline]
-    fn ne(&self, other: &*mut T) -> bool { !self.eq(other) }
+    fn eq(&self, other: &*mut T) -> bool { *self == *other }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<T> Eq for *mut T {}
+impl<T: ?Sized> Eq for *mut T {}
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<T> Clone for *const T {
+impl<T: ?Sized> Clone for *const T {
     #[inline]
     fn clone(&self) -> *const T {
         *self
@@ -408,7 +413,7 @@ fn clone(&self) -> *const T {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<T> Clone for *mut T {
+impl<T: ?Sized> Clone for *mut T {
     #[inline]
     fn clone(&self) -> *mut T {
         *self
@@ -452,7 +457,7 @@ fn eq(&self, other: &extern "C" fn($($p),*) -> _R) -> bool {
 
 // Comparison for pointers
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<T> Ord for *const T {
+impl<T: ?Sized> Ord for *const T {
     #[inline]
     fn cmp(&self, other: &*const T) -> Ordering {
         if self < other {
@@ -466,7 +471,7 @@ fn cmp(&self, other: &*const T) -> Ordering {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<T> PartialOrd for *const T {
+impl<T: ?Sized> PartialOrd for *const T {
     #[inline]
     fn partial_cmp(&self, other: &*const T) -> Option<Ordering> {
         Some(self.cmp(other))
@@ -486,7 +491,7 @@ fn ge(&self, other: &*const T) -> bool { *self >= *other }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<T> Ord for *mut T {
+impl<T: ?Sized> Ord for *mut T {
     #[inline]
     fn cmp(&self, other: &*mut T) -> Ordering {
         if self < other {
@@ -500,7 +505,7 @@ fn cmp(&self, other: &*mut T) -> Ordering {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<T> PartialOrd for *mut T {
+impl<T: ?Sized> PartialOrd for *mut T {
     #[inline]
     fn partial_cmp(&self, other: &*mut T) -> Option<Ordering> {
         Some(self.cmp(other))
@@ -527,8 +532,8 @@ fn ge(&self, other: &*mut T) -> bool { *self >= *other }
 /// modified without a unique path to the `Unique` reference. Useful
 /// for building abstractions like `Vec<T>` or `Box<T>`, which
 /// internally use raw pointers to manage the memory that they own.
-#[unstable(feature = "core", reason = "recently added to this module")]
-pub struct Unique<T:?Sized> {
+#[unstable(feature = "unique")]
+pub struct Unique<T: ?Sized> {
     pointer: NonZero<*const T>,
     _marker: PhantomData<T>,
 }
@@ -537,39 +542,37 @@ pub struct Unique<T:?Sized> {
 /// reference is unaliased. Note that this aliasing invariant is
 /// unenforced by the type system; the abstraction using the
 /// `Unique` must enforce it.
-#[unstable(feature = "core", reason = "recently added to this module")]
+#[unstable(feature = "unique")]
 unsafe impl<T: Send + ?Sized> Send for Unique<T> { }
 
 /// `Unique` pointers are `Sync` if `T` is `Sync` because the data they
 /// reference is unaliased. Note that this aliasing invariant is
 /// unenforced by the type system; the abstraction using the
 /// `Unique` must enforce it.
-#[unstable(feature = "core", reason = "recently added to this module")]
+#[unstable(feature = "unique")]
 unsafe impl<T: Sync + ?Sized> Sync for Unique<T> { }
 
-impl<T:?Sized> Unique<T> {
+impl<T: ?Sized> Unique<T> {
     /// Create a new `Unique`.
-    #[unstable(feature = "core",
-               reason = "recently added to this module")]
+    #[unstable(feature = "unique")]
     pub unsafe fn new(ptr: *mut T) -> Unique<T> {
         Unique { pointer: NonZero::new(ptr as *const T), _marker: PhantomData }
     }
 
     /// Dereference the content.
-    #[unstable(feature = "core",
-               reason = "recently added to this module")]
+    #[unstable(feature = "unique")]
     pub unsafe fn get(&self) -> &T {
         &**self.pointer
     }
 
     /// Mutably dereference the content.
-    #[unstable(feature = "core",
-               reason = "recently added to this module")]
+    #[unstable(feature = "unique")]
     pub unsafe fn get_mut(&mut self) -> &mut T {
         &mut ***self
     }
 }
 
+#[unstable(feature = "unique")]
 impl<T:?Sized> Deref for Unique<T> {
     type Target = *mut T;
 
index 23e936a75d7097e04f972a3da25796a285090711..b8271562d2e670c22677a86ce61964f51325a053 100644 (file)
@@ -548,11 +548,11 @@ pub fn iter_mut(&mut self) -> IterMut<T> {
     /// ```
     /// let x: Result<u32, &str> = Ok(5);
     /// let v: Vec<u32> = x.into_iter().collect();
-    /// assert_eq!(v, vec![5]);
+    /// assert_eq!(v, [5]);
     ///
     /// let x: Result<u32, &str> = Err("nothing!");
     /// let v: Vec<u32> = x.into_iter().collect();
-    /// assert_eq!(v, vec![]);
+    /// assert_eq!(v, []);
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -641,9 +641,9 @@ pub fn and_then<U, F: FnOnce(T) -> Result<U, E>>(self, op: F) -> Result<U, E> {
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn or(self, res: Result<T, E>) -> Result<T, E> {
+    pub fn or<F>(self, res: Result<T, F>) -> Result<T, F> {
         match self {
-            Ok(_) => self,
+            Ok(v) => Ok(v),
             Err(_) => res,
         }
     }
index 2debcaa5813421c0951b434f85c8b01f44001c1d..5b78da34eddde0e7dd363383b3fd0d4b719c5640 100644 (file)
@@ -40,6 +40,7 @@
 use cmp::Ordering::{Less, Equal, Greater};
 use cmp;
 use default::Default;
+use intrinsics::assume;
 use iter::*;
 use ops::{FnMut, self, Index};
 use ops::RangeFull;
@@ -51,7 +52,7 @@
 use ptr::PtrExt;
 use mem;
 use mem::size_of;
-use marker::{Sized, self};
+use marker::{Send, Sized, Sync, self};
 use raw::Repr;
 // Avoid conflicts with *both* the Slice trait (buggy) and the `slice::raw` module.
 use raw::Slice as RawSlice;
@@ -137,6 +138,7 @@ fn split_at(&self, mid: usize) -> (&[T], &[T]) {
     fn iter<'a>(&'a self) -> Iter<'a, T> {
         unsafe {
             let p = self.as_ptr();
+            assume(!p.is_null());
             if mem::size_of::<T>() == 0 {
                 Iter {ptr: p,
                       end: (p as usize + self.len()) as *const T,
@@ -276,6 +278,7 @@ fn split_at_mut(&mut self, mid: usize) -> (&mut [T], &mut [T]) {
     fn iter_mut<'a>(&'a mut self) -> IterMut<'a, T> {
         unsafe {
             let p = self.as_mut_ptr();
+            assume(!p.is_null());
             if mem::size_of::<T>() == 0 {
                 IterMut {ptr: p,
                          end: (p as usize + self.len()) as *mut T,
@@ -740,6 +743,9 @@ pub struct Iter<'a, T: 'a> {
     _marker: marker::PhantomData<&'a T>,
 }
 
+unsafe impl<'a, T: Sync> Sync for Iter<'a, T> {}
+unsafe impl<'a, T: Sync> Send for Iter<'a, T> {}
+
 #[unstable(feature = "core")]
 impl<'a, T> ops::Index<ops::Range<usize>> for Iter<'a, T> {
     type Output = [T];
@@ -830,6 +836,8 @@ pub struct IterMut<'a, T: 'a> {
     _marker: marker::PhantomData<&'a mut T>,
 }
 
+unsafe impl<'a, T: Sync> Sync for IterMut<'a, T> {}
+unsafe impl<'a, T: Send> Send for IterMut<'a, T> {}
 
 #[unstable(feature = "core")]
 impl<'a, T> ops::Index<ops::Range<usize>> for IterMut<'a, T> {
@@ -1500,7 +1508,7 @@ pub trait MutableByteVector {
     impl MutableByteVector for [u8] {
         #[inline]
         fn set_memory(&mut self, value: u8) {
-            unsafe { ptr::set_memory(self.as_mut_ptr(), value, self.len()) };
+            unsafe { ptr::write_bytes(self.as_mut_ptr(), value, self.len()) };
         }
     }
 
@@ -1514,9 +1522,9 @@ pub fn copy_memory(dst: &mut [u8], src: &[u8]) {
         // `dst` is unaliasable, so we know statically it doesn't overlap
         // with `src`.
         unsafe {
-            ptr::copy_nonoverlapping_memory(dst.as_mut_ptr(),
-                                            src.as_ptr(),
-                                            len_src);
+            ptr::copy_nonoverlapping(dst.as_mut_ptr(),
+                                     src.as_ptr(),
+                                     len_src);
         }
     }
 }
index 7e51f8e8503b411e4c62ba740aff3d23a0e112a7..b354116993c23a1e750be1fa8c900dc95261ab85 100644 (file)
@@ -939,6 +939,7 @@ impl<'a, P: Pattern<'a>> Iterator for SplitStr<'a, P> {
     type Item = &'a str;
 
     #[inline]
+    #[allow(deprecated)]
     fn next(&mut self) -> Option<&'a str> {
         Iterator::next(&mut self.0)
     }
index 6cbc7bf1bbc51a72b3e34a5a98e2a545b54b2094..8a27400389f4ada601d595879b3b0ed651c46ff4 100644 (file)
@@ -74,7 +74,7 @@ fn test_multi_iter() {
 fn test_counter_from_iter() {
     let it = count(0, 5).take(10);
     let xs: Vec<int> = FromIterator::from_iter(it);
-    assert!(xs == vec![0, 5, 10, 15, 20, 25, 30, 35, 40, 45]);
+    assert_eq!(xs, [0, 5, 10, 15, 20, 25, 30, 35, 40, 45]);
 }
 
 #[test]
@@ -104,7 +104,7 @@ fn test_iterator_chain() {
 fn test_filter_map() {
     let it = count(0, 1).take(10)
         .filter_map(|x| if x % 2 == 0 { Some(x*x) } else { None });
-    assert!(it.collect::<Vec<uint>>() == vec![0*0, 2*2, 4*4, 6*6, 8*8]);
+    assert_eq!(it.collect::<Vec<uint>>(), [0*0, 2*2, 4*4, 6*6, 8*8]);
 }
 
 #[test]
@@ -730,12 +730,12 @@ fn test_random_access_cycle() {
 
 #[test]
 fn test_double_ended_range() {
-    assert!((11..14).rev().collect::<Vec<_>>() == vec![13, 12, 11]);
+    assert_eq!((11..14).rev().collect::<Vec<_>>(), [13, 12, 11]);
     for _ in (10..0).rev() {
         panic!("unreachable");
     }
 
-    assert!((11..14).rev().collect::<Vec<_>>() == vec![13, 12, 11]);
+    assert_eq!((11..14).rev().collect::<Vec<_>>(), [13, 12, 11]);
     for _ in (10..0).rev() {
         panic!("unreachable");
     }
@@ -743,10 +743,9 @@ fn test_double_ended_range() {
 
 #[test]
 fn test_range() {
-    assert!((0..5).collect::<Vec<_>>() == vec![0, 1, 2, 3, 4]);
-    assert!((-10..-1).collect::<Vec<_>>() ==
-               vec![-10, -9, -8, -7, -6, -5, -4, -3, -2]);
-    assert!((0..5).rev().collect::<Vec<_>>() == vec![4, 3, 2, 1, 0]);
+    assert_eq!((0..5).collect::<Vec<_>>(), [0, 1, 2, 3, 4]);
+    assert_eq!((-10..-1).collect::<Vec<_>>(), [-10, -9, -8, -7, -6, -5, -4, -3, -2]);
+    assert_eq!((0..5).rev().collect::<Vec<_>>(), [4, 3, 2, 1, 0]);
     assert_eq!((200..-5).count(), 0);
     assert_eq!((200..-5).rev().count(), 0);
     assert_eq!((200..200).count(), 0);
@@ -767,38 +766,28 @@ fn test_range_inclusive() {
             vec![5, 4, 3, 2, 1, 0]);
     assert_eq!(range_inclusive(200, -5).count(), 0);
     assert_eq!(range_inclusive(200, -5).rev().count(), 0);
-    assert!(range_inclusive(200, 200).collect::<Vec<int>>() == vec![200]);
-    assert!(range_inclusive(200, 200).rev().collect::<Vec<int>>() == vec![200]);
+    assert_eq!(range_inclusive(200, 200).collect::<Vec<int>>(), [200]);
+    assert_eq!(range_inclusive(200, 200).rev().collect::<Vec<int>>(), [200]);
 }
 
 #[test]
 fn test_range_step() {
-    assert!(range_step(0, 20, 5).collect::<Vec<int>>() ==
-            vec![0, 5, 10, 15]);
-    assert!(range_step(20, 0, -5).collect::<Vec<int>>() ==
-            vec![20, 15, 10, 5]);
-    assert!(range_step(20, 0, -6).collect::<Vec<int>>() ==
-            vec![20, 14, 8, 2]);
-    assert!(range_step(200u8, 255, 50).collect::<Vec<u8>>() ==
-            vec![200u8, 250]);
-    assert!(range_step(200, -5, 1).collect::<Vec<int>>() == vec![]);
-    assert!(range_step(200, 200, 1).collect::<Vec<int>>() == vec![]);
+    assert_eq!(range_step(0, 20, 5).collect::<Vec<int>>(), [0, 5, 10, 15]);
+    assert_eq!(range_step(20, 0, -5).collect::<Vec<int>>(), [20, 15, 10, 5]);
+    assert_eq!(range_step(20, 0, -6).collect::<Vec<int>>(), [20, 14, 8, 2]);
+    assert_eq!(range_step(200u8, 255, 50).collect::<Vec<u8>>(), [200u8, 250]);
+    assert_eq!(range_step(200i, -5, 1).collect::<Vec<int>>(), []);
+    assert_eq!(range_step(200i, 200, 1).collect::<Vec<int>>(), []);
 }
 
 #[test]
 fn test_range_step_inclusive() {
-    assert!(range_step_inclusive(0, 20, 5).collect::<Vec<int>>() ==
-            vec![0, 5, 10, 15, 20]);
-    assert!(range_step_inclusive(20, 0, -5).collect::<Vec<int>>() ==
-            vec![20, 15, 10, 5, 0]);
-    assert!(range_step_inclusive(20, 0, -6).collect::<Vec<int>>() ==
-            vec![20, 14, 8, 2]);
-    assert!(range_step_inclusive(200u8, 255, 50).collect::<Vec<u8>>() ==
-            vec![200u8, 250]);
-    assert!(range_step_inclusive(200, -5, 1).collect::<Vec<int>>() ==
-            vec![]);
-    assert!(range_step_inclusive(200, 200, 1).collect::<Vec<int>>() ==
-            vec![200]);
+    assert_eq!(range_step_inclusive(0, 20, 5).collect::<Vec<int>>(), [0, 5, 10, 15, 20]);
+    assert_eq!(range_step_inclusive(20, 0, -5).collect::<Vec<int>>(), [20, 15, 10, 5, 0]);
+    assert_eq!(range_step_inclusive(20, 0, -6).collect::<Vec<int>>(), [20, 14, 8, 2]);
+    assert_eq!(range_step_inclusive(200u8, 255, 50).collect::<Vec<u8>>(), [200u8, 250]);
+    assert_eq!(range_step_inclusive(200, -5, 1).collect::<Vec<int>>(), []);
+    assert_eq!(range_step_inclusive(200, 200, 1).collect::<Vec<int>>(), [200]);
 }
 
 #[test]
index 5aeb330b78b54023ac388d83d22f5eeff636b319..73000670c61aa839e975fb39829b45eb39be2789 100644 (file)
@@ -103,7 +103,7 @@ impl Foo for int {}
     }
 
     unsafe {
-        assert!(vec![76u8] == transmute::<_, Vec<u8>>("L".to_string()));
+        assert_eq!([76u8], transmute::<_, Vec<u8>>("L".to_string()));
     }
 }
 
index be4c83d23e8b33796600da56907aa81a3a7a5a11..f60570eaaf417941f4e54b4cf6beb5b60f5b8dc2 100644 (file)
@@ -54,7 +54,7 @@ fn test_match_option_empty_vec() {
 fn test_match_option_vec() {
     let a = Some(vec![1, 2, 3, 4]);
     match a {
-        Some(v) => assert_eq!(v, vec![1, 2, 3, 4]),
+        Some(v) => assert_eq!(v, [1, 2, 3, 4]),
         None => panic!("unexpected None while matching on Some(vec![1, 2, 3, 4])")
     }
 }
index 2c6efc0040fae82bb3adb7247ae9506e7ed6b972..03f6e51a3498a4c72f1ce88639172695add9b5cc 100644 (file)
@@ -122,4 +122,9 @@ fn test_int_from_str_overflow() {
         assert_eq!("-9223372036854775808".parse::<i64>().ok(), Some(i64_val));
         assert_eq!("-9223372036854775809".parse::<i64>().ok(), None);
     }
+
+    #[test]
+    fn test_int_from_minus_sign() {
+        assert_eq!("-".parse::<i32>().ok(), None);
+    }
 }
index 57456bfb1a79ba04ce4b68c77999d37c2b507a90..c8a54ef59abda2c0676e72bd196db6090ae220c8 100644 (file)
@@ -156,7 +156,7 @@ fn test_ptr_subtraction() {
             m_ptr = m_ptr.offset(-1);
         }
 
-        assert!(xs_mut == vec![0,2,4,6,8,10,12,14,16,18]);
+        assert_eq!(xs_mut, [0,2,4,6,8,10,12,14,16,18]);
     }
 }
 
index ab7b5101e726a59f652cad6367e09f8b6c151056..10cc3ad64242720e59c2d5e9682a09d8f6aab45d 100644 (file)
@@ -36,10 +36,10 @@ pub fn test_and_then() {
 
 #[test]
 pub fn test_or() {
-    assert_eq!(op1().or(Ok(667)).unwrap(), 666);
+    assert_eq!(op1().or(Ok::<_, &'static str>(667)).unwrap(), 666);
     assert_eq!(op1().or(Err("bad")).unwrap(), 666);
 
-    assert_eq!(op2().or(Ok(667)).unwrap(), 667);
+    assert_eq!(op2().or(Ok::<_, &'static str>(667)).unwrap(), 667);
     assert_eq!(op2().or(Err("bad")).unwrap_err(), "bad");
 }
 
index 46c7730cc6470aeb852892cb2f1cf3f31506dcb3..fe73b3b44079503544c6dead2a334b86f0877f99 100644 (file)
@@ -59,16 +59,16 @@ macro_rules! test {
                 let mut iter = data.iter_mut();
                 assert_eq!(&iter[..], &other_data[..]);
                 // mutability:
-                assert!(&mut iter[] == other_data);
+                assert!(&mut iter[..] == other_data);
 
                 iter.next();
                 assert_eq!(&iter[..], &other_data[1..]);
-                assert!(&mut iter[] == &mut other_data[1..]);
+                assert!(&mut iter[..] == &mut other_data[1..]);
 
                 iter.next_back();
 
                 assert_eq!(&iter[..], &other_data[1..2]);
-                assert!(&mut iter[] == &mut other_data[1..2]);
+                assert!(&mut iter[..] == &mut other_data[1..2]);
 
                 let s = iter.into_slice();
                 assert!(s == &mut other_data[1..2]);
index beb746d25b61cf81a9b0f2d80bdd0b5383de7cd4..019f935911f7a78315f834be60b88c8928835c13 100644 (file)
@@ -22,7 +22,7 @@ fn test_pattern_deref_forward() {
 fn test_empty_match_indices() {
     let data = "aä中!";
     let vec: Vec<_> = data.match_indices("").collect();
-    assert_eq!(vec, vec![(0, 0), (1, 1), (3, 3), (6, 6), (7, 7)]);
+    assert_eq!(vec, [(0, 0), (1, 1), (3, 3), (6, 6), (7, 7)]);
 }
 
 #[test]
@@ -69,20 +69,20 @@ fn test_rsplitn_char_iterator() {
 
     let mut split: Vec<&str> = data.rsplitn(3, ' ').collect();
     split.reverse();
-    assert_eq!(split, vec!["\nMäry häd ä", "little", "lämb\nLittle", "lämb\n"]);
+    assert_eq!(split, ["\nMäry häd ä", "little", "lämb\nLittle", "lämb\n"]);
 
     let mut split: Vec<&str> = data.rsplitn(3, |c: char| c == ' ').collect();
     split.reverse();
-    assert_eq!(split, vec!["\nMäry häd ä", "little", "lämb\nLittle", "lämb\n"]);
+    assert_eq!(split, ["\nMäry häd ä", "little", "lämb\nLittle", "lämb\n"]);
 
     // Unicode
     let mut split: Vec<&str> = data.rsplitn(3, 'ä').collect();
     split.reverse();
-    assert_eq!(split, vec!["\nMäry häd ", " little l", "mb\nLittle l", "mb\n"]);
+    assert_eq!(split, ["\nMäry häd ", " little l", "mb\nLittle l", "mb\n"]);
 
     let mut split: Vec<&str> = data.rsplitn(3, |c: char| c == 'ä').collect();
     split.reverse();
-    assert_eq!(split, vec!["\nMäry häd ", " little l", "mb\nLittle l", "mb\n"]);
+    assert_eq!(split, ["\nMäry häd ", " little l", "mb\nLittle l", "mb\n"]);
 }
 
 #[test]
@@ -90,33 +90,33 @@ fn test_split_char_iterator() {
     let data = "\nMäry häd ä little lämb\nLittle lämb\n";
 
     let split: Vec<&str> = data.split(' ').collect();
-    assert_eq!( split, vec!["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]);
+    assert_eq!( split, ["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]);
 
     let mut rsplit: Vec<&str> = data.split(' ').rev().collect();
     rsplit.reverse();
-    assert_eq!(rsplit, vec!["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]);
+    assert_eq!(rsplit, ["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]);
 
     let split: Vec<&str> = data.split(|c: char| c == ' ').collect();
-    assert_eq!( split, vec!["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]);
+    assert_eq!( split, ["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]);
 
     let mut rsplit: Vec<&str> = data.split(|c: char| c == ' ').rev().collect();
     rsplit.reverse();
-    assert_eq!(rsplit, vec!["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]);
+    assert_eq!(rsplit, ["\nMäry", "häd", "ä", "little", "lämb\nLittle", "lämb\n"]);
 
     // Unicode
     let split: Vec<&str> = data.split('ä').collect();
-    assert_eq!( split, vec!["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]);
+    assert_eq!( split, ["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]);
 
     let mut rsplit: Vec<&str> = data.split('ä').rev().collect();
     rsplit.reverse();
-    assert_eq!(rsplit, vec!["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]);
+    assert_eq!(rsplit, ["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]);
 
     let split: Vec<&str> = data.split(|c: char| c == 'ä').collect();
-    assert_eq!( split, vec!["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]);
+    assert_eq!( split, ["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]);
 
     let mut rsplit: Vec<&str> = data.split(|c: char| c == 'ä').rev().collect();
     rsplit.reverse();
-    assert_eq!(rsplit, vec!["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]);
+    assert_eq!(rsplit, ["\nM", "ry h", "d ", " little l", "mb\nLittle l", "mb\n"]);
 }
 
 #[test]
@@ -125,18 +125,18 @@ fn test_rev_split_char_iterator_no_trailing() {
 
     let mut split: Vec<&str> = data.split('\n').rev().collect();
     split.reverse();
-    assert_eq!(split, vec!["", "Märy häd ä little lämb", "Little lämb", ""]);
+    assert_eq!(split, ["", "Märy häd ä little lämb", "Little lämb", ""]);
 
     let mut split: Vec<&str> = data.split_terminator('\n').rev().collect();
     split.reverse();
-    assert_eq!(split, vec!["", "Märy häd ä little lämb", "Little lämb"]);
+    assert_eq!(split, ["", "Märy häd ä little lämb", "Little lämb"]);
 }
 
 #[test]
 fn test_utf16_code_units() {
     use unicode::str::Utf16Encoder;
     assert_eq!(Utf16Encoder::new(vec!['é', '\u{1F4A9}'].into_iter()).collect::<Vec<u16>>(),
-               vec![0xE9, 0xD83D, 0xDCA9])
+               [0xE9, 0xD83D, 0xDCA9])
 }
 
 #[test]
index 24660b3f396c105031903ceb43822ff6b690cb66..2ce52cdec2560a92ee1e32559e2ae4392b73e37e 100644 (file)
@@ -27,6 +27,7 @@
 #![feature(int_uint)]
 #![feature(libc)]
 #![feature(staged_api)]
+#![feature(unique)]
 
 #[cfg(test)] #[macro_use] extern crate log;
 
index 8d8f6a406f5d4e1a834961664061fbf4d263fa49..74a95b3aba056cdd194a1637b1950d5f5ba5bafa 100644 (file)
@@ -1362,7 +1362,6 @@ pub mod posix88 {
                 use types::os::arch::c95::{c_long};
                 pub type off_t = i64;
                 pub type dev_t = i32;
-                pub type ino_t = u64;
                 pub type pid_t = i32;
                 pub type uid_t = u32;
                 pub type gid_t = u32;
index b1d292ebaa8830b7fb58a40caa63794dd424f107..4a9a9bd40600b73d736244b022a68a46cab331fb 100644 (file)
 #[macro_export]
 macro_rules! log {
     ($lvl:expr, $($arg:tt)+) => ({
-        #[cfg(stage0)]
-        static LOC: ::log::LogLocation = ::log::LogLocation {
-            line: line!() as u32,
-            file: file!(),
-            module_path: module_path!(),
-        };
-        #[cfg(not(stage0))]
         static LOC: ::log::LogLocation = ::log::LogLocation {
             line: line!(),
             file: file!(),
index f4d3e975b75b9e25d187a4fe64e8c86a1608c9eb..06828911471466d2e1e3eb58786eb04567aacf1a 100644 (file)
@@ -134,11 +134,7 @@ pub trait Reseeder<R> {
 /// Reseed an RNG using a `Default` instance. This reseeds by
 /// replacing the RNG with the result of a `Default::default` call.
 #[derive(Copy)]
-pub struct ReseedWithDefault { __hack: [u8; 0] }
-// FIXME(#21721) used to be an unit struct but that can cause
-// certain LLVM versions to abort during optimizations.
-#[allow(non_upper_case_globals)]
-pub const ReseedWithDefault: ReseedWithDefault = ReseedWithDefault { __hack: [] };
+pub struct ReseedWithDefault;
 
 impl<R: Rng + Default> Reseeder<R> for ReseedWithDefault {
     fn reseed(&mut self, rng: &mut R) {
index 230fda11ab5ac58c9744787fd73a65826485e35c..c52465a889907b57c4357f19d4a801677ab8b6c5 100644 (file)
@@ -45,7 +45,7 @@ fn combine(seek: SeekStyle, cur: uint, end: uint, offset: i64) -> IoResult<u64>
 /// let mut w = SeekableMemWriter::new();
 /// w.write(&[0, 1, 2]);
 ///
-/// assert_eq!(w.unwrap(), vec!(0, 1, 2));
+/// assert_eq!(w.unwrap(), [0, 1, 2]);
 /// ```
 pub struct SeekableMemWriter {
     buf: Vec<u8>,
index fe9a81bb7c984f60d7b2b40e12b9f9106ddfd4ce..0b95b38722c18ec834cb268e7439efb09cf59d2d 100644 (file)
@@ -39,7 +39,7 @@
 #![feature(unsafe_destructor)]
 #![feature(staged_api)]
 #![feature(std_misc)]
-#![feature(unicode)]
+#![feature(os)]
 #![cfg_attr(test, feature(test))]
 
 extern crate arena;
index 8a00622486ddc294a9cdd9506f1375cf8e3f8148..44718d1c5251dbfff6cfe42f55d9e7ee67d31df4 100644 (file)
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-//! Lints built in to rustc.
+//! Some lints that are built in to the compiler.
 //!
-//! This is a sibling of `lint::context` in order to ensure that
-//! lints implemented here use the same public API as lint plugins.
-//!
-//! To add a new lint to rustc, declare it here using `declare_lint!()`.
-//! Then add code to emit the new lint in the appropriate circumstances.
-//! You can do that in an existing `LintPass` if it makes sense, or in
-//! a new `LintPass`, or using `Session::add_lint` elsewhere in the
-//! compiler. Only do the latter if the check can't be written cleanly
-//! as a `LintPass`.
-//!
-//! If you define a new `LintPass`, you will also need to add it to the
-//! `add_builtin!` or `add_builtin_with_new!` invocation in `context.rs`.
-//! Use the former for unit-like structs and the latter for structs with
-//! a `pub fn new()`.
-use self::MethodContext::*;
-
-use metadata::{csearch, decoder};
-use middle::def::*;
-use middle::subst::Substs;
-use middle::ty::{self, Ty};
-use middle::{def, pat_util, stability};
-use middle::const_eval::{eval_const_expr_partial, const_int, const_uint};
-use middle::cfg;
-use util::ppaux::{ty_to_string};
-use util::nodemap::{FnvHashMap, NodeSet};
-use lint::{Level, Context, LintPass, LintArray, Lint};
-
-use std::collections::BitSet;
-use std::collections::hash_map::Entry::{Occupied, Vacant};
-use std::num::SignedInt;
-use std::{cmp, slice};
-use std::{i8, i16, i32, i64, u8, u16, u32, u64, f32, f64};
-
-use syntax::{abi, ast, ast_map};
-use syntax::ast_util::is_shift_binop;
-use syntax::attr::{self, AttrMetaMethods};
-use syntax::codemap::{self, Span};
-use syntax::feature_gate::{KNOWN_ATTRIBUTES, AttributeType};
-use syntax::parse::token;
-use syntax::ast::{TyIs, TyUs, TyI8, TyU8, TyI16, TyU16, TyI32, TyU32, TyI64, TyU64};
-use syntax::ast_util;
-use syntax::ptr::P;
-use syntax::visit::{self, Visitor};
-
-declare_lint! {
-    WHILE_TRUE,
-    Warn,
-    "suggest using `loop { }` instead of `while true { }`"
-}
-
-#[derive(Copy)]
-pub struct WhileTrue;
-
-impl LintPass for WhileTrue {
-    fn get_lints(&self) -> LintArray {
-        lint_array!(WHILE_TRUE)
-    }
-
-    fn check_expr(&mut self, cx: &Context, e: &ast::Expr) {
-        if let ast::ExprWhile(ref cond, _, _) = e.node {
-            if let ast::ExprLit(ref lit) = cond.node {
-                if let ast::LitBool(true) = lit.node {
-                    cx.span_lint(WHILE_TRUE, e.span,
-                                 "denote infinite loops with loop { ... }");
-                }
-            }
-        }
-    }
-}
-
-declare_lint! {
-    UNUSED_TYPECASTS,
-    Allow,
-    "detects unnecessary type casts that can be removed"
-}
-
-#[derive(Copy)]
-pub struct UnusedCasts;
-
-impl LintPass for UnusedCasts {
-    fn get_lints(&self) -> LintArray {
-        lint_array!(UNUSED_TYPECASTS)
-    }
-
-    fn check_expr(&mut self, cx: &Context, e: &ast::Expr) {
-        if let ast::ExprCast(ref expr, ref ty) = e.node {
-            let t_t = ty::expr_ty(cx.tcx, e);
-            if ty::expr_ty(cx.tcx, &**expr) == t_t {
-                cx.span_lint(UNUSED_TYPECASTS, ty.span, "unnecessary type cast");
-            }
-        }
-    }
-}
-
-declare_lint! {
-    UNSIGNED_NEGATION,
-    Warn,
-    "using an unary minus operator on unsigned type"
-}
-
-declare_lint! {
-    UNUSED_COMPARISONS,
-    Warn,
-    "comparisons made useless by limits of the types involved"
-}
-
-declare_lint! {
-    OVERFLOWING_LITERALS,
-    Warn,
-    "literal out of range for its type"
-}
-
-declare_lint! {
-    EXCEEDING_BITSHIFTS,
-    Deny,
-    "shift exceeds the type's number of bits"
-}
-
-#[derive(Copy)]
-pub struct TypeLimits {
-    /// Id of the last visited negated expression
-    negated_expr_id: ast::NodeId,
-}
-
-impl TypeLimits {
-    pub fn new() -> TypeLimits {
-        TypeLimits {
-            negated_expr_id: -1,
-        }
-    }
-}
-
-impl LintPass for TypeLimits {
-    fn get_lints(&self) -> LintArray {
-        lint_array!(UNSIGNED_NEGATION, UNUSED_COMPARISONS, OVERFLOWING_LITERALS,
-                    EXCEEDING_BITSHIFTS)
-    }
-
-    fn check_expr(&mut self, cx: &Context, e: &ast::Expr) {
-        match e.node {
-            ast::ExprUnary(ast::UnNeg, ref expr) => {
-                match expr.node  {
-                    ast::ExprLit(ref lit) => {
-                        match lit.node {
-                            ast::LitInt(_, ast::UnsignedIntLit(_)) => {
-                                cx.span_lint(UNSIGNED_NEGATION, e.span,
-                                             "negation of unsigned int literal may \
-                                             be unintentional");
-                            },
-                            _ => ()
-                        }
-                    },
-                    _ => {
-                        let t = ty::expr_ty(cx.tcx, &**expr);
-                        match t.sty {
-                            ty::ty_uint(_) => {
-                                cx.span_lint(UNSIGNED_NEGATION, e.span,
-                                             "negation of unsigned int variable may \
-                                             be unintentional");
-                            },
-                            _ => ()
-                        }
-                    }
-                };
-                // propagate negation, if the negation itself isn't negated
-                if self.negated_expr_id != e.id {
-                    self.negated_expr_id = expr.id;
-                }
-            },
-            ast::ExprParen(ref expr) if self.negated_expr_id == e.id => {
-                self.negated_expr_id = expr.id;
-            },
-            ast::ExprBinary(binop, ref l, ref r) => {
-                if is_comparison(binop) && !check_limits(cx.tcx, binop, &**l, &**r) {
-                    cx.span_lint(UNUSED_COMPARISONS, e.span,
-                                 "comparison is useless due to type limits");
-                }
-
-                if is_shift_binop(binop.node) {
-                    let opt_ty_bits = match ty::expr_ty(cx.tcx, &**l).sty {
-                        ty::ty_int(t) => Some(int_ty_bits(t, cx.sess().target.int_type)),
-                        ty::ty_uint(t) => Some(uint_ty_bits(t, cx.sess().target.uint_type)),
-                        _ => None
-                    };
-
-                    if let Some(bits) = opt_ty_bits {
-                        let exceeding = if let ast::ExprLit(ref lit) = r.node {
-                            if let ast::LitInt(shift, _) = lit.node { shift >= bits }
-                            else { false }
-                        } else {
-                            match eval_const_expr_partial(cx.tcx, &**r, Some(cx.tcx.types.uint)) {
-                                Ok(const_int(shift)) => { shift as u64 >= bits },
-                                Ok(const_uint(shift)) => { shift >= bits },
-                                _ => { false }
-                            }
-                        };
-                        if exceeding {
-                            cx.span_lint(EXCEEDING_BITSHIFTS, e.span,
-                                         "bitshift exceeds the type's number of bits");
-                        }
-                    };
-                }
-            },
-            ast::ExprLit(ref lit) => {
-                match ty::expr_ty(cx.tcx, e).sty {
-                    ty::ty_int(t) => {
-                        match lit.node {
-                            ast::LitInt(v, ast::SignedIntLit(_, ast::Plus)) |
-                            ast::LitInt(v, ast::UnsuffixedIntLit(ast::Plus)) => {
-                                let int_type = if let ast::TyIs(_) = t {
-                                    cx.sess().target.int_type
-                                } else { t };
-                                let (min, max) = int_ty_range(int_type);
-                                let negative = self.negated_expr_id == e.id;
-
-                                if (negative && v > (min.abs() as u64)) ||
-                                   (!negative && v > (max.abs() as u64)) {
-                                    cx.span_lint(OVERFLOWING_LITERALS, e.span,
-                                                 &*format!("literal out of range for {:?}", t));
-                                    return;
-                                }
-                            }
-                            _ => panic!()
-                        };
-                    },
-                    ty::ty_uint(t) => {
-                        let uint_type = if let ast::TyUs(_) = t {
-                            cx.sess().target.uint_type
-                        } else { t };
-                        let (min, max) = uint_ty_range(uint_type);
-                        let lit_val: u64 = match lit.node {
-                            ast::LitByte(_v) => return,  // _v is u8, within range by definition
-                            ast::LitInt(v, _) => v,
-                            _ => panic!()
-                        };
-                        if  lit_val < min || lit_val > max {
-                            cx.span_lint(OVERFLOWING_LITERALS, e.span,
-                                         &*format!("literal out of range for {:?}", t));
-                        }
-                    },
-                    ty::ty_float(t) => {
-                        let (min, max) = float_ty_range(t);
-                        let lit_val: f64 = match lit.node {
-                            ast::LitFloat(ref v, _) |
-                            ast::LitFloatUnsuffixed(ref v) => {
-                                match v.parse().ok() {
-                                    Some(f) => f,
-                                    None => return
-                                }
-                            }
-                            _ => panic!()
-                        };
-                        if lit_val < min || lit_val > max {
-                            cx.span_lint(OVERFLOWING_LITERALS, e.span,
-                                         &*format!("literal out of range for {:?}", t));
-                        }
-                    },
-                    _ => ()
-                };
-            },
-            _ => ()
-        };
-
-        fn is_valid<T:cmp::PartialOrd>(binop: ast::BinOp, v: T,
-                                min: T, max: T) -> bool {
-            match binop.node {
-                ast::BiLt => v >  min && v <= max,
-                ast::BiLe => v >= min && v <  max,
-                ast::BiGt => v >= min && v <  max,
-                ast::BiGe => v >  min && v <= max,
-                ast::BiEq | ast::BiNe => v >= min && v <= max,
-                _ => panic!()
-            }
-        }
-
-        fn rev_binop(binop: ast::BinOp) -> ast::BinOp {
-            codemap::respan(binop.span, match binop.node {
-                ast::BiLt => ast::BiGt,
-                ast::BiLe => ast::BiGe,
-                ast::BiGt => ast::BiLt,
-                ast::BiGe => ast::BiLe,
-                _ => return binop
-            })
-        }
-
-        // for int & uint, be conservative with the warnings, so that the
-        // warnings are consistent between 32- and 64-bit platforms
-        fn int_ty_range(int_ty: ast::IntTy) -> (i64, i64) {
-            match int_ty {
-                ast::TyIs(_) =>    (i64::MIN,        i64::MAX),
-                ast::TyI8 =>   (i8::MIN  as i64, i8::MAX  as i64),
-                ast::TyI16 =>  (i16::MIN as i64, i16::MAX as i64),
-                ast::TyI32 =>  (i32::MIN as i64, i32::MAX as i64),
-                ast::TyI64 =>  (i64::MIN,        i64::MAX)
-            }
-        }
-
-        fn uint_ty_range(uint_ty: ast::UintTy) -> (u64, u64) {
-            match uint_ty {
-                ast::TyUs(_) =>   (u64::MIN,         u64::MAX),
-                ast::TyU8 =>  (u8::MIN   as u64, u8::MAX   as u64),
-                ast::TyU16 => (u16::MIN  as u64, u16::MAX  as u64),
-                ast::TyU32 => (u32::MIN  as u64, u32::MAX  as u64),
-                ast::TyU64 => (u64::MIN,         u64::MAX)
-            }
-        }
-
-        fn float_ty_range(float_ty: ast::FloatTy) -> (f64, f64) {
-            match float_ty {
-                ast::TyF32  => (f32::MIN as f64, f32::MAX as f64),
-                ast::TyF64  => (f64::MIN,        f64::MAX)
-            }
-        }
-
-        fn int_ty_bits(int_ty: ast::IntTy, target_int_ty: ast::IntTy) -> u64 {
-            match int_ty {
-                ast::TyIs(_) =>    int_ty_bits(target_int_ty, target_int_ty),
-                ast::TyI8 =>   i8::BITS  as u64,
-                ast::TyI16 =>  i16::BITS as u64,
-                ast::TyI32 =>  i32::BITS as u64,
-                ast::TyI64 =>  i64::BITS as u64
-            }
-        }
-
-        fn uint_ty_bits(uint_ty: ast::UintTy, target_uint_ty: ast::UintTy) -> u64 {
-            match uint_ty {
-                ast::TyUs(_) =>    uint_ty_bits(target_uint_ty, target_uint_ty),
-                ast::TyU8 =>   u8::BITS  as u64,
-                ast::TyU16 =>  u16::BITS as u64,
-                ast::TyU32 =>  u32::BITS as u64,
-                ast::TyU64 =>  u64::BITS as u64
-            }
-        }
-
-        fn check_limits(tcx: &ty::ctxt, binop: ast::BinOp,
-                        l: &ast::Expr, r: &ast::Expr) -> bool {
-            let (lit, expr, swap) = match (&l.node, &r.node) {
-                (&ast::ExprLit(_), _) => (l, r, true),
-                (_, &ast::ExprLit(_)) => (r, l, false),
-                _ => return true
-            };
-            // Normalize the binop so that the literal is always on the RHS in
-            // the comparison
-            let norm_binop = if swap { rev_binop(binop) } else { binop };
-            match ty::expr_ty(tcx, expr).sty {
-                ty::ty_int(int_ty) => {
-                    let (min, max) = int_ty_range(int_ty);
-                    let lit_val: i64 = match lit.node {
-                        ast::ExprLit(ref li) => match li.node {
-                            ast::LitInt(v, ast::SignedIntLit(_, ast::Plus)) |
-                            ast::LitInt(v, ast::UnsuffixedIntLit(ast::Plus)) => v as i64,
-                            ast::LitInt(v, ast::SignedIntLit(_, ast::Minus)) |
-                            ast::LitInt(v, ast::UnsuffixedIntLit(ast::Minus)) => -(v as i64),
-                            _ => return true
-                        },
-                        _ => panic!()
-                    };
-                    is_valid(norm_binop, lit_val, min, max)
-                }
-                ty::ty_uint(uint_ty) => {
-                    let (min, max): (u64, u64) = uint_ty_range(uint_ty);
-                    let lit_val: u64 = match lit.node {
-                        ast::ExprLit(ref li) => match li.node {
-                            ast::LitInt(v, _) => v,
-                            _ => return true
-                        },
-                        _ => panic!()
-                    };
-                    is_valid(norm_binop, lit_val, min, max)
-                }
-                _ => true
-            }
-        }
-
-        fn is_comparison(binop: ast::BinOp) -> bool {
-            match binop.node {
-                ast::BiEq | ast::BiLt | ast::BiLe |
-                ast::BiNe | ast::BiGe | ast::BiGt => true,
-                _ => false
-            }
-        }
-    }
-}
-
-declare_lint! {
-    IMPROPER_CTYPES,
-    Warn,
-    "proper use of libc types in foreign modules"
-}
-
-struct ImproperCTypesVisitor<'a, 'tcx: 'a> {
-    cx: &'a Context<'a, 'tcx>
-}
-
-impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
-    fn check_def(&mut self, sp: Span, ty_id: ast::NodeId, path_id: ast::NodeId) {
-        match self.cx.tcx.def_map.borrow()[path_id].clone() {
-            def::DefPrimTy(ast::TyInt(ast::TyIs(_))) => {
-                self.cx.span_lint(IMPROPER_CTYPES, sp,
-                                  "found rust type `isize` in foreign module, while \
-                                   libc::c_int or libc::c_long should be used");
-            }
-            def::DefPrimTy(ast::TyUint(ast::TyUs(_))) => {
-                self.cx.span_lint(IMPROPER_CTYPES, sp,
-                                  "found rust type `usize` in foreign module, while \
-                                   libc::c_uint or libc::c_ulong should be used");
-            }
-            def::DefTy(..) => {
-                let tty = match self.cx.tcx.ast_ty_to_ty_cache.borrow().get(&ty_id) {
-                    Some(&ty::atttce_resolved(t)) => t,
-                    _ => panic!("ast_ty_to_ty_cache was incomplete after typeck!")
-                };
-
-                if !ty::is_ffi_safe(self.cx.tcx, tty) {
-                    self.cx.span_lint(IMPROPER_CTYPES, sp,
-                                      "found type without foreign-function-safe
-                                      representation annotation in foreign module, consider \
-                                      adding a #[repr(...)] attribute to the type");
-                }
-            }
-            _ => ()
-        }
-    }
-}
-
-impl<'a, 'tcx, 'v> Visitor<'v> for ImproperCTypesVisitor<'a, 'tcx> {
-    fn visit_ty(&mut self, ty: &ast::Ty) {
-        match ty.node {
-            ast::TyPath(_, id) => self.check_def(ty.span, ty.id, id),
-            _ => (),
-        }
-        visit::walk_ty(self, ty);
-    }
-}
-
-#[derive(Copy)]
-pub struct ImproperCTypes;
-
-impl LintPass for ImproperCTypes {
-    fn get_lints(&self) -> LintArray {
-        lint_array!(IMPROPER_CTYPES)
-    }
-
-    fn check_item(&mut self, cx: &Context, it: &ast::Item) {
-        fn check_ty(cx: &Context, ty: &ast::Ty) {
-            let mut vis = ImproperCTypesVisitor { cx: cx };
-            vis.visit_ty(ty);
-        }
-
-        fn check_foreign_fn(cx: &Context, decl: &ast::FnDecl) {
-            for input in &decl.inputs {
-                check_ty(cx, &*input.ty);
-            }
-            if let ast::Return(ref ret_ty) = decl.output {
-                check_ty(cx, &**ret_ty);
-            }
-        }
-
-        match it.node {
-            ast::ItemForeignMod(ref nmod) if nmod.abi != abi::RustIntrinsic => {
-                for ni in &nmod.items {
-                    match ni.node {
-                        ast::ForeignItemFn(ref decl, _) => check_foreign_fn(cx, &**decl),
-                        ast::ForeignItemStatic(ref t, _) => check_ty(cx, &**t)
-                    }
-                }
-            }
-            _ => (),
-        }
-    }
-}
-
-declare_lint! {
-    BOX_POINTERS,
-    Allow,
-    "use of owned (Box type) heap memory"
-}
-
-#[derive(Copy)]
-pub struct BoxPointers;
-
-impl BoxPointers {
-    fn check_heap_type<'a, 'tcx>(&self, cx: &Context<'a, 'tcx>,
-                                 span: Span, ty: Ty<'tcx>) {
-        let mut n_uniq: usize = 0;
-        ty::fold_ty(cx.tcx, ty, |t| {
-            match t.sty {
-                ty::ty_uniq(_) => {
-                    n_uniq += 1;
-                }
-                _ => ()
-            };
-            t
-        });
-
-        if n_uniq > 0 {
-            let s = ty_to_string(cx.tcx, ty);
-            let m = format!("type uses owned (Box type) pointers: {}", s);
-            cx.span_lint(BOX_POINTERS, span, &m[..]);
-        }
-    }
-}
-
-impl LintPass for BoxPointers {
-    fn get_lints(&self) -> LintArray {
-        lint_array!(BOX_POINTERS)
-    }
-
-    fn check_item(&mut self, cx: &Context, it: &ast::Item) {
-        match it.node {
-            ast::ItemFn(..) |
-            ast::ItemTy(..) |
-            ast::ItemEnum(..) |
-            ast::ItemStruct(..) =>
-                self.check_heap_type(cx, it.span,
-                                     ty::node_id_to_type(cx.tcx, it.id)),
-            _ => ()
-        }
-
-        // If it's a struct, we also have to check the fields' types
-        match it.node {
-            ast::ItemStruct(ref struct_def, _) => {
-                for struct_field in &struct_def.fields {
-                    self.check_heap_type(cx, struct_field.span,
-                                         ty::node_id_to_type(cx.tcx, struct_field.node.id));
-                }
-            }
-            _ => ()
-        }
-    }
-
-    fn check_expr(&mut self, cx: &Context, e: &ast::Expr) {
-        let ty = ty::expr_ty(cx.tcx, e);
-        self.check_heap_type(cx, e.span, ty);
-    }
-}
-
-declare_lint! {
-    RAW_POINTER_DERIVE,
-    Warn,
-    "uses of #[derive] with raw pointers are rarely correct"
-}
-
-struct RawPtrDeriveVisitor<'a, 'tcx: 'a> {
-    cx: &'a Context<'a, 'tcx>
-}
-
-impl<'a, 'tcx, 'v> Visitor<'v> for RawPtrDeriveVisitor<'a, 'tcx> {
-    fn visit_ty(&mut self, ty: &ast::Ty) {
-        static MSG: &'static str = "use of `#[derive]` with a raw pointer";
-        if let ast::TyPtr(..) = ty.node {
-            self.cx.span_lint(RAW_POINTER_DERIVE, ty.span, MSG);
-        }
-        visit::walk_ty(self, ty);
-    }
-    // explicit override to a no-op to reduce code bloat
-    fn visit_expr(&mut self, _: &ast::Expr) {}
-    fn visit_block(&mut self, _: &ast::Block) {}
-}
-
-pub struct RawPointerDerive {
-    checked_raw_pointers: NodeSet,
-}
-
-impl RawPointerDerive {
-    pub fn new() -> RawPointerDerive {
-        RawPointerDerive {
-            checked_raw_pointers: NodeSet(),
-        }
-    }
-}
-
-impl LintPass for RawPointerDerive {
-    fn get_lints(&self) -> LintArray {
-        lint_array!(RAW_POINTER_DERIVE)
-    }
-
-    fn check_item(&mut self, cx: &Context, item: &ast::Item) {
-        if !attr::contains_name(&item.attrs, "automatically_derived") {
-            return
-        }
-        let did = match item.node {
-            ast::ItemImpl(_, _, _, ref t_ref_opt, _, _) => {
-                // Deriving the Copy trait does not cause a warning
-                if let &Some(ref trait_ref) = t_ref_opt {
-                    let def_id = ty::trait_ref_to_def_id(cx.tcx, trait_ref);
-                    if Some(def_id) == cx.tcx.lang_items.copy_trait() {
-                        return
-                    }
-                }
-
-                match ty::node_id_to_type(cx.tcx, item.id).sty {
-                    ty::ty_enum(did, _) => did,
-                    ty::ty_struct(did, _) => did,
-                    _ => return,
-                }
-            }
-            _ => return,
-        };
-        if !ast_util::is_local(did) { return }
-        let item = match cx.tcx.map.find(did.node) {
-            Some(ast_map::NodeItem(item)) => item,
-            _ => return,
-        };
-        if !self.checked_raw_pointers.insert(item.id) { return }
-        match item.node {
-            ast::ItemStruct(..) | ast::ItemEnum(..) => {
-                let mut visitor = RawPtrDeriveVisitor { cx: cx };
-                visit::walk_item(&mut visitor, &*item);
-            }
-            _ => {}
-        }
-    }
-}
-
-declare_lint! {
-    UNUSED_ATTRIBUTES,
-    Warn,
-    "detects attributes that were not used by the compiler"
-}
-
-#[derive(Copy)]
-pub struct UnusedAttributes;
-
-impl LintPass for UnusedAttributes {
-    fn get_lints(&self) -> LintArray {
-        lint_array!(UNUSED_ATTRIBUTES)
-    }
-
-    fn check_attribute(&mut self, cx: &Context, attr: &ast::Attribute) {
-        for &(ref name, ty) in KNOWN_ATTRIBUTES {
-            match ty {
-                AttributeType::Whitelisted
-                | AttributeType::Gated(_, _) if attr.check_name(name) => {
-                    break;
-                },
-                _ => ()
-            }
-        }
-
-        if !attr::is_used(attr) {
-            cx.span_lint(UNUSED_ATTRIBUTES, attr.span, "unused attribute");
-            if KNOWN_ATTRIBUTES.contains(&(&attr.name(), AttributeType::CrateLevel)) {
-                let msg = match attr.node.style {
-                    ast::AttrOuter => "crate-level attribute should be an inner \
-                                       attribute: add an exclamation mark: #![foo]",
-                    ast::AttrInner => "crate-level attribute should be in the \
-                                       root module",
-                };
-                cx.span_lint(UNUSED_ATTRIBUTES, attr.span, msg);
-            }
-        }
-    }
-}
-
-declare_lint! {
-    pub PATH_STATEMENTS,
-    Warn,
-    "path statements with no effect"
-}
-
-#[derive(Copy)]
-pub struct PathStatements;
-
-impl LintPass for PathStatements {
-    fn get_lints(&self) -> LintArray {
-        lint_array!(PATH_STATEMENTS)
-    }
-
-    fn check_stmt(&mut self, cx: &Context, s: &ast::Stmt) {
-        match s.node {
-            ast::StmtSemi(ref expr, _) => {
-                match expr.node {
-                    ast::ExprPath(_) => cx.span_lint(PATH_STATEMENTS, s.span,
-                                                     "path statement with no effect"),
-                    _ => ()
-                }
-            }
-            _ => ()
-        }
-    }
-}
-
-declare_lint! {
-    pub UNUSED_MUST_USE,
-    Warn,
-    "unused result of a type flagged as #[must_use]"
-}
-
-declare_lint! {
-    pub UNUSED_RESULTS,
-    Allow,
-    "unused result of an expression in a statement"
-}
-
-#[derive(Copy)]
-pub struct UnusedResults;
-
-impl LintPass for UnusedResults {
-    fn get_lints(&self) -> LintArray {
-        lint_array!(UNUSED_MUST_USE, UNUSED_RESULTS)
-    }
-
-    fn check_stmt(&mut self, cx: &Context, s: &ast::Stmt) {
-        let expr = match s.node {
-            ast::StmtSemi(ref expr, _) => &**expr,
-            _ => return
-        };
-
-        if let ast::ExprRet(..) = expr.node {
-            return;
-        }
-
-        let t = ty::expr_ty(cx.tcx, expr);
-        let mut warned = false;
-        match t.sty {
-            ty::ty_tup(ref tys) if tys.is_empty() => return,
-            ty::ty_bool => return,
-            ty::ty_struct(did, _) |
-            ty::ty_enum(did, _) => {
-                if ast_util::is_local(did) {
-                    if let ast_map::NodeItem(it) = cx.tcx.map.get(did.node) {
-                        warned |= check_must_use(cx, &it.attrs, s.span);
-                    }
-                } else {
-                    let attrs = csearch::get_item_attrs(&cx.sess().cstore, did);
-                    warned |= check_must_use(cx, &attrs[..], s.span);
-                }
-            }
-            _ => {}
-        }
-        if !warned {
-            cx.span_lint(UNUSED_RESULTS, s.span, "unused result");
-        }
-
-        fn check_must_use(cx: &Context, attrs: &[ast::Attribute], sp: Span) -> bool {
-            for attr in attrs {
-                if attr.check_name("must_use") {
-                    let mut msg = "unused result which must be used".to_string();
-                    // check for #[must_use="..."]
-                    match attr.value_str() {
-                        None => {}
-                        Some(s) => {
-                            msg.push_str(": ");
-                            msg.push_str(&s);
-                        }
-                    }
-                    cx.span_lint(UNUSED_MUST_USE, sp, &msg);
-                    return true;
-                }
-            }
-            false
-        }
-    }
-}
-
-declare_lint! {
-    pub NON_CAMEL_CASE_TYPES,
-    Warn,
-    "types, variants, traits and type parameters should have camel case names"
-}
-
-#[derive(Copy)]
-pub struct NonCamelCaseTypes;
-
-impl NonCamelCaseTypes {
-    fn check_case(&self, cx: &Context, sort: &str, ident: ast::Ident, span: Span) {
-        fn is_camel_case(ident: ast::Ident) -> bool {
-            let ident = token::get_ident(ident);
-            if ident.is_empty() { return true; }
-            let ident = ident.trim_matches('_');
-
-            // start with a non-lowercase letter rather than non-uppercase
-            // ones (some scripts don't have a concept of upper/lowercase)
-            ident.len() > 0 && !ident.char_at(0).is_lowercase() && !ident.contains('_')
-        }
-
-        fn to_camel_case(s: &str) -> String {
-            s.split('_').flat_map(|word| word.chars().enumerate().map(|(i, c)|
-                if i == 0 { c.to_uppercase() }
-                else { c }
-            )).collect()
-        }
-
-        let s = token::get_ident(ident);
-
-        if !is_camel_case(ident) {
-            let c = to_camel_case(&s);
-            let m = if c.is_empty() {
-                format!("{} `{}` should have a camel case name such as `CamelCase`", sort, s)
-            } else {
-                format!("{} `{}` should have a camel case name such as `{}`", sort, s, c)
-            };
-            cx.span_lint(NON_CAMEL_CASE_TYPES, span, &m[..]);
-        }
-    }
-}
-
-impl LintPass for NonCamelCaseTypes {
-    fn get_lints(&self) -> LintArray {
-        lint_array!(NON_CAMEL_CASE_TYPES)
-    }
-
-    fn check_item(&mut self, cx: &Context, it: &ast::Item) {
-        let has_extern_repr = it.attrs.iter().map(|attr| {
-            attr::find_repr_attrs(cx.tcx.sess.diagnostic(), attr).iter()
-                .any(|r| r == &attr::ReprExtern)
-        }).any(|x| x);
-        if has_extern_repr { return }
-
-        match it.node {
-            ast::ItemTy(..) | ast::ItemStruct(..) => {
-                self.check_case(cx, "type", it.ident, it.span)
-            }
-            ast::ItemTrait(..) => {
-                self.check_case(cx, "trait", it.ident, it.span)
-            }
-            ast::ItemEnum(ref enum_definition, _) => {
-                if has_extern_repr { return }
-                self.check_case(cx, "type", it.ident, it.span);
-                for variant in &enum_definition.variants {
-                    self.check_case(cx, "variant", variant.node.name, variant.span);
-                }
-            }
-            _ => ()
-        }
-    }
-
-    fn check_generics(&mut self, cx: &Context, it: &ast::Generics) {
-        for gen in &*it.ty_params {
-            self.check_case(cx, "type parameter", gen.ident, gen.span);
-        }
-    }
-}
-
-#[derive(PartialEq)]
-enum MethodContext {
-    TraitDefaultImpl,
-    TraitImpl,
-    PlainImpl
-}
-
-fn method_context(cx: &Context, m: &ast::Method) -> MethodContext {
-    let did = ast::DefId {
-        krate: ast::LOCAL_CRATE,
-        node: m.id
-    };
-
-    match cx.tcx.impl_or_trait_items.borrow().get(&did).cloned() {
-        None => cx.sess().span_bug(m.span, "missing method descriptor?!"),
-        Some(md) => {
-            match md {
-                ty::MethodTraitItem(md) => {
-                    match md.container {
-                        ty::TraitContainer(..) => TraitDefaultImpl,
-                        ty::ImplContainer(cid) => {
-                            match ty::impl_trait_ref(cx.tcx, cid) {
-                                Some(..) => TraitImpl,
-                                None => PlainImpl
-                            }
-                        }
-                    }
-                }
-                ty::TypeTraitItem(typedef) => {
-                    match typedef.container {
-                        ty::TraitContainer(..) => TraitDefaultImpl,
-                        ty::ImplContainer(cid) => {
-                            match ty::impl_trait_ref(cx.tcx, cid) {
-                                Some(..) => TraitImpl,
-                                None => PlainImpl
-                            }
-                        }
-                    }
-                }
-            }
-        }
-    }
-}
-
-declare_lint! {
-    pub NON_SNAKE_CASE,
-    Warn,
-    "methods, functions, lifetime parameters and modules should have snake case names"
-}
-
-#[derive(Copy)]
-pub struct NonSnakeCase;
-
-impl NonSnakeCase {
-    fn to_snake_case(mut str: &str) -> String {
-        let mut words = vec![];
-        // Preserve leading underscores
-        str = str.trim_left_matches(|c: char| {
-            if c == '_' {
-                words.push(String::new());
-                true
-            } else { false }
-        });
-        for s in str.split('_') {
-            let mut last_upper = false;
-            let mut buf = String::new();
-            if s.is_empty() { continue; }
-            for ch in s.chars() {
-                if !buf.is_empty() && buf != "'"
-                                   && ch.is_uppercase()
-                                   && !last_upper {
-                    words.push(buf);
-                    buf = String::new();
-                }
-                last_upper = ch.is_uppercase();
-                buf.push(ch.to_lowercase());
-            }
-            words.push(buf);
-        }
-        words.connect("_")
-    }
-
-    fn check_snake_case(&self, cx: &Context, sort: &str, ident: ast::Ident, span: Span) {
-        fn is_snake_case(ident: ast::Ident) -> bool {
-            let ident = token::get_ident(ident);
-            if ident.is_empty() { return true; }
-            let ident = ident.trim_left_matches('\'');
-            let ident = ident.trim_matches('_');
-
-            let mut allow_underscore = true;
-            ident.chars().all(|c| {
-                allow_underscore = match c {
-                    '_' if !allow_underscore => return false,
-                    '_' => false,
-                    c if !c.is_uppercase() => true,
-                    _ => return false,
-                };
-                true
-            })
-        }
-
-        let s = token::get_ident(ident);
-
-        if !is_snake_case(ident) {
-            let sc = NonSnakeCase::to_snake_case(&s);
-            if sc != &s[..] {
-                cx.span_lint(NON_SNAKE_CASE, span,
-                    &*format!("{} `{}` should have a snake case name such as `{}`",
-                            sort, s, sc));
-            } else {
-                cx.span_lint(NON_SNAKE_CASE, span,
-                    &*format!("{} `{}` should have a snake case name",
-                            sort, s));
-            }
-        }
-    }
-}
-
-impl LintPass for NonSnakeCase {
-    fn get_lints(&self) -> LintArray {
-        lint_array!(NON_SNAKE_CASE)
-    }
-
-    fn check_fn(&mut self, cx: &Context,
-                fk: visit::FnKind, _: &ast::FnDecl,
-                _: &ast::Block, span: Span, _: ast::NodeId) {
-        match fk {
-            visit::FkMethod(ident, _, m) => match method_context(cx, m) {
-                PlainImpl
-                    => self.check_snake_case(cx, "method", ident, span),
-                TraitDefaultImpl
-                    => self.check_snake_case(cx, "trait method", ident, span),
-                _ => (),
-            },
-            visit::FkItemFn(ident, _, _, _)
-                => self.check_snake_case(cx, "function", ident, span),
-            _ => (),
-        }
-    }
-
-    fn check_item(&mut self, cx: &Context, it: &ast::Item) {
-        if let ast::ItemMod(_) = it.node {
-            self.check_snake_case(cx, "module", it.ident, it.span);
-        }
-    }
-
-    fn check_ty_method(&mut self, cx: &Context, t: &ast::TypeMethod) {
-        self.check_snake_case(cx, "trait method", t.ident, t.span);
-    }
-
-    fn check_lifetime_def(&mut self, cx: &Context, t: &ast::LifetimeDef) {
-        self.check_snake_case(cx, "lifetime", t.lifetime.name.ident(), t.lifetime.span);
-    }
-
-    fn check_pat(&mut self, cx: &Context, p: &ast::Pat) {
-        if let &ast::PatIdent(_, ref path1, _) = &p.node {
-            if let Some(&def::DefLocal(_)) = cx.tcx.def_map.borrow().get(&p.id) {
-                self.check_snake_case(cx, "variable", path1.node, p.span);
-            }
-        }
-    }
-
-    fn check_struct_def(&mut self, cx: &Context, s: &ast::StructDef,
-            _: ast::Ident, _: &ast::Generics, _: ast::NodeId) {
-        for sf in &s.fields {
-            if let ast::StructField_ { kind: ast::NamedField(ident, _), .. } = sf.node {
-                self.check_snake_case(cx, "structure field", ident, sf.span);
-            }
-        }
-    }
-}
-
-declare_lint! {
-    pub NON_UPPER_CASE_GLOBALS,
-    Warn,
-    "static constants should have uppercase identifiers"
-}
-
-#[derive(Copy)]
-pub struct NonUpperCaseGlobals;
-
-impl NonUpperCaseGlobals {
-    fn check_upper_case(cx: &Context, sort: &str, ident: ast::Ident, span: Span) {
-        let s = token::get_ident(ident);
-
-        if s.chars().any(|c| c.is_lowercase()) {
-            let uc: String = NonSnakeCase::to_snake_case(&s).chars()
-                                           .map(|c| c.to_uppercase()).collect();
-            if uc != &s[..] {
-                cx.span_lint(NON_UPPER_CASE_GLOBALS, span,
-                    &format!("{} `{}` should have an upper case name such as `{}`",
-                             sort, s, uc));
-            } else {
-                cx.span_lint(NON_UPPER_CASE_GLOBALS, span,
-                    &format!("{} `{}` should have an upper case name",
-                             sort, s));
-            }
-        }
-    }
-}
-
-impl LintPass for NonUpperCaseGlobals {
-    fn get_lints(&self) -> LintArray {
-        lint_array!(NON_UPPER_CASE_GLOBALS)
-    }
-
-    fn check_item(&mut self, cx: &Context, it: &ast::Item) {
-        match it.node {
-            // only check static constants
-            ast::ItemStatic(_, ast::MutImmutable, _) => {
-                NonUpperCaseGlobals::check_upper_case(cx, "static constant", it.ident, it.span);
-            }
-            ast::ItemConst(..) => {
-                NonUpperCaseGlobals::check_upper_case(cx, "constant", it.ident, it.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)) {
-            (&ast::PatIdent(_, ref path1, _), Some(&def::DefConst(..))) => {
-                NonUpperCaseGlobals::check_upper_case(cx, "constant in pattern",
-                                                      path1.node, p.span);
-            }
-            _ => {}
-        }
-    }
-}
-
-declare_lint! {
-    UNUSED_PARENS,
-    Warn,
-    "`if`, `match`, `while` and `return` do not need parentheses"
-}
-
-#[derive(Copy)]
-pub struct UnusedParens;
-
-impl UnusedParens {
-    fn check_unused_parens_core(&self, cx: &Context, value: &ast::Expr, msg: &str,
-                                     struct_lit_needs_parens: bool) {
-        if let ast::ExprParen(ref inner) = value.node {
-            let necessary = struct_lit_needs_parens && contains_exterior_struct_lit(&**inner);
-            if !necessary {
-                cx.span_lint(UNUSED_PARENS, value.span,
-                             &format!("unnecessary parentheses around {}",
-                                     msg))
-            }
-        }
-
-        /// Expressions that syntactically contain an "exterior" struct
-        /// literal i.e. not surrounded by any parens or other
-        /// delimiters, e.g. `X { y: 1 }`, `X { y: 1 }.method()`, `foo
-        /// == X { y: 1 }` and `X { y: 1 } == foo` all do, but `(X {
-        /// y: 1 }) == foo` does not.
-        fn contains_exterior_struct_lit(value: &ast::Expr) -> bool {
-            match value.node {
-                ast::ExprStruct(..) => true,
-
-                ast::ExprAssign(ref lhs, ref rhs) |
-                ast::ExprAssignOp(_, ref lhs, ref rhs) |
-                ast::ExprBinary(_, ref lhs, ref rhs) => {
-                    // X { y: 1 } + X { y: 2 }
-                    contains_exterior_struct_lit(&**lhs) ||
-                        contains_exterior_struct_lit(&**rhs)
-                }
-                ast::ExprUnary(_, ref x) |
-                ast::ExprCast(ref x, _) |
-                ast::ExprField(ref x, _) |
-                ast::ExprTupField(ref x, _) |
-                ast::ExprIndex(ref x, _) => {
-                    // &X { y: 1 }, X { y: 1 }.y
-                    contains_exterior_struct_lit(&**x)
-                }
-
-                ast::ExprMethodCall(_, _, ref exprs) => {
-                    // X { y: 1 }.bar(...)
-                    contains_exterior_struct_lit(&*exprs[0])
-                }
-
-                _ => false
-            }
-        }
-    }
-}
-
-impl LintPass for UnusedParens {
-    fn get_lints(&self) -> LintArray {
-        lint_array!(UNUSED_PARENS)
-    }
-
-    fn check_expr(&mut self, cx: &Context, e: &ast::Expr) {
-        let (value, msg, struct_lit_needs_parens) = match e.node {
-            ast::ExprIf(ref cond, _, _) => (cond, "`if` condition", true),
-            ast::ExprWhile(ref cond, _, _) => (cond, "`while` condition", true),
-            ast::ExprMatch(ref head, _, source) => match source {
-                ast::MatchSource::Normal => (head, "`match` head expression", true),
-                ast::MatchSource::IfLetDesugar { .. } => (head, "`if let` head expression", true),
-                ast::MatchSource::WhileLetDesugar => (head, "`while let` head expression", true),
-                ast::MatchSource::ForLoopDesugar => (head, "`for` head expression", true),
-            },
-            ast::ExprRet(Some(ref value)) => (value, "`return` value", false),
-            ast::ExprAssign(_, ref value) => (value, "assigned value", false),
-            ast::ExprAssignOp(_, _, ref value) => (value, "assigned value", false),
-            _ => return
-        };
-        self.check_unused_parens_core(cx, &**value, msg, struct_lit_needs_parens);
-    }
-
-    fn check_stmt(&mut self, cx: &Context, s: &ast::Stmt) {
-        let (value, msg) = match s.node {
-            ast::StmtDecl(ref decl, _) => match decl.node {
-                ast::DeclLocal(ref local) => match local.init {
-                    Some(ref value) => (value, "assigned value"),
-                    None => return
-                },
-                _ => return
-            },
-            _ => return
-        };
-        self.check_unused_parens_core(cx, &**value, msg, false);
-    }
-}
-
-declare_lint! {
-    UNUSED_IMPORT_BRACES,
-    Allow,
-    "unnecessary braces around an imported item"
-}
-
-#[derive(Copy)]
-pub struct UnusedImportBraces;
-
-impl LintPass for UnusedImportBraces {
-    fn get_lints(&self) -> LintArray {
-        lint_array!(UNUSED_IMPORT_BRACES)
-    }
-
-    fn check_item(&mut self, cx: &Context, item: &ast::Item) {
-        match item.node {
-            ast::ItemUse(ref view_path) => {
-                match view_path.node {
-                    ast::ViewPathList(_, ref items) => {
-                        if items.len() == 1 {
-                            match items[0].node {
-                                ast::PathListIdent {ref name, ..} => {
-                                    let m = format!("braces around {} is unnecessary",
-                                                    &token::get_ident(*name));
-                                    cx.span_lint(UNUSED_IMPORT_BRACES, item.span,
-                                                 &m[..]);
-                                },
-                                _ => ()
-                            }
-                        }
-                    }
-                    _ => ()
-                }
-            },
-            _ => ()
-        }
-    }
-}
-
-declare_lint! {
-    NON_SHORTHAND_FIELD_PATTERNS,
-    Warn,
-    "using `Struct { x: x }` instead of `Struct { x }`"
-}
-
-#[derive(Copy)]
-pub struct NonShorthandFieldPatterns;
-
-impl LintPass for NonShorthandFieldPatterns {
-    fn get_lints(&self) -> LintArray {
-        lint_array!(NON_SHORTHAND_FIELD_PATTERNS)
-    }
-
-    fn check_pat(&mut self, cx: &Context, pat: &ast::Pat) {
-        let def_map = cx.tcx.def_map.borrow();
-        if let ast::PatStruct(_, ref v, _) = pat.node {
-            for fieldpat in v.iter()
-                             .filter(|fieldpat| !fieldpat.node.is_shorthand)
-                             .filter(|fieldpat| def_map.get(&fieldpat.node.pat.id)
-                                                == Some(&def::DefLocal(fieldpat.node.pat.id))) {
-                if let ast::PatIdent(_, ident, None) = fieldpat.node.pat.node {
-                    if ident.node.as_str() == fieldpat.node.ident.as_str() {
-                        cx.span_lint(NON_SHORTHAND_FIELD_PATTERNS, fieldpat.span,
-                                     &format!("the `{}:` in this pattern is redundant and can \
-                                              be removed", ident.node.as_str()))
-                    }
-                }
-            }
-        }
-    }
-}
-
-declare_lint! {
-    pub UNUSED_UNSAFE,
-    Warn,
-    "unnecessary use of an `unsafe` block"
-}
-
-#[derive(Copy)]
-pub struct UnusedUnsafe;
-
-impl LintPass for UnusedUnsafe {
-    fn get_lints(&self) -> LintArray {
-        lint_array!(UNUSED_UNSAFE)
-    }
-
-    fn check_expr(&mut self, cx: &Context, e: &ast::Expr) {
-        if let ast::ExprBlock(ref blk) = e.node {
-            // Don't warn about generated blocks, that'll just pollute the output.
-            if blk.rules == ast::UnsafeBlock(ast::UserProvided) &&
-                !cx.tcx.used_unsafe.borrow().contains(&blk.id) {
-                    cx.span_lint(UNUSED_UNSAFE, blk.span, "unnecessary `unsafe` block");
-            }
-        }
-    }
-}
-
-declare_lint! {
-    UNSAFE_CODE,
-    Allow,
-    "usage of `unsafe` code"
-}
-
-#[derive(Copy)]
-pub struct UnsafeCode;
-
-impl LintPass for UnsafeCode {
-    fn get_lints(&self) -> LintArray {
-        lint_array!(UNSAFE_CODE)
-    }
-
-    fn check_expr(&mut self, cx: &Context, e: &ast::Expr) {
-        if let ast::ExprBlock(ref blk) = e.node {
-            // Don't warn about generated blocks, that'll just pollute the output.
-            if blk.rules == ast::UnsafeBlock(ast::UserProvided) {
-                cx.span_lint(UNSAFE_CODE, blk.span, "usage of an `unsafe` block");
-            }
-        }
-    }
-
-    fn check_item(&mut self, cx: &Context, it: &ast::Item) {
-        use syntax::ast::Unsafety::Unsafe;
-
-        fn check_method(cx: &Context, meth: &P<ast::Method>) {
-            if let ast::Method_::MethDecl(_, _, _, _, Unsafe, _, _, _) = meth.node {
-                cx.span_lint(UNSAFE_CODE, meth.span, "implementation of an `unsafe` method");
-            }
-        }
-
-        match it.node {
-            ast::ItemFn(_, Unsafe, _, _, _) =>
-                cx.span_lint(UNSAFE_CODE, it.span, "declaration of an `unsafe` function"),
-
-            ast::ItemTrait(trait_safety, _, _, ref items) => {
-                if trait_safety == Unsafe {
-                    cx.span_lint(UNSAFE_CODE, it.span, "declaration of an `unsafe` trait");
-                }
-
-                for it in items {
-                    match *it {
-                        ast::RequiredMethod(ast::TypeMethod { unsafety: Unsafe, span, ..}) =>
-                            cx.span_lint(UNSAFE_CODE, span, "declaration of an `unsafe` method"),
-                        ast::ProvidedMethod(ref meth) => check_method(cx, meth),
-                        _ => (),
-                    }
-                }
-            },
-
-            ast::ItemImpl(impl_safety, _, _, _, _, ref impls) => {
-                if impl_safety == Unsafe {
-                    cx.span_lint(UNSAFE_CODE, it.span, "implementation of an `unsafe` trait");
-                }
-
-                for item in impls {
-                    if let ast::ImplItem::MethodImplItem(ref meth) = *item {
-                        check_method(cx, meth);
-                    }
-                }
-            },
-
-            _ => return,
-        }
-    }
-}
-
-declare_lint! {
-    pub UNUSED_MUT,
-    Warn,
-    "detect mut variables which don't need to be mutable"
-}
-
-#[derive(Copy)]
-pub struct UnusedMut;
-
-impl UnusedMut {
-    fn check_unused_mut_pat(&self, cx: &Context, pats: &[P<ast::Pat>]) {
-        // collect all mutable pattern and group their NodeIDs by their Identifier to
-        // avoid false warnings in match arms with multiple patterns
-
-        let mut mutables = FnvHashMap();
-        for p in pats {
-            pat_util::pat_bindings(&cx.tcx.def_map, &**p, |mode, id, _, path1| {
-                let ident = path1.node;
-                if let ast::BindByValue(ast::MutMutable) = mode {
-                    if !token::get_ident(ident).starts_with("_") {
-                        match mutables.entry(ident.name.usize()) {
-                            Vacant(entry) => { entry.insert(vec![id]); },
-                            Occupied(mut entry) => { entry.get_mut().push(id); },
-                        }
-                    }
-                }
-            });
-        }
-
-        let used_mutables = cx.tcx.used_mut_nodes.borrow();
-        for (_, v) in &mutables {
-            if !v.iter().any(|e| used_mutables.contains(e)) {
-                cx.span_lint(UNUSED_MUT, cx.tcx.map.span(v[0]),
-                             "variable does not need to be mutable");
-            }
-        }
-    }
-}
-
-impl LintPass for UnusedMut {
-    fn get_lints(&self) -> LintArray {
-        lint_array!(UNUSED_MUT)
-    }
-
-    fn check_expr(&mut self, cx: &Context, e: &ast::Expr) {
-        if let ast::ExprMatch(_, ref arms, _) = e.node {
-            for a in arms {
-                self.check_unused_mut_pat(cx, &a.pats)
-            }
-        }
-    }
-
-    fn check_stmt(&mut self, cx: &Context, s: &ast::Stmt) {
-        if let ast::StmtDecl(ref d, _) = s.node {
-            if let ast::DeclLocal(ref l) = d.node {
-                self.check_unused_mut_pat(cx, slice::ref_slice(&l.pat));
-            }
-        }
-    }
-
-    fn check_fn(&mut self, cx: &Context,
-                _: visit::FnKind, decl: &ast::FnDecl,
-                _: &ast::Block, _: Span, _: ast::NodeId) {
-        for a in &decl.inputs {
-            self.check_unused_mut_pat(cx, slice::ref_slice(&a.pat));
-        }
-    }
-}
-
-declare_lint! {
-    UNUSED_ALLOCATION,
-    Warn,
-    "detects unnecessary allocations that can be eliminated"
-}
-
-#[derive(Copy)]
-pub struct UnusedAllocation;
-
-impl LintPass for UnusedAllocation {
-    fn get_lints(&self) -> LintArray {
-        lint_array!(UNUSED_ALLOCATION)
-    }
-
-    fn check_expr(&mut self, cx: &Context, e: &ast::Expr) {
-        match e.node {
-            ast::ExprUnary(ast::UnUniq, _) => (),
-            _ => return
-        }
-
-        if let Some(adjustment) = cx.tcx.adjustments.borrow().get(&e.id) {
-            if let ty::AdjustDerefRef(ty::AutoDerefRef { ref autoref, .. }) = *adjustment {
-                match autoref {
-                    &Some(ty::AutoPtr(_, ast::MutImmutable, None)) => {
-                        cx.span_lint(UNUSED_ALLOCATION, e.span,
-                                     "unnecessary allocation, use & instead");
-                    }
-                    &Some(ty::AutoPtr(_, ast::MutMutable, None)) => {
-                        cx.span_lint(UNUSED_ALLOCATION, e.span,
-                                     "unnecessary allocation, use &mut instead");
-                    }
-                    _ => ()
-                }
-            }
-        }
-    }
-}
-
-declare_lint! {
-    MISSING_DOCS,
-    Allow,
-    "detects missing documentation for public members"
-}
-
-pub struct MissingDoc {
-    /// Stack of IDs of struct definitions.
-    struct_def_stack: Vec<ast::NodeId>,
-
-    /// True if inside variant definition
-    in_variant: bool,
-
-    /// Stack of whether #[doc(hidden)] is set
-    /// at each level which has lint attributes.
-    doc_hidden_stack: Vec<bool>,
-}
-
-impl MissingDoc {
-    pub fn new() -> MissingDoc {
-        MissingDoc {
-            struct_def_stack: vec!(),
-            in_variant: false,
-            doc_hidden_stack: vec!(false),
-        }
-    }
-
-    fn doc_hidden(&self) -> bool {
-        *self.doc_hidden_stack.last().expect("empty doc_hidden_stack")
-    }
-
-    fn check_missing_docs_attrs(&self,
-                               cx: &Context,
-                               id: Option<ast::NodeId>,
-                               attrs: &[ast::Attribute],
-                               sp: Span,
-                               desc: &'static str) {
-        // If we're building a test harness, then warning about
-        // documentation is probably not really relevant right now.
-        if cx.sess().opts.test { return }
-
-        // `#[doc(hidden)]` disables missing_docs check.
-        if self.doc_hidden() { return }
-
-        // Only check publicly-visible items, using the result from the privacy pass.
-        // It's an option so the crate root can also use this function (it doesn't
-        // have a NodeId).
-        if let Some(ref id) = id {
-            if !cx.exported_items.contains(id) {
-                return;
-            }
-        }
-
-        let has_doc = attrs.iter().any(|a| {
-            match a.node.value.node {
-                ast::MetaNameValue(ref name, _) if *name == "doc" => true,
-                _ => false
-            }
-        });
-        if !has_doc {
-            cx.span_lint(MISSING_DOCS, sp,
-                &format!("missing documentation for {}", desc));
-        }
-    }
-}
-
-impl LintPass for MissingDoc {
-    fn get_lints(&self) -> LintArray {
-        lint_array!(MISSING_DOCS)
-    }
-
-    fn enter_lint_attrs(&mut self, _: &Context, attrs: &[ast::Attribute]) {
-        let doc_hidden = self.doc_hidden() || attrs.iter().any(|attr| {
-            attr.check_name("doc") && match attr.meta_item_list() {
-                None => false,
-                Some(l) => attr::contains_name(&l[..], "hidden"),
-            }
-        });
-        self.doc_hidden_stack.push(doc_hidden);
-    }
-
-    fn exit_lint_attrs(&mut self, _: &Context, _: &[ast::Attribute]) {
-        self.doc_hidden_stack.pop().expect("empty doc_hidden_stack");
-    }
-
-    fn check_struct_def(&mut self, _: &Context,
-        _: &ast::StructDef, _: ast::Ident, _: &ast::Generics, id: ast::NodeId) {
-        self.struct_def_stack.push(id);
-    }
-
-    fn check_struct_def_post(&mut self, _: &Context,
-        _: &ast::StructDef, _: ast::Ident, _: &ast::Generics, id: ast::NodeId) {
-        let popped = self.struct_def_stack.pop().expect("empty struct_def_stack");
-        assert!(popped == id);
-    }
-
-    fn check_crate(&mut self, cx: &Context, krate: &ast::Crate) {
-        self.check_missing_docs_attrs(cx, None, &krate.attrs,
-                                     krate.span, "crate");
-    }
-
-    fn check_item(&mut self, cx: &Context, it: &ast::Item) {
-        let desc = match it.node {
-            ast::ItemFn(..) => "a function",
-            ast::ItemMod(..) => "a module",
-            ast::ItemEnum(..) => "an enum",
-            ast::ItemStruct(..) => "a struct",
-            ast::ItemTrait(..) => "a trait",
-            ast::ItemTy(..) => "a type alias",
-            _ => return
-        };
-        self.check_missing_docs_attrs(cx, Some(it.id), &it.attrs,
-                                     it.span, desc);
-    }
-
-    fn check_fn(&mut self, cx: &Context,
-            fk: visit::FnKind, _: &ast::FnDecl,
-            _: &ast::Block, _: Span, _: ast::NodeId) {
-        if let visit::FkMethod(_, _, m) = fk {
-            // If the method is an impl for a trait, don't doc.
-            if method_context(cx, m) == TraitImpl { return; }
-
-            // Otherwise, doc according to privacy. This will also check
-            // doc for default methods defined on traits.
-            self.check_missing_docs_attrs(cx, Some(m.id), &m.attrs,
-                                          m.span, "a method");
-        }
-    }
-
-    fn check_ty_method(&mut self, cx: &Context, tm: &ast::TypeMethod) {
-        self.check_missing_docs_attrs(cx, Some(tm.id), &tm.attrs,
-                                     tm.span, "a type method");
-    }
-
-    fn check_trait_method(&mut self, cx: &Context, it: &ast::TraitItem) {
-        if let ast::TraitItem::TypeTraitItem(ref ty) = *it {
-            let assoc_ty = &ty.ty_param;
-            self.check_missing_docs_attrs(cx, Some(assoc_ty.id), &ty.attrs,
-                                          assoc_ty.span, "an associated type");
-        }
-    }
-
-    fn check_struct_field(&mut self, cx: &Context, sf: &ast::StructField) {
-        if let ast::NamedField(_, vis) = sf.node.kind {
-            if vis == ast::Public || self.in_variant {
-                let cur_struct_def = *self.struct_def_stack.last()
-                    .expect("empty struct_def_stack");
-                self.check_missing_docs_attrs(cx, Some(cur_struct_def),
-                                              &sf.node.attrs, sf.span,
-                                              "a struct field")
-            }
-        }
-    }
-
-    fn check_variant(&mut self, cx: &Context, v: &ast::Variant, _: &ast::Generics) {
-        self.check_missing_docs_attrs(cx, Some(v.node.id), &v.node.attrs,
-                                     v.span, "a variant");
-        assert!(!self.in_variant);
-        self.in_variant = true;
-    }
-
-    fn check_variant_post(&mut self, _: &Context, _: &ast::Variant, _: &ast::Generics) {
-        assert!(self.in_variant);
-        self.in_variant = false;
-    }
-}
-
-#[derive(Copy)]
-pub struct MissingCopyImplementations;
-
-impl LintPass for MissingCopyImplementations {
-    fn get_lints(&self) -> LintArray {
-        lint_array!(MISSING_COPY_IMPLEMENTATIONS)
-    }
-
-    fn check_item(&mut self, cx: &Context, item: &ast::Item) {
-        if !cx.exported_items.contains(&item.id) {
-            return
-        }
-        if cx.tcx
-             .destructor_for_type
-             .borrow()
-             .contains_key(&ast_util::local_def(item.id)) {
-            return
-        }
-        let ty = match item.node {
-            ast::ItemStruct(_, ref ast_generics) => {
-                if ast_generics.is_parameterized() {
-                    return
-                }
-                ty::mk_struct(cx.tcx,
-                              ast_util::local_def(item.id),
-                              cx.tcx.mk_substs(Substs::empty()))
-            }
-            ast::ItemEnum(_, ref ast_generics) => {
-                if ast_generics.is_parameterized() {
-                    return
-                }
-                ty::mk_enum(cx.tcx,
-                            ast_util::local_def(item.id),
-                            cx.tcx.mk_substs(Substs::empty()))
-            }
-            _ => return,
-        };
-        let parameter_environment = ty::empty_parameter_environment(cx.tcx);
-        if !ty::type_moves_by_default(&parameter_environment, item.span, ty) {
-            return
-        }
-        if ty::can_type_implement_copy(&parameter_environment, item.span, ty).is_ok() {
-            cx.span_lint(MISSING_COPY_IMPLEMENTATIONS,
-                         item.span,
-                         "type could implement `Copy`; consider adding `impl \
-                          Copy`")
-        }
-    }
-}
-
-declare_lint! {
-    MISSING_DEBUG_IMPLEMENTATIONS,
-    Allow,
-    "detects missing implementations of fmt::Debug"
-}
-
-pub struct MissingDebugImplementations {
-    impling_types: Option<NodeSet>,
-}
-
-impl MissingDebugImplementations {
-    pub fn new() -> MissingDebugImplementations {
-        MissingDebugImplementations {
-            impling_types: None,
-        }
-    }
-}
-
-impl LintPass for MissingDebugImplementations {
-    fn get_lints(&self) -> LintArray {
-        lint_array!(MISSING_DEBUG_IMPLEMENTATIONS)
-    }
-
-    fn check_item(&mut self, cx: &Context, item: &ast::Item) {
-        if !cx.exported_items.contains(&item.id) {
-            return;
-        }
-
-        match item.node {
-            ast::ItemStruct(..) | ast::ItemEnum(..) => {},
-            _ => return,
-        }
-
-        let debug = match cx.tcx.lang_items.debug_trait() {
-            Some(debug) => debug,
-            None => return,
-        };
-
-        if self.impling_types.is_none() {
-            let impls = cx.tcx.trait_impls.borrow();
-            let impls = match impls.get(&debug) {
-                Some(impls) => {
-                    impls.borrow().iter()
-                        .filter(|d| d.krate == ast::LOCAL_CRATE)
-                        .filter_map(|d| ty::ty_to_def_id(ty::node_id_to_type(cx.tcx, d.node)))
-                        .map(|d| d.node)
-                        .collect()
-                }
-                None => NodeSet(),
-            };
-            self.impling_types = Some(impls);
-            debug!("{:?}", self.impling_types);
-        }
-
-        if !self.impling_types.as_ref().unwrap().contains(&item.id) {
-            cx.span_lint(MISSING_DEBUG_IMPLEMENTATIONS,
-                         item.span,
-                         "type does not implement `fmt::Debug`; consider adding #[derive(Debug)] \
-                          or a manual implementation")
-        }
-    }
-}
-
-declare_lint! {
-    DEPRECATED,
-    Warn,
-    "detects use of #[deprecated] items"
-}
-
-/// Checks for use of items with `#[deprecated]` attributes
-#[derive(Copy)]
-pub struct Stability;
-
-impl Stability {
-    fn lint(&self, cx: &Context, _id: ast::DefId, span: Span, stability: &Option<attr::Stability>) {
-
-        // deprecated attributes apply in-crate and cross-crate
-        let (lint, label) = match *stability {
-            Some(attr::Stability { deprecated_since: Some(_), .. }) =>
-                (DEPRECATED, "deprecated"),
-            _ => return
-        };
-
-        output(cx, span, stability, lint, label);
-
-        fn output(cx: &Context, span: Span, stability: &Option<attr::Stability>,
-                  lint: &'static Lint, label: &'static str) {
-            let msg = match *stability {
-                Some(attr::Stability { reason: Some(ref s), .. }) => {
-                    format!("use of {} item: {}", label, *s)
-                }
-                _ => format!("use of {} item", label)
-            };
-
-            cx.span_lint(lint, span, &msg[..]);
-        }
-    }
-}
-
-impl LintPass for Stability {
-    fn get_lints(&self) -> LintArray {
-        lint_array!(DEPRECATED)
-    }
-
-    fn check_item(&mut self, cx: &Context, item: &ast::Item) {
-        stability::check_item(cx.tcx, item, false,
-                              &mut |id, sp, stab| self.lint(cx, id, sp, stab));
-    }
-
-    fn check_expr(&mut self, cx: &Context, e: &ast::Expr) {
-        stability::check_expr(cx.tcx, e,
-                              &mut |id, sp, stab| self.lint(cx, id, sp, stab));
-    }
-
-    fn check_path(&mut self, cx: &Context, path: &ast::Path, id: ast::NodeId) {
-        stability::check_path(cx.tcx, path, id,
-                              &mut |id, sp, stab| self.lint(cx, id, sp, stab));
-    }
-}
-
-declare_lint! {
-    pub UNCONDITIONAL_RECURSION,
-    Warn,
-    "functions that cannot return without calling themselves"
-}
-
-#[derive(Copy)]
-pub struct UnconditionalRecursion;
-
-
-impl LintPass for UnconditionalRecursion {
-    fn get_lints(&self) -> LintArray {
-        lint_array![UNCONDITIONAL_RECURSION]
-    }
-
-    fn check_fn(&mut self, cx: &Context, fn_kind: visit::FnKind, _: &ast::FnDecl,
-                blk: &ast::Block, sp: Span, id: ast::NodeId) {
-        type F = for<'tcx> fn(&ty::ctxt<'tcx>,
-                              ast::NodeId, ast::NodeId, ast::Ident, ast::NodeId) -> bool;
-
-        let (name, checker) = match fn_kind {
-            visit::FkItemFn(name, _, _, _) => (name, id_refers_to_this_fn as F),
-            visit::FkMethod(name, _, _) => (name, id_refers_to_this_method as F),
-            // closures can't recur, so they don't matter.
-            visit::FkFnBlock => return
-        };
-
-        let impl_def_id = ty::impl_of_method(cx.tcx, ast_util::local_def(id))
-            .unwrap_or(ast_util::local_def(ast::DUMMY_NODE_ID));
-        assert!(ast_util::is_local(impl_def_id));
-        let impl_node_id = impl_def_id.node;
-
-        // Walk through this function (say `f`) looking to see if
-        // every possible path references itself, i.e. the function is
-        // called recursively unconditionally. This is done by trying
-        // to find a path from the entry node to the exit node that
-        // *doesn't* call `f` by traversing from the entry while
-        // pretending that calls of `f` are sinks (i.e. ignoring any
-        // exit edges from them).
-        //
-        // NB. this has an edge case with non-returning statements,
-        // like `loop {}` or `panic!()`: control flow never reaches
-        // the exit node through these, so one can have a function
-        // that never actually calls itselfs but is still picked up by
-        // this lint:
-        //
-        //     fn f(cond: bool) {
-        //         if !cond { panic!() } // could come from `assert!(cond)`
-        //         f(false)
-        //     }
-        //
-        // In general, functions of that form may be able to call
-        // itself a finite number of times and then diverge. The lint
-        // considers this to be an error for two reasons, (a) it is
-        // easier to implement, and (b) it seems rare to actually want
-        // to have behaviour like the above, rather than
-        // e.g. accidentally recurring after an assert.
-
-        let cfg = cfg::CFG::new(cx.tcx, blk);
+//! These are the built-in lints that are emitted direct in the main
+//! compiler code, rather than using their own custom pass. Those
+//! lints are all available in `rustc_lint::builtin`.
 
-        let mut work_queue = vec![cfg.entry];
-        let mut reached_exit_without_self_call = false;
-        let mut self_call_spans = vec![];
-        let mut visited = BitSet::new();
-
-        while let Some(idx) = work_queue.pop() {
-            let cfg_id = idx.node_id();
-            if idx == cfg.exit {
-                // found a path!
-                reached_exit_without_self_call = true;
-                break
-            } else if visited.contains(&cfg_id) {
-                // already done
-                continue
-            }
-            visited.insert(cfg_id);
-            let node_id = cfg.graph.node_data(idx).id();
-
-            // is this a recursive call?
-            if node_id != ast::DUMMY_NODE_ID && checker(cx.tcx, impl_node_id, id, name, node_id) {
-
-                self_call_spans.push(cx.tcx.map.span(node_id));
-                // this is a self call, so we shouldn't explore past
-                // this node in the CFG.
-                continue
-            }
-            // add the successors of this node to explore the graph further.
-            cfg.graph.each_outgoing_edge(idx, |_, edge| {
-                let target_idx = edge.target();
-                let target_cfg_id = target_idx.node_id();
-                if !visited.contains(&target_cfg_id) {
-                    work_queue.push(target_idx)
-                }
-                true
-            });
-        }
-
-        // check the number of sell calls because a function that
-        // doesn't return (e.g. calls a `-> !` function or `loop { /*
-        // no break */ }`) shouldn't be linted unless it actually
-        // recurs.
-        if !reached_exit_without_self_call && self_call_spans.len() > 0 {
-            cx.span_lint(UNCONDITIONAL_RECURSION, sp,
-                         "function cannot return without recurring");
-
-            // FIXME #19668: these could be span_lint_note's instead of this manual guard.
-            if cx.current_level(UNCONDITIONAL_RECURSION) != Level::Allow {
-                let sess = cx.sess();
-                // offer some help to the programmer.
-                for call in &self_call_spans {
-                    sess.span_note(*call, "recursive call site")
-                }
-                sess.span_help(sp, "a `loop` may express intention better if this is on purpose")
-            }
-        }
-
-        // all done
-        return;
-
-        // Functions for identifying if the given NodeId `id`
-        // represents a call to the function `fn_id`/method
-        // `method_id`.
-
-        fn id_refers_to_this_fn<'tcx>(tcx: &ty::ctxt<'tcx>,
-                                      _: ast::NodeId,
-                                      fn_id: ast::NodeId,
-                                      _: ast::Ident,
-                                      id: ast::NodeId) -> bool {
-            tcx.def_map.borrow().get(&id)
-                .map_or(false, |def| {
-                    let did = def.def_id();
-                    ast_util::is_local(did) && did.node == fn_id
-                })
-        }
-
-        // check if the method call `id` refers to method `method_id`
-        // (with name `method_name` contained in impl `impl_id`).
-        fn id_refers_to_this_method<'tcx>(tcx: &ty::ctxt<'tcx>,
-                                          impl_id: ast::NodeId,
-                                          method_id: ast::NodeId,
-                                          method_name: ast::Ident,
-                                          id: ast::NodeId) -> bool {
-            let did = match tcx.method_map.borrow().get(&ty::MethodCall::expr(id)) {
-                None => return false,
-                Some(m) => match m.origin {
-                    // There's no way to know if a method call via a
-                    // vtable is recursion, so we assume it's not.
-                    ty::MethodTraitObject(_) => return false,
-
-                    // This `did` refers directly to the method definition.
-                    ty::MethodStatic(did) | ty::MethodStaticClosure(did) => did,
-
-                    // MethodTypeParam are methods from traits:
-
-                    // The `impl ... for ...` of this method call
-                    // isn't known, e.g. it might be a default method
-                    // in a trait, so we get the def-id of the trait
-                    // method instead.
-                    ty::MethodTypeParam(
-                        ty::MethodParam { ref trait_ref, method_num, impl_def_id: None, }) => {
-                        ty::trait_item(tcx, trait_ref.def_id, method_num).def_id()
-                    }
-
-                    // The `impl` is known, so we check that with a
-                    // special case:
-                    ty::MethodTypeParam(
-                        ty::MethodParam { impl_def_id: Some(impl_def_id), .. }) => {
-
-                        let name = match tcx.map.expect_expr(id).node {
-                            ast::ExprMethodCall(ref sp_ident, _, _) => sp_ident.node,
-                            _ => tcx.sess.span_bug(
-                                tcx.map.span(id),
-                                "non-method call expr behaving like a method call?")
-                        };
-                        // it matches if it comes from the same impl,
-                        // and has the same method name.
-                        return ast_util::is_local(impl_def_id)
-                            && impl_def_id.node == impl_id
-                            && method_name.name == name.name
-                    }
-                }
-            };
-
-            ast_util::is_local(did) && did.node == method_id
-        }
-    }
-}
-
-declare_lint! {
-    PLUGIN_AS_LIBRARY,
-    Warn,
-    "compiler plugin used as ordinary library in non-plugin crate"
-}
-
-#[derive(Copy)]
-pub struct PluginAsLibrary;
-
-impl LintPass for PluginAsLibrary {
-    fn get_lints(&self) -> LintArray {
-        lint_array![PLUGIN_AS_LIBRARY]
-    }
-
-    fn check_item(&mut self, cx: &Context, it: &ast::Item) {
-        if cx.sess().plugin_registrar_fn.get().is_some() {
-            // We're compiling a plugin; it's fine to link other plugins.
-            return;
-        }
-
-        match it.node {
-            ast::ItemExternCrate(..) => (),
-            _ => return,
-        };
-
-        let md = match cx.sess().cstore.find_extern_mod_stmt_cnum(it.id) {
-            Some(cnum) => cx.sess().cstore.get_crate_data(cnum),
-            None => {
-                // Probably means we aren't linking the crate for some reason.
-                //
-                // Not sure if / when this could happen.
-                return;
-            }
-        };
-
-        if decoder::get_plugin_registrar_fn(md.data()).is_some() {
-            cx.span_lint(PLUGIN_AS_LIBRARY, it.span,
-                "compiler plugin used as an ordinary library");
-        }
-    }
-}
+use lint::{LintPass, LintArray};
 
 declare_lint! {
     pub UNUSED_IMPORTS,
@@ -2094,12 +100,6 @@ fn check_item(&mut self, cx: &Context, it: &ast::Item) {
     "detects transmutes of fat pointers"
 }
 
-declare_lint! {
-    pub MISSING_COPY_IMPLEMENTATIONS,
-    Allow,
-    "detects potentially-forgotten implementations of `Copy`"
-}
-
 /// Does nothing as a lint pass, but registers some `Lint`s
 /// which are used by other parts of the compiler.
 #[derive(Copy)]
@@ -2125,82 +125,3 @@ fn get_lints(&self) -> LintArray {
         )
     }
 }
-
-declare_lint! {
-    PRIVATE_NO_MANGLE_FNS,
-    Warn,
-    "functions marked #[no_mangle] should be exported"
-}
-
-declare_lint! {
-    PRIVATE_NO_MANGLE_STATICS,
-    Warn,
-    "statics marked #[no_mangle] should be exported"
-}
-
-declare_lint! {
-    NO_MANGLE_CONST_ITEMS,
-    Deny,
-    "const items will not have their symbols exported"
-}
-
-#[derive(Copy)]
-pub struct InvalidNoMangleItems;
-
-impl LintPass for InvalidNoMangleItems {
-    fn get_lints(&self) -> LintArray {
-        lint_array!(PRIVATE_NO_MANGLE_FNS,
-                    PRIVATE_NO_MANGLE_STATICS,
-                    NO_MANGLE_CONST_ITEMS)
-    }
-
-    fn check_item(&mut self, cx: &Context, it: &ast::Item) {
-        match it.node {
-            ast::ItemFn(..) => {
-                if attr::contains_name(&it.attrs, "no_mangle") &&
-                       !cx.exported_items.contains(&it.id) {
-                    let msg = format!("function {} is marked #[no_mangle], but not exported",
-                                      it.ident);
-                    cx.span_lint(PRIVATE_NO_MANGLE_FNS, it.span, &msg);
-                }
-            },
-            ast::ItemStatic(..) => {
-                if attr::contains_name(it.attrs.as_slice(), "no_mangle") &&
-                       !cx.exported_items.contains(&it.id) {
-                    let msg = format!("static {} is marked #[no_mangle], but not exported",
-                                      it.ident);
-                    cx.span_lint(PRIVATE_NO_MANGLE_STATICS, it.span, msg.as_slice());
-                }
-            },
-            ast::ItemConst(..) => {
-                if attr::contains_name(it.attrs.as_slice(), "no_mangle") {
-                    // Const items do not refer to a particular location in memory, and therefore
-                    // don't have anything to attach a symbol to
-                    let msg = "const items should never be #[no_mangle], consider instead using \
-                        `pub static`";
-                    cx.span_lint(NO_MANGLE_CONST_ITEMS, it.span, msg);
-                }
-            }
-            _ => {},
-        }
-    }
-}
-
-/// Forbids using the `#[feature(...)]` attribute
-#[derive(Copy)]
-pub struct UnstableFeatures;
-
-declare_lint!(UNSTABLE_FEATURES, Allow,
-              "enabling unstable features");
-
-impl LintPass for UnstableFeatures {
-    fn get_lints(&self) -> LintArray {
-        lint_array!(UNSTABLE_FEATURES)
-    }
-    fn check_attribute(&mut self, ctx: &Context, attr: &ast::Attribute) {
-        use syntax::attr;
-        if attr::contains_name(&[attr.node.value.clone()], "feature") {
-            ctx.span_lint(UNSTABLE_FEATURES, attr.span, "unstable feature");
-        }
-    }
-}
index d344ee8c881c5ab4fa796f64f80f9ae2264ffcb2..2b968736ffd9a6240c5bbca23197535fb00d3349 100644 (file)
@@ -159,7 +159,7 @@ pub fn register_group(&mut self, sess: Option<&Session>,
         }
     }
 
-    fn register_renamed(&mut self, old_name: &str, new_name: &str) {
+    pub fn register_renamed(&mut self, old_name: &str, new_name: &str) {
         let target = match self.by_name.get(new_name) {
             Some(&Id(lint_id)) => lint_id.clone(),
             _ => panic!("invalid lint renaming of {} to {}", old_name, new_name)
@@ -167,80 +167,6 @@ fn register_renamed(&mut self, old_name: &str, new_name: &str) {
         self.by_name.insert(old_name.to_string(), Renamed(new_name.to_string(), target));
     }
 
-    pub fn register_builtin(&mut self, sess: Option<&Session>) {
-        macro_rules! add_builtin {
-            ($sess:ident, $($name:ident),*,) => (
-                {$(
-                    self.register_pass($sess, false, box builtin::$name as LintPassObject);
-                )*}
-            )
-        }
-
-        macro_rules! add_builtin_with_new {
-            ($sess:ident, $($name:ident),*,) => (
-                {$(
-                    self.register_pass($sess, false, box builtin::$name::new() as LintPassObject);
-                )*}
-            )
-        }
-
-        macro_rules! add_lint_group {
-            ($sess:ident, $name:expr, $($lint:ident),*) => (
-                self.register_group($sess, false, $name, vec![$(LintId::of(builtin::$lint)),*]);
-            )
-        }
-
-        add_builtin!(sess,
-                     HardwiredLints,
-                     WhileTrue,
-                     UnusedCasts,
-                     ImproperCTypes,
-                     BoxPointers,
-                     UnusedAttributes,
-                     PathStatements,
-                     UnusedResults,
-                     NonCamelCaseTypes,
-                     NonSnakeCase,
-                     NonUpperCaseGlobals,
-                     UnusedParens,
-                     UnusedImportBraces,
-                     NonShorthandFieldPatterns,
-                     UnusedUnsafe,
-                     UnsafeCode,
-                     UnusedMut,
-                     UnusedAllocation,
-                     MissingCopyImplementations,
-                     UnstableFeatures,
-                     Stability,
-                     UnconditionalRecursion,
-                     InvalidNoMangleItems,
-                     PluginAsLibrary,
-        );
-
-        add_builtin_with_new!(sess,
-                              TypeLimits,
-                              RawPointerDerive,
-                              MissingDoc,
-                              MissingDebugImplementations,
-        );
-
-        add_lint_group!(sess, "bad_style",
-                        NON_CAMEL_CASE_TYPES, NON_SNAKE_CASE, NON_UPPER_CASE_GLOBALS);
-
-        add_lint_group!(sess, "unused",
-                        UNUSED_IMPORTS, UNUSED_VARIABLES, UNUSED_ASSIGNMENTS, DEAD_CODE,
-                        UNUSED_MUT, UNREACHABLE_CODE, UNUSED_MUST_USE,
-                        UNUSED_UNSAFE, PATH_STATEMENTS);
-
-        // We have one lint pass defined in this module.
-        self.register_pass(sess, false, box GatherNodeLevels as LintPassObject);
-
-        // Insert temporary renamings for a one-time deprecation
-        self.register_renamed("raw_pointer_deriving", "raw_pointer_derive");
-
-        self.register_renamed("unknown_features", "unused_features");
-    }
-
     #[allow(unused_variables)]
     fn find_lint(&self, lint_name: &str, sess: &Session, span: Option<Span>)
                  -> Option<LintId>
@@ -741,7 +667,7 @@ fn visit_id(&mut self, id: ast::NodeId) {
 // nodes, so that the variant size difference check in trans can call
 // `raw_emit_lint`.
 
-struct GatherNodeLevels;
+pub struct GatherNodeLevels;
 
 impl LintPass for GatherNodeLevels {
     fn get_lints(&self) -> LintArray {
index 021827b0101c81f7dee8caf04ab20ca6bcc9cac5..f3fa3b8846ca2b6d6d6eb175f68873cff5bed564 100644 (file)
@@ -37,7 +37,8 @@
 use syntax::visit::FnKind;
 use syntax::ast;
 
-pub use lint::context::{Context, LintStore, raw_emit_lint, check_crate, gather_attrs};
+pub use lint::context::{Context, LintStore, raw_emit_lint, check_crate, gather_attrs,
+                        GatherNodeLevels};
 
 /// Specification of a single lint.
 #[derive(Copy, Debug)]
index 5ee2f89018946b7af7487fc168a035f15ce6bf5d..f5c4cce065955659fddcfcc17c6f0d4dee2d426e 100644 (file)
@@ -150,12 +150,9 @@ pub fn get_trait_name(cstore: &cstore::CStore, def: ast::DefId) -> ast::Name {
                             def.node)
 }
 
-pub fn get_trait_item_name_and_kind(cstore: &cstore::CStore, def: ast::DefId)
-                                    -> (ast::Name, def::TraitItemKind) {
+pub fn is_static_method(cstore: &cstore::CStore, def: ast::DefId) -> bool {
     let cdata = cstore.get_crate_data(def.krate);
-    decoder::get_trait_item_name_and_kind(cstore.intr.clone(),
-                                          &*cdata,
-                                          def.node)
+    decoder::is_static_method(&*cdata, def.node)
 }
 
 pub fn get_trait_item_def_ids(cstore: &cstore::CStore, def: ast::DefId)
index aeae101a1235c26a56d4bac0cc32010a6843c764..0503045ac6e2d1673027bdf9bf1ede727c0c6f23 100644 (file)
@@ -119,7 +119,6 @@ enum Family {
     StaticMethod,          // F
     Method,                // h
     Type,                  // y
-    ForeignType,           // T
     Mod,                   // m
     ForeignMod,            // n
     Enum,                  // t
@@ -145,7 +144,6 @@ fn item_family(item: rbml::Doc) -> Family {
       'F' => StaticMethod,
       'h' => Method,
       'y' => Type,
-      'T' => ForeignType,
       'm' => Mod,
       'n' => ForeignMod,
       't' => Enum,
@@ -174,16 +172,13 @@ fn item_visibility(item: rbml::Doc) -> ast::Visibility {
     }
 }
 
-fn item_sort(item: rbml::Doc) -> char {
+fn item_sort(item: rbml::Doc) -> Option<char> {
     let mut ret = None;
     reader::tagged_docs(item, tag_item_trait_item_sort, |doc| {
         ret = Some(doc.as_str_slice().as_bytes()[0] as char);
         false
     });
-    match ret {
-        Some(r) => r,
-        None => panic!("No item_sort found")
-    }
+    ret
 }
 
 fn item_symbol(item: rbml::Doc) -> String {
@@ -339,14 +334,16 @@ fn item_to_def_like(item: rbml::Doc, did: ast::DefId, cnum: ast::CrateNum)
                 def::FromImpl(item_reqd_and_translated_parent_item(cnum,
                                                                    item))
             };
-            match fam {
-                // We don't bother to get encode/decode the trait id, we don't need it.
-                Method => DlDef(def::DefMethod(did, None, provenance)),
-                StaticMethod => DlDef(def::DefStaticMethod(did, provenance)),
-                _ => panic!()
+            DlDef(def::DefMethod(did, provenance))
+        }
+        Type => {
+            if item_sort(item) == Some('t') {
+                let trait_did = item_reqd_and_translated_parent_item(cnum, item);
+                DlDef(def::DefAssociatedTy(trait_did, did))
+            } else {
+                DlDef(def::DefTy(did, false))
             }
         }
-        Type | ForeignType => DlDef(def::DefTy(did, false)),
         Mod => DlDef(def::DefMod(did)),
         ForeignMod => DlDef(def::DefForeignMod(did)),
         StructVariant => {
@@ -357,7 +354,7 @@ fn item_to_def_like(item: rbml::Doc, did: ast::DefId, cnum: ast::CrateNum)
             let enum_did = item_reqd_and_translated_parent_item(cnum, item);
             DlDef(def::DefVariant(enum_did, did, false))
         }
-        Trait => DlDef(def::DefaultImpl(did)),
+        Trait => DlDef(def::DefTrait(did)),
         Enum => DlDef(def::DefTy(did, true)),
         Impl | DefaultImpl => DlImpl(did),
         PublicField | InheritedField => DlField,
@@ -831,8 +828,10 @@ 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) {
-            'r' | 'p' => impl_items.push(ty::MethodTraitItemId(def_id)),
-            't' => impl_items.push(ty::TypeTraitItemId(def_id)),
+            Some('r') | Some('p') => {
+                impl_items.push(ty::MethodTraitItemId(def_id))
+            }
+            Some('t') => impl_items.push(ty::TypeTraitItemId(def_id)),
             _ => panic!("unknown impl item sort"),
         }
         true
@@ -849,22 +848,13 @@ pub fn get_trait_name(intr: Rc<IdentInterner>,
     item_name(&*intr, doc)
 }
 
-pub fn get_trait_item_name_and_kind(intr: Rc<IdentInterner>,
-                                    cdata: Cmd,
-                                    id: ast::NodeId)
-                                    -> (ast::Name, def::TraitItemKind) {
+pub fn is_static_method(cdata: Cmd, id: ast::NodeId) -> bool {
     let doc = lookup_item(id, cdata.data());
-    let name = item_name(&*intr, doc);
     match item_sort(doc) {
-        'r' | 'p' => {
-            let explicit_self = get_explicit_self(doc);
-            (name, def::TraitItemKind::from_explicit_self_category(explicit_self))
-        }
-        't' => (name, def::TypeTraitItemKind),
-        c => {
-            panic!("get_trait_item_name_and_kind(): unknown trait item kind \
-                   in metadata: `{}`", c)
+        Some('r') | Some('p') => {
+            get_explicit_self(doc) == ty::StaticExplicitSelfCategory
         }
+        _ => false
     }
 }
 
@@ -889,7 +879,7 @@ pub fn get_impl_or_trait_item<'tcx>(intr: Rc<IdentInterner>,
     let vis = item_visibility(method_doc);
 
     match item_sort(method_doc) {
-        'r' | 'p' => {
+        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);
             let fty = doc_method_fty(method_doc, tcx, cdata);
@@ -906,7 +896,7 @@ pub fn get_impl_or_trait_item<'tcx>(intr: Rc<IdentInterner>,
                                                         container,
                                                         provided_source)))
         }
-        't' => {
+        Some('t') => {
             ty::TypeTraitItem(Rc::new(ty::AssociatedType {
                 name: name,
                 vis: vis,
@@ -926,8 +916,10 @@ 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) {
-            'r' | 'p' => result.push(ty::MethodTraitItemId(def_id)),
-            't' => result.push(ty::TypeTraitItemId(def_id)),
+            Some('r') | Some('p') => {
+                result.push(ty::MethodTraitItemId(def_id));
+            }
+            Some('t') => result.push(ty::TypeTraitItemId(def_id)),
             _ => panic!("unknown trait item sort"),
         }
         true
@@ -956,7 +948,7 @@ pub fn get_provided_trait_methods<'tcx>(intr: Rc<IdentInterner>,
         let did = item_def_id(mth_id, cdata);
         let mth = lookup_item(did.node, data);
 
-        if item_sort(mth) == 'p' {
+        if item_sort(mth) == Some('p') {
             let trait_item = get_impl_or_trait_item(intr.clone(),
                                                     cdata,
                                                     did.node,
@@ -1560,7 +1552,7 @@ pub fn is_associated_type(cdata: Cmd, id: ast::NodeId) -> bool {
     let items = reader::get_doc(rbml::Doc::new(cdata.data()), tag_items);
     match maybe_find_item(id, items) {
         None => false,
-        Some(item) => item_sort(item) == 't',
+        Some(item) => item_sort(item) == Some('t'),
     }
 }
 
index e0832bb683a1c9064963500c8c5387bcabaf5752..ee2745ca66bc59980a675bd7dd7da2f24129d447 100644 (file)
@@ -1193,7 +1193,7 @@ fn add_to_index(item: &ast::Item, rbml_w: &Encoder,
             None => {}
         }
       }
-      ast::ItemDefaultImpl(unsafety, ref ast_trait_ref) => {
+      ast::ItemDefaultImpl(unsafety, _) => {
           add_to_index(item, rbml_w, index);
           rbml_w.start_tag(tag_items_data_item);
           encode_def_id(rbml_w, def_id);
@@ -1201,7 +1201,7 @@ fn add_to_index(item: &ast::Item, rbml_w: &Encoder,
           encode_name(rbml_w, item.ident.name);
           encode_unsafety(rbml_w, unsafety);
 
-          let trait_ref = ty::node_id_to_trait_ref(tcx, ast_trait_ref.ref_id);
+          let trait_ref = ty::impl_id_to_trait_ref(tcx, item.id);
           encode_trait_ref(rbml_w, ecx, &*trait_ref, tag_item_trait_ref);
           rbml_w.end_tag();
       }
@@ -1221,7 +1221,7 @@ fn add_to_index(item: &ast::Item, rbml_w: &Encoder,
         encode_unsafety(rbml_w, unsafety);
         encode_polarity(rbml_w, polarity);
         match ty.node {
-            ast::TyPath(ref path, _) if path.segments.len() == 1 => {
+            ast::TyPath(None, ref path) if path.segments.len() == 1 => {
                 let ident = path.segments.last().unwrap().identifier;
                 encode_impl_type_basename(rbml_w, ident);
             }
@@ -1241,9 +1241,8 @@ fn add_to_index(item: &ast::Item, rbml_w: &Encoder,
             }
             rbml_w.end_tag();
         }
-        if let Some(ref ast_trait_ref) = *opt_trait {
-            let trait_ref = ty::node_id_to_trait_ref(
-                tcx, ast_trait_ref.ref_id);
+        if opt_trait.is_some() {
+            let trait_ref = ty::impl_id_to_trait_ref(tcx, item.id);
             encode_trait_ref(rbml_w, ecx, &*trait_ref, tag_item_trait_ref);
         }
         encode_path(rbml_w, path.clone());
@@ -1871,9 +1870,7 @@ struct ImplVisitor<'a, 'b:'a, 'c:'a, 'tcx:'b> {
 impl<'a, 'b, 'c, 'tcx, 'v> Visitor<'v> for ImplVisitor<'a, 'b, 'c, 'tcx> {
     fn visit_item(&mut self, item: &ast::Item) {
         if let ast::ItemImpl(_, _, _, Some(ref trait_ref), _, _) = item.node {
-            let def_map = &self.ecx.tcx.def_map;
-            let trait_def = def_map.borrow()[trait_ref.ref_id].clone();
-            let def_id = trait_def.def_id();
+            let def_id = self.ecx.tcx.def_map.borrow()[trait_ref.ref_id].def_id();
 
             // Load eagerly if this is an implementation of the Drop trait
             // or if the trait is not defined in this crate.
index d63b3dd60d01d31222ecc4ccc0e15956813ef692..a8d39f95739326174f2f3714ef3085173ffcbfa4 100644 (file)
@@ -14,6 +14,7 @@
 
 use std::collections::HashSet;
 use std::env;
+use std::os;
 use std::old_io::fs::PathExtensions;
 use std::old_io::fs;
 
@@ -194,7 +195,7 @@ fn canonicalize(path: Option<Path>) -> Option<Path> {
             })
     }
 
-    match canonicalize(env::current_exe().ok()) {
+    match canonicalize(os::self_exe_name()) {
         Some(mut p) => { p.pop(); p.pop(); p }
         None => panic!("can't determine value for sysroot")
     }
@@ -224,7 +225,7 @@ pub fn rust_path() -> Vec<Path> {
         }
         None => Vec::new()
     };
-    let mut cwd = env::current_dir().unwrap();
+    let mut cwd = os::getcwd().unwrap();
     // now add in default entries
     let cwd_dot_rust = cwd.join(".rust");
     if !env_rust_path.contains(&cwd_dot_rust) {
@@ -243,7 +244,7 @@ pub fn rust_path() -> Vec<Path> {
         }
         cwd.pop();
     }
-    if let Some(h) = env::home_dir() {
+    if let Some(h) = os::homedir() {
         let p = h.join(".rust");
         if !env_rust_path.contains(&p) && p.exists() {
             env_rust_path.push(p);
index fbc3e76cf934b2e073d18c9bfee730d52bbcfc1f..07082d818769c44ba1d2cf25e5528b396fe1f346 100644 (file)
@@ -736,12 +736,10 @@ fn get_metadata_section_imp(is_osx: bool, filename: &Path) -> Result<MetadataBlo
             }
         };
         return match ArchiveMetadata::new(archive).map(|ar| MetadataArchive(ar)) {
-            None => {
-                return Err((format!("failed to read rlib metadata: '{}'",
-                                    filename.display())))
-            }
-            Some(blob) => return Ok(blob)
-        }
+            None => Err(format!("failed to read rlib metadata: '{}'",
+                                filename.display())),
+            Some(blob) => Ok(blob)
+        };
     }
     unsafe {
         let buf = CString::new(filename.as_vec()).unwrap();
@@ -791,7 +789,7 @@ fn get_metadata_section_imp(is_osx: bool, filename: &Path) -> Result<MetadataBlo
             }
             llvm::LLVMMoveToNextSection(si.llsi);
         }
-        return Err(format!("metadata not found: '{}'", filename.display()));
+        Err(format!("metadata not found: '{}'", filename.display()))
     }
 }
 
index 4a45b7fbfdcc743b48ae28d2522279a2cb46f0f2..baecfb7eb22c5ec6cb95898ee8ca45f60e93f003 100644 (file)
@@ -822,7 +822,6 @@ fn parse_type_param_def_<'a, 'tcx, F>(st: &mut PState<'a, 'tcx>, conv: &mut F)
     assert_eq!(next(st), '|');
     let index = parse_u32(st);
     assert_eq!(next(st), '|');
-    let bounds = parse_bounds_(st, conv);
     let default = parse_opt(st, |st| parse_ty_(st, conv));
     let object_lifetime_default = parse_object_lifetime_default(st, conv);
 
@@ -831,7 +830,6 @@ fn parse_type_param_def_<'a, 'tcx, F>(st: &mut PState<'a, 'tcx>, conv: &mut F)
         def_id: def_id,
         space: space,
         index: index,
-        bounds: bounds,
         default: default,
         object_lifetime_default: object_lifetime_default,
     }
@@ -924,18 +922,18 @@ fn parse_bounds_<'a, 'tcx, F>(st: &mut PState<'a, 'tcx>, conv: &mut F)
 {
     let builtin_bounds = parse_builtin_bounds_(st, conv);
 
+    let region_bounds = parse_region_bounds_(st, conv);
+
     let mut param_bounds = ty::ParamBounds {
-        region_bounds: Vec::new(),
+        region_bounds: region_bounds,
         builtin_bounds: builtin_bounds,
         trait_bounds: Vec::new(),
         projection_bounds: Vec::new(),
     };
+
+
     loop {
         match next(st) {
-            'R' => {
-                param_bounds.region_bounds.push(
-                    parse_region_(st, conv));
-            }
             'I' => {
                 param_bounds.trait_bounds.push(
                     ty::Binder(parse_trait_ref_(st, conv)));
@@ -953,3 +951,18 @@ fn parse_bounds_<'a, 'tcx, F>(st: &mut PState<'a, 'tcx>, conv: &mut F)
         }
     }
 }
+
+fn parse_region_bounds_<'a, 'tcx, F>(st: &mut PState<'a, 'tcx>, conv: &mut F)
+                              -> Vec<ty::Region> where
+    F: FnMut(DefIdSource, ast::DefId) -> ast::DefId,
+{
+    let mut region_bounds = Vec::new();
+    loop {
+        match next(st) {
+            'R' => { region_bounds.push(parse_region_(st, conv)); }
+            '.' => { return region_bounds; }
+            c => { panic!("parse_bounds: bad bounds ('{}')", c); }
+        }
+    }
+}
+
index 11609ebe675efa8522265339ad71d4463828eae0..76a365259aa5713a3eb952a9a3eadfffeefb0bba 100644 (file)
@@ -386,10 +386,7 @@ pub fn enc_bounds<'a, 'tcx>(w: &mut SeekableMemWriter, cx: &ctxt<'a, 'tcx>,
                             bs: &ty::ParamBounds<'tcx>) {
     enc_builtin_bounds(w, cx, &bs.builtin_bounds);
 
-    for &r in &bs.region_bounds {
-        mywrite!(w, "R");
-        enc_region(w, cx, r);
-    }
+    enc_region_bounds(w, cx, &bs.region_bounds);
 
     for tp in &bs.trait_bounds {
         mywrite!(w, "I");
@@ -404,12 +401,22 @@ pub fn enc_bounds<'a, 'tcx>(w: &mut SeekableMemWriter, cx: &ctxt<'a, 'tcx>,
     mywrite!(w, ".");
 }
 
+pub fn enc_region_bounds<'a, 'tcx>(w: &mut SeekableMemWriter,
+                            cx: &ctxt<'a, 'tcx>,
+                            rs: &[ty::Region]) {
+    for &r in rs {
+        mywrite!(w, "R");
+        enc_region(w, cx, r);
+    }
+
+    mywrite!(w, ".");
+}
+
 pub fn enc_type_param_def<'a, 'tcx>(w: &mut SeekableMemWriter, cx: &ctxt<'a, 'tcx>,
                                     v: &ty::TypeParameterDef<'tcx>) {
     mywrite!(w, "{}:{}|{}|{}|",
              token::get_name(v.name), (cx.ds)(v.def_id),
              v.space.to_uint(), v.index);
-    enc_bounds(w, cx, &v.bounds);
     enc_opt(w, v.default, |w, t| enc_ty(w, cx, t));
     enc_object_lifetime_default(w, cx, v.object_lifetime_default);
 }
index d699ba40e822045bf4ac34ff6b13a86bfc93198e..0f98b3c33fb8d61dc1bf055cd6c44e6a2bcbf83a 100644 (file)
 pub const NO_REGIONS: uint = 1;
 pub const NO_TPS: uint = 2;
 
-pub fn check_path_args(tcx: &ty::ctxt,
-                       path: &ast::Path,
-                       flags: uint) {
-    if (flags & NO_TPS) != 0 {
-        if path.segments.iter().any(|s| s.parameters.has_types()) {
-            span_err!(tcx.sess, path.span, E0109,
-                "type parameters are not allowed on this type");
+pub fn check_path_args(tcx: &ty::ctxt, segments: &[ast::PathSegment], flags: uint) {
+    for segment in segments {
+        if (flags & NO_TPS) != 0 {
+            for typ in segment.parameters.types() {
+                span_err!(tcx.sess, typ.span, E0109,
+                          "type parameters are not allowed on this type");
+                break;
+            }
         }
-    }
 
-    if (flags & NO_REGIONS) != 0 {
-        if path.segments.iter().any(|s| s.parameters.has_lifetimes()) {
-            span_err!(tcx.sess, path.span, E0110,
-                "region parameters are not allowed on this type");
+        if (flags & NO_REGIONS) != 0 {
+            for lifetime in segment.parameters.lifetimes() {
+                span_err!(tcx.sess, lifetime.span, E0110,
+                          "lifetime parameters are not allowed on this type");
+                break;
+            }
         }
     }
 }
 
+pub fn prim_ty_to_ty<'tcx>(tcx: &ty::ctxt<'tcx>,
+                           segments: &[ast::PathSegment],
+                           nty: ast::PrimTy)
+                           -> Ty<'tcx> {
+    check_path_args(tcx, segments, NO_TPS | NO_REGIONS);
+    match nty {
+        ast::TyBool => tcx.types.bool,
+        ast::TyChar => tcx.types.char,
+        ast::TyInt(it) => ty::mk_mach_int(tcx, it),
+        ast::TyUint(uit) => ty::mk_mach_uint(tcx, uit),
+        ast::TyFloat(ft) => ty::mk_mach_float(tcx, ft),
+        ast::TyStr => ty::mk_str(tcx)
+    }
+}
+
 pub fn ast_ty_to_prim_ty<'tcx>(tcx: &ty::ctxt<'tcx>, ast_ty: &ast::Ty)
                                -> Option<Ty<'tcx>> {
-    match ast_ty.node {
-        ast::TyPath(ref path, id) => {
-            let a_def = match tcx.def_map.borrow().get(&id) {
-                None => {
-                    tcx.sess.span_bug(ast_ty.span,
-                                      &format!("unbound path {}",
-                                              path.repr(tcx)))
-                }
-                Some(&d) => d
-            };
-            match a_def {
-                def::DefPrimTy(nty) => {
-                    match nty {
-                        ast::TyBool => {
-                            check_path_args(tcx, path, NO_TPS | NO_REGIONS);
-                            Some(tcx.types.bool)
-                        }
-                        ast::TyChar => {
-                            check_path_args(tcx, path, NO_TPS | NO_REGIONS);
-                            Some(tcx.types.char)
-                        }
-                        ast::TyInt(it) => {
-                            check_path_args(tcx, path, NO_TPS | NO_REGIONS);
-                            Some(ty::mk_mach_int(tcx, it))
-                        }
-                        ast::TyUint(uit) => {
-                            check_path_args(tcx, path, NO_TPS | NO_REGIONS);
-                            Some(ty::mk_mach_uint(tcx, uit))
-                        }
-                        ast::TyFloat(ft) => {
-                            check_path_args(tcx, path, NO_TPS | NO_REGIONS);
-                            Some(ty::mk_mach_float(tcx, ft))
-                        }
-                        ast::TyStr => {
-                            Some(ty::mk_str(tcx))
-                        }
-                    }
-                }
-                _ => None
+    if let ast::TyPath(None, ref path) = ast_ty.node {
+        let def = match tcx.def_map.borrow().get(&ast_ty.id) {
+            None => {
+                tcx.sess.span_bug(ast_ty.span,
+                                  &format!("unbound path {}", path.repr(tcx)))
             }
+            Some(d) => d.full_def()
+        };
+        if let def::DefPrimTy(nty) = def {
+            Some(prim_ty_to_ty(tcx, &path.segments, nty))
+        } else {
+            None
         }
-        _ => None
+    } else {
+        None
     }
 }
-
index e63901c21b270aa850b4e77e7b6af7138e975c87..5983829ed8fbef20e56b6124b2a1e868201aaf0d 100644 (file)
@@ -25,6 +25,7 @@
 use metadata::tyencode;
 use middle::check_const::ConstQualif;
 use middle::mem_categorization::Typer;
+use middle::privacy::{AllPublic, LastMod};
 use middle::subst;
 use middle::subst::VecPerParamSpace;
 use middle::ty::{self, Ty, MethodCall, MethodCallee, MethodOrigin};
@@ -423,13 +424,8 @@ impl tr for def::Def {
     fn tr(&self, dcx: &DecodeContext) -> def::Def {
         match *self {
           def::DefFn(did, is_ctor) => def::DefFn(did.tr(dcx), is_ctor),
-          def::DefStaticMethod(did, p) => {
-            def::DefStaticMethod(did.tr(dcx), p.map(|did2| did2.tr(dcx)))
-          }
-          def::DefMethod(did0, did1, p) => {
-            def::DefMethod(did0.tr(dcx),
-                           did1.map(|did1| did1.tr(dcx)),
-                           p.map(|did2| did2.tr(dcx)))
+          def::DefMethod(did, p) => {
+            def::DefMethod(did.tr(dcx), p.map(|did2| did2.tr(dcx)))
           }
           def::DefSelfTy(nid) => { def::DefSelfTy(dcx.tr_id(nid)) }
           def::DefMod(did) => { def::DefMod(did.tr(dcx)) }
@@ -440,13 +436,10 @@ fn tr(&self, dcx: &DecodeContext) -> def::Def {
           def::DefVariant(e_did, v_did, is_s) => {
             def::DefVariant(e_did.tr(dcx), v_did.tr(dcx), is_s)
           },
-          def::DefaultImpl(did) => def::DefaultImpl(did.tr(dcx)),
+          def::DefTrait(did) => def::DefTrait(did.tr(dcx)),
           def::DefTy(did, is_enum) => def::DefTy(did.tr(dcx), is_enum),
-          def::DefAssociatedTy(did) => def::DefAssociatedTy(did.tr(dcx)),
-          def::DefAssociatedPath(def::TyParamProvenance::FromSelf(did), ident) =>
-              def::DefAssociatedPath(def::TyParamProvenance::FromSelf(did.tr(dcx)), ident),
-          def::DefAssociatedPath(def::TyParamProvenance::FromParam(did), ident) =>
-              def::DefAssociatedPath(def::TyParamProvenance::FromParam(did.tr(dcx)), ident),
+          def::DefAssociatedTy(trait_did, did) =>
+              def::DefAssociatedTy(trait_did.tr(dcx), did.tr(dcx)),
           def::DefPrimTy(p) => def::DefPrimTy(p),
           def::DefTyParam(s, index, def_id, n) => def::DefTyParam(s, index, def_id.tr(dcx), n),
           def::DefUse(did) => def::DefUse(did.tr(dcx)),
@@ -455,9 +448,6 @@ fn tr(&self, dcx: &DecodeContext) -> def::Def {
           }
           def::DefStruct(did) => def::DefStruct(did.tr(dcx)),
           def::DefRegion(nid) => def::DefRegion(dcx.tr_id(nid)),
-          def::DefTyParamBinder(nid) => {
-            def::DefTyParamBinder(dcx.tr_id(nid))
-          }
           def::DefLabel(nid) => def::DefLabel(dcx.tr_id(nid))
         }
     }
@@ -1159,10 +1149,10 @@ fn encode_side_tables_for_id(ecx: &e::EncodeContext,
 
     debug!("Encoding side tables for id {}", id);
 
-    if let Some(def) = tcx.def_map.borrow().get(&id) {
+    if let Some(def) = tcx.def_map.borrow().get(&id).map(|d| d.full_def()) {
         rbml_w.tag(c::tag_table_def, |rbml_w| {
             rbml_w.id(id);
-            rbml_w.tag(c::tag_table_val, |rbml_w| (*def).encode(rbml_w).unwrap());
+            rbml_w.tag(c::tag_table_val, |rbml_w| def.encode(rbml_w).unwrap());
         })
     }
 
@@ -1862,7 +1852,12 @@ fn decode_side_tables(dcx: &DecodeContext,
                 match value {
                     c::tag_table_def => {
                         let def = decode_def(dcx, val_doc);
-                        dcx.tcx.def_map.borrow_mut().insert(id, def);
+                        dcx.tcx.def_map.borrow_mut().insert(id, def::PathResolution {
+                            base_def: def,
+                            // This doesn't matter cross-crate.
+                            last_private: LastMod(AllPublic),
+                            depth: 0
+                        });
                     }
                     c::tag_table_node_type => {
                         let ty = val_dsr.read_ty(dcx);
index 52eedc460eb8749695fcb74cca6efab951c950cd..24c54b53590c04f57a4ff6eafe82f3179b9d3cfa 100644 (file)
@@ -398,8 +398,7 @@ fn expr(&mut self, expr: &ast::Expr, pred: CFGIndex) -> CFGIndex {
             ast::ExprMac(..) |
             ast::ExprClosure(..) |
             ast::ExprLit(..) |
-            ast::ExprPath(..) |
-            ast::ExprQPath(..) => {
+            ast::ExprPath(..) => {
                 self.straightline(expr, pred, None::<ast::Expr>.iter())
             }
         }
@@ -610,32 +609,24 @@ fn add_returning_edge(&mut self,
     fn find_scope(&self,
                   expr: &ast::Expr,
                   label: Option<ast::Ident>) -> LoopScope {
-        match label {
-            None => {
-                return *self.loop_scopes.last().unwrap();
-            }
-
-            Some(_) => {
-                match self.tcx.def_map.borrow().get(&expr.id) {
-                    Some(&def::DefLabel(loop_id)) => {
-                        for l in &self.loop_scopes {
-                            if l.loop_id == loop_id {
-                                return *l;
-                            }
-                        }
-                        self.tcx.sess.span_bug(
-                            expr.span,
-                            &format!("no loop scope for id {}",
-                                    loop_id));
-                    }
+        if label.is_none() {
+            return *self.loop_scopes.last().unwrap();
+        }
 
-                    r => {
-                        self.tcx.sess.span_bug(
-                            expr.span,
-                            &format!("bad entry `{:?}` in def_map for label",
-                                    r));
+        match self.tcx.def_map.borrow().get(&expr.id).map(|d| d.full_def()) {
+            Some(def::DefLabel(loop_id)) => {
+                for l in &self.loop_scopes {
+                    if l.loop_id == loop_id {
+                        return *l;
                     }
                 }
+                self.tcx.sess.span_bug(expr.span,
+                    &format!("no loop scope for id {}", loop_id));
+            }
+
+            r => {
+                self.tcx.sess.span_bug(expr.span,
+                    &format!("bad entry `{:?}` in def_map for label", r));
             }
         }
     }
index f1c8ad947642fab284d991ebc1893d3dae1fec61..8401d25024d3577e7fa4921445d7d03a0694393b 100644 (file)
@@ -439,8 +439,8 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>,
                 }
             }
         }
-        ast::ExprPath(_) | ast::ExprQPath(_) => {
-            let def = v.tcx.def_map.borrow().get(&e.id).cloned();
+        ast::ExprPath(..) => {
+            let def = v.tcx.def_map.borrow().get(&e.id).map(|d| d.full_def());
             match def {
                 Some(def::DefVariant(_, _, _)) => {
                     // Count the discriminator or function pointer.
@@ -452,8 +452,7 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>,
                         v.add_qualif(NON_ZERO_SIZED);
                     }
                 }
-                Some(def::DefFn(..)) |
-                Some(def::DefStaticMethod(..)) | Some(def::DefMethod(..)) => {
+                Some(def::DefFn(..)) | Some(def::DefMethod(..)) => {
                     // Count the function pointer.
                     v.add_qualif(NON_ZERO_SIZED);
                 }
@@ -500,7 +499,7 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>,
                     _ => break
                 };
             }
-            let def = v.tcx.def_map.borrow().get(&callee.id).cloned();
+            let def = v.tcx.def_map.borrow().get(&callee.id).map(|d| d.full_def());
             match def {
                 Some(def::DefStruct(..)) => {}
                 Some(def::DefVariant(..)) => {
index 7bd64a4f487d60414863d6456ad65cd330d6f676..c409c8fb13f14502437aa2d1c9813b1365624f9d 100644 (file)
@@ -242,7 +242,7 @@ fn check_for_bindings_named_the_same_as_variants(cx: &MatchCheckCtxt, pat: &Pat)
             ast::PatIdent(ast::BindByValue(ast::MutImmutable), ident, None) => {
                 let pat_ty = ty::pat_ty(cx.tcx, p);
                 if let ty::ty_enum(def_id, _) = pat_ty.sty {
-                    let def = cx.tcx.def_map.borrow().get(&p.id).cloned();
+                    let def = cx.tcx.def_map.borrow().get(&p.id).map(|d| d.full_def());
                     if let Some(DefLocal(_)) = def {
                         if ty::enum_variants(cx.tcx, def_id).iter().any(|variant|
                             token::get_name(variant.name) == token::get_name(ident.node.name)
@@ -434,7 +434,7 @@ 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(..) => {
-                let def = self.tcx.def_map.borrow().get(&pat.id).cloned();
+                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(const_expr) => {
@@ -733,28 +733,28 @@ fn pat_constructors(cx: &MatchCheckCtxt, p: &Pat,
     let pat = raw_pat(p);
     match pat.node {
         ast::PatIdent(..) =>
-            match cx.tcx.def_map.borrow().get(&pat.id) {
-                Some(&DefConst(..)) =>
+            match cx.tcx.def_map.borrow().get(&pat.id).map(|d| d.full_def()) {
+                Some(DefConst(..)) =>
                     cx.tcx.sess.span_bug(pat.span, "const pattern should've \
                                                     been rewritten"),
-                Some(&DefStruct(_)) => vec!(Single),
-                Some(&DefVariant(_, id, _)) => vec!(Variant(id)),
+                Some(DefStruct(_)) => vec!(Single),
+                Some(DefVariant(_, id, _)) => vec!(Variant(id)),
                 _ => vec!()
             },
         ast::PatEnum(..) =>
-            match cx.tcx.def_map.borrow().get(&pat.id) {
-                Some(&DefConst(..)) =>
+            match cx.tcx.def_map.borrow().get(&pat.id).map(|d| d.full_def()) {
+                Some(DefConst(..)) =>
                     cx.tcx.sess.span_bug(pat.span, "const pattern should've \
                                                     been rewritten"),
-                Some(&DefVariant(_, id, _)) => vec!(Variant(id)),
+                Some(DefVariant(_, id, _)) => vec!(Variant(id)),
                 _ => vec!(Single)
             },
         ast::PatStruct(..) =>
-            match cx.tcx.def_map.borrow().get(&pat.id) {
-                Some(&DefConst(..)) =>
+            match cx.tcx.def_map.borrow().get(&pat.id).map(|d| d.full_def()) {
+                Some(DefConst(..)) =>
                     cx.tcx.sess.span_bug(pat.span, "const pattern should've \
                                                     been rewritten"),
-                Some(&DefVariant(_, id, _)) => vec!(Variant(id)),
+                Some(DefVariant(_, id, _)) => vec!(Variant(id)),
                 _ => vec!(Single)
             },
         ast::PatLit(ref expr) =>
@@ -847,7 +847,7 @@ pub fn specialize<'a>(cx: &MatchCheckCtxt, r: &[&'a Pat],
             Some(repeat(DUMMY_WILD_PAT).take(arity).collect()),
 
         ast::PatIdent(_, _, _) => {
-            let opt_def = cx.tcx.def_map.borrow().get(&pat_id).cloned();
+            let opt_def = cx.tcx.def_map.borrow().get(&pat_id).map(|d| d.full_def());
             match opt_def {
                 Some(DefConst(..)) =>
                     cx.tcx.sess.span_bug(pat_span, "const pattern should've \
@@ -862,7 +862,7 @@ pub fn specialize<'a>(cx: &MatchCheckCtxt, r: &[&'a Pat],
         }
 
         ast::PatEnum(_, ref args) => {
-            let def = cx.tcx.def_map.borrow()[pat_id].clone();
+            let def = cx.tcx.def_map.borrow()[pat_id].full_def();
             match def {
                 DefConst(..) =>
                     cx.tcx.sess.span_bug(pat_span, "const pattern should've \
@@ -880,7 +880,7 @@ pub fn specialize<'a>(cx: &MatchCheckCtxt, r: &[&'a Pat],
 
         ast::PatStruct(_, ref pattern_fields, _) => {
             // Is this a struct or an enum variant?
-            let def = cx.tcx.def_map.borrow()[pat_id].clone();
+            let def = cx.tcx.def_map.borrow()[pat_id].full_def();
             let class_id = match def {
                 DefConst(..) =>
                     cx.tcx.sess.span_bug(pat_span, "const pattern should've \
index 4280b7fe3f09649170a73dc7e37f90873a22fa9f..b97978fc03fff33ae23e04c0cb05595511f2d380 100644 (file)
@@ -93,10 +93,10 @@ fn visit_item(&mut self, it: &ast::Item) {
 
     fn visit_expr(&mut self, e: &ast::Expr) {
         match e.node {
-            ast::ExprPath(_) | ast::ExprQPath(_) => {
-                match self.def_map.borrow().get(&e.id) {
-                    Some(&DefStatic(def_id, _)) |
-                    Some(&DefConst(def_id)) if
+            ast::ExprPath(..) => {
+                match self.def_map.borrow().get(&e.id).map(|d| d.base_def) {
+                    Some(DefStatic(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) =>
index 5bf7422dbc0d41ce7051d5a801238c4d4a28b12f..f793d3ce2fb4522c08aca64f0849c4022d18bf39 100644 (file)
@@ -31,7 +31,7 @@
 use std::rc::Rc;
 
 fn lookup_const<'a>(tcx: &'a ty::ctxt, e: &Expr) -> Option<&'a Expr> {
-    let opt_def = tcx.def_map.borrow().get(&e.id).cloned();
+    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)
@@ -148,11 +148,11 @@ pub fn const_expr_to_pat(tcx: &ty::ctxt, expr: &Expr, span: Span) -> P<ast::Pat>
             ast::PatTup(exprs.iter().map(|expr| const_expr_to_pat(tcx, &**expr, span)).collect()),
 
         ast::ExprCall(ref callee, ref args) => {
-            let def = tcx.def_map.borrow()[callee.id].clone();
+            let def = tcx.def_map.borrow()[callee.id];
             if let Vacant(entry) = tcx.def_map.borrow_mut().entry(expr.id) {
                entry.insert(def);
             }
-            let path = match def {
+            let path = match def.full_def() {
                 def::DefStruct(def_id) => def_to_path(tcx, def_id),
                 def::DefVariant(_, variant_did, _) => def_to_path(tcx, variant_did),
                 _ => unreachable!()
@@ -178,8 +178,8 @@ pub fn const_expr_to_pat(tcx: &ty::ctxt, expr: &Expr, span: Span) -> P<ast::Pat>
             ast::PatVec(pats, None, vec![])
         }
 
-        ast::ExprPath(ref path) => {
-            let opt_def = tcx.def_map.borrow().get(&expr.id).cloned();
+        ast::ExprPath(_, ref path) => {
+            let opt_def = tcx.def_map.borrow().get(&expr.id).map(|d| d.full_def());
             match opt_def {
                 Some(def::DefStruct(..)) =>
                     ast::PatStruct(path.clone(), vec![], false),
@@ -194,13 +194,6 @@ pub fn const_expr_to_pat(tcx: &ty::ctxt, expr: &Expr, span: Span) -> P<ast::Pat>
             }
         }
 
-        ast::ExprQPath(_) => {
-            match lookup_const(tcx, expr) {
-                Some(actual) => return const_expr_to_pat(tcx, actual, span),
-                _ => unreachable!()
-            }
-        }
-
         _ => ast::PatLit(P(expr.clone()))
     };
     P(ast::Pat { id: expr.id, node: pat, span: span })
@@ -388,8 +381,8 @@ fn fromb(b: bool) -> Result<const_val, String> { Ok(const_int(b as i64)) }
         let val = try!(eval_const_expr_partial(tcx, &**base, Some(base_hint)));
         cast_const(val, ety)
       }
-      ast::ExprPath(_) | ast::ExprQPath(_) => {
-          let opt_def = tcx.def_map.borrow().get(&e.id).cloned();
+      ast::ExprPath(..) => {
+          let opt_def = tcx.def_map.borrow().get(&e.id).map(|d| d.full_def());
           let (const_expr, const_ty) = match opt_def {
               Some(def::DefConst(def_id)) => {
                   if ast_util::is_local(def_id) {
index ff78deb8d12ea6ba945531b6c34f0762b38a2ee6..2d837ce52b56a4f9abcee7e973d8dc95d7a55d3f 100644 (file)
@@ -71,13 +71,13 @@ 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 {
-                &def::DefConst(_) => {
+            match def.full_def() {
+                def::DefConst(_) => {
                     self.check_def_id(def.def_id())
                 }
                 _ if self.ignore_non_const_paths => (),
-                &def::DefPrimTy(_) => (),
-                &def::DefVariant(enum_id, variant_id, _) => {
+                def::DefPrimTy(_) => (),
+                def::DefVariant(enum_id, variant_id, _) => {
                     self.check_def_id(enum_id);
                     self.check_def_id(variant_id);
                 }
@@ -158,7 +158,7 @@ fn handle_tup_field_access(&mut self, lhs: &ast::Expr, idx: uint) {
 
     fn handle_field_pattern_match(&mut self, lhs: &ast::Pat,
                                   pats: &[codemap::Spanned<ast::FieldPat>]) {
-        let id = match (*self.tcx.def_map.borrow())[lhs.id] {
+        let id = match self.tcx.def_map.borrow()[lhs.id].full_def() {
             def::DefVariant(_, id, _) => id,
             _ => {
                 match ty::ty_to_def_id(ty::node_id_to_type(self.tcx,
index 009bfaf8728f8012e43e928e12f5d6e43d7e5d26..1a054c0f464aac9afb5a91adb6f007490a8969da 100644 (file)
 
 pub use self::Def::*;
 pub use self::MethodProvenance::*;
-pub use self::TraitItemKind::*;
 
+use middle::privacy::LastPrivate;
 use middle::subst::ParamSpace;
-use middle::ty::{ExplicitSelfCategory, StaticExplicitSelfCategory};
 use util::nodemap::NodeMap;
 use syntax::ast;
 use syntax::ast_util::local_def;
@@ -23,7 +22,6 @@
 #[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
 pub enum Def {
     DefFn(ast::DefId, bool /* is_ctor */),
-    DefStaticMethod(/* method */ ast::DefId, MethodProvenance),
     DefSelfTy(/* trait id */ ast::NodeId),
     DefMod(ast::DefId),
     DefForeignMod(ast::DefId),
@@ -32,13 +30,8 @@ pub enum Def {
     DefLocal(ast::NodeId),
     DefVariant(ast::DefId /* enum */, ast::DefId /* variant */, bool /* is_structure */),
     DefTy(ast::DefId, bool /* is_enum */),
-    DefAssociatedTy(ast::DefId),
-    // A partially resolved path to an associated type `T::U` where `T` is a concrete
-    // type (indicated by the DefId) which implements a trait which has an associated
-    // type `U` (indicated by the Ident).
-    // FIXME(#20301) -- should use Name
-    DefAssociatedPath(TyParamProvenance, ast::Ident),
-    DefaultImpl(ast::DefId),
+    DefAssociatedTy(ast::DefId /* trait */, ast::DefId),
+    DefTrait(ast::DefId),
     DefPrimTy(ast::PrimTy),
     DefTyParam(ParamSpace, u32, ast::DefId, ast::Name),
     DefUse(ast::DefId),
@@ -54,14 +47,48 @@ pub enum Def {
     /// - If it's an ExprPath referring to some tuple struct, then DefMap maps
     ///   it to a def whose id is the StructDef.ctor_id.
     DefStruct(ast::DefId),
-    DefTyParamBinder(ast::NodeId), /* struct, impl or trait with ty params */
     DefRegion(ast::NodeId),
     DefLabel(ast::NodeId),
-    DefMethod(ast::DefId /* method */, Option<ast::DefId> /* trait */, MethodProvenance),
+    DefMethod(ast::DefId /* method */, MethodProvenance),
+}
+
+/// The result of resolving a path.
+/// Before type checking completes, `depth` represents the number of
+/// trailing segments which are yet unresolved. Afterwards, if there
+/// were no errors, all paths should be fully resolved, with `depth`
+/// set to `0` and `base_def` representing the final resolution.
+///
+///     module::Type::AssocX::AssocY::MethodOrAssocType
+///     ^~~~~~~~~~~~  ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+///     base_def      depth = 3
+///
+///     <T as Trait>::AssocX::AssocY::MethodOrAssocType
+///           ^~~~~~~~~~~~~~  ^~~~~~~~~~~~~~~~~~~~~~~~~
+///           base_def        depth = 2
+#[derive(Copy, Debug)]
+pub struct PathResolution {
+    pub base_def: Def,
+    pub last_private: LastPrivate,
+    pub depth: usize
+}
+
+impl PathResolution {
+    /// Get the definition, if fully resolved, otherwise panic.
+    pub fn full_def(&self) -> Def {
+        if self.depth != 0 {
+            panic!("path not fully resolved: {:?}", self);
+        }
+        self.base_def
+    }
+
+    /// Get the DefId, if fully resolved, otherwise panic.
+    pub fn def_id(&self) -> ast::DefId {
+        self.full_def().def_id()
+    }
 }
 
 // Definition mapping
-pub type DefMap = RefCell<NodeMap<Def>>;
+pub type DefMap = RefCell<NodeMap<PathResolution>>;
 // This is the replacement export map. It maps a module to all of the exports
 // within.
 pub type ExportMap = NodeMap<Vec<Export>>;
@@ -78,12 +105,6 @@ pub enum MethodProvenance {
     FromImpl(ast::DefId),
 }
 
-#[derive(Clone, Copy, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
-pub enum TyParamProvenance {
-    FromSelf(ast::DefId),
-    FromParam(ast::DefId),
-}
-
 impl MethodProvenance {
     pub fn map<F>(self, f: F) -> MethodProvenance where
         F: FnOnce(ast::DefId) -> ast::DefId,
@@ -95,34 +116,6 @@ pub fn map<F>(self, f: F) -> MethodProvenance where
     }
 }
 
-impl TyParamProvenance {
-    pub fn def_id(&self) -> ast::DefId {
-        match *self {
-            TyParamProvenance::FromSelf(ref did) => did.clone(),
-            TyParamProvenance::FromParam(ref did) => did.clone(),
-        }
-    }
-}
-
-#[derive(Clone, Copy, Eq, PartialEq)]
-pub enum TraitItemKind {
-    NonstaticMethodTraitItemKind,
-    StaticMethodTraitItemKind,
-    TypeTraitItemKind,
-}
-
-impl TraitItemKind {
-    pub fn from_explicit_self_category(explicit_self_category:
-                                       ExplicitSelfCategory)
-                                       -> TraitItemKind {
-        if explicit_self_category == StaticExplicitSelfCategory {
-            StaticMethodTraitItemKind
-        } else {
-            NonstaticMethodTraitItemKind
-        }
-    }
-}
-
 impl Def {
     pub fn local_node_id(&self) -> ast::NodeId {
         let def_id = self.def_id();
@@ -132,25 +125,21 @@ pub fn local_node_id(&self) -> ast::NodeId {
 
     pub fn def_id(&self) -> ast::DefId {
         match *self {
-            DefFn(id, _) | DefStaticMethod(id, _) | DefMod(id) |
-            DefForeignMod(id) | DefStatic(id, _) |
-            DefVariant(_, id, _) | DefTy(id, _) | DefAssociatedTy(id) |
-            DefTyParam(_, _, id, _) | DefUse(id) | DefStruct(id) | DefaultImpl(id) |
-            DefMethod(id, _, _) | DefConst(id) |
-            DefAssociatedPath(TyParamProvenance::FromSelf(id), _) |
-            DefAssociatedPath(TyParamProvenance::FromParam(id), _) => {
+            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) => {
                 id
             }
             DefLocal(id) |
             DefSelfTy(id) |
             DefUpvar(id, _) |
             DefRegion(id) |
-            DefTyParamBinder(id) |
             DefLabel(id) => {
                 local_def(id)
             }
 
-            DefPrimTy(_) => panic!()
+            DefPrimTy(_) => panic!("attempted .def_id() on DefPrimTy")
         }
     }
 
index ba81b2f3899a8b7406e2b8d60a16f9016e34a91e..9c85b7748ab0c3449118daaf2502ea9ffbe44538 100644 (file)
@@ -175,7 +175,7 @@ fn visit_expr(&mut self, expr: &ast::Expr) {
             ast::ExprInlineAsm(..) => {
                 self.require_unsafe(expr.span, "use of inline assembly");
             }
-            ast::ExprPath(_) | ast::ExprQPath(_) => {
+            ast::ExprPath(..) => {
                 if let def::DefStatic(_, true) = ty::resolve_expr(self.tcx, expr) {
                     self.require_unsafe(expr.span, "use of mutable static");
                 }
index 625093e3c5dea50bb8c976a39cbbbec3fa5962db..a1e38a1c8bda795d4c35e304cb35bc4bc406fc32 100644 (file)
@@ -422,7 +422,7 @@ pub fn walk_expr(&mut self, expr: &ast::Expr) {
                 self.walk_expr(&**subexpr)
             }
 
-            ast::ExprPath(_) | ast::ExprQPath(_) => { }
+            ast::ExprPath(..) => { }
 
             ast::ExprUnary(ast::UnDeref, ref base) => {      // *base
                 if !self.walk_overloaded_operator(expr, &**base, Vec::new(), PassArgs::ByRef) {
@@ -1017,7 +1017,7 @@ fn walk_pat(&mut self,
 
                 // Each match binding is effectively an assignment to the
                 // binding being produced.
-                let def = def_map.borrow()[pat.id].clone();
+                let def = def_map.borrow()[pat.id].full_def();
                 match mc.cat_def(pat.id, pat.span, pat_ty, def) {
                     Ok(binding_cmt) => {
                         delegate.mutate(pat.id, pat.span, binding_cmt, Init);
@@ -1097,13 +1097,13 @@ fn walk_pat(&mut self,
 
             match pat.node {
                 ast::PatEnum(_, _) | ast::PatIdent(_, _, None) | ast::PatStruct(..) => {
-                    match def_map.get(&pat.id) {
+                    match def_map.get(&pat.id).map(|d| d.full_def()) {
                         None => {
                             // no definition found: pat is not a
                             // struct or enum pattern.
                         }
 
-                        Some(&def::DefVariant(enum_did, variant_did, _is_struct)) => {
+                        Some(def::DefVariant(enum_did, variant_did, _is_struct)) => {
                             let downcast_cmt =
                                 if ty::enum_is_univariant(tcx, enum_did) {
                                     cmt_pat
@@ -1119,7 +1119,7 @@ fn walk_pat(&mut self,
                             delegate.matched_pat(pat, downcast_cmt, match_mode);
                         }
 
-                        Some(&def::DefStruct(..)) | Some(&def::DefTy(_, false)) => {
+                        Some(def::DefStruct(..)) | Some(def::DefTy(_, false)) => {
                             // A struct (in either the value or type
                             // namespace; we encounter the former on
                             // e.g. patterns for unit structs).
@@ -1131,14 +1131,14 @@ fn walk_pat(&mut self,
                             delegate.matched_pat(pat, cmt_pat, match_mode);
                         }
 
-                        Some(&def::DefConst(..)) |
-                        Some(&def::DefLocal(..)) => {
+                        Some(def::DefConst(..)) |
+                        Some(def::DefLocal(..)) => {
                             // This is a leaf (i.e. identifier binding
                             // or constant value to match); thus no
                             // `matched_pat` call.
                         }
 
-                        Some(def @ &def::DefTy(_, true)) => {
+                        Some(def @ def::DefTy(_, true)) => {
                             // An enum's type -- should never be in a
                             // pattern.
 
index 99cb2a0978e7eeb1668c1680504f13c364544c8a..b782a655d89ff11155bf156793000776a9c6bbed 100644 (file)
@@ -228,11 +228,11 @@ fn fn_sigs(&self, a: &ty::FnSig<'tcx>, b: &ty::FnSig<'tcx>) -> cres<'tcx, ty::Fn
                              variadic: a.variadic});
 
 
-        fn argvecs<'tcx, C: Combine<'tcx>>(combiner: &C,
-                                           a_args: &[Ty<'tcx>],
-                                           b_args: &[Ty<'tcx>])
-                                           -> cres<'tcx, Vec<Ty<'tcx>>>
-        {
+        fn argvecs<'tcx, C>(combiner: &C,
+                            a_args: &[Ty<'tcx>],
+                            b_args: &[Ty<'tcx>])
+                            -> cres<'tcx, Vec<Ty<'tcx>>>
+                            where C: Combine<'tcx> {
             if a_args.len() == b_args.len() {
                 a_args.iter().zip(b_args.iter())
                     .map(|(a, b)| combiner.args(*a, *b)).collect()
@@ -265,13 +265,7 @@ fn projection_tys(&self,
             Err(ty::terr_projection_name_mismatched(
                 expected_found(self, a.item_name, b.item_name)))
         } else {
-            // Note that the trait refs for the projection must be
-            // *equal*. This is because there is no inherent
-            // relationship between `<T as Foo>::Bar` and `<U as
-            // Foo>::Bar` that we can derive based on how `T` relates
-            // to `U`. Issue #21726 contains further discussion and
-            // in-depth examples.
-            let trait_ref = try!(self.equate().trait_refs(&*a.trait_ref, &*b.trait_ref));
+            let trait_ref = try!(self.trait_refs(&*a.trait_ref, &*b.trait_ref));
             Ok(ty::ProjectionTy { trait_ref: Rc::new(trait_ref), item_name: a.item_name })
         }
     }
@@ -351,51 +345,51 @@ pub trait Combineable<'tcx> : Repr<'tcx> + TypeFoldable<'tcx> {
 impl<'tcx,T> Combineable<'tcx> for Rc<T>
     where T : Combineable<'tcx>
 {
-    fn combine<C:Combine<'tcx>>(combiner: &C,
-                                a: &Rc<T>,
-                                b: &Rc<T>)
-                                -> cres<'tcx, Rc<T>>
-    {
+    fn combine<C>(combiner: &C,
+                  a: &Rc<T>,
+                  b: &Rc<T>)
+                  -> cres<'tcx, Rc<T>>
+                  where C: Combine<'tcx> {
         Ok(Rc::new(try!(Combineable::combine(combiner, &**a, &**b))))
     }
 }
 
 impl<'tcx> Combineable<'tcx> for ty::TraitRef<'tcx> {
-    fn combine<C:Combine<'tcx>>(combiner: &C,
-                                a: &ty::TraitRef<'tcx>,
-                                b: &ty::TraitRef<'tcx>)
-                                -> cres<'tcx, ty::TraitRef<'tcx>>
-    {
+    fn combine<C>(combiner: &C,
+                  a: &ty::TraitRef<'tcx>,
+                  b: &ty::TraitRef<'tcx>)
+                  -> cres<'tcx, ty::TraitRef<'tcx>>
+                  where C: Combine<'tcx> {
         combiner.trait_refs(a, b)
     }
 }
 
 impl<'tcx> Combineable<'tcx> for Ty<'tcx> {
-    fn combine<C:Combine<'tcx>>(combiner: &C,
-                                a: &Ty<'tcx>,
-                                b: &Ty<'tcx>)
-                                -> cres<'tcx, Ty<'tcx>>
-    {
+    fn combine<C>(combiner: &C,
+                  a: &Ty<'tcx>,
+                  b: &Ty<'tcx>)
+                  -> cres<'tcx, Ty<'tcx>>
+                  where C: Combine<'tcx> {
         combiner.tys(*a, *b)
     }
 }
 
 impl<'tcx> Combineable<'tcx> for ty::ProjectionPredicate<'tcx> {
-    fn combine<C:Combine<'tcx>>(combiner: &C,
-                                a: &ty::ProjectionPredicate<'tcx>,
-                                b: &ty::ProjectionPredicate<'tcx>)
-                                -> cres<'tcx, ty::ProjectionPredicate<'tcx>>
-    {
+    fn combine<C>(combiner: &C,
+                  a: &ty::ProjectionPredicate<'tcx>,
+                  b: &ty::ProjectionPredicate<'tcx>)
+                  -> cres<'tcx, ty::ProjectionPredicate<'tcx>>
+                  where C: Combine<'tcx> {
         combiner.projection_predicates(a, b)
     }
 }
 
 impl<'tcx> Combineable<'tcx> for ty::FnSig<'tcx> {
-    fn combine<C:Combine<'tcx>>(combiner: &C,
-                                a: &ty::FnSig<'tcx>,
-                                b: &ty::FnSig<'tcx>)
-                                -> cres<'tcx, ty::FnSig<'tcx>>
-    {
+    fn combine<C>(combiner: &C,
+                  a: &ty::FnSig<'tcx>,
+                  b: &ty::FnSig<'tcx>)
+                  -> cres<'tcx, ty::FnSig<'tcx>>
+                  where C: Combine<'tcx> {
         combiner.fn_sigs(a, b)
     }
 }
@@ -407,8 +401,11 @@ pub struct CombineFields<'a, 'tcx: 'a> {
     pub trace: TypeTrace<'tcx>,
 }
 
-pub fn expected_found<'tcx, C: Combine<'tcx>, T>(
-        this: &C, a: T, b: T) -> ty::expected_found<T> {
+pub fn expected_found<'tcx, C, T>(this: &C,
+                                  a: T,
+                                  b: T)
+                                  -> ty::expected_found<T>
+                                  where C: Combine<'tcx> {
     if this.a_is_expected() {
         ty::expected_found {expected: a, found: b}
     } else {
@@ -416,29 +413,26 @@ pub fn expected_found<'tcx, C: Combine<'tcx>, T>(
     }
 }
 
-pub fn super_tys<'tcx, C: Combine<'tcx>>(this: &C,
-                                         a: Ty<'tcx>,
-                                         b: Ty<'tcx>)
-                                         -> cres<'tcx, Ty<'tcx>>
-{
+pub fn super_tys<'tcx, C>(this: &C,
+                          a: Ty<'tcx>,
+                          b: Ty<'tcx>)
+                          -> cres<'tcx, Ty<'tcx>>
+                          where C: Combine<'tcx> {
     let tcx = this.infcx().tcx;
     let a_sty = &a.sty;
     let b_sty = &b.sty;
     debug!("super_tys: a_sty={:?} b_sty={:?}", a_sty, b_sty);
     return match (a_sty, b_sty) {
-      // The "subtype" ought to be handling cases involving var:
-      (&ty::ty_infer(TyVar(_)), _) |
-      (_, &ty::ty_infer(TyVar(_))) => {
-        tcx.sess.bug(
-            &format!("{}: bot and var types should have been handled ({},{})",
-                    this.tag(),
-                    a.repr(this.infcx().tcx),
-                    b.repr(this.infcx().tcx)));
-      }
-
-      (&ty::ty_err, _) | (_, &ty::ty_err) => {
-          Ok(tcx.types.err)
-      }
+        // The "subtype" ought to be handling cases involving var:
+        (&ty::ty_infer(TyVar(_)), _)
+        | (_, &ty::ty_infer(TyVar(_))) =>
+            tcx.sess.bug(
+                &format!("{}: bot and var types should have been handled ({},{})",
+                this.tag(),
+                a.repr(this.infcx().tcx),
+                b.repr(this.infcx().tcx))),
+
+        (&ty::ty_err, _) | (_, &ty::ty_err) => Ok(tcx.types.err),
 
         // Relate integral variables to other types
         (&ty::ty_infer(IntVar(a_id)), &ty::ty_infer(IntVar(b_id))) => {
@@ -475,68 +469,62 @@ pub fn super_tys<'tcx, C: Combine<'tcx>>(this: &C,
             unify_float_variable(this, !this.a_is_expected(), v_id, v)
         }
 
-      (&ty::ty_char, _) |
-      (&ty::ty_bool, _) |
-      (&ty::ty_int(_), _) |
-      (&ty::ty_uint(_), _) |
-      (&ty::ty_float(_), _) => {
-        if a == b {
-            Ok(a)
-        } else {
-            Err(ty::terr_sorts(expected_found(this, a, b)))
-        }
-      }
-
-      (&ty::ty_param(ref a_p), &ty::ty_param(ref b_p)) if
-          a_p.idx == b_p.idx && a_p.space == b_p.space => {
-        Ok(a)
-      }
-
-      (&ty::ty_enum(a_id, a_substs),
-       &ty::ty_enum(b_id, b_substs))
-      if a_id == b_id => {
-          let substs = try!(this.substs(a_id,
-                                          a_substs,
-                                          b_substs));
-          Ok(ty::mk_enum(tcx, a_id, tcx.mk_substs(substs)))
-      }
-
-      (&ty::ty_trait(ref a_),
-       &ty::ty_trait(ref b_)) => {
-          debug!("Trying to match traits {:?} and {:?}", a, b);
-          let principal = try!(this.binders(&a_.principal, &b_.principal));
-          let bounds = try!(this.existential_bounds(&a_.bounds, &b_.bounds));
-          Ok(ty::mk_trait(tcx, principal, bounds))
-      }
-
-      (&ty::ty_struct(a_id, a_substs), &ty::ty_struct(b_id, b_substs))
-      if a_id == b_id => {
+        (&ty::ty_char, _)
+        | (&ty::ty_bool, _)
+        | (&ty::ty_int(_), _)
+        | (&ty::ty_uint(_), _)
+        | (&ty::ty_float(_), _) => {
+            if a == b {
+                Ok(a)
+            } else {
+                Err(ty::terr_sorts(expected_found(this, a, b)))
+            }
+        }
+
+        (&ty::ty_param(ref a_p), &ty::ty_param(ref b_p)) if
+          a_p.idx == b_p.idx && a_p.space == b_p.space => Ok(a),
+
+        (&ty::ty_enum(a_id, a_substs), &ty::ty_enum(b_id, b_substs))
+          if a_id == b_id => {
+            let substs = try!(this.substs(a_id, a_substs, b_substs));
+            Ok(ty::mk_enum(tcx, a_id, tcx.mk_substs(substs)))
+        }
+
+        (&ty::ty_trait(ref a_), &ty::ty_trait(ref b_)) => {
+            debug!("Trying to match traits {:?} and {:?}", a, b);
+            let principal = try!(this.binders(&a_.principal, &b_.principal));
+            let bounds = try!(this.existential_bounds(&a_.bounds, &b_.bounds));
+            Ok(ty::mk_trait(tcx, principal, bounds))
+        }
+
+        (&ty::ty_struct(a_id, a_substs), &ty::ty_struct(b_id, b_substs))
+          if a_id == b_id => {
             let substs = try!(this.substs(a_id, a_substs, b_substs));
             Ok(ty::mk_struct(tcx, a_id, tcx.mk_substs(substs)))
-      }
-
-      (&ty::ty_closure(a_id, a_region, a_substs),
-       &ty::ty_closure(b_id, b_region, b_substs))
-      if a_id == b_id => {
-          // All ty_closure types with the same id represent
-          // the (anonymous) type of the same closure expression. So
-          // all of their regions should be equated.
-          let region = try!(this.equate().regions(*a_region, *b_region));
-          let substs = try!(this.substs_variances(None, a_substs, b_substs));
-          Ok(ty::mk_closure(tcx, a_id, tcx.mk_region(region), tcx.mk_substs(substs)))
-      }
-
-      (&ty::ty_uniq(a_inner), &ty::ty_uniq(b_inner)) => {
-          let typ = try!(this.tys(a_inner, b_inner));
-          Ok(ty::mk_uniq(tcx, typ))
-      }
-
-      (&ty::ty_ptr(ref a_mt), &ty::ty_ptr(ref b_mt)) => {
-          let mt = try!(this.mts(a_mt, b_mt));
-          Ok(ty::mk_ptr(tcx, mt))
-      }
-
-      (&ty::ty_rptr(a_r, ref a_mt), &ty::ty_rptr(b_r, ref b_mt)) => {
+        }
+
+        (&ty::ty_closure(a_id, a_region, a_substs),
+         &ty::ty_closure(b_id, b_region, b_substs))
+          if a_id == b_id => {
+            // All ty_closure types with the same id represent
+            // the (anonymous) type of the same closure expression. So
+            // all of their regions should be equated.
+            let region = try!(this.equate().regions(*a_region, *b_region));
+            let substs = try!(this.substs_variances(None, a_substs, b_substs));
+            Ok(ty::mk_closure(tcx, a_id, tcx.mk_region(region), tcx.mk_substs(substs)))
+        }
+
+        (&ty::ty_uniq(a_inner), &ty::ty_uniq(b_inner)) => {
+            let typ = try!(this.tys(a_inner, b_inner));
+            Ok(ty::mk_uniq(tcx, typ))
+        }
+
+        (&ty::ty_ptr(ref a_mt), &ty::ty_ptr(ref b_mt)) => {
+            let mt = try!(this.mts(a_mt, b_mt));
+            Ok(ty::mk_ptr(tcx, mt))
+        }
+
+        (&ty::ty_rptr(a_r, ref a_mt), &ty::ty_rptr(b_r, ref b_mt)) => {
             let r = try!(this.regions_with_variance(ty::Contravariant, *a_r, *b_r));
 
             // FIXME(14985)  If we have mutable references to trait objects, we
@@ -551,45 +539,43 @@ pub fn super_tys<'tcx, C: Combine<'tcx>>(this: &C,
                 _ => try!(this.mts(a_mt, b_mt))
             };
             Ok(ty::mk_rptr(tcx, tcx.mk_region(r), mt))
-      }
+        }
 
-      (&ty::ty_vec(a_t, Some(sz_a)), &ty::ty_vec(b_t, Some(sz_b))) => {
-        this.tys(a_t, b_t).and_then(|t| {
-            if sz_a == sz_b {
-                Ok(ty::mk_vec(tcx, t, Some(sz_a)))
-            } else {
-                Err(ty::terr_fixed_array_size(expected_found(this, sz_a, sz_b)))
-            }
-        })
-      }
+        (&ty::ty_vec(a_t, Some(sz_a)), &ty::ty_vec(b_t, Some(sz_b))) => {
+            this.tys(a_t, b_t).and_then(|t| {
+                if sz_a == sz_b {
+                    Ok(ty::mk_vec(tcx, t, Some(sz_a)))
+                } else {
+                    Err(ty::terr_fixed_array_size(expected_found(this, sz_a, sz_b)))
+                }
+            })
+        }
 
-      (&ty::ty_vec(a_t, sz_a), &ty::ty_vec(b_t, sz_b)) => {
-        this.tys(a_t, b_t).and_then(|t| {
-            if sz_a == sz_b {
-                Ok(ty::mk_vec(tcx, t, sz_a))
+        (&ty::ty_vec(a_t, sz_a), &ty::ty_vec(b_t, sz_b)) => {
+            this.tys(a_t, b_t).and_then(|t| {
+                if sz_a == sz_b {
+                    Ok(ty::mk_vec(tcx, t, sz_a))
+                } else {
+                    Err(ty::terr_sorts(expected_found(this, a, b)))
+                }
+            })
+        }
+
+        (&ty::ty_str, &ty::ty_str) => Ok(ty::mk_str(tcx)),
+
+        (&ty::ty_tup(ref as_), &ty::ty_tup(ref bs)) => {
+            if as_.len() == bs.len() {
+                as_.iter().zip(bs.iter())
+                   .map(|(a, b)| this.tys(*a, *b))
+                   .collect::<Result<_, _>>()
+                   .map(|ts| ty::mk_tup(tcx, ts))
+            } else if as_.len() != 0 && bs.len() != 0 {
+                Err(ty::terr_tuple_size(
+                    expected_found(this, as_.len(), bs.len())))
             } else {
                 Err(ty::terr_sorts(expected_found(this, a, b)))
             }
-        })
-      }
-
-      (&ty::ty_str, &ty::ty_str) => {
-            Ok(ty::mk_str(tcx))
-      }
-
-      (&ty::ty_tup(ref as_), &ty::ty_tup(ref bs)) => {
-        if as_.len() == bs.len() {
-            as_.iter().zip(bs.iter())
-               .map(|(a, b)| this.tys(*a, *b))
-               .collect::<Result<_, _>>()
-               .map(|ts| ty::mk_tup(tcx, ts))
-        } else if as_.len() != 0 && bs.len() != 0 {
-            Err(ty::terr_tuple_size(
-                expected_found(this, as_.len(), bs.len())))
-        } else {
-            Err(ty::terr_sorts(expected_found(this, a, b)))
         }
-      }
 
         (&ty::ty_bare_fn(a_opt_def_id, a_fty), &ty::ty_bare_fn(b_opt_def_id, b_fty))
             if a_opt_def_id == b_opt_def_id =>
@@ -598,33 +584,33 @@ pub fn super_tys<'tcx, C: Combine<'tcx>>(this: &C,
             Ok(ty::mk_bare_fn(tcx, a_opt_def_id, tcx.mk_bare_fn(fty)))
         }
 
-      (&ty::ty_projection(ref a_data), &ty::ty_projection(ref b_data)) => {
-          let projection_ty = try!(this.projection_tys(a_data, b_data));
-          Ok(ty::mk_projection(tcx, projection_ty.trait_ref, projection_ty.item_name))
-      }
+        (&ty::ty_projection(ref a_data), &ty::ty_projection(ref b_data)) => {
+            let projection_ty = try!(this.projection_tys(a_data, b_data));
+            Ok(ty::mk_projection(tcx, projection_ty.trait_ref, projection_ty.item_name))
+        }
 
-      _ => Err(ty::terr_sorts(expected_found(this, a, b)))
+        _ => Err(ty::terr_sorts(expected_found(this, a, b))),
     };
 
-    fn unify_integral_variable<'tcx, C: Combine<'tcx>>(
-        this: &C,
-        vid_is_expected: bool,
-        vid: ty::IntVid,
-        val: ty::IntVarValue) -> cres<'tcx, Ty<'tcx>>
-    {
+    fn unify_integral_variable<'tcx, C>(this: &C,
+                                        vid_is_expected: bool,
+                                        vid: ty::IntVid,
+                                        val: ty::IntVarValue)
+                                        -> cres<'tcx, Ty<'tcx>>
+                                        where C: Combine<'tcx> {
         try!(this.infcx().simple_var_t(vid_is_expected, vid, val));
         match val {
             IntType(v) => Ok(ty::mk_mach_int(this.tcx(), v)),
-            UintType(v) => Ok(ty::mk_mach_uint(this.tcx(), v))
+            UintType(v) => Ok(ty::mk_mach_uint(this.tcx(), v)),
         }
     }
 
-    fn unify_float_variable<'tcx, C: Combine<'tcx>>(
-        this: &C,
-        vid_is_expected: bool,
-        vid: ty::FloatVid,
-        val: ast::FloatTy) -> cres<'tcx, Ty<'tcx>>
-    {
+    fn unify_float_variable<'tcx, C>(this: &C,
+                                     vid_is_expected: bool,
+                                     vid: ty::FloatVid,
+                                     val: ast::FloatTy)
+                                     -> cres<'tcx, Ty<'tcx>>
+                                     where C: Combine<'tcx> {
         try!(this.infcx().simple_var_t(vid_is_expected, vid, val));
         Ok(ty::mk_mach_float(this.tcx(), val))
     }
@@ -696,12 +682,8 @@ pub fn instantiate(&self,
                 None => {     // ...not yet instantiated:
                     // Generalize type if necessary.
                     let generalized_ty = try!(match dir {
-                        EqTo => {
-                            self.generalize(a_ty, b_vid, false)
-                        }
-                        BiTo | SupertypeOf | SubtypeOf => {
-                            self.generalize(a_ty, b_vid, true)
-                        }
+                        EqTo => self.generalize(a_ty, b_vid, false),
+                        BiTo | SupertypeOf | SubtypeOf => self.generalize(a_ty, b_vid, true),
                     });
                     debug!("instantiate(a_ty={}, dir={:?}, \
                                         b_vid={}, generalized_ty={})",
@@ -723,22 +705,14 @@ pub fn instantiate(&self,
             // to associate causes/spans with each of the relations in
             // the stack to get this right.
             match dir {
-                BiTo => {
-                    try!(self.bivariate().tys(a_ty, b_ty));
-                }
+                BiTo => try!(self.bivariate().tys(a_ty, b_ty)),
 
-                EqTo => {
-                    try!(self.equate().tys(a_ty, b_ty));
-                }
+                EqTo => try!(self.equate().tys(a_ty, b_ty)),
 
-                SubtypeOf => {
-                    try!(self.sub().tys(a_ty, b_ty));
-                }
+                SubtypeOf => try!(self.sub().tys(a_ty, b_ty)),
 
-                SupertypeOf => {
-                    try!(self.sub().tys_with_variance(ty::Contravariant, a_ty, b_ty));
-                }
-            }
+                SupertypeOf => try!(self.sub().tys_with_variance(ty::Contravariant, a_ty, b_ty)),
+            };
         }
 
         Ok(())
@@ -754,11 +728,13 @@ fn generalize(&self,
                   make_region_vars: bool)
                   -> cres<'tcx, Ty<'tcx>>
     {
-        let mut generalize = Generalizer { infcx: self.infcx,
-                                           span: self.trace.origin.span(),
-                                           for_vid: for_vid,
-                                           make_region_vars: make_region_vars,
-                                           cycle_detected: false };
+        let mut generalize = Generalizer {
+            infcx: self.infcx,
+            span: self.trace.origin.span(),
+            for_vid: for_vid,
+            make_region_vars: make_region_vars,
+            cycle_detected: false
+        };
         let u = ty.fold_with(&mut generalize);
         if generalize.cycle_detected {
             Err(ty::terr_cyclic_ty)
index 110c7bf41e559136aa7e7f5059c45e5e140c44ee..da4df813030c3ab504f228b24935a4f1d5b4a79f 100644 (file)
@@ -1233,8 +1233,8 @@ fn rebuild_arg_ty_or_output(&self,
                     }
                     ty_queue.push(&*mut_ty.ty);
                 }
-                ast::TyPath(ref path, id) => {
-                    let a_def = match self.tcx.def_map.borrow().get(&id) {
+                ast::TyPath(ref maybe_qself, ref path) => {
+                    let a_def = match self.tcx.def_map.borrow().get(&cur_ty.id) {
                         None => {
                             self.tcx
                                 .sess
@@ -1242,7 +1242,7 @@ fn rebuild_arg_ty_or_output(&self,
                                         "unbound path {}",
                                         pprust::path_to_string(path)))
                         }
-                        Some(&d) => d
+                        Some(d) => d.full_def()
                     };
                     match a_def {
                         def::DefTy(did, _) | def::DefStruct(did) => {
@@ -1277,9 +1277,16 @@ fn rebuild_arg_ty_or_output(&self,
                                 region_names: region_names
                             };
                             let new_path = self.rebuild_path(rebuild_info, lifetime);
+                            let qself = maybe_qself.as_ref().map(|qself| {
+                                ast::QSelf {
+                                    ty: self.rebuild_arg_ty_or_output(&qself.ty, lifetime,
+                                                                      anon_nums, region_names),
+                                    position: qself.position
+                                }
+                            });
                             let to = ast::Ty {
                                 id: cur_ty.id,
-                                node: ast::TyPath(new_path, id),
+                                node: ast::TyPath(qself, new_path),
                                 span: cur_ty.span
                             };
                             new_ty = self.rebuild_ty(new_ty, P(to));
index 7800d99f8ed4ce7206bbe9b020b9255ae20d7a70..759d7357df1931d71b0843e61594c2dd4624cbcb 100644 (file)
@@ -1133,18 +1133,12 @@ fn contract_node(&self,
                 true // changed
             }
 
-            ErrorValue => {
-                false // no change
-            }
+            ErrorValue => false, // no change
 
             Value(a_region) => {
                 match a_data.classification {
-                    Expanding => {
-                        check_node(self, a_vid, a_data, a_region, b_region)
-                    }
-                    Contracting => {
-                        adjust_node(self, a_vid, a_data, a_region, b_region)
-                    }
+                    Expanding => check_node(self, a_vid, a_data, a_region, b_region),
+                    Contracting => adjust_node(self, a_vid, a_data, a_region, b_region),
                 }
             }
         };
@@ -1154,7 +1148,7 @@ fn check_node(this: &RegionVarBindings,
                       a_data: &mut VarData,
                       a_region: Region,
                       b_region: Region)
-                   -> bool {
+                      -> bool {
             if !this.is_subregion_of(a_region, b_region) {
                 debug!("Setting {:?} to ErrorValue: {} not subregion of {}",
                        a_vid,
@@ -1170,7 +1164,7 @@ fn adjust_node(this: &RegionVarBindings,
                        a_data: &mut VarData,
                        a_region: Region,
                        b_region: Region)
-                    -> bool {
+                       -> bool {
             match this.glb_concrete_regions(a_region, b_region) {
                 Ok(glb) => {
                     if glb == a_region {
index 145fccd7972bb5bcbf927d27d391abc5f4d41c97..2ac019aa964dc6f1f0f15c9c4a17e917d8085a13 100644 (file)
@@ -445,8 +445,8 @@ fn visit_arm(ir: &mut IrMaps, arm: &ast::Arm) {
 fn visit_expr(ir: &mut IrMaps, expr: &Expr) {
     match expr.node {
       // live nodes required for uses or definitions of variables:
-      ast::ExprPath(_) | ast::ExprQPath(_) => {
-        let def = ir.tcx.def_map.borrow()[expr.id].clone();
+      ast::ExprPath(..) => {
+        let def = ir.tcx.def_map.borrow()[expr.id].full_def();
         debug!("expr {}: path that leads to {:?}", expr.id, def);
         if let DefLocal(..) = def {
             ir.add_live_node_for_node(expr.id, ExprNode(expr.span));
@@ -705,8 +705,8 @@ fn find_loop_scope(&self,
             Some(_) => {
                 // Refers to a labeled loop. Use the results of resolve
                 // to find with one
-                match self.ir.tcx.def_map.borrow().get(&id) {
-                    Some(&DefLabel(loop_id)) => loop_id,
+                match self.ir.tcx.def_map.borrow().get(&id).map(|d| d.full_def()) {
+                    Some(DefLabel(loop_id)) => loop_id,
                     _ => self.ir.tcx.sess.span_bug(sp, "label on break/loop \
                                                         doesn't refer to a loop")
                 }
@@ -947,7 +947,7 @@ fn propagate_through_expr(&mut self, expr: &Expr, succ: LiveNode)
         match expr.node {
           // Interesting cases with control flow or which gen/kill
 
-          ast::ExprPath(_) | ast::ExprQPath(_) => {
+          ast::ExprPath(..) => {
               self.access_path(expr, succ, ACC_READ | ACC_USE)
           }
 
@@ -1275,7 +1275,7 @@ fn propagate_through_lvalue_components(&mut self,
         // just ignore such cases and treat them as reads.
 
         match expr.node {
-            ast::ExprPath(_) | ast::ExprQPath(_) => succ,
+            ast::ExprPath(..) => succ,
             ast::ExprField(ref e, _) => self.propagate_through_expr(&**e, succ),
             ast::ExprTupField(ref e, _) => self.propagate_through_expr(&**e, succ),
             _ => self.propagate_through_expr(expr, succ)
@@ -1286,7 +1286,7 @@ fn propagate_through_lvalue_components(&mut self,
     fn write_lvalue(&mut self, expr: &Expr, succ: LiveNode, acc: uint)
                     -> LiveNode {
         match expr.node {
-          ast::ExprPath(_) | ast::ExprQPath(_) => {
+          ast::ExprPath(..) => {
               self.access_path(expr, succ, acc)
           }
 
@@ -1300,7 +1300,7 @@ fn write_lvalue(&mut self, expr: &Expr, succ: LiveNode, acc: uint)
 
     fn access_path(&mut self, expr: &Expr, succ: LiveNode, acc: uint)
                    -> LiveNode {
-        match self.ir.tcx.def_map.borrow()[expr.id].clone() {
+        match self.ir.tcx.def_map.borrow()[expr.id].full_def() {
           DefLocal(nid) => {
             let ln = self.live_node(expr.id, expr.span);
             if acc != 0 {
@@ -1468,7 +1468,7 @@ fn check_expr(this: &mut Liveness, expr: &Expr) {
       ast::ExprBlock(..) | ast::ExprMac(..) | ast::ExprAddrOf(..) |
       ast::ExprStruct(..) | ast::ExprRepeat(..) | ast::ExprParen(..) |
       ast::ExprClosure(..) | ast::ExprPath(..) | ast::ExprBox(..) |
-      ast::ExprRange(..) | ast::ExprQPath(..) => {
+      ast::ExprRange(..) => {
         visit::walk_expr(this, expr);
       }
       ast::ExprIfLet(..) => {
@@ -1561,8 +1561,8 @@ fn check_ret(&self,
 
     fn check_lvalue(&mut self, expr: &Expr) {
         match expr.node {
-            ast::ExprPath(_) | ast::ExprQPath(_) => {
-                if let DefLocal(nid) = self.ir.tcx.def_map.borrow()[expr.id].clone() {
+            ast::ExprPath(..) => {
+                if let DefLocal(nid) = self.ir.tcx.def_map.borrow()[expr.id].full_def() {
                     // Assignment to an immutable variable or argument: only legal
                     // if there is no later assignment. If this local is actually
                     // mutable, then check for a reassignment to flag the mutability
index 5aa6be43002b56d2fa788b03071c6f8ebef35e76..c4446b87855ca622d6a5ebd4fcca78f7ca0b9042 100644 (file)
@@ -529,8 +529,8 @@ pub fn cat_expr_unadjusted(&self, expr: &ast::Expr) -> McResult<cmt<'tcx>> {
             }
           }
 
-          ast::ExprPath(_) | ast::ExprQPath(_) => {
-            let def = (*self.tcx().def_map.borrow())[expr.id];
+          ast::ExprPath(..) => {
+            let def = self.tcx().def_map.borrow()[expr.id].full_def();
             self.cat_def(expr.id, expr.span, expr_ty, def)
           }
 
@@ -575,14 +575,14 @@ pub fn cat_def(&self,
 
         match def {
           def::DefStruct(..) | def::DefVariant(..) | def::DefConst(..) |
-          def::DefFn(..) | def::DefStaticMethod(..) |  def::DefMethod(..) => {
+          def::DefFn(..) | def::DefMethod(..) => {
                 Ok(self.cat_rvalue_node(id, span, expr_ty))
           }
           def::DefMod(_) | def::DefForeignMod(_) | def::DefUse(_) |
-          def::DefaultImpl(_) | def::DefTy(..) | def::DefPrimTy(_) |
-          def::DefTyParam(..) | def::DefTyParamBinder(..) | def::DefRegion(_) |
+          def::DefTrait(_) | def::DefTy(..) | def::DefPrimTy(_) |
+          def::DefTyParam(..) | def::DefRegion(_) |
           def::DefLabel(_) | def::DefSelfTy(..) |
-          def::DefAssociatedTy(..) | def::DefAssociatedPath(..)=> {
+          def::DefAssociatedTy(..) => {
               Ok(Rc::new(cmt_ {
                   id:id,
                   span:span,
@@ -1199,14 +1199,13 @@ fn cat_pattern_<F>(&self, cmt: cmt<'tcx>, pat: &ast::Pat, op: &mut F)
 
         (*op)(self, cmt.clone(), pat);
 
-        let def_map = self.tcx().def_map.borrow();
-        let opt_def = def_map.get(&pat.id);
+        let opt_def = self.tcx().def_map.borrow().get(&pat.id).map(|d| d.full_def());
 
         // Note: This goes up here (rather than within the PatEnum arm
         // alone) because struct patterns can refer to struct types or
         // to struct variants within enums.
         let cmt = match opt_def {
-            Some(&def::DefVariant(enum_did, variant_did, _))
+            Some(def::DefVariant(enum_did, variant_did, _))
                 // univariant enums do not need downcasts
                 if !ty::enum_is_univariant(self.tcx(), enum_did) => {
                     self.cat_downcast(pat, cmt.clone(), cmt.ty, variant_did)
@@ -1224,7 +1223,7 @@ fn cat_pattern_<F>(&self, cmt: cmt<'tcx>, pat: &ast::Pat, op: &mut F)
           }
           ast::PatEnum(_, Some(ref subpats)) => {
             match opt_def {
-                Some(&def::DefVariant(..)) => {
+                Some(def::DefVariant(..)) => {
                     // variant(x, y, z)
                     for (i, subpat) in subpats.iter().enumerate() {
                         let subpat_ty = try!(self.pat_ty(&**subpat)); // see (*2)
@@ -1237,7 +1236,7 @@ fn cat_pattern_<F>(&self, cmt: cmt<'tcx>, pat: &ast::Pat, op: &mut F)
                         try!(self.cat_pattern_(subcmt, &**subpat, op));
                     }
                 }
-                Some(&def::DefStruct(..)) => {
+                Some(def::DefStruct(..)) => {
                     for (i, subpat) in subpats.iter().enumerate() {
                         let subpat_ty = try!(self.pat_ty(&**subpat)); // see (*2)
                         let cmt_field =
@@ -1247,7 +1246,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(..)) => {
                     for subpat in subpats {
                         try!(self.cat_pattern_(cmt.clone(), &**subpat, op));
                     }
index a7df2f4a5dafb4dfe3e4b90e6a2a0b748ca05f2f..c5abff3b96360bceaa9ca8b8d8124e02ad4fb08e 100644 (file)
@@ -34,8 +34,8 @@ pub fn pat_is_refutable(dm: &DefMap, pat: &ast::Pat) -> bool {
         ast::PatEnum(_, _) |
         ast::PatIdent(_, _, None) |
         ast::PatStruct(..) => {
-            match dm.borrow().get(&pat.id) {
-                Some(&DefVariant(..)) => true,
+            match dm.borrow().get(&pat.id).map(|d| d.full_def()) {
+                Some(DefVariant(..)) => true,
                 _ => false
             }
         }
@@ -49,8 +49,8 @@ pub fn pat_is_variant_or_struct(dm: &DefMap, pat: &ast::Pat) -> bool {
         ast::PatEnum(_, _) |
         ast::PatIdent(_, _, None) |
         ast::PatStruct(..) => {
-            match dm.borrow().get(&pat.id) {
-                Some(&DefVariant(..)) | Some(&DefStruct(..)) => true,
+            match dm.borrow().get(&pat.id).map(|d| d.full_def()) {
+                Some(DefVariant(..)) | Some(DefStruct(..)) => true,
                 _ => false
             }
         }
@@ -61,8 +61,8 @@ 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(..) => {
-            match dm.borrow().get(&pat.id) {
-                Some(&DefConst(..)) => true,
+            match dm.borrow().get(&pat.id).map(|d| d.full_def()) {
+                Some(DefConst(..)) => true,
                 _ => false
             }
         }
index dd1e32d13a2be07d512d3d506f159b8387d13f51..3a253735f925b032e93390ce3618f6c4aa4aec87 100644 (file)
@@ -16,7 +16,7 @@
 pub use self::ImportUse::*;
 pub use self::LastPrivate::*;
 
-use util::nodemap::{DefIdSet, NodeMap, NodeSet};
+use util::nodemap::{DefIdSet, NodeSet};
 
 use syntax::ast;
 
@@ -32,9 +32,6 @@
 /// reexporting a public struct doesn't inline the doc).
 pub type PublicItems = NodeSet;
 
-// FIXME: dox
-pub type LastPrivateMap = NodeMap<LastPrivate>;
-
 #[derive(Copy, Debug)]
 pub enum LastPrivate {
     LastMod(PrivateDep),
index 550f4e39447f8252298a6a33fa41c7c9d6207adb..45d565ec693807f63e74e3887839602091372ecd 100644 (file)
@@ -94,9 +94,9 @@ impl<'a, 'tcx, 'v> Visitor<'v> for ReachableContext<'a, 'tcx> {
     fn visit_expr(&mut self, expr: &ast::Expr) {
 
         match expr.node {
-            ast::ExprPath(_) | ast::ExprQPath(_) => {
+            ast::ExprPath(..) => {
                 let def = match self.tcx.def_map.borrow().get(&expr.id) {
-                    Some(&def) => def,
+                    Some(d) => d.full_def(),
                     None => {
                         self.tcx.sess.span_bug(expr.span,
                                                "def ID not in def map?!")
index bef98f5bd02beecb7a2199137f8c6a99dafb131d..a8a2887644a9da40a237e472e9f0e5a66985f4e4 100644 (file)
@@ -165,13 +165,13 @@ fn visit_ty(&mut self, ty: &ast::Ty) {
                     visit::walk_ty(this, ty);
                 });
             }
-            ast::TyPath(ref path, id) => {
+            ast::TyPath(None, ref path) => {
                 // if this path references a trait, then this will resolve to
                 // a trait ref, which introduces a binding scope.
-                match self.def_map.borrow().get(&id) {
-                    Some(&def::DefaultImpl(..)) => {
+                match self.def_map.borrow().get(&ty.id).map(|d| (d.base_def, d.depth)) {
+                    Some((def::DefTrait(..), 0)) => {
                         self.with(LateScope(&Vec::new(), self.scope), |_, this| {
-                            this.visit_path(path, id);
+                            this.visit_path(path, ty.id);
                         });
                     }
                     _ => {
@@ -270,16 +270,12 @@ fn visit_poly_trait_ref(&mut self,
                 for lifetime in &trait_ref.bound_lifetimes {
                     this.visit_lifetime_def(lifetime);
                 }
-                this.visit_trait_ref(&trait_ref.trait_ref)
+                visit::walk_path(this, &trait_ref.trait_ref.path)
             })
         } else {
             self.visit_trait_ref(&trait_ref.trait_ref)
         }
     }
-
-    fn visit_trait_ref(&mut self, trait_ref: &ast::TraitRef) {
-        self.visit_path(&trait_ref.path, trait_ref.ref_id);
-    }
 }
 
 impl<'a> LifetimeContext<'a> {
index cfa5e5fce387930a2a71a6ef89c2dc3b3fdd1824..ddac6cc75143ba85ab176ab3a5d89b013f2884c0 100644 (file)
@@ -58,8 +58,10 @@ fn annotate<F>(&mut self, id: NodeId, use_parent: bool,
                    attrs: &Vec<Attribute>, item_sp: Span, f: F, required: bool) where
         F: FnOnce(&mut Annotator),
     {
+        debug!("annotate(id = {:?}, attrs = {:?})", id, attrs);
         match attr::find_stability(self.sess.diagnostic(), attrs, item_sp) {
             Some(stab) => {
+                debug!("annotate: found {:?}", stab);
                 self.index.local.insert(id, stab.clone());
 
                 // Don't inherit #[stable(feature = "rust1", since = "1.0.0")]
@@ -72,6 +74,8 @@ fn annotate<F>(&mut self, id: NodeId, use_parent: bool,
                 }
             }
             None => {
+                debug!("annotate: not found, use_parent = {:?}, parent = {:?}",
+                       use_parent, self.parent);
                 if use_parent {
                     if let Some(stab) = self.parent.clone() {
                         self.index.local.insert(id, stab);
@@ -299,6 +303,12 @@ fn visit_path(&mut self, path: &ast::Path, id: ast::NodeId) {
                    &mut |id, sp, stab| self.check(id, sp, stab));
         visit::walk_path(self, path)
     }
+
+    fn visit_pat(&mut self, pat: &ast::Pat) {
+        check_pat(self.tcx, pat,
+                  &mut |id, sp, stab| self.check(id, sp, stab));
+        visit::walk_pat(self, pat)
+    }
 }
 
 /// Helper for discovering nodes to check for stability
@@ -385,6 +395,76 @@ pub fn check_expr(tcx: &ty::ctxt, e: &ast::Expr,
                 None => return
             }
         }
+        ast::ExprField(ref base_e, ref field) => {
+            span = field.span;
+            match ty::expr_ty_adjusted(tcx, base_e).sty {
+                ty::ty_struct(did, _) => {
+                    ty::lookup_struct_fields(tcx, did)
+                        .iter()
+                        .find(|f| f.name == field.node.name)
+                        .unwrap_or_else(|| {
+                            tcx.sess.span_bug(field.span,
+                                              "stability::check_expr: unknown named field access")
+                        })
+                        .id
+                }
+                _ => tcx.sess.span_bug(e.span,
+                                       "stability::check_expr: named field access on non-struct")
+            }
+        }
+        ast::ExprTupField(ref base_e, ref field) => {
+            span = field.span;
+            match ty::expr_ty_adjusted(tcx, base_e).sty {
+                ty::ty_struct(did, _) => {
+                    ty::lookup_struct_fields(tcx, did)
+                        .get(field.node)
+                        .unwrap_or_else(|| {
+                            tcx.sess.span_bug(field.span,
+                                              "stability::check_expr: unknown unnamed field access")
+                        })
+                        .id
+                }
+                ty::ty_tup(..) => return,
+                _ => tcx.sess.span_bug(e.span,
+                                       "stability::check_expr: unnamed field access on \
+                                        something other than a tuple or struct")
+            }
+        }
+        ast::ExprStruct(_, ref expr_fields, _) => {
+            let type_ = ty::expr_ty(tcx, e);
+            match type_.sty {
+                ty::ty_struct(did, _) => {
+                    let struct_fields = ty::lookup_struct_fields(tcx, did);
+                    // check the stability of each field that appears
+                    // in the construction expression.
+                    for field in expr_fields {
+                        let did = struct_fields
+                            .iter()
+                            .find(|f| f.name == field.ident.node.name)
+                            .unwrap_or_else(|| {
+                                tcx.sess.span_bug(field.span,
+                                                  "stability::check_expr: unknown named \
+                                                   field access")
+                            })
+                            .id;
+                        maybe_do_stability_check(tcx, did, field.span, cb);
+                    }
+
+                    // we're done.
+                    return
+                }
+                // we don't look at stability attributes on
+                // struct-like enums (yet...), but it's definitely not
+                // a bug to have construct one.
+                ty::ty_enum(..) => return,
+                _ => {
+                    tcx.sess.span_bug(e.span,
+                                      &format!("stability::check_expr: struct construction \
+                                                of non-struct, type {:?}",
+                                               type_.repr(tcx)));
+                }
+            }
+        }
         _ => return
     };
 
@@ -393,12 +473,55 @@ pub fn check_expr(tcx: &ty::ctxt, e: &ast::Expr,
 
 pub fn check_path(tcx: &ty::ctxt, path: &ast::Path, id: ast::NodeId,
                   cb: &mut FnMut(ast::DefId, Span, &Option<Stability>)) {
-    let did = match tcx.def_map.borrow().get(&id) {
-        Some(&def::DefPrimTy(..)) => return,
-        Some(def) => def.def_id(),
-        None => return
+    match tcx.def_map.borrow().get(&id).map(|d| d.full_def()) {
+        Some(def::DefPrimTy(..)) => {}
+        Some(def) => {
+            maybe_do_stability_check(tcx, def.def_id(), path.span, cb);
+        }
+        None => {}
+    }
+
+}
+
+pub fn check_pat(tcx: &ty::ctxt, pat: &ast::Pat,
+                 cb: &mut FnMut(ast::DefId, Span, &Option<Stability>)) {
+    debug!("check_pat(pat = {:?})", pat);
+    if is_internal(tcx, pat.span) { return; }
+
+    let did = match ty::pat_ty_opt(tcx, pat) {
+        Some(&ty::TyS { sty: ty::ty_struct(did, _), .. }) => did,
+        Some(_) | None => return,
     };
-    maybe_do_stability_check(tcx, did, path.span, cb)
+    let struct_fields = ty::lookup_struct_fields(tcx, did);
+    match pat.node {
+        // Foo(a, b, c)
+        ast::PatEnum(_, Some(ref pat_fields)) => {
+            for (field, struct_field) in pat_fields.iter().zip(struct_fields.iter()) {
+                // a .. pattern is fine, but anything positional is
+                // not.
+                if let ast::PatWild(ast::PatWildMulti) = field.node {
+                    continue
+                }
+                maybe_do_stability_check(tcx, struct_field.id, field.span, cb)
+            }
+        }
+        // Foo { a, b, c }
+        ast::PatStruct(_, ref pat_fields, _) => {
+            for field in pat_fields {
+                let did = struct_fields
+                    .iter()
+                    .find(|f| f.name == field.node.ident.name)
+                    .unwrap_or_else(|| {
+                        tcx.sess.span_bug(field.span,
+                                          "stability::check_pat: unknown named field access")
+                    })
+                    .id;
+                maybe_do_stability_check(tcx, did, field.span, cb);
+            }
+        }
+        // everything else is fine.
+        _ => {}
+    }
 }
 
 fn maybe_do_stability_check(tcx: &ty::ctxt, id: ast::DefId, span: Span,
index 4d45bb841f49ff0cecf1d999366c8a73b8110236..62b81f0ebe7dba8b98e7d4368d755f4aba55da64 100644 (file)
@@ -52,9 +52,16 @@ fn overlap(selcx: &mut SelectionContext,
            b_def_id: ast::DefId)
            -> bool
 {
+    debug!("overlap(a_def_id={}, b_def_id={})",
+           a_def_id.repr(selcx.tcx()),
+           b_def_id.repr(selcx.tcx()));
+
     let (a_trait_ref, a_obligations) = impl_trait_ref_and_oblig(selcx, a_def_id);
     let (b_trait_ref, b_obligations) = impl_trait_ref_and_oblig(selcx, b_def_id);
 
+    debug!("overlap: a_trait_ref={}", a_trait_ref.repr(selcx.tcx()));
+    debug!("overlap: b_trait_ref={}", b_trait_ref.repr(selcx.tcx()));
+
     // Does `a <: b` hold? If not, no overlap.
     if let Err(_) = infer::mk_sub_poly_trait_refs(selcx.infcx(),
                                                   true,
@@ -64,10 +71,20 @@ fn overlap(selcx: &mut SelectionContext,
         return false;
     }
 
+    debug!("overlap: subtraitref check succeeded");
+
     // Are any of the obligations unsatisfiable? If so, no overlap.
-    a_obligations.iter()
-                 .chain(b_obligations.iter())
-                 .all(|o| selcx.evaluate_obligation(o))
+    let opt_failing_obligation =
+        a_obligations.iter()
+                     .chain(b_obligations.iter())
+                     .find(|o| !selcx.evaluate_obligation(o));
+
+    if let Some(failing_obligation) = opt_failing_obligation {
+        debug!("overlap: obligation unsatisfiable {}", failing_obligation.repr(selcx.tcx()));
+        return false;
+    }
+
+    true
 }
 
 /// Instantiate fresh variables for all bound parameters of the impl
index 8b836fd322e3cb8e99dbad196fe552e8fb7f6ccf..5a5639c701291f54716eba3b701e76f8bc825786 100644 (file)
@@ -18,7 +18,7 @@
 use middle::subst;
 use middle::ty::{self, HasProjectionTypes, Ty};
 use middle::ty_fold::TypeFoldable;
-use middle::infer::{self, InferCtxt};
+use middle::infer::{self, fixup_err_to_string, InferCtxt};
 use std::slice::Iter;
 use std::rc::Rc;
 use syntax::ast;
@@ -395,53 +395,64 @@ pub fn type_known_to_meet_builtin_bound<'a,'tcx>(infcx: &InferCtxt<'a,'tcx>,
     }
 }
 
+/// Normalizes the parameter environment, reporting errors if they occur.
 pub fn normalize_param_env_or_error<'a,'tcx>(unnormalized_env: ty::ParameterEnvironment<'a,'tcx>,
                                              cause: ObligationCause<'tcx>)
                                              -> ty::ParameterEnvironment<'a,'tcx>
 {
-    match normalize_param_env(&unnormalized_env, cause) {
-        Ok(p) => p,
+    // I'm not wild about reporting errors here; I'd prefer to
+    // have the errors get reported at a defined place (e.g.,
+    // during typeck). Instead I have all parameter
+    // environments, in effect, going through this function
+    // and hence potentially reporting errors. This ensurse of
+    // course that we never forget to normalize (the
+    // alternative seemed like it would involve a lot of
+    // manual invocations of this fn -- and then we'd have to
+    // deal with the errors at each of those sites).
+    //
+    // In any case, in practice, typeck constructs all the
+    // parameter environments once for every fn as it goes,
+    // and errors will get reported then; so after typeck we
+    // can be sure that no errors should occur.
+
+    let tcx = unnormalized_env.tcx;
+    let span = cause.span;
+    let body_id = cause.body_id;
+
+    debug!("normalize_param_env_or_error(unnormalized_env={})",
+           unnormalized_env.repr(tcx));
+
+    let infcx = infer::new_infer_ctxt(tcx);
+    let predicates = match fully_normalize(&infcx, &unnormalized_env, cause,
+                                           &unnormalized_env.caller_bounds) {
+        Ok(predicates) => predicates,
         Err(errors) => {
-            // I'm not wild about reporting errors here; I'd prefer to
-            // have the errors get reported at a defined place (e.g.,
-            // during typeck). Instead I have all parameter
-            // environments, in effect, going through this function
-            // and hence potentially reporting errors. This ensurse of
-            // course that we never forget to normalize (the
-            // alternative seemed like it would involve a lot of
-            // manual invocations of this fn -- and then we'd have to
-            // deal with the errors at each of those sites).
-            //
-            // In any case, in practice, typeck constructs all the
-            // parameter environments once for every fn as it goes,
-            // and errors will get reported then; so after typeck we
-            // can be sure that no errors should occur.
-            let infcx = infer::new_infer_ctxt(unnormalized_env.tcx);
             report_fulfillment_errors(&infcx, &errors);
-
-            // Normalized failed? use what they gave us, it's better than nothing.
-            unnormalized_env
+            return unnormalized_env; // an unnormalized env is better than nothing
         }
-    }
-}
-
-pub fn normalize_param_env<'a,'tcx>(param_env: &ty::ParameterEnvironment<'a,'tcx>,
-                                    cause: ObligationCause<'tcx>)
-                                    -> Result<ty::ParameterEnvironment<'a,'tcx>,
-                                              Vec<FulfillmentError<'tcx>>>
-{
-    let tcx = param_env.tcx;
-
-    debug!("normalize_param_env(param_env={})",
-           param_env.repr(tcx));
+    };
 
-    let infcx = infer::new_infer_ctxt(tcx);
-    let predicates = try!(fully_normalize(&infcx, param_env, cause, &param_env.caller_bounds));
+    infcx.resolve_regions_and_report_errors(body_id);
+    let predicates = match infcx.fully_resolve(&predicates) {
+        Ok(predicates) => predicates,
+        Err(fixup_err) => {
+            // If we encounter a fixup error, it means that some type
+            // variable wound up unconstrained. I actually don't know
+            // if this can happen, and I certainly don't expect it to
+            // happen often, but if it did happen it probably
+            // represents a legitimate failure due to some kind of
+            // unconstrained variable, and it seems better not to ICE,
+            // all things considered.
+            let err_msg = fixup_err_to_string(fixup_err);
+            tcx.sess.span_err(span, &err_msg);
+            return unnormalized_env; // an unnormalized env is better than nothing
+        }
+    };
 
-    debug!("normalize_param_env: predicates={}",
+    debug!("normalize_param_env_or_error: predicates={}",
            predicates.repr(tcx));
 
-    Ok(param_env.with_caller_bounds(predicates))
+    unnormalized_env.with_caller_bounds(predicates)
 }
 
 pub fn fully_normalize<'a,'tcx,T>(infcx: &InferCtxt<'a,'tcx>,
@@ -453,8 +464,7 @@ pub fn fully_normalize<'a,'tcx,T>(infcx: &InferCtxt<'a,'tcx>,
 {
     let tcx = closure_typer.tcx();
 
-    debug!("normalize_param_env(value={})",
-           value.repr(tcx));
+    debug!("normalize_param_env(value={})", value.repr(tcx));
 
     let mut selcx = &mut SelectionContext::new(infcx, closure_typer);
     let mut fulfill_cx = FulfillmentContext::new();
@@ -468,8 +478,7 @@ pub fn fully_normalize<'a,'tcx,T>(infcx: &InferCtxt<'a,'tcx>,
     }
     try!(fulfill_cx.select_all_or_error(infcx, closure_typer));
     let resolved_value = infcx.resolve_type_vars_if_possible(&normalized_value);
-    debug!("normalize_param_env: resolved_value={}",
-           resolved_value.repr(tcx));
+    debug!("normalize_param_env: resolved_value={}", resolved_value.repr(tcx));
     Ok(resolved_value)
 }
 
index 8086ca71e019ed556cf939cf0f40dcde84bc4c5c..9ec89f55b8f329cd61ae5715580cb65aed420893 100644 (file)
@@ -1409,27 +1409,23 @@ fn builtin_bound(&mut self,
 
         let self_ty = self.infcx.shallow_resolve(obligation.predicate.0.self_ty());
         return match self_ty.sty {
-            ty::ty_infer(ty::IntVar(_)) |
-            ty::ty_infer(ty::FloatVar(_)) |
-            ty::ty_uint(_) |
-            ty::ty_int(_) |
-            ty::ty_bool |
-            ty::ty_float(_) |
-            ty::ty_bare_fn(..) |
-            ty::ty_char => {
+            ty::ty_infer(ty::IntVar(_))
+            | ty::ty_infer(ty::FloatVar(_))
+            | ty::ty_uint(_)
+            | ty::ty_int(_)
+            | ty::ty_bool
+            | ty::ty_float(_)
+            | ty::ty_bare_fn(..)
+            ty::ty_char => {
                 // safe for everything
                 Ok(If(Vec::new()))
             }
 
             ty::ty_uniq(_) => {  // Box<T>
                 match bound {
-                    ty::BoundCopy => {
-                        Err(Unimplemented)
-                    }
+                    ty::BoundCopy => Err(Unimplemented),
 
-                    ty::BoundSized => {
-                        Ok(If(Vec::new()))
-                    }
+                    ty::BoundSized => Ok(If(Vec::new())),
 
                     ty::BoundSync | ty::BoundSend => {
                         self.tcx().sess.bug("Send/Sync shouldn't occur in builtin_bounds()");
@@ -1439,9 +1435,7 @@ fn builtin_bound(&mut self,
 
             ty::ty_ptr(..) => {     // *const T, *mut T
                 match bound {
-                    ty::BoundCopy | ty::BoundSized => {
-                        Ok(If(Vec::new()))
-                    }
+                    ty::BoundCopy | ty::BoundSized => Ok(If(Vec::new())),
 
                     ty::BoundSync | ty::BoundSend => {
                         self.tcx().sess.bug("Send/Sync shouldn't occur in builtin_bounds()");
@@ -1451,9 +1445,7 @@ fn builtin_bound(&mut self,
 
             ty::ty_trait(ref data) => {
                 match bound {
-                    ty::BoundSized => {
-                        Err(Unimplemented)
-                    }
+                    ty::BoundSized => Err(Unimplemented),
                     ty::BoundCopy => {
                         if data.bounds.builtin_bounds.contains(&bound) {
                             Ok(If(Vec::new()))
@@ -1485,20 +1477,14 @@ fn builtin_bound(&mut self,
                     ty::BoundCopy => {
                         match mutbl {
                             // &mut T is affine and hence never `Copy`
-                            ast::MutMutable => {
-                                Err(Unimplemented)
-                            }
+                            ast::MutMutable => Err(Unimplemented),
 
                             // &T is always copyable
-                            ast::MutImmutable => {
-                                Ok(If(Vec::new()))
-                            }
+                            ast::MutImmutable => Ok(If(Vec::new())),
                         }
                     }
 
-                    ty::BoundSized => {
-                        Ok(If(Vec::new()))
-                    }
+                    ty::BoundSized => Ok(If(Vec::new())),
 
                     ty::BoundSync | ty::BoundSend => {
                         self.tcx().sess.bug("Send/Sync shouldn't occur in builtin_bounds()");
@@ -1511,14 +1497,11 @@ fn builtin_bound(&mut self,
                 match bound {
                     ty::BoundCopy => {
                         match *len {
-                            Some(_) => {
-                                // [T, ..n] is copy iff T is copy
-                                Ok(If(vec![element_ty]))
-                            }
-                            None => {
-                                // [T] is unsized and hence affine
-                                Err(Unimplemented)
-                            }
+                            // [T, ..n] is copy iff T is copy
+                            Some(_) => Ok(If(vec![element_ty])),
+
+                            // [T] is unsized and hence affine
+                            None => Err(Unimplemented),
                         }
                     }
 
@@ -1543,16 +1526,12 @@ fn builtin_bound(&mut self,
                         self.tcx().sess.bug("Send/Sync shouldn't occur in builtin_bounds()");
                     }
 
-                    ty::BoundCopy | ty::BoundSized => {
-                        Err(Unimplemented)
-                    }
+                    ty::BoundCopy | ty::BoundSized => Err(Unimplemented),
                 }
             }
 
-            ty::ty_tup(ref tys) => {
-                // (T1, ..., Tn) -- meets any bound that all of T1...Tn meet
-                Ok(If(tys.clone()))
-            }
+            // (T1, ..., Tn) -- meets any bound that all of T1...Tn meet
+            ty::ty_tup(ref tys) => Ok(If(tys.clone())),
 
             ty::ty_closure(def_id, _, substs) => {
                 // FIXME -- This case is tricky. In the case of by-ref
@@ -1581,9 +1560,7 @@ fn builtin_bound(&mut self,
                 }
 
                 match self.closure_typer.closure_upvars(def_id, substs) {
-                    Some(upvars) => {
-                        Ok(If(upvars.iter().map(|c| c.ty).collect()))
-                    }
+                    Some(upvars) => Ok(If(upvars.iter().map(|c| c.ty).collect())),
                     None => {
                         debug!("assemble_builtin_bound_candidates: no upvar types available yet");
                         Ok(AmbiguousBuiltin)
@@ -1609,8 +1586,7 @@ fn builtin_bound(&mut self,
                 nominal(bound, types)
             }
 
-            ty::ty_projection(_) |
-            ty::ty_param(_) => {
+            ty::ty_projection(_) | ty::ty_param(_) => {
                 // Note: A type parameter is only considered to meet a
                 // particular bound if there is a where clause telling
                 // us that it does, and that case is handled by
@@ -1626,12 +1602,10 @@ fn builtin_bound(&mut self,
                 Ok(AmbiguousBuiltin)
             }
 
-            ty::ty_err => {
-                Ok(If(Vec::new()))
-            }
+            ty::ty_err => Ok(If(Vec::new())),
 
-            ty::ty_infer(ty::FreshTy(_)) |
-            ty::ty_infer(ty::FreshIntTy(_)) => {
+            ty::ty_infer(ty::FreshTy(_))
+            ty::ty_infer(ty::FreshIntTy(_)) => {
                 self.tcx().sess.bug(
                     &format!(
                         "asked to assemble builtin bounds of unexpected type: {}",
@@ -1641,7 +1615,7 @@ fn builtin_bound(&mut self,
 
         fn nominal<'cx, 'tcx>(bound: ty::BuiltinBound,
                               types: Vec<Ty<'tcx>>)
-                              -> Result<BuiltinBoundConditions<'tcx>,SelectionError<'tcx>>
+                              -> Result<BuiltinBoundConditions<'tcx>, SelectionError<'tcx>>
         {
             // First check for markers and other nonsense.
             match bound {
@@ -1692,7 +1666,7 @@ fn constituent_types_for_ty(&self, t: Ty<'tcx>) -> Option<Vec<Ty<'tcx>>> {
                 self.tcx().sess.bug(
                     &format!(
                         "asked to assemble constituent types of unexpected type: {}",
-                        t.repr(self.tcx()))[]);
+                        t.repr(self.tcx())));
             }
 
             ty::ty_uniq(referent_ty) => {  // Box<T>
@@ -1909,7 +1883,7 @@ fn vtable_builtin_data(&mut self,
         }).collect::<Result<_, _>>();
         let obligations = match obligations {
             Ok(o) => o,
-            Err(ErrorReported) => Vec::new()
+            Err(ErrorReported) => Vec::new(),
         };
 
         let obligations = VecPerParamSpace::new(obligations, Vec::new(), Vec::new());
@@ -1937,14 +1911,12 @@ fn confirm_default_impl_candidate(&mut self,
 
         let self_ty = self.infcx.shallow_resolve(obligation.predicate.0.self_ty());
         match self.constituent_types_for_ty(self_ty) {
-            Some(types) => {
-                Ok(self.vtable_default_impl(obligation, impl_def_id, types))
-            }
+            Some(types) => Ok(self.vtable_default_impl(obligation, impl_def_id, types)),
             None => {
                 self.tcx().sess.bug(
                     &format!(
                         "asked to confirm default implementation for ambiguous type: {}",
-                        self_ty.repr(self.tcx()))[]);
+                        self_ty.repr(self.tcx())));
             }
         }
     }
@@ -2223,9 +2195,7 @@ fn rematch_impl(&mut self,
     {
         match self.match_impl(impl_def_id, obligation, snapshot,
                               skol_map, skol_obligation_trait_ref) {
-            Ok(substs) => {
-                substs
-            }
+            Ok(substs) => substs,
             Err(()) => {
                 self.tcx().sess.bug(
                     &format!("Impl {} was matchable against {} but now is not",
@@ -2273,30 +2243,26 @@ fn match_impl(&mut self,
                skol_obligation_trait_ref.repr(self.tcx()));
 
         let origin = infer::RelateOutputImplTypes(obligation.cause.span);
-        match self.infcx.sub_trait_refs(false,
-                                        origin,
-                                        impl_trait_ref.value.clone(),
-                                        skol_obligation_trait_ref) {
-            Ok(()) => { }
-            Err(e) => {
-                debug!("match_impl: failed sub_trait_refs due to `{}`",
-                       ty::type_err_to_str(self.tcx(), &e));
-                return Err(());
-            }
+        if let Err(e) = self.infcx.sub_trait_refs(false,
+                                                  origin,
+                                                  impl_trait_ref.value.clone(),
+                                                  skol_obligation_trait_ref) {
+            debug!("match_impl: failed sub_trait_refs due to `{}`",
+                   ty::type_err_to_str(self.tcx(), &e));
+            return Err(());
         }
 
-        match self.infcx.leak_check(skol_map, snapshot) {
-            Ok(()) => { }
-            Err(e) => {
-                debug!("match_impl: failed leak check due to `{}`",
-                       ty::type_err_to_str(self.tcx(), &e));
-                return Err(());
-            }
+        if let Err(e) = self.infcx.leak_check(skol_map, snapshot) {
+            debug!("match_impl: failed leak check due to `{}`",
+                   ty::type_err_to_str(self.tcx(), &e));
+            return Err(());
         }
 
         debug!("match_impl: success impl_substs={}", impl_substs.repr(self.tcx()));
-        Ok(Normalized { value: impl_substs,
-                        obligations: impl_trait_ref.obligations })
+        Ok(Normalized {
+            value: impl_substs,
+            obligations: impl_trait_ref.obligations
+        })
     }
 
     fn fast_reject_trait_refs(&mut self,
@@ -2332,9 +2298,7 @@ fn match_where_clause_trait_ref(&mut self,
                                     where_clause_trait_ref: ty::PolyTraitRef<'tcx>)
                                     -> Result<Vec<PredicateObligation<'tcx>>,()>
     {
-        let () =
-            try!(self.match_poly_trait_ref(obligation, where_clause_trait_ref));
-
+        try!(self.match_poly_trait_ref(obligation, where_clause_trait_ref));
         Ok(Vec::new())
     }
 
@@ -2451,7 +2415,7 @@ fn all_impls(&self, trait_def_id: ast::DefId) -> Vec<ast::DefId> {
 
         match self.tcx().trait_impls.borrow().get(&trait_def_id) {
             None => Vec::new(),
-            Some(impls) => impls.borrow().clone()
+            Some(impls) => impls.borrow().clone(),
         }
     }
 
@@ -2549,9 +2513,7 @@ fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
             DefaultImplCandidate(t) => format!("DefaultImplCandidate({:?})", t),
             ProjectionCandidate => format!("ProjectionCandidate"),
             FnPointerCandidate => format!("FnPointerCandidate"),
-            ObjectCandidate => {
-                format!("ObjectCandidate")
-            }
+            ObjectCandidate => format!("ObjectCandidate"),
             ClosureCandidate(c, ref s) => {
                 format!("ClosureCandidate({:?},{})", c, s.repr(tcx))
             }
@@ -2582,9 +2544,7 @@ fn next(&mut self) -> Option<&'o TraitObligationStack<'o, 'tcx>> {
                 *self = o.previous;
                 Some(o)
             }
-            None => {
-                None
-            }
+            None => None
         }
     }
 }
@@ -2599,15 +2559,11 @@ fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
 impl<'tcx> EvaluationResult<'tcx> {
     fn may_apply(&self) -> bool {
         match *self {
-            EvaluatedToOk |
-            EvaluatedToAmbig |
-            EvaluatedToErr(Overflow) |
-            EvaluatedToErr(OutputTypeParameterMismatch(..)) => {
-                true
-            }
-            EvaluatedToErr(Unimplemented) => {
-                false
-            }
+            EvaluatedToOk
+            | EvaluatedToAmbig
+            | EvaluatedToErr(Overflow)
+            | EvaluatedToErr(OutputTypeParameterMismatch(..)) => true,
+            EvaluatedToErr(Unimplemented) => false,
         }
     }
 }
index 3d059e27c5207d4cf5f0f3dd30e8211323b75ddc..635ec09d3394cd52039a4ebba05b6bf026b45e86 100644 (file)
@@ -55,7 +55,7 @@
 use middle::resolve_lifetime;
 use middle::infer;
 use middle::stability;
-use middle::subst::{self, Subst, Substs, VecPerParamSpace};
+use middle::subst::{self, ParamSpace, Subst, Substs, VecPerParamSpace};
 use middle::traits;
 use middle::ty;
 use middle::ty_fold::{self, TypeFoldable, TypeFolder};
@@ -709,7 +709,7 @@ pub struct ctxt<'tcx> {
 
     pub impl_trait_cache: RefCell<DefIdMap<Option<Rc<ty::TraitRef<'tcx>>>>>,
 
-    pub trait_refs: RefCell<NodeMap<Rc<TraitRef<'tcx>>>>,
+    pub impl_trait_refs: RefCell<NodeMap<Rc<TraitRef<'tcx>>>>,
     pub trait_defs: RefCell<DefIdMap<Rc<TraitDef<'tcx>>>>,
 
     /// Maps from the def-id of an item (trait/struct/enum/fn) to its
@@ -1750,7 +1750,6 @@ pub struct TypeParameterDef<'tcx> {
     pub def_id: ast::DefId,
     pub space: subst::ParamSpace,
     pub index: u32,
-    pub bounds: ParamBounds<'tcx>,
     pub default: Option<Ty<'tcx>>,
     pub object_lifetime_default: Option<ObjectLifetimeDefault>,
 }
@@ -2423,7 +2422,7 @@ fn new(arena: &'tcx TypedArena<TyS<'tcx>>,
 
 pub fn mk_ctxt<'tcx>(s: Session,
                      arenas: &'tcx CtxtArenas<'tcx>,
-                     dm: DefMap,
+                     def_map: DefMap,
                      named_region_map: resolve_lifetime::NamedRegionMap,
                      map: ast_map::Map<'tcx>,
                      freevars: RefCell<FreevarMap>,
@@ -2445,11 +2444,11 @@ pub fn mk_ctxt<'tcx>(s: Session,
         item_variance_map: RefCell::new(DefIdMap()),
         variance_computed: Cell::new(false),
         sess: s,
-        def_map: dm,
+        def_map: def_map,
         region_maps: region_maps,
         node_types: RefCell::new(FnvHashMap()),
         item_substs: RefCell::new(NodeMap()),
-        trait_refs: RefCell::new(NodeMap()),
+        impl_trait_refs: RefCell::new(NodeMap()),
         trait_defs: RefCell::new(DefIdMap()),
         predicates: RefCell::new(DefIdMap()),
         object_cast_map: RefCell::new(NodeMap()),
@@ -2546,6 +2545,13 @@ pub fn closure_type(&self,
     {
         self.closure_tys.borrow()[def_id].subst(self, substs)
     }
+
+    pub fn type_parameter_def(&self,
+                              node_id: ast::NodeId)
+                              -> TypeParameterDef<'tcx>
+    {
+        self.ty_param_defs.borrow()[node_id].clone()
+    }
 }
 
 // Interns a type/name combination, stores the resulting box in cx.interner,
@@ -2996,6 +3002,13 @@ pub fn as_opt_param_ty(&self) -> Option<ty::ParamTy> {
             _ => None,
         }
     }
+
+    pub fn is_param(&self, space: ParamSpace, index: u32) -> bool {
+        match self.sty {
+            ty::ty_param(ref data) => data.space == space && data.idx == index,
+            _ => false,
+        }
+    }
 }
 
 pub fn walk_ty<'tcx, F>(ty_root: Ty<'tcx>, mut f: F)
@@ -3883,7 +3896,7 @@ fn same_type<'tcx>(a: Ty<'tcx>, b: Ty<'tcx>) -> bool {
                 let types_a = substs_a.types.get_slice(subst::TypeSpace);
                 let types_b = substs_b.types.get_slice(subst::TypeSpace);
 
-                let pairs = types_a.iter().zip(types_b.iter());
+                let mut pairs = types_a.iter().zip(types_b.iter());
 
                 pairs.all(|(&a, &b)| same_type(a, b))
             }
@@ -4174,12 +4187,12 @@ pub fn named_element_ty<'tcx>(cx: &ctxt<'tcx>,
     }
 }
 
-pub fn node_id_to_trait_ref<'tcx>(cx: &ctxt<'tcx>, id: ast::NodeId)
+pub fn impl_id_to_trait_ref<'tcx>(cx: &ctxt<'tcx>, id: ast::NodeId)
                                   -> Rc<ty::TraitRef<'tcx>> {
-    match cx.trait_refs.borrow().get(&id) {
+    match cx.impl_trait_refs.borrow().get(&id) {
         Some(ty) => ty.clone(),
         None => cx.sess.bug(
-            &format!("node_id_to_trait_ref: no trait ref for node `{}`",
+            &format!("impl_id_to_trait_ref: no trait ref for impl `{}`",
                     cx.map.node_to_string(id)))
     }
 }
@@ -4285,6 +4298,9 @@ pub fn free_region_from_def(outlives_extent: region::DestructionScopeData,
 pub fn pat_ty<'tcx>(cx: &ctxt<'tcx>, pat: &ast::Pat) -> Ty<'tcx> {
     return node_id_to_type(cx, pat.id);
 }
+pub fn pat_ty_opt<'tcx>(cx: &ctxt<'tcx>, pat: &ast::Pat) -> Option<Ty<'tcx>> {
+    return node_id_to_type_opt(cx, pat.id);
+}
 
 
 // Returns the type of an expression as a monotype.
@@ -4502,7 +4518,7 @@ pub fn unsize_ty<'tcx>(cx: &ctxt<'tcx>,
 
 pub fn resolve_expr(tcx: &ctxt, expr: &ast::Expr) -> def::Def {
     match tcx.def_map.borrow().get(&expr.id) {
-        Some(&def) => def,
+        Some(def) => def.full_def(),
         None => {
             tcx.sess.span_bug(expr.span, &format!(
                 "no def-map entry for expr {}", expr.id));
@@ -4550,7 +4566,7 @@ pub fn expr_kind(tcx: &ctxt, expr: &ast::Expr) -> ExprKind {
     }
 
     match expr.node {
-        ast::ExprPath(_) | ast::ExprQPath(_) => {
+        ast::ExprPath(..) => {
             match resolve_expr(tcx, expr) {
                 def::DefVariant(tid, vid, _) => {
                     let variant_info = enum_variant_with_id(tcx, tid, vid);
@@ -4581,7 +4597,7 @@ pub fn expr_kind(tcx: &ctxt, expr: &ast::Expr) -> ExprKind {
                 def::DefFn(_, true) => RvalueDpsExpr,
 
                 // Fn pointers are just scalar values.
-                def::DefFn(..) | def::DefStaticMethod(..) | def::DefMethod(..) => RvalueDatumExpr,
+                def::DefFn(..) | def::DefMethod(..) => RvalueDatumExpr,
 
                 // Note: there is actually a good case to be made that
                 // DefArg's, particularly those of immediate type, ought to
@@ -4685,11 +4701,10 @@ pub fn expr_kind(tcx: &ctxt, expr: &ast::Expr) -> ExprKind {
 
         ast::ExprBox(Some(ref place), _) => {
             // Special case `Box<T>` for now:
-            let definition = match tcx.def_map.borrow().get(&place.id) {
-                Some(&def) => def,
+            let def_id = match tcx.def_map.borrow().get(&place.id) {
+                Some(def) => def.def_id(),
                 None => panic!("no def for place"),
             };
-            let def_id = definition.def_id();
             if tcx.lang_items.exchange_heap() == Some(def_id) {
                 RvalueDatumExpr
             } else {
@@ -5116,25 +5131,16 @@ pub fn impl_trait_ref<'tcx>(cx: &ctxt<'tcx>, id: ast::DefId)
     memoized(&cx.impl_trait_cache, id, |id: ast::DefId| {
         if id.krate == ast::LOCAL_CRATE {
             debug!("(impl_trait_ref) searching for trait impl {:?}", id);
-            match cx.map.find(id.node) {
-                Some(ast_map::NodeItem(item)) => {
-                    match item.node {
-                        ast::ItemImpl(_, _, _, ref opt_trait, _, _) => {
-                            match opt_trait {
-                                &Some(ref t) => {
-                                    let trait_ref = ty::node_id_to_trait_ref(cx, t.ref_id);
-                                    Some(trait_ref)
-                                }
-                                &None => None
-                            }
-                        }
-                        ast::ItemDefaultImpl(_, ref ast_trait_ref) => {
-                            Some(ty::node_id_to_trait_ref(cx, ast_trait_ref.ref_id))
-                        }
-                        _ => None
+            if let Some(ast_map::NodeItem(item)) = cx.map.find(id.node) {
+                match item.node {
+                    ast::ItemImpl(_, _, _, Some(_), _, _) |
+                    ast::ItemDefaultImpl(..) => {
+                        Some(ty::impl_id_to_trait_ref(cx, id.node))
                     }
+                    _ => None
                 }
-                _ => None
+            } else {
+                None
             }
         } else {
             csearch::get_impl_trait(cx, id)
@@ -5143,10 +5149,7 @@ pub fn impl_trait_ref<'tcx>(cx: &ctxt<'tcx>, id: ast::DefId)
 }
 
 pub fn trait_ref_to_def_id(tcx: &ctxt, tr: &ast::TraitRef) -> ast::DefId {
-    let def = *tcx.def_map.borrow()
-                     .get(&tr.ref_id)
-                     .expect("no def-map entry for trait");
-    def.def_id()
+    tcx.def_map.borrow().get(&tr.ref_id).expect("no def-map entry for trait").def_id()
 }
 
 pub fn try_add_builtin_trait(
@@ -5848,7 +5851,7 @@ pub fn eval_repeat_count(tcx: &ctxt, count_expr: &ast::Expr) -> uint {
         }
         Err(_) => {
             let found = match count_expr.node {
-                ast::ExprPath(ast::Path {
+                ast::ExprPath(None, ast::Path {
                     global: false,
                     ref segments,
                     ..
index d2469c052ac51348aa613fa42023c3a332f7ccc5..4bf47c3a75f8003761a99ca641a540b8ae4a7f96 100644 (file)
@@ -377,7 +377,6 @@ fn fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> ty::TypeParameterDef
             def_id: self.def_id,
             space: self.space,
             index: self.index,
-            bounds: self.bounds.fold_with(folder),
             default: self.default.fold_with(folder),
             object_lifetime_default: self.object_lifetime_default.fold_with(folder),
         }
index b3bc898748fdc00ba3637c5efde0d0bc473255cd..a419d4134b40e4677faba9b0355848ccc5e1b98a 100644 (file)
@@ -15,7 +15,7 @@
 use plugin::registry::Registry;
 
 use std::mem;
-use std::env;
+use std::os;
 use std::dynamic_lib::DynamicLibrary;
 use std::borrow::ToOwned;
 use syntax::ast;
@@ -103,7 +103,7 @@ fn dylink_registrar(&mut self,
                         path: Path,
                         symbol: String) -> PluginRegistrarFun {
         // Make sure the path contains a / or the linker will search for it.
-        let path = env::current_dir().unwrap().join(&path);
+        let path = os::getcwd().unwrap().join(&path);
 
         let lib = match DynamicLibrary::open(Some(&path)) {
             Ok(lib) => lib,
index efc12d00b10c60145b43fc222069523169b7a015..efcde8b2fa1ac94cb00bb44c1dbc19616da14561 100644 (file)
@@ -99,6 +99,7 @@ pub struct Options {
     pub test: bool,
     pub parse_only: bool,
     pub no_trans: bool,
+    pub treat_err_as_bug: bool,
     pub no_analysis: bool,
     pub debugging_opts: DebuggingOptions,
     /// Whether to write dependency files. It's (enabled, optional filename).
@@ -223,6 +224,7 @@ pub fn basic_options() -> Options {
         test: false,
         parse_only: false,
         no_trans: false,
+        treat_err_as_bug: false,
         no_analysis: false,
         debugging_opts: basic_debugging_options(),
         write_dependency_info: (false, None),
@@ -573,6 +575,8 @@ fn parse_passes(slot: &mut Passes, v: Option<&str>) -> bool {
           "Parse only; do not compile, assemble, or link"),
     no_trans: bool = (false, parse_bool,
           "Run all passes except translation; no output"),
+    treat_err_as_bug: bool = (false, parse_bool,
+          "Treat all errors that occur as bugs"),
     no_analysis: bool = (false, parse_bool,
           "Parse and expand the source, but run no analysis"),
     extra_plugins: Vec<String> = (Vec::new(), parse_list,
@@ -843,6 +847,7 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
 
     let parse_only = debugging_opts.parse_only;
     let no_trans = debugging_opts.no_trans;
+    let treat_err_as_bug = debugging_opts.treat_err_as_bug;
     let no_analysis = debugging_opts.no_analysis;
 
     if debugging_opts.debug_llvm {
@@ -1030,6 +1035,7 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
         test: test,
         parse_only: parse_only,
         no_trans: no_trans,
+        treat_err_as_bug: treat_err_as_bug,
         no_analysis: no_analysis,
         debugging_opts: debugging_opts,
         write_dependency_info: write_dependency_info,
index b690cc7f7d06b2685e20e21d59e732f4742c989d..67c39bcca81f9a963fd8d863d57dc562675de040 100644 (file)
@@ -8,7 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-
 use lint;
 use metadata::cstore::CStore;
 use metadata::filesearch;
@@ -27,8 +26,8 @@
 
 use rustc_back::target::Target;
 
-use std::env;
 use std::cell::{Cell, RefCell};
+use std::os;
 
 pub mod config;
 pub mod search_paths;
@@ -74,18 +73,27 @@ pub fn fatal(&self, msg: &str) -> ! {
         self.diagnostic().handler().fatal(msg)
     }
     pub fn span_err(&self, sp: Span, msg: &str) {
+        if self.opts.treat_err_as_bug {
+            self.span_bug(sp, msg);
+        }
         match split_msg_into_multilines(msg) {
             Some(msg) => self.diagnostic().span_err(sp, &msg[..]),
             None => self.diagnostic().span_err(sp, msg)
         }
     }
     pub fn span_err_with_code(&self, sp: Span, msg: &str, code: &str) {
+        if self.opts.treat_err_as_bug {
+            self.span_bug(sp, msg);
+        }
         match split_msg_into_multilines(msg) {
             Some(msg) => self.diagnostic().span_err_with_code(sp, &msg[..], code),
             None => self.diagnostic().span_err_with_code(sp, msg, code)
         }
     }
     pub fn err(&self, msg: &str) {
+        if self.opts.treat_err_as_bug {
+            self.bug(msg);
+        }
         self.diagnostic().handler().err(msg)
     }
     pub fn err_count(&self) -> uint {
@@ -347,7 +355,7 @@ pub fn build_session_(sopts: config::Options,
         if path.is_absolute() {
             path.clone()
         } else {
-            env::current_dir().unwrap().join(&path)
+            os::getcwd().unwrap().join(&path)
         }
     );
 
@@ -370,7 +378,7 @@ pub fn build_session_(sopts: config::Options,
         plugin_registrar_fn: Cell::new(None),
         default_sysroot: default_sysroot,
         local_crate_source_file: local_crate_source_file,
-        working_dir: env::current_dir().unwrap(),
+        working_dir: os::getcwd().unwrap(),
         lint_store: RefCell::new(lint::LintStore::new()),
         lints: RefCell::new(NodeMap()),
         crate_types: RefCell::new(Vec::new()),
@@ -380,7 +388,6 @@ pub fn build_session_(sopts: config::Options,
         can_print_warnings: can_print_warnings
     };
 
-    sess.lint_store.borrow_mut().register_builtin(Some(&sess));
     sess
 }
 
index 6bf745315eace71965a8d3ea4b47e71a07557b02..3fcae6a8034c207ac3408c2beb3ea76bdf2f97cb 100644 (file)
@@ -14,7 +14,7 @@
 use std::old_io::process::{Command, ProcessOutput};
 use std::old_io::{fs, TempDir};
 use std::old_io;
-use std::env;
+use std::os;
 use std::str;
 use syntax::diagnostic::Handler as ErrorHandler;
 
@@ -224,7 +224,7 @@ pub fn update_symbols(&mut self) {
     pub fn build(self) -> Archive<'a> {
         // Get an absolute path to the destination, so `ar` will work even
         // though we run it from `self.work_dir`.
-        let abs_dst = env::current_dir().unwrap().join(&self.archive.dst);
+        let abs_dst = os::getcwd().unwrap().join(&self.archive.dst);
         assert!(!abs_dst.is_relative());
         let mut args = vec![&abs_dst];
         let mut total_len = abs_dst.as_vec().len();
@@ -283,7 +283,7 @@ fn add_archive<F>(&mut self, archive: &Path, name: &str,
         // First, extract the contents of the archive to a temporary directory.
         // We don't unpack directly into `self.work_dir` due to the possibility
         // of filename collisions.
-        let archive = env::current_dir().unwrap().join(archive);
+        let archive = os::getcwd().unwrap().join(archive);
         run_ar(self.archive.handler, &self.archive.maybe_ar_prog,
                "x", Some(loc.path()), &[&archive]);
 
index acf49d1ca46e3b6d7a3c55cc44a607d48aea0681..99a1df95a80cddf398549aa2226f3d48fb2be119 100644 (file)
 
 use std::old_io;
 use std::old_io::fs;
-use std::env;
+use std::os;
 
 /// Returns an absolute path in the filesystem that `path` points to. The
 /// returned path does not contain any symlinks in its hierarchy.
 pub fn realpath(original: &Path) -> old_io::IoResult<Path> {
     static MAX_LINKS_FOLLOWED: uint = 256;
-    let original = try!(env::current_dir()).join(original);
+    let original = try!(os::getcwd()).join(original);
 
     // Right now lstat on windows doesn't work quite well
     if cfg!(windows) {
index d589b063204c7d2d0fa903d6ff2848cd2de84454..711f937d2f355991e5cc6ac1f97b6d47ffb93734 100644 (file)
@@ -41,6 +41,7 @@
 #![feature(rustc_private)]
 #![feature(staged_api)]
 #![feature(env)]
+#![feature(path)]
 
 extern crate syntax;
 extern crate serialize;
index 3f2dcee5110951faae02c1ea3481141d5799004a..943ff52925a244545de15c4856f252db57bf7991 100644 (file)
@@ -8,10 +8,10 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-
 use std::collections::HashSet;
 use std::env;
 use std::old_io::IoError;
+use std::os;
 use syntax::ast;
 
 pub struct RPathConfig<F, G> where
@@ -109,7 +109,7 @@ fn get_rpath_relative_to_output<F, G>(config: &mut RPathConfig<F, G>, lib: &Path
         "$ORIGIN"
     };
 
-    let cwd = env::current_dir().unwrap();
+    let cwd = os::getcwd().unwrap();
     let mut lib = (config.realpath)(&cwd.join(lib)).unwrap();
     lib.pop();
     let mut output = (config.realpath)(&cwd.join(&config.out_filename)).unwrap();
@@ -129,7 +129,7 @@ fn get_install_prefix_rpath<F, G>(config: RPathConfig<F, G>) -> String where
     let path = (config.get_install_prefix_lib_path)();
     let path = env::current_dir().unwrap().join(&path);
     // FIXME (#9639): This needs to handle non-utf8 paths
-    path.as_str().expect("non-utf8 component in rpath").to_string()
+    path.to_str().expect("non-utf8 component in rpath").to_string()
 }
 
 fn minimize_rpaths(rpaths: &[String]) -> Vec<String> {
index 2fc43ab26b58ef328699c5a295df5386f79f982f..e16df61c25c47a9e83c97746f13b61ab3c13f41c 100644 (file)
@@ -244,8 +244,7 @@ pub enum SawExprComponent<'a> {
         SawExprAssignOp(ast::BinOp_),
         SawExprIndex,
         SawExprRange,
-        SawExprPath,
-        SawExprQPath,
+        SawExprPath(Option<usize>),
         SawExprAddrOf(ast::Mutability),
         SawExprRet,
         SawExprInlineAsm(&'a ast::InlineAsm),
@@ -277,8 +276,7 @@ fn saw_expr<'a>(node: &'a Expr_) -> SawExprComponent<'a> {
             ExprTupField(_, id)      => SawExprTupField(id.node),
             ExprIndex(..)            => SawExprIndex,
             ExprRange(..)            => SawExprRange,
-            ExprPath(..)             => SawExprPath,
-            ExprQPath(..)            => SawExprQPath,
+            ExprPath(ref qself, _)   => SawExprPath(qself.as_ref().map(|q| q.position)),
             ExprAddrOf(m, _)         => SawExprAddrOf(m),
             ExprBreak(id)            => SawExprBreak(id.map(content)),
             ExprAgain(id)            => SawExprAgain(id.map(content)),
index b04c07977c369be1dfb38233a13ef98d5fa1305f..d09a7c355d3e3c32ef00aa2d1f819f1d9d39ff26 100644 (file)
@@ -310,6 +310,7 @@ macro_rules! key {
     /// JSON decoding.
     pub fn search(target: &str) -> Result<Target, String> {
         use std::env;
+        use std::os;
         use std::ffi::OsString;
         use std::old_io::File;
         use std::old_path::Path;
@@ -396,7 +397,7 @@ macro_rules! load_specific {
 
         // FIXME 16351: add a sane default search path?
 
-        for dir in env::split_paths(&target_path) {
+        for dir in os::split_paths(target_path.to_str().unwrap()).iter() {
             let p =  dir.join(path.clone());
             if p.is_file() {
                 return load_file(&p);
index b0a03408b51e1fed5dc832b662dc0ca620f86769..67462ab01003e29ec33f3f21e3a1cd1998ee3bfa 100644 (file)
@@ -105,10 +105,10 @@ fn borrowck_item(this: &mut BorrowckCtxt, item: &ast::Item) {
         ast::ItemConst(_, ref ex) => {
             gather_loans::gather_loans_in_static_initializer(this, &**ex);
         }
-        _ => {
-            visit::walk_item(this, item);
-        }
+        _ => { }
     }
+
+    visit::walk_item(this, item);
 }
 
 /// Collection of conclusions determined via borrow checker analyses.
index b12f05d7c50f75b527322f2a4af9c7b9d41101eb..425ec7ec452eecd4b2347c36a5d32257f7accf01 100644 (file)
@@ -32,6 +32,7 @@
 use serialize::json;
 
 use std::env;
+use std::os;
 use std::ffi::OsString;
 use std::old_io::fs;
 use std::old_io;
@@ -471,7 +472,7 @@ pub fn phase_2_configure_and_expand(sess: &Session,
             if cfg!(windows) {
                 _old_path = env::var_os("PATH").unwrap_or(_old_path);
                 let mut new_path = sess.host_filesearch(PathKind::All).get_dylib_search_paths();
-                new_path.extend(env::split_paths(&_old_path));
+                new_path.extend(os::split_paths(_old_path.to_str().unwrap()).into_iter());
                 env::set_var("PATH", &env::join_paths(new_path.iter()).unwrap());
             }
             let features = sess.features.borrow();
@@ -571,7 +572,6 @@ pub fn phase_3_run_analysis_passes<'tcx>(sess: Session,
         export_map,
         trait_map,
         external_exports,
-        last_private_map,
         glob_map,
     } =
         time(time_passes, "resolution", (),
@@ -620,10 +620,9 @@ pub fn phase_3_run_analysis_passes<'tcx>(sess: Session,
     time(time_passes, "const checking", (), |_|
          middle::check_const::check_crate(&ty_cx));
 
-    let maps = (external_exports, last_private_map);
     let (exported_items, public_items) =
-            time(time_passes, "privacy checking", maps, |(a, b)|
-                 rustc_privacy::check_crate(&ty_cx, &export_map, a, b));
+            time(time_passes, "privacy checking", (), |_|
+                 rustc_privacy::check_crate(&ty_cx, &export_map, external_exports));
 
     // Do not move this check past lint
     time(time_passes, "stability index", (), |_|
@@ -738,7 +737,7 @@ pub fn phase_6_link_output(sess: &Session,
                            outputs: &OutputFilenames) {
     let old_path = env::var_os("PATH").unwrap_or(OsString::from_str(""));
     let mut new_path = sess.host_filesearch(PathKind::All).get_tools_search_paths();
-    new_path.extend(env::split_paths(&old_path));
+    new_path.extend(os::split_paths(old_path.to_str().unwrap()).into_iter());
     env::set_var("PATH", &env::join_paths(new_path.iter()).unwrap());
 
     time(sess.time_passes(), "linking", (), |_|
index 0fbfeb831850f2d7dc9e4e37cb081899ac5c4029..f0c7777b0af12233a104e6ddbf624678a6452d16 100644 (file)
@@ -47,6 +47,7 @@
 extern crate rustc;
 extern crate rustc_back;
 extern crate rustc_borrowck;
+extern crate rustc_lint;
 extern crate rustc_privacy;
 extern crate rustc_resolve;
 extern crate rustc_trans;
@@ -133,6 +134,7 @@ macro_rules! do_or_return {($expr: expr) => {
     };
 
     let mut sess = build_session(sopts, input_file_path, descriptions);
+    rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess));
     if sess.unstable_options() {
         sess.opts.show_span = matches.opt_str("show-span");
     }
@@ -299,11 +301,12 @@ fn no_input(&mut self,
             0 => {
                 if sopts.describe_lints {
                     let mut ls = lint::LintStore::new();
-                    ls.register_builtin(None);
+                    rustc_lint::register_builtins(&mut ls, None);
                     describe_lints(&ls, false);
                     return None;
                 }
                 let sess = build_session(sopts.clone(), None, descriptions.clone());
+                rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess));
                 let should_stop = RustcDefaultCalls::print_crate_info(&sess, None, odir, ofile);
                 if should_stop == Compilation::Stop {
                     return None;
@@ -844,4 +847,3 @@ pub fn main() {
     let result = run(env::args().collect());
     std::env::set_exit_status(result as i32);
 }
-
index cdcc9850e423e3477d919246999a3deb5c2ee943..cdbee9da334228d42b0ea48443c0456d6ce7d7b7 100644 (file)
@@ -13,6 +13,7 @@
 use diagnostic;
 use diagnostic::Emitter;
 use driver;
+use rustc_lint;
 use rustc_resolve as resolve;
 use rustc_typeck::middle::lang_items;
 use rustc_typeck::middle::region::{self, CodeExtent, DestructionScopeData};
@@ -108,6 +109,7 @@ fn test_env<F>(source_string: &str,
         diagnostic::mk_span_handler(diagnostic_handler, codemap);
 
     let sess = session::build_session_(options, None, span_diagnostic_handler);
+    rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess));
     let krate_config = Vec::new();
     let input = config::Input::Str(source_string.to_string());
     let krate = driver::phase_1_parse_input(&sess, krate_config, &input);
@@ -806,11 +808,11 @@ fn walk_ty() {
         let tup2_ty = ty::mk_tup(tcx, vec!(tup1_ty, tup1_ty, uint_ty));
         let uniq_ty = ty::mk_uniq(tcx, tup2_ty);
         let walked: Vec<_> = uniq_ty.walk().collect();
-        assert_eq!(vec!(uniq_ty,
-                        tup2_ty,
-                        tup1_ty, int_ty, uint_ty, int_ty, uint_ty,
-                        tup1_ty, int_ty, uint_ty, int_ty, uint_ty,
-                        uint_ty),
+        assert_eq!([uniq_ty,
+                    tup2_ty,
+                    tup1_ty, int_ty, uint_ty, int_ty, uint_ty,
+                    tup1_ty, int_ty, uint_ty, int_ty, uint_ty,
+                    uint_ty],
                    walked);
     })
 }
diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs
new file mode 100644 (file)
index 0000000..d0fccf6
--- /dev/null
@@ -0,0 +1,2098 @@
+// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+//! Lints in the Rust compiler.
+//!
+//! This contains lints which can feasibly be implemented as their own
+//! AST visitor. Also see `rustc::lint::builtin`, which contains the
+//! definitions of lints that are emitted directly inside the main
+//! compiler.
+//!
+//! To add a new lint to rustc, declare it here using `declare_lint!()`.
+//! Then add code to emit the new lint in the appropriate circumstances.
+//! You can do that in an existing `LintPass` if it makes sense, or in a
+//! new `LintPass`, or using `Session::add_lint` elsewhere in the
+//! compiler. Only do the latter if the check can't be written cleanly as a
+//! `LintPass` (also, note that such lints will need to be defined in
+//! `rustc::lint::builtin`, not here).
+//!
+//! If you define a new `LintPass`, you will also need to add it to the
+//! `add_builtin!` or `add_builtin_with_new!` invocation in `lib.rs`.
+//! Use the former for unit-like structs and the latter for structs with
+//! a `pub fn new()`.
+
+use self::MethodContext::*;
+
+use metadata::{csearch, decoder};
+use middle::def::*;
+use middle::subst::Substs;
+use middle::ty::{self, Ty};
+use middle::{def, pat_util, stability};
+use middle::const_eval::{eval_const_expr_partial, const_int, const_uint};
+use middle::cfg;
+use util::ppaux::{ty_to_string};
+use util::nodemap::{FnvHashMap, NodeSet};
+use lint::{Level, Context, LintPass, LintArray, Lint};
+
+use std::collections::BitSet;
+use std::collections::hash_map::Entry::{Occupied, Vacant};
+use std::num::SignedInt;
+use std::{cmp, slice};
+use std::{i8, i16, i32, i64, u8, u16, u32, u64, f32, f64};
+
+use syntax::{abi, ast, ast_map};
+use syntax::ast_util::is_shift_binop;
+use syntax::attr::{self, AttrMetaMethods};
+use syntax::codemap::{self, Span};
+use syntax::feature_gate::{KNOWN_ATTRIBUTES, AttributeType};
+use syntax::parse::token;
+use syntax::ast::{TyIs, TyUs, TyI8, TyU8, TyI16, TyU16, TyI32, TyU32, TyI64, TyU64};
+use syntax::ast_util;
+use syntax::ptr::P;
+use syntax::visit::{self, Visitor};
+
+// hardwired lints from librustc
+pub use lint::builtin::*;
+
+declare_lint! {
+    WHILE_TRUE,
+    Warn,
+    "suggest using `loop { }` instead of `while true { }`"
+}
+
+#[derive(Copy)]
+pub struct WhileTrue;
+
+impl LintPass for WhileTrue {
+    fn get_lints(&self) -> LintArray {
+        lint_array!(WHILE_TRUE)
+    }
+
+    fn check_expr(&mut self, cx: &Context, e: &ast::Expr) {
+        if let ast::ExprWhile(ref cond, _, _) = e.node {
+            if let ast::ExprLit(ref lit) = cond.node {
+                if let ast::LitBool(true) = lit.node {
+                    cx.span_lint(WHILE_TRUE, e.span,
+                                 "denote infinite loops with loop { ... }");
+                }
+            }
+        }
+    }
+}
+
+declare_lint! {
+    UNUSED_TYPECASTS,
+    Allow,
+    "detects unnecessary type casts that can be removed"
+}
+
+#[derive(Copy)]
+pub struct UnusedCasts;
+
+impl LintPass for UnusedCasts {
+    fn get_lints(&self) -> LintArray {
+        lint_array!(UNUSED_TYPECASTS)
+    }
+
+    fn check_expr(&mut self, cx: &Context, e: &ast::Expr) {
+        if let ast::ExprCast(ref expr, ref ty) = e.node {
+            let t_t = ty::expr_ty(cx.tcx, e);
+            if ty::expr_ty(cx.tcx, &**expr) == t_t {
+                cx.span_lint(UNUSED_TYPECASTS, ty.span, "unnecessary type cast");
+            }
+        }
+    }
+}
+
+declare_lint! {
+    UNSIGNED_NEGATION,
+    Warn,
+    "using an unary minus operator on unsigned type"
+}
+
+declare_lint! {
+    UNUSED_COMPARISONS,
+    Warn,
+    "comparisons made useless by limits of the types involved"
+}
+
+declare_lint! {
+    OVERFLOWING_LITERALS,
+    Warn,
+    "literal out of range for its type"
+}
+
+declare_lint! {
+    EXCEEDING_BITSHIFTS,
+    Deny,
+    "shift exceeds the type's number of bits"
+}
+
+#[derive(Copy)]
+pub struct TypeLimits {
+    /// Id of the last visited negated expression
+    negated_expr_id: ast::NodeId,
+}
+
+impl TypeLimits {
+    pub fn new() -> TypeLimits {
+        TypeLimits {
+            negated_expr_id: -1,
+        }
+    }
+}
+
+impl LintPass for TypeLimits {
+    fn get_lints(&self) -> LintArray {
+        lint_array!(UNSIGNED_NEGATION, UNUSED_COMPARISONS, OVERFLOWING_LITERALS,
+                    EXCEEDING_BITSHIFTS)
+    }
+
+    fn check_expr(&mut self, cx: &Context, e: &ast::Expr) {
+        match e.node {
+            ast::ExprUnary(ast::UnNeg, ref expr) => {
+                match expr.node  {
+                    ast::ExprLit(ref lit) => {
+                        match lit.node {
+                            ast::LitInt(_, ast::UnsignedIntLit(_)) => {
+                                cx.span_lint(UNSIGNED_NEGATION, e.span,
+                                             "negation of unsigned int literal may \
+                                             be unintentional");
+                            },
+                            _ => ()
+                        }
+                    },
+                    _ => {
+                        let t = ty::expr_ty(cx.tcx, &**expr);
+                        match t.sty {
+                            ty::ty_uint(_) => {
+                                cx.span_lint(UNSIGNED_NEGATION, e.span,
+                                             "negation of unsigned int variable may \
+                                             be unintentional");
+                            },
+                            _ => ()
+                        }
+                    }
+                };
+                // propagate negation, if the negation itself isn't negated
+                if self.negated_expr_id != e.id {
+                    self.negated_expr_id = expr.id;
+                }
+            },
+            ast::ExprParen(ref expr) if self.negated_expr_id == e.id => {
+                self.negated_expr_id = expr.id;
+            },
+            ast::ExprBinary(binop, ref l, ref r) => {
+                if is_comparison(binop) && !check_limits(cx.tcx, binop, &**l, &**r) {
+                    cx.span_lint(UNUSED_COMPARISONS, e.span,
+                                 "comparison is useless due to type limits");
+                }
+
+                if is_shift_binop(binop.node) {
+                    let opt_ty_bits = match ty::expr_ty(cx.tcx, &**l).sty {
+                        ty::ty_int(t) => Some(int_ty_bits(t, cx.sess().target.int_type)),
+                        ty::ty_uint(t) => Some(uint_ty_bits(t, cx.sess().target.uint_type)),
+                        _ => None
+                    };
+
+                    if let Some(bits) = opt_ty_bits {
+                        let exceeding = if let ast::ExprLit(ref lit) = r.node {
+                            if let ast::LitInt(shift, _) = lit.node { shift >= bits }
+                            else { false }
+                        } else {
+                            match eval_const_expr_partial(cx.tcx, &**r, Some(cx.tcx.types.uint)) {
+                                Ok(const_int(shift)) => { shift as u64 >= bits },
+                                Ok(const_uint(shift)) => { shift >= bits },
+                                _ => { false }
+                            }
+                        };
+                        if exceeding {
+                            cx.span_lint(EXCEEDING_BITSHIFTS, e.span,
+                                         "bitshift exceeds the type's number of bits");
+                        }
+                    };
+                }
+            },
+            ast::ExprLit(ref lit) => {
+                match ty::expr_ty(cx.tcx, e).sty {
+                    ty::ty_int(t) => {
+                        match lit.node {
+                            ast::LitInt(v, ast::SignedIntLit(_, ast::Plus)) |
+                            ast::LitInt(v, ast::UnsuffixedIntLit(ast::Plus)) => {
+                                let int_type = if let ast::TyIs(_) = t {
+                                    cx.sess().target.int_type
+                                } else { t };
+                                let (min, max) = int_ty_range(int_type);
+                                let negative = self.negated_expr_id == e.id;
+
+                                if (negative && v > (min.abs() as u64)) ||
+                                   (!negative && v > (max.abs() as u64)) {
+                                    cx.span_lint(OVERFLOWING_LITERALS, e.span,
+                                                 &*format!("literal out of range for {:?}", t));
+                                    return;
+                                }
+                            }
+                            _ => panic!()
+                        };
+                    },
+                    ty::ty_uint(t) => {
+                        let uint_type = if let ast::TyUs(_) = t {
+                            cx.sess().target.uint_type
+                        } else { t };
+                        let (min, max) = uint_ty_range(uint_type);
+                        let lit_val: u64 = match lit.node {
+                            ast::LitByte(_v) => return,  // _v is u8, within range by definition
+                            ast::LitInt(v, _) => v,
+                            _ => panic!()
+                        };
+                        if  lit_val < min || lit_val > max {
+                            cx.span_lint(OVERFLOWING_LITERALS, e.span,
+                                         &*format!("literal out of range for {:?}", t));
+                        }
+                    },
+                    ty::ty_float(t) => {
+                        let (min, max) = float_ty_range(t);
+                        let lit_val: f64 = match lit.node {
+                            ast::LitFloat(ref v, _) |
+                            ast::LitFloatUnsuffixed(ref v) => {
+                                match v.parse().ok() {
+                                    Some(f) => f,
+                                    None => return
+                                }
+                            }
+                            _ => panic!()
+                        };
+                        if lit_val < min || lit_val > max {
+                            cx.span_lint(OVERFLOWING_LITERALS, e.span,
+                                         &*format!("literal out of range for {:?}", t));
+                        }
+                    },
+                    _ => ()
+                };
+            },
+            _ => ()
+        };
+
+        fn is_valid<T:cmp::PartialOrd>(binop: ast::BinOp, v: T,
+                                min: T, max: T) -> bool {
+            match binop.node {
+                ast::BiLt => v >  min && v <= max,
+                ast::BiLe => v >= min && v <  max,
+                ast::BiGt => v >= min && v <  max,
+                ast::BiGe => v >  min && v <= max,
+                ast::BiEq | ast::BiNe => v >= min && v <= max,
+                _ => panic!()
+            }
+        }
+
+        fn rev_binop(binop: ast::BinOp) -> ast::BinOp {
+            codemap::respan(binop.span, match binop.node {
+                ast::BiLt => ast::BiGt,
+                ast::BiLe => ast::BiGe,
+                ast::BiGt => ast::BiLt,
+                ast::BiGe => ast::BiLe,
+                _ => return binop
+            })
+        }
+
+        // for int & uint, be conservative with the warnings, so that the
+        // warnings are consistent between 32- and 64-bit platforms
+        fn int_ty_range(int_ty: ast::IntTy) -> (i64, i64) {
+            match int_ty {
+                ast::TyIs(_) =>    (i64::MIN,        i64::MAX),
+                ast::TyI8 =>   (i8::MIN  as i64, i8::MAX  as i64),
+                ast::TyI16 =>  (i16::MIN as i64, i16::MAX as i64),
+                ast::TyI32 =>  (i32::MIN as i64, i32::MAX as i64),
+                ast::TyI64 =>  (i64::MIN,        i64::MAX)
+            }
+        }
+
+        fn uint_ty_range(uint_ty: ast::UintTy) -> (u64, u64) {
+            match uint_ty {
+                ast::TyUs(_) =>   (u64::MIN,         u64::MAX),
+                ast::TyU8 =>  (u8::MIN   as u64, u8::MAX   as u64),
+                ast::TyU16 => (u16::MIN  as u64, u16::MAX  as u64),
+                ast::TyU32 => (u32::MIN  as u64, u32::MAX  as u64),
+                ast::TyU64 => (u64::MIN,         u64::MAX)
+            }
+        }
+
+        fn float_ty_range(float_ty: ast::FloatTy) -> (f64, f64) {
+            match float_ty {
+                ast::TyF32  => (f32::MIN as f64, f32::MAX as f64),
+                ast::TyF64  => (f64::MIN,        f64::MAX)
+            }
+        }
+
+        fn int_ty_bits(int_ty: ast::IntTy, target_int_ty: ast::IntTy) -> u64 {
+            match int_ty {
+                ast::TyIs(_) =>    int_ty_bits(target_int_ty, target_int_ty),
+                ast::TyI8 =>   i8::BITS  as u64,
+                ast::TyI16 =>  i16::BITS as u64,
+                ast::TyI32 =>  i32::BITS as u64,
+                ast::TyI64 =>  i64::BITS as u64
+            }
+        }
+
+        fn uint_ty_bits(uint_ty: ast::UintTy, target_uint_ty: ast::UintTy) -> u64 {
+            match uint_ty {
+                ast::TyUs(_) =>    uint_ty_bits(target_uint_ty, target_uint_ty),
+                ast::TyU8 =>   u8::BITS  as u64,
+                ast::TyU16 =>  u16::BITS as u64,
+                ast::TyU32 =>  u32::BITS as u64,
+                ast::TyU64 =>  u64::BITS as u64
+            }
+        }
+
+        fn check_limits(tcx: &ty::ctxt, binop: ast::BinOp,
+                        l: &ast::Expr, r: &ast::Expr) -> bool {
+            let (lit, expr, swap) = match (&l.node, &r.node) {
+                (&ast::ExprLit(_), _) => (l, r, true),
+                (_, &ast::ExprLit(_)) => (r, l, false),
+                _ => return true
+            };
+            // Normalize the binop so that the literal is always on the RHS in
+            // the comparison
+            let norm_binop = if swap { rev_binop(binop) } else { binop };
+            match ty::expr_ty(tcx, expr).sty {
+                ty::ty_int(int_ty) => {
+                    let (min, max) = int_ty_range(int_ty);
+                    let lit_val: i64 = match lit.node {
+                        ast::ExprLit(ref li) => match li.node {
+                            ast::LitInt(v, ast::SignedIntLit(_, ast::Plus)) |
+                            ast::LitInt(v, ast::UnsuffixedIntLit(ast::Plus)) => v as i64,
+                            ast::LitInt(v, ast::SignedIntLit(_, ast::Minus)) |
+                            ast::LitInt(v, ast::UnsuffixedIntLit(ast::Minus)) => -(v as i64),
+                            _ => return true
+                        },
+                        _ => panic!()
+                    };
+                    is_valid(norm_binop, lit_val, min, max)
+                }
+                ty::ty_uint(uint_ty) => {
+                    let (min, max): (u64, u64) = uint_ty_range(uint_ty);
+                    let lit_val: u64 = match lit.node {
+                        ast::ExprLit(ref li) => match li.node {
+                            ast::LitInt(v, _) => v,
+                            _ => return true
+                        },
+                        _ => panic!()
+                    };
+                    is_valid(norm_binop, lit_val, min, max)
+                }
+                _ => true
+            }
+        }
+
+        fn is_comparison(binop: ast::BinOp) -> bool {
+            match binop.node {
+                ast::BiEq | ast::BiLt | ast::BiLe |
+                ast::BiNe | ast::BiGe | ast::BiGt => true,
+                _ => false
+            }
+        }
+    }
+}
+
+declare_lint! {
+    IMPROPER_CTYPES,
+    Warn,
+    "proper use of libc types in foreign modules"
+}
+
+struct ImproperCTypesVisitor<'a, 'tcx: 'a> {
+    cx: &'a Context<'a, 'tcx>
+}
+
+impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
+    fn check_def(&mut self, sp: Span, id: ast::NodeId) {
+        match self.cx.tcx.def_map.borrow()[id].full_def() {
+            def::DefPrimTy(ast::TyInt(ast::TyIs(_))) => {
+                self.cx.span_lint(IMPROPER_CTYPES, sp,
+                                  "found rust type `isize` in foreign module, while \
+                                   libc::c_int or libc::c_long should be used");
+            }
+            def::DefPrimTy(ast::TyUint(ast::TyUs(_))) => {
+                self.cx.span_lint(IMPROPER_CTYPES, sp,
+                                  "found rust type `usize` in foreign module, while \
+                                   libc::c_uint or libc::c_ulong should be used");
+            }
+            def::DefTy(..) => {
+                let tty = match self.cx.tcx.ast_ty_to_ty_cache.borrow().get(&id) {
+                    Some(&ty::atttce_resolved(t)) => t,
+                    _ => panic!("ast_ty_to_ty_cache was incomplete after typeck!")
+                };
+
+                if !ty::is_ffi_safe(self.cx.tcx, tty) {
+                    self.cx.span_lint(IMPROPER_CTYPES, sp,
+                                      "found type without foreign-function-safe
+                                      representation annotation in foreign module, consider \
+                                      adding a #[repr(...)] attribute to the type");
+                }
+            }
+            _ => ()
+        }
+    }
+}
+
+impl<'a, 'tcx, 'v> Visitor<'v> for ImproperCTypesVisitor<'a, 'tcx> {
+    fn visit_ty(&mut self, ty: &ast::Ty) {
+        if let ast::TyPath(..) = ty.node {
+            self.check_def(ty.span, ty.id);
+        }
+        visit::walk_ty(self, ty);
+    }
+}
+
+#[derive(Copy)]
+pub struct ImproperCTypes;
+
+impl LintPass for ImproperCTypes {
+    fn get_lints(&self) -> LintArray {
+        lint_array!(IMPROPER_CTYPES)
+    }
+
+    fn check_item(&mut self, cx: &Context, it: &ast::Item) {
+        fn check_ty(cx: &Context, ty: &ast::Ty) {
+            let mut vis = ImproperCTypesVisitor { cx: cx };
+            vis.visit_ty(ty);
+        }
+
+        fn check_foreign_fn(cx: &Context, decl: &ast::FnDecl) {
+            for input in &decl.inputs {
+                check_ty(cx, &*input.ty);
+            }
+            if let ast::Return(ref ret_ty) = decl.output {
+                check_ty(cx, &**ret_ty);
+            }
+        }
+
+        match it.node {
+            ast::ItemForeignMod(ref nmod) if nmod.abi != abi::RustIntrinsic => {
+                for ni in &nmod.items {
+                    match ni.node {
+                        ast::ForeignItemFn(ref decl, _) => check_foreign_fn(cx, &**decl),
+                        ast::ForeignItemStatic(ref t, _) => check_ty(cx, &**t)
+                    }
+                }
+            }
+            _ => (),
+        }
+    }
+}
+
+declare_lint! {
+    BOX_POINTERS,
+    Allow,
+    "use of owned (Box type) heap memory"
+}
+
+#[derive(Copy)]
+pub struct BoxPointers;
+
+impl BoxPointers {
+    fn check_heap_type<'a, 'tcx>(&self, cx: &Context<'a, 'tcx>,
+                                 span: Span, ty: Ty<'tcx>) {
+        let mut n_uniq: usize = 0;
+        ty::fold_ty(cx.tcx, ty, |t| {
+            match t.sty {
+                ty::ty_uniq(_) => {
+                    n_uniq += 1;
+                }
+                _ => ()
+            };
+            t
+        });
+
+        if n_uniq > 0 {
+            let s = ty_to_string(cx.tcx, ty);
+            let m = format!("type uses owned (Box type) pointers: {}", s);
+            cx.span_lint(BOX_POINTERS, span, &m[..]);
+        }
+    }
+}
+
+impl LintPass for BoxPointers {
+    fn get_lints(&self) -> LintArray {
+        lint_array!(BOX_POINTERS)
+    }
+
+    fn check_item(&mut self, cx: &Context, it: &ast::Item) {
+        match it.node {
+            ast::ItemFn(..) |
+            ast::ItemTy(..) |
+            ast::ItemEnum(..) |
+            ast::ItemStruct(..) =>
+                self.check_heap_type(cx, it.span,
+                                     ty::node_id_to_type(cx.tcx, it.id)),
+            _ => ()
+        }
+
+        // If it's a struct, we also have to check the fields' types
+        match it.node {
+            ast::ItemStruct(ref struct_def, _) => {
+                for struct_field in &struct_def.fields {
+                    self.check_heap_type(cx, struct_field.span,
+                                         ty::node_id_to_type(cx.tcx, struct_field.node.id));
+                }
+            }
+            _ => ()
+        }
+    }
+
+    fn check_expr(&mut self, cx: &Context, e: &ast::Expr) {
+        let ty = ty::expr_ty(cx.tcx, e);
+        self.check_heap_type(cx, e.span, ty);
+    }
+}
+
+declare_lint! {
+    RAW_POINTER_DERIVE,
+    Warn,
+    "uses of #[derive] with raw pointers are rarely correct"
+}
+
+struct RawPtrDeriveVisitor<'a, 'tcx: 'a> {
+    cx: &'a Context<'a, 'tcx>
+}
+
+impl<'a, 'tcx, 'v> Visitor<'v> for RawPtrDeriveVisitor<'a, 'tcx> {
+    fn visit_ty(&mut self, ty: &ast::Ty) {
+        static MSG: &'static str = "use of `#[derive]` with a raw pointer";
+        if let ast::TyPtr(..) = ty.node {
+            self.cx.span_lint(RAW_POINTER_DERIVE, ty.span, MSG);
+        }
+        visit::walk_ty(self, ty);
+    }
+    // explicit override to a no-op to reduce code bloat
+    fn visit_expr(&mut self, _: &ast::Expr) {}
+    fn visit_block(&mut self, _: &ast::Block) {}
+}
+
+pub struct RawPointerDerive {
+    checked_raw_pointers: NodeSet,
+}
+
+impl RawPointerDerive {
+    pub fn new() -> RawPointerDerive {
+        RawPointerDerive {
+            checked_raw_pointers: NodeSet(),
+        }
+    }
+}
+
+impl LintPass for RawPointerDerive {
+    fn get_lints(&self) -> LintArray {
+        lint_array!(RAW_POINTER_DERIVE)
+    }
+
+    fn check_item(&mut self, cx: &Context, item: &ast::Item) {
+        if !attr::contains_name(&item.attrs, "automatically_derived") {
+            return
+        }
+        let did = match item.node {
+            ast::ItemImpl(_, _, _, ref t_ref_opt, _, _) => {
+                // Deriving the Copy trait does not cause a warning
+                if let &Some(ref trait_ref) = t_ref_opt {
+                    let def_id = ty::trait_ref_to_def_id(cx.tcx, trait_ref);
+                    if Some(def_id) == cx.tcx.lang_items.copy_trait() {
+                        return
+                    }
+                }
+
+                match ty::node_id_to_type(cx.tcx, item.id).sty {
+                    ty::ty_enum(did, _) => did,
+                    ty::ty_struct(did, _) => did,
+                    _ => return,
+                }
+            }
+            _ => return,
+        };
+        if !ast_util::is_local(did) { return }
+        let item = match cx.tcx.map.find(did.node) {
+            Some(ast_map::NodeItem(item)) => item,
+            _ => return,
+        };
+        if !self.checked_raw_pointers.insert(item.id) { return }
+        match item.node {
+            ast::ItemStruct(..) | ast::ItemEnum(..) => {
+                let mut visitor = RawPtrDeriveVisitor { cx: cx };
+                visit::walk_item(&mut visitor, &*item);
+            }
+            _ => {}
+        }
+    }
+}
+
+declare_lint! {
+    UNUSED_ATTRIBUTES,
+    Warn,
+    "detects attributes that were not used by the compiler"
+}
+
+#[derive(Copy)]
+pub struct UnusedAttributes;
+
+impl LintPass for UnusedAttributes {
+    fn get_lints(&self) -> LintArray {
+        lint_array!(UNUSED_ATTRIBUTES)
+    }
+
+    fn check_attribute(&mut self, cx: &Context, attr: &ast::Attribute) {
+        for &(ref name, ty) in KNOWN_ATTRIBUTES {
+            match ty {
+                AttributeType::Whitelisted
+                | AttributeType::Gated(_, _) if attr.check_name(name) => {
+                    break;
+                },
+                _ => ()
+            }
+        }
+
+        if !attr::is_used(attr) {
+            cx.span_lint(UNUSED_ATTRIBUTES, attr.span, "unused attribute");
+            if KNOWN_ATTRIBUTES.contains(&(&attr.name(), AttributeType::CrateLevel)) {
+                let msg = match attr.node.style {
+                    ast::AttrOuter => "crate-level attribute should be an inner \
+                                       attribute: add an exclamation mark: #![foo]",
+                    ast::AttrInner => "crate-level attribute should be in the \
+                                       root module",
+                };
+                cx.span_lint(UNUSED_ATTRIBUTES, attr.span, msg);
+            }
+        }
+    }
+}
+
+declare_lint! {
+    pub PATH_STATEMENTS,
+    Warn,
+    "path statements with no effect"
+}
+
+#[derive(Copy)]
+pub struct PathStatements;
+
+impl LintPass for PathStatements {
+    fn get_lints(&self) -> LintArray {
+        lint_array!(PATH_STATEMENTS)
+    }
+
+    fn check_stmt(&mut self, cx: &Context, s: &ast::Stmt) {
+        match s.node {
+            ast::StmtSemi(ref expr, _) => {
+                match expr.node {
+                    ast::ExprPath(..) => cx.span_lint(PATH_STATEMENTS, s.span,
+                                                      "path statement with no effect"),
+                    _ => ()
+                }
+            }
+            _ => ()
+        }
+    }
+}
+
+declare_lint! {
+    pub UNUSED_MUST_USE,
+    Warn,
+    "unused result of a type flagged as #[must_use]"
+}
+
+declare_lint! {
+    pub UNUSED_RESULTS,
+    Allow,
+    "unused result of an expression in a statement"
+}
+
+#[derive(Copy)]
+pub struct UnusedResults;
+
+impl LintPass for UnusedResults {
+    fn get_lints(&self) -> LintArray {
+        lint_array!(UNUSED_MUST_USE, UNUSED_RESULTS)
+    }
+
+    fn check_stmt(&mut self, cx: &Context, s: &ast::Stmt) {
+        let expr = match s.node {
+            ast::StmtSemi(ref expr, _) => &**expr,
+            _ => return
+        };
+
+        if let ast::ExprRet(..) = expr.node {
+            return;
+        }
+
+        let t = ty::expr_ty(cx.tcx, expr);
+        let mut warned = false;
+        match t.sty {
+            ty::ty_tup(ref tys) if tys.is_empty() => return,
+            ty::ty_bool => return,
+            ty::ty_struct(did, _) |
+            ty::ty_enum(did, _) => {
+                if ast_util::is_local(did) {
+                    if let ast_map::NodeItem(it) = cx.tcx.map.get(did.node) {
+                        warned |= check_must_use(cx, &it.attrs, s.span);
+                    }
+                } else {
+                    let attrs = csearch::get_item_attrs(&cx.sess().cstore, did);
+                    warned |= check_must_use(cx, &attrs[..], s.span);
+                }
+            }
+            _ => {}
+        }
+        if !warned {
+            cx.span_lint(UNUSED_RESULTS, s.span, "unused result");
+        }
+
+        fn check_must_use(cx: &Context, attrs: &[ast::Attribute], sp: Span) -> bool {
+            for attr in attrs {
+                if attr.check_name("must_use") {
+                    let mut msg = "unused result which must be used".to_string();
+                    // check for #[must_use="..."]
+                    match attr.value_str() {
+                        None => {}
+                        Some(s) => {
+                            msg.push_str(": ");
+                            msg.push_str(&s);
+                        }
+                    }
+                    cx.span_lint(UNUSED_MUST_USE, sp, &msg);
+                    return true;
+                }
+            }
+            false
+        }
+    }
+}
+
+declare_lint! {
+    pub NON_CAMEL_CASE_TYPES,
+    Warn,
+    "types, variants, traits and type parameters should have camel case names"
+}
+
+#[derive(Copy)]
+pub struct NonCamelCaseTypes;
+
+impl NonCamelCaseTypes {
+    fn check_case(&self, cx: &Context, sort: &str, ident: ast::Ident, span: Span) {
+        fn is_camel_case(ident: ast::Ident) -> bool {
+            let ident = token::get_ident(ident);
+            if ident.is_empty() { return true; }
+            let ident = ident.trim_matches('_');
+
+            // start with a non-lowercase letter rather than non-uppercase
+            // ones (some scripts don't have a concept of upper/lowercase)
+            ident.len() > 0 && !ident.char_at(0).is_lowercase() && !ident.contains('_')
+        }
+
+        fn to_camel_case(s: &str) -> String {
+            s.split('_').flat_map(|word| word.chars().enumerate().map(|(i, c)|
+                if i == 0 { c.to_uppercase() }
+                else { c }
+            )).collect()
+        }
+
+        let s = token::get_ident(ident);
+
+        if !is_camel_case(ident) {
+            let c = to_camel_case(&s);
+            let m = if c.is_empty() {
+                format!("{} `{}` should have a camel case name such as `CamelCase`", sort, s)
+            } else {
+                format!("{} `{}` should have a camel case name such as `{}`", sort, s, c)
+            };
+            cx.span_lint(NON_CAMEL_CASE_TYPES, span, &m[..]);
+        }
+    }
+}
+
+impl LintPass for NonCamelCaseTypes {
+    fn get_lints(&self) -> LintArray {
+        lint_array!(NON_CAMEL_CASE_TYPES)
+    }
+
+    fn check_item(&mut self, cx: &Context, it: &ast::Item) {
+        let has_extern_repr = it.attrs.iter().map(|attr| {
+            attr::find_repr_attrs(cx.tcx.sess.diagnostic(), attr).iter()
+                .any(|r| r == &attr::ReprExtern)
+        }).any(|x| x);
+        if has_extern_repr { return }
+
+        match it.node {
+            ast::ItemTy(..) | ast::ItemStruct(..) => {
+                self.check_case(cx, "type", it.ident, it.span)
+            }
+            ast::ItemTrait(..) => {
+                self.check_case(cx, "trait", it.ident, it.span)
+            }
+            ast::ItemEnum(ref enum_definition, _) => {
+                if has_extern_repr { return }
+                self.check_case(cx, "type", it.ident, it.span);
+                for variant in &enum_definition.variants {
+                    self.check_case(cx, "variant", variant.node.name, variant.span);
+                }
+            }
+            _ => ()
+        }
+    }
+
+    fn check_generics(&mut self, cx: &Context, it: &ast::Generics) {
+        for gen in &*it.ty_params {
+            self.check_case(cx, "type parameter", gen.ident, gen.span);
+        }
+    }
+}
+
+#[derive(PartialEq)]
+enum MethodContext {
+    TraitDefaultImpl,
+    TraitImpl,
+    PlainImpl
+}
+
+fn method_context(cx: &Context, m: &ast::Method) -> MethodContext {
+    let did = ast::DefId {
+        krate: ast::LOCAL_CRATE,
+        node: m.id
+    };
+
+    match cx.tcx.impl_or_trait_items.borrow().get(&did).cloned() {
+        None => cx.sess().span_bug(m.span, "missing method descriptor?!"),
+        Some(md) => {
+            match md {
+                ty::MethodTraitItem(md) => {
+                    match md.container {
+                        ty::TraitContainer(..) => TraitDefaultImpl,
+                        ty::ImplContainer(cid) => {
+                            match ty::impl_trait_ref(cx.tcx, cid) {
+                                Some(..) => TraitImpl,
+                                None => PlainImpl
+                            }
+                        }
+                    }
+                }
+                ty::TypeTraitItem(typedef) => {
+                    match typedef.container {
+                        ty::TraitContainer(..) => TraitDefaultImpl,
+                        ty::ImplContainer(cid) => {
+                            match ty::impl_trait_ref(cx.tcx, cid) {
+                                Some(..) => TraitImpl,
+                                None => PlainImpl
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+}
+
+declare_lint! {
+    pub NON_SNAKE_CASE,
+    Warn,
+    "methods, functions, lifetime parameters and modules should have snake case names"
+}
+
+#[derive(Copy)]
+pub struct NonSnakeCase;
+
+impl NonSnakeCase {
+    fn to_snake_case(mut str: &str) -> String {
+        let mut words = vec![];
+        // Preserve leading underscores
+        str = str.trim_left_matches(|c: char| {
+            if c == '_' {
+                words.push(String::new());
+                true
+            } else { false }
+        });
+        for s in str.split('_') {
+            let mut last_upper = false;
+            let mut buf = String::new();
+            if s.is_empty() { continue; }
+            for ch in s.chars() {
+                if !buf.is_empty() && buf != "'"
+                                   && ch.is_uppercase()
+                                   && !last_upper {
+                    words.push(buf);
+                    buf = String::new();
+                }
+                last_upper = ch.is_uppercase();
+                buf.push(ch.to_lowercase());
+            }
+            words.push(buf);
+        }
+        words.connect("_")
+    }
+
+    fn check_snake_case(&self, cx: &Context, sort: &str, ident: ast::Ident, span: Span) {
+        fn is_snake_case(ident: ast::Ident) -> bool {
+            let ident = token::get_ident(ident);
+            if ident.is_empty() { return true; }
+            let ident = ident.trim_left_matches('\'');
+            let ident = ident.trim_matches('_');
+
+            let mut allow_underscore = true;
+            ident.chars().all(|c| {
+                allow_underscore = match c {
+                    '_' if !allow_underscore => return false,
+                    '_' => false,
+                    c if !c.is_uppercase() => true,
+                    _ => return false,
+                };
+                true
+            })
+        }
+
+        let s = token::get_ident(ident);
+
+        if !is_snake_case(ident) {
+            let sc = NonSnakeCase::to_snake_case(&s);
+            if sc != &s[..] {
+                cx.span_lint(NON_SNAKE_CASE, span,
+                    &*format!("{} `{}` should have a snake case name such as `{}`",
+                            sort, s, sc));
+            } else {
+                cx.span_lint(NON_SNAKE_CASE, span,
+                    &*format!("{} `{}` should have a snake case name",
+                            sort, s));
+            }
+        }
+    }
+}
+
+impl LintPass for NonSnakeCase {
+    fn get_lints(&self) -> LintArray {
+        lint_array!(NON_SNAKE_CASE)
+    }
+
+    fn check_fn(&mut self, cx: &Context,
+                fk: visit::FnKind, _: &ast::FnDecl,
+                _: &ast::Block, span: Span, _: ast::NodeId) {
+        match fk {
+            visit::FkMethod(ident, _, m) => match method_context(cx, m) {
+                PlainImpl
+                    => self.check_snake_case(cx, "method", ident, span),
+                TraitDefaultImpl
+                    => self.check_snake_case(cx, "trait method", ident, span),
+                _ => (),
+            },
+            visit::FkItemFn(ident, _, _, _)
+                => self.check_snake_case(cx, "function", ident, span),
+            _ => (),
+        }
+    }
+
+    fn check_item(&mut self, cx: &Context, it: &ast::Item) {
+        if let ast::ItemMod(_) = it.node {
+            self.check_snake_case(cx, "module", it.ident, it.span);
+        }
+    }
+
+    fn check_ty_method(&mut self, cx: &Context, t: &ast::TypeMethod) {
+        self.check_snake_case(cx, "trait method", t.ident, t.span);
+    }
+
+    fn check_lifetime_def(&mut self, cx: &Context, t: &ast::LifetimeDef) {
+        self.check_snake_case(cx, "lifetime", t.lifetime.name.ident(), t.lifetime.span);
+    }
+
+    fn check_pat(&mut self, cx: &Context, p: &ast::Pat) {
+        if let &ast::PatIdent(_, ref path1, _) = &p.node {
+            let def = cx.tcx.def_map.borrow().get(&p.id).map(|d| d.full_def());
+            if let Some(def::DefLocal(_)) = def {
+                self.check_snake_case(cx, "variable", path1.node, p.span);
+            }
+        }
+    }
+
+    fn check_struct_def(&mut self, cx: &Context, s: &ast::StructDef,
+            _: ast::Ident, _: &ast::Generics, _: ast::NodeId) {
+        for sf in &s.fields {
+            if let ast::StructField_ { kind: ast::NamedField(ident, _), .. } = sf.node {
+                self.check_snake_case(cx, "structure field", ident, sf.span);
+            }
+        }
+    }
+}
+
+declare_lint! {
+    pub NON_UPPER_CASE_GLOBALS,
+    Warn,
+    "static constants should have uppercase identifiers"
+}
+
+#[derive(Copy)]
+pub struct NonUpperCaseGlobals;
+
+impl NonUpperCaseGlobals {
+    fn check_upper_case(cx: &Context, sort: &str, ident: ast::Ident, span: Span) {
+        let s = token::get_ident(ident);
+
+        if s.chars().any(|c| c.is_lowercase()) {
+            let uc: String = NonSnakeCase::to_snake_case(&s).chars()
+                                           .map(|c| c.to_uppercase()).collect();
+            if uc != &s[..] {
+                cx.span_lint(NON_UPPER_CASE_GLOBALS, span,
+                    &format!("{} `{}` should have an upper case name such as `{}`",
+                             sort, s, uc));
+            } else {
+                cx.span_lint(NON_UPPER_CASE_GLOBALS, span,
+                    &format!("{} `{}` should have an upper case name",
+                             sort, s));
+            }
+        }
+    }
+}
+
+impl LintPass for NonUpperCaseGlobals {
+    fn get_lints(&self) -> LintArray {
+        lint_array!(NON_UPPER_CASE_GLOBALS)
+    }
+
+    fn check_item(&mut self, cx: &Context, it: &ast::Item) {
+        match it.node {
+            // only check static constants
+            ast::ItemStatic(_, ast::MutImmutable, _) => {
+                NonUpperCaseGlobals::check_upper_case(cx, "static constant", it.ident, it.span);
+            }
+            ast::ItemConst(..) => {
+                NonUpperCaseGlobals::check_upper_case(cx, "constant", it.ident, it.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())) {
+            (&ast::PatIdent(_, ref path1, _), Some(def::DefConst(..))) => {
+                NonUpperCaseGlobals::check_upper_case(cx, "constant in pattern",
+                                                      path1.node, p.span);
+            }
+            _ => {}
+        }
+    }
+}
+
+declare_lint! {
+    UNUSED_PARENS,
+    Warn,
+    "`if`, `match`, `while` and `return` do not need parentheses"
+}
+
+#[derive(Copy)]
+pub struct UnusedParens;
+
+impl UnusedParens {
+    fn check_unused_parens_core(&self, cx: &Context, value: &ast::Expr, msg: &str,
+                                     struct_lit_needs_parens: bool) {
+        if let ast::ExprParen(ref inner) = value.node {
+            let necessary = struct_lit_needs_parens && contains_exterior_struct_lit(&**inner);
+            if !necessary {
+                cx.span_lint(UNUSED_PARENS, value.span,
+                             &format!("unnecessary parentheses around {}",
+                                     msg))
+            }
+        }
+
+        /// Expressions that syntactically contain an "exterior" struct
+        /// literal i.e. not surrounded by any parens or other
+        /// delimiters, e.g. `X { y: 1 }`, `X { y: 1 }.method()`, `foo
+        /// == X { y: 1 }` and `X { y: 1 } == foo` all do, but `(X {
+        /// y: 1 }) == foo` does not.
+        fn contains_exterior_struct_lit(value: &ast::Expr) -> bool {
+            match value.node {
+                ast::ExprStruct(..) => true,
+
+                ast::ExprAssign(ref lhs, ref rhs) |
+                ast::ExprAssignOp(_, ref lhs, ref rhs) |
+                ast::ExprBinary(_, ref lhs, ref rhs) => {
+                    // X { y: 1 } + X { y: 2 }
+                    contains_exterior_struct_lit(&**lhs) ||
+                        contains_exterior_struct_lit(&**rhs)
+                }
+                ast::ExprUnary(_, ref x) |
+                ast::ExprCast(ref x, _) |
+                ast::ExprField(ref x, _) |
+                ast::ExprTupField(ref x, _) |
+                ast::ExprIndex(ref x, _) => {
+                    // &X { y: 1 }, X { y: 1 }.y
+                    contains_exterior_struct_lit(&**x)
+                }
+
+                ast::ExprMethodCall(_, _, ref exprs) => {
+                    // X { y: 1 }.bar(...)
+                    contains_exterior_struct_lit(&*exprs[0])
+                }
+
+                _ => false
+            }
+        }
+    }
+}
+
+impl LintPass for UnusedParens {
+    fn get_lints(&self) -> LintArray {
+        lint_array!(UNUSED_PARENS)
+    }
+
+    fn check_expr(&mut self, cx: &Context, e: &ast::Expr) {
+        let (value, msg, struct_lit_needs_parens) = match e.node {
+            ast::ExprIf(ref cond, _, _) => (cond, "`if` condition", true),
+            ast::ExprWhile(ref cond, _, _) => (cond, "`while` condition", true),
+            ast::ExprMatch(ref head, _, source) => match source {
+                ast::MatchSource::Normal => (head, "`match` head expression", true),
+                ast::MatchSource::IfLetDesugar { .. } => (head, "`if let` head expression", true),
+                ast::MatchSource::WhileLetDesugar => (head, "`while let` head expression", true),
+                ast::MatchSource::ForLoopDesugar => (head, "`for` head expression", true),
+            },
+            ast::ExprRet(Some(ref value)) => (value, "`return` value", false),
+            ast::ExprAssign(_, ref value) => (value, "assigned value", false),
+            ast::ExprAssignOp(_, _, ref value) => (value, "assigned value", false),
+            _ => return
+        };
+        self.check_unused_parens_core(cx, &**value, msg, struct_lit_needs_parens);
+    }
+
+    fn check_stmt(&mut self, cx: &Context, s: &ast::Stmt) {
+        let (value, msg) = match s.node {
+            ast::StmtDecl(ref decl, _) => match decl.node {
+                ast::DeclLocal(ref local) => match local.init {
+                    Some(ref value) => (value, "assigned value"),
+                    None => return
+                },
+                _ => return
+            },
+            _ => return
+        };
+        self.check_unused_parens_core(cx, &**value, msg, false);
+    }
+}
+
+declare_lint! {
+    UNUSED_IMPORT_BRACES,
+    Allow,
+    "unnecessary braces around an imported item"
+}
+
+#[derive(Copy)]
+pub struct UnusedImportBraces;
+
+impl LintPass for UnusedImportBraces {
+    fn get_lints(&self) -> LintArray {
+        lint_array!(UNUSED_IMPORT_BRACES)
+    }
+
+    fn check_item(&mut self, cx: &Context, item: &ast::Item) {
+        match item.node {
+            ast::ItemUse(ref view_path) => {
+                match view_path.node {
+                    ast::ViewPathList(_, ref items) => {
+                        if items.len() == 1 {
+                            match items[0].node {
+                                ast::PathListIdent {ref name, ..} => {
+                                    let m = format!("braces around {} is unnecessary",
+                                                    &token::get_ident(*name));
+                                    cx.span_lint(UNUSED_IMPORT_BRACES, item.span,
+                                                 &m[..]);
+                                },
+                                _ => ()
+                            }
+                        }
+                    }
+                    _ => ()
+                }
+            },
+            _ => ()
+        }
+    }
+}
+
+declare_lint! {
+    NON_SHORTHAND_FIELD_PATTERNS,
+    Warn,
+    "using `Struct { x: x }` instead of `Struct { x }`"
+}
+
+#[derive(Copy)]
+pub struct NonShorthandFieldPatterns;
+
+impl LintPass for NonShorthandFieldPatterns {
+    fn get_lints(&self) -> LintArray {
+        lint_array!(NON_SHORTHAND_FIELD_PATTERNS)
+    }
+
+    fn check_pat(&mut self, cx: &Context, pat: &ast::Pat) {
+        let def_map = cx.tcx.def_map.borrow();
+        if let ast::PatStruct(_, ref v, _) = pat.node {
+            let field_pats = v.iter()
+                              .filter(|fieldpat| !fieldpat.node.is_shorthand)
+                              .filter(|fieldpat| {
+                let def = def_map.get(&fieldpat.node.pat.id).map(|d| d.full_def());
+                def == Some(def::DefLocal(fieldpat.node.pat.id))
+            });
+            for fieldpat in field_pats {
+                if let ast::PatIdent(_, ident, None) = fieldpat.node.pat.node {
+                    if ident.node.as_str() == fieldpat.node.ident.as_str() {
+                        cx.span_lint(NON_SHORTHAND_FIELD_PATTERNS, fieldpat.span,
+                                     &format!("the `{}:` in this pattern is redundant and can \
+                                              be removed", ident.node.as_str()))
+                    }
+                }
+            }
+        }
+    }
+}
+
+declare_lint! {
+    pub UNUSED_UNSAFE,
+    Warn,
+    "unnecessary use of an `unsafe` block"
+}
+
+#[derive(Copy)]
+pub struct UnusedUnsafe;
+
+impl LintPass for UnusedUnsafe {
+    fn get_lints(&self) -> LintArray {
+        lint_array!(UNUSED_UNSAFE)
+    }
+
+    fn check_expr(&mut self, cx: &Context, e: &ast::Expr) {
+        if let ast::ExprBlock(ref blk) = e.node {
+            // Don't warn about generated blocks, that'll just pollute the output.
+            if blk.rules == ast::UnsafeBlock(ast::UserProvided) &&
+                !cx.tcx.used_unsafe.borrow().contains(&blk.id) {
+                    cx.span_lint(UNUSED_UNSAFE, blk.span, "unnecessary `unsafe` block");
+            }
+        }
+    }
+}
+
+declare_lint! {
+    UNSAFE_CODE,
+    Allow,
+    "usage of `unsafe` code"
+}
+
+#[derive(Copy)]
+pub struct UnsafeCode;
+
+impl LintPass for UnsafeCode {
+    fn get_lints(&self) -> LintArray {
+        lint_array!(UNSAFE_CODE)
+    }
+
+    fn check_expr(&mut self, cx: &Context, e: &ast::Expr) {
+        if let ast::ExprBlock(ref blk) = e.node {
+            // Don't warn about generated blocks, that'll just pollute the output.
+            if blk.rules == ast::UnsafeBlock(ast::UserProvided) {
+                cx.span_lint(UNSAFE_CODE, blk.span, "usage of an `unsafe` block");
+            }
+        }
+    }
+
+    fn check_item(&mut self, cx: &Context, it: &ast::Item) {
+        match it.node {
+            ast::ItemTrait(ast::Unsafety::Unsafe, _, _, _) =>
+                cx.span_lint(UNSAFE_CODE, it.span, "declaration of an `unsafe` trait"),
+
+            ast::ItemImpl(ast::Unsafety::Unsafe, _, _, _, _, _) =>
+                cx.span_lint(UNSAFE_CODE, it.span, "implementation of an `unsafe` trait"),
+
+            _ => return,
+        }
+    }
+
+    fn check_fn(&mut self, cx: &Context, fk: visit::FnKind, _: &ast::FnDecl,
+                _: &ast::Block, span: Span, _: ast::NodeId) {
+        match fk {
+            visit::FkItemFn(_, _, ast::Unsafety::Unsafe, _) =>
+                cx.span_lint(UNSAFE_CODE, span, "declaration of an `unsafe` function"),
+
+            visit::FkMethod(_, _, m) => {
+                if let ast::Method_::MethDecl(_, _, _, _, ast::Unsafety::Unsafe, _, _, _) = m.node {
+                    cx.span_lint(UNSAFE_CODE, m.span, "implementation of an `unsafe` method")
+                }
+            },
+
+            _ => (),
+        }
+    }
+
+    fn check_ty_method(&mut self, cx: &Context, ty_method: &ast::TypeMethod) {
+        if let ast::TypeMethod { unsafety: ast::Unsafety::Unsafe, span, ..} = *ty_method {
+            cx.span_lint(UNSAFE_CODE, span, "declaration of an `unsafe` method")
+        }
+    }
+}
+
+declare_lint! {
+    pub UNUSED_MUT,
+    Warn,
+    "detect mut variables which don't need to be mutable"
+}
+
+#[derive(Copy)]
+pub struct UnusedMut;
+
+impl UnusedMut {
+    fn check_unused_mut_pat(&self, cx: &Context, pats: &[P<ast::Pat>]) {
+        // collect all mutable pattern and group their NodeIDs by their Identifier to
+        // avoid false warnings in match arms with multiple patterns
+
+        let mut mutables = FnvHashMap();
+        for p in pats {
+            pat_util::pat_bindings(&cx.tcx.def_map, &**p, |mode, id, _, path1| {
+                let ident = path1.node;
+                if let ast::BindByValue(ast::MutMutable) = mode {
+                    if !token::get_ident(ident).starts_with("_") {
+                        match mutables.entry(ident.name.usize()) {
+                            Vacant(entry) => { entry.insert(vec![id]); },
+                            Occupied(mut entry) => { entry.get_mut().push(id); },
+                        }
+                    }
+                }
+            });
+        }
+
+        let used_mutables = cx.tcx.used_mut_nodes.borrow();
+        for (_, v) in &mutables {
+            if !v.iter().any(|e| used_mutables.contains(e)) {
+                cx.span_lint(UNUSED_MUT, cx.tcx.map.span(v[0]),
+                             "variable does not need to be mutable");
+            }
+        }
+    }
+}
+
+impl LintPass for UnusedMut {
+    fn get_lints(&self) -> LintArray {
+        lint_array!(UNUSED_MUT)
+    }
+
+    fn check_expr(&mut self, cx: &Context, e: &ast::Expr) {
+        if let ast::ExprMatch(_, ref arms, _) = e.node {
+            for a in arms {
+                self.check_unused_mut_pat(cx, &a.pats)
+            }
+        }
+    }
+
+    fn check_stmt(&mut self, cx: &Context, s: &ast::Stmt) {
+        if let ast::StmtDecl(ref d, _) = s.node {
+            if let ast::DeclLocal(ref l) = d.node {
+                self.check_unused_mut_pat(cx, slice::ref_slice(&l.pat));
+            }
+        }
+    }
+
+    fn check_fn(&mut self, cx: &Context,
+                _: visit::FnKind, decl: &ast::FnDecl,
+                _: &ast::Block, _: Span, _: ast::NodeId) {
+        for a in &decl.inputs {
+            self.check_unused_mut_pat(cx, slice::ref_slice(&a.pat));
+        }
+    }
+}
+
+declare_lint! {
+    UNUSED_ALLOCATION,
+    Warn,
+    "detects unnecessary allocations that can be eliminated"
+}
+
+#[derive(Copy)]
+pub struct UnusedAllocation;
+
+impl LintPass for UnusedAllocation {
+    fn get_lints(&self) -> LintArray {
+        lint_array!(UNUSED_ALLOCATION)
+    }
+
+    fn check_expr(&mut self, cx: &Context, e: &ast::Expr) {
+        match e.node {
+            ast::ExprUnary(ast::UnUniq, _) => (),
+            _ => return
+        }
+
+        if let Some(adjustment) = cx.tcx.adjustments.borrow().get(&e.id) {
+            if let ty::AdjustDerefRef(ty::AutoDerefRef { ref autoref, .. }) = *adjustment {
+                match autoref {
+                    &Some(ty::AutoPtr(_, ast::MutImmutable, None)) => {
+                        cx.span_lint(UNUSED_ALLOCATION, e.span,
+                                     "unnecessary allocation, use & instead");
+                    }
+                    &Some(ty::AutoPtr(_, ast::MutMutable, None)) => {
+                        cx.span_lint(UNUSED_ALLOCATION, e.span,
+                                     "unnecessary allocation, use &mut instead");
+                    }
+                    _ => ()
+                }
+            }
+        }
+    }
+}
+
+declare_lint! {
+    MISSING_DOCS,
+    Allow,
+    "detects missing documentation for public members"
+}
+
+pub struct MissingDoc {
+    /// Stack of IDs of struct definitions.
+    struct_def_stack: Vec<ast::NodeId>,
+
+    /// True if inside variant definition
+    in_variant: bool,
+
+    /// Stack of whether #[doc(hidden)] is set
+    /// at each level which has lint attributes.
+    doc_hidden_stack: Vec<bool>,
+}
+
+impl MissingDoc {
+    pub fn new() -> MissingDoc {
+        MissingDoc {
+            struct_def_stack: vec!(),
+            in_variant: false,
+            doc_hidden_stack: vec!(false),
+        }
+    }
+
+    fn doc_hidden(&self) -> bool {
+        *self.doc_hidden_stack.last().expect("empty doc_hidden_stack")
+    }
+
+    fn check_missing_docs_attrs(&self,
+                               cx: &Context,
+                               id: Option<ast::NodeId>,
+                               attrs: &[ast::Attribute],
+                               sp: Span,
+                               desc: &'static str) {
+        // If we're building a test harness, then warning about
+        // documentation is probably not really relevant right now.
+        if cx.sess().opts.test { return }
+
+        // `#[doc(hidden)]` disables missing_docs check.
+        if self.doc_hidden() { return }
+
+        // Only check publicly-visible items, using the result from the privacy pass.
+        // It's an option so the crate root can also use this function (it doesn't
+        // have a NodeId).
+        if let Some(ref id) = id {
+            if !cx.exported_items.contains(id) {
+                return;
+            }
+        }
+
+        let has_doc = attrs.iter().any(|a| {
+            match a.node.value.node {
+                ast::MetaNameValue(ref name, _) if *name == "doc" => true,
+                _ => false
+            }
+        });
+        if !has_doc {
+            cx.span_lint(MISSING_DOCS, sp,
+                &format!("missing documentation for {}", desc));
+        }
+    }
+}
+
+impl LintPass for MissingDoc {
+    fn get_lints(&self) -> LintArray {
+        lint_array!(MISSING_DOCS)
+    }
+
+    fn enter_lint_attrs(&mut self, _: &Context, attrs: &[ast::Attribute]) {
+        let doc_hidden = self.doc_hidden() || attrs.iter().any(|attr| {
+            attr.check_name("doc") && match attr.meta_item_list() {
+                None => false,
+                Some(l) => attr::contains_name(&l[..], "hidden"),
+            }
+        });
+        self.doc_hidden_stack.push(doc_hidden);
+    }
+
+    fn exit_lint_attrs(&mut self, _: &Context, _: &[ast::Attribute]) {
+        self.doc_hidden_stack.pop().expect("empty doc_hidden_stack");
+    }
+
+    fn check_struct_def(&mut self, _: &Context,
+        _: &ast::StructDef, _: ast::Ident, _: &ast::Generics, id: ast::NodeId) {
+        self.struct_def_stack.push(id);
+    }
+
+    fn check_struct_def_post(&mut self, _: &Context,
+        _: &ast::StructDef, _: ast::Ident, _: &ast::Generics, id: ast::NodeId) {
+        let popped = self.struct_def_stack.pop().expect("empty struct_def_stack");
+        assert!(popped == id);
+    }
+
+    fn check_crate(&mut self, cx: &Context, krate: &ast::Crate) {
+        self.check_missing_docs_attrs(cx, None, &krate.attrs,
+                                     krate.span, "crate");
+    }
+
+    fn check_item(&mut self, cx: &Context, it: &ast::Item) {
+        let desc = match it.node {
+            ast::ItemFn(..) => "a function",
+            ast::ItemMod(..) => "a module",
+            ast::ItemEnum(..) => "an enum",
+            ast::ItemStruct(..) => "a struct",
+            ast::ItemTrait(..) => "a trait",
+            ast::ItemTy(..) => "a type alias",
+            _ => return
+        };
+        self.check_missing_docs_attrs(cx, Some(it.id), &it.attrs,
+                                     it.span, desc);
+    }
+
+    fn check_fn(&mut self, cx: &Context,
+            fk: visit::FnKind, _: &ast::FnDecl,
+            _: &ast::Block, _: Span, _: ast::NodeId) {
+        if let visit::FkMethod(_, _, m) = fk {
+            // If the method is an impl for a trait, don't doc.
+            if method_context(cx, m) == TraitImpl { return; }
+
+            // Otherwise, doc according to privacy. This will also check
+            // doc for default methods defined on traits.
+            self.check_missing_docs_attrs(cx, Some(m.id), &m.attrs,
+                                          m.span, "a method");
+        }
+    }
+
+    fn check_ty_method(&mut self, cx: &Context, tm: &ast::TypeMethod) {
+        self.check_missing_docs_attrs(cx, Some(tm.id), &tm.attrs,
+                                     tm.span, "a type method");
+    }
+
+    fn check_trait_method(&mut self, cx: &Context, it: &ast::TraitItem) {
+        if let ast::TraitItem::TypeTraitItem(ref ty) = *it {
+            let assoc_ty = &ty.ty_param;
+            self.check_missing_docs_attrs(cx, Some(assoc_ty.id), &ty.attrs,
+                                          assoc_ty.span, "an associated type");
+        }
+    }
+
+    fn check_struct_field(&mut self, cx: &Context, sf: &ast::StructField) {
+        if let ast::NamedField(_, vis) = sf.node.kind {
+            if vis == ast::Public || self.in_variant {
+                let cur_struct_def = *self.struct_def_stack.last()
+                    .expect("empty struct_def_stack");
+                self.check_missing_docs_attrs(cx, Some(cur_struct_def),
+                                              &sf.node.attrs, sf.span,
+                                              "a struct field")
+            }
+        }
+    }
+
+    fn check_variant(&mut self, cx: &Context, v: &ast::Variant, _: &ast::Generics) {
+        self.check_missing_docs_attrs(cx, Some(v.node.id), &v.node.attrs,
+                                     v.span, "a variant");
+        assert!(!self.in_variant);
+        self.in_variant = true;
+    }
+
+    fn check_variant_post(&mut self, _: &Context, _: &ast::Variant, _: &ast::Generics) {
+        assert!(self.in_variant);
+        self.in_variant = false;
+    }
+}
+
+declare_lint! {
+    pub MISSING_COPY_IMPLEMENTATIONS,
+    Allow,
+    "detects potentially-forgotten implementations of `Copy`"
+}
+
+#[derive(Copy)]
+pub struct MissingCopyImplementations;
+
+impl LintPass for MissingCopyImplementations {
+    fn get_lints(&self) -> LintArray {
+        lint_array!(MISSING_COPY_IMPLEMENTATIONS)
+    }
+
+    fn check_item(&mut self, cx: &Context, item: &ast::Item) {
+        if !cx.exported_items.contains(&item.id) {
+            return
+        }
+        if cx.tcx
+             .destructor_for_type
+             .borrow()
+             .contains_key(&ast_util::local_def(item.id)) {
+            return
+        }
+        let ty = match item.node {
+            ast::ItemStruct(_, ref ast_generics) => {
+                if ast_generics.is_parameterized() {
+                    return
+                }
+                ty::mk_struct(cx.tcx,
+                              ast_util::local_def(item.id),
+                              cx.tcx.mk_substs(Substs::empty()))
+            }
+            ast::ItemEnum(_, ref ast_generics) => {
+                if ast_generics.is_parameterized() {
+                    return
+                }
+                ty::mk_enum(cx.tcx,
+                            ast_util::local_def(item.id),
+                            cx.tcx.mk_substs(Substs::empty()))
+            }
+            _ => return,
+        };
+        let parameter_environment = ty::empty_parameter_environment(cx.tcx);
+        if !ty::type_moves_by_default(&parameter_environment, item.span, ty) {
+            return
+        }
+        if ty::can_type_implement_copy(&parameter_environment, item.span, ty).is_ok() {
+            cx.span_lint(MISSING_COPY_IMPLEMENTATIONS,
+                         item.span,
+                         "type could implement `Copy`; consider adding `impl \
+                          Copy`")
+        }
+    }
+}
+
+declare_lint! {
+    MISSING_DEBUG_IMPLEMENTATIONS,
+    Allow,
+    "detects missing implementations of fmt::Debug"
+}
+
+pub struct MissingDebugImplementations {
+    impling_types: Option<NodeSet>,
+}
+
+impl MissingDebugImplementations {
+    pub fn new() -> MissingDebugImplementations {
+        MissingDebugImplementations {
+            impling_types: None,
+        }
+    }
+}
+
+impl LintPass for MissingDebugImplementations {
+    fn get_lints(&self) -> LintArray {
+        lint_array!(MISSING_DEBUG_IMPLEMENTATIONS)
+    }
+
+    fn check_item(&mut self, cx: &Context, item: &ast::Item) {
+        if !cx.exported_items.contains(&item.id) {
+            return;
+        }
+
+        match item.node {
+            ast::ItemStruct(..) | ast::ItemEnum(..) => {},
+            _ => return,
+        }
+
+        let debug = match cx.tcx.lang_items.debug_trait() {
+            Some(debug) => debug,
+            None => return,
+        };
+
+        if self.impling_types.is_none() {
+            let impls = cx.tcx.trait_impls.borrow();
+            let impls = match impls.get(&debug) {
+                Some(impls) => {
+                    impls.borrow().iter()
+                        .filter(|d| d.krate == ast::LOCAL_CRATE)
+                        .filter_map(|d| ty::ty_to_def_id(ty::node_id_to_type(cx.tcx, d.node)))
+                        .map(|d| d.node)
+                        .collect()
+                }
+                None => NodeSet(),
+            };
+            self.impling_types = Some(impls);
+            debug!("{:?}", self.impling_types);
+        }
+
+        if !self.impling_types.as_ref().unwrap().contains(&item.id) {
+            cx.span_lint(MISSING_DEBUG_IMPLEMENTATIONS,
+                         item.span,
+                         "type does not implement `fmt::Debug`; consider adding #[derive(Debug)] \
+                          or a manual implementation")
+        }
+    }
+}
+
+declare_lint! {
+    DEPRECATED,
+    Warn,
+    "detects use of #[deprecated] items"
+}
+
+/// Checks for use of items with `#[deprecated]` attributes
+#[derive(Copy)]
+pub struct Stability;
+
+impl Stability {
+    fn lint(&self, cx: &Context, _id: ast::DefId, span: Span, stability: &Option<attr::Stability>) {
+
+        // deprecated attributes apply in-crate and cross-crate
+        let (lint, label) = match *stability {
+            Some(attr::Stability { deprecated_since: Some(_), .. }) =>
+                (DEPRECATED, "deprecated"),
+            _ => return
+        };
+
+        output(cx, span, stability, lint, label);
+
+        fn output(cx: &Context, span: Span, stability: &Option<attr::Stability>,
+                  lint: &'static Lint, label: &'static str) {
+            let msg = match *stability {
+                Some(attr::Stability { reason: Some(ref s), .. }) => {
+                    format!("use of {} item: {}", label, *s)
+                }
+                _ => format!("use of {} item", label)
+            };
+
+            cx.span_lint(lint, span, &msg[..]);
+        }
+    }
+}
+
+impl LintPass for Stability {
+    fn get_lints(&self) -> LintArray {
+        lint_array!(DEPRECATED)
+    }
+
+    fn check_item(&mut self, cx: &Context, item: &ast::Item) {
+        stability::check_item(cx.tcx, item, false,
+                              &mut |id, sp, stab| self.lint(cx, id, sp, stab));
+    }
+
+    fn check_expr(&mut self, cx: &Context, e: &ast::Expr) {
+        stability::check_expr(cx.tcx, e,
+                              &mut |id, sp, stab| self.lint(cx, id, sp, stab));
+    }
+
+    fn check_path(&mut self, cx: &Context, path: &ast::Path, id: ast::NodeId) {
+        stability::check_path(cx.tcx, path, id,
+                              &mut |id, sp, stab| self.lint(cx, id, sp, stab));
+    }
+
+    fn check_pat(&mut self, cx: &Context, pat: &ast::Pat) {
+        stability::check_pat(cx.tcx, pat,
+                             &mut |id, sp, stab| self.lint(cx, id, sp, stab))
+    }
+}
+
+declare_lint! {
+    pub UNCONDITIONAL_RECURSION,
+    Warn,
+    "functions that cannot return without calling themselves"
+}
+
+#[derive(Copy)]
+pub struct UnconditionalRecursion;
+
+
+impl LintPass for UnconditionalRecursion {
+    fn get_lints(&self) -> LintArray {
+        lint_array![UNCONDITIONAL_RECURSION]
+    }
+
+    fn check_fn(&mut self, cx: &Context, fn_kind: visit::FnKind, _: &ast::FnDecl,
+                blk: &ast::Block, sp: Span, id: ast::NodeId) {
+        type F = for<'tcx> fn(&ty::ctxt<'tcx>,
+                              ast::NodeId, ast::NodeId, ast::Ident, ast::NodeId) -> bool;
+
+        let (name, checker) = match fn_kind {
+            visit::FkItemFn(name, _, _, _) => (name, id_refers_to_this_fn as F),
+            visit::FkMethod(name, _, _) => (name, id_refers_to_this_method as F),
+            // closures can't recur, so they don't matter.
+            visit::FkFnBlock => return
+        };
+
+        let impl_def_id = ty::impl_of_method(cx.tcx, ast_util::local_def(id))
+            .unwrap_or(ast_util::local_def(ast::DUMMY_NODE_ID));
+        assert!(ast_util::is_local(impl_def_id));
+        let impl_node_id = impl_def_id.node;
+
+        // Walk through this function (say `f`) looking to see if
+        // every possible path references itself, i.e. the function is
+        // called recursively unconditionally. This is done by trying
+        // to find a path from the entry node to the exit node that
+        // *doesn't* call `f` by traversing from the entry while
+        // pretending that calls of `f` are sinks (i.e. ignoring any
+        // exit edges from them).
+        //
+        // NB. this has an edge case with non-returning statements,
+        // like `loop {}` or `panic!()`: control flow never reaches
+        // the exit node through these, so one can have a function
+        // that never actually calls itselfs but is still picked up by
+        // this lint:
+        //
+        //     fn f(cond: bool) {
+        //         if !cond { panic!() } // could come from `assert!(cond)`
+        //         f(false)
+        //     }
+        //
+        // In general, functions of that form may be able to call
+        // itself a finite number of times and then diverge. The lint
+        // considers this to be an error for two reasons, (a) it is
+        // easier to implement, and (b) it seems rare to actually want
+        // to have behaviour like the above, rather than
+        // e.g. accidentally recurring after an assert.
+
+        let cfg = cfg::CFG::new(cx.tcx, blk);
+
+        let mut work_queue = vec![cfg.entry];
+        let mut reached_exit_without_self_call = false;
+        let mut self_call_spans = vec![];
+        let mut visited = BitSet::new();
+
+        while let Some(idx) = work_queue.pop() {
+            let cfg_id = idx.node_id();
+            if idx == cfg.exit {
+                // found a path!
+                reached_exit_without_self_call = true;
+                break
+            } else if visited.contains(&cfg_id) {
+                // already done
+                continue
+            }
+            visited.insert(cfg_id);
+            let node_id = cfg.graph.node_data(idx).id();
+
+            // is this a recursive call?
+            if node_id != ast::DUMMY_NODE_ID && checker(cx.tcx, impl_node_id, id, name, node_id) {
+
+                self_call_spans.push(cx.tcx.map.span(node_id));
+                // this is a self call, so we shouldn't explore past
+                // this node in the CFG.
+                continue
+            }
+            // add the successors of this node to explore the graph further.
+            cfg.graph.each_outgoing_edge(idx, |_, edge| {
+                let target_idx = edge.target();
+                let target_cfg_id = target_idx.node_id();
+                if !visited.contains(&target_cfg_id) {
+                    work_queue.push(target_idx)
+                }
+                true
+            });
+        }
+
+        // check the number of sell calls because a function that
+        // doesn't return (e.g. calls a `-> !` function or `loop { /*
+        // no break */ }`) shouldn't be linted unless it actually
+        // recurs.
+        if !reached_exit_without_self_call && self_call_spans.len() > 0 {
+            cx.span_lint(UNCONDITIONAL_RECURSION, sp,
+                         "function cannot return without recurring");
+
+            // FIXME #19668: these could be span_lint_note's instead of this manual guard.
+            if cx.current_level(UNCONDITIONAL_RECURSION) != Level::Allow {
+                let sess = cx.sess();
+                // offer some help to the programmer.
+                for call in &self_call_spans {
+                    sess.span_note(*call, "recursive call site")
+                }
+                sess.span_help(sp, "a `loop` may express intention better if this is on purpose")
+            }
+        }
+
+        // all done
+        return;
+
+        // Functions for identifying if the given NodeId `id`
+        // represents a call to the function `fn_id`/method
+        // `method_id`.
+
+        fn id_refers_to_this_fn<'tcx>(tcx: &ty::ctxt<'tcx>,
+                                      _: ast::NodeId,
+                                      fn_id: ast::NodeId,
+                                      _: ast::Ident,
+                                      id: ast::NodeId) -> bool {
+            tcx.def_map.borrow().get(&id)
+                .map_or(false, |def| def.def_id() == ast_util::local_def(fn_id))
+        }
+
+        // check if the method call `id` refers to method `method_id`
+        // (with name `method_name` contained in impl `impl_id`).
+        fn id_refers_to_this_method<'tcx>(tcx: &ty::ctxt<'tcx>,
+                                          impl_id: ast::NodeId,
+                                          method_id: ast::NodeId,
+                                          method_name: ast::Ident,
+                                          id: ast::NodeId) -> bool {
+            let did = match tcx.method_map.borrow().get(&ty::MethodCall::expr(id)) {
+                None => return false,
+                Some(m) => match m.origin {
+                    // There's no way to know if a method call via a
+                    // vtable is recursion, so we assume it's not.
+                    ty::MethodTraitObject(_) => return false,
+
+                    // This `did` refers directly to the method definition.
+                    ty::MethodStatic(did) | ty::MethodStaticClosure(did) => did,
+
+                    // MethodTypeParam are methods from traits:
+
+                    // The `impl ... for ...` of this method call
+                    // isn't known, e.g. it might be a default method
+                    // in a trait, so we get the def-id of the trait
+                    // method instead.
+                    ty::MethodTypeParam(
+                        ty::MethodParam { ref trait_ref, method_num, impl_def_id: None, }) => {
+                        ty::trait_item(tcx, trait_ref.def_id, method_num).def_id()
+                    }
+
+                    // The `impl` is known, so we check that with a
+                    // special case:
+                    ty::MethodTypeParam(
+                        ty::MethodParam { impl_def_id: Some(impl_def_id), .. }) => {
+
+                        let name = match tcx.map.expect_expr(id).node {
+                            ast::ExprMethodCall(ref sp_ident, _, _) => sp_ident.node,
+                            _ => tcx.sess.span_bug(
+                                tcx.map.span(id),
+                                "non-method call expr behaving like a method call?")
+                        };
+                        // it matches if it comes from the same impl,
+                        // and has the same method name.
+                        return ast_util::is_local(impl_def_id)
+                            && impl_def_id.node == impl_id
+                            && method_name.name == name.name
+                    }
+                }
+            };
+
+            ast_util::is_local(did) && did.node == method_id
+        }
+    }
+}
+
+declare_lint! {
+    PLUGIN_AS_LIBRARY,
+    Warn,
+    "compiler plugin used as ordinary library in non-plugin crate"
+}
+
+#[derive(Copy)]
+pub struct PluginAsLibrary;
+
+impl LintPass for PluginAsLibrary {
+    fn get_lints(&self) -> LintArray {
+        lint_array![PLUGIN_AS_LIBRARY]
+    }
+
+    fn check_item(&mut self, cx: &Context, it: &ast::Item) {
+        if cx.sess().plugin_registrar_fn.get().is_some() {
+            // We're compiling a plugin; it's fine to link other plugins.
+            return;
+        }
+
+        match it.node {
+            ast::ItemExternCrate(..) => (),
+            _ => return,
+        };
+
+        let md = match cx.sess().cstore.find_extern_mod_stmt_cnum(it.id) {
+            Some(cnum) => cx.sess().cstore.get_crate_data(cnum),
+            None => {
+                // Probably means we aren't linking the crate for some reason.
+                //
+                // Not sure if / when this could happen.
+                return;
+            }
+        };
+
+        if decoder::get_plugin_registrar_fn(md.data()).is_some() {
+            cx.span_lint(PLUGIN_AS_LIBRARY, it.span,
+                "compiler plugin used as an ordinary library");
+        }
+    }
+}
+
+declare_lint! {
+    PRIVATE_NO_MANGLE_FNS,
+    Warn,
+    "functions marked #[no_mangle] should be exported"
+}
+
+declare_lint! {
+    PRIVATE_NO_MANGLE_STATICS,
+    Warn,
+    "statics marked #[no_mangle] should be exported"
+}
+
+declare_lint! {
+    NO_MANGLE_CONST_ITEMS,
+    Deny,
+    "const items will not have their symbols exported"
+}
+
+#[derive(Copy)]
+pub struct InvalidNoMangleItems;
+
+impl LintPass for InvalidNoMangleItems {
+    fn get_lints(&self) -> LintArray {
+        lint_array!(PRIVATE_NO_MANGLE_FNS,
+                    PRIVATE_NO_MANGLE_STATICS,
+                    NO_MANGLE_CONST_ITEMS)
+    }
+
+    fn check_item(&mut self, cx: &Context, it: &ast::Item) {
+        match it.node {
+            ast::ItemFn(..) => {
+                if attr::contains_name(&it.attrs, "no_mangle") &&
+                       !cx.exported_items.contains(&it.id) {
+                    let msg = format!("function {} is marked #[no_mangle], but not exported",
+                                      it.ident);
+                    cx.span_lint(PRIVATE_NO_MANGLE_FNS, it.span, &msg);
+                }
+            },
+            ast::ItemStatic(..) => {
+                if attr::contains_name(it.attrs.as_slice(), "no_mangle") &&
+                       !cx.exported_items.contains(&it.id) {
+                    let msg = format!("static {} is marked #[no_mangle], but not exported",
+                                      it.ident);
+                    cx.span_lint(PRIVATE_NO_MANGLE_STATICS, it.span, msg.as_slice());
+                }
+            },
+            ast::ItemConst(..) => {
+                if attr::contains_name(it.attrs.as_slice(), "no_mangle") {
+                    // Const items do not refer to a particular location in memory, and therefore
+                    // don't have anything to attach a symbol to
+                    let msg = "const items should never be #[no_mangle], consider instead using \
+                        `pub static`";
+                    cx.span_lint(NO_MANGLE_CONST_ITEMS, it.span, msg);
+                }
+            }
+            _ => {},
+        }
+    }
+}
+
+/// Forbids using the `#[feature(...)]` attribute
+#[derive(Copy)]
+pub struct UnstableFeatures;
+
+declare_lint!(UNSTABLE_FEATURES, Allow,
+              "enabling unstable features");
+
+impl LintPass for UnstableFeatures {
+    fn get_lints(&self) -> LintArray {
+        lint_array!(UNSTABLE_FEATURES)
+    }
+    fn check_attribute(&mut self, ctx: &Context, attr: &ast::Attribute) {
+        use syntax::attr;
+        if attr::contains_name(&[attr.node.value.clone()], "feature") {
+            ctx.span_lint(UNSTABLE_FEATURES, attr.span, "unstable feature");
+        }
+    }
+}
diff --git a/src/librustc_lint/lib.rs b/src/librustc_lint/lib.rs
new file mode 100644 (file)
index 0000000..9eef0f1
--- /dev/null
@@ -0,0 +1,137 @@
+// 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.
+
+//! Lints in the Rust compiler.
+//!
+//! This currently only contains the definitions and implementations
+//! of most of the lints that `rustc` supports directly, it does not
+//! contain the infrastructure for defining/registering lints. That is
+//! available in `rustc::lint` and `rustc::plugin` respectively.
+//!
+//! # Note
+//!
+//! This API is completely unstable and subject to change.
+
+#![crate_name = "rustc_lint"]
+#![unstable(feature = "rustc_private")]
+#![staged_api]
+#![crate_type = "dylib"]
+#![crate_type = "rlib"]
+#![doc(html_logo_url = "http://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
+      html_favicon_url = "http://www.rust-lang.org/favicon.ico",
+      html_root_url = "http://doc.rust-lang.org/nightly/")]
+
+#![feature(box_patterns)]
+#![feature(box_syntax)]
+#![feature(collections)]
+#![feature(core)]
+#![feature(int_uint)]
+#![feature(quote)]
+#![feature(rustc_diagnostic_macros)]
+#![feature(rustc_private)]
+#![feature(unsafe_destructor)]
+#![feature(staged_api)]
+#![feature(std_misc)]
+#![feature(unicode)]
+#![cfg_attr(test, feature(test))]
+
+extern crate syntax;
+#[macro_use]
+extern crate rustc;
+#[macro_use]
+extern crate log;
+
+pub use rustc::lint as lint;
+pub use rustc::metadata as metadata;
+pub use rustc::middle as middle;
+pub use rustc::session as session;
+pub use rustc::util as util;
+
+use session::Session;
+use lint::{LintPassObject, LintId};
+
+mod builtin;
+
+/// Tell the `LintStore` about all the built-in lints (the ones
+/// defined in this crate and the ones defined in
+/// `rustc::lint::builtin`).
+pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) {
+    macro_rules! add_builtin {
+        ($sess:ident, $($name:ident),*,) => (
+            {$(
+                store.register_pass($sess, false, box builtin::$name as LintPassObject);
+                )*}
+            )
+    }
+
+    macro_rules! add_builtin_with_new {
+        ($sess:ident, $($name:ident),*,) => (
+            {$(
+                store.register_pass($sess, false, box builtin::$name::new() as LintPassObject);
+                )*}
+            )
+    }
+
+    macro_rules! add_lint_group {
+        ($sess:ident, $name:expr, $($lint:ident),*) => (
+            store.register_group($sess, false, $name, vec![$(LintId::of(builtin::$lint)),*]);
+            )
+    }
+
+    add_builtin!(sess,
+                 HardwiredLints,
+                 WhileTrue,
+                 UnusedCasts,
+                 ImproperCTypes,
+                 BoxPointers,
+                 UnusedAttributes,
+                 PathStatements,
+                 UnusedResults,
+                 NonCamelCaseTypes,
+                 NonSnakeCase,
+                 NonUpperCaseGlobals,
+                 UnusedParens,
+                 UnusedImportBraces,
+                 NonShorthandFieldPatterns,
+                 UnusedUnsafe,
+                 UnsafeCode,
+                 UnusedMut,
+                 UnusedAllocation,
+                 MissingCopyImplementations,
+                 UnstableFeatures,
+                 Stability,
+                 UnconditionalRecursion,
+                 InvalidNoMangleItems,
+                 PluginAsLibrary,
+                 );
+
+    add_builtin_with_new!(sess,
+                          TypeLimits,
+                          RawPointerDerive,
+                          MissingDoc,
+                          MissingDebugImplementations,
+                          );
+
+    add_lint_group!(sess, "bad_style",
+                    NON_CAMEL_CASE_TYPES, NON_SNAKE_CASE, NON_UPPER_CASE_GLOBALS);
+
+    add_lint_group!(sess, "unused",
+                    UNUSED_IMPORTS, UNUSED_VARIABLES, UNUSED_ASSIGNMENTS, DEAD_CODE,
+                    UNUSED_MUT, UNREACHABLE_CODE, UNUSED_MUST_USE,
+                    UNUSED_UNSAFE, PATH_STATEMENTS);
+
+    // We have one lint pass defined specially
+    store.register_pass(sess, false, box lint::GatherNodeLevels as LintPassObject);
+
+    // Insert temporary renamings for a one-time deprecation
+    store.register_renamed("raw_pointer_deriving", "raw_pointer_derive");
+
+    store.register_renamed("unknown_features", "unused_features");
+}
index f0a640aa2e0e2c78a02785b6e723ed06b384ac0e..46729988bb6bd976c658bb1c23e4be691c0e8c38 100644 (file)
@@ -17,7 +17,6 @@
       html_favicon_url = "http://www.rust-lang.org/favicon.ico",
       html_root_url = "http://doc.rust-lang.org/nightly/")]
 
-#![feature(core)]
 #![feature(int_uint)]
 #![feature(rustc_diagnostic_macros)]
 #![feature(rustc_private)]
@@ -38,8 +37,7 @@
 use rustc::middle::privacy::ImportUse::*;
 use rustc::middle::privacy::LastPrivate::*;
 use rustc::middle::privacy::PrivateDep::*;
-use rustc::middle::privacy::{ExportedItems, PublicItems, LastPrivateMap};
-use rustc::middle::privacy::{ExternalExports};
+use rustc::middle::privacy::{ExternalExports, ExportedItems, PublicItems};
 use rustc::middle::ty::{MethodTypeParam, MethodStatic};
 use rustc::middle::ty::{MethodCall, MethodMap, MethodOrigin, MethodParam};
 use rustc::middle::ty::{MethodStaticClosure, MethodObject};
@@ -235,6 +233,7 @@ fn visit_item(&mut self, item: &ast::Item) {
             ast::ItemEnum(ref def, _) if public_first => {
                 for variant in &def.variants {
                     self.exported_items.insert(variant.node.id);
+                    self.public_items.insert(variant.node.id);
                 }
             }
 
@@ -259,8 +258,8 @@ fn visit_item(&mut self, item: &ast::Item) {
             // * Private trait impls for private types can be completely ignored
             ast::ItemImpl(_, _, _, _, ref ty, ref impl_items) => {
                 let public_ty = match ty.node {
-                    ast::TyPath(_, id) => {
-                        match self.tcx.def_map.borrow()[id].clone() {
+                    ast::TyPath(..) => {
+                        match self.tcx.def_map.borrow()[ty.id].full_def() {
                             def::DefPrimTy(..) => true,
                             def => {
                                 let did = def.def_id();
@@ -323,11 +322,20 @@ fn visit_item(&mut self, item: &ast::Item) {
                     Some(id) => { self.exported_items.insert(id); }
                     None => {}
                 }
+                // fields can be public or private, so lets check
+                for field in &def.fields {
+                    let vis = match field.node.kind {
+                        ast::NamedField(_, vis) | ast::UnnamedField(vis) => vis
+                    };
+                    if vis == ast::Public {
+                        self.public_items.insert(field.node.id);
+                    }
+                }
             }
 
             ast::ItemTy(ref ty, _) if public_first => {
-                if let ast::TyPath(_, id) = ty.node {
-                    match self.tcx.def_map.borrow()[id].clone() {
+                if let ast::TyPath(..) = ty.node {
+                    match self.tcx.def_map.borrow()[ty.id].full_def() {
                         def::DefPrimTy(..) | def::DefTyParam(..) => {},
                         def => {
                             let did = def.def_id();
@@ -379,7 +387,6 @@ struct PrivacyVisitor<'a, 'tcx: 'a> {
     in_foreign: bool,
     parents: NodeMap<ast::NodeId>,
     external_exports: ExternalExports,
-    last_private_map: LastPrivateMap,
 }
 
 enum PrivacyResult {
@@ -628,11 +635,11 @@ fn ensure_public(&self, span: Span, to_check: ast::DefId,
                     // back up the chains to find the relevant struct/enum that
                     // was private.
                     ast::ItemImpl(_, _, _, _, ref ty, _) => {
-                        let id = match ty.node {
-                            ast::TyPath(_, id) => id,
+                        match ty.node {
+                            ast::TyPath(..) => {}
                             _ => return Some((err_span, err_msg, None)),
                         };
-                        let def = self.tcx.def_map.borrow()[id].clone();
+                        let def = self.tcx.def_map.borrow()[ty.id].full_def();
                         let did = def.def_id();
                         assert!(is_local(did));
                         match self.tcx.map.get(did.node) {
@@ -716,21 +723,21 @@ fn check_static_method(&mut self,
     }
 
     // Checks that a path is in scope.
-    fn check_path(&mut self, span: Span, path_id: ast::NodeId, path: &ast::Path) {
+    fn check_path(&mut self, span: Span, path_id: ast::NodeId, last: ast::Ident) {
         debug!("privacy - path {}", self.nodestr(path_id));
-        let orig_def = self.tcx.def_map.borrow()[path_id].clone();
+        let path_res = self.tcx.def_map.borrow()[path_id];
         let ck = |tyname: &str| {
             let ck_public = |def: ast::DefId| {
                 debug!("privacy - ck_public {:?}", def);
-                let name = token::get_ident(path.segments.last().unwrap().identifier);
-                let origdid = orig_def.def_id();
+                let name = token::get_ident(last);
+                let origdid = path_res.def_id();
                 self.ensure_public(span,
                                    def,
                                    Some(origdid),
                                    &format!("{} `{}`", tyname, name))
             };
 
-            match self.last_private_map[path_id] {
+            match path_res.last_private {
                 LastMod(AllPublic) => {},
                 LastMod(DependsOn(def)) => {
                     self.report_error(ck_public(def));
@@ -794,17 +801,15 @@ fn check_path(&mut self, span: Span, path_id: ast::NodeId, path: &ast::Path) {
         // def map is not. Therefore the names we work out below will not always
         // be accurate and we can get slightly wonky error messages (but type
         // checking is always correct).
-        match self.tcx.def_map.borrow()[path_id].clone() {
-            def::DefStaticMethod(..) => ck("static method"),
+        match path_res.full_def() {
             def::DefFn(..) => ck("function"),
             def::DefStatic(..) => ck("static"),
             def::DefConst(..) => ck("const"),
             def::DefVariant(..) => ck("variant"),
             def::DefTy(_, false) => ck("type"),
             def::DefTy(_, true) => ck("enum"),
-            def::DefaultImpl(..) => ck("trait"),
+            def::DefTrait(..) => ck("trait"),
             def::DefStruct(..) => ck("struct"),
-            def::DefMethod(_, Some(..), _) => ck("trait method"),
             def::DefMethod(..) => ck("method"),
             def::DefMod(..) => ck("module"),
             _ => {}
@@ -832,37 +837,22 @@ fn check_method(&mut self, span: Span, origin: &MethodOrigin,
 
 impl<'a, 'tcx, 'v> Visitor<'v> for PrivacyVisitor<'a, 'tcx> {
     fn visit_item(&mut self, item: &ast::Item) {
-        match item.node {
-            ast::ItemUse(ref vpath) => {
-                match vpath.node {
-                    ast::ViewPathSimple(..) | ast::ViewPathGlob(..) => {}
-                    ast::ViewPathList(ref prefix, ref list) => {
-                        for pid in list {
-                            match pid.node {
-                                ast::PathListIdent { id, name } => {
-                                    debug!("privacy - ident item {}", id);
-                                    let seg = ast::PathSegment {
-                                        identifier: name,
-                                        parameters: ast::PathParameters::none(),
-                                    };
-                                    let segs = vec![seg];
-                                    let path = ast::Path {
-                                        global: false,
-                                        span: pid.span,
-                                        segments: segs,
-                                    };
-                                    self.check_path(pid.span, id, &path);
-                                }
-                                ast::PathListMod { id } => {
-                                    debug!("privacy - mod item {}", id);
-                                    self.check_path(pid.span, id, prefix);
-                                }
-                            }
+        if let ast::ItemUse(ref vpath) = item.node {
+            if let ast::ViewPathList(ref prefix, ref list) = vpath.node {
+                for pid in list {
+                    match pid.node {
+                        ast::PathListIdent { id, name } => {
+                            debug!("privacy - ident item {}", id);
+                            self.check_path(pid.span, id, name);
+                        }
+                        ast::PathListMod { id } => {
+                            debug!("privacy - mod item {}", id);
+                            let name = prefix.segments.last().unwrap().identifier;
+                            self.check_path(pid.span, id, name);
                         }
                     }
                 }
             }
-            _ => {}
         }
         let orig_curitem = replace(&mut self.curitem, item.id);
         visit::walk_item(self, item);
@@ -908,7 +898,7 @@ fn visit_expr(&mut self, expr: &ast::Expr) {
                         }
                     }
                     ty::ty_enum(_, _) => {
-                        match self.tcx.def_map.borrow()[expr.id].clone() {
+                        match self.tcx.def_map.borrow()[expr.id].full_def() {
                             def::DefVariant(_, variant_id, _) => {
                                 for field in fields {
                                     self.check_field(expr.span, variant_id,
@@ -927,7 +917,7 @@ fn visit_expr(&mut self, expr: &ast::Expr) {
                                                             struct type?!"),
                 }
             }
-            ast::ExprPath(_) | ast::ExprQPath(_) => {
+            ast::ExprPath(..) => {
                 let guard = |did: ast::DefId| {
                     let fields = ty::lookup_struct_fields(self.tcx, did);
                     let any_priv = fields.iter().any(|f| {
@@ -941,8 +931,8 @@ struct type?!"),
                              with private fields");
                     }
                 };
-                match self.tcx.def_map.borrow().get(&expr.id) {
-                    Some(&def::DefStruct(did)) => {
+                match self.tcx.def_map.borrow().get(&expr.id).map(|d| d.full_def()) {
+                    Some(def::DefStruct(did)) => {
                         guard(if is_local(did) {
                             local_def(self.tcx.map.get_parent(did.node))
                         } else {
@@ -981,8 +971,8 @@ fn visit_pat(&mut self, pattern: &ast::Pat) {
                         }
                     }
                     ty::ty_enum(_, _) => {
-                        match self.tcx.def_map.borrow().get(&pattern.id) {
-                            Some(&def::DefVariant(_, variant_id, _)) => {
+                        match self.tcx.def_map.borrow().get(&pattern.id).map(|d| d.full_def()) {
+                            Some(def::DefVariant(_, variant_id, _)) => {
                                 for field in fields {
                                     self.check_field(pattern.span, variant_id,
                                                      NamedField(field.node.ident.name));
@@ -1033,7 +1023,7 @@ fn visit_foreign_item(&mut self, fi: &ast::ForeignItem) {
     }
 
     fn visit_path(&mut self, path: &ast::Path, id: ast::NodeId) {
-        self.check_path(path.span, id, path);
+        self.check_path(path.span, id, path.segments.last().unwrap().identifier);
         visit::walk_path(self, path);
     }
 }
@@ -1233,7 +1223,7 @@ struct CheckTypeForPrivatenessVisitor<'a, 'b: 'a, 'tcx: 'b> {
 
 impl<'a, 'tcx> VisiblePrivateTypesVisitor<'a, 'tcx> {
     fn path_is_private_type(&self, path_id: ast::NodeId) -> bool {
-        let did = match self.tcx.def_map.borrow().get(&path_id).cloned() {
+        let did = match self.tcx.def_map.borrow().get(&path_id).map(|d| d.full_def()) {
             // `int` etc. (None doesn't seem to occur.)
             None | Some(def::DefPrimTy(..)) => return false,
             Some(def) => def.def_id()
@@ -1273,8 +1263,8 @@ fn check_ty_param_bound(&self,
 
 impl<'a, 'b, 'tcx, 'v> Visitor<'v> for CheckTypeForPrivatenessVisitor<'a, 'b, 'tcx> {
     fn visit_ty(&mut self, ty: &ast::Ty) {
-        if let ast::TyPath(_, path_id) = ty.node {
-            if self.inner.path_is_private_type(path_id) {
+        if let ast::TyPath(..) = ty.node {
+            if self.inner.path_is_private_type(ty.id) {
                 self.contains_private = true;
                 // found what we're looking for so let's stop
                 // working.
@@ -1398,7 +1388,7 @@ fn visit_item(&mut self, item: &ast::Item) {
                             //
                             // Those in 2. are warned via walk_generics and this
                             // call here.
-                            self.visit_trait_ref(tr)
+                            visit::walk_path(self, &tr.path);
                         }
                     }
                 } else if trait_ref.is_none() && self_is_public_path {
@@ -1479,9 +1469,9 @@ fn visit_fn(&mut self, fk: visit::FnKind<'v>, fd: &'v ast::FnDecl,
     }
 
     fn visit_ty(&mut self, t: &ast::Ty) {
-        if let ast::TyPath(ref p, path_id) = t.node {
+        if let ast::TyPath(_, ref p) = t.node {
             if !self.tcx.sess.features.borrow().visible_private_types &&
-                self.path_is_private_type(path_id) {
+                self.path_is_private_type(t.id) {
                 self.tcx.sess.span_err(p.span,
                                        "private type in exported type signature");
             }
@@ -1517,8 +1507,7 @@ fn visit_expr(&mut self, _: &ast::Expr) {}
 
 pub fn check_crate(tcx: &ty::ctxt,
                    export_map: &def::ExportMap,
-                   external_exports: ExternalExports,
-                   last_private_map: LastPrivateMap)
+                   external_exports: ExternalExports)
                    -> (ExportedItems, PublicItems) {
     let krate = tcx.map.krate();
 
@@ -1536,7 +1525,6 @@ pub fn check_crate(tcx: &ty::ctxt,
         tcx: tcx,
         parents: visitor.parents,
         external_exports: external_exports,
-        last_private_map: last_private_map,
     };
     visit::walk_crate(&mut visitor, krate);
 
index 31f21a84f842b796f416fe356dc9842b012eae8c..67e2b409c8e2213d8dfd8613d68d803972992dd5 100644 (file)
 use NameBindings;
 use ParentLink::{self, ModuleParentLink, BlockParentLink};
 use Resolver;
-use RibKind::*;
 use Shadowable;
 use TypeNsDef;
-use TypeParameters::HasTypeParameters;
 
 use self::DuplicateCheckingMode::*;
 use self::NamespaceError::*;
@@ -34,7 +32,6 @@
 use rustc::metadata::csearch;
 use rustc::metadata::decoder::{DefLike, DlDef, DlField, DlImpl};
 use rustc::middle::def::*;
-use rustc::middle::subst::FnSpace;
 
 use syntax::ast::{Block, Crate};
 use syntax::ast::{DeclItem, DefId};
 use syntax::ast::{Item, ItemConst, ItemEnum, ItemExternCrate, ItemFn};
 use syntax::ast::{ItemForeignMod, ItemImpl, ItemMac, ItemMod, ItemStatic, ItemDefaultImpl};
 use syntax::ast::{ItemStruct, ItemTrait, ItemTy, ItemUse};
-use syntax::ast::{MethodImplItem, Name, NamedField, NodeId};
-use syntax::ast::{PathListIdent, PathListMod};
-use syntax::ast::{Public, SelfStatic};
+use syntax::ast::{Name, NamedField, NodeId};
+use syntax::ast::{PathListIdent, PathListMod, Public};
 use syntax::ast::StmtDecl;
 use syntax::ast::StructVariantKind;
 use syntax::ast::TupleVariantKind;
-use syntax::ast::TyObjectSum;
-use syntax::ast::{TypeImplItem, UnnamedField};
+use syntax::ast::UnnamedField;
 use syntax::ast::{Variant, ViewPathGlob, ViewPathList, ViewPathSimple};
 use syntax::ast::{Visibility};
-use syntax::ast::TyPath;
 use syntax::ast;
-use syntax::ast_util::{self, PostExpansionMethod, local_def};
+use syntax::ast_util::{self, local_def};
 use syntax::attr::AttrMetaMethods;
 use syntax::parse::token::{self, special_idents};
 use syntax::codemap::{Span, DUMMY_SP};
@@ -181,12 +175,8 @@ fn add_child(&self,
                         Some(TypeNS)
                     }
                     ForbidDuplicateTypesAndModules => {
-                        match child.def_for_namespace(TypeNS) {
-                            None => {}
-                            Some(_) if child.get_module_if_available()
-                                            .map(|m| m.kind.get()) ==
-                                       Some(ImplModuleKind) => {}
-                            Some(_) => duplicate_type = TypeError
+                        if child.defined_in_namespace(TypeNS) {
+                            duplicate_type = TypeError;
                         }
                         Some(TypeNS)
                     }
@@ -465,9 +455,6 @@ fn build_reduced_graph_for_item(&mut self, item: &Item, parent: &Rc<Module>) ->
                 name_bindings.define_type(DefTy(local_def(item.id), true), sp, modifiers);
 
                 let parent_link = self.get_parent_link(parent, name);
-                // We want to make sure the module type is EnumModuleKind
-                // even if there's already an ImplModuleKind module defined,
-                // since that's how we prevent duplicate enum definitions
                 name_bindings.set_module_kind(parent_link,
                                               Some(local_def(item.id)),
                                               EnumModuleKind,
@@ -517,147 +504,8 @@ fn build_reduced_graph_for_item(&mut self, item: &Item, parent: &Rc<Module>) ->
                 parent.clone()
             }
 
-            ItemImpl(_, _, _, None, ref ty, ref impl_items) => {
-                // If this implements an anonymous trait, then add all the
-                // methods within to a new module, if the type was defined
-                // within this module.
-
-                let mod_name = match ty.node {
-                    TyPath(ref path, _) if path.segments.len() == 1 => {
-                        // FIXME(18446) we should distinguish between the name of
-                        // a trait and the name of an impl of that trait.
-                        Some(path.segments.last().unwrap().identifier.name)
-                    }
-                    TyObjectSum(ref lhs_ty, _) => {
-                        match lhs_ty.node {
-                            TyPath(ref path, _) if path.segments.len() == 1 => {
-                                Some(path.segments.last().unwrap().identifier.name)
-                            }
-                            _ => {
-                                None
-                            }
-                        }
-                    }
-                    _ => {
-                        None
-                    }
-                };
-
-                let mod_name = match mod_name {
-                    Some(mod_name) => mod_name,
-                    None => {
-                        self.resolve_error(ty.span,
-                                           "inherent implementations may \
-                                            only be implemented in the same \
-                                            module as the type they are \
-                                            implemented for");
-                        return parent.clone();
-                    }
-                };
-                // Create the module and add all methods.
-                let child_opt = parent.children.borrow().get(&mod_name)
-                                       .and_then(|m| m.get_module_if_available());
-                let new_parent = match child_opt {
-                    // It already exists
-                    Some(ref child) if (child.kind.get() == ImplModuleKind ||
-                                        child.kind.get() == TraitModuleKind) => {
-                        child.clone()
-                    }
-                    Some(ref child) if child.kind.get() == EnumModuleKind ||
-                                       child.kind.get() == TypeModuleKind => {
-                        child.clone()
-                    }
-                    // Create the module
-                    _ => {
-                        let name_bindings =
-                            self.add_child(mod_name, parent, ForbidDuplicateModules, sp);
-
-                        let parent_link = self.get_parent_link(parent, name);
-                        let def_id = local_def(item.id);
-                        let ns = TypeNS;
-                        let is_public =
-                            !name_bindings.defined_in_namespace(ns) ||
-                            name_bindings.defined_in_public_namespace(ns);
-
-                        name_bindings.define_module(parent_link,
-                                                    Some(def_id),
-                                                    ImplModuleKind,
-                                                    false,
-                                                    is_public,
-                                                    sp);
-
-                        name_bindings.get_module()
-                    }
-                };
-
-                // For each implementation item...
-                for impl_item in impl_items {
-                    match *impl_item {
-                        MethodImplItem(ref method) => {
-                            // Add the method to the module.
-                            let name = method.pe_ident().name;
-                            let method_name_bindings =
-                                self.add_child(name,
-                                               &new_parent,
-                                               ForbidDuplicateValues,
-                                               method.span);
-                            let def = match method.pe_explicit_self()
-                                .node {
-                                    SelfStatic => {
-                                        // Static methods become
-                                        // `DefStaticMethod`s.
-                                        DefStaticMethod(local_def(method.id),
-                                                        FromImpl(local_def(item.id)))
-                                    }
-                                    _ => {
-                                        // Non-static methods become
-                                        // `DefMethod`s.
-                                        DefMethod(local_def(method.id),
-                                                  None,
-                                                  FromImpl(local_def(item.id)))
-                                    }
-                                };
-
-                            // NB: not IMPORTABLE
-                            let modifiers = if method.pe_vis() == ast::Public {
-                                PUBLIC
-                            } else {
-                                DefModifiers::empty()
-                            };
-                            method_name_bindings.define_value(
-                                def,
-                                method.span,
-                                modifiers);
-                        }
-                        TypeImplItem(ref typedef) => {
-                            // Add the typedef to the module.
-                            let name = typedef.ident.name;
-                            let typedef_name_bindings =
-                                self.add_child(
-                                    name,
-                                    &new_parent,
-                                    ForbidDuplicateTypesAndModules,
-                                    typedef.span);
-                            let def = DefAssociatedTy(local_def(
-                                typedef.id));
-                            // NB: not IMPORTABLE
-                            let modifiers = if typedef.vis == ast::Public {
-                                PUBLIC
-                            } else {
-                                DefModifiers::empty()
-                            };
-                            typedef_name_bindings.define_type(
-                                def,
-                                typedef.span,
-                                modifiers);
-                        }
-                    }
-                }
-                parent.clone()
-            }
-
             ItemDefaultImpl(_, _) |
-            ItemImpl(_, _, _, Some(_), _, _) => parent.clone(),
+            ItemImpl(..) => parent.clone(),
 
             ItemTrait(_, _, _, ref items) => {
                 let name_bindings =
@@ -677,7 +525,7 @@ fn build_reduced_graph_for_item(&mut self, item: &Item, parent: &Rc<Module>) ->
 
                 // Add the names of all the items to the trait info.
                 for trait_item in items {
-                    let (name, kind) = match *trait_item {
+                    let (name, trait_item_id) = match *trait_item {
                         ast::RequiredMethod(_) |
                         ast::ProvidedMethod(_) => {
                             let ty_m = ast_util::trait_item_to_ty_method(trait_item);
@@ -685,23 +533,8 @@ fn build_reduced_graph_for_item(&mut self, item: &Item, parent: &Rc<Module>) ->
                             let name = ty_m.ident.name;
 
                             // Add it as a name in the trait module.
-                            let (def, static_flag) = match ty_m.explicit_self
-                                                               .node {
-                                SelfStatic => {
-                                    // Static methods become `DefStaticMethod`s.
-                                    (DefStaticMethod(
-                                            local_def(ty_m.id),
-                                            FromTrait(local_def(item.id))),
-                                     StaticMethodTraitItemKind)
-                                }
-                                _ => {
-                                    // Non-static methods become `DefMethod`s.
-                                    (DefMethod(local_def(ty_m.id),
-                                               Some(local_def(item.id)),
-                                               FromTrait(local_def(item.id))),
-                                     NonstaticMethodTraitItemKind)
-                                }
-                            };
+                            let def = DefMethod(local_def(ty_m.id),
+                                                FromTrait(local_def(item.id)));
 
                             let method_name_bindings =
                                 self.add_child(name,
@@ -713,11 +546,11 @@ fn build_reduced_graph_for_item(&mut self, item: &Item, parent: &Rc<Module>) ->
                                                               ty_m.span,
                                                               PUBLIC);
 
-                            (name, static_flag)
+                            (name, local_def(ty_m.id))
                         }
                         ast::TypeTraitItem(ref associated_type) => {
-                            let def = DefAssociatedTy(local_def(
-                                    associated_type.ty_param.id));
+                            let def = DefAssociatedTy(local_def(item.id),
+                                                      local_def(associated_type.ty_param.id));
 
                             let name_bindings =
                                 self.add_child(associated_type.ty_param.ident.name,
@@ -729,14 +562,15 @@ fn build_reduced_graph_for_item(&mut self, item: &Item, parent: &Rc<Module>) ->
                                                       associated_type.ty_param.span,
                                                       PUBLIC);
 
-                            (associated_type.ty_param.ident.name, TypeTraitItemKind)
+                            (associated_type.ty_param.ident.name,
+                             local_def(associated_type.ty_param.id))
                         }
                     };
 
-                    self.trait_item_map.insert((name, def_id), kind);
+                    self.trait_item_map.insert((name, def_id), trait_item_id);
                 }
 
-                name_bindings.define_type(DefaultImpl(def_id), sp, modifiers);
+                name_bindings.define_type(DefTrait(def_id), sp, modifiers);
                 parent.clone()
             }
             ItemMac(..) => parent.clone()
@@ -773,12 +607,9 @@ fn build_reduced_graph_for_variant(&mut self,
     }
 
     /// Constructs the reduced graph for one foreign item.
-    fn build_reduced_graph_for_foreign_item<F>(&mut self,
-                                               foreign_item: &ForeignItem,
-                                               parent: &Rc<Module>,
-                                               f: F) where
-        F: FnOnce(&mut Resolver),
-    {
+    fn build_reduced_graph_for_foreign_item(&mut self,
+                                            foreign_item: &ForeignItem,
+                                            parent: &Rc<Module>) {
         let name = foreign_item.ident.name;
         let is_public = foreign_item.vis == ast::Public;
         let modifiers = if is_public { PUBLIC } else { DefModifiers::empty() } | IMPORTABLE;
@@ -786,25 +617,15 @@ fn build_reduced_graph_for_foreign_item<F>(&mut self,
             self.add_child(name, parent, ForbidDuplicateValues,
                            foreign_item.span);
 
-        match foreign_item.node {
-            ForeignItemFn(_, ref generics) => {
-                let def = DefFn(local_def(foreign_item.id), false);
-                name_bindings.define_value(def, foreign_item.span, modifiers);
-
-                self.with_type_parameter_rib(
-                    HasTypeParameters(generics,
-                                      FnSpace,
-                                      foreign_item.id,
-                                      NormalRibKind),
-                    f);
+        let def = match foreign_item.node {
+            ForeignItemFn(..) => {
+                DefFn(local_def(foreign_item.id), false)
             }
             ForeignItemStatic(_, m) => {
-                let def = DefStatic(local_def(foreign_item.id), m);
-                name_bindings.define_value(def, foreign_item.span, modifiers);
-
-                f(self.resolver)
+                DefStatic(local_def(foreign_item.id), m)
             }
-        }
+        };
+        name_bindings.define_value(def, foreign_item.span, modifiers);
     }
 
     fn build_reduced_graph_for_block(&mut self, block: &Block, parent: &Rc<Module>) -> Rc<Module> {
@@ -850,8 +671,7 @@ fn handle_external_def(&mut self,
 
         let kind = match def {
             DefTy(_, true) => EnumModuleKind,
-            DefTy(_, false) => TypeModuleKind,
-            DefStruct(..) => ImplModuleKind,
+            DefTy(_, false) | DefStruct(..) => TypeModuleKind,
             _ => NormalModuleKind
         };
 
@@ -905,7 +725,7 @@ 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(..) | DefStaticMethod(..) | DefStatic(..) | DefConst(..) | DefMethod(..) => {
+          DefFn(..) | DefStatic(..) | DefConst(..) | 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
@@ -918,7 +738,7 @@ fn handle_external_def(&mut self,
             }
             child_name_bindings.define_value(def, DUMMY_SP, modifiers);
           }
-          DefaultImpl(def_id) => {
+          DefTrait(def_id) => {
               debug!("(building reduced graph for external \
                       crate) building type {}", final_ident);
 
@@ -927,21 +747,19 @@ fn handle_external_def(&mut self,
 
               let trait_item_def_ids =
                 csearch::get_trait_item_def_ids(&self.session.cstore, def_id);
-              for trait_item_def_id in &trait_item_def_ids {
-                  let (trait_item_name, trait_item_kind) =
-                      csearch::get_trait_item_name_and_kind(
-                          &self.session.cstore,
-                          trait_item_def_id.def_id());
+              for trait_item_def in &trait_item_def_ids {
+                  let trait_item_name = csearch::get_trait_name(&self.session.cstore,
+                                                                trait_item_def.def_id());
 
                   debug!("(building reduced graph for external crate) ... \
                           adding trait item '{}'",
                          token::get_name(trait_item_name));
 
-                  self.trait_item_map.insert((trait_item_name, def_id), trait_item_kind);
+                  self.trait_item_map.insert((trait_item_name, def_id),
+                                             trait_item_def.def_id());
 
                   if is_exported {
-                      self.external_exports
-                          .insert(trait_item_def_id.def_id());
+                      self.external_exports.insert(trait_item_def.def_id());
                   }
               }
 
@@ -956,7 +774,7 @@ fn handle_external_def(&mut self,
                                                   is_public,
                                                   DUMMY_SP)
           }
-          DefTy(..) | DefAssociatedTy(..) | DefAssociatedPath(..) => {
+          DefTy(..) | DefAssociatedTy(..) => {
               debug!("(building reduced graph for external \
                       crate) building type {}", final_ident);
 
@@ -980,7 +798,7 @@ fn handle_external_def(&mut self,
           }
           DefLocal(..) | DefPrimTy(..) | DefTyParam(..) |
           DefUse(..) | DefUpvar(..) | DefRegion(..) |
-          DefTyParamBinder(..) | DefLabel(..) | DefSelfTy(..) => {
+          DefLabel(..) | DefSelfTy(..) => {
             panic!("didn't expect `{:?}`", def);
           }
         }
@@ -1027,92 +845,9 @@ fn build_reduced_graph_for_external_crate_def(&mut self,
                     }
                 }
             }
-            DlImpl(def) => {
-                match csearch::get_type_name_if_impl(&self.session.cstore, def) {
-                    None => {}
-                    Some(final_name) => {
-                        let methods_opt =
-                            csearch::get_methods_if_impl(&self.session.cstore, def);
-                        match methods_opt {
-                            Some(ref methods) if
-                                methods.len() >= 1 => {
-                                debug!("(building reduced graph for \
-                                        external crate) processing \
-                                        static methods for type name {}",
-                                        token::get_name(final_name));
-
-                                let child_name_bindings =
-                                    self.add_child(
-                                        final_name,
-                                        root,
-                                        OverwriteDuplicates,
-                                        DUMMY_SP);
-
-                                // Process the static methods. First,
-                                // create the module.
-                                let type_module;
-                                let type_def = child_name_bindings.type_def.borrow().clone();
-                                match type_def {
-                                    Some(TypeNsDef {
-                                        module_def: Some(module_def),
-                                        ..
-                                    }) => {
-                                        // We already have a module. This
-                                        // is OK.
-                                        type_module = module_def;
-
-                                        // Mark it as an impl module if
-                                        // necessary.
-                                        type_module.kind.set(ImplModuleKind);
-                                    }
-                                    Some(_) | None => {
-                                        let parent_link =
-                                            self.get_parent_link(root, final_name);
-                                        child_name_bindings.define_module(
-                                            parent_link,
-                                            Some(def),
-                                            ImplModuleKind,
-                                            true,
-                                            true,
-                                            DUMMY_SP);
-                                        type_module =
-                                            child_name_bindings.
-                                                get_module();
-                                    }
-                                }
-
-                                // Add each static method to the module.
-                                let new_parent = type_module;
-                                for method_info in methods {
-                                    let name = method_info.name;
-                                    debug!("(building reduced graph for \
-                                             external crate) creating \
-                                             static method '{}'",
-                                           token::get_name(name));
-
-                                    let method_name_bindings =
-                                        self.add_child(name,
-                                                       &new_parent,
-                                                       OverwriteDuplicates,
-                                                       DUMMY_SP);
-                                    let def = DefFn(method_info.def_id, false);
-
-                                    // NB: not IMPORTABLE
-                                    let modifiers = if method_info.vis == ast::Public {
-                                        PUBLIC
-                                    } else {
-                                        DefModifiers::empty()
-                                    };
-                                    method_name_bindings.define_value(
-                                        def, DUMMY_SP, modifiers);
-                                }
-                            }
-
-                            // Otherwise, do nothing.
-                            Some(_) | None => {}
-                        }
-                    }
-                }
+            DlImpl(_) => {
+                debug!("(building reduced graph for external crate) \
+                        ignoring impl");
             }
             DlField => {
                 debug!("(building reduced graph for external crate) \
@@ -1241,16 +976,7 @@ fn visit_item(&mut self, item: &Item) {
     }
 
     fn visit_foreign_item(&mut self, foreign_item: &ForeignItem) {
-        let parent = &self.parent;
-        self.builder.build_reduced_graph_for_foreign_item(foreign_item,
-                                                          parent,
-                                                          |r| {
-            let mut v = BuildReducedGraphVisitor {
-                builder: GraphBuilder { resolver: r },
-                parent: parent.clone()
-            };
-            visit::walk_foreign_item(&mut v, foreign_item);
-        })
+        self.builder.build_reduced_graph_for_foreign_item(foreign_item, &self.parent);
     }
 
     fn visit_block(&mut self, block: &Block) {
index a239c73c110dbd67e96353ad8efca3f20b6b82b5..aebbe14407380336174b9c85f82bd693b5084dbd 100644 (file)
@@ -68,17 +68,17 @@ fn finalize_import(&mut self, id: ast::NodeId, span: Span) {
                                   "unused import".to_string());
         }
 
-        let (v_priv, t_priv) = match self.last_private.get(&id) {
-            Some(&LastImport {
-                value_priv: v,
-                value_used: _,
-                type_priv: t,
-                type_used: _
-            }) => (v, t),
-            Some(_) => {
+        let mut def_map = self.def_map.borrow_mut();
+        let path_res = if let Some(r) = def_map.get_mut(&id) {
+            r
+        } else {
+            return;
+        };
+        let (v_priv, t_priv) = match path_res.last_private {
+            LastImport { value_priv, type_priv, .. } => (value_priv, type_priv),
+            _ => {
                 panic!("we should only have LastImport for `use` directives")
             }
-            _ => return,
         };
 
         let mut v_used = if self.used_imports.contains(&(id, ValueNS)) {
@@ -100,10 +100,12 @@ fn finalize_import(&mut self, id: ast::NodeId, span: Span) {
             _ => {},
         }
 
-        self.last_private.insert(id, LastImport{value_priv: v_priv,
-                                                value_used: v_used,
-                                                type_priv: t_priv,
-                                                type_used: t_used});
+        path_res.last_private = LastImport {
+            value_priv: v_priv,
+            value_used: v_used,
+            type_priv: t_priv,
+            type_used: t_used
+        };
     }
 }
 
index c38b8fc750281f0a6f07f93a836cb6f14a962cef..78ce9abe07d92495d9e646a2ae0122845b24231f 100644 (file)
 use self::FallbackSuggestion::*;
 use self::TypeParameters::*;
 use self::RibKind::*;
-use self::MethodSort::*;
 use self::UseLexicalScopeFlag::*;
 use self::ModulePrefixResult::*;
 use self::NameSearchType::*;
 use self::BareIdentifierPatternResolution::*;
 use self::ParentLink::*;
 use self::ModuleKind::*;
-use self::TraitReferenceType::*;
 use self::FallbackChecks::*;
 
 use rustc::session::Session;
 
 use syntax::ast::{Arm, BindByRef, BindByValue, BindingMode, Block, Crate, CrateNum};
 use syntax::ast::{DefId, Expr, ExprAgain, ExprBreak, ExprField};
-use syntax::ast::{ExprClosure, ExprLoop, ExprWhile, ExprMethodCall};
-use syntax::ast::{ExprPath, ExprQPath, ExprStruct, FnDecl};
+use syntax::ast::{ExprLoop, ExprWhile, ExprMethodCall};
+use syntax::ast::{ExprPath, ExprStruct, FnDecl};
 use syntax::ast::{ForeignItemFn, ForeignItemStatic, Generics};
 use syntax::ast::{Ident, ImplItem, Item, ItemConst, ItemEnum, ItemExternCrate};
 use syntax::ast::{ItemFn, ItemForeignMod, ItemImpl, ItemMac, ItemMod, ItemStatic, ItemDefaultImpl};
 use syntax::ast::{ItemStruct, ItemTrait, ItemTy, ItemUse};
-use syntax::ast::{Local, MethodImplItem, Mod, Name, NodeId};
+use syntax::ast::{Local, MethodImplItem, Name, NodeId};
 use syntax::ast::{Pat, PatEnum, PatIdent, PatLit};
-use syntax::ast::{PatRange, PatStruct, Path};
-use syntax::ast::{PolyTraitRef, PrimTy, SelfExplicit};
-use syntax::ast::{RegionTyParamBound, StructField};
-use syntax::ast::{TraitRef, TraitTyParamBound};
-use syntax::ast::{Ty, TyBool, TyChar, TyF32};
-use syntax::ast::{TyF64, TyFloat, TyIs, TyI8, TyI16, TyI32, TyI64, TyInt, TyObjectSum};
-use syntax::ast::{TyParam, TyParamBound, TyPath, TyPtr, TyPolyTraitRef, TyQPath};
+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};
+use syntax::ast::{TyPath, TyPtr};
 use syntax::ast::{TyRptr, TyStr, TyUs, TyU8, TyU16, TyU32, TyU64, TyUint};
 use syntax::ast::{TypeImplItem};
 use syntax::ast;
@@ -89,8 +84,7 @@
 use syntax::attr::AttrMetaMethods;
 use syntax::ext::mtwt;
 use syntax::parse::token::{self, special_names, special_idents};
-use syntax::codemap::{Span, Pos};
-use syntax::owned_slice::OwnedSlice;
+use syntax::codemap::{self, Span, Pos};
 use syntax::visit::{self, Visitor};
 
 use std::collections::{HashMap, HashSet};
@@ -188,6 +182,72 @@ fn visit_local(&mut self, local: &Local) {
     fn visit_ty(&mut self, ty: &Ty) {
         self.resolve_type(ty);
     }
+    fn visit_generics(&mut self, generics: &Generics) {
+        self.resolve_generics(generics);
+    }
+    fn visit_poly_trait_ref(&mut self,
+                            tref: &ast::PolyTraitRef,
+                            m: &ast::TraitBoundModifier) {
+        match self.resolve_trait_reference(tref.trait_ref.ref_id, &tref.trait_ref.path, 0) {
+            Ok(def) => self.record_def(tref.trait_ref.ref_id, def),
+            Err(_) => { /* error already reported */ }
+        }
+        visit::walk_poly_trait_ref(self, tref, m);
+    }
+    fn visit_variant(&mut self, variant: &ast::Variant, generics: &Generics) {
+        if let Some(ref dis_expr) = variant.node.disr_expr {
+            // resolve the discriminator expr as a constant
+            self.with_constant_rib(|this| {
+                this.visit_expr(&**dis_expr);
+            });
+        }
+
+        // `visit::walk_variant` without the discriminant expression.
+        match variant.node.kind {
+            ast::TupleVariantKind(ref variant_arguments) => {
+                for variant_argument in variant_arguments.iter() {
+                    self.visit_ty(&*variant_argument.ty);
+                }
+            }
+            ast::StructVariantKind(ref struct_definition) => {
+                self.visit_struct_def(&**struct_definition,
+                                      variant.node.name,
+                                      generics,
+                                      variant.node.id);
+            }
+        }
+    }
+    fn visit_foreign_item(&mut self, foreign_item: &ast::ForeignItem) {
+        let type_parameters = match foreign_item.node {
+            ForeignItemFn(_, ref generics) => {
+                HasTypeParameters(generics, FnSpace, ItemRibKind)
+            }
+            ForeignItemStatic(..) => NoTypeParameters
+        };
+        self.with_type_parameter_rib(type_parameters, |this| {
+            visit::walk_foreign_item(this, foreign_item);
+        });
+    }
+    fn visit_fn(&mut self,
+                function_kind: visit::FnKind<'v>,
+                declaration: &'v FnDecl,
+                block: &'v Block,
+                _: Span,
+                node_id: NodeId) {
+        let rib_kind = match function_kind {
+            visit::FkItemFn(_, generics, _, _) => {
+                self.visit_generics(generics);
+                ItemRibKind
+            }
+            visit::FkMethod(_, generics, method) => {
+                self.visit_generics(generics);
+                self.visit_explicit_self(method.pe_explicit_self());
+                MethodRibKind
+            }
+            visit::FkFnBlock(..) => ClosureRibKind(node_id)
+        };
+        self.resolve_function(rib_kind, declaration, block);
+    }
 }
 
 /// Contains data for specific types of import directives.
@@ -231,9 +291,6 @@ enum TypeParameters<'a> {
         // were declared on (type, fn, etc)
         ParamSpace,
 
-        // ID of the enclosing item.
-        NodeId,
-
         // The kind of the rib used for type parameters.
         RibKind)
 }
@@ -253,8 +310,7 @@ enum RibKind {
     // methods. Allow references to ty params that impl or trait
     // binds. Disallow any other upvars (including other ty params that are
     // upvars).
-              // parent;   method itself
-    MethodRibKind(NodeId, MethodSort),
+    MethodRibKind,
 
     // We passed through an item scope. Disallow upvars.
     ItemRibKind,
@@ -263,13 +319,6 @@ enum RibKind {
     ConstantItemRibKind
 }
 
-// Methods can be required or provided. RequiredMethod methods only occur in traits.
-#[derive(Copy, Debug)]
-enum MethodSort {
-    RequiredMethod,
-    ProvidedMethod(NodeId)
-}
-
 #[derive(Copy)]
 enum UseLexicalScopeFlag {
     DontUseLexicalScope,
@@ -465,7 +514,6 @@ enum ParentLink {
 enum ModuleKind {
     NormalModuleKind,
     TraitModuleKind,
-    ImplModuleKind,
     EnumModuleKind,
     TypeModuleKind,
     AnonymousModuleKind,
@@ -586,16 +634,6 @@ struct NameBindings {
     value_def: RefCell<Option<ValueNsDef>>, //< Meaning in value namespace.
 }
 
-/// Ways in which a trait can be referenced
-#[derive(Copy)]
-enum TraitReferenceType {
-    TraitImplementation,             // impl SomeTrait for T { ... }
-    TraitDerivation,                 // trait T : SomeTrait { ... }
-    TraitBoundingTypeParameter,      // fn f<T:SomeTrait>() { ... }
-    TraitObject,                     // Box<for<'a> SomeTrait>
-    TraitQPath,                      // <T as SomeTrait>::
-}
-
 impl NameBindings {
     fn new() -> NameBindings {
         NameBindings {
@@ -861,7 +899,7 @@ struct Resolver<'a, 'tcx:'a> {
 
     graph_root: NameBindings,
 
-    trait_item_map: FnvHashMap<(Name, DefId), TraitItemKind>,
+    trait_item_map: FnvHashMap<(Name, DefId), DefId>,
 
     structs: FnvHashMap<DefId, Vec<Name>>,
 
@@ -901,7 +939,6 @@ struct Resolver<'a, 'tcx:'a> {
     export_map: ExportMap,
     trait_map: TraitMap,
     external_exports: ExternalExports,
-    last_private: LastPrivateMap,
 
     // Whether or not to print error messages. Can be set to true
     // when getting additional info for error message suggestions,
@@ -976,7 +1013,6 @@ fn new(session: &'a Session,
             used_imports: HashSet::new(),
             used_crates: HashSet::new(),
             external_exports: DefIdSet(),
-            last_private: NodeMap(),
 
             emit_errors: true,
             make_glob_map: make_glob_map == MakeGlobMap::Yes,
@@ -1096,8 +1132,8 @@ fn names_to_string(&self, names: &[Name]) -> String {
         result
     }
 
-    fn path_names_to_string(&self, path: &Path) -> String {
-        let names: Vec<ast::Name> = path.segments
+    fn path_names_to_string(&self, path: &Path, depth: usize) -> String {
+        let names: Vec<ast::Name> = path.segments[..path.segments.len()-depth]
                                         .iter()
                                         .map(|seg| seg.identifier.name)
                                         .collect();
@@ -1534,31 +1570,36 @@ fn get_binding(this: &mut Resolver,
         // record what this import resolves to for later uses in documentation,
         // this may resolve to either a value or a type, but for documentation
         // purposes it's good enough to just favor one over the other.
-        let value_private = match import_resolution.value_target {
-            Some(ref target) => {
-                let def = target.bindings.def_for_namespace(ValueNS).unwrap();
-                self.def_map.borrow_mut().insert(directive.id, def);
-                let did = def.def_id();
-                if value_used_public {Some(lp)} else {Some(DependsOn(did))}
-            },
-            // AllPublic here and below is a dummy value, it should never be used because
-            // _exists is false.
-            None => None,
-        };
-        let type_private = match import_resolution.type_target {
-            Some(ref target) => {
-                let def = target.bindings.def_for_namespace(TypeNS).unwrap();
-                self.def_map.borrow_mut().insert(directive.id, def);
-                let did = def.def_id();
-                if type_used_public {Some(lp)} else {Some(DependsOn(did))}
-            },
-            None => None,
+        let value_def_and_priv = import_resolution.value_target.as_ref().map(|target| {
+            let def = target.bindings.def_for_namespace(ValueNS).unwrap();
+            (def, if value_used_public { lp } else { DependsOn(def.def_id()) })
+        });
+        let type_def_and_priv = import_resolution.type_target.as_ref().map(|target| {
+            let def = target.bindings.def_for_namespace(TypeNS).unwrap();
+            (def, if type_used_public { lp } else { DependsOn(def.def_id()) })
+        });
+
+        let import_lp = LastImport {
+            value_priv: value_def_and_priv.map(|(_, p)| p),
+            value_used: Used,
+            type_priv: type_def_and_priv.map(|(_, p)| p),
+            type_used: Used
         };
 
-        self.last_private.insert(directive.id, LastImport{value_priv: value_private,
-                                                          value_used: Used,
-                                                          type_priv: type_private,
-                                                          type_used: Used});
+        if let Some((def, _)) = value_def_and_priv {
+            self.def_map.borrow_mut().insert(directive.id, PathResolution {
+                base_def: def,
+                last_private: import_lp,
+                depth: 0
+            });
+        }
+        if let Some((def, _)) = type_def_and_priv {
+            self.def_map.borrow_mut().insert(directive.id, PathResolution {
+                base_def: def,
+                last_private: import_lp,
+                depth: 0
+            });
+        }
 
         debug!("(resolving single import) successfully resolved import");
         return Success(());
@@ -1676,12 +1717,12 @@ fn resolve_glob_import(&mut self,
         }
 
         // Record the destination of this import
-        match containing_module.def_id.get() {
-            Some(did) => {
-                self.def_map.borrow_mut().insert(id, DefMod(did));
-                self.last_private.insert(id, lp);
-            }
-            None => {}
+        if let Some(did) = containing_module.def_id.get() {
+            self.def_map.borrow_mut().insert(id, PathResolution {
+                base_def: DefMod(did),
+                last_private: lp,
+                depth: 0
+            });
         }
 
         debug!("(resolving glob import) successfully resolved import");
@@ -1822,13 +1863,11 @@ fn check_for_conflicts_between_imports_and_items(&mut self,
         match import_resolution.value_target {
             Some(ref target) if target.shadowable != Shadowable::Always => {
                 if let Some(ref value) = *name_bindings.value_def.borrow() {
-                    let msg = format!("import `{}` conflicts with value \
-                                       in this module",
-                                      &token::get_name(name));
-                    span_err!(self.session, import_span, E0255, "{}", &msg[..]);
+                    span_err!(self.session, import_span, E0255,
+                              "import `{}` conflicts with value in this module",
+                              &token::get_name(name));
                     if let Some(span) = value.value_span {
-                        self.session.span_note(span,
-                                               "conflicting value here");
+                        self.session.span_note(span, "conflicting value here");
                     }
                 }
             }
@@ -1838,41 +1877,16 @@ fn check_for_conflicts_between_imports_and_items(&mut self,
         match import_resolution.type_target {
             Some(ref target) if target.shadowable != Shadowable::Always => {
                 if let Some(ref ty) = *name_bindings.type_def.borrow() {
-                    match ty.module_def {
-                        None => {
-                            let msg = format!("import `{}` conflicts with type in \
-                                               this module",
-                                              &token::get_name(name));
-                            span_err!(self.session, import_span, E0256, "{}", &msg[..]);
-                            if let Some(span) = ty.type_span {
-                                self.session.span_note(span,
-                                                       "note conflicting type here")
-                            }
-                        }
-                        Some(ref module_def) => {
-                            match module_def.kind.get() {
-                                ImplModuleKind => {
-                                    if let Some(span) = ty.type_span {
-                                        let msg = format!("inherent implementations \
-                                                           are only allowed on types \
-                                                           defined in the current module");
-                                        span_err!(self.session, span, E0257, "{}", &msg[..]);
-                                        self.session.span_note(import_span,
-                                                               "import from other module here")
-                                    }
-                                }
-                                _ => {
-                                    let msg = format!("import `{}` conflicts with existing \
-                                                       submodule",
-                                                      &token::get_name(name));
-                                    span_err!(self.session, import_span, E0258, "{}", &msg[..]);
-                                    if let Some(span) = ty.type_span {
-                                        self.session.span_note(span,
-                                                               "note conflicting module here")
-                                    }
-                                }
-                            }
-                        }
+                    let (what, note) = if ty.module_def.is_some() {
+                        ("existing submodule", "note conflicting module here")
+                    } else {
+                        ("type in this module", "note conflicting type here")
+                    };
+                    span_err!(self.session, import_span, E0256,
+                              "import `{}` conflicts with {}",
+                              &token::get_name(name), what);
+                    if let Some(span) = ty.type_span {
+                        self.session.span_note(span, note);
                     }
                 }
             }
@@ -2226,7 +2240,6 @@ fn resolve_item_in_lexical_scope(&mut self,
                             return Failed(None);
                         }
                         TraitModuleKind |
-                        ImplModuleKind |
                         EnumModuleKind |
                         TypeModuleKind |
                         AnonymousModuleKind => {
@@ -2324,7 +2337,6 @@ fn get_nearest_normal_module_parent(&mut self, module_: Rc<Module>)
                     match new_module.kind.get() {
                         NormalModuleKind => return Some(new_module),
                         TraitModuleKind |
-                        ImplModuleKind |
                         EnumModuleKind |
                         TypeModuleKind |
                         AnonymousModuleKind => module_ = new_module,
@@ -2341,7 +2353,6 @@ fn get_nearest_normal_module_parent_or_self(&mut self, module_: Rc<Module>)
         match module_.kind.get() {
             NormalModuleKind => return module_,
             TraitModuleKind |
-            ImplModuleKind |
             EnumModuleKind |
             TypeModuleKind |
             AnonymousModuleKind => {
@@ -2600,14 +2611,16 @@ fn upvarify(&self,
                 def_like: DefLike,
                 span: Span)
                 -> Option<DefLike> {
-        match def_like {
-            DlDef(d @ DefUpvar(..)) => {
+        let mut def = match def_like {
+            DlDef(def) => def,
+            _ => return Some(def_like)
+        };
+        match def {
+            DefUpvar(..) => {
                 self.session.span_bug(span,
-                    &format!("unexpected {:?} in bindings", d))
+                    &format!("unexpected {:?} in bindings", def))
             }
-            DlDef(d @ DefLocal(_)) => {
-                let node_id = d.def_id().node;
-                let mut def = d;
+            DefLocal(node_id) => {
                 for rib in ribs {
                     match rib.kind {
                         NormalRibKind => {
@@ -2631,39 +2644,14 @@ fn upvarify(&self,
                             }.push(Freevar { def: prev_def, span: span });
                             seen.insert(node_id);
                         }
-                        MethodRibKind(item_id, _) => {
-                            // If the def is a ty param, and came from the parent
-                            // item, it's ok
-                            match def {
-                                DefTyParam(_, _, did, _) if {
-                                    self.def_map.borrow().get(&did.node).cloned()
-                                        == Some(DefTyParamBinder(item_id))
-                                } => {} // ok
-                                DefSelfTy(did) if did == item_id => {} // ok
-                                _ => {
-                                    // This was an attempt to access an upvar inside a
-                                    // named function item. This is not allowed, so we
-                                    // report an error.
-
-                                    self.resolve_error(
-                                        span,
-                                        "can't capture dynamic environment in a fn item; \
-                                        use the || { ... } closure form instead");
-
-                                    return None;
-                                }
-                            }
-                        }
-                        ItemRibKind => {
+                        ItemRibKind | MethodRibKind => {
                             // This was an attempt to access an upvar inside a
                             // named function item. This is not allowed, so we
                             // report an error.
 
-                            self.resolve_error(
-                                span,
+                            self.resolve_error(span,
                                 "can't capture dynamic environment in a fn item; \
-                                use the || { ... } closure form instead");
-
+                                 use the || { ... } closure form instead");
                             return None;
                         }
                         ConstantItemRibKind => {
@@ -2671,42 +2659,17 @@ fn upvarify(&self,
                             self.resolve_error(span,
                                                "attempt to use a non-constant \
                                                 value in a constant");
-
+                            return None;
                         }
                     }
                 }
-                Some(DlDef(def))
             }
-            DlDef(def @ DefTyParam(..)) |
-            DlDef(def @ DefSelfTy(..)) => {
+            DefTyParam(..) | DefSelfTy(_) => {
                 for rib in ribs {
                     match rib.kind {
-                        NormalRibKind | ClosureRibKind(..) => {
+                        NormalRibKind | MethodRibKind | ClosureRibKind(..) => {
                             // Nothing to do. Continue.
                         }
-                        MethodRibKind(item_id, _) => {
-                            // If the def is a ty param, and came from the parent
-                            // item, it's ok
-                            match def {
-                                DefTyParam(_, _, did, _) if {
-                                    self.def_map.borrow().get(&did.node).cloned()
-                                        == Some(DefTyParamBinder(item_id))
-                                } => {} // ok
-                                DefSelfTy(did) if did == item_id => {} // ok
-
-                                _ => {
-                                    // This was an attempt to use a type parameter outside
-                                    // its scope.
-
-                                    self.resolve_error(span,
-                                                        "can't use type parameters from \
-                                                        outer function; try using a local \
-                                                        type parameter instead");
-
-                                    return None;
-                                }
-                            }
-                        }
                         ItemRibKind => {
                             // This was an attempt to use a type parameter outside
                             // its scope.
@@ -2715,7 +2678,6 @@ fn upvarify(&self,
                                                "can't use type parameters from \
                                                 outer function; try using a local \
                                                 type parameter instead");
-
                             return None;
                         }
                         ConstantItemRibKind => {
@@ -2723,14 +2685,14 @@ fn upvarify(&self,
                             self.resolve_error(span,
                                                "cannot use an outer type \
                                                 parameter in this context");
-
+                            return None;
                         }
                     }
                 }
-                Some(DlDef(def))
             }
-            _ => Some(def_like)
+            _ => {}
         }
+        Some(DlDef(def))
     }
 
     /// Searches the current set of local scopes and
@@ -2743,13 +2705,8 @@ fn search_ribs(&self,
         // FIXME #4950: Try caching?
 
         for (i, rib) in ribs.iter().enumerate().rev() {
-            match rib.bindings.get(&name).cloned() {
-                Some(def_like) => {
-                    return self.upvarify(&ribs[i + 1..], def_like, span);
-                }
-                None => {
-                    // Continue.
-                }
+            if let Some(def_like) = rib.bindings.get(&name).cloned() {
+                return self.upvarify(&ribs[i + 1..], def_like, span);
             }
         }
 
@@ -2797,59 +2754,32 @@ fn resolve_item(&mut self, item: &Item) {
                token::get_name(name));
 
         match item.node {
-
-            // enum item: resolve all the variants' discrs,
-            // then resolve the ty params
-            ItemEnum(ref enum_def, ref generics) => {
+            ItemEnum(_, ref generics) |
+            ItemTy(_, ref generics) |
+            ItemStruct(_, ref generics) => {
                 self.check_if_primitive_type_name(name, item.span);
 
-                for variant in &(*enum_def).variants {
-                    if let Some(ref dis_expr) = variant.node.disr_expr {
-                        // resolve the discriminator expr
-                        // as a constant
-                        self.with_constant_rib(|this| {
-                            this.resolve_expr(&**dis_expr);
-                        });
-                    }
-                }
-
-                // n.b. the discr expr gets visited twice.
-                // but maybe it's okay since the first time will signal an
-                // error if there is one? -- tjc
                 self.with_type_parameter_rib(HasTypeParameters(generics,
                                                                TypeSpace,
-                                                               item.id,
                                                                ItemRibKind),
-                                             |this| {
-                    this.resolve_type_parameters(&generics.ty_params);
-                    this.resolve_where_clause(&generics.where_clause);
-                    visit::walk_item(this, item);
-                });
+                                             |this| visit::walk_item(this, item));
             }
-
-            ItemTy(_, ref generics) => {
-                self.check_if_primitive_type_name(name, item.span);
-
+            ItemFn(_, _, _, ref generics, _) => {
                 self.with_type_parameter_rib(HasTypeParameters(generics,
-                                                               TypeSpace,
-                                                               item.id,
+                                                               FnSpace,
                                                                ItemRibKind),
-                                             |this| {
-                    this.resolve_type_parameters(&generics.ty_params);
-                    visit::walk_item(this, item);
-                });
+                                             |this| visit::walk_item(this, item));
             }
 
             ItemDefaultImpl(_, ref trait_ref) => {
-                self.resolve_trait_reference(item.id, trait_ref, TraitImplementation);
+                self.with_optional_trait_ref(Some(trait_ref), |_| {});
             }
             ItemImpl(_, _,
                      ref generics,
                      ref implemented_traits,
                      ref self_type,
                      ref impl_items) => {
-                self.resolve_implementation(item.id,
-                                            generics,
+                self.resolve_implementation(generics,
                                             implemented_traits,
                                             &**self_type,
                                             &impl_items[..]);
@@ -2869,14 +2799,10 @@ fn resolve_item(&mut self, item: &Item) {
                 // Create a new rib for the trait-wide type parameters.
                 self.with_type_parameter_rib(HasTypeParameters(generics,
                                                                TypeSpace,
-                                                               item.id,
                                                                NormalRibKind),
                                              |this| {
-                    this.resolve_type_parameters(&generics.ty_params);
-                    this.resolve_where_clause(&generics.where_clause);
-
-                    this.resolve_type_parameter_bounds(item.id, bounds,
-                                                       TraitDerivation);
+                    this.visit_generics(generics);
+                    visit::walk_ty_param_bounds_helper(this, bounds);
 
                     for trait_item in &(*trait_items) {
                         // Create a new rib for the trait_item-specific type
@@ -2884,101 +2810,39 @@ fn resolve_item(&mut self, item: &Item) {
                         //
                         // FIXME #4951: Do we need a node ID here?
 
-                        match *trait_item {
-                          ast::RequiredMethod(ref ty_m) => {
-                            this.with_type_parameter_rib
-                                (HasTypeParameters(&ty_m.generics,
-                                                   FnSpace,
-                                                   item.id,
-                                        MethodRibKind(item.id, RequiredMethod)),
-                                 |this| {
-
-                                // Resolve the method-specific type
-                                // parameters.
-                                this.resolve_type_parameters(
-                                    &ty_m.generics.ty_params);
-                                this.resolve_where_clause(&ty_m.generics
-                                                               .where_clause);
-
-                                for argument in &ty_m.decl.inputs {
-                                    this.resolve_type(&*argument.ty);
-                                }
-
-                                if let SelfExplicit(ref typ, _) = ty_m.explicit_self.node {
-                                    this.resolve_type(&**typ)
-                                }
-
-                                if let ast::Return(ref ret_ty) = ty_m.decl.output {
-                                    this.resolve_type(&**ret_ty);
-                                }
-                            });
-                          }
-                          ast::ProvidedMethod(ref m) => {
-                              this.resolve_method(MethodRibKind(item.id,
-                                                                ProvidedMethod(m.id)),
-                                                  &**m)
-                          }
-                          ast::TypeTraitItem(ref data) => {
-                              this.resolve_type_parameter(&data.ty_param);
-                              visit::walk_trait_item(this, trait_item);
-                          }
-                        }
+                        let type_parameters = match *trait_item {
+                            ast::RequiredMethod(ref ty_m) => {
+                                HasTypeParameters(&ty_m.generics,
+                                                  FnSpace,
+                                                  MethodRibKind)
+                            }
+                            ast::ProvidedMethod(ref m) => {
+                                HasTypeParameters(m.pe_generics(),
+                                                  FnSpace,
+                                                  MethodRibKind)
+                            }
+                            ast::TypeTraitItem(ref assoc_ty) => {
+                                let ty_param = &assoc_ty.ty_param;
+                                this.check_if_primitive_type_name(ty_param.ident.name,
+                                                                  ty_param.span);
+                                NoTypeParameters
+                            }
+                        };
+                        this.with_type_parameter_rib(type_parameters, |this| {
+                            visit::walk_trait_item(this, trait_item)
+                        });
                     }
                 });
 
                 self.type_ribs.pop();
             }
 
-            ItemStruct(ref struct_def, ref generics) => {
-                self.check_if_primitive_type_name(name, item.span);
-
-                self.resolve_struct(item.id,
-                                    generics,
-                                    &struct_def.fields);
-            }
-
-            ItemMod(ref module_) => {
+            ItemMod(_) | ItemForeignMod(_) => {
                 self.with_scope(Some(name), |this| {
-                    this.resolve_module(module_, item.span, name,
-                                        item.id);
-                });
-            }
-
-            ItemForeignMod(ref foreign_module) => {
-                self.with_scope(Some(name), |this| {
-                    for foreign_item in &foreign_module.items {
-                        match foreign_item.node {
-                            ForeignItemFn(_, ref generics) => {
-                                this.with_type_parameter_rib(
-                                    HasTypeParameters(
-                                        generics, FnSpace, foreign_item.id,
-                                        ItemRibKind),
-                                    |this| {
-                                        this.resolve_type_parameters(&generics.ty_params);
-                                        this.resolve_where_clause(&generics.where_clause);
-                                        visit::walk_foreign_item(this, &**foreign_item)
-                                    });
-                            }
-                            ForeignItemStatic(..) => {
-                                visit::walk_foreign_item(this,
-                                                         &**foreign_item);
-                            }
-                        }
-                    }
+                    visit::walk_item(this, item);
                 });
             }
 
-            ItemFn(ref fn_decl, _, _, ref generics, ref block) => {
-                self.resolve_function(ItemRibKind,
-                                      Some(&**fn_decl),
-                                      HasTypeParameters
-                                        (generics,
-                                         FnSpace,
-                                         item.id,
-                                         ItemRibKind),
-                                      &**block);
-            }
-
             ItemConst(..) | ItemStatic(..) => {
                 self.with_constant_rib(|this| {
                     visit::walk_item(this, item);
@@ -2988,8 +2852,8 @@ fn resolve_item(&mut self, item: &Item) {
             ItemUse(ref view_path) => {
                 // check for imports shadowing primitive types
                 if let ast::ViewPathSimple(ident, _) = view_path.node {
-                    match self.def_map.borrow().get(&item.id) {
-                        Some(&DefTy(..)) | Some(&DefStruct(..)) | Some(&DefaultImpl(..)) | None => {
+                    match self.def_map.borrow().get(&item.id).map(|d| d.full_def()) {
+                        Some(DefTy(..)) | Some(DefStruct(..)) | Some(DefTrait(..)) | None => {
                             self.check_if_primitive_type_name(ident.name, item.span);
                         }
                         _ => {}
@@ -3007,35 +2871,29 @@ fn with_type_parameter_rib<F>(&mut self, type_parameters: TypeParameters, f: F)
         F: FnOnce(&mut Resolver),
     {
         match type_parameters {
-            HasTypeParameters(generics, space, node_id, rib_kind) => {
+            HasTypeParameters(generics, space, rib_kind) => {
                 let mut function_type_rib = Rib::new(rib_kind);
                 let mut seen_bindings = HashSet::new();
                 for (index, type_parameter) in generics.ty_params.iter().enumerate() {
                     let name = type_parameter.ident.name;
-                    debug!("with_type_parameter_rib: {} {}", node_id,
-                           type_parameter.id);
+                    debug!("with_type_parameter_rib: {}", type_parameter.id);
 
                     if seen_bindings.contains(&name) {
                         self.resolve_error(type_parameter.span,
                                            &format!("the name `{}` is already \
-                                                    used for a type \
-                                                    parameter in this type \
-                                                    parameter list",
-                                                   token::get_name(
-                                                       name)))
+                                                     used for a type \
+                                                     parameter in this type \
+                                                     parameter list",
+                                                    token::get_name(name)))
                     }
                     seen_bindings.insert(name);
 
-                    let def_like = DlDef(DefTyParam(space,
-                                                    index as u32,
-                                                    local_def(type_parameter.id),
-                                                    name));
-                    // Associate this type parameter with
-                    // the item that bound it
-                    self.record_def(type_parameter.id,
-                                    (DefTyParamBinder(node_id), LastMod(AllPublic)));
                     // plain insert (no renaming)
-                    function_type_rib.bindings.insert(name, def_like);
+                    function_type_rib.bindings.insert(name,
+                        DlDef(DefTyParam(space,
+                                         index as u32,
+                                         local_def(type_parameter.id),
+                                         name)));
                 }
                 self.type_ribs.push(function_type_rib);
             }
@@ -3073,224 +2931,84 @@ fn with_constant_rib<F>(&mut self, f: F) where
 
     fn resolve_function(&mut self,
                         rib_kind: RibKind,
-                        optional_declaration: Option<&FnDecl>,
-                        type_parameters: TypeParameters,
+                        declaration: &FnDecl,
                         block: &Block) {
         // Create a value rib for the function.
-        let function_value_rib = Rib::new(rib_kind);
-        self.value_ribs.push(function_value_rib);
+        self.value_ribs.push(Rib::new(rib_kind));
 
         // Create a label rib for the function.
-        let function_label_rib = Rib::new(rib_kind);
-        self.label_ribs.push(function_label_rib);
+        self.label_ribs.push(Rib::new(rib_kind));
 
-        // If this function has type parameters, add them now.
-        self.with_type_parameter_rib(type_parameters, |this| {
-            // Resolve the type parameters.
-            match type_parameters {
-                NoTypeParameters => {
-                    // Continue.
-                }
-                HasTypeParameters(ref generics, _, _, _) => {
-                    this.resolve_type_parameters(&generics.ty_params);
-                    this.resolve_where_clause(&generics.where_clause);
-                }
-            }
-
-            // Add each argument to the rib.
-            match optional_declaration {
-                None => {
-                    // Nothing to do.
-                }
-                Some(declaration) => {
-                    let mut bindings_list = HashMap::new();
-                    for argument in &declaration.inputs {
-                        this.resolve_pattern(&*argument.pat,
-                                             ArgumentIrrefutableMode,
-                                             &mut bindings_list);
-
-                        this.resolve_type(&*argument.ty);
+        // Add each argument to the rib.
+        let mut bindings_list = HashMap::new();
+        for argument in &declaration.inputs {
+            self.resolve_pattern(&*argument.pat,
+                                 ArgumentIrrefutableMode,
+                                 &mut bindings_list);
 
-                        debug!("(resolving function) recorded argument");
-                    }
+            self.visit_ty(&*argument.ty);
 
-                    if let ast::Return(ref ret_ty) = declaration.output {
-                        this.resolve_type(&**ret_ty);
-                    }
-                }
-            }
+            debug!("(resolving function) recorded argument");
+        }
+        visit::walk_fn_ret_ty(self, &declaration.output);
 
-            // Resolve the function body.
-            this.resolve_block(&*block);
+        // Resolve the function body.
+        self.visit_block(&*block);
 
-            debug!("(resolving function) leaving function");
-        });
+        debug!("(resolving function) leaving function");
 
         self.label_ribs.pop();
         self.value_ribs.pop();
     }
 
-    fn resolve_type_parameters(&mut self,
-                               type_parameters: &OwnedSlice<TyParam>) {
-        for type_parameter in &**type_parameters {
-            self.resolve_type_parameter(type_parameter);
-        }
-    }
-
-    fn resolve_type_parameter(&mut self,
-                              type_parameter: &TyParam) {
-        self.check_if_primitive_type_name(type_parameter.ident.name, type_parameter.span);
-        for bound in &*type_parameter.bounds {
-            self.resolve_type_parameter_bound(type_parameter.id, bound,
-                                              TraitBoundingTypeParameter);
-        }
-        match type_parameter.default {
-            Some(ref ty) => self.resolve_type(&**ty),
-            None => {}
-        }
-    }
-
-    fn resolve_type_parameter_bounds(&mut self,
-                                     id: NodeId,
-                                     type_parameter_bounds: &OwnedSlice<TyParamBound>,
-                                     reference_type: TraitReferenceType) {
-        for type_parameter_bound in &**type_parameter_bounds {
-            self.resolve_type_parameter_bound(id, type_parameter_bound,
-                                              reference_type);
-        }
-    }
-
-    fn resolve_type_parameter_bound(&mut self,
-                                    id: NodeId,
-                                    type_parameter_bound: &TyParamBound,
-                                    reference_type: TraitReferenceType) {
-        match *type_parameter_bound {
-            TraitTyParamBound(ref tref, _) => {
-                self.resolve_poly_trait_reference(id, tref, reference_type)
-            }
-            RegionTyParamBound(..) => {}
-        }
-    }
-
-    fn resolve_poly_trait_reference(&mut self,
-                                    id: NodeId,
-                                    poly_trait_reference: &PolyTraitRef,
-                                    reference_type: TraitReferenceType) {
-        self.resolve_trait_reference(id, &poly_trait_reference.trait_ref, reference_type)
-    }
-
     fn resolve_trait_reference(&mut self,
                                id: NodeId,
-                               trait_reference: &TraitRef,
-                               reference_type: TraitReferenceType) {
-        match self.resolve_path(id, &trait_reference.path, TypeNS, true) {
-            None => {
-                let path_str = self.path_names_to_string(&trait_reference.path);
-                let usage_str = match reference_type {
-                    TraitBoundingTypeParameter => "bound type parameter with",
-                    TraitImplementation        => "implement",
-                    TraitDerivation            => "derive",
-                    TraitObject                => "reference",
-                    TraitQPath                 => "extract an associated item from",
-                };
-
-                let msg = format!("attempt to {} a nonexistent trait `{}`", usage_str, path_str);
-                self.resolve_error(trait_reference.path.span, &msg[..]);
-            }
-            Some(def) => {
-                match def {
-                    (DefaultImpl(_), _) => {
-                        debug!("(resolving trait) found trait def: {:?}", def);
-                        self.record_def(trait_reference.ref_id, def);
-                    }
-                    (def, _) => {
-                        self.resolve_error(trait_reference.path.span,
-                                           &format!("`{}` is not a trait",
-                                                   self.path_names_to_string(
-                                                       &trait_reference.path)));
-
-                        // If it's a typedef, give a note
-                        if let DefTy(..) = def {
-                            self.session.span_note(
-                                trait_reference.path.span,
-                                &format!("`type` aliases cannot be used for traits")
-                                );
-                        }
-                    }
+                               trait_path: &Path,
+                               path_depth: usize)
+                               -> Result<PathResolution, ()> {
+        if let Some(path_res) = self.resolve_path(id, trait_path, path_depth, TypeNS, true) {
+            if let DefTrait(_) = path_res.base_def {
+                debug!("(resolving trait) found trait def: {:?}", path_res);
+                Ok(path_res)
+            } else {
+                self.resolve_error(trait_path.span,
+                    &format!("`{}` is not a trait",
+                             self.path_names_to_string(trait_path, path_depth)));
+
+                // If it's a typedef, give a note
+                if let DefTy(..) = path_res.base_def {
+                    self.session.span_note(trait_path.span,
+                                           "`type` aliases cannot be used for traits");
                 }
+                Err(())
             }
+        } else {
+            let msg = format!("use of undeclared trait name `{}`",
+                              self.path_names_to_string(trait_path, path_depth));
+            self.resolve_error(trait_path.span, &msg);
+            Err(())
         }
     }
 
-    fn resolve_where_clause(&mut self, where_clause: &ast::WhereClause) {
-        for predicate in &where_clause.predicates {
+    fn resolve_generics(&mut self, generics: &Generics) {
+        for type_parameter in &*generics.ty_params {
+            self.check_if_primitive_type_name(type_parameter.ident.name, type_parameter.span);
+        }
+        for predicate in &generics.where_clause.predicates {
             match predicate {
-                &ast::WherePredicate::BoundPredicate(ref bound_pred) => {
-                    self.resolve_type(&*bound_pred.bounded_ty);
-
-                    for bound in &*bound_pred.bounds {
-                        self.resolve_type_parameter_bound(bound_pred.bounded_ty.id, bound,
-                                                          TraitBoundingTypeParameter);
-                    }
-                }
+                &ast::WherePredicate::BoundPredicate(_) |
                 &ast::WherePredicate::RegionPredicate(_) => {}
                 &ast::WherePredicate::EqPredicate(ref eq_pred) => {
-                    match self.resolve_path(eq_pred.id, &eq_pred.path, TypeNS, true) {
-                        Some((def @ DefTyParam(..), last_private)) => {
-                            self.record_def(eq_pred.id, (def, last_private));
-                        }
-                        _ => {
-                            self.resolve_error(eq_pred.path.span,
-                                               "undeclared associated type");
-                        }
+                    let path_res = self.resolve_path(eq_pred.id, &eq_pred.path, 0, TypeNS, true);
+                    if let Some(PathResolution { base_def: DefTyParam(..), .. }) = path_res {
+                        self.record_def(eq_pred.id, path_res.unwrap());
+                    } else {
+                        self.resolve_error(eq_pred.path.span, "undeclared associated type");
                     }
-
-                    self.resolve_type(&*eq_pred.ty);
                 }
             }
         }
-    }
-
-    fn resolve_struct(&mut self,
-                      id: NodeId,
-                      generics: &Generics,
-                      fields: &[StructField]) {
-        // If applicable, create a rib for the type parameters.
-        self.with_type_parameter_rib(HasTypeParameters(generics,
-                                                       TypeSpace,
-                                                       id,
-                                                       ItemRibKind),
-                                     |this| {
-            // Resolve the type parameters.
-            this.resolve_type_parameters(&generics.ty_params);
-            this.resolve_where_clause(&generics.where_clause);
-
-            // Resolve fields.
-            for field in fields {
-                this.resolve_type(&*field.node.ty);
-            }
-        });
-    }
-
-    // Does this really need to take a RibKind or is it always going
-    // to be NormalRibKind?
-    fn resolve_method(&mut self,
-                      rib_kind: RibKind,
-                      method: &ast::Method) {
-        let method_generics = method.pe_generics();
-        let type_parameters = HasTypeParameters(method_generics,
-                                                FnSpace,
-                                                method.id,
-                                                rib_kind);
-
-        if let SelfExplicit(ref typ, _) = method.pe_explicit_self().node {
-            self.resolve_type(&**typ);
-        }
-
-        self.resolve_function(rib_kind,
-                              Some(method.pe_fn_decl()),
-                              type_parameters,
-                              method.pe_body());
+        visit::walk_generics(self, generics);
     }
 
     fn with_current_self_type<T, F>(&mut self, self_type: &Ty, f: F) -> T where
@@ -3303,25 +3021,22 @@ fn with_current_self_type<T, F>(&mut self, self_type: &Ty, f: F) -> T where
         result
     }
 
-    fn with_optional_trait_ref<T, F>(&mut self, id: NodeId,
-                                     opt_trait_ref: &Option<TraitRef>,
+    fn with_optional_trait_ref<T, F>(&mut self,
+                                     opt_trait_ref: Option<&TraitRef>,
                                      f: F) -> T where
         F: FnOnce(&mut Resolver) -> T,
     {
-        let new_val = match *opt_trait_ref {
-            Some(ref trait_ref) => {
-                self.resolve_trait_reference(id, trait_ref, TraitImplementation);
-
-                match self.def_map.borrow().get(&trait_ref.ref_id) {
-                    Some(def) => {
-                        let did = def.def_id();
-                        Some((did, trait_ref.clone()))
-                    }
-                    None => None
+        let mut new_val = None;
+        if let Some(trait_ref) = opt_trait_ref {
+            match self.resolve_trait_reference(trait_ref.ref_id, &trait_ref.path, 0) {
+                Ok(path_res) => {
+                    self.record_def(trait_ref.ref_id, path_res);
+                    new_val = Some((path_res.base_def.def_id(), trait_ref.clone()));
                 }
+                Err(_) => { /* error was already reported */ }
             }
-            None => None
-        };
+            visit::walk_trait_ref(self, trait_ref);
+        }
         let original_trait_ref = replace(&mut self.current_trait_ref, new_val);
         let result = f(self);
         self.current_trait_ref = original_trait_ref;
@@ -3329,7 +3044,6 @@ fn with_optional_trait_ref<T, F>(&mut self, id: NodeId,
     }
 
     fn resolve_implementation(&mut self,
-                              id: NodeId,
                               generics: &Generics,
                               opt_trait_reference: &Option<TraitRef>,
                               self_type: &Ty,
@@ -3337,17 +3051,15 @@ fn resolve_implementation(&mut self,
         // If applicable, create a rib for the type parameters.
         self.with_type_parameter_rib(HasTypeParameters(generics,
                                                        TypeSpace,
-                                                       id,
-                                                       NormalRibKind),
+                                                       ItemRibKind),
                                      |this| {
             // Resolve the type parameters.
-            this.resolve_type_parameters(&generics.ty_params);
-            this.resolve_where_clause(&generics.where_clause);
+            this.visit_generics(generics);
 
             // Resolve the trait reference, if necessary.
-            this.with_optional_trait_ref(id, opt_trait_reference, |this| {
+            this.with_optional_trait_ref(opt_trait_reference.as_ref(), |this| {
                 // Resolve the self type.
-                this.resolve_type(self_type);
+                this.visit_ty(self_type);
 
                 this.with_current_self_type(self_type, |this| {
                     for impl_item in impl_items {
@@ -3360,9 +3072,13 @@ fn resolve_implementation(&mut self,
 
                                 // We also need a new scope for the method-
                                 // specific type parameters.
-                                this.resolve_method(
-                                    MethodRibKind(id, ProvidedMethod(method.id)),
-                                    &**method);
+                                let type_parameters =
+                                    HasTypeParameters(method.pe_generics(),
+                                                      FnSpace,
+                                                      MethodRibKind);
+                                this.with_type_parameter_rib(type_parameters, |this| {
+                                    visit::walk_method_helper(this, &**method);
+                                });
                             }
                             TypeImplItem(ref typedef) => {
                                 // If this is a trait impl, ensure the method
@@ -3370,44 +3086,20 @@ fn resolve_implementation(&mut self,
                                 this.check_trait_item(typedef.ident.name,
                                                       typedef.span);
 
-                                this.resolve_type(&*typedef.typ);
+                                this.visit_ty(&*typedef.typ);
                             }
                         }
                     }
                 });
             });
         });
-
-        // Check that the current type is indeed a type, if we have an anonymous impl
-        if opt_trait_reference.is_none() {
-            match self_type.node {
-                // TyPath is the only thing that we handled in `build_reduced_graph_for_item`,
-                // where we created a module with the name of the type in order to implement
-                // an anonymous trait. In the case that the path does not resolve to an actual
-                // type, the result will be that the type name resolves to a module but not
-                // a type (shadowing any imported modules or types with this name), leading
-                // to weird user-visible bugs. So we ward this off here. See #15060.
-                TyPath(ref path, path_id) => {
-                    match self.def_map.borrow().get(&path_id) {
-                        // FIXME: should we catch other options and give more precise errors?
-                        Some(&DefMod(_)) => {
-                            self.resolve_error(path.span, "inherent implementations are not \
-                                                           allowed for types not defined in \
-                                                           the current module");
-                        }
-                        _ => {}
-                    }
-                }
-                _ => { }
-            }
-        }
     }
 
     fn check_trait_item(&self, name: Name, span: Span) {
         // If there is a TraitRef in scope for an impl, then the method must be in the trait.
         if let Some((did, ref trait_ref)) = self.current_trait_ref {
-            if self.trait_item_map.get(&(name, did)).is_none() {
-                let path_str = self.path_names_to_string(&trait_ref.path);
+            if !self.trait_item_map.contains_key(&(name, did)) {
+                let path_str = self.path_names_to_string(&trait_ref.path, 0);
                 self.resolve_error(span,
                                     &format!("method `{}` is not a member of trait `{}`",
                                             token::get_name(name),
@@ -3416,34 +3108,17 @@ fn check_trait_item(&self, name: Name, span: Span) {
         }
     }
 
-    fn resolve_module(&mut self, module: &Mod, _span: Span,
-                      _name: Name, id: NodeId) {
-        // Write the implementations in scope into the module metadata.
-        debug!("(resolving module) resolving module ID {}", id);
-        visit::walk_mod(self, module);
-    }
-
     fn resolve_local(&mut self, local: &Local) {
         // Resolve the type.
-        if let Some(ref ty) = local.ty {
-            self.resolve_type(&**ty);
-        }
+        visit::walk_ty_opt(self, &local.ty);
 
-        // Resolve the initializer, if necessary.
-        match local.init {
-            None => {
-                // Nothing to do.
-            }
-            Some(ref initializer) => {
-                self.resolve_expr(&**initializer);
-            }
-        }
+        // Resolve the initializer.
+        visit::walk_expr_opt(self, &local.init);
 
         // Resolve the pattern.
-        let mut bindings_list = HashMap::new();
         self.resolve_pattern(&*local.pat,
                              LocalIrrefutableMode,
-                             &mut bindings_list);
+                             &mut HashMap::new());
     }
 
     // build a map from pattern identifiers to binding-info's.
@@ -3521,7 +3196,7 @@ fn resolve_arm(&mut self, arm: &Arm) {
         self.check_consistent_bindings(arm);
 
         visit::walk_expr_opt(self, &arm.guard);
-        self.resolve_expr(&*arm.body);
+        self.visit_expr(&*arm.body);
 
         self.value_ribs.pop();
     }
@@ -3573,90 +3248,63 @@ fn resolve_block(&mut self, block: &Block) {
 
     fn resolve_type(&mut self, ty: &Ty) {
         match ty.node {
-            // Like path expressions, the interpretation of path types depends
-            // on whether the path has multiple elements in it or not.
+            // `<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()
+                };
 
-            TyPath(ref path, path_id) => {
-                // This is a path in the type namespace. Walk through scopes
-                // looking for it.
-                let mut result_def = None;
-
-                // First, check to see whether the name is a primitive type.
-                if path.segments.len() == 1 {
-                    let id = path.segments.last().unwrap().identifier;
-
-                    match self.primitive_type_table
-                            .primitive_types
-                            .get(&id.name) {
-
-                        Some(&primitive_type) => {
-                            result_def =
-                                Some((DefPrimTy(primitive_type), LastMod(AllPublic)));
-
-                            if path.segments[0].parameters.has_lifetimes() {
-                                span_err!(self.session, path.span, E0157,
-                                    "lifetime parameters are not allowed on this type");
-                            } else if !path.segments[0].parameters.is_empty() {
-                                span_err!(self.session, path.span, E0153,
-                                    "type parameters are not allowed on this type");
-                            }
-                        }
-                        None => {
-                            // Continue.
-                        }
+                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 None = result_def {
-                    result_def = self.resolve_path(ty.id, path, TypeNS, true);
+                if let Some(DefMod(_)) = resolution.map(|r| r.base_def) {
+                    // A module is not a valid type.
+                    resolution = None;
                 }
 
-                match result_def {
+                // This is a path in the type namespace. Walk through scopes
+                // looking for it.
+                match resolution {
                     Some(def) => {
                         // Write the result into the def map.
                         debug!("(resolving type) writing resolution for `{}` \
                                 (id {}) = {:?}",
-                               self.path_names_to_string(path),
-                               path_id, def);
-                        self.record_def(path_id, def);
+                               self.path_names_to_string(path, 0),
+                               ty.id, def);
+                        self.record_def(ty.id, def);
                     }
                     None => {
-                        let msg = format!("use of undeclared type name `{}`",
-                                          self.path_names_to_string(path));
-                        self.resolve_error(ty.span, &msg[..]);
-                    }
-                }
-            }
+                        // Keep reporting some errors even if they're ignored above.
+                        self.resolve_path(ty.id, path, 0, TypeNS, true);
 
-            TyObjectSum(ref ty, ref bound_vec) => {
-                self.resolve_type(&**ty);
-                self.resolve_type_parameter_bounds(ty.id, bound_vec,
-                                                       TraitBoundingTypeParameter);
-            }
+                        let kind = if maybe_qself.is_some() {
+                            "associated type"
+                        } else {
+                            "type name"
+                        };
 
-            TyQPath(ref qpath) => {
-                self.resolve_type(&*qpath.self_type);
-                self.resolve_trait_reference(ty.id, &*qpath.trait_ref, TraitQPath);
-                for ty in qpath.item_path.parameters.types() {
-                    self.resolve_type(&**ty);
-                }
-                for binding in qpath.item_path.parameters.bindings() {
-                    self.resolve_type(&*binding.ty);
+                        let msg = format!("use of undeclared {} `{}`", kind,
+                                          self.path_names_to_string(path, 0));
+                        self.resolve_error(ty.span, &msg[..]);
+                    }
                 }
             }
-
-            TyPolyTraitRef(ref bounds) => {
-                self.resolve_type_parameter_bounds(
-                    ty.id,
-                    bounds,
-                    TraitObject);
-                visit::walk_ty(self, ty);
-            }
-            _ => {
-                // Just resolve embedded types.
-                visit::walk_ty(self, ty);
-            }
+            _ => {}
         }
+        // Resolve embedded types.
+        visit::walk_ty(self, ty);
     }
 
     fn resolve_pattern(&mut self,
@@ -3683,7 +3331,7 @@ fn resolve_pattern(&mut self,
                     let renamed = mtwt::resolve(ident);
 
                     match self.resolve_bare_identifier_pattern(ident.name, pattern.span) {
-                        FoundStructOrEnumVariant(ref def, lp)
+                        FoundStructOrEnumVariant(def, lp)
                                 if mode == RefutableMode => {
                             debug!("(resolving pattern) resolving `{}` to \
                                     struct or enum variant",
@@ -3693,7 +3341,11 @@ struct or enum variant",
                                 pattern,
                                 binding_mode,
                                 "an enum variant");
-                            self.record_def(pattern.id, (def.clone(), lp));
+                            self.record_def(pattern.id, PathResolution {
+                                base_def: def,
+                                last_private: lp,
+                                depth: 0
+                            });
                         }
                         FoundStructOrEnumVariant(..) => {
                             self.resolve_error(
@@ -3703,7 +3355,7 @@ struct or enum variant",
                                          scope",
                                         token::get_name(renamed)));
                         }
-                        FoundConst(ref def, lp) if mode == RefutableMode => {
+                        FoundConst(def, lp) if mode == RefutableMode => {
                             debug!("(resolving pattern) resolving `{}` to \
                                     constant",
                                    token::get_name(renamed));
@@ -3712,7 +3364,11 @@ struct or enum variant",
                                 pattern,
                                 binding_mode,
                                 "a constant");
-                            self.record_def(pattern.id, (def.clone(), lp));
+                            self.record_def(pattern.id, PathResolution {
+                                base_def: def,
+                                last_private: lp,
+                                depth: 0
+                            });
                         }
                         FoundConst(..) => {
                             self.resolve_error(pattern.span,
@@ -3729,7 +3385,11 @@ struct or enum variant",
                             // will be able to distinguish variants from
                             // locals in patterns.
 
-                            self.record_def(pattern.id, (def, LastMod(AllPublic)));
+                            self.record_def(pattern.id, PathResolution {
+                                base_def: def,
+                                last_private: LastMod(AllPublic),
+                                depth: 0
+                            });
 
                             // Add the binding to the local ribs, if it
                             // doesn't already exist in the bindings list. (We
@@ -3772,50 +3432,34 @@ struct or enum variant",
 
                 PatEnum(ref path, _) => {
                     // This must be an enum variant, struct or const.
-                    match self.resolve_path(pat_id, path, ValueNS, false) {
-                        Some(def @ (DefVariant(..), _)) |
-                        Some(def @ (DefStruct(..), _))  |
-                        Some(def @ (DefConst(..), _)) => {
-                            self.record_def(pattern.id, def);
-                        }
-                        Some((DefStatic(..), _)) => {
-                            self.resolve_error(path.span,
-                                               "static variables cannot be \
-                                                referenced in a pattern, \
-                                                use a `const` instead");
-                        }
-                        Some(_) => {
-                            self.resolve_error(path.span,
-                                &format!("`{}` is not an enum variant, struct or const",
-                                    token::get_ident(
-                                        path.segments.last().unwrap().identifier)));
-                        }
-                        None => {
-                            self.resolve_error(path.span,
-                                &format!("unresolved enum variant, struct or const `{}`",
-                                    token::get_ident(path.segments.last().unwrap().identifier)));
+                    if let Some(path_res) = self.resolve_path(pat_id, path, 0, ValueNS, false) {
+                        match path_res.base_def {
+                            DefVariant(..) | DefStruct(..) | DefConst(..) => {
+                                self.record_def(pattern.id, path_res);
+                            }
+                            DefStatic(..) => {
+                                self.resolve_error(path.span,
+                                                   "static variables cannot be \
+                                                    referenced in a pattern, \
+                                                    use a `const` instead");
+                            }
+                            _ => {
+                                self.resolve_error(path.span,
+                                    &format!("`{}` is not an enum variant, struct or const",
+                                        token::get_ident(
+                                            path.segments.last().unwrap().identifier)));
+                            }
                         }
+                    } else {
+                        self.resolve_error(path.span,
+                            &format!("unresolved enum variant, struct or const `{}`",
+                                token::get_ident(path.segments.last().unwrap().identifier)));
                     }
-
-                    // Check the types in the path pattern.
-                    for ty in path.segments
-                                  .iter()
-                                  .flat_map(|s| s.parameters.types().into_iter()) {
-                        self.resolve_type(&**ty);
-                    }
-                }
-
-                PatLit(ref expr) => {
-                    self.resolve_expr(&**expr);
-                }
-
-                PatRange(ref first_expr, ref last_expr) => {
-                    self.resolve_expr(&**first_expr);
-                    self.resolve_expr(&**last_expr);
+                    visit::walk_path(self, path);
                 }
 
                 PatStruct(ref path, _, _) => {
-                    match self.resolve_path(pat_id, path, TypeNS, false) {
+                    match self.resolve_path(pat_id, path, 0, TypeNS, false) {
                         Some(definition) => {
                             self.record_def(pattern.id, definition);
                         }
@@ -3823,10 +3467,15 @@ struct or enum variant",
                             debug!("(resolving pattern) didn't find struct \
                                     def: {:?}", result);
                             let msg = format!("`{}` does not name a structure",
-                                              self.path_names_to_string(path));
+                                              self.path_names_to_string(path, 0));
                             self.resolve_error(path.span, &msg[..]);
                         }
                     }
+                    visit::walk_path(self, path);
+                }
+
+                PatLit(_) | PatRange(..) => {
+                    visit::walk_pat(self, pattern);
                 }
 
                 _ => {
@@ -3900,75 +3549,51 @@ fn resolve_bare_identifier_pattern(&mut self, name: Name, span: Span)
 
     /// 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
+    /// returned value. See `middle::def::PathResolution` for more info.
     fn resolve_path(&mut self,
                     id: NodeId,
                     path: &Path,
+                    path_depth: usize,
                     namespace: Namespace,
-                    check_ribs: bool) -> Option<(Def, LastPrivate)> {
-        // First, resolve the types and associated type bindings.
-        for ty in path.segments.iter().flat_map(|s| s.parameters.types().into_iter()) {
-            self.resolve_type(&**ty);
-        }
-        for binding in path.segments.iter().flat_map(|s| s.parameters.bindings().into_iter()) {
-            self.resolve_type(&*binding.ty);
-        }
-
-        // A special case for sugared associated type paths `T::A` where `T` is
-        // a type parameter and `A` is an associated type on some bound of `T`.
-        if namespace == TypeNS && path.segments.len() == 2 {
-            match self.resolve_identifier(path.segments[0].identifier,
-                                          TypeNS,
-                                          true,
-                                          path.span) {
-                Some((def, last_private)) => {
-                    match def {
-                        DefTyParam(_, _, did, _) => {
-                            let def = DefAssociatedPath(TyParamProvenance::FromParam(did),
-                                                        path.segments.last()
-                                                            .unwrap().identifier);
-                            return Some((def, last_private));
-                        }
-                        DefSelfTy(nid) => {
-                            let def = DefAssociatedPath(TyParamProvenance::FromSelf(local_def(nid)),
-                                                        path.segments.last()
-                                                            .unwrap().identifier);
-                            return Some((def, last_private));
-                        }
-                        _ => {}
-                    }
-                }
-                _ => {}
-            }
-        }
+                    check_ribs: bool) -> Option<PathResolution> {
+        let span = path.span;
+        let segments = &path.segments[..path.segments.len()-path_depth];
+
+        let mk_res = |(def, lp)| PathResolution {
+            base_def: def,
+            last_private: lp,
+            depth: path_depth
+        };
 
         if path.global {
-            return self.resolve_crate_relative_path(path, namespace);
+            let def = self.resolve_crate_relative_path(span, segments, namespace);
+            return def.map(mk_res);
         }
 
         // Try to find a path to an item in a module.
         let unqualified_def =
-                self.resolve_identifier(path.segments.last().unwrap().identifier,
+                self.resolve_identifier(segments.last().unwrap().identifier,
                                         namespace,
                                         check_ribs,
-                                        path.span);
+                                        span);
 
-        if path.segments.len() > 1 {
-            let def = self.resolve_module_relative_path(path, namespace);
+        if segments.len() > 1 {
+            let def = self.resolve_module_relative_path(span, segments, namespace);
             match (def, unqualified_def) {
                 (Some((ref d, _)), Some((ref ud, _))) if *d == *ud => {
                     self.session
                         .add_lint(lint::builtin::UNUSED_QUALIFICATIONS,
-                                  id,
-                                  path.span,
+                                  id, span,
                                   "unnecessary qualification".to_string());
                 }
                 _ => ()
             }
 
-            return def;
+            def.map(mk_res)
+        } else {
+            unqualified_def.map(mk_res)
         }
-
-        return unqualified_def;
     }
 
     // resolve a single identifier (used as a varref)
@@ -3978,20 +3603,24 @@ fn resolve_identifier(&mut self,
                           check_ribs: bool,
                           span: Span)
                           -> Option<(Def, LastPrivate)> {
+        // First, check to see whether the name is a primitive type.
+        if namespace == TypeNS {
+            if let Some(&prim_ty) = self.primitive_type_table
+                                        .primitive_types
+                                        .get(&identifier.name) {
+                return Some((DefPrimTy(prim_ty), LastMod(AllPublic)));
+            }
+        }
+
         if check_ribs {
-            match self.resolve_identifier_in_local_ribs(identifier,
-                                                        namespace,
-                                                        span) {
-                Some(def) => {
-                    return Some((def, LastMod(AllPublic)));
-                }
-                None => {
-                    // Continue.
-                }
+            if let Some(def) = self.resolve_identifier_in_local_ribs(identifier,
+                                                                     namespace,
+                                                                     span) {
+                return Some((def, LastMod(AllPublic)));
             }
         }
 
-        return self.resolve_item_by_name_in_lexical_scope(identifier.name, namespace);
+        self.resolve_item_by_name_in_lexical_scope(identifier.name, namespace)
     }
 
     // FIXME #4952: Merge me with resolve_name_in_module?
@@ -4070,12 +3699,13 @@ fn resolve_definition_of_name_in_module(&mut self,
 
     // resolve a "module-relative" path, e.g. a::b::c
     fn resolve_module_relative_path(&mut self,
-                                    path: &Path,
+                                    span: Span,
+                                    segments: &[ast::PathSegment],
                                     namespace: Namespace)
                                     -> Option<(Def, LastPrivate)> {
-        let module_path = path.segments.init().iter()
-                                              .map(|ps| ps.identifier.name)
-                                              .collect::<Vec<_>>();
+        let module_path = segments.init().iter()
+                                         .map(|ps| ps.identifier.name)
+                                         .collect::<Vec<_>>();
 
         let containing_module;
         let last_private;
@@ -4083,7 +3713,7 @@ fn resolve_module_relative_path(&mut self,
         match self.resolve_module_path(module,
                                        &module_path[..],
                                        UseLexicalScope,
-                                       path.span,
+                                       span,
                                        PathSearch) {
             Failed(err) => {
                 let (span, msg) = match err {
@@ -4091,7 +3721,7 @@ fn resolve_module_relative_path(&mut self,
                     None => {
                         let msg = format!("Use of undeclared type or module `{}`",
                                           self.names_to_string(&module_path));
-                        (path.span, msg)
+                        (span, msg)
                     }
                 };
 
@@ -4106,7 +3736,7 @@ fn resolve_module_relative_path(&mut self,
             }
         }
 
-        let name = path.segments.last().unwrap().identifier.name;
+        let name = segments.last().unwrap().identifier.name;
         let def = match self.resolve_definition_of_name_in_module(containing_module.clone(),
                                                                   name,
                                                                   namespace) {
@@ -4127,12 +3757,13 @@ fn resolve_module_relative_path(&mut self,
     /// Invariant: This must be called only during main resolution, not during
     /// import resolution.
     fn resolve_crate_relative_path(&mut self,
-                                   path: &Path,
+                                   span: Span,
+                                   segments: &[ast::PathSegment],
                                    namespace: Namespace)
                                        -> Option<(Def, LastPrivate)> {
-        let module_path = path.segments.init().iter()
-                                              .map(|ps| ps.identifier.name)
-                                              .collect::<Vec<_>>();
+        let module_path = segments.init().iter()
+                                         .map(|ps| ps.identifier.name)
+                                         .collect::<Vec<_>>();
 
         let root_module = self.graph_root.get_module();
 
@@ -4141,7 +3772,7 @@ fn resolve_crate_relative_path(&mut self,
         match self.resolve_module_path_from_root(root_module,
                                                  &module_path[..],
                                                  0,
-                                                 path.span,
+                                                 span,
                                                  PathSearch,
                                                  LastMod(AllPublic)) {
             Failed(err) => {
@@ -4150,7 +3781,7 @@ fn resolve_crate_relative_path(&mut self,
                     None => {
                         let msg = format!("Use of undeclared module `::{}`",
                                           self.names_to_string(&module_path[..]));
-                        (path.span, msg)
+                        (span, msg)
                     }
                 };
 
@@ -4169,7 +3800,7 @@ fn resolve_crate_relative_path(&mut self,
             }
         }
 
-        let name = path.segments.last().unwrap().identifier.name;
+        let name = segments.last().unwrap().identifier.name;
         match self.resolve_definition_of_name_in_module(containing_module,
                                                         name,
                                                         namespace) {
@@ -4206,10 +3837,10 @@ fn resolve_identifier_in_local_ribs(&mut self,
                         local: {:?}",
                        token::get_ident(ident),
                        def);
-                return Some(def);
+                Some(def)
             }
             Some(DlField) | Some(DlImpl(_)) | None => {
-                return None;
+                None
             }
         }
     }
@@ -4281,7 +3912,7 @@ fn find_fallback_in_self_type(&mut self, name: Name) -> FallbackSuggestion {
         fn extract_path_and_node_id(t: &Ty, allow: FallbackChecks)
                                                     -> Option<(Path, NodeId, FallbackChecks)> {
             match t.node {
-                TyPath(ref path, node_id) => Some((path.clone(), node_id, allow)),
+                TyPath(None, ref path) => Some((path.clone(), t.id, allow)),
                 TyPtr(ref mut_ty) => extract_path_and_node_id(&*mut_ty.ty, OnlyTraitAndStatics),
                 TyRptr(_, ref mut_ty) => extract_path_and_node_id(&*mut_ty.ty, allow),
                 // This doesn't handle the remaining `Ty` variants as they are not
@@ -4318,6 +3949,26 @@ fn get_module(this: &mut Resolver, span: Span, name_path: &[ast::Name])
             }
         }
 
+        fn is_static_method(this: &Resolver, did: DefId) -> bool {
+            if did.krate == ast::LOCAL_CRATE {
+                let explicit_self = match this.ast_map.get(did.node) {
+                    ast_map::NodeTraitItem(m) => match *m {
+                        ast::RequiredMethod(ref m) => &m.explicit_self,
+                        ast::ProvidedMethod(ref m) => m.pe_explicit_self(),
+                        _ => return false
+                    },
+                    ast_map::NodeImplItem(m) => match *m {
+                        ast::MethodImplItem(ref m) => m.pe_explicit_self(),
+                        _ => return false
+                    },
+                    _ => return false
+                };
+                explicit_self.node == ast::SelfStatic
+            } else {
+                csearch::is_static_method(&this.session.cstore, did)
+            }
+        }
+
         let (path, node_id, allowed) = match self.current_self_type {
             Some(ref ty) => match extract_path_and_node_id(ty, Everything) {
                 Some(x) => x,
@@ -4328,10 +3979,10 @@ fn get_module(this: &mut Resolver, span: Span, name_path: &[ast::Name])
 
         if allowed == Everything {
             // Look for a field with the same name in the current self_type.
-            match self.def_map.borrow().get(&node_id) {
-                 Some(&DefTy(did, _))
-                | Some(&DefStruct(did))
-                | Some(&DefVariant(_, did, _)) => match self.structs.get(&did) {
+            match self.def_map.borrow().get(&node_id).map(|d| d.full_def()) {
+                Some(DefTy(did, _)) |
+                Some(DefStruct(did)) |
+                Some(DefVariant(_, did, _)) => match self.structs.get(&did) {
                     None => {}
                     Some(fields) => {
                         if fields.iter().any(|&field_name| name == field_name) {
@@ -4346,41 +3997,30 @@ fn get_module(this: &mut Resolver, span: Span, name_path: &[ast::Name])
         let name_path = path.segments.iter().map(|seg| seg.identifier.name).collect::<Vec<_>>();
 
         // Look for a method in the current self type's impl module.
-        match get_module(self, path.span, &name_path[..]) {
-            Some(module) => match module.children.borrow().get(&name) {
-                Some(binding) => {
-                    let p_str = self.path_names_to_string(&path);
-                    match binding.def_for_namespace(ValueNS) {
-                        Some(DefStaticMethod(_, provenance)) => {
-                            match provenance {
-                                FromImpl(_) => return StaticMethod(p_str),
-                                FromTrait(_) => unreachable!()
-                            }
-                        }
-                        Some(DefMethod(_, None, _)) if allowed == Everything => return Method,
-                        Some(DefMethod(_, Some(_), _)) => return TraitItem,
-                        _ => ()
+        if let Some(module) = get_module(self, path.span, &name_path) {
+            if let Some(binding) = module.children.borrow().get(&name) {
+                if let Some(DefMethod(did, _)) = binding.def_for_namespace(ValueNS) {
+                    if is_static_method(self, did) {
+                        return StaticMethod(self.path_names_to_string(&path, 0))
+                    }
+                    if self.current_trait_ref.is_some() {
+                        return TraitItem;
+                    } else if allowed == Everything {
+                        return Method;
                     }
                 }
-                None => {}
-            },
-            None => {}
+            }
         }
 
         // Look for a method in the current trait.
-        match self.current_trait_ref {
-            Some((did, ref trait_ref)) => {
-                let path_str = self.path_names_to_string(&trait_ref.path);
-
-                match self.trait_item_map.get(&(name, did)) {
-                    Some(&StaticMethodTraitItemKind) => {
-                        return TraitMethod(path_str)
-                    }
-                    Some(_) => return TraitItem,
-                    None => {}
+        if let Some((trait_did, ref trait_ref)) = self.current_trait_ref {
+            if let Some(&did) = self.trait_item_map.get(&(name, trait_did)) {
+                if is_static_method(self, did) {
+                    return TraitMethod(self.path_names_to_string(&trait_ref.path, 0));
+                } else {
+                    return TraitItem;
                 }
             }
-            None => {}
         }
 
         NoSuggestion
@@ -4430,28 +4070,45 @@ fn resolve_expr(&mut self, expr: &Expr) {
 
         // Next, resolve the node.
         match expr.node {
-            // The interpretation of paths depends on whether the path has
-            // multiple elements in it or not.
-
-            ExprPath(_) | ExprQPath(_) => {
-                let mut path_from_qpath;
-                let path = match expr.node {
-                    ExprPath(ref path) => path,
-                    ExprQPath(ref qpath) => {
-                        self.resolve_type(&*qpath.self_type);
-                        self.resolve_trait_reference(expr.id, &*qpath.trait_ref, TraitQPath);
-                        path_from_qpath = qpath.trait_ref.path.clone();
-                        path_from_qpath.segments.push(qpath.item_path.clone());
-                        &path_from_qpath
-                    }
-                    _ => unreachable!()
+            // `<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;
+                }
+
                 // This is a local path in the value namespace. Walk through
                 // scopes looking for it.
-                match self.resolve_path(expr.id, path, ValueNS, true) {
+                if let Some(path_res) = resolution {
                     // Check if struct variant
-                    Some((DefVariant(_, _, true), _)) => {
-                        let path_name = self.path_names_to_string(path);
+                    if let DefVariant(_, _, true) = path_res.base_def {
+                        let path_name = self.path_names_to_string(path, 0);
                         self.resolve_error(expr.span,
                                 &format!("`{}` is a struct variant name, but \
                                           this expression \
@@ -4462,86 +4119,93 @@ fn resolve_expr(&mut self, expr: &Expr) {
                             &format!("Did you mean to write: \
                                      `{} {{ /* fields */ }}`?",
                                      path_name));
-                    }
-                    Some(def) => {
+                    } else {
                         // Write the result into the def map.
                         debug!("(resolving expr) resolved `{}`",
-                               self.path_names_to_string(path));
+                               self.path_names_to_string(path, 0));
+
+                        // Partial resolutions will need the set of traits in scope,
+                        // 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);
+                            self.trait_map.insert(expr.id, traits);
+                        }
 
-                        self.record_def(expr.id, def);
+                        self.record_def(expr.id, path_res);
                     }
-                    None => {
-                        // Be helpful if the name refers to a struct
-                        // (The pattern matching def_tys where the id is in self.structs
-                        // matches on regular structs while excluding tuple- and enum-like
-                        // structs, which wouldn't result in this error.)
-                        let path_name = self.path_names_to_string(path);
-                        match self.with_no_errors(|this|
-                            this.resolve_path(expr.id, path, TypeNS, false)) {
-                            Some((DefTy(struct_id, _), _))
-                              if self.structs.contains_key(&struct_id) => {
-                                self.resolve_error(expr.span,
-                                        &format!("`{}` is a structure name, but \
-                                                  this expression \
-                                                  uses it like a function name",
-                                                 path_name));
-
-                                self.session.span_help(expr.span,
-                                    &format!("Did you mean to write: \
-                                             `{} {{ /* fields */ }}`?",
-                                             path_name));
-
-                            }
-                            _ => {
-                                let mut method_scope = false;
-                                self.value_ribs.iter().rev().all(|rib| {
-                                    let res = match *rib {
-                                        Rib { bindings: _, kind: MethodRibKind(_, _) } => true,
-                                        Rib { bindings: _, kind: ItemRibKind } => false,
-                                        _ => return true, // Keep advancing
-                                    };
-
-                                    method_scope = res;
-                                    false // Stop advancing
-                                });
+                } else {
+                    // Be helpful if the name refers to a struct
+                    // (The pattern matching def_tys where the id is in self.structs
+                    // matches on regular structs while excluding tuple- and enum-like
+                    // structs, which wouldn't result in this error.)
+                    let path_name = self.path_names_to_string(path, 0);
+                    let type_res = self.with_no_errors(|this| {
+                        this.resolve_path(expr.id, path, 0, TypeNS, false)
+                    });
+                    match type_res.map(|r| r.base_def) {
+                        Some(DefTy(struct_id, _))
+                            if self.structs.contains_key(&struct_id) => {
+                            self.resolve_error(expr.span,
+                                    &format!("`{}` is a structure name, but \
+                                                this expression \
+                                                uses it like a function name",
+                                                path_name));
+
+                            self.session.span_help(expr.span,
+                                &format!("Did you mean to write: \
+                                            `{} {{ /* fields */ }}`?",
+                                            path_name));
 
-                                if method_scope && &token::get_name(self.self_name)[..]
-                                                                   == path_name {
-                                        self.resolve_error(
-                                            expr.span,
-                                            "`self` is not available \
-                                             in a static method. Maybe a \
-                                             `self` argument is missing?");
-                                } else {
-                                    let last_name = path.segments.last().unwrap().identifier.name;
-                                    let mut msg = match self.find_fallback_in_self_type(last_name) {
-                                        NoSuggestion => {
-                                            // limit search to 5 to reduce the number
-                                            // of stupid suggestions
-                                            self.find_best_match_for_name(&path_name, 5)
-                                                                .map_or("".to_string(),
-                                                                        |x| format!("`{}`", x))
-                                        }
-                                        Field =>
-                                            format!("`self.{}`", path_name),
-                                        Method
-                                        | TraitItem =>
-                                            format!("to call `self.{}`", path_name),
-                                        TraitMethod(path_str)
-                                        | StaticMethod(path_str) =>
-                                            format!("to call `{}::{}`", path_str, path_name)
-                                    };
-
-                                    if msg.len() > 0 {
-                                        msg = format!(". Did you mean {}?", msg)
-                                    }
+                        }
+                        _ => {
+                            // Keep reporting some errors even if they're ignored above.
+                            self.resolve_path(expr.id, path, 0, ValueNS, true);
+
+                            let mut method_scope = false;
+                            self.value_ribs.iter().rev().all(|rib| {
+                                method_scope = match rib.kind {
+                                    MethodRibKind => true,
+                                    ItemRibKind | ConstantItemRibKind => false,
+                                    _ => return true, // Keep advancing
+                                };
+                                false // Stop advancing
+                            });
 
+                            if method_scope && &token::get_name(self.self_name)[..]
+                                                                == path_name {
                                     self.resolve_error(
                                         expr.span,
-                                        &format!("unresolved name `{}`{}",
-                                                 path_name,
-                                                 msg));
+                                        "`self` is not available \
+                                         in a static method. Maybe a \
+                                         `self` argument is missing?");
+                            } else {
+                                let last_name = path.segments.last().unwrap().identifier.name;
+                                let mut msg = match self.find_fallback_in_self_type(last_name) {
+                                    NoSuggestion => {
+                                        // limit search to 5 to reduce the number
+                                        // of stupid suggestions
+                                        self.find_best_match_for_name(&path_name, 5)
+                                                            .map_or("".to_string(),
+                                                                    |x| format!("`{}`", x))
+                                    }
+                                    Field => format!("`self.{}`", path_name),
+                                    Method |
+                                    TraitItem =>
+                                        format!("to call `self.{}`", path_name),
+                                    TraitMethod(path_str) |
+                                    StaticMethod(path_str) =>
+                                        format!("to call `{}::{}`", path_str, path_name)
+                                };
+
+                                if msg.len() > 0 {
+                                    msg = format!(". Did you mean {}?", msg)
                                 }
+
+                                self.resolve_error(
+                                    expr.span,
+                                    &format!("unresolved name `{}`{}",
+                                             path_name, msg));
                             }
                         }
                     }
@@ -4550,23 +4214,16 @@ fn resolve_expr(&mut self, expr: &Expr) {
                 visit::walk_expr(self, expr);
             }
 
-            ExprClosure(_, ref fn_decl, ref block) => {
-                self.resolve_function(ClosureRibKind(expr.id),
-                                      Some(&**fn_decl), NoTypeParameters,
-                                      &**block);
-            }
-
             ExprStruct(ref path, _, _) => {
                 // Resolve the path to the structure it goes to. We don't
                 // check to ensure that the path is actually a structure; that
                 // is checked later during typeck.
-                match self.resolve_path(expr.id, path, TypeNS, false) {
+                match self.resolve_path(expr.id, path, 0, TypeNS, false) {
                     Some(definition) => self.record_def(expr.id, definition),
-                    result => {
-                        debug!("(resolving expression) didn't find struct \
-                                def: {:?}", result);
+                    None => {
+                        debug!("(resolving expression) didn't find struct def",);
                         let msg = format!("`{}` does not name a structure",
-                                          self.path_names_to_string(path));
+                                          self.path_names_to_string(path, 0));
                         self.resolve_error(path.span, &msg[..]);
                     }
                 }
@@ -4599,7 +4256,11 @@ fn resolve_expr(&mut self, expr: &Expr) {
                     }
                     Some(DlDef(def @ DefLabel(_))) => {
                         // Since this def is a label, it is never read.
-                        self.record_def(expr.id, (def, LastMod(AllPublic)))
+                        self.record_def(expr.id, PathResolution {
+                            base_def: def,
+                            last_private: LastMod(AllPublic),
+                            depth: 0
+                        })
                     }
                     Some(_) => {
                         self.session.span_bug(expr.span,
@@ -4675,7 +4336,7 @@ fn add_trait_info(found_traits: &mut Vec<DefId>,
                         None => continue
                     };
                     let trait_def_id = match def {
-                        DefaultImpl(trait_def_id) => trait_def_id,
+                        DefTrait(trait_def_id) => trait_def_id,
                         _ => continue,
                     };
                     if self.trait_item_map.contains_key(&(name, trait_def_id)) {
@@ -4691,7 +4352,7 @@ fn add_trait_info(found_traits: &mut Vec<DefId>,
                     Some(target) => target,
                 };
                 let did = match target.bindings.def_for_namespace(TypeNS) {
-                    Some(DefaultImpl(trait_def_id)) => trait_def_id,
+                    Some(DefTrait(trait_def_id)) => trait_def_id,
                     Some(..) | None => continue,
                 };
                 if self.trait_item_map.contains_key(&(name, did)) {
@@ -4717,26 +4378,16 @@ fn add_trait_info(found_traits: &mut Vec<DefId>,
         found_traits
     }
 
-    fn record_def(&mut self, node_id: NodeId, (def, lp): (Def, LastPrivate)) {
-        debug!("(recording def) recording {:?} for {}, last private {:?}",
-                def, node_id, lp);
-        assert!(match lp {LastImport{..} => false, _ => true},
+    fn record_def(&mut self, node_id: NodeId, resolution: PathResolution) {
+        debug!("(recording def) recording {:?} for {}", resolution, node_id);
+        assert!(match resolution.last_private {LastImport{..} => false, _ => true},
                 "Import should only be used for `use` directives");
-        self.last_private.insert(node_id, lp);
 
-        match self.def_map.borrow_mut().entry(node_id) {
-            // Resolve appears to "resolve" the same ID multiple
-            // times, so here is a sanity check it at least comes to
-            // the same conclusion! - nmatsakis
-            Occupied(entry) => if def != *entry.get() {
-                self.session
-                    .bug(&format!("node_id {} resolved first to {:?} and \
-                                  then {:?}",
-                                 node_id,
-                                 *entry.get(),
-                                 def));
-            },
-            Vacant(entry) => { entry.insert(def); },
+        if let Some(prev_res) = self.def_map.borrow_mut().insert(node_id, resolution) {
+            let span = self.ast_map.opt_span(node_id).unwrap_or(codemap::DUMMY_SP);
+            self.session.span_bug(span, &format!("path resolved multiple times \
+                                                  ({:?} before, {:?} now)",
+                                                 prev_res, resolution));
         }
     }
 
@@ -4831,7 +4482,6 @@ pub struct CrateMap {
     pub export_map: ExportMap,
     pub trait_map: TraitMap,
     pub external_exports: ExternalExports,
-    pub last_private_map: LastPrivateMap,
     pub glob_map: Option<GlobMap>
 }
 
@@ -4870,7 +4520,6 @@ pub fn resolve_crate<'a, 'tcx>(session: &'a Session,
         export_map: resolver.export_map,
         trait_map: resolver.trait_map,
         external_exports: resolver.external_exports,
-        last_private_map: resolver.last_private,
         glob_map: if resolver.make_glob_map {
                         Some(resolver.glob_map)
                     } else {
index 9507da2febbdb235f04b87a961eecd8722e06b32..d8a296bf0410cdde29e5c64362037ecc5b009937 100644 (file)
@@ -167,7 +167,12 @@ pub fn run(sess: &session::Session, llmod: ModuleRef,
         llvm::LLVMRustAddAnalysisPasses(tm, pm, llmod);
         llvm::LLVMRustAddPass(pm, "verify\0".as_ptr() as *const _);
 
-        let opt = sess.opts.cg.opt_level.unwrap_or(0) as libc::c_uint;
+        let opt = match sess.opts.optimize {
+            config::No => 0,
+            config::Less => 1,
+            config::Default => 2,
+            config::Aggressive => 3,
+        };
 
         let builder = llvm::LLVMPassManagerBuilderCreate();
         llvm::LLVMPassManagerBuilderSetOptLevel(builder, opt);
index 591450a25956466978a6cb51fb5f0c5509e93870..371b9268fba0de800de32544ce97f95de7f9b707 100644 (file)
@@ -218,7 +218,7 @@ fn lookup_type_ref(&self, ref_id: NodeId) -> Option<DefId> {
             self.sess.bug(&format!("def_map has no key for {} in lookup_type_ref",
                                   ref_id));
         }
-        let def = (*self.analysis.ty_cx.def_map.borrow())[ref_id];
+        let def = self.analysis.ty_cx.def_map.borrow()[ref_id].full_def();
         match def {
             def::DefPrimTy(_) => None,
             _ => Some(def.def_id()),
@@ -231,15 +231,14 @@ fn lookup_def_kind(&self, ref_id: NodeId, span: Span) -> Option<recorder::Row> {
             self.sess.span_bug(span, &format!("def_map has no key for {} in lookup_def_kind",
                                              ref_id));
         }
-        let def = (*def_map)[ref_id];
+        let def = def_map[ref_id].full_def();
         match def {
             def::DefMod(_) |
             def::DefForeignMod(_) => Some(recorder::ModRef),
             def::DefStruct(_) => Some(recorder::StructRef),
             def::DefTy(..) |
             def::DefAssociatedTy(..) |
-            def::DefAssociatedPath(..) |
-            def::DefaultImpl(_) => Some(recorder::TypeRef),
+            def::DefTrait(_) => Some(recorder::TypeRef),
             def::DefStatic(_, _) |
             def::DefConst(_) |
             def::DefLocal(_) |
@@ -250,9 +249,7 @@ fn lookup_def_kind(&self, ref_id: NodeId, span: Span) -> Option<recorder::Row> {
 
             def::DefSelfTy(_) |
             def::DefRegion(_) |
-            def::DefTyParamBinder(_) |
             def::DefLabel(_) |
-            def::DefStaticMethod(..) |
             def::DefTyParam(..) |
             def::DefUse(_) |
             def::DefMethod(..) |
@@ -662,9 +659,9 @@ fn process_impl(&mut self,
         let trait_id = trait_ref.as_ref().and_then(|tr| self.lookup_type_ref(tr.ref_id));
         match typ.node {
             // Common case impl for a struct or something basic.
-            ast::TyPath(ref path, id) => {
+            ast::TyPath(None, ref path) => {
                 let sub_span = self.span.sub_span_for_type_name(path.span);
-                let self_id = self.lookup_type_ref(id).map(|id| {
+                let self_id = self.lookup_type_ref(typ.id).map(|id| {
                     self.fmt.ref_str(recorder::TypeRef,
                                      path.span,
                                      sub_span,
@@ -795,9 +792,9 @@ fn process_path(&mut self,
             self.sess.span_bug(span,
                                &format!("def_map has no key for {} in visit_expr", id));
         }
-        let def = &(*def_map)[id];
+        let def = def_map[id].full_def();
         let sub_span = self.span.span_for_last_ident(span);
-        match *def {
+        match def {
             def::DefUpvar(..) |
             def::DefLocal(..) |
             def::DefStatic(..) |
@@ -817,8 +814,7 @@ fn process_path(&mut self,
                                                       sub_span,
                                                       def_id,
                                                       self.cur_scope),
-            def::DefStaticMethod(declid, provenence) |
-            def::DefMethod(declid, _, provenence) => {
+            def::DefMethod(declid, provenence) => {
                 let sub_span = self.span.sub_span_for_meth_name(span);
                 let defid = if declid.krate == ast::LOCAL_CRATE {
                     let ti = ty::impl_or_trait_item(&self.analysis.ty_cx,
@@ -870,11 +866,18 @@ fn process_path(&mut self,
                                     &format!("Unexpected def kind while looking \
                                               up path in `{}`: `{:?}`",
                                              self.span.snippet(span),
-                                             *def)),
+                                             def)),
         }
         // modules or types in the path prefix
-        match *def {
-            def::DefStaticMethod(..) => self.write_sub_path_trait_truncated(path),
+        match def {
+            def::DefMethod(did, _) => {
+                let ti = ty::impl_or_trait_item(&self.analysis.ty_cx, did);
+                if let ty::MethodTraitItem(m) = ti {
+                    if m.explicit_self == ty::StaticExplicitSelfCategory {
+                        self.write_sub_path_trait_truncated(path);
+                    }
+                }
+            }
             def::DefLocal(_) |
             def::DefStatic(_,_) |
             def::DefConst(..) |
@@ -1001,7 +1004,7 @@ fn process_pat(&mut self, p:&ast::Pat) {
                 self.collected_paths.push((p.id, path.clone(), false, recorder::StructRef));
                 visit::walk_path(self, path);
 
-                let def = self.analysis.ty_cx.def_map.borrow()[p.id];
+                let def = self.analysis.ty_cx.def_map.borrow()[p.id].full_def();
                 let struct_def = match def {
                     def::DefConst(..) => None,
                     def::DefVariant(_, variant_id, _) => Some(variant_id),
@@ -1303,8 +1306,8 @@ fn visit_ty(&mut self, t: &ast::Ty) {
         }
 
         match t.node {
-            ast::TyPath(ref path, id) => {
-                match self.lookup_type_ref(id) {
+            ast::TyPath(_, ref path) => {
+                match self.lookup_type_ref(t.id) {
                     Some(id) => {
                         let sub_span = self.span.sub_span_for_type_name(t.span);
                         self.fmt.ref_str(recorder::TypeRef,
@@ -1334,16 +1337,10 @@ fn visit_expr(&mut self, ex: &ast::Expr) {
                 // Don't need to do anything for function calls,
                 // because just walking the callee path does what we want.
                 visit::walk_expr(self, ex);
-            },
-            ast::ExprPath(ref path) => {
-                self.process_path(ex.id, path.span, path, None);
-                visit::walk_path(self, path);
             }
-            ast::ExprQPath(ref qpath) => {
-                let mut path = qpath.trait_ref.path.clone();
-                path.segments.push(qpath.item_path.clone());
-                self.process_path(ex.id, ex.span, &path, None);
-                visit::walk_qpath(self, ex.span, &**qpath);
+            ast::ExprPath(_, ref path) => {
+                self.process_path(ex.id, path.span, path, None);
+                visit::walk_expr(self, ex);
             }
             ast::ExprStruct(ref path, ref fields, ref base) =>
                 self.process_struct_lit(ex, path, fields, base),
@@ -1459,8 +1456,8 @@ fn visit_arm(&mut self, arm: &ast::Arm) {
                                    &format!("def_map has no key for {} in visit_arm",
                                            id));
             }
-            let def = &(*def_map)[id];
-            match *def {
+            let def = def_map[id].full_def();
+            match def {
                 def::DefLocal(id)  => {
                     let value = if *immut {
                         self.span.snippet(p.span).to_string()
@@ -1483,7 +1480,7 @@ fn visit_arm(&mut self, arm: &ast::Arm) {
                 def::DefStatic(_, _) => {}
                 def::DefConst(..) => {}
                 _ => error!("unexpected definition kind when processing collected paths: {:?}",
-                            *def)
+                            def)
             }
         }
         for &(id, ref path, ref_kind) in &paths_to_process {
index a5bebaa257ca0ca80b192afa37223ab1e6289279..8de046fa6ebb6c8486604be025597ffd6684a976 100644 (file)
@@ -238,6 +238,7 @@ pub fn spans_with_brackets(&self, span: Span, nesting: int, limit: int) -> Vec<S
         let mut toks = self.retokenise_span(span);
         // We keep track of how many brackets we're nested in
         let mut bracket_count = 0;
+        let mut found_ufcs_sep = false;
         loop {
             let ts = toks.real_token();
             if ts.tok == token::Eof {
@@ -254,13 +255,20 @@ pub fn spans_with_brackets(&self, span: Span, nesting: int, limit: int) -> Vec<S
             }
             bracket_count += match ts.tok {
                 token::Lt => 1,
-                token::Gt => -1,
+                token::Gt => {
+                    // Ignore the `>::` in `<Type as Trait>::AssocTy`.
+                    if !found_ufcs_sep && bracket_count == 0 {
+                        found_ufcs_sep = true;
+                        0
+                    } else {
+                        -1
+                    }
+                }
                 token::BinOp(token::Shl) => 2,
                 token::BinOp(token::Shr) => -2,
                 _ => 0
             };
-            if ts.tok.is_ident() &&
-               bracket_count == nesting {
+            if ts.tok.is_ident() && bracket_count == nesting {
                 result.push(self.make_sub_span(span, Some(ts.sp)).unwrap());
             }
         }
index 26e1a981f1bae25de1e722c0783e17af900126a9..48ff4c8332022aac0972c153eade715fbbe7be42 100644 (file)
@@ -598,7 +598,7 @@ fn get_branches<'a, 'p, 'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
             }
             ast::PatIdent(..) | ast::PatEnum(..) | ast::PatStruct(..) => {
                 // This is either an enum variant or a variable binding.
-                let opt_def = tcx.def_map.borrow().get(&cur.id).cloned();
+                let opt_def = tcx.def_map.borrow().get(&cur.id).map(|d| d.full_def());
                 match opt_def {
                     Some(def::DefVariant(enum_id, var_id, _)) => {
                         let variant = ty::enum_variant_with_id(tcx, enum_id, var_id);
@@ -725,14 +725,14 @@ fn any_irrefutable_adt_pat(tcx: &ty::ctxt, m: &[Match], col: uint) -> bool {
         match pat.node {
             ast::PatTup(_) => true,
             ast::PatStruct(..) => {
-                match tcx.def_map.borrow().get(&pat.id) {
-                    Some(&def::DefVariant(..)) => false,
+                match tcx.def_map.borrow().get(&pat.id).map(|d| d.full_def()) {
+                    Some(def::DefVariant(..)) => false,
                     _ => true,
                 }
             }
             ast::PatEnum(..) | ast::PatIdent(_, _, None) => {
-                match tcx.def_map.borrow().get(&pat.id) {
-                    Some(&def::DefStruct(..)) => true,
+                match tcx.def_map.borrow().get(&pat.id).map(|d| d.full_def()) {
+                    Some(def::DefStruct(..)) => true,
                     _ => false
                 }
             }
@@ -1277,20 +1277,20 @@ pub fn trans_match<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
 /// Checks whether the binding in `discr` is assigned to anywhere in the expression `body`
 fn is_discr_reassigned(bcx: Block, discr: &ast::Expr, body: &ast::Expr) -> bool {
     let (vid, field) = match discr.node {
-        ast::ExprPath(_) | ast::ExprQPath(_) => match bcx.def(discr.id) {
+        ast::ExprPath(..) => match bcx.def(discr.id) {
             def::DefLocal(vid) | def::DefUpvar(vid, _) => (vid, None),
             _ => return false
         },
         ast::ExprField(ref base, field) => {
-            let vid = match bcx.tcx().def_map.borrow().get(&base.id) {
-                Some(&def::DefLocal(vid)) | Some(&def::DefUpvar(vid, _)) => vid,
+            let vid = match bcx.tcx().def_map.borrow().get(&base.id).map(|d| d.full_def()) {
+                Some(def::DefLocal(vid)) | Some(def::DefUpvar(vid, _)) => vid,
                 _ => return false
             };
             (vid, Some(mc::NamedField(field.node.name)))
         },
         ast::ExprTupField(ref base, field) => {
-            let vid = match bcx.tcx().def_map.borrow().get(&base.id) {
-                Some(&def::DefLocal(vid)) | Some(&def::DefUpvar(vid, _)) => vid,
+            let vid = match bcx.tcx().def_map.borrow().get(&base.id).map(|d| d.full_def()) {
+                Some(def::DefLocal(vid)) | Some(def::DefUpvar(vid, _)) => vid,
                 _ => return false
             };
             (vid, Some(mc::PositionalField(field.node)))
@@ -1499,6 +1499,7 @@ pub fn store_local<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
     fn create_dummy_locals<'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
                                        pat: &ast::Pat)
                                        -> Block<'blk, 'tcx> {
+        let _icx = push_ctxt("create_dummy_locals");
         // create dummy memory for the variables if we have no
         // value to store into them immediately
         let tcx = bcx.tcx();
@@ -1689,7 +1690,7 @@ fn bind_irrefutable_pat<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
             }
         }
         ast::PatEnum(_, ref sub_pats) => {
-            let opt_def = bcx.tcx().def_map.borrow().get(&pat.id).cloned();
+            let opt_def = bcx.tcx().def_map.borrow().get(&pat.id).map(|d| d.full_def());
             match opt_def {
                 Some(def::DefVariant(enum_id, var_id, _)) => {
                     let repr = adt::represent_node(bcx, pat.id);
index a358a3d89e90c4eedd3e7df3f3a50478768b8c88..4f234fac9a4a0e65dba0040513c2e2d83a08c8fb 100644 (file)
@@ -93,7 +93,7 @@ fn trans<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, expr: &ast::Expr)
 
     // pick out special kinds of expressions that can be called:
     match expr.node {
-        ast::ExprPath(_) | ast::ExprQPath(_) => {
+        ast::ExprPath(..) => {
             return trans_def(bcx, bcx.def(expr.id), expr);
         }
         _ => {}
@@ -165,13 +165,11 @@ fn trans_def<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                 let def_id = inline::maybe_instantiate_inline(bcx.ccx(), did);
                 Callee { bcx: bcx, data: Intrinsic(def_id.node, substs) }
             }
-            def::DefFn(did, _) | def::DefMethod(did, _, def::FromImpl(_)) |
-            def::DefStaticMethod(did, def::FromImpl(_)) => {
+            def::DefFn(did, _) | def::DefMethod(did, def::FromImpl(_)) => {
                 fn_callee(bcx, trans_fn_ref(bcx.ccx(), did, ExprId(ref_expr.id),
                                             bcx.fcx.param_substs).val)
             }
-            def::DefStaticMethod(meth_did, def::FromTrait(trait_did)) |
-            def::DefMethod(meth_did, _, def::FromTrait(trait_did)) => {
+            def::DefMethod(meth_did, def::FromTrait(trait_did)) => {
                 fn_callee(bcx, meth::trans_static_method_callee(bcx.ccx(),
                                                                 meth_did,
                                                                 trait_did,
@@ -207,11 +205,10 @@ fn trans_def<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
             def::DefUpvar(..) => {
                 datum_callee(bcx, ref_expr)
             }
-            def::DefMod(..) | def::DefForeignMod(..) | def::DefaultImpl(..) |
+            def::DefMod(..) | def::DefForeignMod(..) | def::DefTrait(..) |
             def::DefTy(..) | def::DefPrimTy(..) | def::DefAssociatedTy(..) |
-            def::DefUse(..) | def::DefTyParamBinder(..) |
-            def::DefRegion(..) | def::DefLabel(..) | def::DefTyParam(..) |
-            def::DefSelfTy(..) | def::DefAssociatedPath(..) => {
+            def::DefUse(..) | def::DefRegion(..) | def::DefLabel(..) |
+            def::DefTyParam(..) | def::DefSelfTy(..) => {
                 bcx.tcx().sess.span_bug(
                     ref_expr.span,
                     &format!("cannot translate def {:?} \
@@ -737,7 +734,7 @@ pub fn trans_call_inner<'a, 'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>,
             };
             if !is_rust_fn ||
               type_of::return_uses_outptr(ccx, ret_ty) ||
-              common::type_needs_drop(bcx.tcx(), ret_ty) {
+              bcx.fcx.type_needs_drop(ret_ty) {
                 // Push the out-pointer if we use an out-pointer for this
                 // return type, otherwise push "undef".
                 if common::type_is_zero_size(ccx, ret_ty) {
index a3705a67cdc5a4e37f30dbff6bf3e5bdb5b86a3b..ad07f3953ccc5176b8d54a3376617e6016d7a95f 100644 (file)
@@ -386,7 +386,7 @@ fn schedule_drop_mem(&self,
                          cleanup_scope: ScopeId,
                          val: ValueRef,
                          ty: Ty<'tcx>) {
-        if !common::type_needs_drop(self.ccx.tcx(), ty) { return; }
+        if !self.type_needs_drop(ty) { return; }
         let drop = box DropValue {
             is_immediate: false,
             must_unwind: common::type_needs_unwind_cleanup(self.ccx, ty),
@@ -408,7 +408,8 @@ fn schedule_drop_and_zero_mem(&self,
                                   cleanup_scope: ScopeId,
                                   val: ValueRef,
                                   ty: Ty<'tcx>) {
-        if !common::type_needs_drop(self.ccx.tcx(), ty) { return; }
+        if !self.type_needs_drop(ty) { return; }
+
         let drop = box DropValue {
             is_immediate: false,
             must_unwind: common::type_needs_unwind_cleanup(self.ccx, ty),
@@ -432,7 +433,7 @@ fn schedule_drop_immediate(&self,
                                val: ValueRef,
                                ty: Ty<'tcx>) {
 
-        if !common::type_needs_drop(self.ccx.tcx(), ty) { return; }
+        if !self.type_needs_drop(ty) { return; }
         let drop = box DropValue {
             is_immediate: true,
             must_unwind: common::type_needs_unwind_cleanup(self.ccx, ty),
@@ -1007,6 +1008,7 @@ fn trans<'blk>(&self,
                    bcx: Block<'blk, 'tcx>,
                    debug_loc: DebugLoc)
                    -> Block<'blk, 'tcx> {
+        let _icx = base::push_ctxt("<DropValue as Cleanup>::trans");
         let bcx = if self.is_immediate {
             glue::drop_ty_immediate(bcx, self.val, self.ty, debug_loc)
         } else {
index a3ba506fc46a2034b977589d18f3300cb6c89d56..ec7ed2fe89017476a9ed7290c906128365b92a82 100644 (file)
@@ -213,8 +213,43 @@ fn type_needs_unwind_cleanup_<'tcx>(tcx: &ty::ctxt<'tcx>,
     }
 }
 
+/// If `type_needs_drop` returns true, then `ty` is definitely
+/// non-copy and *might* have a destructor attached; if it returns
+/// false, then `ty` definitely has no destructor (i.e. no drop glue).
+///
+/// (Note that this implies that if `ty` has a destructor attached,
+/// then `type_needs_drop` will definitely return `true` for `ty`.)
 pub fn type_needs_drop<'tcx>(cx: &ty::ctxt<'tcx>, ty: Ty<'tcx>) -> bool {
-    ty::type_contents(cx, ty).needs_drop(cx)
+    type_needs_drop_given_env(cx, ty, &ty::empty_parameter_environment(cx))
+}
+
+/// Core implementation of type_needs_drop, potentially making use of
+/// and/or updating caches held in the `param_env`.
+fn type_needs_drop_given_env<'a,'tcx>(cx: &ty::ctxt<'tcx>,
+                                      ty: Ty<'tcx>,
+                                      param_env: &ty::ParameterEnvironment<'a,'tcx>) -> bool {
+    // Issue #22536: We first query type_moves_by_default.  It sees a
+    // normalized version of the type, and therefore will definitely
+    // know whether the type implements Copy (and thus needs no
+    // cleanup/drop/zeroing) ...
+    let implements_copy = !ty::type_moves_by_default(&param_env, DUMMY_SP, ty);
+
+    if implements_copy { return false; }
+
+    // ... (issue #22536 continued) but as an optimization, still use
+    // prior logic of asking if the `needs_drop` bit is set; we need
+    // not zero non-Copy types if they have no destructor.
+
+    // FIXME(#22815): Note that calling `ty::type_contents` is a
+    // conservative heuristic; it may report that `needs_drop` is set
+    // when actual type does not actually have a destructor associated
+    // with it. But since `ty` absolutely did not have the `Copy`
+    // bound attached (see above), it is sound to treat it as having a
+    // destructor (e.g. zero its memory on move).
+
+    let contents = ty::type_contents(cx, ty);
+    debug!("type_needs_drop ty={} contents={:?}", ty.repr(cx), contents);
+    contents.needs_drop(cx)
 }
 
 fn type_is_newtype_immediate<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ty: Ty<'tcx>) -> bool {
@@ -534,6 +569,12 @@ pub fn monomorphize<T>(&self, value: &T) -> T
                                          self.param_substs,
                                          value)
     }
+
+    /// This is the same as `common::type_needs_drop`, except that it
+    /// may use or update caches within this `FunctionContext`.
+    pub fn type_needs_drop(&self, ty: Ty<'tcx>) -> bool {
+        type_needs_drop_given_env(self.ccx.tcx(), ty, &self.param_env)
+    }
 }
 
 // Basic block context.  We create a block context for each basic block
@@ -603,7 +644,7 @@ pub fn expr_to_string(&self, e: &ast::Expr) -> String {
 
     pub fn def(&self, nid: ast::NodeId) -> def::Def {
         match self.tcx().def_map.borrow().get(&nid) {
-            Some(v) => v.clone(),
+            Some(v) => v.full_def(),
             None => {
                 self.tcx().sess.bug(&format!(
                     "no def associated with node id {}", nid));
index 19046d84d6972f5b2ff4df293a9cd3271c801b01..c1d22cc973c240c209b88dce5d1d5c8728c2eb70 100644 (file)
@@ -193,8 +193,8 @@ pub fn get_const_expr_as_global<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
                                           -> ValueRef {
     // Special-case constants to cache a common global for all uses.
     match expr.node {
-        ast::ExprPath(_) => {
-            let def = ccx.tcx().def_map.borrow()[expr.id];
+        ast::ExprPath(..) => {
+            let def = ccx.tcx().def_map.borrow()[expr.id].full_def();
             match def {
                 def::DefConst(def_id) => {
                     if !ccx.tcx().adjustments.borrow().contains_key(&expr.id) {
@@ -359,7 +359,7 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
     };
     unsafe {
         let _icx = push_ctxt("const_expr");
-        return match e.node {
+        match e.node {
           ast::ExprLit(ref lit) => {
               const_lit(cx, e, &**lit)
           }
@@ -379,7 +379,7 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
             let (te2, _) = const_expr(cx, &**e2, param_substs);
             let te2 = base::cast_shift_const_rhs(b, te1, te2);
 
-            return match b.node {
+            match b.node {
               ast::BiAdd   => {
                 if is_float { llvm::LLVMConstFAdd(te1, te2) }
                 else        { llvm::LLVMConstAdd(te1, te2) }
@@ -433,7 +433,7 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
           ast::ExprUnary(u, ref e) => {
             let (te, ty) = const_expr(cx, &**e, param_substs);
             let is_float = ty::type_is_fp(ty);
-            return match u {
+            match u {
               ast::UnUniq | ast::UnDeref => {
                 const_deref(cx, te, ty).0
               }
@@ -514,8 +514,8 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
             if expr::cast_is_noop(basety, ety) {
                 return v;
             }
-            return match (expr::cast_type_kind(cx.tcx(), basety),
-                           expr::cast_type_kind(cx.tcx(), ety)) {
+            match (expr::cast_type_kind(cx.tcx(), basety),
+                   expr::cast_type_kind(cx.tcx(), ety)) {
 
               (expr::cast_integral, expr::cast_integral) => {
                 let s = ty::type_is_signed(basety) as Bool;
@@ -582,15 +582,15 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                       _ => break,
                   }
               }
-              let opt_def = cx.tcx().def_map.borrow().get(&cur.id).cloned();
+              let opt_def = cx.tcx().def_map.borrow().get(&cur.id).map(|d| d.full_def());
               if let Some(def::DefStatic(def_id, _)) = opt_def {
-                  return get_static_val(cx, def_id, ety);
+                  get_static_val(cx, def_id, ety)
+              } else {
+                  // If this isn't the address of a static, then keep going through
+                  // normal constant evaluation.
+                  let (v, _) = const_expr(cx, &**sub, param_substs);
+                  addr_of(cx, v, "ref", e.id)
               }
-
-              // If this isn't the address of a static, then keep going through
-              // normal constant evaluation.
-              let (v, _) = const_expr(cx, &**sub, param_substs);
-              addr_of(cx, v, "ref", e.id)
           }
           ast::ExprAddrOf(ast::MutMutable, ref sub) => {
               let (v, _) = const_expr(cx, &**sub, param_substs);
@@ -663,10 +663,10 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                 C_array(llunitty, &vs[..])
             }
           }
-          ast::ExprPath(_) | ast::ExprQPath(_) => {
-            let def = cx.tcx().def_map.borrow()[e.id];
+          ast::ExprPath(..) => {
+            let def = cx.tcx().def_map.borrow()[e.id].full_def();
             match def {
-                def::DefFn(..) | def::DefStaticMethod(..) | def::DefMethod(..) => {
+                def::DefFn(..) | def::DefMethod(..) => {
                     expr::trans_def_fn_unadjusted(cx, e, def, param_substs).val
                 }
                 def::DefConst(def_id) => {
@@ -701,7 +701,7 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
             }
           }
           ast::ExprCall(ref callee, ref args) => {
-              let opt_def = cx.tcx().def_map.borrow().get(&callee.id).cloned();
+              let opt_def = cx.tcx().def_map.borrow().get(&callee.id).map(|d| d.full_def());
               let arg_vals = map_list(&args[..]);
               match opt_def {
                   Some(def::DefStruct(_)) => {
@@ -740,7 +740,7 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
           }
           _ => cx.sess().span_bug(e.span,
                   "bad constant expression type in consts::const_expr")
-        };
+        }
     }
 }
 
index 5eebe6a4a05fb5e98ca06b3b15793b5692923924..85d0bc0319f308d93998463b3c2c410d5af30e53 100644 (file)
@@ -77,7 +77,7 @@ pub fn trans_stmt_semi<'blk, 'tcx>(cx: Block<'blk, 'tcx>, e: &ast::Expr)
                                    -> Block<'blk, 'tcx> {
     let _icx = push_ctxt("trans_stmt_semi");
     let ty = expr_ty(cx, e);
-    if type_needs_drop(cx.tcx(), ty) {
+    if cx.fcx.type_needs_drop(ty) {
         expr::trans_to_lvalue(cx, e, "stmt").bcx
     } else {
         expr::trans_into(cx, e, expr::Ignore)
@@ -306,11 +306,10 @@ pub fn trans_break_cont<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
     let loop_id = match opt_label {
         None => fcx.top_loop_scope(),
         Some(_) => {
-            match bcx.tcx().def_map.borrow().get(&expr.id) {
-                Some(&def::DefLabel(loop_id)) => loop_id,
-                ref r => {
-                    bcx.tcx().sess.bug(&format!("{:?} in def-map for label",
-                                               r))
+            match bcx.tcx().def_map.borrow().get(&expr.id).map(|d| d.full_def())  {
+                Some(def::DefLabel(loop_id)) => loop_id,
+                r => {
+                    bcx.tcx().sess.bug(&format!("{:?} in def-map for label", r))
                 }
             }
         }
index 8262dbf55ddaefe0ca376064cff207eb648c27d9..6ca71254868f3f62d339852a4276319acf9d7f45 100644 (file)
@@ -311,7 +311,8 @@ fn post_store<'blk, 'tcx>(&self,
                               val: ValueRef,
                               ty: Ty<'tcx>)
                               -> Block<'blk, 'tcx> {
-        if type_needs_drop(bcx.tcx(), ty) {
+        let _icx = push_ctxt("<Lvalue as KindOps>::post_store");
+        if bcx.fcx.type_needs_drop(ty) {
             // cancel cleanup of affine values by zeroing out
             let () = zero_mem(bcx, val, ty);
             bcx
@@ -656,7 +657,7 @@ pub fn appropriate_rvalue_mode<'a>(&self, ccx: &CrateContext<'a, 'tcx>)
     /// scalar-ish (like an int or a pointer) which (1) does not require drop glue and (2) is
     /// naturally passed around by value, and not by reference.
     pub fn to_llscalarish<'blk>(self, bcx: Block<'blk, 'tcx>) -> ValueRef {
-        assert!(!type_needs_drop(bcx.tcx(), self.ty));
+        assert!(!bcx.fcx.type_needs_drop(self.ty));
         assert!(self.appropriate_rvalue_mode(bcx.ccx()) == ByValue);
         if self.kind.is_by_ref() {
             load_ty(bcx, self.val, self.ty)
index 162881f58c74e2a96a4fe18a9d4fb0e3361a1791..d70a904b81189fde012837d6b320799e493eabe5 100644 (file)
@@ -3487,8 +3487,7 @@ fn walk_expr(cx: &CrateContext,
             ast::ExprLit(_)   |
             ast::ExprBreak(_) |
             ast::ExprAgain(_) |
-            ast::ExprPath(_)  |
-            ast::ExprQPath(_) => {}
+            ast::ExprPath(..) => {}
 
             ast::ExprCast(ref sub_exp, _)     |
             ast::ExprAddrOf(_, ref sub_exp)  |
index 9e9ee4537524b81bfc262027c61bb614c45296ad..27f9b9506a58a12e7848f441b98fbda733f22877 100644 (file)
@@ -143,7 +143,7 @@ pub fn trans_into<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
             // it prefers in-place instantiation, likely because it contains
             // `[x; N]` somewhere within.
             match expr.node {
-                ast::ExprPath(_) | ast::ExprQPath(_) => {
+                ast::ExprPath(..) => {
                     match bcx.def(expr.id) {
                         def::DefConst(did) => {
                             let expr = consts::get_const_expr(bcx.ccx(), did, expr);
@@ -629,7 +629,7 @@ fn trans_datum_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
         ast::ExprParen(ref e) => {
             trans(bcx, &**e)
         }
-        ast::ExprPath(_) | ast::ExprQPath(_) => {
+        ast::ExprPath(..) => {
             trans_def(bcx, expr, bcx.def(expr.id))
         }
         ast::ExprField(ref base, ident) => {
@@ -875,7 +875,7 @@ fn trans_def<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
 
     let _icx = push_ctxt("trans_def_lvalue");
     match def {
-        def::DefFn(..) | def::DefStaticMethod(..) | def::DefMethod(..) |
+        def::DefFn(..) | def::DefMethod(..) |
         def::DefStruct(_) | def::DefVariant(..) => {
             let datum = trans_def_fn_unadjusted(bcx.ccx(), ref_expr, def,
                                                 bcx.fcx.param_substs);
@@ -974,7 +974,7 @@ fn trans_rvalue_stmt_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
             let src_datum = unpack_datum!(bcx, trans(bcx, &**src));
             let dst_datum = unpack_datum!(bcx, trans_to_lvalue(bcx, &**dst, "assign"));
 
-            if type_needs_drop(bcx.tcx(), dst_datum.ty) {
+            if bcx.fcx.type_needs_drop(dst_datum.ty) {
                 // If there are destructors involved, make sure we
                 // are copying from an rvalue, since that cannot possible
                 // alias an lvalue. We are concerned about code like:
@@ -1033,7 +1033,7 @@ fn trans_rvalue_dps_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
         ast::ExprParen(ref e) => {
             trans_into(bcx, &**e, dest)
         }
-        ast::ExprPath(_) | ast::ExprQPath(_) => {
+        ast::ExprPath(..) => {
             trans_def_dps_unadjusted(bcx, expr, bcx.def(expr.id), dest)
         }
         ast::ExprIf(ref cond, ref thn, ref els) => {
@@ -1275,12 +1275,10 @@ pub fn trans_def_fn_unadjusted<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
     match def {
         def::DefFn(did, _) |
         def::DefStruct(did) | def::DefVariant(_, did, _) |
-        def::DefStaticMethod(did, def::FromImpl(_)) |
-        def::DefMethod(did, _, def::FromImpl(_)) => {
+        def::DefMethod(did, def::FromImpl(_)) => {
             callee::trans_fn_ref(ccx, did, ExprId(ref_expr.id), param_substs)
         }
-        def::DefStaticMethod(impl_did, def::FromTrait(trait_did)) |
-        def::DefMethod(impl_did, _, def::FromTrait(trait_did)) => {
+        def::DefMethod(impl_did, def::FromTrait(trait_did)) => {
             meth::trans_static_method_callee(ccx, impl_did,
                                              trait_did, ref_expr.id,
                                              param_substs)
@@ -1365,7 +1363,7 @@ pub fn with_field_tys<'tcx, R, F>(tcx: &ty::ctxt<'tcx>,
                         ty.repr(tcx)));
                 }
                 Some(node_id) => {
-                    let def = tcx.def_map.borrow()[node_id].clone();
+                    let def = tcx.def_map.borrow()[node_id].full_def();
                     match def {
                         def::DefVariant(enum_id, variant_id, _) => {
                             let variant_info = ty::enum_variant_with_id(
@@ -1500,7 +1498,7 @@ pub fn trans_adt<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
         assert_eq!(discr, 0);
 
         match ty::expr_kind(bcx.tcx(), &*base.expr) {
-            ty::RvalueDpsExpr | ty::RvalueDatumExpr if !type_needs_drop(bcx.tcx(), ty) => {
+            ty::RvalueDpsExpr | ty::RvalueDatumExpr if !bcx.fcx.type_needs_drop(ty) => {
                 bcx = trans_into(bcx, &*base.expr, SaveIn(addr));
             },
             ty::RvalueStmtExpr => bcx.tcx().sess.bug("unexpected expr kind for struct base expr"),
@@ -2118,7 +2116,7 @@ fn trans_assign_op<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
 
     // Evaluate LHS (destination), which should be an lvalue
     let dst_datum = unpack_datum!(bcx, trans_to_lvalue(bcx, dst, "assign_op"));
-    assert!(!type_needs_drop(bcx.tcx(), dst_datum.ty));
+    assert!(!bcx.fcx.type_needs_drop(dst_datum.ty));
     let dst_ty = dst_datum.ty;
     let dst = load_ty(bcx, dst_datum.val, dst_datum.ty);
 
index c14683aeade058407b940b8a4f61ee856e5f7536..9491c8377a655fdbe10eee9e63cc2200f29092f2 100644 (file)
@@ -99,6 +99,16 @@ pub fn get_drop_glue_type<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
     if !type_is_sized(tcx, t) {
         return t
     }
+
+    // FIXME (#22815): note that type_needs_drop conservatively
+    // approximates in some cases and may say a type expression
+    // requires drop glue when it actually does not.
+    //
+    // (In this case it is not clear whether any harm is done, i.e.
+    // erroneously returning `t` in some cases where we could have
+    // returned `tcx.types.i8` does not appear unsound. The impact on
+    // code quality is unknown at this time.)
+
     if !type_needs_drop(tcx, t) {
         return tcx.types.i8;
     }
@@ -125,7 +135,7 @@ pub fn drop_ty<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
     // NB: v is an *alias* of type t here, not a direct value.
     debug!("drop_ty(t={})", t.repr(bcx.tcx()));
     let _icx = push_ctxt("drop_ty");
-    if type_needs_drop(bcx.tcx(), t) {
+    if bcx.fcx.type_needs_drop(t) {
         let ccx = bcx.ccx();
         let glue = get_drop_glue(ccx, t);
         let glue_type = get_drop_glue_type(ccx, t);
@@ -480,7 +490,7 @@ fn make_drop_glue<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, v0: ValueRef, t: Ty<'tcx>)
         },
         _ => {
             assert!(type_is_sized(bcx.tcx(), t));
-            if type_needs_drop(bcx.tcx(), t) && ty::type_is_structural(t) {
+            if bcx.fcx.type_needs_drop(t) && ty::type_is_structural(t) {
                 iter_structural_ty(bcx,
                                    v0,
                                    t,
index 993c9eae45bf6326f016693dea46bb25dfe043ec..54644c92869cfe0ea83c7c6d780545e1a2dd32d1 100644 (file)
@@ -156,6 +156,8 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
     let ccx = fcx.ccx;
     let tcx = bcx.tcx();
 
+    let _icx = push_ctxt("trans_intrinsic_call");
+
     let ret_ty = match callee_ty.sty {
         ty::ty_bare_fn(_, ref f) => {
             ty::erase_late_bound_regions(bcx.tcx(), &f.sig.output())
@@ -376,7 +378,8 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
         }
         (_, "needs_drop") => {
             let tp_ty = *substs.types.get(FnSpace, 0);
-            C_bool(ccx, type_needs_drop(ccx.tcx(), tp_ty))
+
+            C_bool(ccx, bcx.fcx.type_needs_drop(tp_ty))
         }
         (_, "owns_managed") => {
             let tp_ty = *substs.types.get(FnSpace, 0);
index 3411f12886d2266c959bfecb0f1a5d6975045e6b..4423cd2774446a8df5dea1bb2aa5ebabc706f485 100644 (file)
@@ -454,7 +454,7 @@ fn trans_trait_callee<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
     let self_datum = unpack_datum!(
         bcx, expr::trans(bcx, self_expr));
 
-    let llval = if type_needs_drop(bcx.tcx(), self_datum.ty) {
+    let llval = if bcx.fcx.type_needs_drop(self_datum.ty) {
         let self_datum = unpack_datum!(
             bcx, self_datum.to_rvalue_datum(bcx, "trait_callee"));
 
index d3acd23e6416d8537fbd4e2e356019af8f5a50a5..a5c3923336ae8a99b06f48b121962ea97e87478a 100644 (file)
@@ -53,11 +53,10 @@ pub fn make_drop_glue_unboxed<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
     let not_null = IsNotNull(bcx, vptr);
     with_cond(bcx, not_null, |bcx| {
         let ccx = bcx.ccx();
-        let tcx = bcx.tcx();
         let _icx = push_ctxt("tvec::make_drop_glue_unboxed");
 
         let dataptr = get_dataptr(bcx, vptr);
-        let bcx = if type_needs_drop(tcx, unit_ty) {
+        let bcx = if bcx.fcx.type_needs_drop(unit_ty) {
             let len = get_len(bcx, vptr);
             iter_vec_raw(bcx,
                          dataptr,
index 581279c2c9ca89ee082120a71e87d96aced31f75..d9dc050aebf10d13e251f192e9f9113187b9af79 100644 (file)
 //! case but `&a` in the second.  Basically, defaults that appear inside
 //! an rptr (`&r.T`) use the region `r` that appears in the rptr.
 
-use middle::astconv_util::{ast_ty_to_prim_ty, check_path_args, NO_TPS, NO_REGIONS};
+use middle::astconv_util::{prim_ty_to_ty, check_path_args, NO_TPS, NO_REGIONS};
 use middle::const_eval;
 use middle::def;
 use middle::resolve_lifetime as rl;
+use middle::privacy::{AllPublic, LastMod};
 use middle::subst::{FnSpace, TypeSpace, SelfSpace, Subst, Substs};
 use middle::traits;
 use middle::ty::{self, RegionEscape, ToPolyTraitRef, Ty};
 use rscope::{self, UnelidableRscope, RegionScope, ElidableRscope,
              ObjectLifetimeDefaultRscope, ShiftedRscope, BindingRscope};
-use TypeAndSubsts;
 use util::common::{ErrorReported, FN_OUTPUT_NAME};
 use util::nodemap::DefIdMap;
 use util::ppaux::{self, Repr, UserString};
 
-use std::rc::Rc;
 use std::iter::{repeat, AdditiveIterator};
+use std::rc::Rc;
+use std::slice;
 use syntax::{abi, ast, ast_util};
 use syntax::codemap::Span;
 use syntax::parse::token;
 pub trait AstConv<'tcx> {
     fn tcx<'a>(&'a self) -> &'a ty::ctxt<'tcx>;
 
-    fn get_item_type_scheme(&self, id: ast::DefId) -> ty::TypeScheme<'tcx>;
+    fn get_item_type_scheme(&self, span: Span, id: ast::DefId)
+                            -> Result<ty::TypeScheme<'tcx>, ErrorReported>;
 
-    fn get_trait_def(&self, id: ast::DefId) -> Rc<ty::TraitDef<'tcx>>;
+    fn get_trait_def(&self, span: Span, id: ast::DefId)
+                     -> Result<Rc<ty::TraitDef<'tcx>>, ErrorReported>;
+
+    fn get_type_parameter_bounds(&self, span: Span, def_id: ast::NodeId)
+                                 -> Result<Vec<ty::PolyTraitRef<'tcx>>, ErrorReported>;
 
     /// Return an (optional) substitution to convert bound type parameters that
     /// are in scope into free ones. This function should only return Some
@@ -245,8 +251,10 @@ pub fn opt_ast_region_to_region<'tcx>(
 pub fn ast_path_substs_for_ty<'tcx>(
     this: &AstConv<'tcx>,
     rscope: &RegionScope,
+    span: Span,
+    param_mode: PathParamMode,
     decl_generics: &ty::Generics<'tcx>,
-    path: &ast::Path)
+    item_segment: &ast::PathSegment)
     -> Substs<'tcx>
 {
     let tcx = this.tcx();
@@ -262,27 +270,36 @@ pub fn ast_path_substs_for_ty<'tcx>(
     assert!(decl_generics.regions.all(|d| d.space == TypeSpace));
     assert!(decl_generics.types.all(|d| d.space != FnSpace));
 
-    let (regions, types, assoc_bindings) = match path.segments.last().unwrap().parameters {
+    let (regions, types, assoc_bindings) = match item_segment.parameters {
         ast::AngleBracketedParameters(ref data) => {
-            convert_angle_bracketed_parameters(this, rscope, path.span, decl_generics, data)
+            convert_angle_bracketed_parameters(this, rscope, span, decl_generics, data)
         }
         ast::ParenthesizedParameters(ref data) => {
-            span_err!(tcx.sess, path.span, E0214,
+            span_err!(tcx.sess, span, E0214,
                 "parenthesized parameters may only be used with a trait");
-            convert_parenthesized_parameters(this, rscope, path.span, decl_generics, data)
+            convert_parenthesized_parameters(this, rscope, span, decl_generics, data)
         }
     };
 
     prohibit_projections(this.tcx(), &assoc_bindings);
 
     create_substs_for_ast_path(this,
-                               path.span,
+                               span,
+                               param_mode,
                                decl_generics,
                                None,
                                types,
                                regions)
 }
 
+#[derive(PartialEq, Eq)]
+pub enum PathParamMode {
+    // Any path in a type context.
+    Explicit,
+    // The `module::Type` in `module::Type::method` in an expression.
+    Optional
+}
+
 fn create_region_substs<'tcx>(
     this: &AstConv<'tcx>,
     rscope: &RegionScope,
@@ -330,6 +347,7 @@ fn create_region_substs<'tcx>(
 fn create_substs_for_ast_path<'tcx>(
     this: &AstConv<'tcx>,
     span: Span,
+    param_mode: PathParamMode,
     decl_generics: &ty::Generics<'tcx>,
     self_ty: Option<Ty<'tcx>>,
     types_provided: Vec<Ty<'tcx>>,
@@ -348,13 +366,21 @@ fn create_substs_for_ast_path<'tcx>(
 
     // Convert the type parameters supplied by the user.
     let ty_param_defs = decl_generics.types.get_slice(TypeSpace);
-    let supplied_ty_param_count = types_provided.len();
     let formal_ty_param_count = ty_param_defs.len();
     let required_ty_param_count = ty_param_defs.iter()
                                                .take_while(|x| x.default.is_none())
                                                .count();
 
-    let mut type_substs = types_provided;
+    // Fill with `ty_infer` if no params were specified, as long as
+    // they were optional (e.g. paths inside expressions).
+    let mut type_substs = if param_mode == PathParamMode::Optional &&
+                             types_provided.is_empty() {
+        (0..formal_ty_param_count).map(|_| this.ty_infer(span)).collect()
+    } else {
+        types_provided
+    };
+
+    let supplied_ty_param_count = type_substs.len();
     check_type_argument_count(this.tcx(), span, supplied_ty_param_count,
                               required_ty_param_count, formal_ty_param_count);
 
@@ -414,7 +440,7 @@ fn create_substs_for_ast_path<'tcx>(
         }
     }
 
-    return substs;
+    substs
 }
 
 struct ConvertedBinding<'tcx> {
@@ -574,9 +600,9 @@ pub fn instantiate_poly_trait_ref<'tcx>(
     // lifetimes. Oh well, not there yet.
     let shifted_rscope = ShiftedRscope::new(rscope);
 
-    let trait_ref =
-        instantiate_trait_ref(this, &shifted_rscope, &ast_trait_ref.trait_ref,
-                              self_ty, Some(&mut projections));
+    let trait_ref = instantiate_trait_ref(this, &shifted_rscope,
+                                          &ast_trait_ref.trait_ref,
+                                          None, self_ty, Some(&mut projections));
 
     for projection in projections {
         poly_projections.push(ty::Binder(projection));
@@ -594,26 +620,31 @@ pub fn instantiate_poly_trait_ref<'tcx>(
 pub fn instantiate_trait_ref<'tcx>(
     this: &AstConv<'tcx>,
     rscope: &RegionScope,
-    ast_trait_ref: &ast::TraitRef,
+    trait_ref: &ast::TraitRef,
+    impl_id: Option<ast::NodeId>,
     self_ty: Option<Ty<'tcx>>,
     projections: Option<&mut Vec<ty::ProjectionPredicate<'tcx>>>)
     -> Rc<ty::TraitRef<'tcx>>
 {
-    match ::lookup_def_tcx(this.tcx(), ast_trait_ref.path.span, ast_trait_ref.ref_id) {
-        def::DefaultImpl(trait_def_id) => {
+    let path = &trait_ref.path;
+    match ::lookup_full_def(this.tcx(), path.span, trait_ref.ref_id) {
+        def::DefTrait(trait_def_id) => {
             let trait_ref = ast_path_to_trait_ref(this,
                                                   rscope,
+                                                  path.span,
+                                                  PathParamMode::Explicit,
                                                   trait_def_id,
                                                   self_ty,
-                                                  &ast_trait_ref.path,
+                                                  path.segments.last().unwrap(),
                                                   projections);
-            this.tcx().trait_refs.borrow_mut().insert(ast_trait_ref.ref_id, trait_ref.clone());
+            if let Some(id) = impl_id {
+                this.tcx().impl_trait_refs.borrow_mut().insert(id, trait_ref.clone());
+            }
             trait_ref
         }
         _ => {
-            span_fatal!(this.tcx().sess, ast_trait_ref.path.span, E0245,
-                "`{}` is not a trait",
-                        ast_trait_ref.path.user_string(this.tcx()));
+            span_fatal!(this.tcx().sess, path.span, E0245, "`{}` is not a trait",
+                        path.user_string(this.tcx()));
         }
     }
 }
@@ -621,8 +652,10 @@ pub fn instantiate_trait_ref<'tcx>(
 fn object_path_to_poly_trait_ref<'a,'tcx>(
     this: &AstConv<'tcx>,
     rscope: &RegionScope,
+    span: Span,
+    param_mode: PathParamMode,
     trait_def_id: ast::DefId,
-    path: &ast::Path,
+    trait_segment: &ast::PathSegment,
     mut projections: &mut Vec<ty::PolyProjectionPredicate<'tcx>>)
     -> ty::PolyTraitRef<'tcx>
 {
@@ -633,9 +666,11 @@ fn object_path_to_poly_trait_ref<'a,'tcx>(
     let mut tmp = Vec::new();
     let trait_ref = ty::Binder(ast_path_to_trait_ref(this,
                                                      &shifted_rscope,
+                                                     span,
+                                                     param_mode,
                                                      trait_def_id,
                                                      None,
-                                                     path,
+                                                     trait_segment,
                                                      Some(&mut tmp)));
     projections.extend(tmp.into_iter().map(ty::Binder));
     trait_ref
@@ -644,48 +679,58 @@ fn object_path_to_poly_trait_ref<'a,'tcx>(
 fn ast_path_to_trait_ref<'a,'tcx>(
     this: &AstConv<'tcx>,
     rscope: &RegionScope,
+    span: Span,
+    param_mode: PathParamMode,
     trait_def_id: ast::DefId,
     self_ty: Option<Ty<'tcx>>,
-    path: &ast::Path,
+    trait_segment: &ast::PathSegment,
     mut projections: Option<&mut Vec<ty::ProjectionPredicate<'tcx>>>)
     -> Rc<ty::TraitRef<'tcx>>
 {
-    debug!("ast_path_to_trait_ref {:?}", path);
-    let trait_def = this.get_trait_def(trait_def_id);
+    debug!("ast_path_to_trait_ref {:?}", trait_segment);
+    let trait_def = match this.get_trait_def(span, trait_def_id) {
+        Ok(trait_def) => trait_def,
+        Err(ErrorReported) => {
+            // No convenient way to recover from a cycle here. Just bail. Sorry!
+            this.tcx().sess.abort_if_errors();
+            this.tcx().sess.bug("ErrorReported returned, but no errors reports?")
+        }
+    };
 
-    let (regions, types, assoc_bindings) = match path.segments.last().unwrap().parameters {
+    let (regions, types, assoc_bindings) = match trait_segment.parameters {
         ast::AngleBracketedParameters(ref data) => {
             // For now, require that parenthetical notation be used
             // only with `Fn()` etc.
             if !this.tcx().sess.features.borrow().unboxed_closures && trait_def.paren_sugar {
-                span_err!(this.tcx().sess, path.span, E0215,
+                span_err!(this.tcx().sess, span, E0215,
                                          "angle-bracket notation is not stable when \
                                          used with the `Fn` family of traits, use parentheses");
-                span_help!(this.tcx().sess, path.span,
+                span_help!(this.tcx().sess, span,
                            "add `#![feature(unboxed_closures)]` to \
                             the crate attributes to enable");
             }
 
-            convert_angle_bracketed_parameters(this, rscope, path.span, &trait_def.generics, data)
+            convert_angle_bracketed_parameters(this, rscope, span, &trait_def.generics, data)
         }
         ast::ParenthesizedParameters(ref data) => {
             // For now, require that parenthetical notation be used
             // only with `Fn()` etc.
             if !this.tcx().sess.features.borrow().unboxed_closures && !trait_def.paren_sugar {
-                span_err!(this.tcx().sess, path.span, E0216,
+                span_err!(this.tcx().sess, span, E0216,
                                          "parenthetical notation is only stable when \
                                          used with the `Fn` family of traits");
-                span_help!(this.tcx().sess, path.span,
+                span_help!(this.tcx().sess, span,
                            "add `#![feature(unboxed_closures)]` to \
                             the crate attributes to enable");
             }
 
-            convert_parenthesized_parameters(this, rscope, path.span, &trait_def.generics, data)
+            convert_parenthesized_parameters(this, rscope, span, &trait_def.generics, data)
         }
     };
 
     let substs = create_substs_for_ast_path(this,
-                                            path.span,
+                                            span,
+                                            param_mode,
                                             &trait_def.generics,
                                             self_ty,
                                             types,
@@ -818,78 +863,36 @@ fn ast_type_binding_to_projection_predicate<'tcx>(
     })
 }
 
-pub fn ast_path_to_ty<'tcx>(
+fn ast_path_to_ty<'tcx>(
     this: &AstConv<'tcx>,
     rscope: &RegionScope,
+    span: Span,
+    param_mode: PathParamMode,
     did: ast::DefId,
-    path: &ast::Path)
-    -> TypeAndSubsts<'tcx>
+    item_segment: &ast::PathSegment)
+    -> Ty<'tcx>
 {
     let tcx = this.tcx();
-    let ty::TypeScheme {
-        generics,
-        ty: decl_ty
-    } = this.get_item_type_scheme(did);
-
-    let substs = ast_path_substs_for_ty(this,
-                                        rscope,
-                                        &generics,
-                                        path);
-    let ty = decl_ty.subst(tcx, &substs);
-    TypeAndSubsts { substs: substs, ty: ty }
-}
+    let (generics, decl_ty) = match this.get_item_type_scheme(span, did) {
+        Ok(ty::TypeScheme { generics,  ty: decl_ty }) => {
+            (generics, decl_ty)
+        }
+        Err(ErrorReported) => {
+            return tcx.types.err;
+        }
+    };
 
-/// Converts the given AST type to a built-in type. A "built-in type" is, at
-/// present, either a core numeric type, a string, or `Box`.
-pub fn ast_ty_to_builtin_ty<'tcx>(
-        this: &AstConv<'tcx>,
-        rscope: &RegionScope,
-        ast_ty: &ast::Ty)
-        -> Option<Ty<'tcx>> {
-    match ast_ty_to_prim_ty(this.tcx(), ast_ty) {
-        Some(typ) => return Some(typ),
-        None => {}
-    }
+    let substs = ast_path_substs_for_ty(this, rscope,
+                                        span, param_mode,
+                                        &generics, item_segment);
 
-    match ast_ty.node {
-        ast::TyPath(ref path, id) => {
-            let a_def = match this.tcx().def_map.borrow().get(&id) {
-                None => {
-                    this.tcx()
-                        .sess
-                        .span_bug(ast_ty.span,
-                                  &format!("unbound path {}",
-                                          path.repr(this.tcx())))
-                }
-                Some(&d) => d
-            };
-
-            // FIXME(#12938): This is a hack until we have full support for
-            // DST.
-            match a_def {
-                def::DefTy(did, _) |
-                def::DefStruct(did) if Some(did) == this.tcx().lang_items.owned_box() => {
-                    let ty = ast_path_to_ty(this, rscope, did, path).ty;
-                    match ty.sty {
-                        ty::ty_struct(struct_def_id, ref substs) => {
-                            assert_eq!(struct_def_id, did);
-                            assert_eq!(substs.types.len(TypeSpace), 1);
-                            let referent_ty = *substs.types.get(TypeSpace, 0);
-                            Some(ty::mk_uniq(this.tcx(), referent_ty))
-                        }
-                        _ => {
-                            this.tcx().sess.span_bug(
-                                path.span,
-                                &format!("converting `Box` to `{}`",
-                                        ty.repr(this.tcx())));
-                        }
-                    }
-                }
-                _ => None
-            }
-        }
-        _ => None
+    // FIXME(#12938): This is a hack until we have full support for DST.
+    if Some(did) == this.tcx().lang_items.owned_box() {
+        assert_eq!(substs.types.len(TypeSpace), 1);
+        return ty::mk_uniq(this.tcx(), *substs.types.get(TypeSpace, 0));
     }
+
+    decl_ty.subst(this.tcx(), &substs)
 }
 
 type TraitAndProjections<'tcx> = (ty::PolyTraitRef<'tcx>, Vec<ty::PolyProjectionPredicate<'tcx>>);
@@ -912,14 +915,20 @@ fn ast_ty_to_trait_ref<'tcx>(this: &AstConv<'tcx>,
      */
 
     match ty.node {
-        ast::TyPath(ref path, id) => {
-            match this.tcx().def_map.borrow().get(&id) {
-                Some(&def::DefaultImpl(trait_def_id)) => {
+        ast::TyPath(None, ref path) => {
+            let def = match this.tcx().def_map.borrow().get(&ty.id) {
+                Some(&def::PathResolution { base_def, depth: 0, .. }) => Some(base_def),
+                _ => None
+            };
+            match def {
+                Some(def::DefTrait(trait_def_id)) => {
                     let mut projection_bounds = Vec::new();
                     let trait_ref = object_path_to_poly_trait_ref(this,
                                                                   rscope,
+                                                                  path.span,
+                                                                  PathParamMode::Explicit,
                                                                   trait_def_id,
-                                                                  path,
+                                                                  path.segments.last().unwrap(),
                                                                   &mut projection_bounds);
                     Ok((trait_ref, projection_bounds))
                 }
@@ -982,45 +991,70 @@ fn trait_ref_to_object_type<'tcx>(this: &AstConv<'tcx>,
     result
 }
 
+fn report_ambiguous_associated_type(tcx: &ty::ctxt,
+                                    span: Span,
+                                    type_str: &str,
+                                    trait_str: &str,
+                                    name: &str) {
+    span_err!(tcx.sess, span, E0223,
+              "ambiguous associated type; specify the type using the syntax \
+               `<{} as {}>::{}`",
+              type_str, trait_str, name);
+}
+
 fn associated_path_def_to_ty<'tcx>(this: &AstConv<'tcx>,
-                                   ast_ty: &ast::Ty,
-                                   provenance: def::TyParamProvenance,
-                                   assoc_name: ast::Name)
-                                   -> Ty<'tcx>
+                                   span: Span,
+                                   ty: Ty<'tcx>,
+                                   ty_path_def: def::Def,
+                                   item_segment: &ast::PathSegment)
+                                   -> (Ty<'tcx>, def::Def)
 {
     let tcx = this.tcx();
-    let ty_param_def_id = provenance.def_id();
-
-    let mut suitable_bounds: Vec<_>;
-    let ty_param_name: ast::Name;
-    { // contain scope of refcell:
-        let ty_param_defs = tcx.ty_param_defs.borrow();
-        let ty_param_def = &ty_param_defs[ty_param_def_id.node];
-        ty_param_name = ty_param_def.name;
-
-        // FIXME(#20300) -- search where clauses, not bounds
-        suitable_bounds =
-            traits::transitive_bounds(tcx, &ty_param_def.bounds.trait_bounds)
-            .filter(|b| trait_defines_associated_type_named(this, b.def_id(), assoc_name))
-            .collect();
-    }
+    check_path_args(tcx, slice::ref_slice(item_segment), NO_TPS | NO_REGIONS);
+    let assoc_name = item_segment.identifier.name;
+
+    let is_param = match (&ty.sty, ty_path_def) {
+        (&ty::ty_param(_), def::DefTyParam(..)) |
+        (&ty::ty_param(_), def::DefSelfTy(_)) => true,
+        _ => false
+    };
+
+    let ty_param_node_id = if is_param {
+        ty_path_def.local_node_id()
+    } else {
+        report_ambiguous_associated_type(
+            tcx, span, &ty.user_string(tcx), "Trait", &token::get_name(assoc_name));
+        return (tcx.types.err, ty_path_def);
+    };
+
+    let ty_param_name = tcx.ty_param_defs.borrow()[ty_param_node_id].name;
+
+    // FIXME(#20300) -- search where clauses, not bounds
+    let bounds =
+        this.get_type_parameter_bounds(span, ty_param_node_id)
+            .unwrap_or(Vec::new());
+
+    let mut suitable_bounds: Vec<_> =
+        traits::transitive_bounds(tcx, &bounds)
+        .filter(|b| trait_defines_associated_type_named(this, b.def_id(), assoc_name))
+        .collect();
 
     if suitable_bounds.len() == 0 {
-        span_err!(tcx.sess, ast_ty.span, E0220,
+        span_err!(tcx.sess, span, E0220,
                           "associated type `{}` not found for type parameter `{}`",
                                   token::get_name(assoc_name),
                                   token::get_name(ty_param_name));
-        return this.tcx().types.err;
+        return (this.tcx().types.err, ty_path_def);
     }
 
     if suitable_bounds.len() > 1 {
-        span_err!(tcx.sess, ast_ty.span, E0221,
+        span_err!(tcx.sess, span, E0221,
                           "ambiguous associated type `{}` in bounds of `{}`",
                                   token::get_name(assoc_name),
                                   token::get_name(ty_param_name));
 
         for suitable_bound in &suitable_bounds {
-            span_note!(this.tcx().sess, ast_ty.span,
+            span_note!(this.tcx().sess, span,
                        "associated type `{}` could derive from `{}`",
                        token::get_name(ty_param_name),
                        suitable_bound.user_string(this.tcx()));
@@ -1028,7 +1062,32 @@ fn associated_path_def_to_ty<'tcx>(this: &AstConv<'tcx>,
     }
 
     let suitable_bound = suitable_bounds.pop().unwrap().clone();
-    return this.projected_ty_from_poly_trait_ref(ast_ty.span, suitable_bound, assoc_name);
+    let trait_did = suitable_bound.0.def_id;
+
+    let ty = this.projected_ty_from_poly_trait_ref(span, suitable_bound, assoc_name);
+
+    let item_did = if trait_did.krate == ast::LOCAL_CRATE {
+        // `ty::trait_items` used below requires information generated
+        // by type collection, which may be in progress at this point.
+        match this.tcx().map.expect_item(trait_did.node).node {
+            ast::ItemTrait(_, _, _, ref trait_items) => {
+                trait_items.iter().filter_map(|i| {
+                    if let ast::TypeTraitItem(ref assoc) = *i {
+                        if assoc.ty_param.ident.name == assoc_name {
+                            return Some(ast_util::local_def(assoc.ty_param.id));
+                        }
+                    }
+                    None
+                }).next().expect("missing associated type")
+            }
+            _ => unreachable!()
+        }
+    } else {
+        let trait_items = ty::trait_items(this.tcx(), trait_did);
+        let item = trait_items.iter().find(|i| i.name() == assoc_name);
+        item.expect("missing associated type").def_id()
+    };
+    (ty, def::DefAssociatedTy(trait_did, item_did))
 }
 
 fn trait_defines_associated_type_named(this: &AstConv,
@@ -1043,31 +1102,41 @@ fn trait_defines_associated_type_named(this: &AstConv,
 
 fn qpath_to_ty<'tcx>(this: &AstConv<'tcx>,
                      rscope: &RegionScope,
-                     ast_ty: &ast::Ty, // the TyQPath
-                     qpath: &ast::QPath)
+                     span: Span,
+                     param_mode: PathParamMode,
+                     opt_self_ty: Option<Ty<'tcx>>,
+                     trait_def_id: ast::DefId,
+                     trait_segment: &ast::PathSegment,
+                     item_segment: &ast::PathSegment)
                      -> Ty<'tcx>
 {
-    debug!("qpath_to_ty(ast_ty={})",
-           ast_ty.repr(this.tcx()));
+    let tcx = this.tcx();
 
-    let self_type = ast_ty_to_ty(this, rscope, &*qpath.self_type);
+    check_path_args(tcx, slice::ref_slice(item_segment), NO_TPS | NO_REGIONS);
+
+    let self_ty = if let Some(ty) = opt_self_ty {
+        ty
+    } else {
+        let path_str = ty::item_path_str(tcx, trait_def_id);
+        report_ambiguous_associated_type(
+            tcx, span, "Type", &path_str, &token::get_ident(item_segment.identifier));
+        return tcx.types.err;
+    };
 
-    debug!("qpath_to_ty: self_type={}", self_type.repr(this.tcx()));
+    debug!("qpath_to_ty: self_type={}", self_ty.repr(tcx));
 
-    let trait_ref = instantiate_trait_ref(this,
+    let trait_ref = ast_path_to_trait_ref(this,
                                           rscope,
-                                          &*qpath.trait_ref,
-                                          Some(self_type),
+                                          span,
+                                          param_mode,
+                                          trait_def_id,
+                                          Some(self_ty),
+                                          trait_segment,
                                           None);
 
-    debug!("qpath_to_ty: trait_ref={}", trait_ref.repr(this.tcx()));
+    debug!("qpath_to_ty: trait_ref={}", trait_ref.repr(tcx));
 
-    // `<T as Trait>::U<V>` shouldn't parse right now.
-    assert!(qpath.item_path.parameters.is_empty());
-
-    return this.projected_ty(ast_ty.span,
-                             trait_ref,
-                             qpath.item_path.identifier.name);
+    this.projected_ty(span, trait_ref, item_segment.identifier.name)
 }
 
 /// Convert a type supplied as value for a type argument from AST into our
@@ -1103,6 +1172,96 @@ pub fn ast_ty_arg_to_ty<'tcx>(this: &AstConv<'tcx>,
     }
 }
 
+pub fn finish_resolving_def_to_ty<'tcx>(this: &AstConv<'tcx>,
+                                        rscope: &RegionScope,
+                                        span: Span,
+                                        param_mode: PathParamMode,
+                                        def: &mut def::Def,
+                                        opt_self_ty: Option<Ty<'tcx>>,
+                                        segments: &[ast::PathSegment],
+                                        assoc_segments: &[ast::PathSegment])
+                                        -> Ty<'tcx> {
+    let tcx = this.tcx();
+
+    let base_ty = match *def {
+        def::DefTrait(trait_def_id) => {
+            // N.B. this case overlaps somewhat with
+            // TyObjectSum, see that fn for details
+            let mut projection_bounds = Vec::new();
+
+            let trait_ref = object_path_to_poly_trait_ref(this,
+                                                          rscope,
+                                                          span,
+                                                          param_mode,
+                                                          trait_def_id,
+                                                          segments.last().unwrap(),
+                                                          &mut projection_bounds);
+
+            check_path_args(tcx, segments.init(), NO_TPS | NO_REGIONS);
+            trait_ref_to_object_type(this, rscope, span, trait_ref,
+                                     projection_bounds, &[])
+        }
+        def::DefTy(did, _) | def::DefStruct(did) => {
+            check_path_args(tcx, segments.init(), NO_TPS | NO_REGIONS);
+            ast_path_to_ty(this, rscope, span,
+                           param_mode, did,
+                           segments.last().unwrap())
+        }
+        def::DefTyParam(space, index, _, name) => {
+            check_path_args(tcx, segments, NO_TPS | NO_REGIONS);
+            ty::mk_param(tcx, space, index, name)
+        }
+        def::DefSelfTy(_) => {
+            // n.b.: resolve guarantees that the this type only appears in a
+            // trait, which we rely upon in various places when creating
+            // substs
+            check_path_args(tcx, segments, NO_TPS | NO_REGIONS);
+            ty::mk_self_type(tcx)
+        }
+        def::DefAssociatedTy(trait_did, _) => {
+            check_path_args(tcx, &segments[..segments.len()-2], NO_TPS | NO_REGIONS);
+            qpath_to_ty(this, rscope, span, param_mode,
+                        opt_self_ty, trait_did,
+                        &segments[segments.len()-2],
+                        segments.last().unwrap())
+        }
+        def::DefMod(id) => {
+            // Used as sentinel by callers to indicate the `<T>::A::B::C` form.
+            // FIXME(#22519) This part of the resolution logic should be
+            // avoided entirely for that form, once we stop needed a Def
+            // for `associated_path_def_to_ty`.
+            if segments.is_empty() {
+                opt_self_ty.expect("missing T in <T>::a::b::c")
+            } else {
+                tcx.sess.span_bug(span,
+                                  &format!("found module name used as a type: {}",
+                                           tcx.map.node_to_string(id.node)));
+            }
+        }
+        def::DefPrimTy(prim_ty) => {
+            prim_ty_to_ty(tcx, segments, prim_ty)
+        }
+        _ => {
+            span_fatal!(tcx.sess, span, E0248,
+                        "found value name used as a type: {:?}", *def);
+        }
+    };
+
+    // If any associated type segments remain, attempt to resolve them.
+    let mut ty = base_ty;
+    for segment in assoc_segments {
+        if ty.sty == ty::ty_err {
+            break;
+        }
+        // This is pretty bad (it will fail except for T::A and Self::A).
+        let (a_ty, a_def) = associated_path_def_to_ty(this, span,
+                                                      ty, *def, segment);
+        ty = a_ty;
+        *def = a_def;
+    }
+    ty
+}
+
 /// Parses the programmer's textual representation of a type into our
 /// internal notion of a type.
 pub fn ast_ty_to_ty<'tcx>(this: &AstConv<'tcx>,
@@ -1129,173 +1288,128 @@ pub fn ast_ty_to_ty<'tcx>(this: &AstConv<'tcx>,
     ast_ty_to_ty_cache.insert(ast_ty.id, ty::atttce_unresolved);
     drop(ast_ty_to_ty_cache);
 
-    let typ = ast_ty_to_builtin_ty(this, rscope, ast_ty).unwrap_or_else(|| {
-        match ast_ty.node {
-            ast::TyVec(ref ty) => {
-                ty::mk_vec(tcx, ast_ty_to_ty(this, rscope, &**ty), None)
-            }
-            ast::TyObjectSum(ref ty, ref bounds) => {
-                match ast_ty_to_trait_ref(this, rscope, &**ty, &bounds[..]) {
-                    Ok((trait_ref, projection_bounds)) => {
-                        trait_ref_to_object_type(this,
-                                                 rscope,
-                                                 ast_ty.span,
-                                                 trait_ref,
-                                                 projection_bounds,
-                                                 &bounds[..])
-                    }
-                    Err(ErrorReported) => {
-                        this.tcx().types.err
-                    }
+    let typ = match ast_ty.node {
+        ast::TyVec(ref ty) => {
+            ty::mk_vec(tcx, ast_ty_to_ty(this, rscope, &**ty), None)
+        }
+        ast::TyObjectSum(ref ty, ref bounds) => {
+            match ast_ty_to_trait_ref(this, rscope, &**ty, bounds) {
+                Ok((trait_ref, projection_bounds)) => {
+                    trait_ref_to_object_type(this,
+                                             rscope,
+                                             ast_ty.span,
+                                             trait_ref,
+                                             projection_bounds,
+                                             bounds)
                 }
-            }
-            ast::TyPtr(ref mt) => {
-                ty::mk_ptr(tcx, ty::mt {
-                    ty: ast_ty_to_ty(this, rscope, &*mt.ty),
-                    mutbl: mt.mutbl
-                })
-            }
-            ast::TyRptr(ref region, ref mt) => {
-                let r = opt_ast_region_to_region(this, rscope, ast_ty.span, region);
-                debug!("ty_rptr r={}", r.repr(this.tcx()));
-                let rscope1 =
-                    &ObjectLifetimeDefaultRscope::new(
-                        rscope,
-                        Some(ty::ObjectLifetimeDefault::Specific(r)));
-                let t = ast_ty_to_ty(this, rscope1, &*mt.ty);
-                ty::mk_rptr(tcx, tcx.mk_region(r), ty::mt {ty: t, mutbl: mt.mutbl})
-            }
-            ast::TyTup(ref fields) => {
-                let flds = fields.iter()
-                                 .map(|t| ast_ty_to_ty(this, rscope, &**t))
-                                 .collect();
-                ty::mk_tup(tcx, flds)
-            }
-            ast::TyParen(ref typ) => ast_ty_to_ty(this, rscope, &**typ),
-            ast::TyBareFn(ref bf) => {
-                if bf.decl.variadic && bf.abi != abi::C {
-                    span_err!(tcx.sess, ast_ty.span, E0222,
-                                      "variadic function must have C calling convention");
+                Err(ErrorReported) => {
+                    this.tcx().types.err
                 }
-                let bare_fn = ty_of_bare_fn(this, bf.unsafety, bf.abi, &*bf.decl);
-                ty::mk_bare_fn(tcx, None, tcx.mk_bare_fn(bare_fn))
             }
-            ast::TyPolyTraitRef(ref bounds) => {
-                conv_ty_poly_trait_ref(this, rscope, ast_ty.span, &bounds[..])
+        }
+        ast::TyPtr(ref mt) => {
+            ty::mk_ptr(tcx, ty::mt {
+                ty: ast_ty_to_ty(this, rscope, &*mt.ty),
+                mutbl: mt.mutbl
+            })
+        }
+        ast::TyRptr(ref region, ref mt) => {
+            let r = opt_ast_region_to_region(this, rscope, ast_ty.span, region);
+            debug!("ty_rptr r={}", r.repr(this.tcx()));
+            let rscope1 =
+                &ObjectLifetimeDefaultRscope::new(
+                    rscope,
+                    Some(ty::ObjectLifetimeDefault::Specific(r)));
+            let t = ast_ty_to_ty(this, rscope1, &*mt.ty);
+            ty::mk_rptr(tcx, tcx.mk_region(r), ty::mt {ty: t, mutbl: mt.mutbl})
+        }
+        ast::TyTup(ref fields) => {
+            let flds = fields.iter()
+                             .map(|t| ast_ty_to_ty(this, rscope, &**t))
+                             .collect();
+            ty::mk_tup(tcx, flds)
+        }
+        ast::TyParen(ref typ) => ast_ty_to_ty(this, rscope, &**typ),
+        ast::TyBareFn(ref bf) => {
+            if bf.decl.variadic && bf.abi != abi::C {
+                span_err!(tcx.sess, ast_ty.span, E0222,
+                          "variadic function must have C calling convention");
             }
-            ast::TyPath(ref path, id) => {
-                let a_def = match tcx.def_map.borrow().get(&id) {
-                    None => {
-                        tcx.sess
-                           .span_bug(ast_ty.span,
-                                     &format!("unbound path {}",
-                                             path.repr(tcx)))
-                    }
-                    Some(&d) => d
-                };
-                match a_def {
-                    def::DefaultImpl(trait_def_id) => {
-                        // N.B. this case overlaps somewhat with
-                        // TyObjectSum, see that fn for details
-                        let mut projection_bounds = Vec::new();
-
-                        let trait_ref = object_path_to_poly_trait_ref(this,
-                                                                      rscope,
-                                                                      trait_def_id,
-                                                                      path,
-                                                                      &mut projection_bounds);
-
-                        trait_ref_to_object_type(this, rscope, path.span,
-                                                 trait_ref, projection_bounds, &[])
-                    }
-                    def::DefTy(did, _) | def::DefStruct(did) => {
-                        ast_path_to_ty(this, rscope, did, path).ty
-                    }
-                    def::DefTyParam(space, index, _, name) => {
-                        check_path_args(tcx, path, NO_TPS | NO_REGIONS);
-                        ty::mk_param(tcx, space, index, name)
-                    }
-                    def::DefSelfTy(_) => {
-                        // n.b.: resolve guarantees that the this type only appears in a
-                        // trait, which we rely upon in various places when creating
-                        // substs
-                        check_path_args(tcx, path, NO_TPS | NO_REGIONS);
-                        ty::mk_self_type(tcx)
-                    }
-                    def::DefMod(id) => {
-                        span_fatal!(tcx.sess, ast_ty.span, E0247,
-                            "found module name used as a type: {}",
-                                    tcx.map.node_to_string(id.node));
-                    }
-                    def::DefPrimTy(_) => {
-                        panic!("DefPrimTy arm missed in previous ast_ty_to_prim_ty call");
-                    }
-                    def::DefAssociatedTy(trait_type_id) => {
-                        let path_str = tcx.map.path_to_string(
-                            tcx.map.get_parent(trait_type_id.node));
-                        span_err!(tcx.sess, ast_ty.span, E0223,
-                                          "ambiguous associated \
-                                                   type; specify the type \
-                                                   using the syntax `<Type \
-                                                   as {}>::{}`",
-                                                  path_str,
-                                                  &token::get_ident(
-                                                      path.segments
-                                                          .last()
-                                                          .unwrap()
-                                                          .identifier));
-                        this.tcx().types.err
-                    }
-                    def::DefAssociatedPath(provenance, assoc_ident) => {
-                        associated_path_def_to_ty(this, ast_ty, provenance, assoc_ident.name)
-                    }
-                    _ => {
-                        span_fatal!(tcx.sess, ast_ty.span, E0248,
-                                            "found value name used \
-                                                     as a type: {:?}",
-                                                    a_def);
-                    }
+            let bare_fn = ty_of_bare_fn(this, bf.unsafety, bf.abi, &*bf.decl);
+            ty::mk_bare_fn(tcx, None, tcx.mk_bare_fn(bare_fn))
+        }
+        ast::TyPolyTraitRef(ref bounds) => {
+            conv_ty_poly_trait_ref(this, rscope, ast_ty.span, bounds)
+        }
+        ast::TyPath(ref maybe_qself, ref path) => {
+            let path_res = if let Some(&d) = tcx.def_map.borrow().get(&ast_ty.id) {
+                d
+            } else if let Some(ast::QSelf { position: 0, .. }) = *maybe_qself {
+                // Create some fake resolution that can't possibly be a type.
+                def::PathResolution {
+                    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(ast_ty.span,
+                                  &format!("unbound path {}", ast_ty.repr(tcx)))
+            };
+            let mut def = path_res.base_def;
+            let base_ty_end = path.segments.len() - path_res.depth;
+            let opt_self_ty = maybe_qself.as_ref().map(|qself| {
+                ast_ty_to_ty(this, rscope, &qself.ty)
+            });
+            let ty = finish_resolving_def_to_ty(this, rscope, ast_ty.span,
+                                                PathParamMode::Explicit, &mut def,
+                                                opt_self_ty,
+                                                &path.segments[..base_ty_end],
+                                                &path.segments[base_ty_end..]);
+
+            if path_res.depth != 0 && ty.sty != ty::ty_err {
+                // Write back the new resolution.
+                tcx.def_map.borrow_mut().insert(ast_ty.id, def::PathResolution {
+                    base_def: def,
+                    last_private: path_res.last_private,
+                    depth: 0
+                });
             }
-            ast::TyQPath(ref qpath) => {
-                qpath_to_ty(this, rscope, ast_ty, &**qpath)
-            }
-            ast::TyFixedLengthVec(ref ty, ref e) => {
-                match const_eval::eval_const_expr_partial(tcx, &**e, Some(tcx.types.uint)) {
-                    Ok(ref r) => {
-                        match *r {
-                            const_eval::const_int(i) =>
-                                ty::mk_vec(tcx, ast_ty_to_ty(this, rscope, &**ty),
-                                           Some(i as uint)),
-                            const_eval::const_uint(i) =>
-                                ty::mk_vec(tcx, ast_ty_to_ty(this, rscope, &**ty),
-                                           Some(i as uint)),
-                            _ => {
-                                span_fatal!(tcx.sess, ast_ty.span, E0249,
-                                            "expected constant expr for array length");
-                            }
+
+            ty
+        }
+        ast::TyFixedLengthVec(ref ty, ref e) => {
+            match const_eval::eval_const_expr_partial(tcx, &**e, Some(tcx.types.uint)) {
+                Ok(r) => {
+                    match r {
+                        const_eval::const_int(i) =>
+                            ty::mk_vec(tcx, ast_ty_to_ty(this, rscope, &**ty),
+                                        Some(i as uint)),
+                        const_eval::const_uint(i) =>
+                            ty::mk_vec(tcx, ast_ty_to_ty(this, rscope, &**ty),
+                                        Some(i as uint)),
+                        _ => {
+                            span_fatal!(tcx.sess, ast_ty.span, E0249,
+                                        "expected constant expr for array length");
                         }
                     }
-                    Err(ref r) => {
-                        span_fatal!(tcx.sess, ast_ty.span, E0250,
-                            "expected constant expr for array \
-                                     length: {}",
-                                    *r);
-                    }
                 }
-            }
-            ast::TyTypeof(ref _e) => {
-                tcx.sess.span_bug(ast_ty.span, "typeof is reserved but unimplemented");
-            }
-            ast::TyInfer => {
-                // TyInfer also appears as the type of arguments or return
-                // values in a ExprClosure, or as
-                // the type of local variables. Both of these cases are
-                // handled specially and will not descend into this routine.
-                this.ty_infer(ast_ty.span)
+                Err(r) => {
+                    span_fatal!(tcx.sess, ast_ty.span, E0250,
+                                "expected constant expr for array length: {}", r);
+                }
             }
         }
-    });
+        ast::TyTypeof(ref _e) => {
+            tcx.sess.span_bug(ast_ty.span, "typeof is reserved but unimplemented");
+        }
+        ast::TyInfer => {
+            // TyInfer also appears as the type of arguments or return
+            // values in a ExprClosure, or as
+            // the type of local variables. Both of these cases are
+            // handled specially and will not descend into this routine.
+            this.ty_infer(ast_ty.span)
+        }
+    };
 
     tcx.ast_ty_to_ty_cache.borrow_mut().insert(ast_ty.id, ty::atttce_resolved(typ));
     return typ;
@@ -1803,8 +1917,8 @@ pub fn partition_bounds<'a>(tcx: &ty::ctxt,
     for ast_bound in ast_bounds {
         match *ast_bound {
             ast::TraitTyParamBound(ref b, ast::TraitBoundModifier::None) => {
-                match ::lookup_def_tcx(tcx, b.trait_ref.path.span, b.trait_ref.ref_id) {
-                    def::DefaultImpl(trait_did) => {
+                match ::lookup_full_def(tcx, b.trait_ref.path.span, b.trait_ref.ref_id) {
+                    def::DefTrait(trait_did) => {
                         match trait_def_ids.get(&trait_did) {
                             // Already seen this trait. We forbid
                             // duplicates in the list (for some
index 26ba0fe8ed148230054fa8eba805580dcf1baa15..dd2ab6c6b13ca5d5ee273eb59080b04edc962333 100644 (file)
@@ -103,7 +103,7 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
             demand::eqtype(fcx, pat.span, expected, lhs_ty);
         }
         ast::PatEnum(..) | ast::PatIdent(..) if pat_is_const(&tcx.def_map, pat) => {
-            let const_did = tcx.def_map.borrow()[pat.id].clone().def_id();
+            let const_did = tcx.def_map.borrow()[pat.id].def_id();
             let const_scheme = ty::lookup_item_type(tcx, const_did);
             assert!(const_scheme.generics.is_empty());
             let const_ty = pcx.fcx.instantiate_type_scheme(pat.span,
@@ -433,9 +433,9 @@ pub fn check_pat_struct<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, pat: &'tcx ast::Pat,
     let fcx = pcx.fcx;
     let tcx = pcx.fcx.ccx.tcx;
 
-    let def = tcx.def_map.borrow()[pat.id].clone();
+    let def = tcx.def_map.borrow()[pat.id].full_def();
     let (enum_def_id, variant_def_id) = match def {
-        def::DefaultImpl(_) => {
+        def::DefTrait(_) => {
             let name = pprust::path_to_string(path);
             span_err!(tcx.sess, pat.span, E0168,
                 "use of trait `{}` in a struct pattern", name);
@@ -470,7 +470,7 @@ pub fn check_pat_struct<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, pat: &'tcx ast::Pat,
     };
 
     instantiate_path(pcx.fcx,
-                     path,
+                     &path.segments,
                      ty::lookup_item_type(tcx, enum_def_id),
                      &ty::lookup_predicates(tcx, enum_def_id),
                      None,
@@ -502,7 +502,7 @@ 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()[pat.id].clone();
+    let def = tcx.def_map.borrow()[pat.id].full_def();
     let enum_def = def.variant_def_ids()
         .map_or_else(|| def.def_id(), |(enum_def, _)| enum_def);
 
@@ -517,7 +517,9 @@ pub fn check_pat_enum<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
     } else {
         ctor_scheme
     };
-    instantiate_path(pcx.fcx, path, path_scheme, &ctor_predicates, None, def, pat.span, pat.id);
+    instantiate_path(pcx.fcx, &path.segments,
+                     path_scheme, &ctor_predicates,
+                     None, def, pat.span, pat.id);
 
     let pat_ty = fcx.node_ty(pat.id);
     demand::eqtype(fcx, pat.span, expected, pat_ty);
index 256cd415a33afbf9a07ea87a8042cdd794e8f328..7ef2db2c28d883f59c4f36a2fd34120aad269704 100644 (file)
@@ -14,6 +14,8 @@
 use check::{FnCtxt};
 use check::vtable;
 use check::vtable::select_new_fcx_obligations;
+use middle::def;
+use middle::privacy::{AllPublic, DependsOn, LastPrivate, LastMod};
 use middle::subst;
 use middle::traits;
 use middle::ty::*;
@@ -66,7 +68,8 @@ pub fn exists<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                         call_expr_id: ast::NodeId)
                         -> bool
 {
-    match probe::probe(fcx, span, method_name, self_ty, call_expr_id) {
+    let mode = probe::Mode::MethodCall;
+    match probe::probe(fcx, span, mode, method_name, self_ty, call_expr_id) {
         Ok(..) => true,
         Err(NoMatch(..)) => false,
         Err(Ambiguity(..)) => true,
@@ -103,8 +106,9 @@ pub fn lookup<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
            call_expr.repr(fcx.tcx()),
            self_expr.repr(fcx.tcx()));
 
+    let mode = probe::Mode::MethodCall;
     let self_ty = fcx.infcx().resolve_type_vars_if_possible(&self_ty);
-    let pick = try!(probe::probe(fcx, span, method_name, self_ty, call_expr.id));
+    let pick = try!(probe::probe(fcx, span, mode, method_name, self_ty, call_expr.id));
     Ok(confirm::confirm(fcx, span, self_expr, call_expr, self_ty, pick, supplied_method_types))
 }
 
@@ -301,6 +305,29 @@ pub fn lookup_in_trait_adjusted<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
     Some(callee)
 }
 
+pub fn resolve_ufcs<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
+                              span: Span,
+                              method_name: ast::Name,
+                              self_ty: Ty<'tcx>,
+                              expr_id: ast::NodeId)
+                              -> Result<(def::Def, LastPrivate), MethodError>
+{
+    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 mut lp = LastMod(AllPublic);
+    let provenance = match pick.kind {
+        probe::InherentImplPick(impl_def_id) => {
+            if pick.method_ty.vis != ast::Public {
+                lp = LastMod(DependsOn(def_id));
+            }
+            def::FromImpl(impl_def_id)
+        }
+        _ => def::FromTrait(pick.method_ty.container.id())
+    };
+    Ok((def::DefMethod(def_id, provenance), lp))
+}
+
 
 /// Find method with name `method_name` defined in `trait_def_id` and return it, along with its
 /// index (or `None`, if no such method).
index 1cc4fe37fbdddf59928799b287752c412457d9db..f24da78bc7d3974ea304f5c8f38f9d1f80a237ec 100644 (file)
@@ -37,6 +37,7 @@
 struct ProbeContext<'a, 'tcx:'a> {
     fcx: &'a FnCtxt<'a, 'tcx>,
     span: Span,
+    mode: Mode,
     method_name: ast::Name,
     steps: Rc<Vec<CandidateStep<'tcx>>>,
     opt_simplified_steps: Option<Vec<fast_reject::SimplifiedType>>,
@@ -108,17 +109,30 @@ pub enum PickAdjustment {
     AutoRef(ast::Mutability, Box<PickAdjustment>),
 }
 
+#[derive(PartialEq, Eq, Copy)]
+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`.
+    // No autoderefs are performed, lookup is done based on the type each
+    // implementation is for, and static methods are included.
+    Path
+}
+
 pub fn probe<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                        span: Span,
+                       mode: Mode,
                        method_name: ast::Name,
                        self_ty: Ty<'tcx>,
-                       call_expr_id: ast::NodeId)
+                       scope_expr_id: ast::NodeId)
                        -> PickResult<'tcx>
 {
-    debug!("probe(self_ty={}, method_name={}, call_expr_id={})",
+    debug!("probe(self_ty={}, method_name={}, scope_expr_id={})",
            self_ty.repr(fcx.tcx()),
            method_name,
-           call_expr_id);
+           scope_expr_id);
 
     // FIXME(#18741) -- right now, creating the steps involves evaluating the
     // `*` operator, which registers obligations that then escape into
@@ -127,9 +141,16 @@ pub fn probe<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
     // it ride, although it's really not great, and in fact could I
     // think cause spurious errors. Really though this part should
     // take place in the `fcx.infcx().probe` below.
-    let steps = match create_steps(fcx, span, self_ty) {
-        Some(steps) => steps,
-        None => return Err(MethodError::NoMatch(Vec::new(), Vec::new())),
+    let steps = if mode == Mode::MethodCall {
+        match create_steps(fcx, span, self_ty) {
+            Some(steps) => steps,
+            None => return Err(MethodError::NoMatch(Vec::new(), Vec::new())),
+        }
+    } else {
+        vec![CandidateStep {
+            self_ty: self_ty,
+            adjustment: AutoDeref(0)
+        }]
     };
 
     // Create a list of simplified self types, if we can.
@@ -153,12 +174,15 @@ pub fn probe<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
 
     // this creates one big transaction so that all type variables etc
     // that we create during the probe process are removed later
-    let mut dummy = Some((steps, opt_simplified_steps)); // FIXME(#18101) need once closures
     fcx.infcx().probe(|_| {
-        let (steps, opt_simplified_steps) = dummy.take().unwrap();
-        let mut probe_cx = ProbeContext::new(fcx, span, method_name, steps, opt_simplified_steps);
+        let mut probe_cx = ProbeContext::new(fcx,
+                                             span,
+                                             mode,
+                                             method_name,
+                                             steps,
+                                             opt_simplified_steps);
         probe_cx.assemble_inherent_candidates();
-        try!(probe_cx.assemble_extension_candidates_for_traits_in_scope(call_expr_id));
+        try!(probe_cx.assemble_extension_candidates_for_traits_in_scope(scope_expr_id));
         probe_cx.pick()
     })
 }
@@ -198,6 +222,7 @@ fn create_steps<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
 impl<'a,'tcx> ProbeContext<'a,'tcx> {
     fn new(fcx: &'a FnCtxt<'a,'tcx>,
            span: Span,
+           mode: Mode,
            method_name: ast::Name,
            steps: Vec<CandidateStep<'tcx>>,
            opt_simplified_steps: Option<Vec<fast_reject::SimplifiedType>>)
@@ -206,6 +231,7 @@ fn new(fcx: &'a FnCtxt<'a,'tcx>,
         ProbeContext {
             fcx: fcx,
             span: span,
+            mode: mode,
             method_name: method_name,
             inherent_candidates: Vec::new(),
             extension_candidates: Vec::new(),
@@ -255,6 +281,11 @@ fn assemble_probe(&mut self, self_ty: Ty<'tcx>) {
             ty::ty_closure(did, _, _) => {
                 self.assemble_inherent_impl_candidates_for_type(did);
             }
+            ty::ty_uniq(_) => {
+                if let Some(box_did) = self.tcx().lang_items.owned_box() {
+                    self.assemble_inherent_impl_candidates_for_type(box_did);
+                }
+            }
             ty::ty_param(p) => {
                 self.assemble_inherent_candidates_from_param(self_ty, p);
             }
@@ -292,11 +323,12 @@ fn assemble_inherent_impl_probe(&mut self, impl_def_id: ast::DefId) {
             return self.record_static_candidate(ImplSource(impl_def_id));
         }
 
-        let impl_substs = self.impl_substs(impl_def_id);
+        let (impl_ty, impl_substs) = self.impl_ty_and_substs(impl_def_id);
+        let impl_ty = self.fcx.instantiate_type_scheme(self.span, &impl_substs, &impl_ty);
 
         // Determine the receiver type that the method itself expects.
         let xform_self_ty =
-            self.xform_self_ty(&method, &impl_substs);
+            self.xform_self_ty(&method, impl_ty, &impl_substs);
 
         self.inherent_candidates.push(Candidate {
             xform_self_ty: xform_self_ty,
@@ -330,7 +362,9 @@ fn assemble_inherent_candidates_from_object(&mut self,
                                                           new_trait_ref.def_id,
                                                           method_num);
 
-            let xform_self_ty = this.xform_self_ty(&m, new_trait_ref.substs);
+            let xform_self_ty = this.xform_self_ty(&m,
+                                                   new_trait_ref.self_ty(),
+                                                   new_trait_ref.substs);
 
             this.inherent_candidates.push(Candidate {
                 xform_self_ty: xform_self_ty,
@@ -373,7 +407,9 @@ fn assemble_inherent_candidates_from_param(&mut self,
                 this.erase_late_bound_regions(&poly_trait_ref);
 
             let xform_self_ty =
-                this.xform_self_ty(&m, trait_ref.substs);
+                this.xform_self_ty(&m,
+                                   trait_ref.self_ty(),
+                                   trait_ref.substs);
 
             debug!("found match: trait_ref={} substs={} m={}",
                    trait_ref.repr(this.tcx()),
@@ -540,7 +576,7 @@ fn assemble_extension_candidates_for_trait_impls(&mut self,
                 continue;
             }
 
-            let impl_substs = self.impl_substs(impl_def_id);
+            let (_, impl_substs) = self.impl_ty_and_substs(impl_def_id);
 
             debug!("impl_substs={}", impl_substs.repr(self.tcx()));
 
@@ -553,7 +589,9 @@ 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, impl_trait_ref.substs);
+                self.xform_self_ty(&method,
+                                   impl_trait_ref.self_ty(),
+                                   impl_trait_ref.substs);
 
             debug!("xform_self_ty={}", xform_self_ty.repr(self.tcx()));
 
@@ -630,7 +668,9 @@ fn assemble_closure_candidates(&mut self,
                                                              &trait_def.generics,
                                                              step.self_ty);
 
-            let xform_self_ty = self.xform_self_ty(&method_ty, &substs);
+            let xform_self_ty = self.xform_self_ty(&method_ty,
+                                                   step.self_ty,
+                                                   &substs);
             self.inherent_candidates.push(Candidate {
                 xform_self_ty: xform_self_ty,
                 method_ty: method_ty.clone(),
@@ -684,7 +724,9 @@ 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, bound.substs);
+                    let xform_self_ty = self.xform_self_ty(&method,
+                                                           bound.self_ty(),
+                                                           bound.substs);
 
                     debug!("assemble_projection_candidates: bound={} xform_self_ty={}",
                            bound.repr(self.tcx()),
@@ -714,7 +756,9 @@ 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, bound.substs);
+            let xform_self_ty = self.xform_self_ty(&method_ty,
+                                                   bound.self_ty(),
+                                                   bound.substs);
 
             debug!("assemble_where_clause_candidates: bound={} xform_self_ty={}",
                    bound.repr(self.tcx()),
@@ -1023,7 +1067,9 @@ fn has_applicable_self(&self, method: &ty::Method) -> bool {
         // "fast track" -- check for usage of sugar
         match method.explicit_self {
             ty::StaticExplicitSelfCategory => {
-                // fallthrough
+                if self.mode == Mode::Path {
+                    return true;
+                }
             }
             ty::ByValueExplicitSelfCategory |
             ty::ByReferenceExplicitSelfCategory(..) |
@@ -1047,11 +1093,13 @@ fn record_static_candidate(&mut self, source: CandidateSource) {
 
     fn xform_self_ty(&self,
                      method: &Rc<ty::Method<'tcx>>,
+                     impl_ty: Ty<'tcx>,
                      substs: &subst::Substs<'tcx>)
                      -> Ty<'tcx>
     {
-        debug!("xform_self_ty(self_ty={}, substs={})",
-               method.fty.sig.0.inputs[0].repr(self.tcx()),
+        debug!("xform_self_ty(impl_ty={}, self_ty={}, substs={})",
+               impl_ty.repr(self.tcx()),
+               method.fty.sig.0.inputs.get(0).repr(self.tcx()),
                substs.repr(self.tcx()));
 
         assert!(!substs.has_escaping_regions());
@@ -1063,6 +1111,11 @@ fn xform_self_ty(&self,
         // if there are any.
         assert_eq!(substs.types.len(subst::FnSpace), 0);
         assert_eq!(substs.regions().len(subst::FnSpace), 0);
+
+        if self.mode == Mode::Path {
+            return impl_ty;
+        }
+
         let placeholder;
         let mut substs = substs;
         if
@@ -1094,9 +1147,10 @@ fn xform_self_ty(&self,
         xform_self_ty
     }
 
-    fn impl_substs(&self,
-                   impl_def_id: ast::DefId)
-                   -> subst::Substs<'tcx>
+    /// Get the type of an impl and generate substitutions with placeholders.
+    fn impl_ty_and_substs(&self,
+                          impl_def_id: ast::DefId)
+                          -> (Ty<'tcx>, subst::Substs<'tcx>)
     {
         let impl_pty = ty::lookup_item_type(self.tcx(), impl_def_id);
 
@@ -1108,7 +1162,8 @@ fn impl_substs(&self,
             impl_pty.generics.regions.map(
                 |_| ty::ReStatic); // see erase_late_bound_regions() for an expl of why 'static
 
-        subst::Substs::new(type_vars, region_placeholders)
+        let substs = subst::Substs::new(type_vars, region_placeholders);
+        (impl_pty.ty, substs)
     }
 
     /// Replace late-bound-regions bound by `value` with `'static` using
index 9b1693cba1e99166c294fe33f484b32e1e218062..9832fe1cb6eacd35ebf8ac3723829c28a68a129b 100644 (file)
@@ -33,7 +33,7 @@ pub fn report_error<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                               span: Span,
                               rcvr_ty: Ty<'tcx>,
                               method_name: ast::Name,
-                              callee_expr: &ast::Expr,
+                              rcvr_expr: Option<&ast::Expr>,
                               error: MethodError)
 {
     // avoid suggestions when we don't know what's going on.
@@ -46,16 +46,6 @@ pub fn report_error<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
             let cx = fcx.tcx();
             let method_ustring = method_name.user_string(cx);
 
-            // True if the type is a struct and contains a field with
-            // the same name as the not-found method
-            let is_field = match rcvr_ty.sty {
-                ty::ty_struct(did, _) =>
-                    ty::lookup_struct_fields(cx, did)
-                        .iter()
-                        .any(|f| f.name.user_string(cx) == method_ustring),
-                _ => false
-            };
-
             fcx.type_error_message(
                 span,
                 |actual| {
@@ -68,10 +58,13 @@ pub fn report_error<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                 None);
 
             // If the method has the name of a field, give a help note
-            if is_field {
-                cx.sess.span_note(span,
-                    &format!("use `(s.{0})(...)` if you meant to call the \
-                            function stored in the `{0}` field", method_ustring));
+            if let (&ty::ty_struct(did, _), Some(_)) = (&rcvr_ty.sty, rcvr_expr) {
+                let fields = ty::lookup_struct_fields(cx, did);
+                if fields.iter().any(|f| f.name == method_name) {
+                    cx.sess.span_note(span,
+                        &format!("use `(s.{0})(...)` if you meant to call the \
+                                 function stored in the `{0}` field", method_ustring));
+                }
             }
 
             if static_sources.len() > 0 {
@@ -82,7 +75,8 @@ pub fn report_error<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                 report_candidates(fcx, span, method_name, static_sources);
             }
 
-            suggest_traits_to_import(fcx, span, rcvr_ty, method_name, out_of_scope_traits)
+            suggest_traits_to_import(fcx, span, rcvr_ty, method_name,
+                                     rcvr_expr, out_of_scope_traits)
         }
 
         MethodError::Ambiguity(sources) => {
@@ -93,15 +87,18 @@ pub fn report_error<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
         }
 
         MethodError::ClosureAmbiguity(trait_def_id) => {
-            fcx.sess().span_err(
-                span,
-                &*format!("the `{}` method from the `{}` trait cannot be explicitly \
-                           invoked on this closure as we have not yet inferred what \
-                           kind of closure it is; use overloaded call notation instead \
-                           (e.g., `{}()`)",
-                          method_name.user_string(fcx.tcx()),
-                          ty::item_path_str(fcx.tcx(), trait_def_id),
-                          pprust::expr_to_string(callee_expr)));
+            let msg = format!("the `{}` method from the `{}` trait cannot be explicitly \
+                               invoked on this closure as we have not yet inferred what \
+                               kind of closure it is",
+                               method_name.user_string(fcx.tcx()),
+                               ty::item_path_str(fcx.tcx(), trait_def_id));
+            let msg = if let Some(callee) = rcvr_expr {
+                format!("{}; use overloaded call notation instead (e.g., `{}()`)",
+                        msg, pprust::expr_to_string(callee))
+            } else {
+                msg
+            };
+            fcx.sess().span_err(span, &msg);
         }
     }
 
@@ -156,6 +153,7 @@ fn suggest_traits_to_import<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                                       span: Span,
                                       rcvr_ty: Ty<'tcx>,
                                       method_name: ast::Name,
+                                      rcvr_expr: Option<&ast::Expr>,
                                       valid_out_of_scope_traits: Vec<ast::DefId>)
 {
     let tcx = fcx.tcx();
@@ -184,7 +182,7 @@ fn suggest_traits_to_import<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
         return
     }
 
-    let type_is_local = type_derefs_to_local(fcx, span, rcvr_ty);
+    let type_is_local = type_derefs_to_local(fcx, span, rcvr_ty, rcvr_expr);
 
     // there's no implemented traits, so lets suggest some traits to
     // implement, by finding ones that have the method name, and are
@@ -233,33 +231,39 @@ fn suggest_traits_to_import<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
 /// autoderefs of `rcvr_ty`.
 fn type_derefs_to_local<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                                   span: Span,
-                                  rcvr_ty: Ty<'tcx>) -> bool {
-    check::autoderef(fcx, span, rcvr_ty, None,
-                     check::UnresolvedTypeAction::Ignore, check::NoPreference,
-                     |&: ty, _| {
-        let is_local = match ty.sty {
+                                  rcvr_ty: Ty<'tcx>,
+                                  rcvr_expr: Option<&ast::Expr>) -> bool {
+    fn is_local(ty: Ty) -> bool {
+        match ty.sty {
             ty::ty_enum(did, _) | ty::ty_struct(did, _) => ast_util::is_local(did),
 
             ty::ty_trait(ref tr) => ast_util::is_local(tr.principal_def_id()),
 
             ty::ty_param(_) => true,
 
-            // the user cannot implement traits for unboxed closures, so
-            // there's no point suggesting anything at all, local or not.
-            ty::ty_closure(..) => return Some(false),
-
             // everything else (primitive types etc.) is effectively
             // non-local (there are "edge" cases, e.g. (LocalType,), but
             // the noise from these sort of types is usually just really
             // annoying, rather than any sort of help).
             _ => false
-        };
-        if is_local {
-            Some(true)
+        }
+    }
+
+    // This occurs for UFCS desugaring of `T::method`, where there is no
+    // receiver expression for the method call, and thus no autoderef.
+    if rcvr_expr.is_none() {
+        return is_local(fcx.resolve_type_vars_if_possible(rcvr_ty));
+    }
+
+    check::autoderef(fcx, span, rcvr_ty, None,
+                     check::UnresolvedTypeAction::Ignore, check::NoPreference,
+                     |ty, _| {
+        if is_local(ty) {
+            Some(())
         } else {
             None
         }
-    }).2.unwrap_or(false)
+    }).2.is_some()
 }
 
 #[derive(Copy)]
@@ -330,7 +334,7 @@ fn handle_external_def(traits: &mut AllTraitsVec,
                                cstore: &cstore::CStore,
                                dl: decoder::DefLike) {
             match dl {
-                decoder::DlDef(def::DefaultImpl(did)) => {
+                decoder::DlDef(def::DefTrait(did)) => {
                     traits.push(TraitInfo::new(did));
                 }
                 decoder::DlDef(def::DefMod(did)) => {
index 81e72ef6326c7d47854486d433623c5f18ce2598..fd6ba79ec21bb87955d3c237fa1ca707edc1a5f4 100644 (file)
 use self::IsBinopAssignment::*;
 use self::TupleArgumentsFlag::*;
 
-use astconv::{self, ast_region_to_region, ast_ty_to_ty, AstConv};
+use astconv::{self, ast_region_to_region, ast_ty_to_ty, AstConv, PathParamMode};
 use check::_match::pat_ctxt;
 use fmt_macros::{Parser, Piece, Position};
+use middle::astconv_util::{check_path_args, NO_TPS, NO_REGIONS};
 use middle::{const_eval, def};
 use middle::infer;
 use middle::mem_categorization as mc;
 use middle::mem_categorization::McResult;
 use middle::pat_util::{self, pat_id_map};
+use middle::privacy::{AllPublic, LastMod};
 use middle::region::{self, CodeExtent};
 use middle::subst::{self, Subst, Substs, VecPerParamSpace, ParamSpace, TypeSpace};
 use middle::traits;
 use middle::ty::{FnSig, GenericPredicates, VariantInfo, TypeScheme};
 use middle::ty::{Disr, ParamTy, ParameterEnvironment};
-use middle::ty::{self, HasProjectionTypes, RegionEscape, Ty};
+use middle::ty::{self, HasProjectionTypes, RegionEscape, ToPolyTraitRef, Ty};
 use middle::ty::liberate_late_bound_regions;
 use middle::ty::{MethodCall, MethodCallee, MethodMap, ObjectCastMap};
 use middle::ty_fold::{TypeFolder, TypeFoldable};
 use rscope::RegionScope;
 use session::Session;
-use {CrateCtxt, lookup_def_ccx, require_same_types};
+use {CrateCtxt, lookup_full_def, require_same_types};
 use TypeAndSubsts;
 use lint;
-use util::common::{block_query, indenter, loop_query};
+use util::common::{block_query, ErrorReported, indenter, loop_query};
 use util::ppaux::{self, Repr};
 use util::nodemap::{DefIdMap, FnvHashMap, NodeMap};
 use util::lev_distance::lev_distance;
@@ -1204,18 +1206,48 @@ fn check_cast<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
 impl<'a, 'tcx> AstConv<'tcx> for FnCtxt<'a, 'tcx> {
     fn tcx(&self) -> &ty::ctxt<'tcx> { self.ccx.tcx }
 
-    fn get_item_type_scheme(&self, id: ast::DefId) -> ty::TypeScheme<'tcx> {
-        ty::lookup_item_type(self.tcx(), id)
+    fn get_item_type_scheme(&self, _: Span, id: ast::DefId)
+                            -> Result<ty::TypeScheme<'tcx>, ErrorReported>
+    {
+        Ok(ty::lookup_item_type(self.tcx(), id))
     }
 
-    fn get_trait_def(&self, id: ast::DefId) -> Rc<ty::TraitDef<'tcx>> {
-        ty::lookup_trait_def(self.tcx(), id)
+    fn get_trait_def(&self, _: Span, id: ast::DefId)
+                     -> Result<Rc<ty::TraitDef<'tcx>>, ErrorReported>
+    {
+        Ok(ty::lookup_trait_def(self.tcx(), id))
     }
 
     fn get_free_substs(&self) -> Option<&Substs<'tcx>> {
         Some(&self.inh.param_env.free_substs)
     }
 
+    fn get_type_parameter_bounds(&self,
+                                 _: Span,
+                                 node_id: ast::NodeId)
+                                 -> Result<Vec<ty::PolyTraitRef<'tcx>>, ErrorReported>
+    {
+        let def = self.tcx().type_parameter_def(node_id);
+        let r = self.inh.param_env.caller_bounds
+                                  .iter()
+                                  .filter_map(|predicate| {
+                                      match *predicate {
+                                          ty::Predicate::Trait(ref data) => {
+                                              if data.0.self_ty().is_param(def.space, def.index) {
+                                                  Some(data.to_poly_trait_ref())
+                                              } else {
+                                                  None
+                                              }
+                                          }
+                                          _ => {
+                                              None
+                                          }
+                                      }
+                                  })
+                                  .collect();
+        Ok(r)
+    }
+
     fn ty_infer(&self, _span: Span) -> Ty<'tcx> {
         self.infcx().next_ty_var()
     }
@@ -1598,23 +1630,11 @@ fn instantiate_struct_literal_ty(&self,
         let ty::TypeScheme { generics, ty: decl_ty } =
             ty::lookup_item_type(tcx, did);
 
-        let wants_params =
-            generics.has_type_params(TypeSpace) || generics.has_region_params(TypeSpace);
-
-        let needs_defaults =
-            wants_params &&
-            path.segments.iter().all(|s| s.parameters.is_empty());
-
-        let substs = if needs_defaults {
-            let tps =
-                self.infcx().next_ty_vars(generics.types.len(TypeSpace));
-            let rps =
-                self.infcx().region_vars_for_defs(path.span,
-                                                  generics.regions.get_slice(TypeSpace));
-            Substs::new_type(tps, rps)
-        } else {
-            astconv::ast_path_substs_for_ty(self, self, &generics, path)
-        };
+        let substs = astconv::ast_path_substs_for_ty(self, self,
+                                                     path.span,
+                                                     PathParamMode::Optional,
+                                                     &generics,
+                                                     path.segments.last().unwrap());
 
         let ty = self.instantiate_type_scheme(path.span, &substs, &decl_ty);
 
@@ -2698,7 +2718,7 @@ fn check_method_call<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
             }
             Err(error) => {
                 method::report_error(fcx, method_name.span, expr_t,
-                                     method_name.node.name, rcvr, error);
+                                     method_name.node.name, Some(rcvr), error);
                 fcx.write_error(expr.id);
                 fcx.tcx().types.err
             }
@@ -3408,10 +3428,10 @@ fn check_struct_fields_on_error<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
 
           let mut checked = false;
           opt_place.as_ref().map(|place| match place.node {
-              ast::ExprPath(ref path) => {
+              ast::ExprPath(None, ref path) => {
                   // FIXME(pcwalton): For now we hardcode the two permissible
                   // places: the exchange heap and the managed heap.
-                  let definition = lookup_def(fcx, path.span, place.id);
+                  let definition = lookup_full_def(tcx, path.span, place.id);
                   let def_id = definition.def_id();
                   let referent_ty = fcx.expr_ty(&**subexpr);
                   if tcx.lang_items.exchange_heap() == Some(def_id) {
@@ -3601,26 +3621,65 @@ fn check_struct_fields_on_error<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
         };
         fcx.write_ty(id, oprnd_t);
       }
-      ast::ExprPath(ref path) => {
-          let defn = lookup_def(fcx, path.span, id);
-          let (scheme, predicates) = type_scheme_and_predicates_for_def(fcx, expr.span, defn);
-          instantiate_path(fcx, path, scheme, &predicates, None, defn, expr.span, expr.id);
+      ast::ExprPath(ref maybe_qself, ref path) => {
+          let opt_self_ty = maybe_qself.as_ref().map(|qself| {
+              fcx.to_ty(&qself.ty)
+          });
 
-          // We always require that the type provided as the value for
-          // a type parameter outlives the moment of instantiation.
-          constrain_path_type_parameters(fcx, expr);
-      }
-      ast::ExprQPath(ref qpath) => {
-          // Require explicit type params for the trait.
-          let self_ty = fcx.to_ty(&*qpath.self_type);
-          astconv::instantiate_trait_ref(fcx, fcx, &*qpath.trait_ref, Some(self_ty), None);
-
-          let defn = lookup_def(fcx, expr.span, id);
-          let (scheme, predicates) = type_scheme_and_predicates_for_def(fcx, expr.span, defn);
-          let mut path = qpath.trait_ref.path.clone();
-          path.segments.push(qpath.item_path.clone());
-          instantiate_path(fcx, &path, scheme, &predicates, Some(self_ty),
-                           defn, expr.span, expr.id);
+          let path_res = if let Some(&d) = tcx.def_map.borrow().get(&id) {
+              d
+          } else if let Some(ast::QSelf { position: 0, .. }) = *maybe_qself {
+                // Create some fake resolution that can't possibly be a type.
+                def::PathResolution {
+                    base_def: def::DefMod(local_def(ast::CRATE_NODE_ID)),
+                    last_private: LastMod(AllPublic),
+                    depth: path.segments.len()
+                }
+            } else {
+              tcx.sess.span_bug(expr.span,
+                                &format!("unbound path {}", expr.repr(tcx)))
+          };
+
+          let mut def = path_res.base_def;
+          if path_res.depth == 0 {
+              let (scheme, predicates) =
+                  type_scheme_and_predicates_for_def(fcx, expr.span, def);
+              instantiate_path(fcx, &path.segments,
+                               scheme, &predicates,
+                               opt_self_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,
+                                                           &mut 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
           // a type parameter outlives the moment of instantiation.
@@ -3855,14 +3914,14 @@ fn check_struct_fields_on_error<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
       }
       ast::ExprStruct(ref path, ref fields, ref base_expr) => {
         // Resolve the path.
-        let def = tcx.def_map.borrow().get(&id).cloned();
+        let def = lookup_full_def(tcx, path.span, id);
         let struct_id = match def {
-            Some(def::DefVariant(enum_id, variant_id, true)) => {
+            def::DefVariant(enum_id, variant_id, true) => {
                 check_struct_enum_variant(fcx, id, expr.span, enum_id,
                                           variant_id, &fields[..]);
                 enum_id
             }
-            Some(def::DefaultImpl(def_id)) => {
+            def::DefTrait(def_id) => {
                 span_err!(tcx.sess, path.span, E0159,
                     "use of trait `{}` as a struct constructor",
                     pprust::path_to_string(path));
@@ -3872,7 +3931,7 @@ fn check_struct_fields_on_error<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
                                              base_expr);
                 def_id
             },
-            Some(def) => {
+            def => {
                 // Verify that this was actually a struct.
                 let typ = ty::lookup_item_type(fcx.ccx.tcx, def.def_id());
                 match typ.ty.sty {
@@ -3897,10 +3956,6 @@ fn check_struct_fields_on_error<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
 
                 def.def_id()
             }
-            _ => {
-                tcx.sess.span_bug(path.span,
-                                  "structure constructor wasn't resolved")
-            }
         };
 
         // Turn the path into a type and verify that that type unifies with
@@ -4614,10 +4669,6 @@ fn do_check<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
     check_instantiable(ccx.tcx, sp, id);
 }
 
-pub fn lookup_def(fcx: &FnCtxt, sp: Span, id: ast::NodeId) -> def::Def {
-    lookup_def_ccx(fcx.ccx, sp, id)
-}
-
 // Returns the type parameter count and the type for the given definition.
 fn type_scheme_and_predicates_for_def<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                                                 sp: Span,
@@ -4629,22 +4680,20 @@ fn type_scheme_and_predicates_for_def<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
             (ty::TypeScheme { generics: ty::Generics::empty(), ty: typ },
              ty::GenericPredicates::empty())
         }
-        def::DefFn(id, _) | def::DefStaticMethod(id, _) | def::DefMethod(id, _, _) |
+        def::DefFn(id, _) | def::DefMethod(id, _) |
         def::DefStatic(id, _) | def::DefVariant(_, id, _) |
         def::DefStruct(id) | def::DefConst(id) => {
             (ty::lookup_item_type(fcx.tcx(), id), ty::lookup_predicates(fcx.tcx(), id))
         }
-        def::DefaultImpl(_) |
+        def::DefTrait(_) |
         def::DefTy(..) |
         def::DefAssociatedTy(..) |
-        def::DefAssociatedPath(..) |
         def::DefPrimTy(_) |
         def::DefTyParam(..) |
         def::DefMod(..) |
         def::DefForeignMod(..) |
         def::DefUse(..) |
         def::DefRegion(..) |
-        def::DefTyParamBinder(..) |
         def::DefLabel(..) |
         def::DefSelfTy(..) => {
             fcx.ccx.tcx.sess.span_bug(sp, &format!("expected value, found {:?}", defn));
@@ -4655,15 +4704,15 @@ fn type_scheme_and_predicates_for_def<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
 // Instantiates the given path, which must refer to an item with the given
 // number of type parameters and type.
 pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
-                                  path: &ast::Path,
+                                  segments: &[ast::PathSegment],
                                   type_scheme: TypeScheme<'tcx>,
                                   type_predicates: &ty::GenericPredicates<'tcx>,
                                   opt_self_ty: Option<Ty<'tcx>>,
                                   def: def::Def,
                                   span: Span,
                                   node_id: ast::NodeId) {
-    debug!("instantiate_path(path={}, def={}, node_id={}, type_scheme={})",
-           path.repr(fcx.tcx()),
+    debug!("instantiate_path(path={:?}, def={}, node_id={}, type_scheme={})",
+           segments,
            def.repr(fcx.tcx()),
            node_id,
            type_scheme.repr(fcx.tcx()));
@@ -4727,23 +4776,23 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
     //
     // The first step then is to categorize the segments appropriately.
 
-    assert!(path.segments.len() >= 1);
+    assert!(segments.len() >= 1);
+
+    let mut ufcs_method = None;
     let mut segment_spaces: Vec<_>;
     match def {
         // Case 1 and 1b. Reference to a *type* or *enum variant*.
         def::DefSelfTy(..) |
         def::DefStruct(..) |
         def::DefVariant(..) |
-        def::DefTyParamBinder(..) |
         def::DefTy(..) |
         def::DefAssociatedTy(..) |
-        def::DefAssociatedPath(..) |
-        def::DefaultImpl(..) |
+        def::DefTrait(..) |
         def::DefPrimTy(..) |
         def::DefTyParam(..) => {
             // Everything but the final segment should have no
             // parameters at all.
-            segment_spaces = repeat(None).take(path.segments.len() - 1).collect();
+            segment_spaces = repeat(None).take(segments.len() - 1).collect();
             segment_spaces.push(Some(subst::TypeSpace));
         }
 
@@ -4751,25 +4800,29 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
         def::DefFn(..) |
         def::DefConst(..) |
         def::DefStatic(..) => {
-            segment_spaces = repeat(None).take(path.segments.len() - 1).collect();
+            segment_spaces = repeat(None).take(segments.len() - 1).collect();
             segment_spaces.push(Some(subst::FnSpace));
         }
 
         // Case 3. Reference to a method.
-        def::DefStaticMethod(_, providence) |
-        def::DefMethod(_, _, providence) => {
-            assert!(path.segments.len() >= 2);
-
-            match providence {
+        def::DefMethod(_, provenance) => {
+            match provenance {
                 def::FromTrait(trait_did) => {
                     callee::check_legal_trait_for_method_call(fcx.ccx, span, trait_did)
                 }
                 def::FromImpl(_) => {}
             }
 
-            segment_spaces = repeat(None).take(path.segments.len() - 2).collect();
-            segment_spaces.push(Some(subst::TypeSpace));
-            segment_spaces.push(Some(subst::FnSpace));
+            if segments.len() >= 2 {
+                segment_spaces = repeat(None).take(segments.len() - 2).collect();
+                segment_spaces.push(Some(subst::TypeSpace));
+                segment_spaces.push(Some(subst::FnSpace));
+            } else {
+                // `<T>::method` will end up here, and so can `T::method`.
+                let self_ty = opt_self_ty.expect("UFCS sugared method missing Self");
+                segment_spaces = vec![Some(subst::FnSpace)];
+                ufcs_method = Some((provenance, self_ty));
+            }
         }
 
         // Other cases. Various nonsense that really shouldn't show up
@@ -4782,10 +4835,15 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
         def::DefRegion(..) |
         def::DefLabel(..) |
         def::DefUpvar(..) => {
-            segment_spaces = repeat(None).take(path.segments.len()).collect();
+            segment_spaces = repeat(None).take(segments.len()).collect();
         }
     }
-    assert_eq!(segment_spaces.len(), path.segments.len());
+    assert_eq!(segment_spaces.len(), segments.len());
+
+    // In `<T as Trait<A, B>>::method`, `A` and `B` are mandatory, but
+    // `opt_self_ty` can also be Some for `Foo::method`, where Foo's
+    // type parameters are not mandatory.
+    let require_type_space = opt_self_ty.is_some() && ufcs_method.is_none();
 
     debug!("segment_spaces={:?}", segment_spaces);
 
@@ -4799,16 +4857,17 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
     // provided (if any) into their appropriate spaces. We'll also report
     // errors if type parameters are provided in an inappropriate place.
     let mut substs = Substs::empty();
-    for (opt_space, segment) in segment_spaces.iter().zip(path.segments.iter()) {
+    for (opt_space, segment) in segment_spaces.iter().zip(segments.iter()) {
         match *opt_space {
             None => {
-                report_error_if_segment_contains_type_parameters(fcx, segment);
+                check_path_args(fcx.tcx(), slice::ref_slice(segment),
+                                NO_TPS | NO_REGIONS);
             }
 
             Some(space) => {
                 push_explicit_parameters_from_segment_to_substs(fcx,
                                                                 space,
-                                                                path.span,
+                                                                span,
                                                                 type_defs,
                                                                 region_defs,
                                                                 segment,
@@ -4817,9 +4876,9 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
         }
     }
     if let Some(self_ty) = opt_self_ty {
-        // `<T as Trait>::foo` shouldn't have resolved to a `Self`-less item.
-        assert_eq!(type_defs.len(subst::SelfSpace), 1);
-        substs.types.push(subst::SelfSpace, self_ty);
+        if type_defs.len(subst::SelfSpace) == 1 {
+            substs.types.push(subst::SelfSpace, self_ty);
+        }
     }
 
     // Now we have to compare the types that the user *actually*
@@ -4829,7 +4888,8 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
     // to add defaults. If the user provided *too many* types, that's
     // a problem.
     for &space in &ParamSpace::all() {
-        adjust_type_parameters(fcx, span, space, type_defs, &mut substs);
+        adjust_type_parameters(fcx, span, space, type_defs,
+                               require_type_space, &mut substs);
         assert_eq!(substs.types.len(space), type_defs.len(space));
 
         adjust_region_parameters(fcx, span, space, region_defs, &mut substs);
@@ -4852,27 +4912,32 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
     // the referenced item.
     let ty_substituted = fcx.instantiate_type_scheme(span, &substs, &type_scheme.ty);
 
-    fcx.write_ty(node_id, ty_substituted);
-    fcx.write_substs(node_id, ty::ItemSubsts { substs: substs });
-    return;
 
-    fn report_error_if_segment_contains_type_parameters(
-        fcx: &FnCtxt,
-        segment: &ast::PathSegment)
-    {
-        for typ in &segment.parameters.types() {
-            span_err!(fcx.tcx().sess, typ.span, E0085,
-                "type parameters may not appear here");
-            break;
-        }
+    if let Some((def::FromImpl(impl_def_id), self_ty)) = ufcs_method {
+        // In the case of `Foo<T>::method` and `<Foo<T>>::method`, if `method`
+        // is inherent, there is no `Self` parameter, instead, the impl needs
+        // type parameters, which we can infer by unifying the provided `Self`
+        // with the substituted impl type.
+        let impl_scheme = ty::lookup_item_type(fcx.tcx(), impl_def_id);
+        assert_eq!(substs.types.len(subst::TypeSpace),
+                   impl_scheme.generics.types.len(subst::TypeSpace));
+        assert_eq!(substs.regions().len(subst::TypeSpace),
+                   impl_scheme.generics.regions.len(subst::TypeSpace));
 
-        for lifetime in &segment.parameters.lifetimes() {
-            span_err!(fcx.tcx().sess, lifetime.span, E0086,
-                "lifetime parameters may not appear here");
-            break;
+        let impl_ty = fcx.instantiate_type_scheme(span, &substs, &impl_scheme.ty);
+        if fcx.mk_subty(false, infer::Misc(span), self_ty, impl_ty).is_err() {
+            fcx.tcx().sess.span_bug(span,
+            &format!(
+                "instantiate_path: (UFCS) {} was a subtype of {} but now is not?",
+                self_ty.repr(fcx.tcx()),
+                impl_ty.repr(fcx.tcx())));
         }
     }
 
+    fcx.write_ty(node_id, ty_substituted);
+    fcx.write_substs(node_id, ty::ItemSubsts { substs: substs });
+    return;
+
     /// Finds the parameters that the user provided and adds them to `substs`. If too many
     /// parameters are provided, then reports an error and clears the output vector.
     ///
@@ -5007,6 +5072,7 @@ fn adjust_type_parameters<'a, 'tcx>(
         span: Span,
         space: ParamSpace,
         defs: &VecPerParamSpace<ty::TypeParameterDef<'tcx>>,
+        require_type_space: bool,
         substs: &mut Substs<'tcx>)
     {
         let provided_len = substs.types.len(space);
@@ -5029,9 +5095,8 @@ fn adjust_type_parameters<'a, 'tcx>(
 
         // Nothing specified at all: supply inference variables for
         // everything.
-        if provided_len == 0 {
-            substs.types.replace(space,
-                                 fcx.infcx().next_ty_vars(desired.len()));
+        if provided_len == 0 && !(require_type_space && space == subst::TypeSpace) {
+            substs.types.replace(space, fcx.infcx().next_ty_vars(desired.len()));
             return;
         }
 
@@ -5153,18 +5218,15 @@ pub fn may_break(cx: &ty::ctxt, id: ast::NodeId, b: &ast::Block) -> bool {
             _ => false
         }
     })) ||
-   // Second: is there a labeled break with label
-   // <id> nested anywhere inside the loop?
+    // Second: is there a labeled break with label
+    // <id> nested anywhere inside the loop?
     (block_query(b, |e| {
-        match e.node {
-            ast::ExprBreak(Some(_)) => {
-                match cx.def_map.borrow().get(&e.id) {
-                    Some(&def::DefLabel(loop_id)) if id == loop_id => true,
-                    _ => false,
-                }
-            }
-            _ => false
-        }}))
+        if let ast::ExprBreak(Some(_)) = e.node {
+            lookup_full_def(cx, e.span, e.id) == def::DefLabel(id)
+        } else {
+            false
+        }
+    }))
 }
 
 pub fn check_bounds_are_used<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
index f6ac1ddee497694ac39c4be6d7edbd6af4a7d9e0..1518a09e7dc063656d2dba73782be746a686cbb7 100644 (file)
@@ -554,8 +554,12 @@ fn visit_expr(rcx: &mut Rcx, expr: &ast::Expr) {
                                                                expr.span);
             }
             Err(..) => {
-                rcx.fcx.tcx().sess.span_note(expr.span,
-                                             "cat_expr_unadjusted Errd during dtor check");
+                let tcx = rcx.fcx.tcx();
+                if tcx.sess.has_errors() {
+                    // cannot run dropck; okay b/c in error state anyway.
+                } else {
+                    tcx.sess.span_bug(expr.span, "cat_expr_unadjusted Errd");
+                }
             }
         }
     }
@@ -571,8 +575,12 @@ fn visit_expr(rcx: &mut Rcx, expr: &ast::Expr) {
             check_safety_of_rvalue_destructor_if_necessary(rcx, head_cmt, expr.span);
         }
         Err(..) => {
-            rcx.fcx.tcx().sess.span_note(expr.span,
-                                         "cat_expr Errd during dtor check");
+            let tcx = rcx.fcx.tcx();
+            if tcx.sess.has_errors() {
+                // cannot run dropck; okay b/c in error state anyway.
+            } else {
+                tcx.sess.span_bug(expr.span, "cat_expr Errd");
+            }
         }
     }
 
index 399795c66567e3df49861e3ca14a9051d78161ca..e024526d0016f7756c18baa0e2036f2379b0a213 100644 (file)
@@ -81,8 +81,8 @@ fn check_item_well_formed(&mut self, item: &ast::Item) {
             ast::ItemImpl(_, ast::ImplPolarity::Positive, _, _, _, _) => {
                 self.check_impl(item);
             }
-            ast::ItemImpl(_, ast::ImplPolarity::Negative, _, Some(ref tref), _, _) => {
-                let trait_ref = ty::node_id_to_trait_ref(ccx.tcx, tref.ref_id);
+            ast::ItemImpl(_, ast::ImplPolarity::Negative, _, Some(_), _, _) => {
+                let trait_ref = ty::impl_id_to_trait_ref(ccx.tcx, item.id);
                 ty::populate_implementations_for_trait_if_necessary(ccx.tcx, trait_ref.def_id);
                 match ccx.tcx.lang_items.to_builtin_kind(trait_ref.def_id) {
                     Some(ty::BoundSend) | Some(ty::BoundSync) => {}
index e535b86a7bfd1e0cfa72c2cb8e74ed84fcc3e261..e89c96b36e1a23887e2b52631945d2a2c99985dd 100644 (file)
@@ -28,8 +28,8 @@ struct ImplsChecker<'cx, 'tcx:'cx> {
 impl<'cx, 'tcx,'v> visit::Visitor<'v> for ImplsChecker<'cx, 'tcx> {
     fn visit_item(&mut self, item: &'v ast::Item) {
         match item.node {
-            ast::ItemImpl(_, _, _, Some(ref opt_trait), _, _) => {
-                let trait_ref = ty::node_id_to_trait_ref(self.tcx, opt_trait.ref_id);
+            ast::ItemImpl(_, _, _, Some(_), _, _) => {
+                let trait_ref = ty::impl_id_to_trait_ref(self.tcx, item.id);
                 if let Some(_) = self.tcx.lang_items.to_builtin_kind(trait_ref.def_id) {
                     match trait_ref.self_ty().sty {
                         ty::ty_struct(..) | ty::ty_enum(..) => {}
index 7dac1eeb6f11723d95acf77184e164a6c7a24d8d..1913b55f1d8e69d03da3fc0b368345b055522ed5 100644 (file)
@@ -106,19 +106,9 @@ fn visit_item(&mut self, item: &Item) {
 
         //debug!("(checking coherence) item '{}'", token::get_ident(item.ident));
 
-        match item.node {
-            ItemImpl(_, _, _, ref opt_trait, _, _) => {
-                match opt_trait.clone() {
-                    Some(opt_trait) => {
-                        self.cc.check_implementation(item, &[opt_trait]);
-                    }
-                    None => self.cc.check_implementation(item, &[])
-                }
-            }
-            _ => {
-                // Nothing to do.
-            }
-        };
+        if let ItemImpl(_, _, _, ref opt_trait, _, _) = item.node {
+            self.cc.check_implementation(item, opt_trait.as_ref())
+        }
 
         visit::walk_item(self, item);
     }
@@ -155,9 +145,7 @@ fn check(&self, krate: &Crate) {
         self.check_implementations_of_copy();
     }
 
-    fn check_implementation(&self,
-                            item: &Item,
-                            associated_traits: &[TraitRef]) {
+    fn check_implementation(&self, item: &Item, opt_trait: Option<&TraitRef>) {
         let tcx = self.crate_context.tcx;
         let impl_did = local_def(item.id);
         let self_type = ty::lookup_item_type(tcx, impl_did);
@@ -167,9 +155,8 @@ fn check_implementation(&self,
 
         let impl_items = self.create_impl_from_item(item);
 
-        for associated_trait in associated_traits {
-            let trait_ref = ty::node_id_to_trait_ref(self.crate_context.tcx,
-                                                     associated_trait.ref_id);
+        if opt_trait.is_some() {
+            let trait_ref = ty::impl_id_to_trait_ref(self.crate_context.tcx, item.id);
             debug!("(checking implementation) adding impl for trait '{}', item '{}'",
                    trait_ref.repr(self.crate_context.tcx),
                    token::get_ident(item.ident));
@@ -191,7 +178,7 @@ fn check_implementation(&self,
             }
             Some(base_type_def_id) => {
                 // FIXME: Gather up default methods?
-                if associated_traits.len() == 0 {
+                if opt_trait.is_none() {
                     self.add_inherent_impl(base_type_def_id, impl_did);
                 }
             }
@@ -289,7 +276,7 @@ fn get_self_type_for_implementation(&self, impl_did: DefId)
     // Converts an implementation in the AST to a vector of items.
     fn create_impl_from_item(&self, item: &Item) -> Vec<ImplOrTraitItemId> {
         match item.node {
-            ItemImpl(_, _, _, ref trait_refs, _, ref ast_items) => {
+            ItemImpl(_, _, _, ref opt_trait, _, ref ast_items) => {
                 let mut items: Vec<ImplOrTraitItemId> =
                         ast_items.iter()
                                  .map(|ast_item| {
@@ -304,13 +291,12 @@ fn create_impl_from_item(&self, item: &Item) -> Vec<ImplOrTraitItemId> {
                             }
                         }).collect();
 
-                if let Some(ref trait_ref) = *trait_refs {
-                    let ty_trait_ref = ty::node_id_to_trait_ref(
-                        self.crate_context.tcx,
-                        trait_ref.ref_id);
+                if opt_trait.is_some() {
+                    let trait_ref = ty::impl_id_to_trait_ref(self.crate_context.tcx,
+                                                             item.id);
 
                     self.instantiate_default_methods(local_def(item.id),
-                                                     &*ty_trait_ref,
+                                                     &*trait_ref,
                                                      &mut items);
                 }
 
index d34a16a924f70cb725a542a4744888f728353e8d..95dafccd866bf3369136c8f936b31edf362e7397 100644 (file)
@@ -16,7 +16,6 @@
 use syntax::ast::{Item, ItemImpl};
 use syntax::ast;
 use syntax::ast_util;
-use syntax::codemap::Span;
 use syntax::visit;
 use util::ppaux::{Repr, UserString};
 
@@ -30,9 +29,9 @@ struct OrphanChecker<'cx, 'tcx:'cx> {
 }
 
 impl<'cx, 'tcx> OrphanChecker<'cx, 'tcx> {
-    fn check_def_id(&self, span: Span, def_id: ast::DefId) {
+    fn check_def_id(&self, item: &ast::Item, def_id: ast::DefId) {
         if def_id.krate != ast::LOCAL_CRATE {
-            span_err!(self.tcx.sess, span, E0116,
+            span_err!(self.tcx.sess, item.span, E0116,
                       "cannot associate methods with a type outside the \
                        crate the type is defined in; define and implement \
                        a trait or new type instead");
@@ -41,7 +40,7 @@ fn check_def_id(&self, span: Span, def_id: ast::DefId) {
 }
 
 impl<'cx, 'tcx,'v> visit::Visitor<'v> for OrphanChecker<'cx, 'tcx> {
-    fn visit_item(&mut self, item: &'v ast::Item) {
+    fn visit_item(&mut self, item: &ast::Item) {
         let def_id = ast_util::local_def(item.id);
         match item.node {
             ast::ItemImpl(_, _, _, None, _, _) => {
@@ -52,15 +51,13 @@ fn visit_item(&mut self, item: &'v ast::Item) {
                 match self_ty.sty {
                     ty::ty_enum(def_id, _) |
                     ty::ty_struct(def_id, _) => {
-                        self.check_def_id(item.span, def_id);
+                        self.check_def_id(item, def_id);
                     }
                     ty::ty_trait(ref data) => {
-                        self.check_def_id(item.span, data.principal_def_id());
+                        self.check_def_id(item, data.principal_def_id());
                     }
                     ty::ty_uniq(..) => {
-                        self.check_def_id(item.span,
-                                          self.tcx.lang_items.owned_box()
-                                              .unwrap());
+                        self.check_def_id(item, self.tcx.lang_items.owned_box().unwrap());
                     }
                     _ => {
                         span_err!(self.tcx.sess, item.span, E0118,
@@ -96,10 +93,10 @@ fn visit_item(&mut self, item: &'v ast::Item) {
                     }
                 }
             }
-            ast::ItemDefaultImpl(_, ref ast_trait_ref) => {
+            ast::ItemDefaultImpl(..) => {
                 // "Trait" impl
                 debug!("coherence2::orphan check: default trait impl {}", item.repr(self.tcx));
-                let trait_ref = ty::node_id_to_trait_ref(self.tcx, ast_trait_ref.ref_id);
+                let trait_ref = ty::impl_trait_ref(self.tcx, def_id).unwrap();
                 if trait_ref.def_id.krate != ast::LOCAL_CRATE {
                     span_err!(self.tcx.sess, item.span, E0318,
                               "cannot create default implementations for traits outside the \
index 366e934b4ddce1e8d5165a3bb0dc95e90d26cd08..a6ecafb6241316382fd516b7236ff6527b80571a 100644 (file)
@@ -147,7 +147,7 @@ fn visit_item(&mut self, item: &'v ast::Item) {
                             None => {
                                 self.tcx.sess.bug(
                                           &format!("no default implementation recorded for `{:?}`",
-                                          item)[]);
+                                          item));
                             }
                         }
                     }
index 353e8e097a897d64e22c9e4e714bbc44835e806d..74fed6cbf3937364db6459f02cb83cd4b3975509 100644 (file)
@@ -91,19 +91,19 @@ trait hierarchy is only necessary for shorthands like `T::X` or
 use middle::lang_items::SizedTraitLangItem;
 use middle::region;
 use middle::resolve_lifetime;
-use middle::subst;
-use middle::subst::{Substs, SelfSpace, TypeSpace, VecPerParamSpace};
+use middle::subst::{Substs, FnSpace, ParamSpace, SelfSpace, TypeSpace, VecPerParamSpace};
 use middle::ty::{AsPredicate, ImplContainer, ImplOrTraitItemContainer, TraitContainer};
-use middle::ty::{self, RegionEscape, Ty, TypeScheme};
+use middle::ty::{self, RegionEscape, ToPolyTraitRef, Ty, TypeScheme};
 use middle::ty_fold::{self, TypeFolder, TypeFoldable};
 use middle::infer;
 use rscope::*;
-use util::common::memoized;
+use util::common::{ErrorReported, memoized};
 use util::nodemap::{FnvHashMap, FnvHashSet};
 use util::ppaux;
 use util::ppaux::{Repr,UserString};
 use write_ty_to_tcx;
 
+use std::cell::RefCell;
 use std::collections::HashSet;
 use std::rc::Rc;
 
@@ -121,7 +121,7 @@ trait hierarchy is only necessary for shorthands like `T::X` or
 // Main entry point
 
 pub fn collect_item_types(tcx: &ty::ctxt) {
-    let ccx = &CollectCtxt { tcx: tcx };
+    let ccx = &CrateCtxt { tcx: tcx, stack: RefCell::new(Vec::new()) };
 
     match ccx.tcx.lang_items.ty_desc() {
         Some(id) => { collect_intrinsic_type(ccx, id); }
@@ -141,17 +141,43 @@ pub fn collect_item_types(tcx: &ty::ctxt) {
 
 ///////////////////////////////////////////////////////////////////////////
 
-struct CollectCtxt<'a,'tcx:'a> {
+struct CrateCtxt<'a,'tcx:'a> {
     tcx: &'a ty::ctxt<'tcx>,
+
+    // This stack is used to identify cycles in the user's source.
+    // Note that these cycles can cross multiple items.
+    stack: RefCell<Vec<AstConvRequest>>,
+}
+
+/// Context specific to some particular item. This is what implements
+/// AstConv. It has information about the predicates that are defined
+/// on the trait. Unfortunately, this predicate information is
+/// available in various different forms at various points in the
+/// process. So we can't just store a pointer to e.g. the AST or the
+/// parsed ty form, we have to be more flexible. To this end, the
+/// `ItemCtxt` is parameterized by a `GetTypeParameterBounds` object
+/// that it uses to satisfy `get_type_parameter_bounds` requests.
+/// This object might draw the information from the AST
+/// (`ast::Generics`) or it might draw from a `ty::GenericPredicates`
+/// or both (a tuple).
+struct ItemCtxt<'a,'tcx:'a> {
+    ccx: &'a CrateCtxt<'a,'tcx>,
+    param_bounds: &'a (GetTypeParameterBounds<'tcx>+'a),
+}
+
+#[derive(Copy, PartialEq, Eq)]
+enum AstConvRequest {
+    GetItemTypeScheme(ast::DefId),
+    GetTraitDef(ast::DefId),
+    GetTypeParameterBounds(ast::NodeId),
 }
 
 ///////////////////////////////////////////////////////////////////////////
 // Zeroth phase: collect types of intrinsics
 
-fn collect_intrinsic_type(ccx: &CollectCtxt,
+fn collect_intrinsic_type(ccx: &CrateCtxt,
                           lang_item: ast::DefId) {
-    let ty::TypeScheme { ty, .. } =
-        ccx.get_item_type_scheme(lang_item);
+    let ty::TypeScheme { ty, .. } = type_scheme_of_def_id(ccx, lang_item);
     ccx.tcx.intrinsic_defs.borrow_mut().insert(lang_item, ty);
 }
 
@@ -161,7 +187,7 @@ fn collect_intrinsic_type(ccx: &CollectCtxt,
 // know later when parsing field defs.
 
 struct CollectTraitDefVisitor<'a, 'tcx: 'a> {
-    ccx: &'a CollectCtxt<'a, 'tcx>
+    ccx: &'a CrateCtxt<'a, 'tcx>
 }
 
 impl<'a, 'tcx, 'v> visit::Visitor<'v> for CollectTraitDefVisitor<'a, 'tcx> {
@@ -182,7 +208,7 @@ fn visit_item(&mut self, i: &ast::Item) {
 // Second phase: collection proper.
 
 struct CollectItemTypesVisitor<'a, 'tcx: 'a> {
-    ccx: &'a CollectCtxt<'a, 'tcx>
+    ccx: &'a CrateCtxt<'a, 'tcx>
 }
 
 impl<'a, 'tcx, 'v> visit::Visitor<'v> for CollectItemTypesVisitor<'a, 'tcx> {
@@ -199,42 +225,143 @@ fn visit_foreign_item(&mut self, i: &ast::ForeignItem) {
 ///////////////////////////////////////////////////////////////////////////
 // Utility types and common code for the above passes.
 
-pub trait ToTy<'tcx> {
-    fn to_ty<RS:RegionScope>(&self, rs: &RS, ast_ty: &ast::Ty) -> Ty<'tcx>;
-}
+impl<'a,'tcx> CrateCtxt<'a,'tcx> {
+    fn icx(&'a self, param_bounds: &'a GetTypeParameterBounds<'tcx>) -> ItemCtxt<'a,'tcx> {
+        ItemCtxt { ccx: self, param_bounds: param_bounds }
+    }
 
-impl<'a,'tcx> ToTy<'tcx> for CollectCtxt<'a,'tcx> {
-    fn to_ty<RS:RegionScope>(&self, rs: &RS, ast_ty: &ast::Ty) -> Ty<'tcx> {
-        ast_ty_to_ty(self, rs, ast_ty)
+    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()[def_id] {
+            ty::MethodTraitItem(ref mty) => mty.clone(),
+            ty::TypeTraitItem(..) => {
+                self.tcx.sess.bug(&format!("method with id {} has the wrong type", method_id));
+            }
+        }
     }
-}
 
-impl<'a, 'tcx> AstConv<'tcx> for CollectCtxt<'a, 'tcx> {
-    fn tcx(&self) -> &ty::ctxt<'tcx> { self.tcx }
+    fn cycle_check<F,R>(&self,
+                        span: Span,
+                        request: AstConvRequest,
+                        code: F)
+                        -> Result<R,ErrorReported>
+        where F: FnOnce() -> R
+    {
+        {
+            let mut stack = self.stack.borrow_mut();
+            match stack.iter().enumerate().rev().find(|&(_, r)| *r == request) {
+                None => { }
+                Some((i, _)) => {
+                    let cycle = &stack[i..];
+                    self.report_cycle(span, cycle);
+                    return Err(ErrorReported);
+                }
+            }
+            stack.push(request);
+        }
+
+        let result = code();
 
-    fn get_item_type_scheme(&self, id: ast::DefId) -> ty::TypeScheme<'tcx> {
-        if id.krate != ast::LOCAL_CRATE {
-            return ty::lookup_item_type(self.tcx, id);
+        self.stack.borrow_mut().pop();
+        Ok(result)
+    }
+
+    fn report_cycle(&self,
+                    span: Span,
+                    cycle: &[AstConvRequest])
+    {
+        assert!(!cycle.is_empty());
+        let tcx = self.tcx;
+
+        tcx.sess.span_err(
+            span,
+            &format!("unsupported cyclic reference between types/traits detected"));
+
+        match cycle[0] {
+            AstConvRequest::GetItemTypeScheme(def_id) |
+            AstConvRequest::GetTraitDef(def_id) => {
+                tcx.sess.note(
+                    &format!("the cycle begins when processing `{}`...",
+                             ty::item_path_str(tcx, def_id)));
+            }
+            AstConvRequest::GetTypeParameterBounds(id) => {
+                let def = tcx.type_parameter_def(id);
+                tcx.sess.note(
+                    &format!("the cycle begins when computing the bounds \
+                              for type parameter `{}`...",
+                             def.name.user_string(tcx)));
+            }
         }
 
-        match self.tcx.map.find(id.node) {
-            Some(ast_map::NodeItem(item)) => {
-                type_scheme_of_item(self, &*item)
+        for request in cycle[1..].iter() {
+            match *request {
+                AstConvRequest::GetItemTypeScheme(def_id) |
+                AstConvRequest::GetTraitDef(def_id) => {
+                    tcx.sess.note(
+                        &format!("...which then requires processing `{}`...",
+                                 ty::item_path_str(tcx, def_id)));
+                }
+                AstConvRequest::GetTypeParameterBounds(id) => {
+                    let def = tcx.type_parameter_def(id);
+                    tcx.sess.note(
+                        &format!("...which then requires computing the bounds \
+                                  for type parameter `{}`...",
+                                 def.name.user_string(tcx)));
+                }
             }
-            Some(ast_map::NodeForeignItem(foreign_item)) => {
-                let abi = self.tcx.map.get_foreign_abi(id.node);
-                type_scheme_of_foreign_item(self, &*foreign_item, abi)
+        }
+
+        match cycle[0] {
+            AstConvRequest::GetItemTypeScheme(def_id) |
+            AstConvRequest::GetTraitDef(def_id) => {
+                tcx.sess.note(
+                    &format!("...which then again requires processing `{}`, completing the cycle.",
+                             ty::item_path_str(tcx, def_id)));
             }
-            x => {
-                self.tcx.sess.bug(&format!("unexpected sort of node \
-                                            in get_item_type_scheme(): {:?}",
-                                           x));
+            AstConvRequest::GetTypeParameterBounds(id) => {
+                let def = tcx.type_parameter_def(id);
+                tcx.sess.note(
+                    &format!("...which then again requires computing the bounds \
+                              for type parameter `{}`, completing the cycle.",
+                             def.name.user_string(tcx)));
             }
         }
     }
+}
 
-    fn get_trait_def(&self, id: ast::DefId) -> Rc<ty::TraitDef<'tcx>> {
-        get_trait_def(self, id)
+impl<'a,'tcx> ItemCtxt<'a,'tcx> {
+    fn to_ty<RS:RegionScope>(&self, rs: &RS, ast_ty: &ast::Ty) -> Ty<'tcx> {
+        ast_ty_to_ty(self, rs, ast_ty)
+    }
+}
+
+impl<'a, 'tcx> AstConv<'tcx> for ItemCtxt<'a, 'tcx> {
+    fn tcx(&self) -> &ty::ctxt<'tcx> { self.ccx.tcx }
+
+    fn get_item_type_scheme(&self, span: Span, id: ast::DefId)
+                            -> Result<ty::TypeScheme<'tcx>, ErrorReported>
+    {
+        self.ccx.cycle_check(span, AstConvRequest::GetItemTypeScheme(id), || {
+            type_scheme_of_def_id(self.ccx, id)
+        })
+    }
+
+    fn get_trait_def(&self, span: Span, id: ast::DefId)
+                     -> Result<Rc<ty::TraitDef<'tcx>>, ErrorReported>
+    {
+        self.ccx.cycle_check(span, AstConvRequest::GetTraitDef(id), || {
+            get_trait_def(self.ccx, id)
+        })
+    }
+
+    fn get_type_parameter_bounds(&self,
+                                 span: Span,
+                                 node_id: ast::NodeId)
+                                 -> Result<Vec<ty::PolyTraitRef<'tcx>>, ErrorReported>
+    {
+        self.ccx.cycle_check(span, AstConvRequest::GetTypeParameterBounds(node_id), || {
+            self.param_bounds.get_type_parameter_bounds(self, span, node_id)
+        })
     }
 
     fn ty_infer(&self, span: Span) -> Ty<'tcx> {
@@ -253,11 +380,147 @@ fn projected_ty(&self,
     }
 }
 
-fn get_enum_variant_types<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
+/// Interface used to find the bounds on a type parameter from within
+/// an `ItemCtxt`. This allows us to use multiple kinds of sources.
+trait GetTypeParameterBounds<'tcx> {
+    fn get_type_parameter_bounds(&self,
+                                 astconv: &AstConv<'tcx>,
+                                 span: Span,
+                                 node_id: ast::NodeId)
+                                 -> Vec<ty::PolyTraitRef<'tcx>>;
+}
+
+/// Find bounds from both elements of the tuple.
+impl<'a,'b,'tcx,A,B> GetTypeParameterBounds<'tcx> for (&'a A,&'b B)
+    where A : GetTypeParameterBounds<'tcx>, B : GetTypeParameterBounds<'tcx>
+{
+    fn get_type_parameter_bounds(&self,
+                                 astconv: &AstConv<'tcx>,
+                                 span: Span,
+                                 node_id: ast::NodeId)
+                                 -> Vec<ty::PolyTraitRef<'tcx>>
+    {
+        let mut v = self.0.get_type_parameter_bounds(astconv, span, node_id);
+        v.extend(self.1.get_type_parameter_bounds(astconv, span, node_id).into_iter());
+        v
+    }
+}
+
+/// Empty set of bounds.
+impl<'tcx> GetTypeParameterBounds<'tcx> for () {
+    fn get_type_parameter_bounds(&self,
+                                 _astconv: &AstConv<'tcx>,
+                                 _span: Span,
+                                 _node_id: ast::NodeId)
+                                 -> Vec<ty::PolyTraitRef<'tcx>>
+    {
+        Vec::new()
+    }
+}
+
+/// Find bounds from the parsed and converted predicates.  This is
+/// used when converting methods, because by that time the predicates
+/// from the trait/impl have been fully converted.
+impl<'tcx> GetTypeParameterBounds<'tcx> for ty::GenericPredicates<'tcx> {
+    fn get_type_parameter_bounds(&self,
+                                 astconv: &AstConv<'tcx>,
+                                 _span: Span,
+                                 node_id: ast::NodeId)
+                                 -> Vec<ty::PolyTraitRef<'tcx>>
+    {
+        let def = astconv.tcx().type_parameter_def(node_id);
+
+        self.predicates
+            .iter()
+            .filter_map(|predicate| {
+                match *predicate {
+                    ty::Predicate::Trait(ref data) => {
+                        if data.0.self_ty().is_param(def.space, def.index) {
+                            Some(data.to_poly_trait_ref())
+                        } else {
+                            None
+                        }
+                    }
+                    ty::Predicate::Equate(..) |
+                    ty::Predicate::RegionOutlives(..) |
+                    ty::Predicate::TypeOutlives(..) |
+                    ty::Predicate::Projection(..) => {
+                        None
+                    }
+                }
+            })
+            .collect()
+    }
+}
+
+/// Find bounds from ast::Generics. This requires scanning through the
+/// AST. We do this to avoid having to convert *all* the bounds, which
+/// would create artificial cycles. Instead we can only convert the
+/// bounds for those a type parameter `X` if `X::Foo` is used.
+impl<'tcx> GetTypeParameterBounds<'tcx> for ast::Generics {
+    fn get_type_parameter_bounds(&self,
+                                 astconv: &AstConv<'tcx>,
+                                 _: Span,
+                                 node_id: ast::NodeId)
+                                 -> Vec<ty::PolyTraitRef<'tcx>>
+    {
+        // In the AST, bounds can derive from two places. Either
+        // written inline like `<T:Foo>` or in a where clause like
+        // `where T:Foo`.
+
+        let def = astconv.tcx().type_parameter_def(node_id);
+        let ty = ty::mk_param_from_def(astconv.tcx(), &def);
+
+        let from_ty_params =
+            self.ty_params
+                .iter()
+                .filter(|p| p.id == node_id)
+                .flat_map(|p| p.bounds.iter())
+                .filter_map(|b| poly_trait_ref_from_bound(astconv, ty, b, &mut Vec::new()));
+
+        let from_where_clauses =
+            self.where_clause
+                .predicates
+                .iter()
+                .filter_map(|wp| match *wp {
+                    ast::WherePredicate::BoundPredicate(ref bp) => Some(bp),
+                    _ => None
+                })
+                .filter(|bp| is_param(astconv.tcx(), &bp.bounded_ty, node_id))
+                .flat_map(|bp| bp.bounds.iter())
+                .filter_map(|b| poly_trait_ref_from_bound(astconv, ty, b, &mut Vec::new()));
+
+        from_ty_params.chain(from_where_clauses).collect()
+    }
+}
+
+/// Tests whether this is the AST for a reference to the type
+/// parameter with id `param_id`. We use this so as to avoid running
+/// `ast_ty_to_ty`, because we want to avoid triggering an all-out
+/// conversion of the type to avoid inducing unnecessary cycles.
+fn is_param<'tcx>(tcx: &ty::ctxt<'tcx>,
+                  ast_ty: &ast::Ty,
+                  param_id: ast::NodeId)
+                  -> bool
+{
+    if let ast::TyPath(None, _) = ast_ty.node {
+        let path_res = tcx.def_map.borrow()[ast_ty.id];
+        if let def::DefTyParam(_, _, def_id, _) = path_res.base_def {
+            path_res.depth == 0 && def_id == local_def(param_id)
+        } else {
+            false
+        }
+    } else {
+        false
+    }
+}
+
+fn get_enum_variant_types<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                                     enum_scheme: ty::TypeScheme<'tcx>,
                                     enum_predicates: ty::GenericPredicates<'tcx>,
                                     variants: &[P<ast::Variant>]) {
     let tcx = ccx.tcx;
+    let icx = ccx.icx(&enum_predicates);
 
     // Create a set of parameter types shared among all the variants.
     for variant in variants {
@@ -268,8 +531,8 @@ fn get_enum_variant_types<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
         let result_ty = match variant.node.kind {
             ast::TupleVariantKind(ref args) if args.len() > 0 => {
                 let rs = ExplicitRscope;
-                let input_tys: Vec<_> = args.iter().map(|va| ccx.to_ty(&rs, &*va.ty)).collect();
-                ty::mk_ctor_fn(tcx, variant_def_id, &input_tys[..], enum_scheme.ty)
+                let input_tys: Vec<_> = args.iter().map(|va| icx.to_ty(&rs, &*va.ty)).collect();
+                ty::mk_ctor_fn(tcx, variant_def_id, &input_tys, enum_scheme.ty)
             }
 
             ast::TupleVariantKind(_) => {
@@ -294,7 +557,7 @@ fn get_enum_variant_types<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
     }
 }
 
-fn collect_trait_methods<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
+fn collect_trait_methods<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                                    trait_id: ast::NodeId,
                                    trait_def: &ty::TraitDef<'tcx>,
                                    trait_predicates: &ty::GenericPredicates<'tcx>) {
@@ -393,7 +656,7 @@ fn collect_trait_methods<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
         }
     }
 
-    fn make_method_ty<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>, m: &ty::Method<'tcx>) {
+    fn make_method_ty<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, m: &ty::Method<'tcx>) {
         ccx.tcx.tcache.borrow_mut().insert(
             m.def_id,
             TypeScheme {
@@ -405,7 +668,7 @@ fn make_method_ty<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>, m: &ty::Method<'tcx>) {
             m.predicates.clone());
     }
 
-    fn ty_method_of_trait_method<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
+    fn ty_method_of_trait_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                                            trait_id: ast::NodeId,
                                            trait_generics: &ty::Generics<'tcx>,
                                            trait_bounds: &ty::GenericPredicates<'tcx>,
@@ -417,21 +680,17 @@ fn ty_method_of_trait_method<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
                                            m_generics: &ast::Generics,
                                            m_unsafety: &ast::Unsafety,
                                            m_decl: &ast::FnDecl)
-                                           -> ty::Method<'tcx> {
+                                           -> ty::Method<'tcx>
+    {
         let ty_generics =
-            ty_generics_for_fn_or_method(ccx,
-                                         m_generics,
-                                         trait_generics.clone());
+            ty_generics_for_fn(ccx, m_generics, trait_generics);
 
-        let ty_bounds =
-            ty_generic_bounds_for_fn_or_method(ccx,
-                                               m_generics,
-                                               &ty_generics,
-                                               trait_bounds.clone());
+        let ty_generic_predicates =
+            ty_generic_predicates_for_fn(ccx, m_generics, trait_bounds);
 
         let (fty, explicit_self_category) = {
             let trait_self_ty = ty::mk_self_type(ccx.tcx);
-            astconv::ty_of_method(ccx,
+            astconv::ty_of_method(&ccx.icx(&(trait_bounds, m_generics)),
                                   *m_unsafety,
                                   trait_self_ty,
                                   m_explicit_self,
@@ -442,7 +701,7 @@ fn ty_method_of_trait_method<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
         ty::Method::new(
             *m_name,
             ty_generics,
-            ty_bounds,
+            ty_generic_predicates,
             fty,
             explicit_self_category,
             // assume public, because this is only invoked on trait methods
@@ -454,12 +713,14 @@ fn ty_method_of_trait_method<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
     }
 }
 
-fn convert_field<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
-                                struct_generics: &ty::Generics<'tcx>,
-                                struct_predicates: &ty::GenericPredicates<'tcx>,
-                                v: &ast::StructField,
-                                origin: ast::DefId) -> ty::field_ty {
-    let tt = ccx.to_ty(&ExplicitRscope, &*v.node.ty);
+fn convert_field<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
+                           struct_generics: &ty::Generics<'tcx>,
+                           struct_predicates: &ty::GenericPredicates<'tcx>,
+                           v: &ast::StructField,
+                           origin: ast::DefId)
+                           -> ty::field_ty
+{
+    let tt = ccx.icx(struct_predicates).to_ty(&ExplicitRscope, &*v.node.ty);
     write_ty_to_tcx(ccx.tcx, v.node.id, tt);
 
     /* add the field to the tcache */
@@ -491,7 +752,7 @@ fn convert_field<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
     }
 }
 
-fn convert_associated_type<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
+fn convert_associated_type<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                                      trait_def: &ty::TraitDef<'tcx>,
                                      associated_type: &ast::AssociatedType)
 {
@@ -504,18 +765,18 @@ fn convert_associated_type<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
     ccx.tcx
        .impl_or_trait_items
        .borrow_mut()
-       .insert(associated_type.def_id,
-               ty::TypeTraitItem(associated_type));
+       .insert(associated_type.def_id, ty::TypeTraitItem(associated_type));
 }
 
-fn convert_methods<'a,'tcx,'i,I>(ccx: &CollectCtxt<'a, 'tcx>,
+fn convert_methods<'a,'tcx,'i,I>(ccx: &CrateCtxt<'a, 'tcx>,
                                  container: ImplOrTraitItemContainer,
                                  ms: I,
                                  untransformed_rcvr_ty: Ty<'tcx>,
                                  rcvr_ty_generics: &ty::Generics<'tcx>,
                                  rcvr_ty_predicates: &ty::GenericPredicates<'tcx>,
                                  rcvr_visibility: ast::Visibility)
-                                 where I: Iterator<Item=&'i ast::Method> {
+                                 where I: Iterator<Item=&'i ast::Method>
+{
     debug!("convert_methods(untransformed_rcvr_ty={}, rcvr_ty_generics={})",
            untransformed_rcvr_ty.repr(ccx.tcx),
            rcvr_ty_generics.repr(ccx.tcx));
@@ -559,31 +820,28 @@ fn convert_methods<'a,'tcx,'i,I>(ccx: &CollectCtxt<'a, 'tcx>,
            .insert(mty.def_id, ty::MethodTraitItem(mty));
     }
 
-    fn ty_of_method<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
+    fn ty_of_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                               container: ImplOrTraitItemContainer,
                               m: &ast::Method,
                               untransformed_rcvr_ty: Ty<'tcx>,
                               rcvr_ty_generics: &ty::Generics<'tcx>,
                               rcvr_ty_predicates: &ty::GenericPredicates<'tcx>,
                               rcvr_visibility: ast::Visibility)
-                              -> ty::Method<'tcx> {
+                              -> ty::Method<'tcx>
+    {
         let m_ty_generics =
-            ty_generics_for_fn_or_method(ccx,
-                                         m.pe_generics(),
-                                         rcvr_ty_generics.clone());
-
-        let m_ty_bounds =
-            ty_generic_bounds_for_fn_or_method(ccx,
-                                               m.pe_generics(),
-                                               &m_ty_generics,
-                                               rcvr_ty_predicates.clone());
-
-        let (fty, explicit_self_category) = astconv::ty_of_method(ccx,
-                                                                  m.pe_unsafety(),
-                                                                  untransformed_rcvr_ty,
-                                                                  m.pe_explicit_self(),
-                                                                  &*m.pe_fn_decl(),
-                                                                  m.pe_abi());
+            ty_generics_for_fn(ccx, m.pe_generics(), rcvr_ty_generics);
+
+        let m_ty_generic_predicates =
+            ty_generic_predicates_for_fn(ccx, m.pe_generics(), rcvr_ty_predicates);
+
+        let (fty, explicit_self_category) =
+            astconv::ty_of_method(&ccx.icx(&(rcvr_ty_predicates, m.pe_generics())),
+                                  m.pe_unsafety(),
+                                  untransformed_rcvr_ty,
+                                  m.pe_explicit_self(),
+                                  &*m.pe_fn_decl(),
+                                  m.pe_abi());
 
         // if the method specifies a visibility, use that, otherwise
         // inherit the visibility from the impl (so `foo` in `pub impl
@@ -593,7 +851,7 @@ fn ty_of_method<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
 
         ty::Method::new(m.pe_ident().name,
                         m_ty_generics,
-                        m_ty_bounds,
+                        m_ty_generic_predicates,
                         fty,
                         explicit_self_category,
                         method_vis,
@@ -603,7 +861,7 @@ fn ty_of_method<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
     }
 }
 
-fn ensure_no_ty_param_bounds(ccx: &CollectCtxt,
+fn ensure_no_ty_param_bounds(ccx: &CrateCtxt,
                                  span: Span,
                                  generics: &ast::Generics,
                                  thing: &'static str) {
@@ -632,7 +890,7 @@ fn ensure_no_ty_param_bounds(ccx: &CollectCtxt,
     }
 }
 
-fn convert_item(ccx: &CollectCtxt, it: &ast::Item) {
+fn convert_item(ccx: &CrateCtxt, it: &ast::Item) {
     let tcx = ccx.tcx;
     debug!("convert: item {} with id {}", token::get_ident(it.ident), it.id);
     match it.node {
@@ -649,8 +907,12 @@ fn convert_item(ccx: &CollectCtxt, it: &ast::Item) {
                                    &enum_definition.variants);
         },
         ast::ItemDefaultImpl(_, ref ast_trait_ref) => {
-            let trait_ref = astconv::instantiate_trait_ref(ccx, &ExplicitRscope,
-                                                           ast_trait_ref, None, None);
+            let trait_ref = astconv::instantiate_trait_ref(&ccx.icx(&()),
+                                                           &ExplicitRscope,
+                                                           ast_trait_ref,
+                                                           Some(it.id),
+                                                           None,
+                                                           None);
 
             ty::record_default_trait_implementation(tcx, trait_ref.def_id, local_def(it.id))
         }
@@ -663,11 +925,11 @@ fn convert_item(ccx: &CollectCtxt, it: &ast::Item) {
 
             debug!("convert: ast_generics={:?}", generics);
             let ty_generics = ty_generics_for_type_or_impl(ccx, generics);
-            let ty_predicates = ty_generic_bounds_for_type_or_impl(ccx, &ty_generics, generics);
+            let ty_predicates = ty_generic_predicates_for_type_or_impl(ccx, generics);
 
             debug!("convert: impl_bounds={:?}", ty_predicates);
 
-            let selfty = ccx.to_ty(&ExplicitRscope, &**selfty);
+            let selfty = ccx.icx(&ty_predicates).to_ty(&ExplicitRscope, &**selfty);
             write_ty_to_tcx(tcx, it.id, selfty);
 
             tcx.tcache.borrow_mut().insert(local_def(it.id),
@@ -691,12 +953,6 @@ fn convert_item(ccx: &CollectCtxt, it: &ast::Item) {
             for impl_item in impl_items {
                 match *impl_item {
                     ast::MethodImplItem(ref method) => {
-                        let body_id = method.pe_body().id;
-                        check_method_self_type(ccx,
-                                               &BindingRscope::new(),
-                                               selfty,
-                                               method.pe_explicit_self(),
-                                               body_id);
                         methods.push(&**method);
                     }
                     ast::TypeImplItem(ref typedef) => {
@@ -705,7 +961,7 @@ fn convert_item(ccx: &CollectCtxt, it: &ast::Item) {
                                               "associated items are not allowed in inherent impls");
                         }
 
-                        let typ = ccx.to_ty(&ExplicitRscope, &*typedef.typ);
+                        let typ = ccx.icx(&ty_predicates).to_ty(&ExplicitRscope, &*typedef.typ);
                         tcx.tcache.borrow_mut().insert(local_def(typedef.id),
                                                        TypeScheme {
                                                            generics: ty::Generics::empty(),
@@ -737,10 +993,26 @@ fn convert_item(ccx: &CollectCtxt, it: &ast::Item) {
                             &ty_predicates,
                             parent_visibility);
 
+            for impl_item in impl_items {
+                match *impl_item {
+                    ast::MethodImplItem(ref method) => {
+                        let body_id = method.pe_body().id;
+                        check_method_self_type(ccx,
+                                               &BindingRscope::new(),
+                                               ccx.method_ty(method.id),
+                                               selfty,
+                                               method.pe_explicit_self(),
+                                               body_id);
+                    }
+                    ast::TypeImplItem(..) => { }
+                }
+            }
+
             if let Some(ref trait_ref) = *opt_trait_ref {
-                astconv::instantiate_trait_ref(ccx,
+                astconv::instantiate_trait_ref(&ccx.icx(&ty_predicates),
                                                &ExplicitRscope,
                                                trait_ref,
+                                               Some(it.id),
                                                Some(selfty),
                                                None);
             }
@@ -749,20 +1021,42 @@ fn convert_item(ccx: &CollectCtxt, it: &ast::Item) {
                                                    generics,
                                                    local_def(it.id));
         },
-        ast::ItemTrait(_, _, _, ref trait_methods) => {
+        ast::ItemTrait(_, _, _, ref trait_items) => {
             let trait_def = trait_def_of_item(ccx, it);
             convert_trait_predicates(ccx, it);
             let trait_predicates = ty::lookup_predicates(ccx.tcx, local_def(it.id));
 
             debug!("convert: trait_bounds={:?}", trait_predicates);
 
-            for trait_method in trait_methods {
+            // Run convert_methods on the provided methods.
+            let untransformed_rcvr_ty = ty::mk_self_type(tcx);
+            convert_methods(ccx,
+                            TraitContainer(local_def(it.id)),
+                            trait_items.iter().filter_map(|m| match *m {
+                                ast::RequiredMethod(_) => None,
+                                ast::ProvidedMethod(ref m) => Some(&**m),
+                                ast::TypeTraitItem(_) => None,
+                            }),
+                            untransformed_rcvr_ty,
+                            &trait_def.generics,
+                            &trait_predicates,
+                            it.vis);
+
+            // We need to do this *after* converting methods, since
+            // convert_methods produces a tcache entry that is wrong for
+            // static trait methods. This is somewhat unfortunate.
+            collect_trait_methods(ccx, it.id, &*trait_def, &trait_predicates);
+
+            // This must be done after `collect_trait_methods` so that
+            // we have a method type stored for every method.
+            for trait_item in trait_items {
                 let self_type = ty::mk_self_type(tcx);
-                match *trait_method {
+                match *trait_item {
                     ast::RequiredMethod(ref type_method) => {
                         let rscope = BindingRscope::new();
                         check_method_self_type(ccx,
                                                &rscope,
+                                               ccx.method_ty(type_method.id),
                                                self_type,
                                                &type_method.explicit_self,
                                                it.id)
@@ -770,6 +1064,7 @@ fn convert_item(ccx: &CollectCtxt, it: &ast::Item) {
                     ast::ProvidedMethod(ref method) => {
                         check_method_self_type(ccx,
                                                &BindingRscope::new(),
+                                               ccx.method_ty(method.id),
                                                self_type,
                                                method.pe_explicit_self(),
                                                it.id)
@@ -781,25 +1076,6 @@ fn convert_item(ccx: &CollectCtxt, it: &ast::Item) {
                     }
                 }
             }
-
-            // Run convert_methods on the provided methods.
-            let untransformed_rcvr_ty = ty::mk_self_type(tcx);
-            convert_methods(ccx,
-                            TraitContainer(local_def(it.id)),
-                            trait_methods.iter().filter_map(|m| match *m {
-                                ast::RequiredMethod(_) => None,
-                                ast::ProvidedMethod(ref m) => Some(&**m),
-                                ast::TypeTraitItem(_) => None,
-                            }),
-                            untransformed_rcvr_ty,
-                            &trait_def.generics,
-                            &trait_predicates,
-                            it.vis);
-
-            // We need to do this *after* converting methods, since
-            // convert_methods produces a tcache entry that is wrong for
-            // static trait methods. This is somewhat unfortunate.
-            collect_trait_methods(ccx, it.id, &*trait_def, &trait_predicates);
         },
         ast::ItemStruct(ref struct_def, _) => {
             // Write the class type.
@@ -822,7 +1098,7 @@ fn convert_item(ccx: &CollectCtxt, it: &ast::Item) {
     }
 }
 
-fn convert_struct<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
+fn convert_struct<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                             struct_def: &ast::StructDef,
                             scheme: ty::TypeScheme<'tcx>,
                             predicates: ty::GenericPredicates<'tcx>,
@@ -892,7 +1168,7 @@ fn convert_struct<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
     }
 }
 
-fn get_trait_def<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
+fn get_trait_def<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                            trait_id: ast::DefId)
                            -> Rc<ty::TraitDef<'tcx>> {
     let tcx = ccx.tcx;
@@ -910,7 +1186,7 @@ fn get_trait_def<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
     }
 }
 
-fn trait_def_of_item<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
+fn trait_def_of_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                                it: &ast::Item)
                                -> Rc<ty::TraitDef<'tcx>>
 {
@@ -953,7 +1229,7 @@ fn trait_def_of_item<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
     let self_param_ty = ty::ParamTy::for_self().to_ty(ccx.tcx);
 
     // supertraits:
-    let bounds = compute_bounds(ccx,
+    let bounds = compute_bounds(&ccx.icx(generics),
                                 self_param_ty,
                                 bounds,
                                 SizedByDefault::No,
@@ -987,9 +1263,9 @@ fn trait_def_of_item<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
 
     return trait_def;
 
-    fn mk_trait_substs<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
+    fn mk_trait_substs<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                                  generics: &ast::Generics)
-                                 -> subst::Substs<'tcx>
+                                 -> Substs<'tcx>
     {
         let tcx = ccx.tcx;
 
@@ -999,7 +1275,7 @@ fn mk_trait_substs<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
                     .iter()
                     .enumerate()
                     .map(|(i, def)| ty::ReEarlyBound(def.lifetime.id,
-                                                     subst::TypeSpace,
+                                                     TypeSpace,
                                                      i as u32,
                                                      def.lifetime.name))
                     .collect();
@@ -1009,18 +1285,18 @@ fn mk_trait_substs<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
             generics.ty_params
                     .iter()
                     .enumerate()
-                    .map(|(i, def)| ty::mk_param(tcx, subst::TypeSpace,
+                    .map(|(i, def)| ty::mk_param(tcx, TypeSpace,
                                                  i as u32, def.ident.name))
                     .collect();
 
         // ...and also create the `Self` parameter.
         let self_ty = ty::mk_self_type(tcx);
 
-        subst::Substs::new_trait(types, regions, self_ty)
+        Substs::new_trait(types, regions, self_ty)
     }
 }
 
-fn convert_trait_predicates<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>, it: &ast::Item) {
+fn convert_trait_predicates<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, it: &ast::Item) {
     let tcx = ccx.tcx;
     let trait_def = trait_def_of_item(ccx, it);
 
@@ -1039,9 +1315,7 @@ fn convert_trait_predicates<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>, it: &ast::Ite
 
     let super_predicates = ty::predicates(ccx.tcx, self_param_ty, &trait_def.bounds);
 
-    let assoc_predicates = predicates_for_associated_types(ccx, &trait_def.trait_ref, items);
-
-    // `ty_generic_bounds` below will consider the bounds on the type
+    // `ty_generic_predicates` below will consider the bounds on the type
     // parameters (including `Self`) and the explicit where-clauses,
     // but to get the full set of predicates on a trait we need to add
     // in the supertrait bounds and anything declared on the
@@ -1050,27 +1324,31 @@ fn convert_trait_predicates<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>, it: &ast::Ite
         ty::GenericPredicates {
             predicates: VecPerParamSpace::new(super_predicates, vec![], vec![])
         };
-    base_predicates.predicates.extend(subst::TypeSpace, assoc_predicates.into_iter());
 
-    let self_bounds = &trait_def.generics.types.get_self().unwrap().bounds;
-    base_predicates.predicates.extend(
-        subst::SelfSpace,
-        ty::predicates(ccx.tcx, self_param_ty, self_bounds).into_iter());
+    // Add in a predicate that `Self:Trait` (where `Trait` is the
+    // current trait).  This is needed for builtin bounds.
+    let self_predicate = trait_def.trait_ref.to_poly_trait_ref().as_predicate();
+    base_predicates.predicates.push(SelfSpace, self_predicate);
 
     // add in the explicit where-clauses
-    let trait_predicates =
-        ty_generic_bounds(ccx,
-                          subst::TypeSpace,
-                          &trait_def.generics,
-                          base_predicates,
-                          &generics.where_clause);
+    let mut trait_predicates =
+        ty_generic_predicates(ccx, TypeSpace, generics, &base_predicates);
+
+    let assoc_predicates = predicates_for_associated_types(ccx,
+                                                           generics,
+                                                           &trait_predicates,
+                                                           &trait_def.trait_ref,
+                                                           items);
+    trait_predicates.predicates.extend(TypeSpace, assoc_predicates.into_iter());
 
     let prev_predicates = tcx.predicates.borrow_mut().insert(def_id, trait_predicates);
     assert!(prev_predicates.is_none());
 
     return;
 
-    fn predicates_for_associated_types<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
+    fn predicates_for_associated_types<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
+                                                 ast_generics: &ast::Generics,
+                                                 trait_predicates: &ty::GenericPredicates<'tcx>,
                                                  self_trait_ref: &Rc<ty::TraitRef<'tcx>>,
                                                  trait_items: &[ast::TraitItem])
                                                  -> Vec<ty::Predicate<'tcx>>
@@ -1089,7 +1367,7 @@ fn predicates_for_associated_types<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
                                                  self_trait_ref.clone(),
                                                  assoc_type_def.ident.name);
 
-                let bounds = compute_bounds(ccx,
+                let bounds = compute_bounds(&ccx.icx(&(ast_generics, trait_predicates)),
                                             assoc_ty,
                                             &*assoc_type_def.bounds,
                                             SizedByDefault::Yes,
@@ -1101,7 +1379,31 @@ fn predicates_for_associated_types<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
     }
 }
 
-fn type_scheme_of_item<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>,
+fn type_scheme_of_def_id<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
+                                  def_id: ast::DefId)
+                                  -> ty::TypeScheme<'tcx>
+{
+    if def_id.krate != ast::LOCAL_CRATE {
+        return ty::lookup_item_type(ccx.tcx, def_id);
+    }
+
+    match ccx.tcx.map.find(def_id.node) {
+        Some(ast_map::NodeItem(item)) => {
+            type_scheme_of_item(ccx, &*item)
+        }
+        Some(ast_map::NodeForeignItem(foreign_item)) => {
+            let abi = ccx.tcx.map.get_foreign_abi(def_id.node);
+            type_scheme_of_foreign_item(ccx, &*foreign_item, abi)
+        }
+        x => {
+            ccx.tcx.sess.bug(&format!("unexpected sort of node \
+                                            in get_item_type_scheme(): {:?}",
+                                       x));
+        }
+    }
+}
+
+fn type_scheme_of_item<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
                                 it: &ast::Item)
                                 -> ty::TypeScheme<'tcx>
 {
@@ -1110,28 +1412,25 @@ fn type_scheme_of_item<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>,
              |_| compute_type_scheme_of_item(ccx, it))
 }
 
-
-fn compute_type_scheme_of_item<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>,
-                                              it: &ast::Item)
-                                              -> ty::TypeScheme<'tcx>
+fn compute_type_scheme_of_item<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
+                                        it: &ast::Item)
+                                        -> ty::TypeScheme<'tcx>
 {
     let tcx = ccx.tcx;
     match it.node {
         ast::ItemStatic(ref t, _, _) | ast::ItemConst(ref t, _) => {
-            let ty = ccx.to_ty(&ExplicitRscope, &**t);
+            let ty = ccx.icx(&()).to_ty(&ExplicitRscope, &**t);
             ty::TypeScheme { ty: ty, generics: ty::Generics::empty() }
         }
         ast::ItemFn(ref decl, unsafety, abi, ref generics, _) => {
-            let ty_generics = ty_generics_for_fn_or_method(ccx,
-                                                           generics,
-                                                           ty::Generics::empty());
-            let tofd = astconv::ty_of_bare_fn(ccx, unsafety, abi, &**decl);
+            let ty_generics = ty_generics_for_fn(ccx, generics, &ty::Generics::empty());
+            let tofd = astconv::ty_of_bare_fn(&ccx.icx(generics), unsafety, abi, &**decl);
             let ty = ty::mk_bare_fn(tcx, Some(local_def(it.id)), tcx.mk_bare_fn(tofd));
             ty::TypeScheme { ty: ty, generics: ty_generics }
         }
         ast::ItemTy(ref t, ref generics) => {
-            let ty = ccx.to_ty(&ExplicitRscope, &**t);
             let ty_generics = ty_generics_for_type_or_impl(ccx, generics);
+            let ty = ccx.icx(generics).to_ty(&ExplicitRscope, &**t);
             ty::TypeScheme { ty: ty, generics: ty_generics }
         }
         ast::ItemEnum(_, ref generics) => {
@@ -1163,7 +1462,7 @@ fn compute_type_scheme_of_item<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>,
     }
 }
 
-fn convert_typed_item<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
+fn convert_typed_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                                 it: &ast::Item)
                                 -> (ty::TypeScheme<'tcx>, ty::GenericPredicates<'tcx>)
 {
@@ -1176,19 +1475,16 @@ fn convert_typed_item<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
             ty::GenericPredicates::empty()
         }
         ast::ItemFn(_, _, _, ref ast_generics, _) => {
-            ty_generic_bounds_for_fn_or_method(ccx,
-                                               ast_generics,
-                                               &scheme.generics,
-                                               ty::GenericPredicates::empty())
+            ty_generic_predicates_for_fn(ccx, ast_generics, &ty::GenericPredicates::empty())
         }
         ast::ItemTy(_, ref generics) => {
-            ty_generic_bounds_for_type_or_impl(ccx, &scheme.generics, generics)
+            ty_generic_predicates_for_type_or_impl(ccx, generics)
         }
         ast::ItemEnum(_, ref generics) => {
-            ty_generic_bounds_for_type_or_impl(ccx, &scheme.generics, generics)
+            ty_generic_predicates_for_type_or_impl(ccx, generics)
         }
         ast::ItemStruct(_, ref generics) => {
-            ty_generic_bounds_for_type_or_impl(ccx, &scheme.generics, generics)
+            ty_generic_predicates_for_type_or_impl(ccx, generics)
         }
         ast::ItemDefaultImpl(..) |
         ast::ItemTrait(..) |
@@ -1200,8 +1496,8 @@ fn convert_typed_item<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
         ast::ItemMac(..) => {
             tcx.sess.span_bug(
                 it.span,
-                format!("compute_type_scheme_of_item: unexpected item type: {:?}",
-                        it.node).as_slice());
+                &format!("compute_type_scheme_of_item: unexpected item type: {:?}",
+                         it.node));
         }
     };
 
@@ -1217,7 +1513,7 @@ fn convert_typed_item<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
                                      Some(ty::ObjectLifetimeDefault::Specific(r)) =>
                                          r.user_string(tcx),
                                      d =>
-                                         d.repr(ccx.tcx()),
+                                         d.repr(ccx.tcx),
                                  })
                                  .collect::<Vec<String>>()
                                  .connect(",");
@@ -1229,18 +1525,18 @@ fn convert_typed_item<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
 }
 
 fn type_scheme_of_foreign_item<'a, 'tcx>(
-    ccx: &CollectCtxt<'a, 'tcx>,
+    ccx: &CrateCtxt<'a, 'tcx>,
     it: &ast::ForeignItem,
     abi: abi::Abi)
     -> ty::TypeScheme<'tcx>
 {
-    memoized(&ccx.tcx().tcache,
+    memoized(&ccx.tcx.tcache,
              local_def(it.id),
              |_| compute_type_scheme_of_foreign_item(ccx, it, abi))
 }
 
 fn compute_type_scheme_of_foreign_item<'a, 'tcx>(
-    ccx: &CollectCtxt<'a, 'tcx>,
+    ccx: &CrateCtxt<'a, 'tcx>,
     it: &ast::ForeignItem,
     abi: abi::Abi)
     -> ty::TypeScheme<'tcx>
@@ -1252,13 +1548,13 @@ fn compute_type_scheme_of_foreign_item<'a, 'tcx>(
         ast::ForeignItemStatic(ref t, _) => {
             ty::TypeScheme {
                 generics: ty::Generics::empty(),
-                ty: ast_ty_to_ty(ccx, &ExplicitRscope, t)
+                ty: ast_ty_to_ty(&ccx.icx(&()), &ExplicitRscope, t)
             }
         }
     }
 }
 
-fn convert_foreign_item<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
+fn convert_foreign_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                                   it: &ast::ForeignItem)
 {
     // For reasons I cannot fully articulate, I do so hate the AST
@@ -1273,10 +1569,7 @@ fn convert_foreign_item<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
 
     let predicates = match it.node {
         ast::ForeignItemFn(_, ref generics) => {
-            ty_generic_bounds_for_fn_or_method(ccx,
-                                               generics,
-                                               &scheme.generics,
-                                               ty::GenericPredicates::empty())
+            ty_generic_predicates_for_fn(ccx, generics, &ty::GenericPredicates::empty())
         }
         ast::ForeignItemStatic(..) => {
             ty::GenericPredicates::empty()
@@ -1287,45 +1580,29 @@ fn convert_foreign_item<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
     assert!(prev_predicates.is_none());
 }
 
-fn ty_generics_for_type_or_impl<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
+fn ty_generics_for_type_or_impl<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                                           generics: &ast::Generics)
                                           -> ty::Generics<'tcx> {
-    ty_generics(ccx,
-                subst::TypeSpace,
-                &generics.lifetimes,
-                &generics.ty_params,
-                &generics.where_clause,
-                ty::Generics::empty())
+    ty_generics(ccx, TypeSpace, generics, &ty::Generics::empty())
 }
 
-fn ty_generic_bounds_for_type_or_impl<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>,
-                                               ty_generics: &ty::Generics<'tcx>,
-                                               generics: &ast::Generics)
-                                               -> ty::GenericPredicates<'tcx>
+fn ty_generic_predicates_for_type_or_impl<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
+                                                   generics: &ast::Generics)
+                                                   -> ty::GenericPredicates<'tcx>
 {
-    ty_generic_bounds(ccx,
-                      subst::TypeSpace,
-                      ty_generics,
-                      ty::GenericPredicates::empty(),
-                      &generics.where_clause)
+    ty_generic_predicates(ccx, TypeSpace, generics, &ty::GenericPredicates::empty())
 }
 
-fn ty_generics_for_trait<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
+fn ty_generics_for_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                                    trait_id: ast::NodeId,
-                                   substs: &'tcx subst::Substs<'tcx>,
+                                   substs: &'tcx Substs<'tcx>,
                                    ast_generics: &ast::Generics)
                                    -> ty::Generics<'tcx>
 {
     debug!("ty_generics_for_trait(trait_id={}, substs={})",
            local_def(trait_id).repr(ccx.tcx), substs.repr(ccx.tcx));
 
-    let mut generics =
-        ty_generics(ccx,
-                    subst::TypeSpace,
-                    &ast_generics.lifetimes,
-                    &ast_generics.ty_params,
-                    &ast_generics.where_clause,
-                    ty::Generics::empty());
+    let mut generics = ty_generics_for_type_or_impl(ccx, ast_generics);
 
     // Add in the self type parameter.
     //
@@ -1333,65 +1610,46 @@ fn ty_generics_for_trait<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
     // the node id for the Self type parameter.
     let param_id = trait_id;
 
-    let self_trait_ref =
-        Rc::new(ty::TraitRef { def_id: local_def(trait_id),
-                               substs: substs });
-
     let def = ty::TypeParameterDef {
-        space: subst::SelfSpace,
+        space: SelfSpace,
         index: 0,
         name: special_idents::type_self.name,
         def_id: local_def(param_id),
-        bounds: ty::ParamBounds {
-            region_bounds: vec!(),
-            builtin_bounds: ty::empty_builtin_bounds(),
-            trait_bounds: vec!(ty::Binder(self_trait_ref.clone())),
-            projection_bounds: vec!(),
-        },
         default: None,
         object_lifetime_default: None,
     };
 
     ccx.tcx.ty_param_defs.borrow_mut().insert(param_id, def.clone());
 
-    generics.types.push(subst::SelfSpace, def);
+    generics.types.push(SelfSpace, def);
 
     return generics;
 }
 
-fn ty_generics_for_fn_or_method<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>,
-                                         generics: &ast::Generics,
-                                         base_generics: ty::Generics<'tcx>)
-                                         -> ty::Generics<'tcx>
+fn ty_generics_for_fn<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
+                               generics: &ast::Generics,
+                               base_generics: &ty::Generics<'tcx>)
+                               -> ty::Generics<'tcx>
 {
-    let early_lifetimes = resolve_lifetime::early_bound_lifetimes(generics);
-    ty_generics(ccx,
-                subst::FnSpace,
-                &early_lifetimes[..],
-                &generics.ty_params,
-                &generics.where_clause,
-                base_generics)
+    ty_generics(ccx, FnSpace, generics, base_generics)
 }
 
-fn ty_generic_bounds_for_fn_or_method<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>,
-                                               generics: &ast::Generics,
-                                               ty_generics: &ty::Generics<'tcx>,
-                                               base: ty::GenericPredicates<'tcx>)
-                                               -> ty::GenericPredicates<'tcx>
+fn ty_generic_predicates_for_fn<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
+                                         generics: &ast::Generics,
+                                         base_predicates: &ty::GenericPredicates<'tcx>)
+                                         -> ty::GenericPredicates<'tcx>
 {
-    ty_generic_bounds(ccx,
-                      subst::FnSpace,
-                      ty_generics,
-                      base,
-                      &generics.where_clause)
+    ty_generic_predicates(ccx, FnSpace, generics, base_predicates)
 }
 
 // Add the Sized bound, unless the type parameter is marked as `?Sized`.
-fn add_unsized_bound<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>,
-                              bounds: &mut ty::BuiltinBounds,
-                              ast_bounds: &[ast::TyParamBound],
-                              span: Span)
+fn add_unsized_bound<'tcx>(astconv: &AstConv<'tcx>,
+                           bounds: &mut ty::BuiltinBounds,
+                           ast_bounds: &[ast::TyParamBound],
+                           span: Span)
 {
+    let tcx = astconv.tcx();
+
     // Try to find an unbound in bounds.
     let mut unbound = None;
     for ab in ast_bounds {
@@ -1400,80 +1658,108 @@ fn add_unsized_bound<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>,
                 assert!(ptr.bound_lifetimes.is_empty());
                 unbound = Some(ptr.trait_ref.clone());
             } else {
-                span_err!(ccx.tcx.sess, span, E0203,
+                span_err!(tcx.sess, span, E0203,
                           "type parameter has more than one relaxed default \
                                                 bound, only one is supported");
             }
         }
     }
 
-    let kind_id = ccx.tcx.lang_items.require(SizedTraitLangItem);
+    let kind_id = tcx.lang_items.require(SizedTraitLangItem);
     match unbound {
         Some(ref tpb) => {
             // FIXME(#8559) currently requires the unbound to be built-in.
-            let trait_def_id = ty::trait_ref_to_def_id(ccx.tcx, tpb);
+            let trait_def_id = ty::trait_ref_to_def_id(tcx, tpb);
             match kind_id {
                 Ok(kind_id) if trait_def_id != kind_id => {
-                    ccx.tcx.sess.span_warn(span,
-                                              "default bound relaxed for a type parameter, but \
-                                               this does nothing because the given bound is not \
-                                               a default. Only `?Sized` is supported");
-                    ty::try_add_builtin_trait(ccx.tcx,
-                                              kind_id,
-                                              bounds);
+                    tcx.sess.span_warn(span,
+                                       "default bound relaxed for a type parameter, but \
+                                       this does nothing because the given bound is not \
+                                       a default. Only `?Sized` is supported");
+                    ty::try_add_builtin_trait(tcx, kind_id, bounds);
                 }
                 _ => {}
             }
         }
         _ if kind_id.is_ok() => {
-            ty::try_add_builtin_trait(ccx.tcx, kind_id.unwrap(), bounds);
+            ty::try_add_builtin_trait(tcx, kind_id.unwrap(), bounds);
         }
         // No lang item for Sized, so we can't add it as a bound.
         None => {}
     }
 }
 
-fn ty_generic_bounds<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>,
-                              space: subst::ParamSpace,
-                              generics: &ty::Generics<'tcx>,
-                              base: ty::GenericPredicates<'tcx>,
-                              where_clause: &ast::WhereClause)
-                              -> ty::GenericPredicates<'tcx>
+/// Returns the early-bound lifetimes declared in this generics
+/// listing.  For anything other than fns/methods, this is just all
+/// the lifetimes that are declared. For fns or methods, we have to
+/// screen out those that do not appear in any where-clauses etc using
+/// `resolve_lifetime::early_bound_lifetimes`.
+fn early_bound_lifetimes_from_generics(space: ParamSpace,
+                                       ast_generics: &ast::Generics)
+                                       -> Vec<ast::LifetimeDef>
+{
+    match space {
+        SelfSpace | TypeSpace => ast_generics.lifetimes.to_vec(),
+        FnSpace => resolve_lifetime::early_bound_lifetimes(ast_generics),
+    }
+}
+
+fn ty_generic_predicates<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
+                                  space: ParamSpace,
+                                  ast_generics: &ast::Generics,
+                                  base_predicates: &ty::GenericPredicates<'tcx>)
+                                  -> ty::GenericPredicates<'tcx>
 {
     let tcx = ccx.tcx;
-    let mut result = base;
-
-    // For now, scrape the bounds out of parameters from Generics. This is not great.
-    for def in generics.regions.get_slice(space) {
-        let r_a = def.to_early_bound_region();
-        for &r_b in &def.bounds {
-            let outlives = ty::Binder(ty::OutlivesPredicate(r_a, r_b));
-            result.predicates.push(def.space, ty::Predicate::RegionOutlives(outlives));
-        }
+    let mut result = base_predicates.clone();
+
+    // Collect the predicates that were written inline by the user on each
+    // type parameter (e.g., `<T:Foo>`).
+    for (index, param) in ast_generics.ty_params.iter().enumerate() {
+        let index = index as u32;
+        let param_ty = ty::ParamTy::new(space, index, param.ident.name).to_ty(ccx.tcx);
+        let bounds = compute_bounds(&ccx.icx(&(base_predicates, ast_generics)),
+                                    param_ty,
+                                    &param.bounds,
+                                    SizedByDefault::Yes,
+                                    param.span);
+        let predicates = ty::predicates(ccx.tcx, param_ty, &bounds);
+        result.predicates.extend(space, predicates.into_iter());
     }
-    for def in generics.types.get_slice(space) {
-        let t = ty::mk_param_from_def(ccx.tcx, def);
-        result.predicates.extend(def.space, ty::predicates(ccx.tcx, t, &def.bounds).into_iter());
+
+    // Collect the region predicates that were declared inline as
+    // well. In the case of parameters declared on a fn or method, we
+    // have to be careful to only iterate over early-bound regions.
+    let early_lifetimes = early_bound_lifetimes_from_generics(space, ast_generics);
+    for (index, param) in early_lifetimes.iter().enumerate() {
+        let index = index as u32;
+        let region = ty::ReEarlyBound(param.lifetime.id, space, index, param.lifetime.name);
+        for bound in &param.bounds {
+            let bound_region = ast_region_to_region(ccx.tcx, bound);
+            let outlives = ty::Binder(ty::OutlivesPredicate(region, bound_region));
+            result.predicates.push(space, outlives.as_predicate());
+        }
     }
 
-    // Add the bounds not associated with a type parameter
+    // Add in the bounds that appear in the where-clause
+    let where_clause = &ast_generics.where_clause;
     for predicate in &where_clause.predicates {
         match predicate {
             &ast::WherePredicate::BoundPredicate(ref bound_pred) => {
-                let ty = ast_ty_to_ty(ccx, &ExplicitRscope, &*bound_pred.bounded_ty);
+                let ty = ast_ty_to_ty(&ccx.icx(&(base_predicates, ast_generics)),
+                                      &ExplicitRscope,
+                                      &*bound_pred.bounded_ty);
 
                 for bound in &*bound_pred.bounds {
                     match bound {
                         &ast::TyParamBound::TraitTyParamBound(ref poly_trait_ref, _) => {
                             let mut projections = Vec::new();
 
-                            let trait_ref = astconv::instantiate_poly_trait_ref(
-                                ccx,
-                                &ExplicitRscope,
-                                poly_trait_ref,
-                                Some(ty),
-                                &mut projections,
-                            );
+                            let trait_ref =
+                                conv_poly_trait_ref(&ccx.icx(&(base_predicates, ast_generics)),
+                                                    ty,
+                                                    poly_trait_ref,
+                                                    &mut projections);
 
                             result.predicates.push(space, trait_ref.as_predicate());
 
@@ -1512,18 +1798,17 @@ fn ty_generic_bounds<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>,
     return result;
 }
 
-fn ty_generics<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>,
-                        space: subst::ParamSpace,
-                        lifetime_defs: &[ast::LifetimeDef],
-                        types: &[ast::TyParam],
-                        where_clause: &ast::WhereClause,
-                        base_generics: ty::Generics<'tcx>)
+fn ty_generics<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
+                        space: ParamSpace,
+                        ast_generics: &ast::Generics,
+                        base_generics: &ty::Generics<'tcx>)
                         -> ty::Generics<'tcx>
 {
     let tcx = ccx.tcx;
-    let mut result = base_generics;
+    let mut result = base_generics.clone();
 
-    for (i, l) in lifetime_defs.iter().enumerate() {
+    let early_lifetimes = early_bound_lifetimes_from_generics(space, ast_generics);
+    for (i, l) in early_lifetimes.iter().enumerate() {
         let bounds = l.bounds.iter()
                              .map(|l| ast_region_to_region(tcx, l))
                              .collect();
@@ -1532,16 +1817,14 @@ fn ty_generics<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>,
                                            index: i as u32,
                                            def_id: local_def(l.lifetime.id),
                                            bounds: bounds };
-        // debug!("ty_generics: def for region param: {:?}",
-        //        def.repr(tcx));
         result.regions.push(space, def);
     }
 
     assert!(result.types.is_empty_in(space));
 
     // Now create the real type parameters.
-    for (i, param) in types.iter().enumerate() {
-        let def = get_or_create_type_parameter_def(ccx, space, param, i as u32, where_clause);
+    for i in 0..ast_generics.ty_params.len() {
+        let def = get_or_create_type_parameter_def(ccx, ast_generics, space, i as u32);
         debug!("ty_generics: def for type param: {:?}, {:?}", def, space);
         result.types.push(space, def);
     }
@@ -1549,29 +1832,24 @@ fn ty_generics<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>,
     result
 }
 
-fn get_or_create_type_parameter_def<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>,
-                                             space: subst::ParamSpace,
-                                             param: &ast::TyParam,
-                                             index: u32,
-                                             where_clause: &ast::WhereClause)
+fn get_or_create_type_parameter_def<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
+                                             ast_generics: &ast::Generics,
+                                             space: ParamSpace,
+                                             index: u32)
                                              -> ty::TypeParameterDef<'tcx>
 {
+    let param = &ast_generics.ty_params[index as usize];
+
     let tcx = ccx.tcx;
     match tcx.ty_param_defs.borrow().get(&param.id) {
         Some(d) => { return d.clone(); }
         None => { }
     }
 
-    let param_ty = ty::ParamTy::new(space, index, param.ident.name);
-    let bounds = compute_bounds(ccx,
-                                param_ty.to_ty(ccx.tcx),
-                                &param.bounds,
-                                SizedByDefault::Yes,
-                                param.span);
     let default = match param.default {
         None => None,
         Some(ref path) => {
-            let ty = ast_ty_to_ty(ccx, &ExplicitRscope, &**path);
+            let ty = ast_ty_to_ty(&ccx.icx(&()), &ExplicitRscope, &**path);
             let cur_idx = index;
 
             ty::walk_ty(ty, |t| {
@@ -1590,14 +1868,14 @@ fn get_or_create_type_parameter_def<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>,
     };
 
     let object_lifetime_default =
-        compute_object_lifetime_default(ccx, space, index, &param.bounds, where_clause);
+        compute_object_lifetime_default(ccx, param.id,
+                                        &param.bounds, &ast_generics.where_clause);
 
     let def = ty::TypeParameterDef {
         space: space,
         index: index,
         name: param.ident.name,
         def_id: local_def(param.id),
-        bounds: bounds,
         default: default,
         object_lifetime_default: object_lifetime_default,
     };
@@ -1613,15 +1891,14 @@ fn get_or_create_type_parameter_def<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>,
 /// intentionally avoid just asking astconv to convert all the where
 /// clauses into a `ty::Predicate`. This is because that could induce
 /// artificial cycles.
-fn compute_object_lifetime_default<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>,
-                                            space: subst::ParamSpace,
-                                            index: u32,
+fn compute_object_lifetime_default<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
+                                            param_id: ast::NodeId,
                                             param_bounds: &[ast::TyParamBound],
                                             where_clause: &ast::WhereClause)
                                             -> Option<ty::ObjectLifetimeDefault>
 {
     let inline_bounds = from_bounds(ccx, param_bounds);
-    let where_bounds = from_predicates(ccx, space, index, &where_clause.predicates);
+    let where_bounds = from_predicates(ccx, param_id, &where_clause.predicates);
     let all_bounds: HashSet<_> = inline_bounds.into_iter()
                                               .chain(where_bounds.into_iter())
                                               .collect();
@@ -1633,7 +1910,7 @@ fn compute_object_lifetime_default<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>,
                   .map(ty::ObjectLifetimeDefault::Specific)
     };
 
-    fn from_bounds<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>,
+    fn from_bounds<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
                             bounds: &[ast::TyParamBound])
                             -> Vec<ty::Region>
     {
@@ -1643,15 +1920,14 @@ fn from_bounds<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>,
                       ast::TraitTyParamBound(..) =>
                           None,
                       ast::RegionTyParamBound(ref lifetime) =>
-                          Some(astconv::ast_region_to_region(ccx.tcx(), lifetime)),
+                          Some(astconv::ast_region_to_region(ccx.tcx, lifetime)),
                   }
               })
               .collect()
     }
 
-    fn from_predicates<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>,
-                                space: subst::ParamSpace,
-                                index: u32,
+    fn from_predicates<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
+                                param_id: ast::NodeId,
                                 predicates: &[ast::WherePredicate])
                                 -> Vec<ty::Region>
     {
@@ -1660,7 +1936,7 @@ fn from_predicates<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>,
                       match *predicate {
                           ast::WherePredicate::BoundPredicate(ref data) => {
                               if data.bound_lifetimes.len() == 0 &&
-                                  is_param(ccx, &data.bounded_ty, space, index)
+                                  is_param(ccx.tcx, &data.bounded_ty, param_id)
                               {
                                   from_bounds(ccx, &data.bounds).into_iter()
                               } else {
@@ -1675,29 +1951,6 @@ fn from_predicates<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>,
                   })
                   .collect()
     }
-
-    fn is_param(ccx: &CollectCtxt,
-                ast_ty: &ast::Ty,
-                space: subst::ParamSpace,
-                index: u32)
-                -> bool
-    {
-        match ast_ty.node {
-            ast::TyPath(_, id) => {
-                match ccx.tcx.def_map.borrow()[id] {
-                    def::DefTyParam(s, i, _, _) => {
-                        space == s && index == i
-                    }
-                    _ => {
-                        false
-                    }
-                }
-            }
-            _ => {
-                false
-            }
-        }
-    }
 }
 
 enum SizedByDefault { Yes, No }
@@ -1705,25 +1958,25 @@ enum SizedByDefault { Yes, No }
 /// Translate the AST's notion of ty param bounds (which are an enum consisting of a newtyped Ty or
 /// a region) to ty's notion of ty param bounds, which can either be user-defined traits, or the
 /// built-in trait (formerly known as kind): Send.
-fn compute_bounds<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>,
-                           param_ty: ty::Ty<'tcx>,
-                           ast_bounds: &[ast::TyParamBound],
-                           sized_by_default: SizedByDefault,
-                           span: Span)
-                           -> ty::ParamBounds<'tcx>
+fn compute_bounds<'tcx>(astconv: &AstConv<'tcx>,
+                        param_ty: ty::Ty<'tcx>,
+                        ast_bounds: &[ast::TyParamBound],
+                        sized_by_default: SizedByDefault,
+                        span: Span)
+                        -> ty::ParamBounds<'tcx>
 {
-    let mut param_bounds = conv_param_bounds(ccx,
+    let mut param_bounds = conv_param_bounds(astconv,
                                              span,
                                              param_ty,
                                              ast_bounds);
 
     if let SizedByDefault::Yes = sized_by_default {
-        add_unsized_bound(ccx,
+        add_unsized_bound(astconv,
                           &mut param_bounds.builtin_bounds,
                           ast_bounds,
                           span);
 
-        check_bounds_compatible(ccx,
+        check_bounds_compatible(astconv,
                                 param_ty,
                                 &param_bounds,
                                 span);
@@ -1734,35 +1987,72 @@ fn compute_bounds<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>,
     param_bounds
 }
 
-fn check_bounds_compatible<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>,
-                                    param_ty: Ty<'tcx>,
-                                    param_bounds: &ty::ParamBounds<'tcx>,
-                                    span: Span) {
+fn check_bounds_compatible<'tcx>(astconv: &AstConv<'tcx>,
+                                 param_ty: Ty<'tcx>,
+                                 param_bounds: &ty::ParamBounds<'tcx>,
+                                 span: Span) {
+    let tcx = astconv.tcx();
     if !param_bounds.builtin_bounds.contains(&ty::BoundSized) {
         ty::each_bound_trait_and_supertraits(
-            ccx.tcx,
+            tcx,
             &param_bounds.trait_bounds,
             |trait_ref| {
-                let trait_def = ccx.get_trait_def(trait_ref.def_id());
-                if trait_def.bounds.builtin_bounds.contains(&ty::BoundSized) {
-                    span_err!(ccx.tcx.sess, span, E0129,
-                              "incompatible bounds on `{}`, \
-                               bound `{}` does not allow unsized type",
-                              param_ty.user_string(ccx.tcx),
-                              trait_ref.user_string(ccx.tcx));
+                match astconv.get_trait_def(span, trait_ref.def_id()) {
+                    Ok(trait_def) => {
+                        if trait_def.bounds.builtin_bounds.contains(&ty::BoundSized) {
+                            span_err!(tcx.sess, span, E0129,
+                                      "incompatible bounds on `{}`, \
+                                        bound `{}` does not allow unsized type",
+                                      param_ty.user_string(tcx),
+                                      trait_ref.user_string(tcx));
+                        }
+                    }
+                    Err(ErrorReported) => { }
                 }
                 true
             });
     }
 }
 
-fn conv_param_bounds<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>,
+/// Converts a specific TyParamBound from the AST into the
+/// appropriate poly-trait-reference.
+fn poly_trait_ref_from_bound<'tcx>(astconv: &AstConv<'tcx>,
+                                   param_ty: Ty<'tcx>,
+                                   bound: &ast::TyParamBound,
+                                   projections: &mut Vec<ty::PolyProjectionPredicate<'tcx>>)
+                                   -> Option<ty::PolyTraitRef<'tcx>>
+{
+    match *bound {
+        ast::TraitTyParamBound(ref tr, ast::TraitBoundModifier::None) => {
+            Some(conv_poly_trait_ref(astconv, param_ty, tr, projections))
+        }
+        ast::TraitTyParamBound(_, ast::TraitBoundModifier::Maybe) |
+        ast::RegionTyParamBound(_) => {
+            None
+        }
+    }
+}
+
+fn conv_poly_trait_ref<'tcx>(astconv: &AstConv<'tcx>,
+                             param_ty: Ty<'tcx>,
+                             trait_ref: &ast::PolyTraitRef,
+                             projections: &mut Vec<ty::PolyProjectionPredicate<'tcx>>)
+                             -> ty::PolyTraitRef<'tcx>
+{
+    astconv::instantiate_poly_trait_ref(astconv,
+                                        &ExplicitRscope,
+                                        trait_ref,
+                                        Some(param_ty),
+                                        projections)
+}
+
+fn conv_param_bounds<'a,'tcx>(astconv: &AstConv<'tcx>,
                               span: Span,
                               param_ty: ty::Ty<'tcx>,
                               ast_bounds: &[ast::TyParamBound])
                               -> ty::ParamBounds<'tcx>
 {
-    let tcx = ccx.tcx;
+    let tcx = astconv.tcx();
     let astconv::PartitionedBounds {
         builtin_bounds,
         trait_bounds,
@@ -1772,19 +2062,16 @@ fn conv_param_bounds<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>,
     let mut projection_bounds = Vec::new();
 
     let trait_bounds: Vec<ty::PolyTraitRef> =
-        trait_bounds.into_iter()
-        .map(|bound| {
-            astconv::instantiate_poly_trait_ref(ccx,
-                                                &ExplicitRscope,
-                                                bound,
-                                                Some(param_ty),
-                                                &mut projection_bounds)
-        })
-    .collect();
+        trait_bounds.iter()
+                    .map(|bound| conv_poly_trait_ref(astconv,
+                                                     param_ty,
+                                                     *bound,
+                                                     &mut projection_bounds))
+                    .collect();
 
     let region_bounds: Vec<ty::Region> =
         region_bounds.into_iter()
-                     .map(|r| ast_region_to_region(ccx.tcx, r))
+                     .map(|r| ast_region_to_region(tcx, r))
                      .collect();
 
     ty::ParamBounds {
@@ -1796,7 +2083,7 @@ fn conv_param_bounds<'a,'tcx>(ccx: &CollectCtxt<'a,'tcx>,
 }
 
 fn compute_type_scheme_of_foreign_fn_decl<'a, 'tcx>(
-    ccx: &CollectCtxt<'a, 'tcx>,
+    ccx: &CrateCtxt<'a, 'tcx>,
     decl: &ast::FnDecl,
     ast_generics: &ast::Generics,
     abi: abi::Abi)
@@ -1813,17 +2100,17 @@ fn compute_type_scheme_of_foreign_fn_decl<'a, 'tcx>(
         }
     }
 
-    let ty_generics = ty_generics_for_fn_or_method(ccx, ast_generics, ty::Generics::empty());
+    let ty_generics = ty_generics_for_fn(ccx, ast_generics, &ty::Generics::empty());
 
     let rb = BindingRscope::new();
     let input_tys = decl.inputs
                         .iter()
-                        .map(|a| ty_of_arg(ccx, &rb, a, None))
+                        .map(|a| ty_of_arg(&ccx.icx(ast_generics), &rb, a, None))
                         .collect();
 
     let output = match decl.output {
         ast::Return(ref ty) =>
-            ty::FnConverging(ast_ty_to_ty(ccx, &rb, &**ty)),
+            ty::FnConverging(ast_ty_to_ty(&ccx.icx(ast_generics), &rb, &**ty)),
         ast::DefaultReturn(..) =>
             ty::FnConverging(ty::mk_nil(ccx.tcx)),
         ast::NoReturn(..) =>
@@ -1847,9 +2134,9 @@ fn compute_type_scheme_of_foreign_fn_decl<'a, 'tcx>(
     }
 }
 
-fn mk_item_substs<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
+fn mk_item_substs<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                             ty_generics: &ty::Generics<'tcx>)
-                            -> subst::Substs<'tcx>
+                            -> Substs<'tcx>
 {
     let types =
         ty_generics.types.map(
@@ -1859,7 +2146,7 @@ fn mk_item_substs<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
         ty_generics.regions.map(
             |def| def.to_early_bound_region());
 
-    subst::Substs::new(types, regions)
+    Substs::new(types, regions)
 }
 
 /// Verifies that the explicit self type of a method matches the impl
@@ -1869,15 +2156,16 @@ fn mk_item_substs<'a, 'tcx>(ccx: &CollectCtxt<'a, 'tcx>,
 /// comes back to check after the fact that explicit type the user
 /// wrote actually matches what the pre-defined option said.
 fn check_method_self_type<'a, 'tcx, RS:RegionScope>(
-    ccx: &CollectCtxt<'a, 'tcx>,
+    ccx: &CrateCtxt<'a, 'tcx>,
     rs: &RS,
+    method_type: Rc<ty::Method<'tcx>>,
     required_type: Ty<'tcx>,
     explicit_self: &ast::ExplicitSelf,
     body_id: ast::NodeId)
 {
     let tcx = ccx.tcx;
     if let ast::SelfExplicit(ref ast_type, _) = explicit_self.node {
-        let typ = ccx.to_ty(rs, &**ast_type);
+        let typ = ccx.icx(&method_type.predicates).to_ty(rs, &**ast_type);
         let base_type = match typ.sty {
             ty::ty_ptr(tm) | ty::ty_rptr(_, tm) => tm.ty,
             ty::ty_uniq(typ) => typ,
index 6f363faef60396d58ce14004aec6413673b0d4a7..7b43a9fef06dcd36d604f5b42425fd42b3cecf72 100644 (file)
@@ -80,6 +80,7 @@
     E0120,
     E0121,
     E0122,
+    E0123,
     E0124,
     E0127,
     E0128,
index 78f13b37a8238012127ec66826562a994b3d0d42..78dd66c8e7dbbd02e80bc8f197f2d014a2bf990e 100644 (file)
@@ -163,20 +163,16 @@ fn write_substs_to_tcx<'tcx>(tcx: &ty::ctxt<'tcx>,
         tcx.item_substs.borrow_mut().insert(node_id, item_substs);
     }
 }
-fn lookup_def_tcx(tcx:&ty::ctxt, sp: Span, id: ast::NodeId) -> def::Def {
+
+fn lookup_full_def(tcx: &ty::ctxt, sp: Span, id: ast::NodeId) -> def::Def {
     match tcx.def_map.borrow().get(&id) {
-        Some(x) => x.clone(),
-        _ => {
+        Some(x) => x.full_def(),
+        None => {
             span_fatal!(tcx.sess, sp, E0242, "internal error looking up a definition")
         }
     }
 }
 
-fn lookup_def_ccx(ccx: &CrateCtxt, sp: Span, id: ast::NodeId)
-                   -> def::Def {
-    lookup_def_tcx(ccx.tcx, sp, id)
-}
-
 fn require_same_types<'a, 'tcx, M>(tcx: &ty::ctxt<'tcx>,
                                    maybe_infcx: Option<&infer::InferCtxt<'a, 'tcx>>,
                                    t1_is_expected: bool,
index 90ca6a798056bf6e7694e1ea893f76888fa75a9f..1fba4a21ccd376a61ab08fbc52609e1cb9b32b50 100644 (file)
 //! failure, but rather because the target type `Foo<Y>` is itself just
 //! not well-formed. Basically we get to assume well-formedness of all
 //! types involved before considering variance.
+//!
+//! ### Associated types
+//!
+//! Any trait with an associated type is invariant with respect to all
+//! of its inputs. To see why this makes sense, consider what
+//! subtyping for a trait reference means:
+//!
+//!    <T as Trait> <: <U as Trait>
+//!
+//! means that if I know that `T as Trait`,
+//! I also know that `U as
+//! Trait`. Moreover, if you think of it as
+//! dictionary passing style, it means that
+//! a dictionary for `<T as Trait>` is safe
+//! to use where a dictionary for `<U as
+//! Trait>` is expected.
+//!
+//! The problem is that when you can
+//! project types out from `<T as Trait>`,
+//! the relationship to types projected out
+//! of `<U as Trait>` is completely unknown
+//! unless `T==U` (see #21726 for more
+//! details). Making `Trait` invariant
+//! ensures that this is true.
+//!
+//! *Historical note: we used to preserve this invariant another way,
+//! by tweaking the subtyping rules and requiring that when a type `T`
+//! appeared as part of a projection, that was considered an invariant
+//! location, but this version does away with the need for those
+//! somewhat "special-case-feeling" rules.*
+//!
+//! Another related reason is that if we didn't make traits with
+//! associated types invariant, then projection is no longer a
+//! function with a single result. Consider:
+//!
+//! ```
+//! trait Identity { type Out; fn foo(&self); }
+//! impl<T> Identity for T { type Out = T; ... }
+//! ```
+//!
+//! Now if I have `<&'static () as Identity>::Out`, this can be
+//! validly derived as `&'a ()` for any `'a`:
+//!
+//!    <&'a () as Identity> <: <&'static () as Identity>
+//!    if &'static () < : &'a ()   -- Identity is contravariant in Self
+//!    if 'static : 'a             -- Subtyping rules for relations
+//!
+//! This change otoh means that `<'static () as Identity>::Out` is
+//! always `&'static ()` (which might then be upcast to `'a ()`,
+//! separately). This was helpful in solving #21750.
 
 use self::VarianceTerm::*;
 use self::ParamKind::*;
@@ -613,7 +663,18 @@ fn visit_item(&mut self, item: &ast::Item) {
                                 &method.fty.sig,
                                 self.covariant);
                         }
-                        ty::TypeTraitItem(_) => {}
+                        ty::TypeTraitItem(ref data) => {
+                            // Any trait with an associated type is
+                            // invariant with respect to all of its
+                            // inputs. See length discussion in the comment
+                            // on this module.
+                            let projection_ty = ty::mk_projection(tcx,
+                                                                  trait_def.trait_ref.clone(),
+                                                                  data.name);
+                            self.add_constraints_from_ty(&trait_def.generics,
+                                                         projection_ty,
+                                                         self.invariant);
+                        }
                     }
                 }
             }
@@ -893,7 +954,7 @@ fn add_constraints_from_ty(&mut self,
                     trait_def.generics.types.as_slice(),
                     trait_def.generics.regions.as_slice(),
                     trait_ref.substs,
-                    self.invariant);
+                    variance);
             }
 
             ty::ty_trait(ref data) => {
index 4cd6f6551d0885cd8e2448112a44b0e5c56ea55a..2bb4424822a4749c5b58b3537fee5d09cb860823 100644 (file)
@@ -46,7 +46,7 @@ pub fn try_inline(cx: &DocContext, id: ast::NodeId, into: Option<ast::Ident>)
         None => return None,
     };
     let def = match tcx.def_map.borrow().get(&id) {
-        Some(def) => *def,
+        Some(d) => d.full_def(),
         None => return None,
     };
     let did = def.def_id();
@@ -69,7 +69,7 @@ fn try_inline_def(cx: &DocContext, tcx: &ty::ctxt,
     let mut ret = Vec::new();
     let did = def.def_id();
     let inner = match def {
-        def::DefaultImpl(did) => {
+        def::DefTrait(did) => {
             record_extern_fqn(cx, did, clean::TypeTrait);
             clean::TraitItem(build_external_trait(cx, tcx, did))
         }
@@ -308,6 +308,9 @@ fn build_impl(cx: &DocContext, tcx: &ty::ctxt,
                 if method.vis != ast::Public && associated_trait.is_none() {
                     return None
                 }
+                if method.provided_source.is_some() {
+                    return None
+                }
                 let mut item = method.clean(cx);
                 item.inner = match item.inner.clone() {
                     clean::TyMethodItem(clean::TyMethod {
index a3e0cecdd4826092f506d16c2824e013f86c9d87..36d39fa58ba7e5ec7e23a8bcc5cc2c595e59f341 100644 (file)
@@ -479,11 +479,10 @@ impl<'tcx> Clean<TyParam> for ty::TypeParameterDef<'tcx> {
     fn clean(&self, cx: &DocContext) -> TyParam {
         cx.external_typarams.borrow_mut().as_mut().unwrap()
           .insert(self.def_id, self.name.clean(cx));
-        let bounds = self.bounds.clean(cx);
         TyParam {
             name: self.name.clean(cx),
             did: self.def_id,
-            bounds: bounds,
+            bounds: vec![], // these are filled in from the where-clauses
             default: self.default.clean(cx),
         }
     }
@@ -892,9 +891,7 @@ fn has_sized_bound(bounds: &[TyParamBound], cx: &DocContext) -> bool {
         // Bounds in the type_params and lifetimes fields are repeated in the predicates
         // field (see rustc_typeck::collect::ty_generics), so remove them.
         let stripped_typarams = gens.types.get_slice(space).iter().map(|tp| {
-            let mut stp = tp.clone();
-            stp.bounds = ty::ParamBounds::empty();
-            stp.clean(cx)
+            tp.clean(cx)
         }).collect::<Vec<_>>();
         let stripped_lifetimes = gens.regions.get_slice(space).iter().map(|rp| {
             let mut srp = rp.clone();
@@ -1344,8 +1341,6 @@ pub enum Type {
         typarams: Option<Vec<TyParamBound>>,
         did: ast::DefId,
     },
-    // I have no idea how to usefully use this.
-    TyParamBinder(ast::NodeId),
     /// For parameterized types, so the consumer of the JSON don't go
     /// looking for types which don't exist anywhere.
     Generic(String),
@@ -1496,8 +1491,17 @@ fn clean(&self, cx: &DocContext) -> Type {
             TyFixedLengthVec(ref ty, ref e) => FixedVector(box ty.clean(cx),
                                                            e.span.to_src(cx)),
             TyTup(ref tys) => Tuple(tys.clean(cx)),
-            TyPath(ref p, id) => {
-                resolve_type(cx, p.clean(cx), id)
+            TyPath(None, ref p) => {
+                resolve_type(cx, p.clean(cx), self.id)
+            }
+            TyPath(Some(ref qself), ref p) => {
+                let mut trait_path = p.clone();
+                trait_path.segments.pop();
+                Type::QPath {
+                    name: p.segments.last().unwrap().identifier.clean(cx),
+                    self_type: box qself.ty.clean(cx),
+                    trait_: box resolve_type(cx, trait_path.clean(cx), self.id)
+                }
             }
             TyObjectSum(ref lhs, ref bounds) => {
                 let lhs_ty = lhs.clean(cx);
@@ -1512,7 +1516,6 @@ fn clean(&self, cx: &DocContext) -> Type {
             }
             TyBareFn(ref barefn) => BareFunction(box barefn.clean(cx)),
             TyParen(ref ty) => ty.clean(cx),
-            TyQPath(ref qp) => qp.clean(cx),
             TyPolyTraitRef(ref bounds) => {
                 PolyTraitRef(bounds.clean(cx))
             },
@@ -1624,16 +1627,6 @@ fn clean(&self, cx: &DocContext) -> Type {
     }
 }
 
-impl Clean<Type> for ast::QPath {
-    fn clean(&self, cx: &DocContext) -> Type {
-        Type::QPath {
-            name: self.item_path.identifier.clean(cx),
-            self_type: box self.self_type.clean(cx),
-            trait_: box self.trait_ref.clean(cx)
-        }
-    }
-}
-
 #[derive(Clone, RustcEncodable, RustcDecodable, Debug)]
 pub enum StructField {
     HiddenStructField, // inserted later by strip passes
@@ -2392,7 +2385,7 @@ fn resolve_type(cx: &DocContext,
     };
     debug!("searching for {} in defmap", id);
     let def = match tcx.def_map.borrow().get(&id) {
-        Some(&k) => k,
+        Some(k) => k.full_def(),
         None => panic!("unresolved id not in defmap")
     };
 
@@ -2418,7 +2411,6 @@ fn resolve_type(cx: &DocContext,
             ast::TyFloat(ast::TyF64) => return Primitive(F64),
         },
         def::DefTyParam(_, _, _, n) => return Generic(token::get_name(n).to_string()),
-        def::DefTyParamBinder(i) => return TyParamBinder(i),
         _ => {}
     };
     let did = register_def(&*cx, def);
@@ -2430,7 +2422,7 @@ fn register_def(cx: &DocContext, def: def::Def) -> ast::DefId {
         def::DefFn(i, _) => (i, TypeFunction),
         def::DefTy(i, false) => (i, TypeTypedef),
         def::DefTy(i, true) => (i, TypeEnum),
-        def::DefaultImpl(i) => (i, TypeTrait),
+        def::DefTrait(i) => (i, TypeTrait),
         def::DefStruct(i) => (i, TypeStruct),
         def::DefMod(i) => (i, TypeModule),
         def::DefStatic(i, _) => (i, TypeStatic),
@@ -2459,7 +2451,7 @@ fn resolve_use_source(cx: &DocContext, path: Path, id: ast::NodeId) -> ImportSou
 
 fn resolve_def(cx: &DocContext, id: ast::NodeId) -> Option<ast::DefId> {
     cx.tcx_opt().and_then(|tcx| {
-        tcx.def_map.borrow().get(&id).map(|&def| register_def(cx, def))
+        tcx.def_map.borrow().get(&id).map(|d| register_def(cx, d.full_def()))
     })
 }
 
index f862970446c14909dd0a2a6568b0c923a3b1fa25..113a622b07ae47cd2430288adc66c86313c02730 100644 (file)
@@ -9,6 +9,7 @@
 // except according to those terms.
 pub use self::MaybeTyped::*;
 
+use rustc_lint;
 use rustc_driver::driver;
 use rustc::session::{self, config};
 use rustc::session::config::UnstableFeatures;
@@ -114,6 +115,7 @@ pub fn run_core(search_paths: SearchPaths, cfgs: Vec<String>, externs: Externs,
 
     let sess = session::build_session_(sessopts, cpath,
                                        span_diagnostic_handler);
+    rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess));
 
     let cfg = config::build_configuration(&sess);
 
index 11d9ecac14dd06a89d5d53c54890f8903d3d587e..03a2d708ee43aa5b742c2efc9c19aacdf4764ecf 100644 (file)
@@ -454,9 +454,6 @@ fn tybounds(w: &mut fmt::Formatter,
 impl fmt::Display for clean::Type {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         match *self {
-            clean::TyParamBinder(id) => {
-                f.write_str(&cache().typarams[ast_util::local_def(id)])
-            }
             clean::Generic(ref name) => {
                 f.write_str(name)
             }
index f9e0948d7bc8a0ee6d707bb349d71d3592bf32f4..fcad91bf14ad99f245863c820c6885483b095d27 100644 (file)
@@ -42,6 +42,7 @@
 extern crate rustc_trans;
 extern crate rustc_driver;
 extern crate rustc_resolve;
+extern crate rustc_lint;
 extern crate serialize;
 extern crate syntax;
 extern crate "test" as testing;
index bf14b86ebd1e39e21189cd0097dff9072a15fcd7..43e8f44244e788c258b5f3a0d0b6873d2cd317ef 100644 (file)
 use std::dynamic_lib::DynamicLibrary;
 use std::old_io::{Command, TempDir};
 use std::old_io;
-use std::env;
+use std::os;
 use std::str;
 use std::thread;
 use std::thunk::Thunk;
 
 use std::collections::{HashSet, HashMap};
 use testing;
+use rustc_lint;
 use rustc::session::{self, config};
 use rustc::session::config::get_unstable_features_setting;
 use rustc::session::search_paths::{SearchPaths, PathKind};
@@ -46,7 +47,7 @@ pub fn run(input: &str,
     let input = config::Input::File(input_path.clone());
 
     let sessopts = config::Options {
-        maybe_sysroot: Some(env::current_exe().unwrap().dir_path().dir_path()),
+        maybe_sysroot: Some(os::self_exe_name().unwrap().dir_path().dir_path()),
         search_paths: libs.clone(),
         crate_types: vec!(config::CrateTypeDylib),
         externs: externs.clone(),
@@ -62,6 +63,7 @@ pub fn run(input: &str,
     let sess = session::build_session_(sessopts,
                                       Some(input_path.clone()),
                                       span_diagnostic_handler);
+    rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess));
 
     let mut cfg = config::build_configuration(&sess);
     cfg.extend(config::parse_cfgspecs(cfgs).into_iter());
@@ -113,7 +115,7 @@ fn runtest(test: &str, cratename: &str, libs: SearchPaths,
     let input = config::Input::Str(test.to_string());
 
     let sessopts = config::Options {
-        maybe_sysroot: Some(env::current_exe().unwrap().dir_path().dir_path()),
+        maybe_sysroot: Some(os::self_exe_name().unwrap().dir_path().dir_path()),
         search_paths: libs,
         crate_types: vec!(config::CrateTypeExecutable),
         output_types: vec!(config::OutputTypeExe),
@@ -165,6 +167,7 @@ fn runtest(test: &str, cratename: &str, libs: SearchPaths,
     let sess = session::build_session_(sessopts,
                                        None,
                                        span_diagnostic_handler);
+    rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess));
 
     let outdir = TempDir::new("rustdoctest").ok().expect("rustdoc needs a tempdir");
     let out = Some(outdir.path().clone());
index 9f5e3be9e3229a71711e60e1dcdcf1d0dcc1215c..3e998166397bc5deb38e2a30bb6497c0da82e63c 100644 (file)
@@ -196,7 +196,7 @@ fn resolve_id(&mut self, id: ast::NodeId, renamed: Option<ast::Ident>,
             Some(tcx) => tcx,
             None => return false
         };
-        let def = (*tcx.def_map.borrow())[id].def_id();
+        let def = tcx.def_map.borrow()[id].def_id();
         if !ast_util::is_local(def) { return false }
         let analysis = match self.analysis {
             Some(analysis) => analysis, None => return false
index a0f42815b439611b61fd1e07a748b69adaa2cef4..14930f91c9152f02335e731e2ab3bdbdcbd01b39 100644 (file)
@@ -3074,19 +3074,19 @@ fn test_read_array() {
     #[test]
     fn test_decode_array() {
         let v: Vec<()> = super::decode("[]").unwrap();
-        assert_eq!(v, vec![]);
+        assert_eq!(v, []);
 
         let v: Vec<()> = super::decode("[null]").unwrap();
-        assert_eq!(v, vec![()]);
+        assert_eq!(v, [()]);
 
         let v: Vec<bool> = super::decode("[true]").unwrap();
-        assert_eq!(v, vec![true]);
+        assert_eq!(v, [true]);
 
         let v: Vec<int> = super::decode("[3, 1]").unwrap();
-        assert_eq!(v, vec![3, 1]);
+        assert_eq!(v, [3, 1]);
 
         let v: Vec<Vec<uint>> = super::decode("[[3], [1, 2]]").unwrap();
-        assert_eq!(v, vec![vec![3], vec![1, 2]]);
+        assert_eq!(v, [vec![3], vec![1, 2]]);
     }
 
     #[test]
@@ -3945,9 +3945,7 @@ fn test_to_json() {
 
     #[test]
     fn test_encode_hashmap_with_arbitrary_key() {
-        use std::old_io::Writer;
         use std::collections::HashMap;
-        use std::fmt;
         #[derive(PartialEq, Eq, Hash, RustcEncodable)]
         struct ArbitraryType(uint);
         let mut hm: HashMap<ArbitraryType, bool> = HashMap::new();
index df2fb538c0a5080d034e72fd0fac78f5cb71cf25..faddbba50590f9ce1a87499ef7db2a299e21b038 100644 (file)
@@ -1212,7 +1212,7 @@ impl<K, V, S> Debug for HashMap<K, V, S>
     where K: Eq + Hash + Debug, V: Debug, S: HashState
 {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        try!(write!(f, "HashMap {{"));
+        try!(write!(f, "{{"));
 
         for (i, (k, v)) in self.iter().enumerate() {
             if i != 0 { try!(write!(f, ", ")); }
@@ -1999,9 +1999,9 @@ fn test_show() {
 
         let map_str = format!("{:?}", map);
 
-        assert!(map_str == "HashMap {1: 2, 3: 4}" ||
-                map_str == "HashMap {3: 4, 1: 2}");
-        assert_eq!(format!("{:?}", empty), "HashMap {}");
+        assert!(map_str == "{1: 2, 3: 4}" ||
+                map_str == "{3: 4, 1: 2}");
+        assert_eq!(format!("{:?}", empty), "{}");
     }
 
     #[test]
index e0631a64d44b127048402f0667195daed7e4ffc6..cdc0ebd76aada5d823709363e9c96203211cf0dd 100644 (file)
@@ -598,7 +598,7 @@ impl<T, S> fmt::Debug for HashSet<T, S>
           S: HashState
 {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        try!(write!(f, "HashSet {{"));
+        try!(write!(f, "{{"));
 
         for (i, x) in self.iter().enumerate() {
             if i != 0 { try!(write!(f, ", ")); }
@@ -1186,8 +1186,8 @@ fn test_show() {
 
         let set_str = format!("{:?}", set);
 
-        assert!(set_str == "HashSet {1, 2}" || set_str == "HashSet {2, 1}");
-        assert_eq!(format!("{:?}", empty), "HashSet {}");
+        assert!(set_str == "{1, 2}" || set_str == "{2, 1}");
+        assert_eq!(format!("{:?}", empty), "{}");
     }
 
     #[test]
index 7513cb8a61c7c63f77f20c7f2bb813f5b049b786..4c03d8915eb8a04ca0909e022739eb6c38ade22a 100644 (file)
@@ -23,7 +23,7 @@
 use ops::{Deref, DerefMut, Drop};
 use option::Option;
 use option::Option::{Some, None};
-use ptr::{self, PtrExt, copy_nonoverlapping_memory, Unique, zero_memory};
+use ptr::{self, PtrExt, Unique};
 use rt::heap::{allocate, deallocate, EMPTY};
 use collections::hash_state::HashState;
 
@@ -477,8 +477,8 @@ pub fn full(&self) -> &FullBucket<K, V, M> {
     pub fn shift(mut self) -> Option<GapThenFull<K, V, M>> {
         unsafe {
             *self.gap.raw.hash = mem::replace(&mut *self.full.raw.hash, EMPTY_BUCKET);
-            copy_nonoverlapping_memory(self.gap.raw.key, self.full.raw.key, 1);
-            copy_nonoverlapping_memory(self.gap.raw.val, self.full.raw.val, 1);
+            ptr::copy_nonoverlapping(self.gap.raw.key, self.full.raw.key, 1);
+            ptr::copy_nonoverlapping(self.gap.raw.val, self.full.raw.val, 1);
         }
 
         let FullBucket { raw: prev_raw, idx: prev_idx, .. } = self.full;
@@ -637,7 +637,7 @@ fn first_bucket_raw(&self) -> RawBucket<K, V> {
     pub fn new(capacity: usize) -> RawTable<K, V> {
         unsafe {
             let ret = RawTable::new_uninitialized(capacity);
-            zero_memory(*ret.hashes, capacity);
+            ptr::write_bytes(*ret.hashes, 0, capacity);
             ret
         }
     }
index fcae8e791604dd87011296eb52e2c9b8e6b431ae..babae3b3019ec18c33d01b2749c4395d4ae7bd13 100644 (file)
@@ -21,6 +21,7 @@
 use mem;
 use env;
 use str;
+use os;
 
 pub struct DynamicLibrary {
     handle: *mut u8
@@ -102,7 +103,7 @@ fn separator() -> u8 {
     /// process
     pub fn search_path() -> Vec<Path> {
         match env::var_os(DynamicLibrary::envvar()) {
-            Some(var) => env::split_paths(&var).collect(),
+            Some(var) => os::split_paths(var.to_str().unwrap()),
             None => Vec::new(),
         }
     }
index 0e1f5f2ba029403246b87e42491e094bb6bfc720..e2849ec92e08835f007cdbaba0e1901b84a3f477 100644 (file)
@@ -21,7 +21,8 @@
 use error::Error;
 use ffi::{OsString, AsOsStr};
 use fmt;
-use old_io::IoResult;
+use io;
+use path::{AsPath, PathBuf};
 use sync::atomic::{AtomicIsize, ATOMIC_ISIZE_INIT, Ordering};
 use sync::{StaticMutex, MUTEX_INIT};
 use sys::os as os_imp;
@@ -46,7 +47,7 @@
 /// let p = env::current_dir().unwrap();
 /// println!("The current directory is {}", p.display());
 /// ```
-pub fn current_dir() -> IoResult<Path> {
+pub fn current_dir() -> io::Result<PathBuf> {
     os_imp::getcwd()
 }
 
@@ -57,14 +58,14 @@ pub fn current_dir() -> IoResult<Path> {
 ///
 /// ```rust
 /// use std::env;
-/// use std::old_path::Path;
+/// use std::path::Path;
 ///
 /// let root = Path::new("/");
 /// assert!(env::set_current_dir(&root).is_ok());
 /// println!("Successfully changed working directory to {}!", root.display());
 /// ```
-pub fn set_current_dir(p: &Path) -> IoResult<()> {
-    os_imp::chdir(p)
+pub fn set_current_dir<P: AsPath + ?Sized>(p: &P) -> io::Result<()> {
+    os_imp::chdir(p.as_path())
 }
 
 static ENV_LOCK: StaticMutex = MUTEX_INIT;
@@ -280,8 +281,8 @@ pub fn split_paths<T: AsOsStr + ?Sized>(unparsed: &T) -> SplitPaths {
 }
 
 impl<'a> Iterator for SplitPaths<'a> {
-    type Item = Path;
-    fn next(&mut self) -> Option<Path> { self.inner.next() }
+    type Item = PathBuf;
+    fn next(&mut self) -> Option<PathBuf> { self.inner.next() }
     fn size_hint(&self) -> (usize, Option<usize>) { self.inner.size_hint() }
 }
 
@@ -305,10 +306,11 @@ pub struct JoinPathsError {
 ///
 /// ```rust
 /// use std::env;
+/// use std::path::PathBuf;
 ///
 /// if let Some(path) = env::var_os("PATH") {
 ///     let mut paths = env::split_paths(&path).collect::<Vec<_>>();
-///     paths.push(Path::new("/home/xyz/bin"));
+///     paths.push(PathBuf::new("/home/xyz/bin"));
 ///     let new_path = env::join_paths(paths.iter()).unwrap();
 ///     env::set_var("PATH", &new_path);
 /// }
@@ -355,7 +357,7 @@ fn description(&self) -> &str { self.inner.description() }
 ///     None => println!("Impossible to get your home dir!")
 /// }
 /// ```
-pub fn home_dir() -> Option<Path> {
+pub fn home_dir() -> Option<PathBuf> {
     os_imp::home_dir()
 }
 
@@ -369,7 +371,7 @@ pub fn home_dir() -> Option<Path> {
 /// On Windows, returns the value of, in order, the 'TMP', 'TEMP',
 /// 'USERPROFILE' environment variable  if any are set and not the empty
 /// string. Otherwise, tmpdir returns the path to the Windows directory.
-pub fn temp_dir() -> Path {
+pub fn temp_dir() -> PathBuf {
     os_imp::temp_dir()
 }
 
@@ -396,7 +398,7 @@ pub fn temp_dir() -> Path {
 ///     Err(e) => println!("failed to get current exe path: {}", e),
 /// };
 /// ```
-pub fn current_exe() -> IoResult<Path> {
+pub fn current_exe() -> io::Result<PathBuf> {
     os_imp::current_exe()
 }
 
@@ -825,6 +827,7 @@ mod tests {
     use iter::repeat;
     use rand::{self, Rng};
     use ffi::{OsString, OsStr};
+    use path::PathBuf;
 
     fn make_rand_name() -> OsString {
         let mut rng = rand::thread_rng();
@@ -924,7 +927,7 @@ fn test() {
     fn split_paths_windows() {
         fn check_parse(unparsed: &str, parsed: &[&str]) -> bool {
             split_paths(unparsed).collect::<Vec<_>>() ==
-                parsed.iter().map(|s| Path::new(*s)).collect::<Vec<_>>()
+                parsed.iter().map(|s| PathBuf::new(*s)).collect::<Vec<_>>()
         }
 
         assert!(check_parse("", &mut [""]));
@@ -944,7 +947,7 @@ fn check_parse(unparsed: &str, parsed: &[&str]) -> bool {
     fn split_paths_unix() {
         fn check_parse(unparsed: &str, parsed: &[&str]) -> bool {
             split_paths(unparsed).collect::<Vec<_>>() ==
-                parsed.iter().map(|s| Path::new(*s)).collect::<Vec<_>>()
+                parsed.iter().map(|s| PathBuf::new(*s)).collect::<Vec<_>>()
         }
 
         assert!(check_parse("", &mut [""]));
diff --git a/src/libstd/fs.rs b/src/libstd/fs.rs
deleted file mode 100644 (file)
index 98c1b50..0000000
+++ /dev/null
@@ -1,1503 +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.
-
-//! Filesystem manipulation operations
-//!
-//! This module contains basic methods to manipulate the contents of the local
-//! filesystem. All methods in this module represent cross-platform filesystem
-//! operations. Extra platform-specific functionality can be found in the
-//! extension traits of `std::os::$platform`.
-
-#![unstable(feature = "fs")]
-
-use core::prelude::*;
-
-use io::{self, Error, ErrorKind, SeekFrom, Seek, Read, Write};
-use path::{AsPath, Path, PathBuf};
-use sys::fs2 as fs_imp;
-use sys_common::{AsInnerMut, FromInner, AsInner};
-use vec::Vec;
-
-/// A reference to an open file on the filesystem.
-///
-/// An instance of a `File` can be read and/or written depending on what options
-/// it was opened with. Files also implement `Seek` to alter the logical cursor
-/// that the file contains internally.
-///
-/// # Example
-///
-/// ```no_run
-/// use std::io::prelude::*;
-/// use std::fs::File;
-///
-/// # fn foo() -> std::io::Result<()> {
-/// let mut f = try!(File::create("foo.txt"));
-/// try!(f.write_all(b"Hello, world!"));
-///
-/// let mut f = try!(File::open("foo.txt"));
-/// let mut s = String::new();
-/// try!(f.read_to_string(&mut s));
-/// assert_eq!(s, "Hello, world!");
-/// # Ok(())
-/// # }
-/// ```
-pub struct File {
-    inner: fs_imp::File,
-    path: PathBuf,
-}
-
-/// Metadata information about a file.
-///
-/// This structure is returned from the `metadata` function or method and
-/// represents known metadata about a file such as its permissions, size,
-/// modification times, etc.
-pub struct Metadata(fs_imp::FileAttr);
-
-/// Iterator over the entries in a directory.
-///
-/// This iterator is returned from the `read_dir` function of this module and
-/// will yield instances of `io::Result<DirEntry>`. Through a `DirEntry`
-/// information like the entry's path and possibly other metadata can be
-/// learned.
-pub struct ReadDir(fs_imp::ReadDir);
-
-/// Entries returned by the `ReadDir` iterator.
-///
-/// An instance of `DirEntry` represents an entry inside of a directory on the
-/// filesystem. Each entry can be inspected via methods to learn about the full
-/// path or possibly other metadata through per-platform extension traits.
-pub struct DirEntry(fs_imp::DirEntry);
-
-/// An iterator that recursively walks over the contents of a directory.
-pub struct WalkDir {
-    cur: Option<ReadDir>,
-    stack: Vec<io::Result<ReadDir>>,
-}
-
-/// Options and flags which can be used to configure how a file is opened.
-///
-/// This builder exposes the ability to configure how a `File` is opened and
-/// what operations are permitted on the open file. The `File::open` and
-/// `File::create` methods are aliases for commonly used options using this
-/// builder.
-#[derive(Clone)]
-pub struct OpenOptions(fs_imp::OpenOptions);
-
-/// Representation of the various permissions on a file.
-///
-/// This module only currently provides one bit of information, `readonly`,
-/// which is exposed on all currently supported platforms. Unix-specific
-/// functionality, such as mode bits, is available through the
-/// `os::unix::PermissionsExt` trait.
-#[derive(Clone, PartialEq, Eq, Debug)]
-pub struct Permissions(fs_imp::FilePermissions);
-
-impl File {
-    /// Attempts to open a file in read-only mode.
-    ///
-    /// See the `OpenOptions::open` method for more details.
-    ///
-    /// # Errors
-    ///
-    /// This function will return an error if `path` does not already exist.
-    /// Other errors may also be returned according to `OpenOptions::open`.
-    pub fn open<P: AsPath + ?Sized>(path: &P) -> io::Result<File> {
-        OpenOptions::new().read(true).open(path)
-    }
-
-    /// Open a file in write-only mode.
-    ///
-    /// This function will create a file if it does not exist,
-    /// and will truncate it if it does.
-    ///
-    /// See the `OpenOptions::open` function for more details.
-    pub fn create<P: AsPath + ?Sized>(path: &P) -> io::Result<File> {
-        OpenOptions::new().write(true).create(true).truncate(true).open(path)
-    }
-
-    /// Returns the original path that was used to open this file.
-    pub fn path(&self) -> Option<&Path> {
-        Some(&self.path)
-    }
-
-    /// Attempt to sync all OS-internal metadata to disk.
-    ///
-    /// This function will attempt to ensure that all in-core data reaches the
-    /// filesystem before returning.
-    pub fn sync_all(&self) -> io::Result<()> {
-        self.inner.fsync()
-    }
-
-    /// This function is similar to `sync_all`, except that it may not
-    /// synchronize file metadata to the filesystem.
-    ///
-    /// This is intended for use cases that must synchronize content, but don't
-    /// need the metadata on disk. The goal of this method is to reduce disk
-    /// operations.
-    ///
-    /// Note that some platforms may simply implement this in terms of
-    /// `sync_all`.
-    pub fn sync_data(&self) -> io::Result<()> {
-        self.inner.datasync()
-    }
-
-    /// Truncates or extends the underlying file, updating the size of
-    /// this file to become `size`.
-    ///
-    /// If the `size` is less than the current file's size, then the file will
-    /// be shrunk. If it is greater than the current file's size, then the file
-    /// will be extended to `size` and have all of the intermediate data filled
-    /// in with 0s.
-    pub fn set_len(&self, size: u64) -> io::Result<()> {
-        self.inner.truncate(size)
-    }
-
-    /// Queries information about the underlying file.
-    pub fn metadata(&self) -> io::Result<Metadata> {
-        self.inner.file_attr().map(Metadata)
-    }
-}
-
-impl AsInner<fs_imp::File> for File {
-    fn as_inner(&self) -> &fs_imp::File { &self.inner }
-}
-impl Read for File {
-    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
-        self.inner.read(buf)
-    }
-}
-impl Write for File {
-    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
-        self.inner.write(buf)
-    }
-    fn flush(&mut self) -> io::Result<()> { self.inner.flush() }
-}
-impl Seek for File {
-    fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {
-        self.inner.seek(pos)
-    }
-}
-impl<'a> Read for &'a File {
-    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
-        self.inner.read(buf)
-    }
-}
-impl<'a> Write for &'a File {
-    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
-        self.inner.write(buf)
-    }
-    fn flush(&mut self) -> io::Result<()> { self.inner.flush() }
-}
-impl<'a> Seek for &'a File {
-    fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {
-        self.inner.seek(pos)
-    }
-}
-
-impl OpenOptions {
-    /// Creates a blank net set of options ready for configuration.
-    ///
-    /// All options are initially set to `false`.
-    pub fn new() -> OpenOptions {
-        OpenOptions(fs_imp::OpenOptions::new())
-    }
-
-    /// Set the option for read access.
-    ///
-    /// This option, when true, will indicate that the file should be
-    /// `read`-able if opened.
-    pub fn read(&mut self, read: bool) -> &mut OpenOptions {
-        self.0.read(read); self
-    }
-
-    /// Set the option for write access.
-    ///
-    /// This option, when true, will indicate that the file should be
-    /// `write`-able if opened.
-    pub fn write(&mut self, write: bool) -> &mut OpenOptions {
-        self.0.write(write); self
-    }
-
-    /// Set the option for the append mode.
-    ///
-    /// This option, when true, means that writes will append to a file instead
-    /// of overwriting previous contents.
-    pub fn append(&mut self, append: bool) -> &mut OpenOptions {
-        self.0.append(append); self
-    }
-
-    /// Set the option for truncating a previous file.
-    ///
-    /// If a file is successfully opened with this option set it will truncate
-    /// the file to 0 length if it already exists.
-    pub fn truncate(&mut self, truncate: bool) -> &mut OpenOptions {
-        self.0.truncate(truncate); self
-    }
-
-    /// Set the option for creating a new file.
-    ///
-    /// This option indicates whether a new file will be created if the file
-    /// does not yet already exist.
-    pub fn create(&mut self, create: bool) -> &mut OpenOptions {
-        self.0.create(create); self
-    }
-
-    /// Open a file at `path` with the options specified by `self`.
-    ///
-    /// # Errors
-    ///
-    /// This function will return an error under a number of different
-    /// circumstances, to include but not limited to:
-    ///
-    /// * Opening a file that does not exist with read access.
-    /// * Attempting to open a file with access that the user lacks
-    ///   permissions for
-    /// * Filesystem-level errors (full disk, etc)
-    pub fn open<P: AsPath + ?Sized>(&self, path: &P) -> io::Result<File> {
-        let path = path.as_path();
-        let inner = try!(fs_imp::File::open(path, &self.0));
-
-        // On *BSD systems, we can open a directory as a file and read from
-        // it: fd=open("/tmp", O_RDONLY); read(fd, buf, N); due to an old
-        // tradition before the introduction of opendir(3).  We explicitly
-        // reject it because there are few use cases.
-        if cfg!(not(any(target_os = "linux", target_os = "android"))) &&
-           try!(inner.file_attr()).is_dir() {
-            Err(Error::new(ErrorKind::InvalidInput, "is a directory", None))
-        } else {
-            Ok(File { path: path.to_path_buf(), inner: inner })
-        }
-    }
-}
-impl AsInnerMut<fs_imp::OpenOptions> for OpenOptions {
-    fn as_inner_mut(&mut self) -> &mut fs_imp::OpenOptions { &mut self.0 }
-}
-
-impl Metadata {
-    /// Returns whether this metadata is for a directory.
-    pub fn is_dir(&self) -> bool { self.0.is_dir() }
-
-    /// Returns whether this metadata is for a regular file.
-    pub fn is_file(&self) -> bool { self.0.is_file() }
-
-    /// Returns the size of the file, in bytes, this metadata is for.
-    pub fn len(&self) -> u64 { self.0.size() }
-
-    /// Returns the permissions of the file this metadata is for.
-    pub fn permissions(&self) -> Permissions {
-        Permissions(self.0.perm())
-    }
-
-    /// Returns the most recent access time for a file.
-    ///
-    /// The return value is in milliseconds since the epoch.
-    pub fn accessed(&self) -> u64 { self.0.accessed() }
-
-    /// Returns the most recent modification time for a file.
-    ///
-    /// The return value is in milliseconds since the epoch.
-    pub fn modified(&self) -> u64 { self.0.modified() }
-}
-
-impl Permissions {
-    /// Returns whether these permissions describe a readonly file.
-    pub fn readonly(&self) -> bool { self.0.readonly() }
-
-    /// Modify the readonly flag for this set of permissions.
-    ///
-    /// This operation does **not** modify the filesystem. To modify the
-    /// filesystem use the `fs::set_permissions` function.
-    pub fn set_readonly(&mut self, readonly: bool) {
-        self.0.set_readonly(readonly)
-    }
-}
-
-impl FromInner<fs_imp::FilePermissions> for Permissions {
-    fn from_inner(f: fs_imp::FilePermissions) -> Permissions {
-        Permissions(f)
-    }
-}
-
-impl Iterator for ReadDir {
-    type Item = io::Result<DirEntry>;
-
-    fn next(&mut self) -> Option<io::Result<DirEntry>> {
-        self.0.next().map(|entry| entry.map(DirEntry))
-    }
-}
-
-impl DirEntry {
-    /// Returns the full path to the file that this entry represents.
-    ///
-    /// The full path is created by joining the original path to `read_dir` or
-    /// `walk_dir` with the filename of this entry.
-    pub fn path(&self) -> PathBuf { self.0.path() }
-}
-
-/// Remove a file from the underlying filesystem.
-///
-/// # Example
-///
-/// ```rust,no_run
-/// use std::fs;
-///
-/// fs::remove_file("/some/file/path.txt");
-/// ```
-///
-/// Note that, just because an unlink call was successful, it is not
-/// guaranteed that a file is immediately deleted (e.g. depending on
-/// platform, other open file descriptors may prevent immediate removal).
-///
-/// # Errors
-///
-/// This function will return an error if `path` points to a directory, if the
-/// user lacks permissions to remove the file, or if some other filesystem-level
-/// error occurs.
-pub fn remove_file<P: AsPath + ?Sized>(path: &P) -> io::Result<()> {
-    let path = path.as_path();
-    let e = match fs_imp::unlink(path) {
-        Ok(()) => return Ok(()),
-        Err(e) => e,
-    };
-    if !cfg!(windows) { return Err(e) }
-
-    // On unix, a readonly file can be successfully removed. On windows,
-    // however, it cannot. To keep the two platforms in line with
-    // respect to their behavior, catch this case on windows, attempt to
-    // change it to read-write, and then remove the file.
-    if e.kind() != ErrorKind::PermissionDenied { return Err(e) }
-
-    let attr = match metadata(path) { Ok(a) => a, Err(..) => return Err(e) };
-    let mut perms = attr.permissions();
-    if !perms.readonly() { return Err(e) }
-    perms.set_readonly(false);
-
-    if set_permissions(path, perms).is_err() { return Err(e) }
-    if fs_imp::unlink(path).is_ok() { return Ok(()) }
-
-    // Oops, try to put things back the way we found it
-    let _ = set_permissions(path, attr.permissions());
-    Err(e)
-}
-
-/// Given a path, query the file system to get information about a file,
-/// directory, etc.
-///
-/// This function will traverse soft links to query information about the
-/// destination file.
-///
-/// # Example
-///
-/// ```rust,no_run
-/// # fn foo() -> std::io::Result<()> {
-/// use std::fs;
-///
-/// let attr = try!(fs::metadata("/some/file/path.txt"));
-/// // inspect attr ...
-/// # Ok(())
-/// # }
-/// ```
-///
-/// # Errors
-///
-/// This function will return an error if the user lacks the requisite
-/// permissions to perform a `metadata` call on the given `path` or if there
-/// is no entry in the filesystem at the provided path.
-pub fn metadata<P: AsPath + ?Sized>(path: &P) -> io::Result<Metadata> {
-    fs_imp::stat(path.as_path()).map(Metadata)
-}
-
-/// Rename a file or directory to a new name.
-///
-/// # Example
-///
-/// ```rust,no_run
-/// use std::fs;
-///
-/// fs::rename("foo", "bar");
-/// ```
-///
-/// # Errors
-///
-/// This function will return an error if the provided `from` doesn't exist, if
-/// the process lacks permissions to view the contents, if `from` and `to`
-/// reside on separate filesystems, or if some other intermittent I/O error
-/// occurs.
-pub fn rename<P: AsPath + ?Sized, Q: AsPath + ?Sized>(from: &P, to: &Q)
-                                                      -> io::Result<()> {
-    fs_imp::rename(from.as_path(), to.as_path())
-}
-
-/// Copies the contents of one file to another. This function will also
-/// copy the permission bits of the original file to the destination file.
-///
-/// This function will **overwrite** the contents of `to`.
-///
-/// Note that if `from` and `to` both point to the same file, then the file
-/// will likely get truncated by this operation.
-///
-/// # Example
-///
-/// ```rust
-/// use std::fs;
-///
-/// fs::copy("foo.txt", "bar.txt");
-/// ```
-///
-/// # Errors
-///
-/// This function will return an error in the following situations, but is not
-/// limited to just these cases:
-///
-/// * The `from` path is not a file
-/// * The `from` file does not exist
-/// * The current process does not have the permission rights to access
-///   `from` or write `to`
-pub fn copy<P: AsPath + ?Sized, Q: AsPath + ?Sized>(from: &P, to: &Q)
-                                                    -> io::Result<u64> {
-    let from = from.as_path();
-    if !from.is_file() {
-        return Err(Error::new(ErrorKind::MismatchedFileTypeForOperation,
-                              "the source path is not an existing file",
-                              None))
-    }
-
-    let mut reader = try!(File::open(from));
-    let mut writer = try!(File::create(to));
-    let perm = try!(reader.metadata()).permissions();
-
-    let ret = try!(io::copy(&mut reader, &mut writer));
-    try!(set_permissions(to, perm));
-    Ok(ret)
-}
-
-/// Creates a new hard link on the filesystem.
-///
-/// The `dst` path will be a link pointing to the `src` path. Note that systems
-/// often require these two paths to both be located on the same filesystem.
-pub fn hard_link<P: AsPath + ?Sized, Q: AsPath + ?Sized>(src: &P, dst: &Q)
-                                                         -> io::Result<()> {
-    fs_imp::link(src.as_path(), dst.as_path())
-}
-
-/// Creates a new soft link on the filesystem.
-///
-/// The `dst` path will be a soft link pointing to the `src` path.
-pub fn soft_link<P: AsPath + ?Sized, Q: AsPath + ?Sized>(src: &P, dst: &Q)
-                                                         -> io::Result<()> {
-    fs_imp::symlink(src.as_path(), dst.as_path())
-}
-
-/// Reads a soft link, returning the file that the link points to.
-///
-/// # Errors
-///
-/// This function will return an error on failure. Failure conditions include
-/// reading a file that does not exist or reading a file that is not a soft
-/// link.
-pub fn read_link<P: AsPath + ?Sized>(path: &P) -> io::Result<PathBuf> {
-    fs_imp::readlink(path.as_path())
-}
-
-/// Create a new, empty directory at the provided path
-///
-/// # Example
-///
-/// ```rust
-/// use std::fs;
-///
-/// fs::create_dir("/some/dir");
-/// ```
-///
-/// # Errors
-///
-/// This function will return an error if the user lacks permissions to make a
-/// new directory at the provided `path`, or if the directory already exists.
-pub fn create_dir<P: AsPath + ?Sized>(path: &P) -> io::Result<()> {
-    fs_imp::mkdir(path.as_path())
-}
-
-/// Recursively create a directory and all of its parent components if they
-/// are missing.
-///
-/// # Errors
-///
-/// This function will fail if any directory in the path specified by `path`
-/// does not already exist and it could not be created otherwise. The specific
-/// error conditions for when a directory is being created (after it is
-/// determined to not exist) are outlined by `fs::create_dir`.
-pub fn create_dir_all<P: AsPath + ?Sized>(path: &P) -> io::Result<()> {
-    let path = path.as_path();
-    if path.is_dir() { return Ok(()) }
-    match path.parent() {
-        Some(p) if p != path => try!(create_dir_all(p)),
-        _ => {}
-    }
-    create_dir(path)
-}
-
-/// Remove an existing, empty directory
-///
-/// # Example
-///
-/// ```rust
-/// use std::fs;
-///
-/// fs::remove_dir("/some/dir");
-/// ```
-///
-/// # Errors
-///
-/// This function will return an error if the user lacks permissions to remove
-/// the directory at the provided `path`, or if the directory isn't empty.
-pub fn remove_dir<P: AsPath + ?Sized>(path: &P) -> io::Result<()> {
-    fs_imp::rmdir(path.as_path())
-}
-
-/// Removes a directory at this path, after removing all its contents. Use
-/// carefully!
-///
-/// This function does **not** follow soft links and it will simply remove the
-/// soft link itself.
-///
-/// # Errors
-///
-/// See `file::remove_file` and `fs::remove_dir`
-pub fn remove_dir_all<P: AsPath + ?Sized>(path: &P) -> io::Result<()> {
-    let path = path.as_path();
-    for child in try!(read_dir(path)) {
-        let child = try!(child).path();
-        let stat = try!(lstat(&*child));
-        if stat.is_dir() {
-            try!(remove_dir_all(&*child));
-        } else {
-            try!(remove_file(&*child));
-        }
-    }
-    return remove_dir(path);
-
-    #[cfg(unix)]
-    fn lstat(path: &Path) -> io::Result<fs_imp::FileAttr> { fs_imp::lstat(path) }
-    #[cfg(windows)]
-    fn lstat(path: &Path) -> io::Result<fs_imp::FileAttr> { fs_imp::stat(path) }
-}
-
-/// Returns an iterator over the entries within a directory.
-///
-/// The iterator will yield instances of `io::Result<DirEntry>`. New errors may
-/// be encountered after an iterator is initially constructed.
-///
-/// # Example
-///
-/// ```rust
-/// use std::io;
-/// use std::fs::{self, PathExt, DirEntry};
-/// use std::path::Path;
-///
-/// // one possible implementation of fs::walk_dir only visiting files
-/// fn visit_dirs(dir: &Path, cb: &mut FnMut(DirEntry)) -> io::Result<()> {
-///     if dir.is_dir() {
-///         for entry in try!(fs::read_dir(dir)) {
-///             let entry = try!(entry);
-///             if entry.path().is_dir() {
-///                 try!(visit_dirs(&entry.path(), cb));
-///             } else {
-///                 cb(entry);
-///             }
-///         }
-///     }
-///     Ok(())
-/// }
-/// ```
-///
-/// # Errors
-///
-/// This function will return an error if the provided `path` doesn't exist, if
-/// the process lacks permissions to view the contents or if the `path` points
-/// at a non-directory file
-pub fn read_dir<P: AsPath + ?Sized>(path: &P) -> io::Result<ReadDir> {
-    fs_imp::readdir(path.as_path()).map(ReadDir)
-}
-
-/// Returns an iterator that will recursively walk the directory structure
-/// rooted at `path`.
-///
-/// The path given will not be iterated over, and this will perform iteration in
-/// some top-down order.  The contents of unreadable subdirectories are ignored.
-///
-/// The iterator will yield instances of `io::Result<DirEntry>`. New errors may
-/// be encountered after an iterator is initially constructed.
-pub fn walk_dir<P: AsPath + ?Sized>(path: &P) -> io::Result<WalkDir> {
-    let start = try!(read_dir(path));
-    Ok(WalkDir { cur: Some(start), stack: Vec::new() })
-}
-
-impl Iterator for WalkDir {
-    type Item = io::Result<DirEntry>;
-
-    fn next(&mut self) -> Option<io::Result<DirEntry>> {
-        loop {
-            if let Some(ref mut cur) = self.cur {
-                match cur.next() {
-                    Some(Err(e)) => return Some(Err(e)),
-                    Some(Ok(next)) => {
-                        let path = next.path();
-                        if path.is_dir() {
-                            self.stack.push(read_dir(&*path));
-                        }
-                        return Some(Ok(next))
-                    }
-                    None => {}
-                }
-            }
-            self.cur = None;
-            match self.stack.pop() {
-                Some(Err(e)) => return Some(Err(e)),
-                Some(Ok(next)) => self.cur = Some(next),
-                None => return None,
-            }
-        }
-    }
-}
-
-/// Utility methods for paths.
-pub trait PathExt {
-    /// Get information on the file, directory, etc at this path.
-    ///
-    /// Consult the `fs::stat` documentation for more info.
-    ///
-    /// This call preserves identical runtime/error semantics with `file::stat`.
-    fn metadata(&self) -> io::Result<Metadata>;
-
-    /// Boolean value indicator whether the underlying file exists on the local
-    /// filesystem. Returns false in exactly the cases where `fs::stat` fails.
-    fn exists(&self) -> bool;
-
-    /// Whether the underlying implementation (be it a file path, or something
-    /// else) points at a "regular file" on the FS. Will return false for paths
-    /// to non-existent locations or directories or other non-regular files
-    /// (named pipes, etc). Follows links when making this determination.
-    fn is_file(&self) -> bool;
-
-    /// Whether the underlying implementation (be it a file path, or something
-    /// else) is pointing at a directory in the underlying FS. Will return
-    /// false for paths to non-existent locations or if the item is not a
-    /// directory (eg files, named pipes, etc). Follows links when making this
-    /// determination.
-    fn is_dir(&self) -> bool;
-}
-
-impl PathExt for Path {
-    fn metadata(&self) -> io::Result<Metadata> { metadata(self) }
-
-    fn exists(&self) -> bool { metadata(self).is_ok() }
-
-    fn is_file(&self) -> bool {
-        metadata(self).map(|s| s.is_file()).unwrap_or(false)
-    }
-    fn is_dir(&self) -> bool {
-        metadata(self).map(|s| s.is_dir()).unwrap_or(false)
-    }
-}
-
-/// Changes the timestamps for a file's last modification and access time.
-///
-/// The file at the path specified will have its last access time set to
-/// `atime` and its modification time set to `mtime`. The times specified should
-/// be in milliseconds.
-pub fn set_file_times<P: AsPath + ?Sized>(path: &P, accessed: u64,
-                                          modified: u64) -> io::Result<()> {
-    fs_imp::utimes(path.as_path(), accessed, modified)
-}
-
-/// Changes the permissions found on a file or a directory.
-///
-/// # Example
-///
-/// ```
-/// # fn foo() -> std::io::Result<()> {
-/// use std::fs;
-///
-/// let mut perms = try!(fs::metadata("foo.txt")).permissions();
-/// perms.set_readonly(true);
-/// try!(fs::set_permissions("foo.txt", perms));
-/// # Ok(())
-/// # }
-/// ```
-///
-/// # Errors
-///
-/// This function will return an error if the provided `path` doesn't exist, if
-/// the process lacks permissions to change the attributes of the file, or if
-/// some other I/O error is encountered.
-pub fn set_permissions<P: AsPath + ?Sized>(path: &P, perm: Permissions)
-                                           -> io::Result<()> {
-    fs_imp::set_perm(path.as_path(), perm.0)
-}
-
-#[cfg(test)]
-mod tests {
-    #![allow(deprecated)] //rand
-
-    use prelude::v1::*;
-    use io::prelude::*;
-
-    use fs::{self, File, OpenOptions};
-    use io::{ErrorKind, SeekFrom};
-    use path::PathBuf;
-    use path::Path as Path2;
-    use os;
-    use rand::{self, StdRng, Rng};
-    use str;
-
-    macro_rules! check { ($e:expr) => (
-        match $e {
-            Ok(t) => t,
-            Err(e) => panic!("{} failed with: {}", stringify!($e), e),
-        }
-    ) }
-
-    macro_rules! error { ($e:expr, $s:expr) => (
-        match $e {
-            Ok(_) => panic!("Unexpected success. Should've been: {:?}", $s),
-            Err(ref err) => assert!(err.to_string().contains($s.as_slice()),
-                                    format!("`{}` did not contain `{}`", err, $s))
-        }
-    ) }
-
-    pub struct TempDir(PathBuf);
-
-    impl TempDir {
-        fn join(&self, path: &str) -> PathBuf {
-            let TempDir(ref p) = *self;
-            p.join(path)
-        }
-
-        fn path<'a>(&'a self) -> &'a Path2 {
-            let TempDir(ref p) = *self;
-            p
-        }
-    }
-
-    impl Drop for TempDir {
-        fn drop(&mut self) {
-            // Gee, seeing how we're testing the fs module I sure hope that we
-            // at least implement this correctly!
-            let TempDir(ref p) = *self;
-            check!(fs::remove_dir_all(p));
-        }
-    }
-
-    pub fn tmpdir() -> TempDir {
-        let s = os::tmpdir();
-        let p = Path2::new(s.as_str().unwrap());
-        let ret = p.join(&format!("rust-{}", rand::random::<u32>()));
-        check!(fs::create_dir(&ret));
-        TempDir(ret)
-    }
-
-    #[test]
-    fn file_test_io_smoke_test() {
-        let message = "it's alright. have a good time";
-        let tmpdir = tmpdir();
-        let filename = &tmpdir.join("file_rt_io_file_test.txt");
-        {
-            let mut write_stream = check!(File::create(filename));
-            check!(write_stream.write(message.as_bytes()));
-        }
-        {
-            let mut read_stream = check!(File::open(filename));
-            let mut read_buf = [0; 1028];
-            let read_str = match check!(read_stream.read(&mut read_buf)) {
-                -1|0 => panic!("shouldn't happen"),
-                n => str::from_utf8(&read_buf[..n]).unwrap().to_string()
-            };
-            assert_eq!(read_str.as_slice(), message);
-        }
-        check!(fs::remove_file(filename));
-    }
-
-    #[test]
-    fn invalid_path_raises() {
-        let tmpdir = tmpdir();
-        let filename = &tmpdir.join("file_that_does_not_exist.txt");
-        let result = File::open(filename);
-
-        if cfg!(unix) {
-            error!(result, "o such file or directory");
-        }
-        // error!(result, "couldn't open path as file");
-        // error!(result, format!("path={}; mode=open; access=read", filename.display()));
-    }
-
-    #[test]
-    fn file_test_iounlinking_invalid_path_should_raise_condition() {
-        let tmpdir = tmpdir();
-        let filename = &tmpdir.join("file_another_file_that_does_not_exist.txt");
-
-        let result = fs::remove_file(filename);
-
-        if cfg!(unix) {
-            error!(result, "o such file or directory");
-        }
-        // error!(result, "couldn't unlink path");
-        // error!(result, format!("path={}", filename.display()));
-    }
-
-    #[test]
-    fn file_test_io_non_positional_read() {
-        let message: &str = "ten-four";
-        let mut read_mem = [0; 8];
-        let tmpdir = tmpdir();
-        let filename = &tmpdir.join("file_rt_io_file_test_positional.txt");
-        {
-            let mut rw_stream = check!(File::create(filename));
-            check!(rw_stream.write(message.as_bytes()));
-        }
-        {
-            let mut read_stream = check!(File::open(filename));
-            {
-                let read_buf = &mut read_mem[0..4];
-                check!(read_stream.read(read_buf));
-            }
-            {
-                let read_buf = &mut read_mem[4..8];
-                check!(read_stream.read(read_buf));
-            }
-        }
-        check!(fs::remove_file(filename));
-        let read_str = str::from_utf8(&read_mem).unwrap();
-        assert_eq!(read_str, message);
-    }
-
-    #[test]
-    fn file_test_io_seek_and_tell_smoke_test() {
-        let message = "ten-four";
-        let mut read_mem = [0; 4];
-        let set_cursor = 4 as u64;
-        let mut tell_pos_pre_read;
-        let mut tell_pos_post_read;
-        let tmpdir = tmpdir();
-        let filename = &tmpdir.join("file_rt_io_file_test_seeking.txt");
-        {
-            let mut rw_stream = check!(File::create(filename));
-            check!(rw_stream.write(message.as_bytes()));
-        }
-        {
-            let mut read_stream = check!(File::open(filename));
-            check!(read_stream.seek(SeekFrom::Start(set_cursor)));
-            tell_pos_pre_read = check!(read_stream.seek(SeekFrom::Current(0)));
-            check!(read_stream.read(&mut read_mem));
-            tell_pos_post_read = check!(read_stream.seek(SeekFrom::Current(0)));
-        }
-        check!(fs::remove_file(filename));
-        let read_str = str::from_utf8(&read_mem).unwrap();
-        assert_eq!(read_str, &message[4..8]);
-        assert_eq!(tell_pos_pre_read, set_cursor);
-        assert_eq!(tell_pos_post_read, message.len() as u64);
-    }
-
-    #[test]
-    fn file_test_io_seek_and_write() {
-        let initial_msg =   "food-is-yummy";
-        let overwrite_msg =    "-the-bar!!";
-        let final_msg =     "foo-the-bar!!";
-        let seek_idx = 3;
-        let mut read_mem = [0; 13];
-        let tmpdir = tmpdir();
-        let filename = &tmpdir.join("file_rt_io_file_test_seek_and_write.txt");
-        {
-            let mut rw_stream = check!(File::create(filename));
-            check!(rw_stream.write(initial_msg.as_bytes()));
-            check!(rw_stream.seek(SeekFrom::Start(seek_idx)));
-            check!(rw_stream.write(overwrite_msg.as_bytes()));
-        }
-        {
-            let mut read_stream = check!(File::open(filename));
-            check!(read_stream.read(&mut read_mem));
-        }
-        check!(fs::remove_file(filename));
-        let read_str = str::from_utf8(&read_mem).unwrap();
-        assert!(read_str == final_msg);
-    }
-
-    #[test]
-    fn file_test_io_seek_shakedown() {
-        //                   01234567890123
-        let initial_msg =   "qwer-asdf-zxcv";
-        let chunk_one: &str = "qwer";
-        let chunk_two: &str = "asdf";
-        let chunk_three: &str = "zxcv";
-        let mut read_mem = [0; 4];
-        let tmpdir = tmpdir();
-        let filename = &tmpdir.join("file_rt_io_file_test_seek_shakedown.txt");
-        {
-            let mut rw_stream = check!(File::create(filename));
-            check!(rw_stream.write(initial_msg.as_bytes()));
-        }
-        {
-            let mut read_stream = check!(File::open(filename));
-
-            check!(read_stream.seek(SeekFrom::End(-4)));
-            check!(read_stream.read(&mut read_mem));
-            assert_eq!(str::from_utf8(&read_mem).unwrap(), chunk_three);
-
-            check!(read_stream.seek(SeekFrom::Current(-9)));
-            check!(read_stream.read(&mut read_mem));
-            assert_eq!(str::from_utf8(&read_mem).unwrap(), chunk_two);
-
-            check!(read_stream.seek(SeekFrom::Start(0)));
-            check!(read_stream.read(&mut read_mem));
-            assert_eq!(str::from_utf8(&read_mem).unwrap(), chunk_one);
-        }
-        check!(fs::remove_file(filename));
-    }
-
-    #[test]
-    fn file_test_stat_is_correct_on_is_file() {
-        let tmpdir = tmpdir();
-        let filename = &tmpdir.join("file_stat_correct_on_is_file.txt");
-        {
-            let mut opts = OpenOptions::new();
-            let mut fs = check!(opts.read(true).write(true)
-                                    .create(true).open(filename));
-            let msg = "hw";
-            fs.write(msg.as_bytes()).unwrap();
-
-            let fstat_res = check!(fs.metadata());
-            assert!(fstat_res.is_file());
-        }
-        let stat_res_fn = check!(fs::metadata(filename));
-        assert!(stat_res_fn.is_file());
-        let stat_res_meth = check!(filename.metadata());
-        assert!(stat_res_meth.is_file());
-        check!(fs::remove_file(filename));
-    }
-
-    #[test]
-    fn file_test_stat_is_correct_on_is_dir() {
-        let tmpdir = tmpdir();
-        let filename = &tmpdir.join("file_stat_correct_on_is_dir");
-        check!(fs::create_dir(filename));
-        let stat_res_fn = check!(fs::metadata(filename));
-        assert!(stat_res_fn.is_dir());
-        let stat_res_meth = check!(filename.metadata());
-        assert!(stat_res_meth.is_dir());
-        check!(fs::remove_dir(filename));
-    }
-
-    #[test]
-    fn file_test_fileinfo_false_when_checking_is_file_on_a_directory() {
-        let tmpdir = tmpdir();
-        let dir = &tmpdir.join("fileinfo_false_on_dir");
-        check!(fs::create_dir(dir));
-        assert!(dir.is_file() == false);
-        check!(fs::remove_dir(dir));
-    }
-
-    #[test]
-    fn file_test_fileinfo_check_exists_before_and_after_file_creation() {
-        let tmpdir = tmpdir();
-        let file = &tmpdir.join("fileinfo_check_exists_b_and_a.txt");
-        check!(check!(File::create(file)).write(b"foo"));
-        assert!(file.exists());
-        check!(fs::remove_file(file));
-        assert!(!file.exists());
-    }
-
-    #[test]
-    fn file_test_directoryinfo_check_exists_before_and_after_mkdir() {
-        let tmpdir = tmpdir();
-        let dir = &tmpdir.join("before_and_after_dir");
-        assert!(!dir.exists());
-        check!(fs::create_dir(dir));
-        assert!(dir.exists());
-        assert!(dir.is_dir());
-        check!(fs::remove_dir(dir));
-        assert!(!dir.exists());
-    }
-
-    #[test]
-    fn file_test_directoryinfo_readdir() {
-        let tmpdir = tmpdir();
-        let dir = &tmpdir.join("di_readdir");
-        check!(fs::create_dir(dir));
-        let prefix = "foo";
-        for n in range(0, 3) {
-            let f = dir.join(&format!("{}.txt", n));
-            let mut w = check!(File::create(&f));
-            let msg_str = format!("{}{}", prefix, n.to_string());
-            let msg = msg_str.as_bytes();
-            check!(w.write(msg));
-        }
-        let files = check!(fs::read_dir(dir));
-        let mut mem = [0u8; 4];
-        for f in files {
-            let f = f.unwrap().path();
-            {
-                let n = f.file_stem().unwrap();
-                check!(check!(File::open(&f)).read(&mut mem));
-                let read_str = str::from_utf8(&mem).unwrap();
-                let expected = format!("{}{}", prefix, n.to_str().unwrap());
-                assert_eq!(expected.as_slice(), read_str);
-            }
-            check!(fs::remove_file(&f));
-        }
-        check!(fs::remove_dir(dir));
-    }
-
-    #[test]
-    fn file_test_walk_dir() {
-        let tmpdir = tmpdir();
-        let dir = &tmpdir.join("walk_dir");
-        check!(fs::create_dir(dir));
-
-        let dir1 = &dir.join("01/02/03");
-        check!(fs::create_dir_all(dir1));
-        check!(File::create(&dir1.join("04")));
-
-        let dir2 = &dir.join("11/12/13");
-        check!(fs::create_dir_all(dir2));
-        check!(File::create(&dir2.join("14")));
-
-        let files = check!(fs::walk_dir(dir));
-        let mut cur = [0u8; 2];
-        for f in files {
-            let f = f.unwrap().path();
-            let stem = f.file_stem().unwrap().to_str().unwrap();
-            let root = stem.as_bytes()[0] - b'0';
-            let name = stem.as_bytes()[1] - b'0';
-            assert!(cur[root as usize] < name);
-            cur[root as usize] = name;
-        }
-
-        check!(fs::remove_dir_all(dir));
-    }
-
-    #[test]
-    fn mkdir_path_already_exists_error() {
-        let tmpdir = tmpdir();
-        let dir = &tmpdir.join("mkdir_error_twice");
-        check!(fs::create_dir(dir));
-        let e = fs::create_dir(dir).err().unwrap();
-        assert_eq!(e.kind(), ErrorKind::PathAlreadyExists);
-    }
-
-    #[test]
-    fn recursive_mkdir() {
-        let tmpdir = tmpdir();
-        let dir = tmpdir.join("d1/d2");
-        check!(fs::create_dir_all(&dir));
-        assert!(dir.is_dir())
-    }
-
-    #[test]
-    fn recursive_mkdir_failure() {
-        let tmpdir = tmpdir();
-        let dir = tmpdir.join("d1");
-        let file = dir.join("f1");
-
-        check!(fs::create_dir_all(&dir));
-        check!(File::create(&file));
-
-        let result = fs::create_dir_all(&file);
-
-        assert!(result.is_err());
-        // error!(result, "couldn't recursively mkdir");
-        // error!(result, "couldn't create directory");
-        // error!(result, "mode=0700");
-        // error!(result, format!("path={}", file.display()));
-    }
-
-    #[test]
-    fn recursive_mkdir_slash() {
-        check!(fs::create_dir_all(&Path2::new("/")));
-    }
-
-    // FIXME(#12795) depends on lstat to work on windows
-    #[cfg(not(windows))]
-    #[test]
-    fn recursive_rmdir() {
-        let tmpdir = tmpdir();
-        let d1 = tmpdir.join("d1");
-        let dt = d1.join("t");
-        let dtt = dt.join("t");
-        let d2 = tmpdir.join("d2");
-        let canary = d2.join("do_not_delete");
-        check!(fs::create_dir_all(&dtt));
-        check!(fs::create_dir_all(&d2));
-        check!(check!(File::create(&canary)).write(b"foo"));
-        check!(fs::soft_link(&d2, &dt.join("d2")));
-        check!(fs::remove_dir_all(&d1));
-
-        assert!(!d1.is_dir());
-        assert!(canary.exists());
-    }
-
-    #[test]
-    fn unicode_path_is_dir() {
-        assert!(Path2::new(".").is_dir());
-        assert!(!Path2::new("test/stdtest/fs.rs").is_dir());
-
-        let tmpdir = tmpdir();
-
-        let mut dirpath = tmpdir.path().to_path_buf();
-        dirpath.push(&format!("test-가一ー你好"));
-        check!(fs::create_dir(&dirpath));
-        assert!(dirpath.is_dir());
-
-        let mut filepath = dirpath;
-        filepath.push("unicode-file-\u{ac00}\u{4e00}\u{30fc}\u{4f60}\u{597d}.rs");
-        check!(File::create(&filepath)); // ignore return; touch only
-        assert!(!filepath.is_dir());
-        assert!(filepath.exists());
-    }
-
-    #[test]
-    fn unicode_path_exists() {
-        assert!(Path2::new(".").exists());
-        assert!(!Path2::new("test/nonexistent-bogus-path").exists());
-
-        let tmpdir = tmpdir();
-        let unicode = tmpdir.path();
-        let unicode = unicode.join(&format!("test-각丁ー再见"));
-        check!(fs::create_dir(&unicode));
-        assert!(unicode.exists());
-        assert!(!Path2::new("test/unicode-bogus-path-각丁ー再见").exists());
-    }
-
-    #[test]
-    fn copy_file_does_not_exist() {
-        let from = Path2::new("test/nonexistent-bogus-path");
-        let to = Path2::new("test/other-bogus-path");
-
-        match fs::copy(&from, &to) {
-            Ok(..) => panic!(),
-            Err(..) => {
-                assert!(!from.exists());
-                assert!(!to.exists());
-            }
-        }
-    }
-
-    #[test]
-    fn copy_file_ok() {
-        let tmpdir = tmpdir();
-        let input = tmpdir.join("in.txt");
-        let out = tmpdir.join("out.txt");
-
-        check!(check!(File::create(&input)).write(b"hello"));
-        check!(fs::copy(&input, &out));
-        let mut v = Vec::new();
-        check!(check!(File::open(&out)).read_to_end(&mut v));
-        assert_eq!(v.as_slice(), b"hello");
-
-        assert_eq!(check!(input.metadata()).permissions(),
-                   check!(out.metadata()).permissions());
-    }
-
-    #[test]
-    fn copy_file_dst_dir() {
-        let tmpdir = tmpdir();
-        let out = tmpdir.join("out");
-
-        check!(File::create(&out));
-        match fs::copy(&*out, tmpdir.path()) {
-            Ok(..) => panic!(), Err(..) => {}
-        }
-    }
-
-    #[test]
-    fn copy_file_dst_exists() {
-        let tmpdir = tmpdir();
-        let input = tmpdir.join("in");
-        let output = tmpdir.join("out");
-
-        check!(check!(File::create(&input)).write("foo".as_bytes()));
-        check!(check!(File::create(&output)).write("bar".as_bytes()));
-        check!(fs::copy(&input, &output));
-
-        let mut v = Vec::new();
-        check!(check!(File::open(&output)).read_to_end(&mut v));
-        assert_eq!(v, b"foo".to_vec());
-    }
-
-    #[test]
-    fn copy_file_src_dir() {
-        let tmpdir = tmpdir();
-        let out = tmpdir.join("out");
-
-        match fs::copy(tmpdir.path(), &out) {
-            Ok(..) => panic!(), Err(..) => {}
-        }
-        assert!(!out.exists());
-    }
-
-    #[test]
-    fn copy_file_preserves_perm_bits() {
-        let tmpdir = tmpdir();
-        let input = tmpdir.join("in.txt");
-        let out = tmpdir.join("out.txt");
-
-        let attr = check!(check!(File::create(&input)).metadata());
-        let mut p = attr.permissions();
-        p.set_readonly(true);
-        check!(fs::set_permissions(&input, p));
-        check!(fs::copy(&input, &out));
-        assert!(check!(out.metadata()).permissions().readonly());
-    }
-
-    #[cfg(not(windows))] // FIXME(#10264) operation not permitted?
-    #[test]
-    fn symlinks_work() {
-        let tmpdir = tmpdir();
-        let input = tmpdir.join("in.txt");
-        let out = tmpdir.join("out.txt");
-
-        check!(check!(File::create(&input)).write("foobar".as_bytes()));
-        check!(fs::soft_link(&input, &out));
-        // if cfg!(not(windows)) {
-        //     assert_eq!(check!(lstat(&out)).kind, FileType::Symlink);
-        //     assert_eq!(check!(out.lstat()).kind, FileType::Symlink);
-        // }
-        assert_eq!(check!(fs::metadata(&out)).len(),
-                   check!(fs::metadata(&input)).len());
-        let mut v = Vec::new();
-        check!(check!(File::open(&out)).read_to_end(&mut v));
-        assert_eq!(v, b"foobar".to_vec());
-    }
-
-    #[cfg(not(windows))] // apparently windows doesn't like symlinks
-    #[test]
-    fn symlink_noexist() {
-        let tmpdir = tmpdir();
-        // symlinks can point to things that don't exist
-        check!(fs::soft_link(&tmpdir.join("foo"), &tmpdir.join("bar")));
-        assert_eq!(check!(fs::read_link(&tmpdir.join("bar"))),
-                   tmpdir.join("foo"));
-    }
-
-    #[test]
-    fn readlink_not_symlink() {
-        let tmpdir = tmpdir();
-        match fs::read_link(tmpdir.path()) {
-            Ok(..) => panic!("wanted a failure"),
-            Err(..) => {}
-        }
-    }
-
-    #[test]
-    fn links_work() {
-        let tmpdir = tmpdir();
-        let input = tmpdir.join("in.txt");
-        let out = tmpdir.join("out.txt");
-
-        check!(check!(File::create(&input)).write("foobar".as_bytes()));
-        check!(fs::hard_link(&input, &out));
-        assert_eq!(check!(fs::metadata(&out)).len(),
-                   check!(fs::metadata(&input)).len());
-        assert_eq!(check!(fs::metadata(&out)).len(),
-                   check!(input.metadata()).len());
-        let mut v = Vec::new();
-        check!(check!(File::open(&out)).read_to_end(&mut v));
-        assert_eq!(v, b"foobar".to_vec());
-
-        // can't link to yourself
-        match fs::hard_link(&input, &input) {
-            Ok(..) => panic!("wanted a failure"),
-            Err(..) => {}
-        }
-        // can't link to something that doesn't exist
-        match fs::hard_link(&tmpdir.join("foo"), &tmpdir.join("bar")) {
-            Ok(..) => panic!("wanted a failure"),
-            Err(..) => {}
-        }
-    }
-
-    #[test]
-    fn chmod_works() {
-        let tmpdir = tmpdir();
-        let file = tmpdir.join("in.txt");
-
-        check!(File::create(&file));
-        let attr = check!(fs::metadata(&file));
-        assert!(!attr.permissions().readonly());
-        let mut p = attr.permissions();
-        p.set_readonly(true);
-        check!(fs::set_permissions(&file, p.clone()));
-        let attr = check!(fs::metadata(&file));
-        assert!(attr.permissions().readonly());
-
-        match fs::set_permissions(&tmpdir.join("foo"), p) {
-            Ok(..) => panic!("wanted a panic"),
-            Err(..) => {}
-        }
-    }
-
-    #[test]
-    fn sync_doesnt_kill_anything() {
-        let tmpdir = tmpdir();
-        let path = tmpdir.join("in.txt");
-
-        let mut file = check!(File::create(&path));
-        check!(file.sync_all());
-        check!(file.sync_data());
-        check!(file.write(b"foo"));
-        check!(file.sync_all());
-        check!(file.sync_data());
-    }
-
-    #[test]
-    fn truncate_works() {
-        let tmpdir = tmpdir();
-        let path = tmpdir.join("in.txt");
-
-        let mut file = check!(File::create(&path));
-        check!(file.write(b"foo"));
-        check!(file.sync_all());
-
-        // Do some simple things with truncation
-        assert_eq!(check!(file.metadata()).len(), 3);
-        check!(file.set_len(10));
-        assert_eq!(check!(file.metadata()).len(), 10);
-        check!(file.write(b"bar"));
-        check!(file.sync_all());
-        assert_eq!(check!(file.metadata()).len(), 10);
-
-        let mut v = Vec::new();
-        check!(check!(File::open(&path)).read_to_end(&mut v));
-        assert_eq!(v, b"foobar\0\0\0\0".to_vec());
-
-        // Truncate to a smaller length, don't seek, and then write something.
-        // Ensure that the intermediate zeroes are all filled in (we're seeked
-        // past the end of the file).
-        check!(file.set_len(2));
-        assert_eq!(check!(file.metadata()).len(), 2);
-        check!(file.write(b"wut"));
-        check!(file.sync_all());
-        assert_eq!(check!(file.metadata()).len(), 9);
-        let mut v = Vec::new();
-        check!(check!(File::open(&path)).read_to_end(&mut v));
-        assert_eq!(v, b"fo\0\0\0\0wut".to_vec());
-    }
-
-    #[test]
-    fn open_flavors() {
-        use fs::OpenOptions as OO;
-        fn c<T: Clone>(t: &T) -> T { t.clone() }
-
-        let tmpdir = tmpdir();
-
-        let mut r = OO::new(); r.read(true);
-        let mut w = OO::new(); w.write(true);
-        let mut rw = OO::new(); rw.write(true).read(true);
-
-        match r.open(&tmpdir.join("a")) {
-            Ok(..) => panic!(), Err(..) => {}
-        }
-
-        // Perform each one twice to make sure that it succeeds the second time
-        // (where the file exists)
-        check!(c(&w).create(true).open(&tmpdir.join("b")));
-        assert!(tmpdir.join("b").exists());
-        check!(c(&w).create(true).open(&tmpdir.join("b")));
-        check!(w.open(&tmpdir.join("b")));
-
-        check!(c(&rw).create(true).open(&tmpdir.join("c")));
-        assert!(tmpdir.join("c").exists());
-        check!(c(&rw).create(true).open(&tmpdir.join("c")));
-        check!(rw.open(&tmpdir.join("c")));
-
-        check!(c(&w).append(true).create(true).open(&tmpdir.join("d")));
-        assert!(tmpdir.join("d").exists());
-        check!(c(&w).append(true).create(true).open(&tmpdir.join("d")));
-        check!(c(&w).append(true).open(&tmpdir.join("d")));
-
-        check!(c(&rw).append(true).create(true).open(&tmpdir.join("e")));
-        assert!(tmpdir.join("e").exists());
-        check!(c(&rw).append(true).create(true).open(&tmpdir.join("e")));
-        check!(c(&rw).append(true).open(&tmpdir.join("e")));
-
-        check!(c(&w).truncate(true).create(true).open(&tmpdir.join("f")));
-        assert!(tmpdir.join("f").exists());
-        check!(c(&w).truncate(true).create(true).open(&tmpdir.join("f")));
-        check!(c(&w).truncate(true).open(&tmpdir.join("f")));
-
-        check!(c(&rw).truncate(true).create(true).open(&tmpdir.join("g")));
-        assert!(tmpdir.join("g").exists());
-        check!(c(&rw).truncate(true).create(true).open(&tmpdir.join("g")));
-        check!(c(&rw).truncate(true).open(&tmpdir.join("g")));
-
-        check!(check!(File::create(&tmpdir.join("h"))).write("foo".as_bytes()));
-        check!(r.open(&tmpdir.join("h")));
-        {
-            let mut f = check!(r.open(&tmpdir.join("h")));
-            assert!(f.write("wut".as_bytes()).is_err());
-        }
-        assert_eq!(check!(fs::metadata(&tmpdir.join("h"))).len(), 3);
-        {
-            let mut f = check!(c(&w).append(true).open(&tmpdir.join("h")));
-            check!(f.write("bar".as_bytes()));
-        }
-        assert_eq!(check!(fs::metadata(&tmpdir.join("h"))).len(), 6);
-        {
-            let mut f = check!(c(&w).truncate(true).open(&tmpdir.join("h")));
-            check!(f.write("bar".as_bytes()));
-        }
-        assert_eq!(check!(fs::metadata(&tmpdir.join("h"))).len(), 3);
-    }
-
-    #[test]
-    fn utime() {
-        let tmpdir = tmpdir();
-        let path = tmpdir.join("a");
-        check!(File::create(&path));
-        // These numbers have to be bigger than the time in the day to account
-        // for timezones Windows in particular will fail in certain timezones
-        // with small enough values
-        check!(fs::set_file_times(&path, 100000, 200000));
-        assert_eq!(check!(path.metadata()).accessed(), 100000);
-        assert_eq!(check!(path.metadata()).modified(), 200000);
-    }
-
-    #[test]
-    fn utime_noexist() {
-        let tmpdir = tmpdir();
-
-        match fs::set_file_times(&tmpdir.join("a"), 100, 200) {
-            Ok(..) => panic!(),
-            Err(..) => {}
-        }
-    }
-
-    #[test]
-    fn binary_file() {
-        let mut bytes = [0; 1024];
-        StdRng::new().ok().unwrap().fill_bytes(&mut bytes);
-
-        let tmpdir = tmpdir();
-
-        check!(check!(File::create(&tmpdir.join("test"))).write(&bytes));
-        let mut v = Vec::new();
-        check!(check!(File::open(&tmpdir.join("test"))).read_to_end(&mut v));
-        assert!(v == bytes.as_slice());
-    }
-
-    #[test]
-    fn unlink_readonly() {
-        let tmpdir = tmpdir();
-        let path = tmpdir.join("file");
-        check!(File::create(&path));
-        let mut perm = check!(fs::metadata(&path)).permissions();
-        perm.set_readonly(true);
-        check!(fs::set_permissions(&path, perm));
-        check!(fs::remove_file(&path));
-    }
-}
diff --git a/src/libstd/fs/mod.rs b/src/libstd/fs/mod.rs
new file mode 100644 (file)
index 0000000..64ec025
--- /dev/null
@@ -0,0 +1,1525 @@
+// 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.
+
+//! Filesystem manipulation operations
+//!
+//! This module contains basic methods to manipulate the contents of the local
+//! filesystem. All methods in this module represent cross-platform filesystem
+//! operations. Extra platform-specific functionality can be found in the
+//! extension traits of `std::os::$platform`.
+
+#![unstable(feature = "fs")]
+
+use core::prelude::*;
+
+use io::{self, Error, ErrorKind, SeekFrom, Seek, Read, Write};
+use path::{AsPath, Path, PathBuf};
+use sys::fs2 as fs_imp;
+use sys_common::{AsInnerMut, FromInner, AsInner};
+use vec::Vec;
+
+pub use self::tempdir::TempDir;
+
+mod tempdir;
+
+/// A reference to an open file on the filesystem.
+///
+/// An instance of a `File` can be read and/or written depending on what options
+/// it was opened with. Files also implement `Seek` to alter the logical cursor
+/// that the file contains internally.
+///
+/// # Example
+///
+/// ```no_run
+/// use std::io::prelude::*;
+/// use std::fs::File;
+///
+/// # fn foo() -> std::io::Result<()> {
+/// let mut f = try!(File::create("foo.txt"));
+/// try!(f.write_all(b"Hello, world!"));
+///
+/// let mut f = try!(File::open("foo.txt"));
+/// let mut s = String::new();
+/// try!(f.read_to_string(&mut s));
+/// assert_eq!(s, "Hello, world!");
+/// # Ok(())
+/// # }
+/// ```
+pub struct File {
+    inner: fs_imp::File,
+    path: PathBuf,
+}
+
+/// Metadata information about a file.
+///
+/// This structure is returned from the `metadata` function or method and
+/// represents known metadata about a file such as its permissions, size,
+/// modification times, etc.
+pub struct Metadata(fs_imp::FileAttr);
+
+/// Iterator over the entries in a directory.
+///
+/// This iterator is returned from the `read_dir` function of this module and
+/// will yield instances of `io::Result<DirEntry>`. Through a `DirEntry`
+/// information like the entry's path and possibly other metadata can be
+/// learned.
+pub struct ReadDir(fs_imp::ReadDir);
+
+/// Entries returned by the `ReadDir` iterator.
+///
+/// An instance of `DirEntry` represents an entry inside of a directory on the
+/// filesystem. Each entry can be inspected via methods to learn about the full
+/// path or possibly other metadata through per-platform extension traits.
+pub struct DirEntry(fs_imp::DirEntry);
+
+/// An iterator that recursively walks over the contents of a directory.
+pub struct WalkDir {
+    cur: Option<ReadDir>,
+    stack: Vec<io::Result<ReadDir>>,
+}
+
+/// Options and flags which can be used to configure how a file is opened.
+///
+/// This builder exposes the ability to configure how a `File` is opened and
+/// what operations are permitted on the open file. The `File::open` and
+/// `File::create` methods are aliases for commonly used options using this
+/// builder.
+#[derive(Clone)]
+pub struct OpenOptions(fs_imp::OpenOptions);
+
+/// Representation of the various permissions on a file.
+///
+/// This module only currently provides one bit of information, `readonly`,
+/// which is exposed on all currently supported platforms. Unix-specific
+/// functionality, such as mode bits, is available through the
+/// `os::unix::PermissionsExt` trait.
+#[derive(Clone, PartialEq, Eq, Debug)]
+pub struct Permissions(fs_imp::FilePermissions);
+
+impl File {
+    /// Attempts to open a file in read-only mode.
+    ///
+    /// See the `OpenOptions::open` method for more details.
+    ///
+    /// # Errors
+    ///
+    /// This function will return an error if `path` does not already exist.
+    /// Other errors may also be returned according to `OpenOptions::open`.
+    pub fn open<P: AsPath + ?Sized>(path: &P) -> io::Result<File> {
+        OpenOptions::new().read(true).open(path)
+    }
+
+    /// Open a file in write-only mode.
+    ///
+    /// This function will create a file if it does not exist,
+    /// and will truncate it if it does.
+    ///
+    /// See the `OpenOptions::open` function for more details.
+    pub fn create<P: AsPath + ?Sized>(path: &P) -> io::Result<File> {
+        OpenOptions::new().write(true).create(true).truncate(true).open(path)
+    }
+
+    /// Returns the original path that was used to open this file.
+    pub fn path(&self) -> Option<&Path> {
+        Some(&self.path)
+    }
+
+    /// Attempt to sync all OS-internal metadata to disk.
+    ///
+    /// This function will attempt to ensure that all in-core data reaches the
+    /// filesystem before returning.
+    pub fn sync_all(&self) -> io::Result<()> {
+        self.inner.fsync()
+    }
+
+    /// This function is similar to `sync_all`, except that it may not
+    /// synchronize file metadata to the filesystem.
+    ///
+    /// This is intended for use cases that must synchronize content, but don't
+    /// need the metadata on disk. The goal of this method is to reduce disk
+    /// operations.
+    ///
+    /// Note that some platforms may simply implement this in terms of
+    /// `sync_all`.
+    pub fn sync_data(&self) -> io::Result<()> {
+        self.inner.datasync()
+    }
+
+    /// Truncates or extends the underlying file, updating the size of
+    /// this file to become `size`.
+    ///
+    /// If the `size` is less than the current file's size, then the file will
+    /// be shrunk. If it is greater than the current file's size, then the file
+    /// will be extended to `size` and have all of the intermediate data filled
+    /// in with 0s.
+    pub fn set_len(&self, size: u64) -> io::Result<()> {
+        self.inner.truncate(size)
+    }
+
+    /// Queries information about the underlying file.
+    pub fn metadata(&self) -> io::Result<Metadata> {
+        self.inner.file_attr().map(Metadata)
+    }
+}
+
+impl AsInner<fs_imp::File> for File {
+    fn as_inner(&self) -> &fs_imp::File { &self.inner }
+}
+impl Read for File {
+    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
+        self.inner.read(buf)
+    }
+}
+impl Write for File {
+    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
+        self.inner.write(buf)
+    }
+    fn flush(&mut self) -> io::Result<()> { self.inner.flush() }
+}
+impl Seek for File {
+    fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {
+        self.inner.seek(pos)
+    }
+}
+impl<'a> Read for &'a File {
+    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
+        self.inner.read(buf)
+    }
+}
+impl<'a> Write for &'a File {
+    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
+        self.inner.write(buf)
+    }
+    fn flush(&mut self) -> io::Result<()> { self.inner.flush() }
+}
+impl<'a> Seek for &'a File {
+    fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {
+        self.inner.seek(pos)
+    }
+}
+
+impl OpenOptions {
+    /// Creates a blank net set of options ready for configuration.
+    ///
+    /// All options are initially set to `false`.
+    pub fn new() -> OpenOptions {
+        OpenOptions(fs_imp::OpenOptions::new())
+    }
+
+    /// Set the option for read access.
+    ///
+    /// This option, when true, will indicate that the file should be
+    /// `read`-able if opened.
+    pub fn read(&mut self, read: bool) -> &mut OpenOptions {
+        self.0.read(read); self
+    }
+
+    /// Set the option for write access.
+    ///
+    /// This option, when true, will indicate that the file should be
+    /// `write`-able if opened.
+    pub fn write(&mut self, write: bool) -> &mut OpenOptions {
+        self.0.write(write); self
+    }
+
+    /// Set the option for the append mode.
+    ///
+    /// This option, when true, means that writes will append to a file instead
+    /// of overwriting previous contents.
+    pub fn append(&mut self, append: bool) -> &mut OpenOptions {
+        self.0.append(append); self
+    }
+
+    /// Set the option for truncating a previous file.
+    ///
+    /// If a file is successfully opened with this option set it will truncate
+    /// the file to 0 length if it already exists.
+    pub fn truncate(&mut self, truncate: bool) -> &mut OpenOptions {
+        self.0.truncate(truncate); self
+    }
+
+    /// Set the option for creating a new file.
+    ///
+    /// This option indicates whether a new file will be created if the file
+    /// does not yet already exist.
+    pub fn create(&mut self, create: bool) -> &mut OpenOptions {
+        self.0.create(create); self
+    }
+
+    /// Open a file at `path` with the options specified by `self`.
+    ///
+    /// # Errors
+    ///
+    /// This function will return an error under a number of different
+    /// circumstances, to include but not limited to:
+    ///
+    /// * Opening a file that does not exist with read access.
+    /// * Attempting to open a file with access that the user lacks
+    ///   permissions for
+    /// * Filesystem-level errors (full disk, etc)
+    pub fn open<P: AsPath + ?Sized>(&self, path: &P) -> io::Result<File> {
+        let path = path.as_path();
+        let inner = try!(fs_imp::File::open(path, &self.0));
+
+        // On *BSD systems, we can open a directory as a file and read from
+        // it: fd=open("/tmp", O_RDONLY); read(fd, buf, N); due to an old
+        // tradition before the introduction of opendir(3).  We explicitly
+        // reject it because there are few use cases.
+        if cfg!(not(any(target_os = "linux", target_os = "android"))) &&
+           try!(inner.file_attr()).is_dir() {
+            Err(Error::new(ErrorKind::InvalidInput, "is a directory", None))
+        } else {
+            Ok(File { path: path.to_path_buf(), inner: inner })
+        }
+    }
+}
+impl AsInnerMut<fs_imp::OpenOptions> for OpenOptions {
+    fn as_inner_mut(&mut self) -> &mut fs_imp::OpenOptions { &mut self.0 }
+}
+
+impl Metadata {
+    /// Returns whether this metadata is for a directory.
+    pub fn is_dir(&self) -> bool { self.0.is_dir() }
+
+    /// Returns whether this metadata is for a regular file.
+    pub fn is_file(&self) -> bool { self.0.is_file() }
+
+    /// Returns the size of the file, in bytes, this metadata is for.
+    pub fn len(&self) -> u64 { self.0.size() }
+
+    /// Returns the permissions of the file this metadata is for.
+    pub fn permissions(&self) -> Permissions {
+        Permissions(self.0.perm())
+    }
+
+    /// Returns the most recent access time for a file.
+    ///
+    /// The return value is in milliseconds since the epoch.
+    pub fn accessed(&self) -> u64 { self.0.accessed() }
+
+    /// Returns the most recent modification time for a file.
+    ///
+    /// The return value is in milliseconds since the epoch.
+    pub fn modified(&self) -> u64 { self.0.modified() }
+}
+
+impl Permissions {
+    /// Returns whether these permissions describe a readonly file.
+    pub fn readonly(&self) -> bool { self.0.readonly() }
+
+    /// Modify the readonly flag for this set of permissions.
+    ///
+    /// This operation does **not** modify the filesystem. To modify the
+    /// filesystem use the `fs::set_permissions` function.
+    pub fn set_readonly(&mut self, readonly: bool) {
+        self.0.set_readonly(readonly)
+    }
+}
+
+impl FromInner<fs_imp::FilePermissions> for Permissions {
+    fn from_inner(f: fs_imp::FilePermissions) -> Permissions {
+        Permissions(f)
+    }
+}
+
+impl AsInner<fs_imp::FilePermissions> for Permissions {
+    fn as_inner(&self) -> &fs_imp::FilePermissions { &self.0 }
+}
+
+impl Iterator for ReadDir {
+    type Item = io::Result<DirEntry>;
+
+    fn next(&mut self) -> Option<io::Result<DirEntry>> {
+        self.0.next().map(|entry| entry.map(DirEntry))
+    }
+}
+
+impl DirEntry {
+    /// Returns the full path to the file that this entry represents.
+    ///
+    /// The full path is created by joining the original path to `read_dir` or
+    /// `walk_dir` with the filename of this entry.
+    pub fn path(&self) -> PathBuf { self.0.path() }
+}
+
+/// Remove a file from the underlying filesystem.
+///
+/// # Example
+///
+/// ```rust,no_run
+/// use std::fs;
+///
+/// fs::remove_file("/some/file/path.txt");
+/// ```
+///
+/// Note that, just because an unlink call was successful, it is not
+/// guaranteed that a file is immediately deleted (e.g. depending on
+/// platform, other open file descriptors may prevent immediate removal).
+///
+/// # Errors
+///
+/// This function will return an error if `path` points to a directory, if the
+/// user lacks permissions to remove the file, or if some other filesystem-level
+/// error occurs.
+pub fn remove_file<P: AsPath + ?Sized>(path: &P) -> io::Result<()> {
+    let path = path.as_path();
+    let e = match fs_imp::unlink(path) {
+        Ok(()) => return Ok(()),
+        Err(e) => e,
+    };
+    if !cfg!(windows) { return Err(e) }
+
+    // On unix, a readonly file can be successfully removed. On windows,
+    // however, it cannot. To keep the two platforms in line with
+    // respect to their behavior, catch this case on windows, attempt to
+    // change it to read-write, and then remove the file.
+    if e.kind() != ErrorKind::PermissionDenied { return Err(e) }
+
+    let attr = match metadata(path) { Ok(a) => a, Err(..) => return Err(e) };
+    let mut perms = attr.permissions();
+    if !perms.readonly() { return Err(e) }
+    perms.set_readonly(false);
+
+    if set_permissions(path, perms).is_err() { return Err(e) }
+    if fs_imp::unlink(path).is_ok() { return Ok(()) }
+
+    // Oops, try to put things back the way we found it
+    let _ = set_permissions(path, attr.permissions());
+    Err(e)
+}
+
+/// Given a path, query the file system to get information about a file,
+/// directory, etc.
+///
+/// This function will traverse soft links to query information about the
+/// destination file.
+///
+/// # Example
+///
+/// ```rust,no_run
+/// # fn foo() -> std::io::Result<()> {
+/// use std::fs;
+///
+/// let attr = try!(fs::metadata("/some/file/path.txt"));
+/// // inspect attr ...
+/// # Ok(())
+/// # }
+/// ```
+///
+/// # Errors
+///
+/// This function will return an error if the user lacks the requisite
+/// permissions to perform a `metadata` call on the given `path` or if there
+/// is no entry in the filesystem at the provided path.
+pub fn metadata<P: AsPath + ?Sized>(path: &P) -> io::Result<Metadata> {
+    fs_imp::stat(path.as_path()).map(Metadata)
+}
+
+/// Rename a file or directory to a new name.
+///
+/// # Example
+///
+/// ```rust,no_run
+/// use std::fs;
+///
+/// fs::rename("foo", "bar");
+/// ```
+///
+/// # Errors
+///
+/// This function will return an error if the provided `from` doesn't exist, if
+/// the process lacks permissions to view the contents, if `from` and `to`
+/// reside on separate filesystems, or if some other intermittent I/O error
+/// occurs.
+pub fn rename<P: AsPath + ?Sized, Q: AsPath + ?Sized>(from: &P, to: &Q)
+                                                      -> io::Result<()> {
+    fs_imp::rename(from.as_path(), to.as_path())
+}
+
+/// Copies the contents of one file to another. This function will also
+/// copy the permission bits of the original file to the destination file.
+///
+/// This function will **overwrite** the contents of `to`.
+///
+/// Note that if `from` and `to` both point to the same file, then the file
+/// will likely get truncated by this operation.
+///
+/// # Example
+///
+/// ```rust
+/// use std::fs;
+///
+/// fs::copy("foo.txt", "bar.txt");
+/// ```
+///
+/// # Errors
+///
+/// This function will return an error in the following situations, but is not
+/// limited to just these cases:
+///
+/// * The `from` path is not a file
+/// * The `from` file does not exist
+/// * The current process does not have the permission rights to access
+///   `from` or write `to`
+pub fn copy<P: AsPath + ?Sized, Q: AsPath + ?Sized>(from: &P, to: &Q)
+                                                    -> io::Result<u64> {
+    let from = from.as_path();
+    if !from.is_file() {
+        return Err(Error::new(ErrorKind::MismatchedFileTypeForOperation,
+                              "the source path is not an existing file",
+                              None))
+    }
+
+    let mut reader = try!(File::open(from));
+    let mut writer = try!(File::create(to));
+    let perm = try!(reader.metadata()).permissions();
+
+    let ret = try!(io::copy(&mut reader, &mut writer));
+    try!(set_permissions(to, perm));
+    Ok(ret)
+}
+
+/// Creates a new hard link on the filesystem.
+///
+/// The `dst` path will be a link pointing to the `src` path. Note that systems
+/// often require these two paths to both be located on the same filesystem.
+pub fn hard_link<P: AsPath + ?Sized, Q: AsPath + ?Sized>(src: &P, dst: &Q)
+                                                         -> io::Result<()> {
+    fs_imp::link(src.as_path(), dst.as_path())
+}
+
+/// Creates a new soft link on the filesystem.
+///
+/// The `dst` path will be a soft link pointing to the `src` path.
+pub fn soft_link<P: AsPath + ?Sized, Q: AsPath + ?Sized>(src: &P, dst: &Q)
+                                                         -> io::Result<()> {
+    fs_imp::symlink(src.as_path(), dst.as_path())
+}
+
+/// Reads a soft link, returning the file that the link points to.
+///
+/// # Errors
+///
+/// This function will return an error on failure. Failure conditions include
+/// reading a file that does not exist or reading a file that is not a soft
+/// link.
+pub fn read_link<P: AsPath + ?Sized>(path: &P) -> io::Result<PathBuf> {
+    fs_imp::readlink(path.as_path())
+}
+
+/// Create a new, empty directory at the provided path
+///
+/// # Example
+///
+/// ```rust
+/// use std::fs;
+///
+/// fs::create_dir("/some/dir");
+/// ```
+///
+/// # Errors
+///
+/// This function will return an error if the user lacks permissions to make a
+/// new directory at the provided `path`, or if the directory already exists.
+pub fn create_dir<P: AsPath + ?Sized>(path: &P) -> io::Result<()> {
+    fs_imp::mkdir(path.as_path())
+}
+
+/// Recursively create a directory and all of its parent components if they
+/// are missing.
+///
+/// # Errors
+///
+/// This function will fail if any directory in the path specified by `path`
+/// does not already exist and it could not be created otherwise. The specific
+/// error conditions for when a directory is being created (after it is
+/// determined to not exist) are outlined by `fs::create_dir`.
+pub fn create_dir_all<P: AsPath + ?Sized>(path: &P) -> io::Result<()> {
+    let path = path.as_path();
+    if path.is_dir() { return Ok(()) }
+    match path.parent() {
+        Some(p) if p != path => try!(create_dir_all(p)),
+        _ => {}
+    }
+    // If the file name of the given `path` is blank then the creation of the
+    // parent directory will have taken care of the whole path for us, so we're
+    // good to go.
+    if path.file_name().is_none() {
+        Ok(())
+    } else {
+        create_dir(path)
+    }
+}
+
+/// Remove an existing, empty directory
+///
+/// # Example
+///
+/// ```rust
+/// use std::fs;
+///
+/// fs::remove_dir("/some/dir");
+/// ```
+///
+/// # Errors
+///
+/// This function will return an error if the user lacks permissions to remove
+/// the directory at the provided `path`, or if the directory isn't empty.
+pub fn remove_dir<P: AsPath + ?Sized>(path: &P) -> io::Result<()> {
+    fs_imp::rmdir(path.as_path())
+}
+
+/// Removes a directory at this path, after removing all its contents. Use
+/// carefully!
+///
+/// This function does **not** follow soft links and it will simply remove the
+/// soft link itself.
+///
+/// # Errors
+///
+/// See `file::remove_file` and `fs::remove_dir`
+pub fn remove_dir_all<P: AsPath + ?Sized>(path: &P) -> io::Result<()> {
+    let path = path.as_path();
+    for child in try!(read_dir(path)) {
+        let child = try!(child).path();
+        let stat = try!(lstat(&*child));
+        if stat.is_dir() {
+            try!(remove_dir_all(&*child));
+        } else {
+            try!(remove_file(&*child));
+        }
+    }
+    return remove_dir(path);
+
+    #[cfg(unix)]
+    fn lstat(path: &Path) -> io::Result<fs_imp::FileAttr> { fs_imp::lstat(path) }
+    #[cfg(windows)]
+    fn lstat(path: &Path) -> io::Result<fs_imp::FileAttr> { fs_imp::stat(path) }
+}
+
+/// Returns an iterator over the entries within a directory.
+///
+/// The iterator will yield instances of `io::Result<DirEntry>`. New errors may
+/// be encountered after an iterator is initially constructed.
+///
+/// # Example
+///
+/// ```rust
+/// use std::io;
+/// use std::fs::{self, PathExt, DirEntry};
+/// use std::path::Path;
+///
+/// // one possible implementation of fs::walk_dir only visiting files
+/// fn visit_dirs(dir: &Path, cb: &mut FnMut(DirEntry)) -> io::Result<()> {
+///     if dir.is_dir() {
+///         for entry in try!(fs::read_dir(dir)) {
+///             let entry = try!(entry);
+///             if entry.path().is_dir() {
+///                 try!(visit_dirs(&entry.path(), cb));
+///             } else {
+///                 cb(entry);
+///             }
+///         }
+///     }
+///     Ok(())
+/// }
+/// ```
+///
+/// # Errors
+///
+/// This function will return an error if the provided `path` doesn't exist, if
+/// the process lacks permissions to view the contents or if the `path` points
+/// at a non-directory file
+pub fn read_dir<P: AsPath + ?Sized>(path: &P) -> io::Result<ReadDir> {
+    fs_imp::readdir(path.as_path()).map(ReadDir)
+}
+
+/// Returns an iterator that will recursively walk the directory structure
+/// rooted at `path`.
+///
+/// The path given will not be iterated over, and this will perform iteration in
+/// some top-down order.  The contents of unreadable subdirectories are ignored.
+///
+/// The iterator will yield instances of `io::Result<DirEntry>`. New errors may
+/// be encountered after an iterator is initially constructed.
+pub fn walk_dir<P: AsPath + ?Sized>(path: &P) -> io::Result<WalkDir> {
+    let start = try!(read_dir(path));
+    Ok(WalkDir { cur: Some(start), stack: Vec::new() })
+}
+
+impl Iterator for WalkDir {
+    type Item = io::Result<DirEntry>;
+
+    fn next(&mut self) -> Option<io::Result<DirEntry>> {
+        loop {
+            if let Some(ref mut cur) = self.cur {
+                match cur.next() {
+                    Some(Err(e)) => return Some(Err(e)),
+                    Some(Ok(next)) => {
+                        let path = next.path();
+                        if path.is_dir() {
+                            self.stack.push(read_dir(&*path));
+                        }
+                        return Some(Ok(next))
+                    }
+                    None => {}
+                }
+            }
+            self.cur = None;
+            match self.stack.pop() {
+                Some(Err(e)) => return Some(Err(e)),
+                Some(Ok(next)) => self.cur = Some(next),
+                None => return None,
+            }
+        }
+    }
+}
+
+/// Utility methods for paths.
+pub trait PathExt {
+    /// Get information on the file, directory, etc at this path.
+    ///
+    /// Consult the `fs::stat` documentation for more info.
+    ///
+    /// This call preserves identical runtime/error semantics with `file::stat`.
+    fn metadata(&self) -> io::Result<Metadata>;
+
+    /// Boolean value indicator whether the underlying file exists on the local
+    /// filesystem. Returns false in exactly the cases where `fs::stat` fails.
+    fn exists(&self) -> bool;
+
+    /// Whether the underlying implementation (be it a file path, or something
+    /// else) points at a "regular file" on the FS. Will return false for paths
+    /// to non-existent locations or directories or other non-regular files
+    /// (named pipes, etc). Follows links when making this determination.
+    fn is_file(&self) -> bool;
+
+    /// Whether the underlying implementation (be it a file path, or something
+    /// else) is pointing at a directory in the underlying FS. Will return
+    /// false for paths to non-existent locations or if the item is not a
+    /// directory (eg files, named pipes, etc). Follows links when making this
+    /// determination.
+    fn is_dir(&self) -> bool;
+}
+
+impl PathExt for Path {
+    fn metadata(&self) -> io::Result<Metadata> { metadata(self) }
+
+    fn exists(&self) -> bool { metadata(self).is_ok() }
+
+    fn is_file(&self) -> bool {
+        metadata(self).map(|s| s.is_file()).unwrap_or(false)
+    }
+    fn is_dir(&self) -> bool {
+        metadata(self).map(|s| s.is_dir()).unwrap_or(false)
+    }
+}
+
+/// Changes the timestamps for a file's last modification and access time.
+///
+/// The file at the path specified will have its last access time set to
+/// `atime` and its modification time set to `mtime`. The times specified should
+/// be in milliseconds.
+pub fn set_file_times<P: AsPath + ?Sized>(path: &P, accessed: u64,
+                                          modified: u64) -> io::Result<()> {
+    fs_imp::utimes(path.as_path(), accessed, modified)
+}
+
+/// Changes the permissions found on a file or a directory.
+///
+/// # Example
+///
+/// ```
+/// # fn foo() -> std::io::Result<()> {
+/// use std::fs;
+///
+/// let mut perms = try!(fs::metadata("foo.txt")).permissions();
+/// perms.set_readonly(true);
+/// try!(fs::set_permissions("foo.txt", perms));
+/// # Ok(())
+/// # }
+/// ```
+///
+/// # Errors
+///
+/// This function will return an error if the provided `path` doesn't exist, if
+/// the process lacks permissions to change the attributes of the file, or if
+/// some other I/O error is encountered.
+pub fn set_permissions<P: AsPath + ?Sized>(path: &P, perm: Permissions)
+                                           -> io::Result<()> {
+    fs_imp::set_perm(path.as_path(), perm.0)
+}
+
+#[cfg(test)]
+mod tests {
+    #![allow(deprecated)] //rand
+
+    use prelude::v1::*;
+    use io::prelude::*;
+
+    use fs::{self, File, OpenOptions};
+    use io::{ErrorKind, SeekFrom};
+    use path::PathBuf;
+    use path::Path as Path2;
+    use os;
+    use rand::{self, StdRng, Rng};
+    use str;
+
+    macro_rules! check { ($e:expr) => (
+        match $e {
+            Ok(t) => t,
+            Err(e) => panic!("{} failed with: {}", stringify!($e), e),
+        }
+    ) }
+
+    macro_rules! error { ($e:expr, $s:expr) => (
+        match $e {
+            Ok(_) => panic!("Unexpected success. Should've been: {:?}", $s),
+            Err(ref err) => assert!(err.to_string().contains($s.as_slice()),
+                                    format!("`{}` did not contain `{}`", err, $s))
+        }
+    ) }
+
+    pub struct TempDir(PathBuf);
+
+    impl TempDir {
+        fn join(&self, path: &str) -> PathBuf {
+            let TempDir(ref p) = *self;
+            p.join(path)
+        }
+
+        fn path<'a>(&'a self) -> &'a Path2 {
+            let TempDir(ref p) = *self;
+            p
+        }
+    }
+
+    impl Drop for TempDir {
+        fn drop(&mut self) {
+            // Gee, seeing how we're testing the fs module I sure hope that we
+            // at least implement this correctly!
+            let TempDir(ref p) = *self;
+            check!(fs::remove_dir_all(p));
+        }
+    }
+
+    pub fn tmpdir() -> TempDir {
+        let s = os::tmpdir();
+        let p = Path2::new(s.as_str().unwrap());
+        let ret = p.join(&format!("rust-{}", rand::random::<u32>()));
+        check!(fs::create_dir(&ret));
+        TempDir(ret)
+    }
+
+    #[test]
+    fn file_test_io_smoke_test() {
+        let message = "it's alright. have a good time";
+        let tmpdir = tmpdir();
+        let filename = &tmpdir.join("file_rt_io_file_test.txt");
+        {
+            let mut write_stream = check!(File::create(filename));
+            check!(write_stream.write(message.as_bytes()));
+        }
+        {
+            let mut read_stream = check!(File::open(filename));
+            let mut read_buf = [0; 1028];
+            let read_str = match check!(read_stream.read(&mut read_buf)) {
+                -1|0 => panic!("shouldn't happen"),
+                n => str::from_utf8(&read_buf[..n]).unwrap().to_string()
+            };
+            assert_eq!(read_str.as_slice(), message);
+        }
+        check!(fs::remove_file(filename));
+    }
+
+    #[test]
+    fn invalid_path_raises() {
+        let tmpdir = tmpdir();
+        let filename = &tmpdir.join("file_that_does_not_exist.txt");
+        let result = File::open(filename);
+
+        if cfg!(unix) {
+            error!(result, "o such file or directory");
+        }
+        // error!(result, "couldn't open path as file");
+        // error!(result, format!("path={}; mode=open; access=read", filename.display()));
+    }
+
+    #[test]
+    fn file_test_iounlinking_invalid_path_should_raise_condition() {
+        let tmpdir = tmpdir();
+        let filename = &tmpdir.join("file_another_file_that_does_not_exist.txt");
+
+        let result = fs::remove_file(filename);
+
+        if cfg!(unix) {
+            error!(result, "o such file or directory");
+        }
+        // error!(result, "couldn't unlink path");
+        // error!(result, format!("path={}", filename.display()));
+    }
+
+    #[test]
+    fn file_test_io_non_positional_read() {
+        let message: &str = "ten-four";
+        let mut read_mem = [0; 8];
+        let tmpdir = tmpdir();
+        let filename = &tmpdir.join("file_rt_io_file_test_positional.txt");
+        {
+            let mut rw_stream = check!(File::create(filename));
+            check!(rw_stream.write(message.as_bytes()));
+        }
+        {
+            let mut read_stream = check!(File::open(filename));
+            {
+                let read_buf = &mut read_mem[0..4];
+                check!(read_stream.read(read_buf));
+            }
+            {
+                let read_buf = &mut read_mem[4..8];
+                check!(read_stream.read(read_buf));
+            }
+        }
+        check!(fs::remove_file(filename));
+        let read_str = str::from_utf8(&read_mem).unwrap();
+        assert_eq!(read_str, message);
+    }
+
+    #[test]
+    fn file_test_io_seek_and_tell_smoke_test() {
+        let message = "ten-four";
+        let mut read_mem = [0; 4];
+        let set_cursor = 4 as u64;
+        let mut tell_pos_pre_read;
+        let mut tell_pos_post_read;
+        let tmpdir = tmpdir();
+        let filename = &tmpdir.join("file_rt_io_file_test_seeking.txt");
+        {
+            let mut rw_stream = check!(File::create(filename));
+            check!(rw_stream.write(message.as_bytes()));
+        }
+        {
+            let mut read_stream = check!(File::open(filename));
+            check!(read_stream.seek(SeekFrom::Start(set_cursor)));
+            tell_pos_pre_read = check!(read_stream.seek(SeekFrom::Current(0)));
+            check!(read_stream.read(&mut read_mem));
+            tell_pos_post_read = check!(read_stream.seek(SeekFrom::Current(0)));
+        }
+        check!(fs::remove_file(filename));
+        let read_str = str::from_utf8(&read_mem).unwrap();
+        assert_eq!(read_str, &message[4..8]);
+        assert_eq!(tell_pos_pre_read, set_cursor);
+        assert_eq!(tell_pos_post_read, message.len() as u64);
+    }
+
+    #[test]
+    fn file_test_io_seek_and_write() {
+        let initial_msg =   "food-is-yummy";
+        let overwrite_msg =    "-the-bar!!";
+        let final_msg =     "foo-the-bar!!";
+        let seek_idx = 3;
+        let mut read_mem = [0; 13];
+        let tmpdir = tmpdir();
+        let filename = &tmpdir.join("file_rt_io_file_test_seek_and_write.txt");
+        {
+            let mut rw_stream = check!(File::create(filename));
+            check!(rw_stream.write(initial_msg.as_bytes()));
+            check!(rw_stream.seek(SeekFrom::Start(seek_idx)));
+            check!(rw_stream.write(overwrite_msg.as_bytes()));
+        }
+        {
+            let mut read_stream = check!(File::open(filename));
+            check!(read_stream.read(&mut read_mem));
+        }
+        check!(fs::remove_file(filename));
+        let read_str = str::from_utf8(&read_mem).unwrap();
+        assert!(read_str == final_msg);
+    }
+
+    #[test]
+    fn file_test_io_seek_shakedown() {
+        //                   01234567890123
+        let initial_msg =   "qwer-asdf-zxcv";
+        let chunk_one: &str = "qwer";
+        let chunk_two: &str = "asdf";
+        let chunk_three: &str = "zxcv";
+        let mut read_mem = [0; 4];
+        let tmpdir = tmpdir();
+        let filename = &tmpdir.join("file_rt_io_file_test_seek_shakedown.txt");
+        {
+            let mut rw_stream = check!(File::create(filename));
+            check!(rw_stream.write(initial_msg.as_bytes()));
+        }
+        {
+            let mut read_stream = check!(File::open(filename));
+
+            check!(read_stream.seek(SeekFrom::End(-4)));
+            check!(read_stream.read(&mut read_mem));
+            assert_eq!(str::from_utf8(&read_mem).unwrap(), chunk_three);
+
+            check!(read_stream.seek(SeekFrom::Current(-9)));
+            check!(read_stream.read(&mut read_mem));
+            assert_eq!(str::from_utf8(&read_mem).unwrap(), chunk_two);
+
+            check!(read_stream.seek(SeekFrom::Start(0)));
+            check!(read_stream.read(&mut read_mem));
+            assert_eq!(str::from_utf8(&read_mem).unwrap(), chunk_one);
+        }
+        check!(fs::remove_file(filename));
+    }
+
+    #[test]
+    fn file_test_stat_is_correct_on_is_file() {
+        let tmpdir = tmpdir();
+        let filename = &tmpdir.join("file_stat_correct_on_is_file.txt");
+        {
+            let mut opts = OpenOptions::new();
+            let mut fs = check!(opts.read(true).write(true)
+                                    .create(true).open(filename));
+            let msg = "hw";
+            fs.write(msg.as_bytes()).unwrap();
+
+            let fstat_res = check!(fs.metadata());
+            assert!(fstat_res.is_file());
+        }
+        let stat_res_fn = check!(fs::metadata(filename));
+        assert!(stat_res_fn.is_file());
+        let stat_res_meth = check!(filename.metadata());
+        assert!(stat_res_meth.is_file());
+        check!(fs::remove_file(filename));
+    }
+
+    #[test]
+    fn file_test_stat_is_correct_on_is_dir() {
+        let tmpdir = tmpdir();
+        let filename = &tmpdir.join("file_stat_correct_on_is_dir");
+        check!(fs::create_dir(filename));
+        let stat_res_fn = check!(fs::metadata(filename));
+        assert!(stat_res_fn.is_dir());
+        let stat_res_meth = check!(filename.metadata());
+        assert!(stat_res_meth.is_dir());
+        check!(fs::remove_dir(filename));
+    }
+
+    #[test]
+    fn file_test_fileinfo_false_when_checking_is_file_on_a_directory() {
+        let tmpdir = tmpdir();
+        let dir = &tmpdir.join("fileinfo_false_on_dir");
+        check!(fs::create_dir(dir));
+        assert!(dir.is_file() == false);
+        check!(fs::remove_dir(dir));
+    }
+
+    #[test]
+    fn file_test_fileinfo_check_exists_before_and_after_file_creation() {
+        let tmpdir = tmpdir();
+        let file = &tmpdir.join("fileinfo_check_exists_b_and_a.txt");
+        check!(check!(File::create(file)).write(b"foo"));
+        assert!(file.exists());
+        check!(fs::remove_file(file));
+        assert!(!file.exists());
+    }
+
+    #[test]
+    fn file_test_directoryinfo_check_exists_before_and_after_mkdir() {
+        let tmpdir = tmpdir();
+        let dir = &tmpdir.join("before_and_after_dir");
+        assert!(!dir.exists());
+        check!(fs::create_dir(dir));
+        assert!(dir.exists());
+        assert!(dir.is_dir());
+        check!(fs::remove_dir(dir));
+        assert!(!dir.exists());
+    }
+
+    #[test]
+    fn file_test_directoryinfo_readdir() {
+        let tmpdir = tmpdir();
+        let dir = &tmpdir.join("di_readdir");
+        check!(fs::create_dir(dir));
+        let prefix = "foo";
+        for n in range(0, 3) {
+            let f = dir.join(&format!("{}.txt", n));
+            let mut w = check!(File::create(&f));
+            let msg_str = format!("{}{}", prefix, n.to_string());
+            let msg = msg_str.as_bytes();
+            check!(w.write(msg));
+        }
+        let files = check!(fs::read_dir(dir));
+        let mut mem = [0u8; 4];
+        for f in files {
+            let f = f.unwrap().path();
+            {
+                let n = f.file_stem().unwrap();
+                check!(check!(File::open(&f)).read(&mut mem));
+                let read_str = str::from_utf8(&mem).unwrap();
+                let expected = format!("{}{}", prefix, n.to_str().unwrap());
+                assert_eq!(expected.as_slice(), read_str);
+            }
+            check!(fs::remove_file(&f));
+        }
+        check!(fs::remove_dir(dir));
+    }
+
+    #[test]
+    fn file_test_walk_dir() {
+        let tmpdir = tmpdir();
+        let dir = &tmpdir.join("walk_dir");
+        check!(fs::create_dir(dir));
+
+        let dir1 = &dir.join("01/02/03");
+        check!(fs::create_dir_all(dir1));
+        check!(File::create(&dir1.join("04")));
+
+        let dir2 = &dir.join("11/12/13");
+        check!(fs::create_dir_all(dir2));
+        check!(File::create(&dir2.join("14")));
+
+        let files = check!(fs::walk_dir(dir));
+        let mut cur = [0u8; 2];
+        for f in files {
+            let f = f.unwrap().path();
+            let stem = f.file_stem().unwrap().to_str().unwrap();
+            let root = stem.as_bytes()[0] - b'0';
+            let name = stem.as_bytes()[1] - b'0';
+            assert!(cur[root as usize] < name);
+            cur[root as usize] = name;
+        }
+
+        check!(fs::remove_dir_all(dir));
+    }
+
+    #[test]
+    fn mkdir_path_already_exists_error() {
+        let tmpdir = tmpdir();
+        let dir = &tmpdir.join("mkdir_error_twice");
+        check!(fs::create_dir(dir));
+        let e = fs::create_dir(dir).err().unwrap();
+        assert_eq!(e.kind(), ErrorKind::PathAlreadyExists);
+    }
+
+    #[test]
+    fn recursive_mkdir() {
+        let tmpdir = tmpdir();
+        let dir = tmpdir.join("d1/d2");
+        check!(fs::create_dir_all(&dir));
+        assert!(dir.is_dir())
+    }
+
+    #[test]
+    fn recursive_mkdir_failure() {
+        let tmpdir = tmpdir();
+        let dir = tmpdir.join("d1");
+        let file = dir.join("f1");
+
+        check!(fs::create_dir_all(&dir));
+        check!(File::create(&file));
+
+        let result = fs::create_dir_all(&file);
+
+        assert!(result.is_err());
+        // error!(result, "couldn't recursively mkdir");
+        // error!(result, "couldn't create directory");
+        // error!(result, "mode=0700");
+        // error!(result, format!("path={}", file.display()));
+    }
+
+    #[test]
+    fn recursive_mkdir_slash() {
+        check!(fs::create_dir_all(&Path2::new("/")));
+    }
+
+    // FIXME(#12795) depends on lstat to work on windows
+    #[cfg(not(windows))]
+    #[test]
+    fn recursive_rmdir() {
+        let tmpdir = tmpdir();
+        let d1 = tmpdir.join("d1");
+        let dt = d1.join("t");
+        let dtt = dt.join("t");
+        let d2 = tmpdir.join("d2");
+        let canary = d2.join("do_not_delete");
+        check!(fs::create_dir_all(&dtt));
+        check!(fs::create_dir_all(&d2));
+        check!(check!(File::create(&canary)).write(b"foo"));
+        check!(fs::soft_link(&d2, &dt.join("d2")));
+        check!(fs::remove_dir_all(&d1));
+
+        assert!(!d1.is_dir());
+        assert!(canary.exists());
+    }
+
+    #[test]
+    fn unicode_path_is_dir() {
+        assert!(Path2::new(".").is_dir());
+        assert!(!Path2::new("test/stdtest/fs.rs").is_dir());
+
+        let tmpdir = tmpdir();
+
+        let mut dirpath = tmpdir.path().to_path_buf();
+        dirpath.push(&format!("test-가一ー你好"));
+        check!(fs::create_dir(&dirpath));
+        assert!(dirpath.is_dir());
+
+        let mut filepath = dirpath;
+        filepath.push("unicode-file-\u{ac00}\u{4e00}\u{30fc}\u{4f60}\u{597d}.rs");
+        check!(File::create(&filepath)); // ignore return; touch only
+        assert!(!filepath.is_dir());
+        assert!(filepath.exists());
+    }
+
+    #[test]
+    fn unicode_path_exists() {
+        assert!(Path2::new(".").exists());
+        assert!(!Path2::new("test/nonexistent-bogus-path").exists());
+
+        let tmpdir = tmpdir();
+        let unicode = tmpdir.path();
+        let unicode = unicode.join(&format!("test-각丁ー再见"));
+        check!(fs::create_dir(&unicode));
+        assert!(unicode.exists());
+        assert!(!Path2::new("test/unicode-bogus-path-각丁ー再见").exists());
+    }
+
+    #[test]
+    fn copy_file_does_not_exist() {
+        let from = Path2::new("test/nonexistent-bogus-path");
+        let to = Path2::new("test/other-bogus-path");
+
+        match fs::copy(&from, &to) {
+            Ok(..) => panic!(),
+            Err(..) => {
+                assert!(!from.exists());
+                assert!(!to.exists());
+            }
+        }
+    }
+
+    #[test]
+    fn copy_file_ok() {
+        let tmpdir = tmpdir();
+        let input = tmpdir.join("in.txt");
+        let out = tmpdir.join("out.txt");
+
+        check!(check!(File::create(&input)).write(b"hello"));
+        check!(fs::copy(&input, &out));
+        let mut v = Vec::new();
+        check!(check!(File::open(&out)).read_to_end(&mut v));
+        assert_eq!(v.as_slice(), b"hello");
+
+        assert_eq!(check!(input.metadata()).permissions(),
+                   check!(out.metadata()).permissions());
+    }
+
+    #[test]
+    fn copy_file_dst_dir() {
+        let tmpdir = tmpdir();
+        let out = tmpdir.join("out");
+
+        check!(File::create(&out));
+        match fs::copy(&*out, tmpdir.path()) {
+            Ok(..) => panic!(), Err(..) => {}
+        }
+    }
+
+    #[test]
+    fn copy_file_dst_exists() {
+        let tmpdir = tmpdir();
+        let input = tmpdir.join("in");
+        let output = tmpdir.join("out");
+
+        check!(check!(File::create(&input)).write("foo".as_bytes()));
+        check!(check!(File::create(&output)).write("bar".as_bytes()));
+        check!(fs::copy(&input, &output));
+
+        let mut v = Vec::new();
+        check!(check!(File::open(&output)).read_to_end(&mut v));
+        assert_eq!(v, b"foo".to_vec());
+    }
+
+    #[test]
+    fn copy_file_src_dir() {
+        let tmpdir = tmpdir();
+        let out = tmpdir.join("out");
+
+        match fs::copy(tmpdir.path(), &out) {
+            Ok(..) => panic!(), Err(..) => {}
+        }
+        assert!(!out.exists());
+    }
+
+    #[test]
+    fn copy_file_preserves_perm_bits() {
+        let tmpdir = tmpdir();
+        let input = tmpdir.join("in.txt");
+        let out = tmpdir.join("out.txt");
+
+        let attr = check!(check!(File::create(&input)).metadata());
+        let mut p = attr.permissions();
+        p.set_readonly(true);
+        check!(fs::set_permissions(&input, p));
+        check!(fs::copy(&input, &out));
+        assert!(check!(out.metadata()).permissions().readonly());
+    }
+
+    #[cfg(not(windows))] // FIXME(#10264) operation not permitted?
+    #[test]
+    fn symlinks_work() {
+        let tmpdir = tmpdir();
+        let input = tmpdir.join("in.txt");
+        let out = tmpdir.join("out.txt");
+
+        check!(check!(File::create(&input)).write("foobar".as_bytes()));
+        check!(fs::soft_link(&input, &out));
+        // if cfg!(not(windows)) {
+        //     assert_eq!(check!(lstat(&out)).kind, FileType::Symlink);
+        //     assert_eq!(check!(out.lstat()).kind, FileType::Symlink);
+        // }
+        assert_eq!(check!(fs::metadata(&out)).len(),
+                   check!(fs::metadata(&input)).len());
+        let mut v = Vec::new();
+        check!(check!(File::open(&out)).read_to_end(&mut v));
+        assert_eq!(v, b"foobar".to_vec());
+    }
+
+    #[cfg(not(windows))] // apparently windows doesn't like symlinks
+    #[test]
+    fn symlink_noexist() {
+        let tmpdir = tmpdir();
+        // symlinks can point to things that don't exist
+        check!(fs::soft_link(&tmpdir.join("foo"), &tmpdir.join("bar")));
+        assert_eq!(check!(fs::read_link(&tmpdir.join("bar"))),
+                   tmpdir.join("foo"));
+    }
+
+    #[test]
+    fn readlink_not_symlink() {
+        let tmpdir = tmpdir();
+        match fs::read_link(tmpdir.path()) {
+            Ok(..) => panic!("wanted a failure"),
+            Err(..) => {}
+        }
+    }
+
+    #[test]
+    fn links_work() {
+        let tmpdir = tmpdir();
+        let input = tmpdir.join("in.txt");
+        let out = tmpdir.join("out.txt");
+
+        check!(check!(File::create(&input)).write("foobar".as_bytes()));
+        check!(fs::hard_link(&input, &out));
+        assert_eq!(check!(fs::metadata(&out)).len(),
+                   check!(fs::metadata(&input)).len());
+        assert_eq!(check!(fs::metadata(&out)).len(),
+                   check!(input.metadata()).len());
+        let mut v = Vec::new();
+        check!(check!(File::open(&out)).read_to_end(&mut v));
+        assert_eq!(v, b"foobar".to_vec());
+
+        // can't link to yourself
+        match fs::hard_link(&input, &input) {
+            Ok(..) => panic!("wanted a failure"),
+            Err(..) => {}
+        }
+        // can't link to something that doesn't exist
+        match fs::hard_link(&tmpdir.join("foo"), &tmpdir.join("bar")) {
+            Ok(..) => panic!("wanted a failure"),
+            Err(..) => {}
+        }
+    }
+
+    #[test]
+    fn chmod_works() {
+        let tmpdir = tmpdir();
+        let file = tmpdir.join("in.txt");
+
+        check!(File::create(&file));
+        let attr = check!(fs::metadata(&file));
+        assert!(!attr.permissions().readonly());
+        let mut p = attr.permissions();
+        p.set_readonly(true);
+        check!(fs::set_permissions(&file, p.clone()));
+        let attr = check!(fs::metadata(&file));
+        assert!(attr.permissions().readonly());
+
+        match fs::set_permissions(&tmpdir.join("foo"), p) {
+            Ok(..) => panic!("wanted a panic"),
+            Err(..) => {}
+        }
+    }
+
+    #[test]
+    fn sync_doesnt_kill_anything() {
+        let tmpdir = tmpdir();
+        let path = tmpdir.join("in.txt");
+
+        let mut file = check!(File::create(&path));
+        check!(file.sync_all());
+        check!(file.sync_data());
+        check!(file.write(b"foo"));
+        check!(file.sync_all());
+        check!(file.sync_data());
+    }
+
+    #[test]
+    fn truncate_works() {
+        let tmpdir = tmpdir();
+        let path = tmpdir.join("in.txt");
+
+        let mut file = check!(File::create(&path));
+        check!(file.write(b"foo"));
+        check!(file.sync_all());
+
+        // Do some simple things with truncation
+        assert_eq!(check!(file.metadata()).len(), 3);
+        check!(file.set_len(10));
+        assert_eq!(check!(file.metadata()).len(), 10);
+        check!(file.write(b"bar"));
+        check!(file.sync_all());
+        assert_eq!(check!(file.metadata()).len(), 10);
+
+        let mut v = Vec::new();
+        check!(check!(File::open(&path)).read_to_end(&mut v));
+        assert_eq!(v, b"foobar\0\0\0\0".to_vec());
+
+        // Truncate to a smaller length, don't seek, and then write something.
+        // Ensure that the intermediate zeroes are all filled in (we're seeked
+        // past the end of the file).
+        check!(file.set_len(2));
+        assert_eq!(check!(file.metadata()).len(), 2);
+        check!(file.write(b"wut"));
+        check!(file.sync_all());
+        assert_eq!(check!(file.metadata()).len(), 9);
+        let mut v = Vec::new();
+        check!(check!(File::open(&path)).read_to_end(&mut v));
+        assert_eq!(v, b"fo\0\0\0\0wut".to_vec());
+    }
+
+    #[test]
+    fn open_flavors() {
+        use fs::OpenOptions as OO;
+        fn c<T: Clone>(t: &T) -> T { t.clone() }
+
+        let tmpdir = tmpdir();
+
+        let mut r = OO::new(); r.read(true);
+        let mut w = OO::new(); w.write(true);
+        let mut rw = OO::new(); rw.write(true).read(true);
+
+        match r.open(&tmpdir.join("a")) {
+            Ok(..) => panic!(), Err(..) => {}
+        }
+
+        // Perform each one twice to make sure that it succeeds the second time
+        // (where the file exists)
+        check!(c(&w).create(true).open(&tmpdir.join("b")));
+        assert!(tmpdir.join("b").exists());
+        check!(c(&w).create(true).open(&tmpdir.join("b")));
+        check!(w.open(&tmpdir.join("b")));
+
+        check!(c(&rw).create(true).open(&tmpdir.join("c")));
+        assert!(tmpdir.join("c").exists());
+        check!(c(&rw).create(true).open(&tmpdir.join("c")));
+        check!(rw.open(&tmpdir.join("c")));
+
+        check!(c(&w).append(true).create(true).open(&tmpdir.join("d")));
+        assert!(tmpdir.join("d").exists());
+        check!(c(&w).append(true).create(true).open(&tmpdir.join("d")));
+        check!(c(&w).append(true).open(&tmpdir.join("d")));
+
+        check!(c(&rw).append(true).create(true).open(&tmpdir.join("e")));
+        assert!(tmpdir.join("e").exists());
+        check!(c(&rw).append(true).create(true).open(&tmpdir.join("e")));
+        check!(c(&rw).append(true).open(&tmpdir.join("e")));
+
+        check!(c(&w).truncate(true).create(true).open(&tmpdir.join("f")));
+        assert!(tmpdir.join("f").exists());
+        check!(c(&w).truncate(true).create(true).open(&tmpdir.join("f")));
+        check!(c(&w).truncate(true).open(&tmpdir.join("f")));
+
+        check!(c(&rw).truncate(true).create(true).open(&tmpdir.join("g")));
+        assert!(tmpdir.join("g").exists());
+        check!(c(&rw).truncate(true).create(true).open(&tmpdir.join("g")));
+        check!(c(&rw).truncate(true).open(&tmpdir.join("g")));
+
+        check!(check!(File::create(&tmpdir.join("h"))).write("foo".as_bytes()));
+        check!(r.open(&tmpdir.join("h")));
+        {
+            let mut f = check!(r.open(&tmpdir.join("h")));
+            assert!(f.write("wut".as_bytes()).is_err());
+        }
+        assert_eq!(check!(fs::metadata(&tmpdir.join("h"))).len(), 3);
+        {
+            let mut f = check!(c(&w).append(true).open(&tmpdir.join("h")));
+            check!(f.write("bar".as_bytes()));
+        }
+        assert_eq!(check!(fs::metadata(&tmpdir.join("h"))).len(), 6);
+        {
+            let mut f = check!(c(&w).truncate(true).open(&tmpdir.join("h")));
+            check!(f.write("bar".as_bytes()));
+        }
+        assert_eq!(check!(fs::metadata(&tmpdir.join("h"))).len(), 3);
+    }
+
+    #[test]
+    fn utime() {
+        let tmpdir = tmpdir();
+        let path = tmpdir.join("a");
+        check!(File::create(&path));
+        // These numbers have to be bigger than the time in the day to account
+        // for timezones Windows in particular will fail in certain timezones
+        // with small enough values
+        check!(fs::set_file_times(&path, 100000, 200000));
+        assert_eq!(check!(path.metadata()).accessed(), 100000);
+        assert_eq!(check!(path.metadata()).modified(), 200000);
+    }
+
+    #[test]
+    fn utime_noexist() {
+        let tmpdir = tmpdir();
+
+        match fs::set_file_times(&tmpdir.join("a"), 100, 200) {
+            Ok(..) => panic!(),
+            Err(..) => {}
+        }
+    }
+
+    #[test]
+    fn binary_file() {
+        let mut bytes = [0; 1024];
+        StdRng::new().ok().unwrap().fill_bytes(&mut bytes);
+
+        let tmpdir = tmpdir();
+
+        check!(check!(File::create(&tmpdir.join("test"))).write(&bytes));
+        let mut v = Vec::new();
+        check!(check!(File::open(&tmpdir.join("test"))).read_to_end(&mut v));
+        assert!(v == bytes.as_slice());
+    }
+
+    #[test]
+    fn unlink_readonly() {
+        let tmpdir = tmpdir();
+        let path = tmpdir.join("file");
+        check!(File::create(&path));
+        let mut perm = check!(fs::metadata(&path)).permissions();
+        perm.set_readonly(true);
+        check!(fs::set_permissions(&path, perm));
+        check!(fs::remove_file(&path));
+    }
+
+    #[test]
+    fn mkdir_trailing_slash() {
+        let tmpdir = tmpdir();
+        let path = tmpdir.join("file");
+        check!(fs::create_dir_all(&path.join("a/")));
+    }
+}
diff --git a/src/libstd/fs/tempdir.rs b/src/libstd/fs/tempdir.rs
new file mode 100644 (file)
index 0000000..79bdb35
--- /dev/null
@@ -0,0 +1,125 @@
+// 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 = "tempdir", reason = "needs an RFC before stabilization")]
+
+use prelude::v1::*;
+
+use env;
+use io::{self, Error, ErrorKind};
+use fs;
+use path::{self, PathBuf, AsPath};
+use rand::{thread_rng, Rng};
+
+/// A wrapper for a path to temporary directory implementing automatic
+/// scope-based deletion.
+pub struct TempDir {
+    path: Option<PathBuf>,
+}
+
+// How many times should we (re)try finding an unused random name? It should be
+// enough that an attacker will run out of luck before we run out of patience.
+const NUM_RETRIES: u32 = 1 << 31;
+// How many characters should we include in a random file name? It needs to
+// be enough to dissuade an attacker from trying to preemptively create names
+// of that length, but not so huge that we unnecessarily drain the random number
+// generator of entropy.
+const NUM_RAND_CHARS: uint = 12;
+
+impl TempDir {
+    /// Attempts to make a temporary directory inside of `tmpdir` whose name
+    /// will have the prefix `prefix`. The directory will be automatically
+    /// deleted once the returned wrapper is destroyed.
+    ///
+    /// If no directory can be created, `Err` is returned.
+    #[allow(deprecated)] // rand usage
+    pub fn new_in<P: AsPath + ?Sized>(tmpdir: &P, prefix: &str)
+                                      -> io::Result<TempDir> {
+        let storage;
+        let mut tmpdir = tmpdir.as_path();
+        if !tmpdir.is_absolute() {
+            let cur_dir = try!(env::current_dir());
+            storage = cur_dir.join(tmpdir);
+            tmpdir = &storage;
+            // return TempDir::new_in(&cur_dir.join(tmpdir), prefix);
+        }
+
+        let mut rng = thread_rng();
+        for _ in 0..NUM_RETRIES {
+            let suffix: String = rng.gen_ascii_chars().take(NUM_RAND_CHARS).collect();
+            let leaf = if prefix.len() > 0 {
+                format!("{}.{}", prefix, suffix)
+            } else {
+                // If we're given an empty string for a prefix, then creating a
+                // directory starting with "." would lead to it being
+                // semi-invisible on some systems.
+                suffix
+            };
+            let path = tmpdir.join(&leaf);
+            match fs::create_dir(&path) {
+                Ok(_) => return Ok(TempDir { path: Some(path) }),
+                Err(ref e) if e.kind() == ErrorKind::PathAlreadyExists => {}
+                Err(e) => return Err(e)
+            }
+        }
+
+        Err(Error::new(ErrorKind::PathAlreadyExists,
+                       "too many temporary directories already exist",
+                       None))
+    }
+
+    /// Attempts to make a temporary directory inside of `env::temp_dir()` whose
+    /// name will have the prefix `prefix`. The directory will be automatically
+    /// deleted once the returned wrapper is destroyed.
+    ///
+    /// If no directory can be created, `Err` is returned.
+    #[allow(deprecated)]
+    pub fn new(prefix: &str) -> io::Result<TempDir> {
+        TempDir::new_in(&env::temp_dir(), prefix)
+    }
+
+    /// Unwrap the wrapped `std::path::Path` from the `TempDir` wrapper.
+    /// This discards the wrapper so that the automatic deletion of the
+    /// temporary directory is prevented.
+    pub fn into_path(mut self) -> PathBuf {
+        self.path.take().unwrap()
+    }
+
+    /// Access the wrapped `std::path::Path` to the temporary directory.
+    pub fn path(&self) -> &path::Path {
+        self.path.as_ref().unwrap()
+    }
+
+    /// Close and remove the temporary directory
+    ///
+    /// Although `TempDir` removes the directory on drop, in the destructor
+    /// any errors are ignored. To detect errors cleaning up the temporary
+    /// directory, call `close` instead.
+    pub fn close(mut self) -> io::Result<()> {
+        self.cleanup_dir()
+    }
+
+    fn cleanup_dir(&mut self) -> io::Result<()> {
+        match self.path {
+            Some(ref p) => fs::remove_dir_all(p),
+            None => Ok(())
+        }
+    }
+}
+
+impl Drop for TempDir {
+    fn drop(&mut self) {
+        let _ = self.cleanup_dir();
+    }
+}
+
+// the tests for this module need to change the path using change_dir,
+// and this doesn't play nicely with other tests so these unit tests are located
+// in src/test/run-pass/tempfile.rs
index 9ef319782369d7090506bddfcb676b0e30f8640b..1135609959015d2fbee5d2565a0dd18affd69b7f 100644 (file)
@@ -48,7 +48,7 @@ pub fn with_capacity(cap: usize, inner: R) -> BufReader<R> {
     }
 
     /// Gets a reference to the underlying reader.
-    pub fn get_ref<'a>(&self) -> &R { &self.inner }
+    pub fn get_ref(&self) -> &R { &self.inner }
 
     /// Gets a mutable reference to the underlying reader.
     ///
@@ -155,9 +155,9 @@ fn flush_buf(&mut self) -> io::Result<()> {
         if written > 0 {
             // NB: would be better expressed as .remove(0..n) if it existed
             unsafe {
-                ptr::copy_memory(self.buf.as_mut_ptr(),
-                                 self.buf.as_ptr().offset(written as isize),
-                                 len - written);
+                ptr::copy(self.buf.as_mut_ptr(),
+                          self.buf.as_ptr().offset(written as isize),
+                          len - written);
             }
         }
         self.buf.truncate(len - written);
index f6cb4a8c9f36988f3b834b55261f1394eda32e70..b1779587528c26b20ca9635cca37e48bbdc851ba 100644 (file)
@@ -173,7 +173,7 @@ fn test_mem_writer() {
         assert_eq!(writer.write(&[1, 2, 3]), Ok(3));
         assert_eq!(writer.write(&[4, 5, 6, 7]), Ok(4));
         let b: &[_] = &[0, 1, 2, 3, 4, 5, 6, 7];
-        assert_eq!(&writer.get_ref()[], b);
+        assert_eq!(&writer.get_ref()[..], b);
     }
 
     #[test]
@@ -369,28 +369,28 @@ fn test_seekable_mem_writer() {
         assert_eq!(writer.write(&[4, 5, 6, 7]), Ok(4));
         assert_eq!(writer.position(), 8);
         let b: &[_] = &[0, 1, 2, 3, 4, 5, 6, 7];
-        assert_eq!(&writer.get_ref()[], b);
+        assert_eq!(&writer.get_ref()[..], b);
 
         assert_eq!(writer.seek(SeekFrom::Start(0)), Ok(0));
         assert_eq!(writer.position(), 0);
         assert_eq!(writer.write(&[3, 4]), Ok(2));
         let b: &[_] = &[3, 4, 2, 3, 4, 5, 6, 7];
-        assert_eq!(&writer.get_ref()[], b);
+        assert_eq!(&writer.get_ref()[..], b);
 
         assert_eq!(writer.seek(SeekFrom::Current(1)), Ok(3));
         assert_eq!(writer.write(&[0, 1]), Ok(2));
         let b: &[_] = &[3, 4, 2, 0, 1, 5, 6, 7];
-        assert_eq!(&writer.get_ref()[], b);
+        assert_eq!(&writer.get_ref()[..], b);
 
         assert_eq!(writer.seek(SeekFrom::End(-1)), Ok(7));
         assert_eq!(writer.write(&[1, 2]), Ok(2));
         let b: &[_] = &[3, 4, 2, 0, 1, 5, 6, 1, 2];
-        assert_eq!(&writer.get_ref()[], b);
+        assert_eq!(&writer.get_ref()[..], b);
 
         assert_eq!(writer.seek(SeekFrom::End(1)), Ok(10));
         assert_eq!(writer.write(&[1]), Ok(1));
         let b: &[_] = &[3, 4, 2, 0, 1, 5, 6, 1, 2, 0, 1];
-        assert_eq!(&writer.get_ref()[], b);
+        assert_eq!(&writer.get_ref()[..], b);
     }
 
     #[test]
index caaedeeb2fc5469a2cbdb5ec75a4fbaccc0fdb15..b5bdeb7f181b0ddab0bebb3c25491c619d385ddc 100644 (file)
 #![feature(unsafe_no_drop_flag)]
 #![feature(macro_reexport)]
 #![feature(hash)]
+#![feature(unique)]
 #![cfg_attr(test, feature(test, rustc_private, env))]
 
 // Don't link to std. We are std.
index c70e92884ac653749ea3d9915323fe760b65b6aa..dbebede9f50e42881c627dec9aa41dac14f842d4 100644 (file)
 use net::{SocketAddr, IpAddr};
 use sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering};
 
+static PORT: AtomicUsize = ATOMIC_USIZE_INIT;
+
 pub fn next_test_ip4() -> SocketAddr {
-    static PORT: AtomicUsize = ATOMIC_USIZE_INIT;
     SocketAddr::new(IpAddr::new_v4(127, 0, 0, 1),
                     PORT.fetch_add(1, Ordering::SeqCst) as u16 + base_port())
 }
 
 pub fn next_test_ip6() -> SocketAddr {
-    static PORT: AtomicUsize = ATOMIC_USIZE_INIT;
     SocketAddr::new(IpAddr::new_v6(0, 0, 0, 0, 0, 0, 0, 1),
                     PORT.fetch_add(1, Ordering::SeqCst) as u16 + base_port())
 }
@@ -34,6 +34,6 @@ fn base_port() -> u16 {
     let dirs = ["32-opt", "32-nopt", "64-opt", "64-nopt", "64-opt-vg",
                 "all-opt", "snap3", "dist"];
     dirs.iter().enumerate().find(|&(_, dir)| {
-        cwd.as_str().unwrap().contains(dir)
+        cwd.to_str().unwrap().contains(dir)
     }).map(|p| p.0).unwrap_or(0) as u16 * 1000 + 19600
 }
index c2a6c515acc70b2978fdcd1f494884127549bc25..8bd19f063f0300c51cc9256b70f6c7f0d1aa5fba 100644 (file)
@@ -328,7 +328,7 @@ fn bytes_error() {
     fn read_bytes() {
         let mut reader = MemReader::new(vec!(10, 11, 12, 13));
         let bytes = reader.read_exact(4).unwrap();
-        assert!(bytes == vec!(10, 11, 12, 13));
+        assert_eq!(bytes, [10, 11, 12, 13]);
     }
 
     #[test]
@@ -337,7 +337,7 @@ fn read_bytes_partial() {
             count: 0,
         };
         let bytes = reader.read_exact(4).unwrap();
-        assert!(bytes == vec!(10, 11, 12, 13));
+        assert_eq!(bytes, [10, 11, 12, 13]);
     }
 
     #[test]
@@ -351,7 +351,7 @@ fn push_at_least() {
         let mut reader = MemReader::new(vec![10, 11, 12, 13]);
         let mut buf = vec![8, 9];
         assert!(reader.push_at_least(4, 4, &mut buf).is_ok());
-        assert!(buf == vec![8, 9, 10, 11, 12, 13]);
+        assert_eq!(buf, [8, 9, 10, 11, 12, 13]);
     }
 
     #[test]
@@ -361,7 +361,7 @@ fn push_at_least_partial() {
         };
         let mut buf = vec![8, 9];
         assert!(reader.push_at_least(4, 4, &mut buf).is_ok());
-        assert!(buf == vec![8, 9, 10, 11, 12, 13]);
+        assert_eq!(buf, [8, 9, 10, 11, 12, 13]);
     }
 
     #[test]
@@ -369,7 +369,7 @@ fn push_at_least_eof() {
         let mut reader = MemReader::new(vec![10, 11]);
         let mut buf = vec![8, 9];
         assert!(reader.push_at_least(4, 4, &mut buf).is_err());
-        assert!(buf == vec![8, 9, 10, 11]);
+        assert_eq!(buf, [8, 9, 10, 11]);
     }
 
     #[test]
@@ -379,7 +379,7 @@ fn push_at_least_error() {
         };
         let mut buf = vec![8, 9];
         assert!(reader.push_at_least(4, 4, &mut buf).is_err());
-        assert!(buf == vec![8, 9, 10]);
+        assert_eq!(buf, [8, 9, 10]);
     }
 
     #[test]
@@ -388,7 +388,7 @@ fn read_to_end() {
             count: 0,
         };
         let buf = reader.read_to_end().unwrap();
-        assert!(buf == vec!(10, 11, 12, 13));
+        assert_eq!(buf, [10, 11, 12, 13]);
     }
 
     #[test]
@@ -398,7 +398,7 @@ fn read_to_end_error() {
             count: 0,
         };
         let buf = reader.read_to_end().unwrap();
-        assert!(buf == vec!(10, 11));
+        assert_eq!(buf, [10, 11]);
     }
 
     #[test]
index 1fd527014a3d62d4e6fcdac2a6df7b20c26c424d..e6a8b90ea333401388a98e3ae17bd5f890f5dc54 100644 (file)
@@ -60,7 +60,7 @@ fn write_all(&mut self, buf: &[u8]) -> IoResult<()> {
 /// let mut w = MemWriter::new();
 /// w.write(&[0, 1, 2]);
 ///
-/// assert_eq!(w.into_inner(), vec!(0, 1, 2));
+/// assert_eq!(w.into_inner(), [0, 1, 2]);
 /// ```
 #[unstable(feature = "io")]
 #[deprecated(since = "1.0.0",
@@ -102,6 +102,7 @@ pub fn into_inner(self) -> Vec<u8> { self.buf }
 
 impl Writer for MemWriter {
     #[inline]
+    #[allow(deprecated)]
     fn write_all(&mut self, buf: &[u8]) -> IoResult<()> {
         self.buf.push_all(buf);
         Ok(())
@@ -118,7 +119,7 @@ fn write_all(&mut self, buf: &[u8]) -> IoResult<()> {
 ///
 /// let mut r = MemReader::new(vec!(0, 1, 2));
 ///
-/// assert_eq!(r.read_to_end().unwrap(), vec!(0, 1, 2));
+/// assert_eq!(r.read_to_end().unwrap(), [0, 1, 2]);
 /// ```
 pub struct MemReader {
     buf: Vec<u8>,
@@ -321,7 +322,7 @@ fn seek(&mut self, pos: i64, style: SeekStyle) -> IoResult<()> {
 /// let buf = [0, 1, 2, 3];
 /// let mut r = BufReader::new(&buf);
 ///
-/// assert_eq!(r.read_to_end().unwrap(), vec![0, 1, 2, 3]);
+/// assert_eq!(r.read_to_end().unwrap(), [0, 1, 2, 3]);
 /// ```
 pub struct BufReader<'a> {
     buf: &'a [u8],
@@ -504,8 +505,8 @@ fn test_mem_reader() {
         assert_eq!(&buf[..3], b);
         assert!(reader.read(&mut buf).is_err());
         let mut reader = MemReader::new(vec!(0, 1, 2, 3, 4, 5, 6, 7));
-        assert_eq!(reader.read_until(3).unwrap(), vec!(0, 1, 2, 3));
-        assert_eq!(reader.read_until(3).unwrap(), vec!(4, 5, 6, 7));
+        assert_eq!(reader.read_until(3).unwrap(), [0, 1, 2, 3]);
+        assert_eq!(reader.read_until(3).unwrap(), [4, 5, 6, 7]);
         assert!(reader.read(&mut buf).is_err());
     }
 
@@ -530,8 +531,8 @@ fn test_slice_reader() {
         assert_eq!(&buf[..3], b);
         assert!(reader.read(&mut buf).is_err());
         let mut reader = &mut &*in_buf;
-        assert_eq!(reader.read_until(3).unwrap(), vec!(0, 1, 2, 3));
-        assert_eq!(reader.read_until(3).unwrap(), vec!(4, 5, 6, 7));
+        assert_eq!(reader.read_until(3).unwrap(), [0, 1, 2, 3]);
+        assert_eq!(reader.read_until(3).unwrap(), [4, 5, 6, 7]);
         assert!(reader.read(&mut buf).is_err());
     }
 
@@ -557,8 +558,8 @@ fn test_buf_reader() {
         assert_eq!(&buf[..3], b);
         assert!(reader.read(&mut buf).is_err());
         let mut reader = BufReader::new(&in_buf);
-        assert_eq!(reader.read_until(3).unwrap(), vec!(0, 1, 2, 3));
-        assert_eq!(reader.read_until(3).unwrap(), vec!(4, 5, 6, 7));
+        assert_eq!(reader.read_until(3).unwrap(), [0, 1, 2, 3]);
+        assert_eq!(reader.read_until(3).unwrap(), [4, 5, 6, 7]);
         assert!(reader.read(&mut buf).is_err());
     }
 
index f42cb6ce8c97bf4d9c9f93d1b5ef9a2b5273945a..cdf2bae1cbad3c260e28e36b682b1db6b1a4a201 100644 (file)
@@ -87,7 +87,7 @@ fn test_option_writer() {
         let mut writer: old_io::IoResult<Vec<u8>> = Ok(Vec::new());
         writer.write_all(&[0, 1, 2]).unwrap();
         writer.flush().unwrap();
-        assert_eq!(writer.unwrap(), vec!(0, 1, 2));
+        assert_eq!(writer.unwrap(), [0, 1, 2]);
     }
 
     #[test]
index 42317c7a2d4316be452817d5b0988bc00a667cad..76753dca52e1eec4dfdad70d862723c3b5e88427 100644 (file)
@@ -96,9 +96,10 @@ impl TempDir {
     /// deleted once the returned wrapper is destroyed.
     ///
     /// If no directory can be created, `Err` is returned.
+    #[allow(deprecated)]
     pub fn new_in(tmpdir: &Path, prefix: &str) -> IoResult<TempDir> {
         if !tmpdir.is_absolute() {
-            let cur_dir = try!(env::current_dir());
+            let cur_dir = try!(::os::getcwd());
             return TempDir::new_in(&cur_dir.join(tmpdir), prefix);
         }
 
@@ -132,8 +133,9 @@ pub fn new_in(tmpdir: &Path, prefix: &str) -> IoResult<TempDir> {
     /// deleted once the returned wrapper is destroyed.
     ///
     /// If no directory can be created, `Err` is returned.
+    #[allow(deprecated)]
     pub fn new(prefix: &str) -> IoResult<TempDir> {
-        TempDir::new_in(&env::temp_dir(), prefix)
+        TempDir::new_in(&::os::tmpdir(), prefix)
     }
 
     /// Unwrap the wrapped `std::path::Path` from the `TempDir` wrapper.
index ee72beccfa8488f61fa0f997809ea11b8bc8c3fa..43c0b9268a242d065cc90b9c53c0a71a3207cb9c 100644 (file)
@@ -38,10 +38,11 @@ fn next_test_unix_socket() -> String {
 
 /// Get a temporary path which could be the location of a unix socket
 #[cfg(not(target_os = "ios"))]
+#[allow(deprecated)]
 pub fn next_test_unix() -> Path {
     let string = next_test_unix_socket();
     if cfg!(unix) {
-        env::temp_dir().join(string)
+        ::os::tmpdir().join(string)
     } else {
         Path::new(format!("{}{}", r"\\.\pipe\", string))
     }
@@ -88,7 +89,7 @@ fn base_port() -> u16 {
 
     // FIXME (#9639): This needs to handle non-utf8 paths
     let path = env::current_dir().unwrap();
-    let path_s = path.as_str().unwrap();
+    let path_s = path.to_str().unwrap();
 
     let mut final_base = base;
 
index 5ae239014d188145e55a2014b36be610b3f03dba..8e49335ed5469e110114ab9823866d113903e071 100644 (file)
@@ -284,7 +284,7 @@ fn test_limit_reader_unlimited() {
         let mut r = MemReader::new(vec!(0, 1, 2));
         {
             let mut r = LimitReader::new(r.by_ref(), 4);
-            assert_eq!(vec!(0, 1, 2), r.read_to_end().unwrap());
+            assert_eq!([0, 1, 2], r.read_to_end().unwrap());
         }
     }
 
@@ -293,9 +293,9 @@ fn test_limit_reader_limited() {
         let mut r = MemReader::new(vec!(0, 1, 2));
         {
             let mut r = LimitReader::new(r.by_ref(), 2);
-            assert_eq!(vec!(0, 1), r.read_to_end().unwrap());
+            assert_eq!([0, 1], r.read_to_end().unwrap());
         }
-        assert_eq!(vec!(2), r.read_to_end().unwrap());
+        assert_eq!([2], r.read_to_end().unwrap());
     }
 
     #[test]
@@ -305,7 +305,7 @@ fn test_limit_reader_limit() {
         assert_eq!(3, r.limit());
         assert_eq!(0, r.read_byte().unwrap());
         assert_eq!(2, r.limit());
-        assert_eq!(vec!(1, 2), r.read_to_end().unwrap());
+        assert_eq!([1, 2], r.read_to_end().unwrap());
         assert_eq!(0, r.limit());
     }
 
@@ -314,7 +314,7 @@ fn test_limit_reader_overlong_consume() {
         let mut r = MemReader::new(vec![0, 1, 2, 3, 4, 5]);
         let mut r = LimitReader::new(r.by_ref(), 1);
         r.consume(2);
-        assert_eq!(vec![], r.read_to_end().unwrap());
+        assert_eq!([], r.read_to_end().unwrap());
     }
 
     #[test]
@@ -330,7 +330,7 @@ fn test_zero_reader() {
         let mut s = ZeroReader;
         let mut buf = vec![1, 2, 3];
         assert_eq!(s.read(&mut buf), Ok(3));
-        assert_eq!(vec![0, 0, 0], buf);
+        assert_eq!([0, 0, 0], buf);
     }
 
     #[test]
@@ -373,16 +373,16 @@ fn test_chained_reader() {
         let rs = vec!(MemReader::new(vec!(0, 1)), MemReader::new(vec!()),
                       MemReader::new(vec!(2, 3)));
         let mut r = ChainedReader::new(rs.into_iter());
-        assert_eq!(vec!(0, 1, 2, 3), r.read_to_end().unwrap());
+        assert_eq!([0, 1, 2, 3], r.read_to_end().unwrap());
     }
 
     #[test]
     fn test_tee_reader() {
         let mut r = TeeReader::new(MemReader::new(vec!(0, 1, 2)),
                                    Vec::new());
-        assert_eq!(vec!(0, 1, 2), r.read_to_end().unwrap());
+        assert_eq!([0, 1, 2], r.read_to_end().unwrap());
         let (_, w) = r.into_inner();
-        assert_eq!(vec!(0, 1, 2), w);
+        assert_eq!([0, 1, 2], w);
     }
 
     #[test]
@@ -390,7 +390,7 @@ fn test_copy() {
         let mut r = MemReader::new(vec!(0, 1, 2, 3, 4));
         let mut w = Vec::new();
         copy(&mut r, &mut w).unwrap();
-        assert_eq!(vec!(0, 1, 2, 3, 4), w);
+        assert_eq!([0, 1, 2, 3, 4], w);
     }
 
     #[test]
index 86f5c2c356e5e924643e91ab61c746ad7214d49f..9c42d1be77ee1c009ead6a37df39ebbaeda03878 100644 (file)
@@ -49,6 +49,7 @@
 use option::Option::{Some, None};
 use option::Option;
 use old_path::{Path, GenericPath, BytesContainer};
+use path::{self, PathBuf};
 use ptr::PtrExt;
 use ptr;
 use result::Result::{Err, Ok};
 #[cfg(unix)] pub use sys::ext as unix;
 #[cfg(windows)] pub use sys::ext as windows;
 
+fn err2old(new: ::io::Error) -> IoError {
+    IoError {
+        kind: ::old_io::OtherIoError,
+        desc: "os error",
+        detail: Some(new.to_string()),
+    }
+}
+
+#[cfg(windows)]
+fn path2new(path: &Path) -> PathBuf {
+    PathBuf::new(path.as_str().unwrap())
+}
+#[cfg(unix)]
+fn path2new(path: &Path) -> PathBuf {
+    use os::unix::prelude::*;
+    PathBuf::new(<OsStr as OsStrExt>::from_bytes(path.as_vec()))
+}
+
+#[cfg(unix)]
+fn path2old(path: &path::Path) -> Path {
+    use os::unix::prelude::*;
+    use ffi::AsOsStr;
+    Path::new(path.as_os_str().as_bytes())
+}
+#[cfg(windows)]
+fn path2old(path: &path::Path) -> Path {
+    Path::new(path.to_str().unwrap())
+}
+
 /// Get the number of cores available
 pub fn num_cpus() -> uint {
     unsafe {
@@ -100,10 +130,9 @@ pub fn num_cpus() -> uint {
 /// let current_working_directory = os::getcwd().unwrap();
 /// println!("The current directory is {:?}", current_working_directory.display());
 /// ```
-#[deprecated(since = "1.0.0", reason = "renamed to std::env::current_dir")]
 #[unstable(feature = "os")]
 pub fn getcwd() -> IoResult<Path> {
-    env::current_dir()
+    env::current_dir().map_err(err2old).map(|s| path2old(&s))
 }
 
 /// Returns a vector of (variable, value) pairs, for all the environment
@@ -245,12 +274,11 @@ pub fn unsetenv(n: &str) {
 ///     None => println!("{} is not defined in the environment.", key)
 /// }
 /// ```
-#[deprecated(since = "1.0.0", reason = "renamed to env::split_paths")]
 #[unstable(feature = "os")]
 pub fn split_paths<T: BytesContainer>(unparsed: T) -> Vec<Path> {
     let b = unparsed.container_as_bytes();
     let s = str::from_utf8(b).unwrap();
-    env::split_paths(s).collect()
+    env::split_paths(s).map(|s| path2old(&s)).collect()
 }
 
 /// Joins a collection of `Path`s appropriately for the `PATH`
@@ -274,7 +302,6 @@ pub fn split_paths<T: BytesContainer>(unparsed: T) -> Vec<Path> {
 /// paths.push(Path::new("/home/xyz/bin"));
 /// os::setenv(key, os::join_paths(paths.as_slice()).unwrap());
 /// ```
-#[deprecated(since = "1.0.0", reason = "renamed to env::join_paths")]
 #[unstable(feature = "os")]
 pub fn join_paths<T: BytesContainer>(paths: &[T]) -> Result<Vec<u8>, &'static str> {
     env::join_paths(paths.iter().map(|s| {
@@ -335,10 +362,9 @@ pub fn dll_filename(base: &str) -> String {
 ///     None => println!("Unable to get the path of this executable!")
 /// };
 /// ```
-#[deprecated(since = "1.0.0", reason = "renamed to env::current_exe")]
 #[unstable(feature = "os")]
 pub fn self_exe_name() -> Option<Path> {
-    env::current_exe().ok()
+    env::current_exe().ok().map(|p| path2old(&p))
 }
 
 /// Optionally returns the filesystem path to the current executable which is
@@ -356,10 +382,9 @@ pub fn self_exe_name() -> Option<Path> {
 ///     None => println!("Impossible to fetch the path of this executable.")
 /// };
 /// ```
-#[deprecated(since = "1.0.0", reason = "use env::current_exe + dir_path/pop")]
 #[unstable(feature = "os")]
 pub fn self_exe_path() -> Option<Path> {
-    env::current_exe().ok().map(|mut p| { p.pop(); p })
+    env::current_exe().ok().map(|p| { let mut p = path2old(&p); p.pop(); p })
 }
 
 /// Optionally returns the path to the current user's home directory if known.
@@ -386,9 +411,8 @@ pub fn self_exe_path() -> Option<Path> {
 ///     None => println!("Impossible to get your home dir!")
 /// }
 /// ```
-#[deprecated(since = "1.0.0", reason = "renamed to env::home_dir")]
-#[allow(deprecated)]
 #[unstable(feature = "os")]
+#[allow(deprecated)]
 pub fn homedir() -> Option<Path> {
     #[inline]
     #[cfg(unix)]
@@ -424,9 +448,8 @@ fn aux_homedir(home_name: &str) -> Option<Path> {
 /// On Windows, returns the value of, in order, the 'TMP', 'TEMP',
 /// 'USERPROFILE' environment variable  if any are set and not the empty
 /// string. Otherwise, tmpdir returns the path to the Windows directory.
-#[deprecated(since = "1.0.0", reason = "renamed to env::temp_dir")]
-#[allow(deprecated)]
 #[unstable(feature = "os")]
+#[allow(deprecated)]
 pub fn tmpdir() -> Path {
     return lookup();
 
@@ -488,7 +511,8 @@ pub fn make_absolute(p: &Path) -> IoResult<Path> {
     if p.is_absolute() {
         Ok(p.clone())
     } else {
-        env::current_dir().map(|mut cwd| {
+        env::current_dir().map_err(err2old).map(|cwd| {
+            let mut cwd = path2old(&cwd);
             cwd.push(p);
             cwd
         })
@@ -507,10 +531,9 @@ pub fn make_absolute(p: &Path) -> IoResult<Path> {
 /// assert!(os::change_dir(&root).is_ok());
 /// println!("Successfully changed working directory to {}!", root.display());
 /// ```
-#[deprecated(since = "1.0.0", reason = "renamed to env::set_current_dir")]
 #[unstable(feature = "os")]
 pub fn change_dir(p: &Path) -> IoResult<()> {
-    return sys::os::chdir(p);
+    sys::os::chdir(&path2new(p)).map_err(err2old)
 }
 
 /// Returns the platform-specific value of errno
index 88543ad85ed116e78326c1dbc83d392733637745..b85a0dcec81805cb0a844a926531e5b2501c15dd 100755 (executable)
 use core::prelude::*;
 
 use ascii::*;
-use borrow::{Borrow, ToOwned, Cow};
+use borrow::{Borrow, IntoCow, ToOwned, Cow};
 use cmp;
 use iter::{self, IntoIterator};
 use mem;
@@ -987,6 +987,18 @@ fn borrow(&self) -> &Path {
     }
 }
 
+impl IntoCow<'static, Path> for PathBuf {
+    fn into_cow(self) -> Cow<'static, Path> {
+        Cow::Owned(self)
+    }
+}
+
+impl<'a> IntoCow<'a, Path> for &'a Path {
+    fn into_cow(self) -> Cow<'a, Path> {
+        Cow::Borrowed(self)
+    }
+}
+
 impl ToOwned for Path {
     type Owned = PathBuf;
     fn to_owned(&self) -> PathBuf { self.to_path_buf() }
@@ -1411,6 +1423,26 @@ macro_rules! t(
         );
     );
 
+    #[test]
+    fn into_cow() {
+        use borrow::{Cow, IntoCow};
+
+        let static_path = Path::new("/home/foo");
+        let static_cow_path: Cow<'static, Path> = static_path.into_cow();
+        let pathbuf = PathBuf::new("/home/foo");
+
+        {
+            let path: &Path = &pathbuf;
+            let borrowed_cow_path: Cow<Path> = path.into_cow();
+
+            assert_eq!(static_cow_path, borrowed_cow_path);
+        }
+
+        let owned_cow_path: Cow<'static, Path> = pathbuf.into_cow();
+
+        assert_eq!(static_cow_path, owned_cow_path);
+    }
+
     #[test]
     #[cfg(unix)]
     pub fn test_decompositions_unix() {
index 86604f62171ef073369a56646de779961ba80c38..c24b08deec2dc482d8395a7038214f22fc7762c9 100644 (file)
@@ -355,11 +355,11 @@ impl Stdio {
     pub fn capture() -> Stdio { Stdio(StdioImp::Capture) }
 
     /// The child inherits from the corresponding parent descriptor.
-    pub fn inherit() -> Stdio { Stdio(StdioImp::Capture) }
+    pub fn inherit() -> Stdio { Stdio(StdioImp::Inherit) }
 
     /// This stream will be ignored. This is the equivalent of attaching the
     /// stream to `/dev/null`
-    pub fn null() -> Stdio { Stdio(StdioImp::Capture) }
+    pub fn null() -> Stdio { Stdio(StdioImp::Null) }
 }
 
 /// Describes the result of a process after it has terminated.
index 0e2766f3889441331b0ec73c3ecad0ddfb25c8ca..1a13405633d2ede6f2218e4caa596c67baf7d4e1 100644 (file)
@@ -188,7 +188,6 @@ mod imp {
     extern crate libc;
 
     use old_io::{IoResult};
-    use marker::Sync;
     use mem;
     use os;
     use rand::Rng;
@@ -214,10 +213,8 @@ pub struct OsRng {
     #[repr(C)]
     struct SecRandom;
 
-    unsafe impl Sync for *const SecRandom {}
-
     #[allow(non_upper_case_globals)]
-    static kSecRandomDefault: *const SecRandom = 0 as *const SecRandom;
+    const kSecRandomDefault: *const SecRandom = 0 as *const SecRandom;
 
     #[link(name = "Security", kind = "framework")]
     extern "C" {
index aa87abc6e9aacdecce704f680c08911e2888d780..e7ee9bd2066514f4e47a04b3bf2eb102de874fc6 100644 (file)
@@ -61,9 +61,6 @@
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct Condvar { inner: Box<StaticCondvar> }
 
-unsafe impl Send for Condvar {}
-unsafe impl Sync for Condvar {}
-
 /// Statically allocated condition variables.
 ///
 /// This structure is identical to `Condvar` except that it is suitable for use
@@ -83,9 +80,6 @@ pub struct StaticCondvar {
     mutex: AtomicUsize,
 }
 
-unsafe impl Send for StaticCondvar {}
-unsafe impl Sync for StaticCondvar {}
-
 /// Constant initializer for a statically allocated condition variable.
 #[unstable(feature = "std_misc",
            reason = "may be merged with Condvar in the future")]
index f3b721438d807a2872f2fa706e441ebc2df3a3f2..68137601c405c84876ee746a0b8d302300cd2b03 100644 (file)
@@ -31,6 +31,7 @@
 pub use self::poison::{PoisonError, TryLockError, TryLockResult, LockResult};
 
 pub use self::future::Future;
+#[allow(deprecated)]
 pub use self::task_pool::TaskPool;
 
 pub mod mpsc;
index 7bd1f3542eb13828ca4a2806e53a623bc8c68e45..1310d476f8ee20f15540b6bc75f7df4a64eb7acc 100644 (file)
@@ -384,7 +384,7 @@ impl<T> !Sync for SyncSender<T> {}
 /// contains the data being sent as a payload so it can be recovered.
 #[stable(feature = "rust1", since = "1.0.0")]
 #[derive(PartialEq, Eq, Clone, Copy)]
-pub struct SendError<T>(pub T);
+pub struct SendError<T>(#[stable(feature = "rust1", since = "1.0.0")] pub T);
 
 /// An error returned from the `recv` function on a `Receiver`.
 ///
index 02b2db572ec4fe49be4efa50643560b4638c759d..4c3b5d98a3cb172e13673201c2296d49b27f1c54 100644 (file)
@@ -15,6 +15,7 @@
 use ops::{Deref, DerefMut};
 use sync::poison::{self, TryLockError, TryLockResult, LockResult};
 use sys_common::mutex as sys;
+use fmt;
 
 /// A mutual exclusion primitive useful for protecting shared data
 ///
@@ -152,8 +153,6 @@ pub struct StaticMutex {
     poison: poison::Flag,
 }
 
-unsafe impl Sync for StaticMutex {}
-
 /// An RAII implementation of a "scoped lock" of a mutex. When this structure is
 /// dropped (falls out of scope), the lock will be unlocked.
 ///
@@ -252,6 +251,19 @@ fn drop(&mut self) {
     }
 }
 
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<T: fmt::Debug + Send + 'static> fmt::Debug for Mutex<T> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        match self.try_lock() {
+            Ok(guard) => write!(f, "Mutex {{ data: {:?} }}", *guard),
+            Err(TryLockError::Poisoned(err)) => {
+                write!(f, "Mutex {{ data: Poisoned({:?}) }}", **err.get_ref())
+            },
+            Err(TryLockError::WouldBlock) => write!(f, "Mutex {{ <locked> }}")
+        }
+    }
+}
+
 struct Dummy(UnsafeCell<()>);
 unsafe impl Sync for Dummy {}
 static DUMMY: Dummy = Dummy(UnsafeCell { value: () });
index 97f985e21e8aba0bbc5068d55db1e2e6432695ea..d2054a1e819ab377d5204799f8e33e77e7bad937 100644 (file)
 //! This primitive is meant to be used to run one-time initialization. An
 //! example use case would be for initializing an FFI library.
 
+use prelude::v1::*;
+
 use isize;
-use marker::Sync;
-use mem::drop;
-use ops::FnOnce;
 use sync::atomic::{AtomicIsize, Ordering, ATOMIC_ISIZE_INIT};
 use sync::{StaticMutex, MUTEX_INIT};
 
@@ -43,8 +42,6 @@ pub struct Once {
     lock_cnt: AtomicIsize,
 }
 
-unsafe impl Sync for Once {}
-
 /// Initialization value for static `Once` values.
 #[stable(feature = "rust1", since = "1.0.0")]
 pub const ONCE_INIT: Once = Once {
index 32c8150ba4070172473cfe7d7602dca56a8c09de..2587ff5238ea7b86eb29d107856be5ed31629198 100644 (file)
 use thread;
 
 pub struct Flag { failed: UnsafeCell<bool> }
+
+// This flag is only ever accessed with a lock previously held. Note that this
+// a totally private structure.
+unsafe impl Send for Flag {}
+unsafe impl Sync for Flag {}
+
 pub const FLAG_INIT: Flag = Flag { failed: UnsafeCell { value: false } };
 
 impl Flag {
index 6fd2a6ed77d264c754e19e5ae46873ce274cb117..454c5b4f0cf7b20eb6bca82ca9cc7d9d3a73a89f 100644 (file)
@@ -15,6 +15,7 @@
 use ops::{Deref, DerefMut};
 use sync::poison::{self, LockResult, TryLockError, TryLockResult};
 use sys_common::rwlock as sys;
+use fmt;
 
 /// A reader-writer lock
 ///
@@ -97,9 +98,6 @@ pub struct StaticRwLock {
     poison: poison::Flag,
 }
 
-unsafe impl Send for StaticRwLock {}
-unsafe impl Sync for StaticRwLock {}
-
 /// Constant initialization for a statically-initialized rwlock.
 #[unstable(feature = "std_misc",
            reason = "may be merged with RwLock in the future")]
@@ -258,6 +256,19 @@ fn drop(&mut self) {
     }
 }
 
+#[stable(feature = "rust1", since = "1.0.0")]
+impl<T: fmt::Debug + Send + Sync> fmt::Debug for RwLock<T> {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        match self.try_read() {
+            Ok(guard) => write!(f, "RwLock {{ data: {:?} }}", *guard),
+            Err(TryLockError::Poisoned(err)) => {
+                write!(f, "RwLock {{ data: Poisoned({:?}) }}", **err.get_ref())
+            },
+            Err(TryLockError::WouldBlock) => write!(f, "RwLock {{ <locked> }}")
+        }
+    }
+}
+
 struct Dummy(UnsafeCell<()>);
 unsafe impl Sync for Dummy {}
 static DUMMY: Dummy = Dummy(UnsafeCell { value: () });
index 31f3dfd877cfb682f6e2208d30dc6f48f27ec0ad..efb6689e7855a40da3f9d374ead25439b9bee138 100644 (file)
 
 //! Abstraction of a thread pool for basic parallelism.
 
-#![unstable(feature = "std_misc",
-            reason = "the semantics of a failing task and whether a thread is \
-                      re-attached to a thread pool are somewhat unclear, and the \
-                      utility of this type in `std::sync` is questionable with \
-                      respect to the jobs of other primitives")]
+#![deprecated(since = "1.0.0",
+              reason = "This kind of API needs some time to bake in \
+                        crates.io. This functionality is available through \
+                        https://crates.io/crates/threadpool")]
+#![unstable(feature = "std_misc")]
+
+#![allow(deprecated)]
 
 use core::prelude::*;
 
index b5cd42219e128f4f5c182079baf8a21dd67e414a..228362e3d62ae2450ed349fae0b518f02db651b6 100644 (file)
@@ -503,7 +503,7 @@ pub fn connect_timeout(fd: sock_t,
     #[cfg(windows)] use libc::WSAEWOULDBLOCK as WOULDBLOCK;
 
     // Make sure the call to connect() doesn't block
-    try!(set_nonblocking(fd, true));
+    set_nonblocking(fd, true);
 
     let ret = match unsafe { libc::connect(fd, addrp, len) } {
         // If the connection is in progress, then we need to wait for it to
@@ -533,7 +533,7 @@ pub fn connect_timeout(fd: sock_t,
     };
 
     // be sure to turn blocking I/O back on
-    try!(set_nonblocking(fd, false));
+    set_nonblocking(fd, false);
     return ret;
 
     #[cfg(unix)]
@@ -626,7 +626,7 @@ pub struct Guard<'a> {
 #[unsafe_destructor]
 impl<'a> Drop for Guard<'a> {
     fn drop(&mut self) {
-        assert!(set_nonblocking(self.fd, false).is_ok());
+        set_nonblocking(self.fd, false);
     }
 }
 
@@ -723,7 +723,7 @@ fn lock_nonblocking<'a>(&'a self) -> Guard<'a> {
             fd: self.fd(),
             guard: self.inner.lock.lock().unwrap(),
         };
-        assert!(set_nonblocking(self.fd(), true).is_ok());
+        set_nonblocking(self.fd(), true);
         ret
     }
 
@@ -862,7 +862,7 @@ fn lock_nonblocking<'a>(&'a self) -> Guard<'a> {
             fd: self.fd(),
             guard: self.inner.lock.lock().unwrap(),
         };
-        assert!(set_nonblocking(self.fd(), true).is_ok());
+        set_nonblocking(self.fd(), true);
         ret
     }
 
@@ -887,9 +887,7 @@ pub fn recv_from(&mut self, buf: &mut [u8]) -> IoResult<(uint, SocketAddr)> {
                            storagep,
                            &mut addrlen) as libc::c_int
         }));
-        sockaddr_to_addr(&storage, addrlen as uint).and_then(|addr| {
-            Ok((n as uint, addr))
-        })
+        Ok((n as uint, sockaddr_to_addr(&storage, addrlen as uint).unwrap()))
     }
 
     pub fn send_to(&mut self, buf: &[u8], dst: SocketAddr) -> IoResult<()> {
@@ -910,11 +908,8 @@ pub fn send_to(&mut self, buf: &[u8], dst: SocketAddr) -> IoResult<()> {
         };
 
         let n = try!(write(fd, self.write_deadline, buf, false, dolock, dowrite));
-        if n != buf.len() {
-            Err(short_write(n, "couldn't send entire packet at once"))
-        } else {
-            Ok(())
-        }
+        assert!(n == buf.len(), "UDP packet not completely written.");
+        Ok(())
     }
 
     pub fn join_multicast(&mut self, multi: IpAddr) -> IoResult<()> {
index 9119a3c60d855a3d2b0e2b87b1ad9e006b698259..fb9d6fef1faa7e0071343937f6aad0eea519eba4 100644 (file)
@@ -1202,11 +1202,11 @@ fn cp(string: &Wtf8Buf) -> Vec<Option<char>> {
             string.code_points().map(|c| c.to_char()).collect::<Vec<_>>()
         }
         let mut string = Wtf8Buf::from_str("é ");
-        assert_eq!(cp(&string), vec![Some('é'), Some(' ')]);
+        assert_eq!(cp(&string), [Some('é'), Some(' ')]);
         string.push(c(0xD83D));
-        assert_eq!(cp(&string), vec![Some('é'), Some(' '), None]);
+        assert_eq!(cp(&string), [Some('é'), Some(' '), None]);
         string.push(c(0xDCA9));
-        assert_eq!(cp(&string), vec![Some('é'), Some(' '), Some('💩')]);
+        assert_eq!(cp(&string), [Some('é'), Some(' '), Some('💩')]);
     }
 
     #[test]
index 09630f8f584fe7c93c91bbae0fe267ae65faa7ae..3695b615f62b8fe17237684d631f6f9b733bf700 100644 (file)
@@ -84,8 +84,9 @@
 /// all unix platforms we support right now, so it at least gets the job done.
 
 use prelude::v1::*;
+use os::unix::prelude::*;
 
-use ffi::CStr;
+use ffi::{CStr, AsOsStr};
 use old_io::IoResult;
 use libc;
 use mem;
@@ -370,7 +371,7 @@ unsafe fn init_state() -> *mut backtrace_state {
         };
         let filename = match selfname {
             Some(path) => {
-                let bytes = path.as_vec();
+                let bytes = path.as_os_str().as_bytes();
                 if bytes.len() < LAST_FILENAME.len() {
                     let i = bytes.iter();
                     for (slot, val) in LAST_FILENAME.iter_mut().zip(i) {
index 3bc414731526300d15d5fa0d0716b132c7d892f6..90dfebc4c454c7735808255c52a5994e08452f34 100644 (file)
@@ -8,10 +8,11 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use prelude::v1::*;
+
 use cell::UnsafeCell;
 use libc;
 use ptr;
-use std::option::Option::{Some, None};
 use sys::mutex::{self, Mutex};
 use sys::time;
 use sys::sync as ffi;
@@ -20,6 +21,9 @@
 
 pub struct Condvar { inner: UnsafeCell<ffi::pthread_cond_t> }
 
+unsafe impl Send for Condvar {}
+unsafe impl Sync for Condvar {}
+
 pub const CONDVAR_INIT: Condvar = Condvar {
     inner: UnsafeCell { value: ffi::PTHREAD_COND_INITIALIZER },
 };
index b8b9dcfb3c68920b2602ed2e1e22072ac5d106be..3f9da6e3c51bb004fb6b1cf40a917825237136b5 100644 (file)
@@ -173,10 +173,13 @@ fn to_cstring(&self) -> Result<CString, NulError> {
 
 // Unix-specific extensions to `Permissions`
 pub trait PermissionsExt {
+    fn mode(&self) -> i32;
     fn set_mode(&mut self, mode: i32);
 }
 
 impl PermissionsExt for Permissions {
+    fn mode(&self) -> i32 { self.as_inner().mode() }
+
     fn set_mode(&mut self, mode: i32) {
         *self = FromInner::from_inner(FromInner::from_inner(mode));
     }
index 1c28d629d40f07f0c89f17290b72aae66a3c1bc6..71b6214460f4b9550926f95e1488fe2dd73519a1 100644 (file)
@@ -291,29 +291,14 @@ fn mkstat(stat: &libc::stat) -> FileStat {
     // FileStat times are in milliseconds
     fn mktime(secs: u64, nsecs: u64) -> u64 { secs * 1000 + nsecs / 1000000 }
 
-    #[cfg(target_os = "bitrig")]
-    fn ctime(stat: &libc::stat) -> u64 {
-      mktime(stat.st_ctim.tv_sec as u64, stat.st_ctim.tv_nsec as u64)
-    }
-    #[cfg(not(target_os = "bitrig"))]
     fn ctime(stat: &libc::stat) -> u64 {
       mktime(stat.st_ctime as u64, stat.st_ctime_nsec as u64)
     }
 
-    #[cfg(target_os = "bitrig")]
-    fn atime(stat: &libc::stat) -> u64 {
-      mktime(stat.st_atim.tv_sec as u64, stat.st_atim.tv_nsec as u64)
-    }
-    #[cfg(not(target_os = "bitrig"))]
     fn atime(stat: &libc::stat) -> u64 {
       mktime(stat.st_atime as u64, stat.st_atime_nsec as u64)
     }
 
-    #[cfg(target_os = "bitrig")]
-    fn mtime(stat: &libc::stat) -> u64 {
-      mktime(stat.st_mtim.tv_sec as u64, stat.st_mtim.tv_nsec as u64)
-    }
-    #[cfg(not(target_os = "bitrig"))]
     fn mtime(stat: &libc::stat) -> u64 {
       mktime(stat.st_mtime as u64, stat.st_mtime_nsec as u64)
     }
index c6b9c2cba5227f34190513944b590aaf5b2169dc..72e0b8dd36c66151eab686d374a2f44f928c42d3 100644 (file)
@@ -90,6 +90,7 @@ pub fn set_readonly(&mut self, readonly: bool) {
             self.mode |= 0o222;
         }
     }
+    pub fn mode(&self) -> i32 { self.mode as i32 }
 }
 
 impl FromInner<i32> for FilePermissions {
index b79ad7031fa48dc31dcc208036ae5f5bf353eaf1..632270bc5ccbf250286bc176d1f7c08ce9ea4935 100644 (file)
@@ -214,9 +214,9 @@ pub fn wouldblock() -> bool {
     err == libc::EWOULDBLOCK as i32 || err == libc::EAGAIN as i32
 }
 
-pub fn set_nonblocking(fd: sock_t, nb: bool) -> IoResult<()> {
+pub fn set_nonblocking(fd: sock_t, nb: bool) {
     let set = nb as libc::c_int;
-    mkerr_libc(retry(|| unsafe { c::ioctl(fd, c::FIONBIO, &set) }))
+    mkerr_libc(retry(|| unsafe { c::ioctl(fd, c::FIONBIO, &set) })).unwrap();
 }
 
 // nothing needed on unix platforms
index 9e1527aef201abdfb0215143a18bdb46ef0bc4cd..f87c0339533dfb672273d881cbf9b7623e9b16c2 100644 (file)
@@ -8,8 +8,9 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use prelude::v1::*;
+
 use cell::UnsafeCell;
-use marker::Sync;
 use sys::sync as ffi;
 use sys_common::mutex;
 
@@ -24,6 +25,7 @@ pub unsafe fn raw(m: &Mutex) -> *mut ffi::pthread_mutex_t {
     inner: UnsafeCell { value: ffi::PTHREAD_MUTEX_INITIALIZER },
 };
 
+unsafe impl Send for Mutex {}
 unsafe impl Sync for Mutex {}
 
 impl Mutex {
index d51f907307e46f12dff05a9306888e54b7dbb13e..a38c7a30b757840983f0e523db3aae11f827af0a 100644 (file)
 use error::Error as StdError;
 use ffi::{CString, CStr, OsString, OsStr, AsOsStr};
 use fmt;
+use io;
 use iter;
 use libc::{self, c_int, c_char, c_void};
 use mem;
-use io;
-use old_io::{IoResult, IoError, fs};
+use old_io::{IoError, IoResult};
 use ptr;
+use path::{self, PathBuf};
 use slice;
 use str;
 use sys::c;
 const BUF_BYTES: usize = 2048;
 const TMPBUF_SZ: usize = 128;
 
+fn bytes2path(b: &[u8]) -> PathBuf {
+    PathBuf::new(<OsStr as OsStrExt>::from_bytes(b))
+}
+
+fn os2path(os: OsString) -> PathBuf {
+    bytes2path(os.as_bytes())
+}
+
 /// Returns the platform-specific value of errno
 pub fn errno() -> i32 {
     #[cfg(any(target_os = "macos",
@@ -102,30 +111,30 @@ fn strerror_r(errnum: c_int, buf: *mut c_char,
     }
 }
 
-pub fn getcwd() -> IoResult<Path> {
+pub fn getcwd() -> io::Result<PathBuf> {
     let mut buf = [0 as c_char; BUF_BYTES];
     unsafe {
         if libc::getcwd(buf.as_mut_ptr(), buf.len() as libc::size_t).is_null() {
-            Err(IoError::last_error())
+            Err(io::Error::last_os_error())
         } else {
-            Ok(Path::new(CStr::from_ptr(buf.as_ptr()).to_bytes()))
+            Ok(bytes2path(CStr::from_ptr(buf.as_ptr()).to_bytes()))
         }
     }
 }
 
-pub fn chdir(p: &Path) -> IoResult<()> {
-    let p = CString::new(p.as_vec()).unwrap();
+pub fn chdir(p: &path::Path) -> io::Result<()> {
+    let p = try!(CString::new(p.as_os_str().as_bytes()));
     unsafe {
         match libc::chdir(p.as_ptr()) == (0 as c_int) {
             true => Ok(()),
-            false => Err(IoError::last_error()),
+            false => Err(io::Error::last_os_error()),
         }
     }
 }
 
 pub struct SplitPaths<'a> {
     iter: iter::Map<slice::Split<'a, u8, fn(&u8) -> bool>,
-                    fn(&'a [u8]) -> Path>,
+                    fn(&'a [u8]) -> PathBuf>,
 }
 
 pub fn split_paths<'a>(unparsed: &'a OsStr) -> SplitPaths<'a> {
@@ -133,13 +142,13 @@ fn is_colon(b: &u8) -> bool { *b == b':' }
     let unparsed = unparsed.as_bytes();
     SplitPaths {
         iter: unparsed.split(is_colon as fn(&u8) -> bool)
-                      .map(Path::new as fn(&'a [u8]) ->  Path)
+                      .map(bytes2path as fn(&'a [u8]) -> PathBuf)
     }
 }
 
 impl<'a> Iterator for SplitPaths<'a> {
-    type Item = Path;
-    fn next(&mut self) -> Option<Path> { self.iter.next() }
+    type Item = PathBuf;
+    fn next(&mut self) -> Option<PathBuf> { self.iter.next() }
     fn size_hint(&self) -> (usize, Option<usize>) { self.iter.size_hint() }
 }
 
@@ -174,7 +183,7 @@ fn description(&self) -> &str { "failed to join paths" }
 }
 
 #[cfg(target_os = "freebsd")]
-pub fn current_exe() -> IoResult<Path> {
+pub fn current_exe() -> io::Result<PathBuf> {
     unsafe {
         use libc::funcs::bsd44::*;
         use libc::consts::os::extra::*;
@@ -186,26 +195,26 @@ pub fn current_exe() -> IoResult<Path> {
         let err = sysctl(mib.as_mut_ptr(), mib.len() as ::libc::c_uint,
                          ptr::null_mut(), &mut sz, ptr::null_mut(),
                          0 as libc::size_t);
-        if err != 0 { return Err(IoError::last_error()); }
-        if sz == 0 { return Err(IoError::last_error()); }
+        if err != 0 { return Err(io::Error::last_os_error()); }
+        if sz == 0 { return Err(io::Error::last_os_error()); }
         let mut v: Vec<u8> = Vec::with_capacity(sz as uint);
         let err = sysctl(mib.as_mut_ptr(), mib.len() as ::libc::c_uint,
                          v.as_mut_ptr() as *mut libc::c_void, &mut sz,
                          ptr::null_mut(), 0 as libc::size_t);
-        if err != 0 { return Err(IoError::last_error()); }
-        if sz == 0 { return Err(IoError::last_error()); }
+        if err != 0 { return Err(io::Error::last_os_error()); }
+        if sz == 0 { return Err(io::Error::last_os_error()); }
         v.set_len(sz as uint - 1); // chop off trailing NUL
-        Ok(Path::new(v))
+        Ok(PathBuf::new::<OsString>(&OsStringExt::from_vec(v)))
     }
 }
 
 #[cfg(target_os = "dragonfly")]
-pub fn current_exe() -> IoResult<Path> {
-    fs::readlink(&Path::new("/proc/curproc/file"))
+pub fn current_exe() -> io::Result<PathBuf> {
+    ::fs::read_link("/proc/curproc/file")
 }
 
 #[cfg(any(target_os = "bitrig", target_os = "openbsd"))]
-pub fn current_exe() -> IoResult<Path> {
+pub fn current_exe() -> io::Result<PathBuf> {
     use sync::{StaticMutex, MUTEX_INIT};
     static LOCK: StaticMutex = MUTEX_INIT;
 
@@ -218,30 +227,31 @@ pub fn current_exe() -> IoResult<Path> {
     unsafe {
         let v = rust_current_exe();
         if v.is_null() {
-            Err(IoError::last_error())
+            Err(io::Error::last_os_error())
         } else {
-            Ok(Path::new(CStr::from_ptr(v).to_bytes().to_vec()))
+            let vec = CStr::from_ptr(v).to_bytes().to_vec();
+            Ok(PathBuf::new::<OsString>(&OsStringExt::from_vec(vec)))
         }
     }
 }
 
 #[cfg(any(target_os = "linux", target_os = "android"))]
-pub fn current_exe() -> IoResult<Path> {
-    fs::readlink(&Path::new("/proc/self/exe"))
+pub fn current_exe() -> io::Result<PathBuf> {
+    ::fs::read_link("/proc/self/exe")
 }
 
 #[cfg(any(target_os = "macos", target_os = "ios"))]
-pub fn current_exe() -> IoResult<Path> {
+pub fn current_exe() -> io::Result<PathBuf> {
     unsafe {
         use libc::funcs::extra::_NSGetExecutablePath;
         let mut sz: u32 = 0;
         _NSGetExecutablePath(ptr::null_mut(), &mut sz);
-        if sz == 0 { return Err(IoError::last_error()); }
+        if sz == 0 { return Err(io::Error::last_os_error()); }
         let mut v: Vec<u8> = Vec::with_capacity(sz as uint);
         let err = _NSGetExecutablePath(v.as_mut_ptr() as *mut i8, &mut sz);
-        if err != 0 { return Err(IoError::last_error()); }
+        if err != 0 { return Err(io::Error::last_os_error()); }
         v.set_len(sz as uint - 1); // chop off trailing NUL
-        Ok(Path::new(v))
+        Ok(PathBuf::new::<OsString>(&OsStringExt::from_vec(v)))
     }
 }
 
@@ -451,22 +461,20 @@ pub fn page_size() -> usize {
     }
 }
 
-pub fn temp_dir() -> Path {
-    getenv("TMPDIR".as_os_str()).map(|p| Path::new(p.into_vec())).unwrap_or_else(|| {
+pub fn temp_dir() -> PathBuf {
+    getenv("TMPDIR".as_os_str()).map(os2path).unwrap_or_else(|| {
         if cfg!(target_os = "android") {
-            Path::new("/data/local/tmp")
+            PathBuf::new("/data/local/tmp")
         } else {
-            Path::new("/tmp")
+            PathBuf::new("/tmp")
         }
     })
 }
 
-pub fn home_dir() -> Option<Path> {
+pub fn home_dir() -> Option<PathBuf> {
     return getenv("HOME".as_os_str()).or_else(|| unsafe {
         fallback()
-    }).map(|os| {
-        Path::new(os.into_vec())
-    });
+    }).map(os2path);
 
     #[cfg(any(target_os = "android",
               target_os = "ios"))]
index 3c9cdc65975f6f9f5e1b7027774b2a7dd0fa564f..33863d31437f3f7f68d4a6e2aaf4d1907cbc3d75 100644 (file)
@@ -145,7 +145,7 @@ fn lock_nonblocking<'a>(&'a self) -> Guard<'a> {
             fd: self.fd(),
             guard: unsafe { self.inner.lock.lock().unwrap() },
         };
-        assert!(set_nonblocking(self.fd(), true).is_ok());
+        set_nonblocking(self.fd(), true);
         ret
     }
 
@@ -235,9 +235,9 @@ pub fn listen(self) -> IoResult<UnixAcceptor> {
 
             _ => {
                 let (reader, writer) = try!(unsafe { sys::os::pipe() });
-                try!(set_nonblocking(reader.fd(), true));
-                try!(set_nonblocking(writer.fd(), true));
-                try!(set_nonblocking(self.fd(), true));
+                set_nonblocking(reader.fd(), true);
+                set_nonblocking(writer.fd(), true);
+                set_nonblocking(self.fd(), true);
                 Ok(UnixAcceptor {
                     inner: Arc::new(AcceptorInner {
                         listener: self,
index 2be841989e6b355b02676f04cd5a04112c9f2446..68c5c65e7cdb11cfac9bf64ff25732d8efbba32b 100644 (file)
@@ -69,7 +69,6 @@ pub fn spawn<K, V, C, P>(cfg: &C, in_fd: Option<P>,
               K: BytesContainer + Eq + Hash, V: BytesContainer
     {
         use libc::funcs::posix88::unistd::{fork, dup2, close, chdir, execvp};
-        use libc::funcs::bsd44::getdtablesize;
 
         mod rustrt {
             extern {
@@ -82,6 +81,15 @@ unsafe fn set_cloexec(fd: c_int) {
             assert_eq!(ret, 0);
         }
 
+        #[cfg(all(target_os = "android", target_arch = "aarch64"))]
+        unsafe fn getdtablesize() -> c_int {
+            libc::sysconf(libc::consts::os::sysconf::_SC_OPEN_MAX) as c_int
+        }
+        #[cfg(not(all(target_os = "android", target_arch = "aarch64")))]
+        unsafe fn getdtablesize() -> c_int {
+            libc::funcs::bsd44::getdtablesize()
+        }
+
         let dirp = cfg.cwd().map(|c| c.as_ptr()).unwrap_or(ptr::null());
 
         // temporary until unboxed closures land
@@ -345,8 +353,8 @@ fn register_sigchld() -> (libc::c_int, c::sigaction) {
             unsafe {
                 let mut pipes = [0; 2];
                 assert_eq!(libc::pipe(pipes.as_mut_ptr()), 0);
-                set_nonblocking(pipes[0], true).ok().unwrap();
-                set_nonblocking(pipes[1], true).ok().unwrap();
+                set_nonblocking(pipes[0], true);
+                set_nonblocking(pipes[1], true);
                 WRITE_FD = pipes[1];
 
                 let mut old: c::sigaction = mem::zeroed();
@@ -362,7 +370,7 @@ fn register_sigchld() -> (libc::c_int, c::sigaction) {
         fn waitpid_helper(input: libc::c_int,
                           messages: Receiver<Req>,
                           (read_fd, old): (libc::c_int, c::sigaction)) {
-            set_nonblocking(input, true).ok().unwrap();
+            set_nonblocking(input, true);
             let mut set: c::fd_set = unsafe { mem::zeroed() };
             let mut tv: libc::timeval;
             let mut active = Vec::<(libc::pid_t, Sender<ProcessExit>, u64)>::new();
index 06fa5c4bba7253d66f4a3b45c00a6e3097168b8f..a7d0a864a08aa0a31e38e3f85601721d432e6e0b 100644 (file)
@@ -141,7 +141,6 @@ pub fn spawn(cfg: &Command,
                  -> io::Result<Process>
     {
         use libc::funcs::posix88::unistd::{fork, dup2, close, chdir, execvp};
-        use libc::funcs::bsd44::getdtablesize;
 
         mod rustrt {
             extern {
@@ -154,6 +153,16 @@ unsafe fn set_cloexec(fd: c_int) {
             assert_eq!(ret, 0);
         }
 
+        #[cfg(all(target_os = "android", target_arch = "aarch64"))]
+        unsafe fn getdtablesize() -> c_int {
+            libc::sysconf(libc::consts::os::sysconf::_SC_OPEN_MAX) as c_int
+        }
+
+        #[cfg(not(all(target_os = "android", target_arch = "aarch64")))]
+        unsafe fn getdtablesize() -> c_int {
+            libc::funcs::bsd44::getdtablesize()
+        }
+
         let dirp = cfg.cwd.as_ref().map(|c| c.as_ptr()).unwrap_or(ptr::null());
 
         with_envp(cfg.env.as_ref(), |envp: *const c_void| {
@@ -430,6 +439,7 @@ pub fn WTERMSIG(status: i32) -> i32 { status & 0x7f }
               target_os = "ios",
               target_os = "freebsd",
               target_os = "dragonfly",
+              target_os = "bitrig",
               target_os = "openbsd"))]
     mod imp {
         pub fn WIFEXITED(status: i32) -> bool { (status & 0x7f) == 0 }
index 54523e0076dc3c47ce41897cb416b4b2f795b385..b857f4ab75fed31160e45e63acdf887f545acdca 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use prelude::v1::*;
+
 use cell::UnsafeCell;
 use sys::sync as ffi;
 
@@ -17,6 +19,9 @@ pub struct RWLock { inner: UnsafeCell<ffi::pthread_rwlock_t> }
     inner: UnsafeCell { value: ffi::PTHREAD_RWLOCK_INITIALIZER },
 };
 
+unsafe impl Send for RWLock {}
+unsafe impl Sync for RWLock {}
+
 impl RWLock {
     #[inline]
     pub unsafe fn new() -> RWLock {
index c8f9d318482b09c39a3a2a9f993c2f1d27e11e83..b08f6ef9b9032ebe19b9af176d086164f0de2d7a 100644 (file)
@@ -67,9 +67,9 @@ pub fn listen(self, backlog: int) -> IoResult<TcpAcceptor> {
             -1 => Err(last_net_error()),
             _ => {
                 let (reader, writer) = try!(unsafe { sys::os::pipe() });
-                try!(set_nonblocking(reader.fd(), true));
-                try!(set_nonblocking(writer.fd(), true));
-                try!(set_nonblocking(self.fd(), true));
+                set_nonblocking(reader.fd(), true);
+                set_nonblocking(writer.fd(), true);
+                set_nonblocking(self.fd(), true);
                 Ok(TcpAcceptor {
                     inner: Arc::new(AcceptorInner {
                         listener: self,
index db8038006fd6a81451a3783951609bddb7f8719f..071637e3a939f82eda497d497dabdbef9e72ea31 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use prelude::v1::*;
+
 use cell::UnsafeCell;
 use libc::{self, DWORD};
 use os;
@@ -17,6 +19,9 @@
 
 pub struct Condvar { inner: UnsafeCell<ffi::CONDITION_VARIABLE> }
 
+unsafe impl Send for Condvar {}
+unsafe impl Sync for Condvar {}
+
 pub const CONDVAR_INIT: Condvar = Condvar {
     inner: UnsafeCell { value: ffi::CONDITION_VARIABLE_INIT }
 };
index 304d7e015327960747c3fc6dbb0e413d4b5845fd..309d6c9dc48c26b48c27f4cae8af38e2a11a194c 100644 (file)
@@ -368,7 +368,9 @@ pub fn readlink(p: &Path) -> IoResult<Path> {
                                   buf as *const u16,
                                   sz - 1,
                                   libc::VOLUME_NAME_DOS)
-    }, super::os2path);
+    }, |data| {
+        Path::new(String::from_utf16(data).unwrap())
+    });
     assert!(unsafe { libc::CloseHandle(handle) } != 0);
     return ret;
 }
index a756fb29f81aeb5f32c4d446efb633cf6220b2b9..5bb2a134533ed0217b7dd9135b51e070e56fd346 100644 (file)
 
 use prelude::v1::*;
 
-use ffi::OsStr;
+use ffi::{OsStr, OsString};
 use io::{self, ErrorKind};
 use libc;
 use mem;
-use old_io::{self, IoResult, IoError};
 use num::Int;
-use os::windows::OsStrExt;
+use old_io::{self, IoResult, IoError};
+use os::windows::{OsStrExt, OsStringExt};
+use path::PathBuf;
 use sync::{Once, ONCE_INIT};
 
 macro_rules! helper_init { (static $name:ident: Helper<$m:ty>) => (
@@ -192,12 +193,12 @@ pub fn wouldblock() -> bool {
     err == libc::WSAEWOULDBLOCK as i32
 }
 
-pub fn set_nonblocking(fd: sock_t, nb: bool) -> IoResult<()> {
+pub fn set_nonblocking(fd: sock_t, nb: bool) {
     let mut set = nb as libc::c_ulong;
-    if unsafe { c::ioctlsocket(fd, c::FIONBIO, &mut set) != 0 } {
-        Err(last_error())
-    } else {
-        Ok(())
+    if unsafe { c::ioctlsocket(fd, c::FIONBIO, &mut set) } != 0 {
+        // The above function should not return an error unless we passed it
+        // invalid parameters. Panic on errors.
+        panic!("set_nonblocking called with invalid parameters: {}", last_error());
     }
 }
 
@@ -314,9 +315,10 @@ fn fill_utf16_buf_new<F1, F2, T>(f1: F1, f2: F2) -> io::Result<T>
     fill_utf16_buf_base(f1, f2).map_err(|()| io::Error::last_os_error())
 }
 
-fn os2path(s: &[u16]) -> Path {
-    // FIXME: this should not be a panicking conversion (aka path reform)
-    Path::new(String::from_utf16(s).unwrap())
+fn os2path(s: &[u16]) -> PathBuf {
+    let os = <OsString as OsStringExt>::from_wide(s);
+    // FIXME(#22751) should consume `os`
+    PathBuf::new(&os)
 }
 
 pub fn truncate_utf16_at_nul<'a>(v: &'a [u16]) -> &'a [u16] {
index 75495efc7cbb60f9d2a7f12ffa78980f2540ab39..0847f3b52bfabe171e370bed4e1b6a43cb75bfa5 100644 (file)
@@ -8,7 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use marker::Sync;
+use prelude::v1::*;
+
 use cell::UnsafeCell;
 use sys::sync as ffi;
 
@@ -18,6 +19,7 @@ pub struct Mutex { inner: UnsafeCell<ffi::SRWLOCK> }
     inner: UnsafeCell { value: ffi::SRWLOCK_INIT }
 };
 
+unsafe impl Send for Mutex {}
 unsafe impl Sync for Mutex {}
 
 #[inline]
@@ -27,14 +29,15 @@ pub unsafe fn raw(m: &Mutex) -> ffi::PSRWLOCK {
 
 // So you might be asking why we're using SRWLock instead of CriticalSection?
 //
-// 1. SRWLock is several times faster than CriticalSection according to benchmarks performed on both
-// Windows 8 and Windows 7.
+// 1. SRWLock is several times faster than CriticalSection according to
+//    benchmarks performed on both Windows 8 and Windows 7.
 //
-// 2. CriticalSection allows recursive locking while SRWLock deadlocks. The Unix implementation
-// deadlocks so consistency is preferred. See #19962 for more details.
+// 2. CriticalSection allows recursive locking while SRWLock deadlocks. The Unix
+//    implementation deadlocks so consistency is preferred. See #19962 for more
+//    details.
 //
-// 3. While CriticalSection is fair and SRWLock is not, the current Rust policy is there there are
-// no guarantees of fairness.
+// 3. While CriticalSection is fair and SRWLock is not, the current Rust policy
+//    is there there are no guarantees of fairness.
 
 impl Mutex {
     #[inline]
index 3451232f40ab89acb88de0fa53ce591dc2739cbd..6caa4df5dfe6269e58bd3fa903e4ee19d70dfe81 100644 (file)
@@ -25,6 +25,8 @@
 
 pub struct Socket(libc::SOCKET);
 
+/// Checks whether the Windows socket interface has been started already, and
+/// if not, starts it.
 pub fn init() {
     static START: Once = ONCE_INIT;
 
@@ -38,10 +40,16 @@ pub fn init() {
     });
 }
 
+/// Returns the last error from the Windows socket interface.
 fn last_error() -> io::Error {
     io::Error::from_os_error(unsafe { c::WSAGetLastError() })
 }
 
+/// Checks if the signed integer is the Windows constant `SOCKET_ERROR` (-1)
+/// and if so, returns the last error from the Windows socket interface. . This
+/// function must be called before another call to the socket API is made.
+///
+/// FIXME: generics needed?
 pub fn cvt<T: SignedInt>(t: T) -> io::Result<T> {
     let one: T = Int::one();
     if t == -one {
@@ -51,11 +59,14 @@ pub fn cvt<T: SignedInt>(t: T) -> io::Result<T> {
     }
 }
 
+/// Provides the functionality of `cvt` for the return values of `getaddrinfo`
+/// and similar, meaning that they return an error if the return value is 0.
 pub fn cvt_gai(err: c_int) -> io::Result<()> {
     if err == 0 { return Ok(()) }
     cvt(err).map(|_| ())
 }
 
+/// Provides the functionality of `cvt` for a closure.
 pub fn cvt_r<T: SignedInt, F>(mut f: F) -> io::Result<T> where F: FnMut() -> T {
     cvt(f())
 }
@@ -112,7 +123,7 @@ pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
 
 impl Drop for Socket {
     fn drop(&mut self) {
-        unsafe { let _ = libc::closesocket(self.0); }
+        unsafe { cvt(libc::closesocket(self.0)).unwrap(); }
     }
 }
 
index 6520d30487c76d978e6d5441370214c0332402c3..587ab7924fd1dc541fd7751cb82a61ff077f3362 100644 (file)
 use error::Error as StdError;
 use ffi::{OsString, OsStr, AsOsStr};
 use fmt;
-use ops::Range;
+use io;
 use libc::types::os::arch::extra::LPWCH;
 use libc::{self, c_int, c_void};
 use mem;
 use old_io::{IoError, IoResult};
+use ops::Range;
+use path::{self, PathBuf};
 use ptr;
 use slice;
 use sys::c;
@@ -151,8 +153,8 @@ pub fn split_paths(unparsed: &OsStr) -> SplitPaths {
 }
 
 impl<'a> Iterator for SplitPaths<'a> {
-    type Item = Path;
-    fn next(&mut self) -> Option<Path> {
+    type Item = PathBuf;
+    fn next(&mut self) -> Option<PathBuf> {
         // On Windows, the PATH environment variable is semicolon separated.
         // Double quotes are used as a way of introducing literal semicolons
         // (since c:\some;dir is a valid Windows path). Double quotes are not
@@ -186,7 +188,7 @@ fn next(&mut self) -> Option<Path> {
         if !must_yield && in_progress.is_empty() {
             None
         } else {
-            Some(super::os2path(&in_progress[..]))
+            Some(super::os2path(&in_progress))
         }
     }
 }
@@ -228,33 +230,33 @@ impl StdError for JoinPathsError {
     fn description(&self) -> &str { "failed to join paths" }
 }
 
-pub fn current_exe() -> IoResult<Path> {
-    super::fill_utf16_buf(|buf, sz| unsafe {
+pub fn current_exe() -> io::Result<PathBuf> {
+    super::fill_utf16_buf_new(|buf, sz| unsafe {
         libc::GetModuleFileNameW(ptr::null_mut(), buf, sz)
     }, super::os2path)
 }
 
-pub fn getcwd() -> IoResult<Path> {
-    super::fill_utf16_buf(|buf, sz| unsafe {
+pub fn getcwd() -> io::Result<PathBuf> {
+    super::fill_utf16_buf_new(|buf, sz| unsafe {
         libc::GetCurrentDirectoryW(sz, buf)
     }, super::os2path)
 }
 
-pub fn chdir(p: &Path) -> IoResult<()> {
+pub fn chdir(p: &path::Path) -> io::Result<()> {
     let mut p = p.as_os_str().encode_wide().collect::<Vec<_>>();
     p.push(0);
 
     unsafe {
         match libc::SetCurrentDirectoryW(p.as_ptr()) != (0 as libc::BOOL) {
             true => Ok(()),
-            false => Err(IoError::last_error()),
+            false => Err(io::Error::last_os_error()),
         }
     }
 }
 
 pub fn getenv(k: &OsStr) -> Option<OsString> {
     let k = super::to_utf16_os(k);
-    super::fill_utf16_buf(|buf, sz| unsafe {
+    super::fill_utf16_buf_new(|buf, sz| unsafe {
         libc::GetEnvironmentVariableW(k.as_ptr(), buf, sz)
     }, |buf| {
         OsStringExt::from_wide(buf)
@@ -349,18 +351,18 @@ pub unsafe fn pipe() -> IoResult<(FileDesc, FileDesc)> {
     }
 }
 
-pub fn temp_dir() -> Path {
-    super::fill_utf16_buf(|buf, sz| unsafe {
+pub fn temp_dir() -> PathBuf {
+    super::fill_utf16_buf_new(|buf, sz| unsafe {
         c::GetTempPathW(sz, buf)
     }, super::os2path).unwrap()
 }
 
-pub fn home_dir() -> Option<Path> {
+pub fn home_dir() -> Option<PathBuf> {
     getenv("HOME".as_os_str()).or_else(|| {
         getenv("USERPROFILE".as_os_str())
     }).map(|os| {
-        // FIXME: OsString => Path
-        Path::new(os.to_str().unwrap())
+        // FIXME(#22751) should consume `os`
+        PathBuf::new(&os)
     }).or_else(|| unsafe {
         let me = c::GetCurrentProcess();
         let mut token = ptr::null_mut();
@@ -368,7 +370,7 @@ pub fn home_dir() -> Option<Path> {
             return None
         }
         let _handle = RawHandle::new(token);
-        super::fill_utf16_buf(|buf, mut sz| {
+        super::fill_utf16_buf_new(|buf, mut sz| {
             match c::GetUserProfileDirectoryW(token, buf, &mut sz) {
                 0 if libc::GetLastError() != 0 => 0,
                 0 => sz,
index 19e38196d199fc360f20c199dd5047ed9cf5d939..d4c6e85489f5d25d87f82e01791834869ba96fea 100644 (file)
 use env;
 use ffi::{OsString, OsStr};
 use fmt;
+use fs;
 use io::{self, Error};
 use libc::{self, c_void};
-use old_io::fs;
-use old_path;
 use os::windows::OsStrExt;
 use ptr;
 use sync::{StaticMutex, MUTEX_INIT};
+use sys::handle::Handle;
 use sys::pipe2::AnonPipe;
 use sys::{self, cvt};
-use sys::handle::Handle;
 use sys_common::{AsInner, FromInner};
 
 ////////////////////////////////////////////////////////////////////////////////
@@ -142,9 +141,8 @@ pub fn spawn(cfg: &Command,
                 for path in split_paths(&v) {
                     let path = path.join(cfg.program.to_str().unwrap())
                                    .with_extension(env::consts::EXE_EXTENSION);
-                    // FIXME: update with new fs module once it lands
-                    if fs::stat(&old_path::Path::new(&path)).is_ok() {
-                        return Some(OsString::from_str(path.as_str().unwrap()))
+                    if fs::metadata(&path).is_ok() {
+                        return Some(path.into_os_string())
                     }
                 }
                 break
index 76fe352ed7717cf6ca623bb693a1fcf48663d5c1..009605535a0237026d18ec29e0d783feb626a362 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use prelude::v1::*;
+
 use cell::UnsafeCell;
 use sys::sync as ffi;
 
@@ -17,6 +19,9 @@ pub struct RWLock { inner: UnsafeCell<ffi::SRWLOCK> }
     inner: UnsafeCell { value: ffi::SRWLOCK_INIT }
 };
 
+unsafe impl Send for RWLock {}
+unsafe impl Sync for RWLock {}
+
 impl RWLock {
     #[inline]
     pub unsafe fn read(&self) {
index 4804ca510cb0ba0e9be1b8fffdbd75285e78a703..25b70918591d0fc54c6ad488f36f8e42643013ac 100644 (file)
@@ -192,7 +192,7 @@ pub fn accept(&mut self) -> IoResult<TcpStream> {
                         c::WSAEventSelect(socket, events[1], 0)
                     };
                     if ret != 0 { return Err(last_net_error()) }
-                    try!(set_nonblocking(socket, false));
+                    set_nonblocking(socket, false);
                     return Ok(stream)
                 }
             }
index 20ceff0aa6931c41105646a50b01c0fade32f4df..209460df10b7ceb118f53669dafc0257e2a6ae88 100644 (file)
@@ -12,6 +12,8 @@
 use time::Duration;
 use sync::{Once, ONCE_INIT};
 
+const NANOS_PER_SEC: i64 = 1_000_000_000;
+
 pub struct SteadyTime {
     t: libc::LARGE_INTEGER,
 }
@@ -24,7 +26,7 @@ pub fn now() -> SteadyTime {
     }
 
     pub fn ns(&self) -> u64 {
-        self.t as u64 * 1_000_000_000 / frequency() as u64
+        mul_div_i64(self.t as i64, NANOS_PER_SEC, frequency() as i64) as u64
     }
 }
 
@@ -45,6 +47,27 @@ impl<'a> Sub for &'a SteadyTime {
 
     fn sub(self, other: &SteadyTime) -> Duration {
         let diff = self.t as i64 - other.t as i64;
-        Duration::microseconds(diff * 1_000_000 / frequency() as i64)
+        Duration::nanoseconds(mul_div_i64(diff, NANOS_PER_SEC, frequency() as i64))
     }
 }
+
+// Computes (value*numer)/denom without overflow, as long as both
+// (numer*denom) and the overall result fit into i64 (which is the case
+// for our time conversions).
+fn mul_div_i64(value: i64, numer: i64, denom: i64) -> i64 {
+    let q = value / denom;
+    let r = value % denom;
+    // Decompose value as (value/denom*denom + value%denom),
+    // substitute into (value*numer)/denom and simplify.
+    // r < denom, so (denom*numer) is the upper bound of (r*numer)
+    q * numer + r * numer / denom
+}
+
+#[test]
+fn test_muldiv() {
+    assert_eq!(mul_div_i64( 1_000_000_000_001, 1_000_000_000, 1_000_000),  1_000_000_000_001_000);
+    assert_eq!(mul_div_i64(-1_000_000_000_001, 1_000_000_000, 1_000_000), -1_000_000_000_001_000);
+    assert_eq!(mul_div_i64(-1_000_000_000_001,-1_000_000_000, 1_000_000),  1_000_000_000_001_000);
+    assert_eq!(mul_div_i64( 1_000_000_000_001, 1_000_000_000,-1_000_000), -1_000_000_000_001_000);
+    assert_eq!(mul_div_i64( 1_000_000_000_001,-1_000_000_000,-1_000_000),  1_000_000_000_001_000);
+}
index 8a8b53090570cadcd188b6f840b41ffbe81771ed..c9bac69c434c32ff965213742d1c4d0c08346d51 100644 (file)
@@ -52,7 +52,7 @@ fn invalid_encoding() -> IoError {
 
 pub fn is_tty(fd: c_int) -> bool {
     let mut out: DWORD = 0;
-    // If this function doesn't panic then fd is a TTY
+    // If this function doesn't return an error, then fd is a TTY
     match unsafe { GetConsoleMode(get_osfhandle(fd) as HANDLE,
                                   &mut out as LPDWORD) } {
         0 => false,
index d65156dae9604835e9459e8874a1823a79d0d9de..764c7d730cb0e448d4c20c390c08769e3624fa49 100644 (file)
@@ -105,10 +105,12 @@ pub struct Key<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,
 }
 
index effaac52716340e2c0f77f4821b0de6d0f01a5e9..6d6fdffa95095b25c6fd6b5684df59d12d8ae611 100644 (file)
@@ -753,11 +753,10 @@ pub enum Expr_ {
     ExprIndex(P<Expr>, P<Expr>),
     ExprRange(Option<P<Expr>>, Option<P<Expr>>),
 
-    /// Variable reference, possibly containing `::` and/or
-    /// type parameters, e.g. foo::bar::<baz>
-    ExprPath(Path),
-    /// A "qualified path", e.g. `<Vec<T> as SomeTrait>::SomeType`
-    ExprQPath(P<QPath>),
+    /// Variable reference, possibly containing `::` and/or type
+    /// parameters, e.g. foo::bar::<baz>. Optionally "qualified",
+    /// e.g. `<Vec<T> as SomeTrait>::SomeType`.
+    ExprPath(Option<QSelf>, Path),
 
     ExprAddrOf(Mutability, P<Expr>),
     ExprBreak(Option<Ident>),
@@ -778,16 +777,22 @@ pub enum Expr_ {
     ExprParen(P<Expr>)
 }
 
-/// A "qualified path":
+/// The explicit Self type in a "qualified path". The actual
+/// path, including the trait and the associated item, is stored
+/// sepparately. `position` represents the index of the associated
+/// item qualified with this Self type.
 ///
-///     <Vec<T> as SomeTrait>::SomeAssociatedItem
-///      ^~~~~     ^~~~~~~~~   ^~~~~~~~~~~~~~~~~~
-///      self_type  trait_name  item_path
+///     <Vec<T> as a::b::Trait>::AssociatedItem
+///      ^~~~~     ~~~~~~~~~~~~~~^
+///      ty        position = 3
+///
+///     <Vec<T>>::AssociatedItem
+///      ^~~~~    ^
+///      ty       position = 0
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
-pub struct QPath {
-    pub self_type: P<Ty>,
-    pub trait_ref: P<TraitRef>,
-    pub item_path: PathSegment,
+pub struct QSelf {
+    pub ty: P<Ty>,
+    pub position: usize
 }
 
 #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)]
@@ -1254,16 +1259,15 @@ pub enum Ty_ {
     TyBareFn(P<BareFnTy>),
     /// A tuple (`(A, B, C, D,...)`)
     TyTup(Vec<P<Ty>> ),
-    /// A path (`module::module::...::Type`) or primitive
+    /// A path (`module::module::...::Type`), optionally
+    /// "qualified", e.g. `<Vec<T> as SomeTrait>::SomeType`.
     ///
     /// Type parameters are stored in the Path itself
-    TyPath(Path, NodeId),
+    TyPath(Option<QSelf>, Path),
     /// Something like `A+B`. Note that `B` must always be a path.
     TyObjectSum(P<Ty>, TyParamBounds),
     /// A type like `for<'a> Foo<&'a Bar>`
     TyPolyTraitRef(TyParamBounds),
-    /// A "qualified path", e.g. `<Vec<T> as SomeTrait>::SomeType`
-    TyQPath(P<QPath>),
     /// No-op; kept solely so that we can pretty-print faithfully
     TyParen(P<Ty>),
     /// Unused for now
index f1228c1d36308a365d968d36ed34660fdd5d18bb..264e05f5c8d31ec1229b01ff6f6c39c0316b97ab 100644 (file)
@@ -134,7 +134,7 @@ pub fn unop_to_string(op: UnOp) -> &'static str {
 }
 
 pub fn is_path(e: P<Expr>) -> bool {
-    return match e.node { ExprPath(_) => true, _ => false };
+    match e.node { ExprPath(..) => true, _ => false }
 }
 
 /// Get a string representation of a signed int type, with its value.
@@ -488,9 +488,6 @@ fn visit_expr(&mut self, expression: &Expr) {
 
     fn visit_ty(&mut self, typ: &Ty) {
         self.operation.visit_id(typ.id);
-        if let TyPath(_, id) = typ.node {
-            self.operation.visit_id(id);
-        }
         visit::walk_ty(self, typ)
     }
 
@@ -564,13 +561,18 @@ fn visit_trait_item(&mut self, tm: &ast::TraitItem) {
         visit::walk_trait_item(self, tm);
     }
 
-    fn visit_lifetime_ref(&mut self, lifetime: &'v Lifetime) {
+    fn visit_lifetime_ref(&mut self, lifetime: &Lifetime) {
         self.operation.visit_id(lifetime.id);
     }
 
-    fn visit_lifetime_def(&mut self, def: &'v LifetimeDef) {
+    fn visit_lifetime_def(&mut self, def: &LifetimeDef) {
         self.visit_lifetime_ref(&def.lifetime);
     }
+
+    fn visit_trait_ref(&mut self, trait_ref: &TraitRef) {
+        self.operation.visit_id(trait_ref.ref_id);
+        visit::walk_trait_ref(self, trait_ref);
+    }
 }
 
 pub fn visit_ids_for_inlined_item<O: IdVisitingOperation>(item: &InlinedItem,
@@ -758,13 +760,13 @@ fn ident_to_segment(id : &Ident) -> PathSegment {
     #[test] fn idents_name_eq_test() {
         assert!(segments_name_eq(
             &[Ident{name:Name(3),ctxt:4}, Ident{name:Name(78),ctxt:82}]
-                .iter().map(ident_to_segment).collect::<Vec<PathSegment>>()[],
+                .iter().map(ident_to_segment).collect::<Vec<PathSegment>>(),
             &[Ident{name:Name(3),ctxt:104}, Ident{name:Name(78),ctxt:182}]
-                .iter().map(ident_to_segment).collect::<Vec<PathSegment>>()[]));
+                .iter().map(ident_to_segment).collect::<Vec<PathSegment>>()));
         assert!(!segments_name_eq(
             &[Ident{name:Name(3),ctxt:4}, Ident{name:Name(78),ctxt:82}]
-                .iter().map(ident_to_segment).collect::<Vec<PathSegment>>()[],
+                .iter().map(ident_to_segment).collect::<Vec<PathSegment>>(),
             &[Ident{name:Name(3),ctxt:104}, Ident{name:Name(77),ctxt:182}]
-                .iter().map(ident_to_segment).collect::<Vec<PathSegment>>()[]));
+                .iter().map(ident_to_segment).collect::<Vec<PathSegment>>()));
     }
 }
index 656d507ed69b826952ecbe61bb354f1c72c69836..d916651b05617d25cedd8bd6f06867eba885f712 100644 (file)
@@ -41,16 +41,16 @@ fn path_all(&self, sp: Span,
         -> ast::Path;
 
     fn qpath(&self, self_type: P<ast::Ty>,
-             trait_ref: P<ast::TraitRef>,
-             ident: ast::Ident )
-        -> P<ast::QPath>;
+             trait_path: ast::Path,
+             ident: ast::Ident)
+             -> (ast::QSelf, ast::Path);
     fn qpath_all(&self, self_type: P<ast::Ty>,
-                trait_ref: P<ast::TraitRef>,
+                trait_path: ast::Path,
                 ident: ast::Ident,
                 lifetimes: Vec<ast::Lifetime>,
                 types: Vec<P<ast::Ty>>,
-                bindings: Vec<P<ast::TypeBinding>> )
-        -> P<ast::QPath>;
+                bindings: Vec<P<ast::TypeBinding>>)
+                -> (ast::QSelf, ast::Path);
 
     // types
     fn ty_mt(&self, ty: P<ast::Ty>, mutbl: ast::Mutability) -> ast::MutTy;
@@ -114,7 +114,7 @@ fn block_all(&self, span: Span,
     // expressions
     fn expr(&self, span: Span, node: ast::Expr_) -> P<ast::Expr>;
     fn expr_path(&self, path: ast::Path) -> P<ast::Expr>;
-    fn expr_qpath(&self, span: Span, qpath: P<ast::QPath>) -> P<ast::Expr>;
+    fn expr_qpath(&self, span: Span, qself: ast::QSelf, path: ast::Path) -> P<ast::Expr>;
     fn expr_ident(&self, span: Span, id: ast::Ident) -> P<ast::Expr>;
 
     fn expr_self(&self, span: Span) -> P<ast::Expr>;
@@ -346,40 +346,40 @@ fn path_all(&self,
 
     /// Constructs a qualified path.
     ///
-    /// Constructs a path like `<self_type as trait_ref>::ident`.
+    /// Constructs a path like `<self_type as trait_path>::ident`.
     fn qpath(&self,
              self_type: P<ast::Ty>,
-             trait_ref: P<ast::TraitRef>,
+             trait_path: ast::Path,
              ident: ast::Ident)
-             -> P<ast::QPath> {
-        self.qpath_all(self_type, trait_ref, ident, Vec::new(), Vec::new(), Vec::new())
+             -> (ast::QSelf, ast::Path) {
+        self.qpath_all(self_type, trait_path, ident, vec![], vec![], vec![])
     }
 
     /// Constructs a qualified path.
     ///
-    /// Constructs a path like `<self_type as trait_ref>::ident<a, T, A=Bar>`.
+    /// Constructs a path like `<self_type as trait_path>::ident<'a, T, A=Bar>`.
     fn qpath_all(&self,
                  self_type: P<ast::Ty>,
-                 trait_ref: P<ast::TraitRef>,
+                 trait_path: ast::Path,
                  ident: ast::Ident,
                  lifetimes: Vec<ast::Lifetime>,
                  types: Vec<P<ast::Ty>>,
-                 bindings: Vec<P<ast::TypeBinding>> )
-                 -> P<ast::QPath> {
-        let segment = ast::PathSegment {
+                 bindings: Vec<P<ast::TypeBinding>>)
+                 -> (ast::QSelf, ast::Path) {
+        let mut path = trait_path;
+        path.segments.push(ast::PathSegment {
             identifier: ident,
             parameters: ast::AngleBracketedParameters(ast::AngleBracketedParameterData {
                 lifetimes: lifetimes,
                 types: OwnedSlice::from_vec(types),
                 bindings: OwnedSlice::from_vec(bindings),
             })
-        };
+        });
 
-        P(ast::QPath {
-            self_type: self_type,
-            trait_ref: trait_ref,
-            item_path: segment,
-        })
+        (ast::QSelf {
+            ty: self_type,
+            position: path.segments.len() - 1
+        }, path)
     }
 
     fn ty_mt(&self, ty: P<ast::Ty>, mutbl: ast::Mutability) -> ast::MutTy {
@@ -398,7 +398,7 @@ fn ty(&self, span: Span, ty: ast::Ty_) -> P<ast::Ty> {
     }
 
     fn ty_path(&self, path: ast::Path) -> P<ast::Ty> {
-        self.ty(path.span, ast::TyPath(path, ast::DUMMY_NODE_ID))
+        self.ty(path.span, ast::TyPath(None, path))
     }
 
     fn ty_sum(&self, path: ast::Path, bounds: OwnedSlice<ast::TyParamBound>) -> P<ast::Ty> {
@@ -603,12 +603,12 @@ fn expr(&self, span: Span, node: ast::Expr_) -> P<ast::Expr> {
     }
 
     fn expr_path(&self, path: ast::Path) -> P<ast::Expr> {
-        self.expr(path.span, ast::ExprPath(path))
+        self.expr(path.span, ast::ExprPath(None, path))
     }
 
     /// Constructs a QPath expression.
-    fn expr_qpath(&self, span: Span, qpath: P<ast::QPath>) -> P<ast::Expr> {
-        self.expr(span, ast::ExprQPath(qpath))
+    fn expr_qpath(&self, span: Span, qself: ast::QSelf, path: ast::Path) -> P<ast::Expr> {
+        self.expr(span, ast::ExprPath(Some(qself), path))
     }
 
     fn expr_ident(&self, span: Span, id: ast::Ident) -> P<ast::Expr> {
index 9410a51e7a5f660a368534d275fa651d7d5e13e1..2303eb9645b640415c7c3a1f9eaac7aa1e25315e 100644 (file)
@@ -53,7 +53,7 @@ pub fn expand_syntax_ext<'cx>(cx: &mut ExtCtxt, sp: Span, tts: &[ast::TokenTree]
 
     let e = P(ast::Expr {
         id: ast::DUMMY_NODE_ID,
-        node: ast::ExprPath(
+        node: ast::ExprPath(None,
             ast::Path {
                  span: sp,
                  global: false,
index 91212a86958962d08c71761b30545ea7432e15f5..80ef882745f878e152f3d24b29276bf6624db513 100644 (file)
@@ -70,7 +70,7 @@ macro_rules! md {
                 generics: LifetimeBounds::empty(),
                 explicit_self: borrowed_explicit_self(),
                 args: vec!(borrowed_self()),
-                ret_ty: Literal(path!(bool)),
+                ret_ty: Literal(path_local!(bool)),
                 attributes: attrs,
                 combine_substructure: combine_substructure(box |a, b, c| {
                     $f(a, b, c)
index b109850a6bd23dac42f217f7e4b742bb527dcc7c..be4a33002aa1c69e87f2227fa0e6490e6571c120 100644 (file)
@@ -36,7 +36,7 @@ macro_rules! md {
                 generics: LifetimeBounds::empty(),
                 explicit_self: borrowed_explicit_self(),
                 args: vec!(borrowed_self()),
-                ret_ty: Literal(path!(bool)),
+                ret_ty: Literal(path_local!(bool)),
                 attributes: attrs,
                 combine_substructure: combine_substructure(box |cx, span, substr| {
                     cs_op($op, $equal, cx, span, substr)
index eee780f457c9f053049e67f174f093c9016b5477..973c8f5fa1e0b4b26a39defe621cbe74107aab0f 100644 (file)
@@ -30,6 +30,12 @@ macro_rules! path {
     )
 }
 
+macro_rules! path_local {
+    ($x:ident) => (
+        ::ext::deriving::generic::ty::Path::new_local(stringify!($x))
+    )
+}
+
 macro_rules! pathvec_std {
     ($cx:expr, $first:ident :: $($rest:ident)::+) => (
         if $cx.use_std {
index 22c87d978c9e5aa2771d3971e71b2c155693527a..3b96292323a95039ab6f17535c704ce75023138b 100644 (file)
@@ -38,7 +38,7 @@ pub fn expand_deriving_from_primitive<F>(cx: &mut ExtCtxt,
                 name: "from_i64",
                 generics: LifetimeBounds::empty(),
                 explicit_self: None,
-                args: vec!(Literal(path!(i64))),
+                args: vec!(Literal(path_local!(i64))),
                 ret_ty: Literal(Path::new_(pathvec_std!(cx, core::option::Option),
                                            None,
                                            vec!(box Self_),
@@ -53,7 +53,7 @@ pub fn expand_deriving_from_primitive<F>(cx: &mut ExtCtxt,
                 name: "from_u64",
                 generics: LifetimeBounds::empty(),
                 explicit_self: None,
-                args: vec!(Literal(path!(u64))),
+                args: vec!(Literal(path_local!(u64))),
                 ret_ty: Literal(Path::new_(pathvec_std!(cx, core::option::Option),
                                            None,
                                            vec!(box Self_),
index bc239d0c7c2698fb5d097579ff555f56202ff8ea..bea57ae14e4af27c91d8600e7016525bdda30456 100644 (file)
@@ -41,7 +41,7 @@ pub fn expand_type(t: P<ast::Ty>,
     debug!("expanding type {:?} with impl_ty {:?}", t, impl_ty);
     let t = match (t.node.clone(), impl_ty) {
         // Expand uses of `Self` in impls to the concrete type.
-        (ast::Ty_::TyPath(ref path, _), Some(ref impl_ty)) => {
+        (ast::Ty_::TyPath(None, ref path), Some(ref impl_ty)) => {
             let path_as_ident = path_to_ident(path);
             // Note unhygenic comparison here. I think this is correct, since
             // even though `Self` is almost just a type parameter, the treatment
@@ -1594,13 +1594,10 @@ struct PathExprFinderContext {
 
     impl<'v> Visitor<'v> for PathExprFinderContext {
         fn visit_expr(&mut self, expr: &ast::Expr) {
-            match expr.node {
-                ast::ExprPath(ref p) => {
-                    self.path_accumulator.push(p.clone());
-                    // not calling visit_path, but it should be fine.
-                }
-                _ => visit::walk_expr(self, expr)
+            if let ast::ExprPath(None, ref p) = expr.node {
+                self.path_accumulator.push(p.clone());
             }
+            visit::walk_expr(self, expr);
         }
     }
 
@@ -2028,7 +2025,7 @@ fn ident_renamer_test () {
         let renamed_crate = renamer.fold_crate(the_crate);
         let idents = crate_idents(&renamed_crate);
         let resolved : Vec<ast::Name> = idents.iter().map(|id| mtwt::resolve(*id)).collect();
-        assert_eq!(resolved,vec!(f_ident.name,Name(16),int_ident.name,Name(16),Name(16),Name(16)));
+        assert_eq!(resolved, [f_ident.name,Name(16),int_ident.name,Name(16),Name(16),Name(16)]);
     }
 
     // test the PatIdentRenamer; only PatIdents get renamed
@@ -2044,8 +2041,6 @@ fn pat_ident_renamer_test () {
         let idents = crate_idents(&renamed_crate);
         let resolved : Vec<ast::Name> = idents.iter().map(|id| mtwt::resolve(*id)).collect();
         let x_name = x_ident.name;
-        assert_eq!(resolved,vec!(f_ident.name,Name(16),int_ident.name,Name(16),x_name,x_name));
+        assert_eq!(resolved, [f_ident.name,Name(16),int_ident.name,Name(16),x_name,x_name]);
     }
-
-
 }
index b6563d77b8864e7df854dd6be4dbee1af75fecae..72431d8e6aa2c317ccd23aa9449193f01445c344 100644 (file)
@@ -288,19 +288,19 @@ mod tests {
     fn xorpush_test () {
         let mut s = Vec::new();
         xor_push(&mut s, 14);
-        assert_eq!(s.clone(), vec!(14));
+        assert_eq!(s.clone(), [14]);
         xor_push(&mut s, 14);
-        assert_eq!(s.clone(), Vec::new());
+        assert_eq!(s.clone(), []);
         xor_push(&mut s, 14);
-        assert_eq!(s.clone(), vec!(14));
+        assert_eq!(s.clone(), [14]);
         xor_push(&mut s, 15);
-        assert_eq!(s.clone(), vec!(14, 15));
+        assert_eq!(s.clone(), [14, 15]);
         xor_push(&mut s, 16);
-        assert_eq!(s.clone(), vec!(14, 15, 16));
+        assert_eq!(s.clone(), [14, 15, 16]);
         xor_push(&mut s, 16);
-        assert_eq!(s.clone(), vec!(14, 15));
+        assert_eq!(s.clone(), [14, 15]);
         xor_push(&mut s, 15);
-        assert_eq!(s.clone(), vec!(14));
+        assert_eq!(s.clone(), [14]);
     }
 
     fn id(n: u32, s: SyntaxContext) -> Ident {
@@ -389,13 +389,13 @@ fn test_marksof () {
         assert_eq!(marksof_internal (EMPTY_CTXT,stopname,&t),Vec::new());
         // FIXME #5074: ANF'd to dodge nested calls
         { let ans = unfold_marks(vec!(4,98),EMPTY_CTXT,&mut t);
-         assert_eq! (marksof_internal (ans,stopname,&t),vec!(4,98));}
+         assert_eq! (marksof_internal (ans,stopname,&t), [4, 98]);}
         // does xoring work?
         { let ans = unfold_marks(vec!(5,5,16),EMPTY_CTXT,&mut t);
-         assert_eq! (marksof_internal (ans,stopname,&t), vec!(16));}
+         assert_eq! (marksof_internal (ans,stopname,&t), [16]);}
         // does nested xoring work?
         { let ans = unfold_marks(vec!(5,10,10,5,16),EMPTY_CTXT,&mut t);
-         assert_eq! (marksof_internal (ans, stopname,&t), vec!(16));}
+         assert_eq! (marksof_internal (ans, stopname,&t), [16]);}
         // rename where stop doesn't match:
         { let chain = vec!(M(9),
                         R(id(name1.usize() as u32,
@@ -403,7 +403,7 @@ fn test_marksof () {
                           Name(100101102)),
                         M(14));
          let ans = unfold_test_sc(chain,EMPTY_CTXT,&mut t);
-         assert_eq! (marksof_internal (ans, stopname, &t), vec!(9,14));}
+         assert_eq! (marksof_internal (ans, stopname, &t), [9, 14]);}
         // rename where stop does match
         { let name1sc = apply_mark_internal(4, EMPTY_CTXT, &mut t);
          let chain = vec!(M(9),
@@ -411,7 +411,7 @@ fn test_marksof () {
                          stopname),
                        M(14));
          let ans = unfold_test_sc(chain,EMPTY_CTXT,&mut t);
-         assert_eq! (marksof_internal (ans, stopname, &t), vec!(9)); }
+         assert_eq! (marksof_internal (ans, stopname, &t), [9]); }
     }
 
 
index fa6d934a4575581561476a177af7bb8872cdf195..67011ad21a6dd8eec7111f7c07929e9664a0f7ce 100644 (file)
@@ -334,6 +334,10 @@ fn check_matcher<'a, I>(cx: &mut ExtCtxt, matcher: I, follow: &Token)
                 let tok = if let TtToken(_, ref tok) = *token { tok } else { unreachable!() };
                 // If T' is in the set FOLLOW(NT), continue. Else, reject.
                 match (&next_token, is_in_follow(cx, &next_token, frag_spec.as_str())) {
+                    (_, Err(msg)) => {
+                        cx.span_err(sp, &msg);
+                        continue
+                    }
                     (&Eof, _) => return Some((sp, tok.clone())),
                     (_, Ok(true)) => continue,
                     (next, Ok(false)) => {
@@ -343,10 +347,6 @@ fn check_matcher<'a, I>(cx: &mut ExtCtxt, matcher: I, follow: &Token)
                                                  token_to_string(next)));
                         continue
                     },
-                    (_, Err(msg)) => {
-                        cx.span_err(sp, &msg);
-                        continue
-                    }
                 }
             },
             TtSequence(sp, ref seq) => {
index 071158fcebb5cf32da776b2e98394450dbf47108..ffc136d5a1d1a19b41bab604f7774b2e8fabfb54 100644 (file)
@@ -187,6 +187,7 @@ enum Status {
     ("no_link", Normal),
     ("derive", Normal),
     ("should_fail", Normal),
+    ("should_panic", Normal),
     ("ignore", Normal),
     ("no_implicit_prelude", Normal),
     ("reexport_test_harness_main", Normal),
@@ -243,7 +244,9 @@ enum Status {
     ("static_assert", Whitelisted),
     ("no_debug", Whitelisted),
     ("omit_gdb_pretty_printer_section", Whitelisted),
-    ("unsafe_no_drop_flag", Whitelisted),
+    ("unsafe_no_drop_flag", Gated("unsafe_no_drop_flag",
+                                  "unsafe_no_drop_flag has unstable semantics \
+                                   and may be removed in the future")),
 
     // used in resolve
     ("prelude_import", Whitelisted),
@@ -549,7 +552,7 @@ fn visit_foreign_item(&mut self, i: &ast::ForeignItem) {
 
     fn visit_ty(&mut self, t: &ast::Ty) {
         match t.node {
-            ast::TyPath(ref p, _) => {
+            ast::TyPath(None, ref p) => {
                 match &*p.segments {
 
                     [ast::PathSegment { identifier, .. }] => {
index dae830583c44b43ce2c9e0b2e9832d95a1942bd9..a556b2dfd2a99a88104844817f329d13a9f6669e 100644 (file)
@@ -146,10 +146,6 @@ fn fold_ty(&mut self, t: P<Ty>) -> P<Ty> {
         noop_fold_ty(t, self)
     }
 
-    fn fold_qpath(&mut self, t: P<QPath>) -> P<QPath> {
-        noop_fold_qpath(t, self)
-    }
-
     fn fold_ty_binding(&mut self, t: P<TypeBinding>) -> P<TypeBinding> {
         noop_fold_ty_binding(t, self)
     }
@@ -428,17 +424,19 @@ pub fn noop_fold_ty<T: Folder>(t: P<Ty>, fld: &mut T) -> P<Ty> {
             }
             TyTup(tys) => TyTup(tys.move_map(|ty| fld.fold_ty(ty))),
             TyParen(ty) => TyParen(fld.fold_ty(ty)),
-            TyPath(path, id) => {
-                let id = fld.new_id(id);
-                TyPath(fld.fold_path(path), id)
+            TyPath(qself, path) => {
+                let qself = qself.map(|QSelf { ty, position }| {
+                    QSelf {
+                        ty: fld.fold_ty(ty),
+                        position: position
+                    }
+                });
+                TyPath(qself, fld.fold_path(path))
             }
             TyObjectSum(ty, bounds) => {
                 TyObjectSum(fld.fold_ty(ty),
                             fld.fold_bounds(bounds))
             }
-            TyQPath(qpath) => {
-                TyQPath(fld.fold_qpath(qpath))
-            }
             TyFixedLengthVec(ty, e) => {
                 TyFixedLengthVec(fld.fold_ty(ty), fld.fold_expr(e))
             }
@@ -453,19 +451,6 @@ pub fn noop_fold_ty<T: Folder>(t: P<Ty>, fld: &mut T) -> P<Ty> {
     })
 }
 
-pub fn noop_fold_qpath<T: Folder>(qpath: P<QPath>, fld: &mut T) -> P<QPath> {
-    qpath.map(|qpath| {
-        QPath {
-            self_type: fld.fold_ty(qpath.self_type),
-            trait_ref: qpath.trait_ref.map(|tr| fld.fold_trait_ref(tr)),
-            item_path: PathSegment {
-                identifier: fld.fold_ident(qpath.item_path.identifier),
-                parameters: fld.fold_path_parameters(qpath.item_path.parameters),
-            }
-        }
-    })
-}
-
 pub fn noop_fold_foreign_mod<T: Folder>(ForeignMod {abi, items}: ForeignMod,
                                         fld: &mut T) -> ForeignMod {
     ForeignMod {
@@ -1364,8 +1349,15 @@ pub fn noop_fold_expr<T: Folder>(Expr {id, node, span}: Expr, folder: &mut T) ->
                 ExprRange(e1.map(|x| folder.fold_expr(x)),
                           e2.map(|x| folder.fold_expr(x)))
             }
-            ExprPath(pth) => ExprPath(folder.fold_path(pth)),
-            ExprQPath(qpath) => ExprQPath(folder.fold_qpath(qpath)),
+            ExprPath(qself, path) => {
+                let qself = qself.map(|QSelf { ty, position }| {
+                    QSelf {
+                        ty: folder.fold_ty(ty),
+                        position: position
+                    }
+                });
+                ExprPath(qself, folder.fold_path(path))
+            }
             ExprBreak(opt_ident) => ExprBreak(opt_ident.map(|x| folder.fold_ident(x))),
             ExprAgain(opt_ident) => ExprAgain(opt_ident.map(|x| folder.fold_ident(x))),
             ExprRet(e) => ExprRet(e.map(|x| folder.fold_expr(x))),
index 43dfcbae57e497b0a82f493ff427bbaccfe75fe4..4d099529cb49ae50439b15fe1b3a03142d419af8 100644 (file)
@@ -774,7 +774,7 @@ fn sp(a: u32, b: u32) -> Span {
         assert!(string_to_expr("a".to_string()) ==
                    P(ast::Expr{
                     id: ast::DUMMY_NODE_ID,
-                    node: ast::ExprPath(ast::Path {
+                    node: ast::ExprPath(None, ast::Path {
                         span: sp(0, 1),
                         global: false,
                         segments: vec!(
@@ -792,7 +792,7 @@ fn sp(a: u32, b: u32) -> Span {
         assert!(string_to_expr("::a::b".to_string()) ==
                    P(ast::Expr {
                     id: ast::DUMMY_NODE_ID,
-                    node: ast::ExprPath(ast::Path {
+                    node: ast::ExprPath(None, ast::Path {
                             span: sp(0, 6),
                             global: true,
                             segments: vec!(
@@ -974,7 +974,7 @@ fn string_to_tts_1 () {
                     id: ast::DUMMY_NODE_ID,
                     node:ast::ExprRet(Some(P(ast::Expr{
                         id: ast::DUMMY_NODE_ID,
-                        node:ast::ExprPath(ast::Path{
+                        node:ast::ExprPath(None, ast::Path{
                             span: sp(7, 8),
                             global: false,
                             segments: vec!(
@@ -995,7 +995,7 @@ fn string_to_tts_1 () {
                    P(Spanned{
                        node: ast::StmtExpr(P(ast::Expr {
                            id: ast::DUMMY_NODE_ID,
-                           node: ast::ExprPath(ast::Path {
+                           node: ast::ExprPath(None, ast::Path {
                                span:sp(0,1),
                                global:false,
                                segments: vec!(
@@ -1041,7 +1041,7 @@ fn parser_done(p: Parser){
                             node: ast::ItemFn(P(ast::FnDecl {
                                 inputs: vec!(ast::Arg{
                                     ty: P(ast::Ty{id: ast::DUMMY_NODE_ID,
-                                                  node: ast::TyPath(ast::Path{
+                                                  node: ast::TyPath(None, ast::Path{
                                         span:sp(10,13),
                                         global:false,
                                         segments: vec!(
@@ -1051,7 +1051,7 @@ fn parser_done(p: Parser){
                                                 parameters: ast::PathParameters::none(),
                                             }
                                         ),
-                                        }, ast::DUMMY_NODE_ID),
+                                        }),
                                         span:sp(10,13)
                                     }),
                                     pat: P(ast::Pat {
@@ -1084,7 +1084,7 @@ fn parser_done(p: Parser){
                                         stmts: vec!(P(Spanned{
                                             node: ast::StmtSemi(P(ast::Expr{
                                                 id: ast::DUMMY_NODE_ID,
-                                                node: ast::ExprPath(
+                                                node: ast::ExprPath(None,
                                                       ast::Path{
                                                         span:sp(17,18),
                                                         global:false,
index fec33eddb91c18756a46170bff4f9c57081c5a3c..f171e8279f49c47440ce715dd1e616d469a614fb 100644 (file)
@@ -25,7 +25,7 @@
 use ast::{ExprBreak, ExprCall, ExprCast};
 use ast::{ExprField, ExprTupField, ExprClosure, ExprIf, ExprIfLet, ExprIndex};
 use ast::{ExprLit, ExprLoop, ExprMac, ExprRange};
-use ast::{ExprMethodCall, ExprParen, ExprPath, ExprQPath};
+use ast::{ExprMethodCall, ExprParen, ExprPath};
 use ast::{ExprRepeat, ExprRet, ExprStruct, ExprTup, ExprUnary};
 use ast::{ExprVec, ExprWhile, ExprWhileLet, ExprForLoop, Field, FnDecl};
 use ast::{ForeignItem, ForeignItemStatic, ForeignItemFn, ForeignMod, FunctionRetTy};
@@ -43,7 +43,7 @@
 use ast::{Pat, PatEnum, PatIdent, PatLit, PatRange, PatRegion, PatStruct};
 use ast::{PatTup, PatBox, PatWild, PatWildMulti, PatWildSingle};
 use ast::{PolyTraitRef};
-use ast::{QPath, RequiredMethod};
+use ast::{QSelf, RequiredMethod};
 use ast::{Return, BiShl, BiShr, Stmt, StmtDecl};
 use ast::{StmtExpr, StmtSemi, StmtMac, StructDef, StructField};
 use ast::{StructVariantKind, BiSub, StrStyle};
@@ -53,7 +53,7 @@
 use ast::{TupleVariantKind, Ty, Ty_, TypeBinding};
 use ast::{TyFixedLengthVec, TyBareFn};
 use ast::{TyTypeof, TyInfer, TypeMethod};
-use ast::{TyParam, TyParamBound, TyParen, TyPath, TyPolyTraitRef, TyPtr, TyQPath};
+use ast::{TyParam, TyParamBound, TyParen, TyPath, TyPolyTraitRef, TyPtr};
 use ast::{TyRptr, TyTup, TyU32, TyVec, UnUniq};
 use ast::{TypeImplItem, TypeTraitItem, Typedef,};
 use ast::{UnnamedField, UnsafeBlock};
@@ -143,7 +143,7 @@ macro_rules! maybe_whole_expr {
                         _ => unreachable!()
                     };
                     let span = $p.span;
-                    Some($p.mk_expr(span.lo, span.hi, ExprPath(pt)))
+                    Some($p.mk_expr(span.lo, span.hi, ExprPath(None, pt)))
                 }
                 token::Interpolated(token::NtBlock(_)) => {
                     // FIXME: The following avoids an issue with lexical borrowck scopes,
@@ -1076,8 +1076,7 @@ pub fn parse_for_in_type(&mut self) -> Ty_ {
     }
 
     pub fn parse_ty_path(&mut self) -> Ty_ {
-        let path = self.parse_path(LifetimeAndTypesWithoutColons);
-        TyPath(path, ast::DUMMY_NODE_ID)
+        TyPath(None, self.parse_path(LifetimeAndTypesWithoutColons))
     }
 
     /// parse a TyBareFn type:
@@ -1525,19 +1524,36 @@ pub fn parse_ty(&mut self) -> P<Ty> {
         } else if self.eat_lt() {
             // QUALIFIED PATH `<TYPE as TRAIT_REF>::item`
             let self_type = self.parse_ty_sum();
-            self.expect_keyword(keywords::As);
-            let trait_ref = self.parse_trait_ref();
+
+            let mut path = if self.eat_keyword(keywords::As) {
+                self.parse_path(LifetimeAndTypesWithoutColons)
+            } else {
+                ast::Path {
+                    span: self.span,
+                    global: false,
+                    segments: vec![]
+                }
+            };
+
+            let qself = QSelf {
+                ty: self_type,
+                position: path.segments.len()
+            };
+
             self.expect(&token::Gt);
             self.expect(&token::ModSep);
-            let item_name = self.parse_ident();
-            TyQPath(P(QPath {
-                self_type: self_type,
-                trait_ref: P(trait_ref),
-                item_path: ast::PathSegment {
-                    identifier: item_name,
-                    parameters: ast::PathParameters::none()
-                }
-            }))
+
+            path.segments.push(ast::PathSegment {
+                identifier: 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;
+
+            TyPath(Some(qself), path)
         } else if self.check(&token::ModSep) ||
                   self.token.is_ident() ||
                   self.token.is_path() {
@@ -2178,7 +2194,7 @@ pub fn parse_bottom_expr(&mut self) -> P<Expr> {
                          }, token::Plain) => {
                 self.bump();
                 let path = ast_util::ident_to_path(mk_sp(lo, hi), id);
-                ex = ExprPath(path);
+                ex = ExprPath(None, path);
                 hi = self.last_span.hi;
             }
             token::OpenDelim(token::Bracket) => {
@@ -2220,10 +2236,22 @@ pub fn parse_bottom_expr(&mut self) -> P<Expr> {
                 if self.eat_lt() {
                     // QUALIFIED PATH `<TYPE as TRAIT_REF>::item::<'a, T>`
                     let self_type = self.parse_ty_sum();
-                    self.expect_keyword(keywords::As);
-                    let trait_ref = self.parse_trait_ref();
+                    let mut path = if self.eat_keyword(keywords::As) {
+                        self.parse_path(LifetimeAndTypesWithoutColons)
+                    } else {
+                        ast::Path {
+                            span: self.span,
+                            global: false,
+                            segments: vec![]
+                        }
+                    };
+                    let qself = QSelf {
+                        ty: self_type,
+                        position: path.segments.len()
+                    };
                     self.expect(&token::Gt);
                     self.expect(&token::ModSep);
+
                     let item_name = self.parse_ident();
                     let parameters = if self.eat(&token::ModSep) {
                         self.expect_lt();
@@ -2238,15 +2266,18 @@ pub fn parse_bottom_expr(&mut self) -> P<Expr> {
                     } 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 hi = self.span.hi;
-                    return self.mk_expr(lo, hi, ExprQPath(P(QPath {
-                        self_type: self_type,
-                        trait_ref: P(trait_ref),
-                        item_path: ast::PathSegment {
-                            identifier: item_name,
-                            parameters: parameters
-                        }
-                    })));
+                    return self.mk_expr(lo, hi, ExprPath(Some(qself), path));
                 }
                 if self.eat_keyword(keywords::Move) {
                     return self.parse_lambda_expr(CaptureByValue);
@@ -2386,7 +2417,7 @@ pub fn parse_bottom_expr(&mut self) -> P<Expr> {
                     }
 
                     hi = pth.span.hi;
-                    ex = ExprPath(pth);
+                    ex = ExprPath(None, pth);
                 } else {
                     // other literal expression
                     let lit = self.parse_lit();
@@ -3428,7 +3459,7 @@ pub fn parse_pat(&mut self) -> P<Pat> {
                 let end = if self.token.is_ident() || self.token.is_path() {
                     let path = self.parse_path(LifetimeAndTypesWithColons);
                     let hi = self.span.hi;
-                    self.mk_expr(lo, hi, ExprPath(path))
+                    self.mk_expr(lo, hi, ExprPath(None, path))
                 } else {
                     self.parse_literal_maybe_minus()
                 };
@@ -4815,10 +4846,10 @@ fn parse_item_impl(&mut self, unsafety: ast::Unsafety) -> ItemInfo {
         let opt_trait = if could_be_trait && self.eat_keyword(keywords::For) {
             // New-style trait. Reinterpret the type as a trait.
             match ty.node {
-                TyPath(ref path, node_id) => {
+                TyPath(None, ref path) => {
                     Some(TraitRef {
                         path: (*path).clone(),
-                        ref_id: node_id,
+                        ref_id: ty.id,
                     })
                 }
                 _ => {
index 869dad867ebc4f6c8d7fc45783410ac8b6e45a34..af16e19c9f034a1c33399045ef009407cdbf09c1 100644 (file)
@@ -373,7 +373,7 @@ pub fn fn_block_to_string(p: &ast::FnDecl) -> String {
 }
 
 pub fn path_to_string(p: &ast::Path) -> String {
-    $to_string(|s| s.print_path(p, false))
+    $to_string(|s| s.print_path(p, false, 0))
 }
 
 pub fn ident_to_string(id: &ast::Ident) -> String {
@@ -729,8 +729,11 @@ pub fn print_type(&mut self, ty: &ast::Ty) -> IoResult<()> {
                                       &generics,
                                       None));
             }
-            ast::TyPath(ref path, _) => {
-                try!(self.print_path(path, false));
+            ast::TyPath(None, ref path) => {
+                try!(self.print_path(path, false, 0));
+            }
+            ast::TyPath(Some(ref qself), ref path) => {
+                try!(self.print_qpath(path, qself, false))
             }
             ast::TyObjectSum(ref ty, ref bounds) => {
                 try!(self.print_type(&**ty));
@@ -739,9 +742,6 @@ pub fn print_type(&mut self, ty: &ast::Ty) -> IoResult<()> {
             ast::TyPolyTraitRef(ref bounds) => {
                 try!(self.print_bounds("", &bounds[..]));
             }
-            ast::TyQPath(ref qpath) => {
-                try!(self.print_qpath(&**qpath, false))
-            }
             ast::TyFixedLengthVec(ref ty, ref v) => {
                 try!(word(&mut self.s, "["));
                 try!(self.print_type(&**ty));
@@ -1018,7 +1018,7 @@ pub fn print_item(&mut self, item: &ast::Item) -> IoResult<()> {
             ast::ItemMac(codemap::Spanned { node: ast::MacInvocTT(ref pth, ref tts, _),
                                             ..}) => {
                 try!(self.print_visibility(item.vis));
-                try!(self.print_path(pth, false));
+                try!(self.print_path(pth, false, 0));
                 try!(word(&mut self.s, "! "));
                 try!(self.print_ident(item.ident));
                 try!(self.cbox(indent_unit));
@@ -1033,7 +1033,7 @@ pub fn print_item(&mut self, item: &ast::Item) -> IoResult<()> {
     }
 
     fn print_trait_ref(&mut self, t: &ast::TraitRef) -> IoResult<()> {
-        self.print_path(&t.path, false)
+        self.print_path(&t.path, false, 0)
     }
 
     fn print_formal_lifetime_list(&mut self, lifetimes: &[ast::LifetimeDef]) -> IoResult<()> {
@@ -1297,7 +1297,7 @@ pub fn print_method(&mut self, meth: &ast::Method) -> IoResult<()> {
             ast::MethMac(codemap::Spanned { node: ast::MacInvocTT(ref pth, ref tts, _),
                                             ..}) => {
                 // code copied from ItemMac:
-                try!(self.print_path(pth, false));
+                try!(self.print_path(pth, false, 0));
                 try!(word(&mut self.s, "! "));
                 try!(self.cbox(indent_unit));
                 try!(self.popen());
@@ -1514,7 +1514,7 @@ pub fn print_mac(&mut self, m: &ast::Mac, delim: token::DelimToken)
         match m.node {
             // I think it's reasonable to hide the ctxt here:
             ast::MacInvocTT(ref pth, ref tts, _) => {
-                try!(self.print_path(pth, false));
+                try!(self.print_path(pth, false, 0));
                 try!(word(&mut self.s, "!"));
                 match delim {
                     token::Paren => try!(self.popen()),
@@ -1584,7 +1584,7 @@ fn print_expr_struct(&mut self,
                          path: &ast::Path,
                          fields: &[ast::Field],
                          wth: &Option<P<ast::Expr>>) -> IoResult<()> {
-        try!(self.print_path(path, true));
+        try!(self.print_path(path, true, 0));
         if !(fields.is_empty() && wth.is_none()) {
             try!(word(&mut self.s, "{"));
             try!(self.commasep_cmnt(
@@ -1852,8 +1852,12 @@ pub fn print_expr(&mut self, expr: &ast::Expr) -> IoResult<()> {
                     try!(self.print_expr(&**e));
                 }
             }
-            ast::ExprPath(ref path) => try!(self.print_path(path, true)),
-            ast::ExprQPath(ref qpath) => try!(self.print_qpath(&**qpath, true)),
+            ast::ExprPath(None, ref path) => {
+                try!(self.print_path(path, true, 0))
+            }
+            ast::ExprPath(Some(ref qself), ref path) => {
+                try!(self.print_qpath(path, qself, true))
+            }
             ast::ExprBreak(opt_ident) => {
                 try!(word(&mut self.s, "break"));
                 try!(space(&mut self.s));
@@ -2014,16 +2018,14 @@ pub fn print_for_decl(&mut self, loc: &ast::Local,
 
     fn print_path(&mut self,
                   path: &ast::Path,
-                  colons_before_params: bool)
+                  colons_before_params: bool,
+                  depth: usize)
                   -> IoResult<()>
     {
         try!(self.maybe_print_comment(path.span.lo));
-        if path.global {
-            try!(word(&mut self.s, "::"));
-        }
 
-        let mut first = true;
-        for segment in &path.segments {
+        let mut first = !path.global;
+        for segment in &path.segments[..path.segments.len()-depth] {
             if first {
                 first = false
             } else {
@@ -2039,19 +2041,24 @@ fn print_path(&mut self,
     }
 
     fn print_qpath(&mut self,
-                   qpath: &ast::QPath,
+                   path: &ast::Path,
+                   qself: &ast::QSelf,
                    colons_before_params: bool)
                    -> IoResult<()>
     {
         try!(word(&mut self.s, "<"));
-        try!(self.print_type(&*qpath.self_type));
-        try!(space(&mut self.s));
-        try!(self.word_space("as"));
-        try!(self.print_trait_ref(&*qpath.trait_ref));
+        try!(self.print_type(&qself.ty));
+        if qself.position > 0 {
+            try!(space(&mut self.s));
+            try!(self.word_space("as"));
+            let depth = path.segments.len() - qself.position;
+            try!(self.print_path(&path, false, depth));
+        }
         try!(word(&mut self.s, ">"));
         try!(word(&mut self.s, "::"));
-        try!(self.print_ident(qpath.item_path.identifier));
-        self.print_path_parameters(&qpath.item_path.parameters, colons_before_params)
+        let item_segment = path.segments.last().unwrap();
+        try!(self.print_ident(item_segment.identifier));
+        self.print_path_parameters(&item_segment.parameters, colons_before_params)
     }
 
     fn print_path_parameters(&mut self,
@@ -2156,7 +2163,7 @@ pub fn print_pat(&mut self, pat: &ast::Pat) -> IoResult<()> {
                 }
             }
             ast::PatEnum(ref path, ref args_) => {
-                try!(self.print_path(path, true));
+                try!(self.print_path(path, true, 0));
                 match *args_ {
                     None => try!(word(&mut self.s, "(..)")),
                     Some(ref args) => {
@@ -2170,7 +2177,7 @@ pub fn print_pat(&mut self, pat: &ast::Pat) -> IoResult<()> {
                 }
             }
             ast::PatStruct(ref path, ref fields, etc) => {
-                try!(self.print_path(path, true));
+                try!(self.print_path(path, true, 0));
                 try!(self.nbsp());
                 try!(self.word_space("{"));
                 try!(self.commasep_cmnt(
@@ -2555,7 +2562,7 @@ pub fn print_where_clause(&mut self, generics: &ast::Generics)
                     }
                 }
                 &ast::WherePredicate::EqPredicate(ast::WhereEqPredicate{ref path, ref ty, ..}) => {
-                    try!(self.print_path(path, false));
+                    try!(self.print_path(path, false, 0));
                     try!(space(&mut self.s));
                     try!(self.word_space("="));
                     try!(self.print_type(&**ty));
@@ -2592,7 +2599,7 @@ pub fn print_meta_item(&mut self, item: &ast::MetaItem) -> IoResult<()> {
     pub fn print_view_path(&mut self, vp: &ast::ViewPath) -> IoResult<()> {
         match vp.node {
             ast::ViewPathSimple(ident, ref path) => {
-                try!(self.print_path(path, false));
+                try!(self.print_path(path, false, 0));
 
                 // FIXME(#6993) can't compare identifiers directly here
                 if path.segments.last().unwrap().identifier.name !=
@@ -2606,7 +2613,7 @@ pub fn print_view_path(&mut self, vp: &ast::ViewPath) -> IoResult<()> {
             }
 
             ast::ViewPathGlob(ref path) => {
-                try!(self.print_path(path, false));
+                try!(self.print_path(path, false, 0));
                 word(&mut self.s, "::*")
             }
 
@@ -2614,7 +2621,7 @@ pub fn print_view_path(&mut self, vp: &ast::ViewPath) -> IoResult<()> {
                 if path.segments.is_empty() {
                     try!(word(&mut self.s, "{"));
                 } else {
-                    try!(self.print_path(path, false));
+                    try!(self.print_path(path, false, 0));
                     try!(word(&mut self.s, "::{"));
                 }
                 try!(self.commasep(Inconsistent, &idents[..], |s, w| {
index 0a39d3809045a2e56f745255e6b204bc5d43f8d0..90df23882a1d4bf53c790a36ed40dae5ac899696 100644 (file)
@@ -229,10 +229,10 @@ fn test_move_iter() {
         assert_eq!(Vec::new(), v);
 
         let v = SmallVector::one(1);
-        assert_eq!(vec![1], v.into_iter().collect::<Vec<_>>());
+        assert_eq!([1], v.into_iter().collect::<Vec<_>>());
 
         let v = SmallVector::many(vec![1, 2, 3]);
-        assert_eq!(vec!(1, 2, 3), v.into_iter().collect::<Vec<_>>());
+        assert_eq!([1, 2, 3], v.into_iter().collect::<Vec<_>>());
     }
 
     #[test]
index 412bf0fa22a00a37dd77567636fd9eeb40a4914e..33d8d56b4b11469cb6ccbf9890a57ba9d7555389 100644 (file)
@@ -125,9 +125,6 @@ fn visit_mac(&mut self, _mac: &'v Mac) {
     fn visit_path(&mut self, path: &'v Path, _id: ast::NodeId) {
         walk_path(self, path)
     }
-    fn visit_qpath(&mut self, qpath_span: Span, qpath: &'v QPath) {
-        walk_qpath(self, qpath_span, qpath)
-    }
     fn visit_path_segment(&mut self, path_span: Span, path_segment: &'v PathSegment) {
         walk_path_segment(self, path_span, path_segment)
     }
@@ -399,16 +396,16 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty) {
             walk_fn_ret_ty(visitor, &function_declaration.decl.output);
             walk_lifetime_decls_helper(visitor, &function_declaration.lifetimes);
         }
-        TyPath(ref path, id) => {
-            visitor.visit_path(path, id);
+        TyPath(ref maybe_qself, ref path) => {
+            if let Some(ref qself) = *maybe_qself {
+                visitor.visit_ty(&qself.ty);
+            }
+            visitor.visit_path(path, typ.id);
         }
         TyObjectSum(ref ty, ref bounds) => {
             visitor.visit_ty(&**ty);
             walk_ty_param_bounds_helper(visitor, bounds);
         }
-        TyQPath(ref qpath) => {
-            visitor.visit_qpath(typ.span, &**qpath);
-        }
         TyFixedLengthVec(ref ty, ref expression) => {
             visitor.visit_ty(&**ty);
             visitor.visit_expr(&**expression)
@@ -436,14 +433,6 @@ pub fn walk_path<'v, V: Visitor<'v>>(visitor: &mut V, path: &'v Path) {
     }
 }
 
-pub fn walk_qpath<'v, V: Visitor<'v>>(visitor: &mut V,
-                                      qpath_span: Span,
-                                      qpath: &'v QPath) {
-    visitor.visit_ty(&*qpath.self_type);
-    visitor.visit_trait_ref(&*qpath.trait_ref);
-    visitor.visit_path_segment(qpath_span, &qpath.item_path);
-}
-
 pub fn walk_path_segment<'v, V: Visitor<'v>>(visitor: &mut V,
                                              path_span: Span,
                                              segment: &'v PathSegment) {
@@ -869,12 +858,12 @@ pub fn walk_expr<'v, V: Visitor<'v>>(visitor: &mut V, expression: &'v Expr) {
             walk_expr_opt(visitor, start);
             walk_expr_opt(visitor, end)
         }
-        ExprPath(ref path) => {
+        ExprPath(ref maybe_qself, ref path) => {
+            if let Some(ref qself) = *maybe_qself {
+                visitor.visit_ty(&qself.ty);
+            }
             visitor.visit_path(path, expression.id)
         }
-        ExprQPath(ref qpath) => {
-            visitor.visit_qpath(expression.span, &**qpath)
-        }
         ExprBreak(_) | ExprAgain(_) => {}
         ExprRet(ref optional_expression) => {
             walk_expr_opt(visitor, optional_expression)
index 5418533aff1d918129f9bae1f6f5059dd603fe55..823d2879236d1a9d961a60f5c9a8a646968fb7a0 100644 (file)
@@ -60,6 +60,7 @@
 #![feature(unicode)]
 #![feature(std_misc)]
 #![feature(env)]
+#![feature(os)]
 #![cfg_attr(windows, feature(libc))]
 
 #[macro_use] extern crate log;
index 0b577f8de74c2a9b2e8178584173c29e8d134b7a..112525fcce96efe2a1762a6555f4ddee0a80daa5 100644 (file)
@@ -652,15 +652,15 @@ fn test_comparison_ops() {
             let s = format!("%{{1}}%{{2}}%{}%d", op);
             let res = expand(s.as_bytes(), &[], &mut Variables::new());
             assert!(res.is_ok(), res.err().unwrap());
-            assert_eq!(res.unwrap(), vec!(b'0' + bs[0]));
+            assert_eq!(res.unwrap(), [b'0' + bs[0]]);
             let s = format!("%{{1}}%{{1}}%{}%d", op);
             let res = expand(s.as_bytes(), &[], &mut Variables::new());
             assert!(res.is_ok(), res.err().unwrap());
-            assert_eq!(res.unwrap(), vec!(b'0' + bs[1]));
+            assert_eq!(res.unwrap(), [b'0' + bs[1]]);
             let s = format!("%{{2}}%{{1}}%{}%d", op);
             let res = expand(s.as_bytes(), &[], &mut Variables::new());
             assert!(res.is_ok(), res.err().unwrap());
-            assert_eq!(res.unwrap(), vec!(b'0' + bs[2]));
+            assert_eq!(res.unwrap(), [b'0' + bs[2]]);
         }
     }
 
index c40a5534efbbb4e8d3d6146c6c513a124a420c62..a0cd78420700187e78aa2ef451e5ff81f0bf2a3a 100644 (file)
 use std::env;
 
 /// Return path to database entry for `term`
+#[allow(deprecated)]
 pub fn get_dbpath_for_term(term: &str) -> Option<Box<Path>> {
     if term.len() == 0 {
         return None;
     }
 
-    let homedir = env::home_dir();
+    let homedir = ::std::os::homedir();
 
     let mut dirs_to_search = Vec::new();
     let first_char = term.char_at(0);
index 82c1a4b1195ce06ca1f948e39c13fe01f613991f..7c7f1fd478aa9e8b7016d8f6a1279fd38644a90f 100644 (file)
@@ -506,16 +506,25 @@ pub fn write_pretty(&mut self,
                 if self.use_color {
                     try!(term.reset());
                 }
-                Ok(())
+                term.flush()
+            }
+            Raw(ref mut stdout) => {
+                try!(stdout.write_all(word.as_bytes()));
+                stdout.flush()
             }
-            Raw(ref mut stdout) => stdout.write_all(word.as_bytes())
         }
     }
 
     pub fn write_plain(&mut self, s: &str) -> old_io::IoResult<()> {
         match self.out {
-            Pretty(ref mut term) => term.write_all(s.as_bytes()),
-            Raw(ref mut stdout) => stdout.write_all(s.as_bytes())
+            Pretty(ref mut term) => {
+                try!(term.write_all(s.as_bytes()));
+                term.flush()
+            },
+            Raw(ref mut stdout) => {
+                try!(stdout.write_all(s.as_bytes()));
+                stdout.flush()
+            },
         }
     }
 
index 3c116aa860bca9c10c1cf285832dde4f028ca07b..8900b60d1913a2eb533702a630fda0cb4f0b9063 100644 (file)
@@ -114,12 +114,12 @@ fn collapse(stack: &mut Vec<BookItem>,
             }
         };
 
-        let star_idx = match line.find_str("*") { Some(i) => i, None => continue };
+        let star_idx = match line.find("*") { Some(i) => i, None => continue };
 
-        let start_bracket = star_idx + line[star_idx..].find_str("[").unwrap();
-        let end_bracket = start_bracket + line[start_bracket..].find_str("](").unwrap();
+        let start_bracket = star_idx + line[star_idx..].find("[").unwrap();
+        let end_bracket = start_bracket + line[start_bracket..].find("](").unwrap();
         let start_paren = end_bracket + 1;
-        let end_paren = start_paren + line[start_paren..].find_str(")").unwrap();
+        let end_paren = start_paren + line[start_paren..].find(")").unwrap();
 
         let given_path = &line[start_paren + 1 .. end_paren];
         let title = line[start_bracket + 1..end_bracket].to_string();
index 9f35bdaa367e5ee5d6d31d4f517cbfecdbc31cbe..f36d97d6d120d50ef2f42aaa2f47f3de788e49c7 100644 (file)
@@ -11,6 +11,7 @@
 //! Implementation of the `build` subcommand, used to compile a book.
 
 use std::env;
+use std::os;
 use std::old_io;
 use std::old_io::{fs, File, BufferedWriter, TempDir, IoResult};
 
@@ -81,7 +82,7 @@ fn render(book: &Book, tgt: &Path) -> CliResult<()> {
 
         let src;
         if env::args().len() < 3 {
-            src = env::current_dir().unwrap().clone();
+            src = os::getcwd().unwrap().clone();
         } else {
             src = Path::new(env::args().nth(2).unwrap().clone());
         }
@@ -149,7 +150,7 @@ fn parse_args(&mut self, _: &[String]) -> CliResult<()> {
     }
     fn usage(&self) {}
     fn execute(&mut self, term: &mut Term) -> CommandResult<()> {
-        let cwd = env::current_dir().unwrap();
+        let cwd = os::getcwd().unwrap();
         let src;
         let tgt;
 
index 68e4ba54d94c168fdf5c22305288056dd2a93c48..b9fc011e8b9a584edf198247e2eb1d0de9f67399 100644 (file)
@@ -13,6 +13,7 @@
 #![feature(core)]
 #![feature(old_io)]
 #![feature(env)]
+#![feature(os)]
 #![feature(old_path)]
 #![feature(rustdoc)]
 
index bff366163dc2f974f6c95792a1a7e5e534ac80c9..727a385a8f02811e19eb7a43d87b6500cd369e63 100644 (file)
@@ -17,7 +17,7 @@
 use term::Term;
 use book;
 use std::old_io::{Command, File};
-use std::env;
+use std::os;
 
 struct Test;
 
@@ -35,7 +35,7 @@ fn parse_args(&mut self, _: &[String]) -> CliResult<()> {
     }
     fn usage(&self) {}
     fn execute(&mut self, term: &mut Term) -> CommandResult<()> {
-        let cwd = env::current_dir().unwrap();
+        let cwd = os::getcwd().unwrap();
         let src = cwd.clone();
 
         let summary = File::open(&src.join("SUMMARY.md"));
index 46a942b6eeb86a24f1345dbe733a2dc1b0279e55..318f66b946585d6cbd44f6760ab8e0e56f54d62b 100644 (file)
@@ -1,3 +1,12 @@
+S 2015-02-25 880fb89
+  freebsd-x86_64 f4cbe4227739de986444211f8ee8d74745ab8f7f
+  linux-i386 3278ebbce8cb269acc0614dac5ddac07eab6a99c
+  linux-x86_64 72287d0d88de3e5a53bae78ac0d958e1a7637d73
+  macos-i386 33b366b5287427a340a0aa6ed886d5ff4edf6a76
+  macos-x86_64 914bf9baa32081a9d5633f1d06f4d382cd71504e
+  winnt-i386 d58b415b9d8629cb6c4952f1f6611a526a38323f
+  winnt-x86_64 2cb1dcc563d2ac6deada054de15748f5dd599c7e
+
 S 2015-02-19 522d09d
   freebsd-x86_64 7ea14ef85a25bca70a310a2cd660b356cf61abc7
   linux-i386 26e3caa1ce1c482b9941a6bdc64b3e65d036c200
index fb535eb8336f9b2df90d027c61cef3fb9f731097..d47575403e171729b4dd4c579eaa85a9e0dcfbc9 100644 (file)
@@ -100,14 +100,22 @@ pub trait UnstableTrait { fn dummy(&self) { } }
 
 #[stable(feature = "test_feature", since = "1.0.0")]
 #[deprecated(since = "1.0.0")]
-pub struct DeprecatedStruct { pub i: int }
+pub struct DeprecatedStruct {
+    #[stable(feature = "test_feature", since = "1.0.0")] pub i: int
+}
 #[unstable(feature = "test_feature")]
 #[deprecated(since = "1.0.0")]
-pub struct DeprecatedUnstableStruct { pub i: int }
+pub struct DeprecatedUnstableStruct {
+    #[stable(feature = "test_feature", since = "1.0.0")] pub i: int
+}
 #[unstable(feature = "test_feature")]
-pub struct UnstableStruct { pub i: int }
+pub struct UnstableStruct {
+    #[stable(feature = "test_feature", since = "1.0.0")] pub i: int
+}
 #[stable(feature = "rust1", since = "1.0.0")]
-pub struct StableStruct { pub i: int }
+pub struct StableStruct {
+    #[stable(feature = "test_feature", since = "1.0.0")] pub i: int
+}
 
 #[stable(feature = "test_feature", since = "1.0.0")]
 #[deprecated(since = "1.0.0")]
@@ -137,14 +145,14 @@ pub enum Enum {
 
 #[stable(feature = "test_feature", since = "1.0.0")]
 #[deprecated(since = "1.0.0")]
-pub struct DeprecatedTupleStruct(pub int);
+pub struct DeprecatedTupleStruct(#[stable(feature = "rust1", since = "1.0.0")] pub int);
 #[unstable(feature = "test_feature")]
 #[deprecated(since = "1.0.0")]
-pub struct DeprecatedUnstableTupleStruct(pub int);
+pub struct DeprecatedUnstableTupleStruct(#[stable(feature = "rust1", since = "1.0.0")] pub int);
 #[unstable(feature = "test_feature")]
-pub struct UnstableTupleStruct(pub int);
+pub struct UnstableTupleStruct(#[stable(feature = "rust1", since = "1.0.0")] pub int);
 #[stable(feature = "rust1", since = "1.0.0")]
-pub struct StableTupleStruct(pub int);
+pub struct StableTupleStruct(#[stable(feature = "rust1", since = "1.0.0")] pub int);
 
 #[macro_export]
 macro_rules! macro_test {
diff --git a/src/test/auxiliary/lint_stability_fields.rs b/src/test/auxiliary/lint_stability_fields.rs
new file mode 100644 (file)
index 0000000..66940ee
--- /dev/null
@@ -0,0 +1,60 @@
+// 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(staged_api)]
+#![staged_api]
+#![stable(feature = "rust1", since = "1.0.0")]
+
+#[stable(feature = "rust1", since = "1.0.0")]
+pub struct Stable {
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub inherit: u8, // it's a lie (stable doesn't inherit)
+    #[unstable(feature = "test_feature")]
+    pub override1: u8,
+    #[deprecated(since = "1.0.0")]
+    #[unstable(feature = "test_feature")]
+    pub override2: u8,
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+pub struct Stable2(#[stable(feature = "rust1", since = "1.0.0")] pub u8,
+                   #[unstable(feature = "test_feature")] pub u8,
+                   #[unstable(feature = "test_feature")] #[deprecated(since = "1.0.0")] pub u8);
+
+#[unstable(feature = "test_feature")]
+pub struct Unstable {
+    pub inherit: u8,
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub override1: u8,
+    #[deprecated(since = "1.0.0")]
+    #[unstable(feature = "test_feature")]
+    pub override2: u8,
+}
+
+#[unstable(feature = "test_feature")]
+pub struct Unstable2(pub u8,
+                     #[stable(feature = "rust1", since = "1.0.0")] pub u8,
+                     #[unstable(feature = "test_feature")] #[deprecated(since = "1.0.0")] pub u8);
+
+#[unstable(feature = "test_feature")]
+#[deprecated(feature = "rust1", since = "1.0.0")]
+pub struct Deprecated {
+    pub inherit: u8,
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub override1: u8,
+    #[unstable(feature = "test_feature")]
+    pub override2: u8,
+}
+
+#[unstable(feature = "test_feature")]
+#[deprecated(feature = "rust1", since = "1.0.0")]
+pub struct Deprecated2(pub u8,
+                       #[stable(feature = "rust1", since = "1.0.0")] pub u8,
+                       #[unstable(feature = "test_feature")] pub u8);
index d84ded25702f4b38de4abf61bb5721b6e526068a..e61fb49add5b1e7aa5f53082113d483488178d3c 100644 (file)
 #![crate_name="static_methods_crate"]
 #![crate_type = "lib"]
 
-use std::int;
-
 pub trait read {
     fn readMaybe(s: String) -> Option<Self>;
 }
 
-impl read for int {
-    fn readMaybe(s: String) -> Option<int> {
+impl read for isize {
+    fn readMaybe(s: String) -> Option<isize> {
         s.parse().ok()
     }
 }
index 6b412c47cd7f81bdf9d0713f8818dbd84aaa1471..896b0ee57a04cb47186e29aaafd7b5a634d2fed6 100644 (file)
@@ -40,9 +40,7 @@ fn run(repeat: int, depth: int) {
     }
 }
 
-// FIXME(#21721) used to be `List<()>` but that can cause
-// certain LLVM versions to abort during optimizations.
-type nillist = List<[u8; 0]>;
+type nillist = List<()>;
 
 // Filled with things that have to be unwound
 
@@ -83,11 +81,11 @@ fn recurse_or_panic(depth: int, st: Option<State>) {
             }
             Some(st) => {
                 let mut v = st.vec.clone();
-                v.push_all(&[box List::Cons([], st.vec.last().unwrap().clone())]);
+                v.push_all(&[box List::Cons((), st.vec.last().unwrap().clone())]);
                 State {
-                    unique: box List::Cons([], box *st.unique),
+                    unique: box List::Cons((), box *st.unique),
                     vec: v,
-                    res: r(box List::Cons([], st.res._l.clone())),
+                    res: r(box List::Cons((), st.res._l.clone())),
                 }
             }
         };
diff --git a/src/test/compile-fail/associated-type-projection-ambig-between-bound-and-where-clause.rs b/src/test/compile-fail/associated-type-projection-ambig-between-bound-and-where-clause.rs
new file mode 100644 (file)
index 0000000..ce97019
--- /dev/null
@@ -0,0 +1,52 @@
+// 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.
+
+// Test equality constraints in a where clause where the type being
+// equated appears in a supertrait.
+
+pub trait Vehicle {
+    type Color;
+
+    fn go(&self) {  }
+}
+
+pub trait Box {
+    type Color;
+
+    fn mail(&self) {  }
+}
+
+fn a<C:Vehicle+Box>(_: C::Color) {
+    //~^ ERROR ambiguous associated type `Color` in bounds of `C`
+}
+
+fn b<C>(_: C::Color) where C : Vehicle+Box {
+    //~^ ERROR ambiguous associated type `Color` in bounds of `C`
+}
+
+fn c<C>(_: C::Color) where C : Vehicle, C : Box {
+    //~^ ERROR ambiguous associated type `Color` in bounds of `C`
+}
+
+struct D<X>;
+impl<X> D<X> where X : Vehicle {
+    fn d(&self, _: X::Color) where X : Box { }
+    //~^ ERROR ambiguous associated type `Color` in bounds of `X`
+}
+
+trait E<X:Vehicle> {
+    fn e(&self, _: X::Color) where X : Box;
+    //~^ ERROR ambiguous associated type `Color` in bounds of `X`
+
+    fn f(&self, _: X::Color) where X : Box { }
+    //~^ ERROR ambiguous associated type `Color` in bounds of `X`
+}
+
+pub fn main() { }
index 3999e9cbe753d1d90ab8294ada23d1d1be274f6a..becbc27138b770e700d524844357252c7c017c95 100644 (file)
@@ -22,5 +22,8 @@ trait Grab {
     //~^ ERROR ambiguous associated type
 }
 
+type X = std::ops::Deref::Target;
+//~^ ERROR ambiguous associated type
+
 fn main() {
 }
index 3e02a11c378bd5a2292e8824c149cc4792479098..7a7406115d39365a5735d7f24a735eaa43c91941 100644 (file)
@@ -43,7 +43,7 @@ fn foo<'a>() {
     //~^ ERROR too many type parameters provided
 
     let _ = S::<'a,isize>::new::<f64>(1, 1.0);
-    //~^ ERROR too many lifetime parameters provided
+    //~^ ERROR wrong number of lifetime parameters
 
     let _: S2 = Trait::new::<isize,f64>(1, 1.0);
     //~^ ERROR too many type parameters provided
diff --git a/src/test/compile-fail/borrowck-fn-in-const-a.rs b/src/test/compile-fail/borrowck-fn-in-const-a.rs
new file mode 100644 (file)
index 0000000..3098807
--- /dev/null
@@ -0,0 +1,22 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Check that we check fns appearing in constant declarations.
+// Issue #22382.
+
+const MOVE: fn(&String) -> String = {
+    fn broken(x: &String) -> String {
+        return *x //~ ERROR cannot move
+    }
+    broken
+};
+
+fn main() {
+}
diff --git a/src/test/compile-fail/borrowck-fn-in-const-b.rs b/src/test/compile-fail/borrowck-fn-in-const-b.rs
new file mode 100644 (file)
index 0000000..7e29b2e
--- /dev/null
@@ -0,0 +1,24 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Check that we check fns appearing in constant declarations.
+// Issue #22382.
+
+// How about mutating an immutable vector?
+const MUTATE: fn(&Vec<String>) = {
+    fn broken(x: &Vec<String>) {
+        x.push(format!("this is broken"));
+        //~^ ERROR cannot borrow
+    }
+    broken
+};
+
+fn main() {
+}
diff --git a/src/test/compile-fail/borrowck-fn-in-const-c.rs b/src/test/compile-fail/borrowck-fn-in-const-c.rs
new file mode 100644 (file)
index 0000000..e607397
--- /dev/null
@@ -0,0 +1,33 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Check that we check fns appearing in constant declarations.
+// Issue #22382.
+
+// Returning local references?
+struct DropString {
+    inner: String
+}
+impl Drop for DropString {
+    fn drop(&mut self) {
+        self.inner.clear();
+        self.inner.push_str("dropped");
+    }
+}
+const LOCAL_REF: fn() -> &'static str = {
+    fn broken() -> &'static str {
+        let local = DropString { inner: format!("Some local string") };
+        return &local.inner; //~ ERROR does not live long enough
+    }
+    broken
+};
+
+fn main() {
+}
diff --git a/src/test/compile-fail/cycle-projection-based-on-where-clause.rs b/src/test/compile-fail/cycle-projection-based-on-where-clause.rs
new file mode 100644 (file)
index 0000000..abcbf56
--- /dev/null
@@ -0,0 +1,34 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Example cycle where a bound on `T` uses a shorthand for `T`. This
+// creates a cycle because we have to know the bounds on `T` to figure
+// out what trait defines `Item`, but we can't know the bounds on `T`
+// without knowing how to handle `T::Item`.
+//
+// Note that in the future cases like this could perhaps become legal,
+// if we got more fine-grained about our cycle detection or changed
+// how we handle `T::Item` resolution.
+
+use std::ops::Add;
+
+// Preamble.
+trait Trait { type Item; }
+
+struct A<T>
+    where T : Trait,
+          T : Add<T::Item>
+    //~^ ERROR illegal recursive type
+{
+    data: T
+}
+
+fn main() {
+}
diff --git a/src/test/compile-fail/cycle-trait-supertrait-direct.rs b/src/test/compile-fail/cycle-trait-supertrait-direct.rs
new file mode 100644 (file)
index 0000000..ef3fead
--- /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.
+
+// Test a supertrait cycle where a trait extends itself.
+
+trait Chromosome: Chromosome {
+    //~^ ERROR unsupported cyclic reference
+}
+
+fn main() { }
diff --git a/src/test/compile-fail/cycle-trait-supertrait-indirect.rs b/src/test/compile-fail/cycle-trait-supertrait-indirect.rs
new file mode 100644 (file)
index 0000000..6ebd9a1
--- /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.
+
+// Test a supertrait cycle where the first trait we find (`A`) is not
+// a direct participant in the cycle.
+
+trait A: B {
+}
+
+trait B: C { }
+
+trait C: B { }
+    //~^ ERROR unsupported cyclic reference
+
+fn main() { }
index ade8b397e0003d0e306f145ee334f934a8850a0d..21334e1d51375420c373ed906fdd09e59f1c6bc0 100644 (file)
@@ -24,7 +24,7 @@
 
     // Unresolved bounds should still error.
     fn align_of<T: NoSuchTrait>() -> usize;
-    //~^ ERROR attempt to bound type parameter with a nonexistent trait `NoSuchTrait`
+    //~^ ERROR use of undeclared trait name `NoSuchTrait`
 }
 
 fn main() {}
index 9fea5e609d1f4807812476ea8b2e53c5da09fcdf..5fa429445a35e66fc5d68df606e872227e308adf 100644 (file)
@@ -19,5 +19,5 @@ fn new() -> Foo<A, B, C> {Foo(marker::PhantomData)}
 
 fn main() {
     Foo::<isize>::new();
-    //~^ ERROR too few type parameters provided
+    //~^ ERROR wrong number of type arguments
 }
index 73c19aa012dcf67dd0d39d97f8a748f9cb1a436c..d3babb8982ddca652bdd9c16e113d89ea74f445a 100644 (file)
@@ -21,5 +21,5 @@ fn new() -> Vec<T, A> {Vec(marker::PhantomData)}
 
 fn main() {
     Vec::<isize, Heap, bool>::new();
-    //~^ ERROR too many type parameters provided
+    //~^ ERROR wrong number of type arguments
 }
index fce8a07d7270d3444fb83e4343a77e2bc90f7886..181503db818462907d8854a0cbb9e6b4cd4752dd 100644 (file)
@@ -36,9 +36,6 @@ fn main() {
     import(); //~ ERROR: unresolved
 
     foo::<A>(); //~ ERROR: undeclared
-    //~^ ERROR: undeclared
     foo::<C>(); //~ ERROR: undeclared
-    //~^ ERROR: undeclared
     foo::<D>(); //~ ERROR: undeclared
-    //~^ ERROR: undeclared
 }
index c6ce4d04e10866951d30c17fadb8c4dfefb1e56b..c0c951dd8b10835c990421bfc3a26ddfa2a9f055 100644 (file)
@@ -11,7 +11,7 @@
 struct Foo;
 impl Foo {
     fn orange(&self){}
-    fn orange(&self){}   //~ ERROR error: duplicate definition of value `orange`
+    fn orange(&self){}   //~ ERROR error: duplicate method in trait impl
 }
 
 fn main() {}
diff --git a/src/test/compile-fail/impl-not-adjacent-to-type.rs b/src/test/compile-fail/impl-not-adjacent-to-type.rs
deleted file mode 100644 (file)
index 7a7673d..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-mod foo {
-    pub struct Foo {
-        x: isize,
-        y: isize,
-    }
-}
-
-impl foo::Foo {
-//~^ ERROR implementations may only be implemented in the same module
-    fn bar() {}
-}
-
-fn main() {}
-
index abd7efe0e8ed1faf141b88d662d7e4482294cc3c..cf2a70deee513cf3945a6389557febc52367ec1f 100644 (file)
@@ -14,7 +14,8 @@ enum Bar<T> { What }
 
 fn foo<T>() {
     static a: Bar<T> = Bar::What;
-    //~^ ERROR: cannot use an outer type parameter in this context
+    //~^ ERROR cannot use an outer type parameter in this context
+    //~| ERROR use of undeclared type name `T`
 }
 
 fn main() {
diff --git a/src/test/compile-fail/issue-12729.rs b/src/test/compile-fail/issue-12729.rs
deleted file mode 100644 (file)
index ae033bb..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// ignore-tidy-linelength
-
-pub struct Foo;
-
-mod bar {
-    use Foo;
-
-    impl Foo { //~ERROR inherent implementations are only allowed on types defined in the current module
-        fn baz(&self) {}
-    }
-}
-fn main() {}
-
index 3f5d29a82175805b40221dac4818821908952190..51b6dc0d07865eda130cbc0e8633f90907501550 100644 (file)
@@ -17,9 +17,9 @@ impl Bar { pub fn new() {} }
 
 fn main() {
     a::Foo::new();
-    //~^ ERROR: static method `new` is inaccessible
+    //~^ ERROR: method `new` is inaccessible
     //~^^ NOTE: struct `Foo` is private
     a::Bar::new();
-    //~^ ERROR: static method `new` is inaccessible
+    //~^ ERROR: method `new` is inaccessible
     //~^^ NOTE: enum `Bar` is private
 }
index 74eea0c57a01aaf3e29e86a5b197986134119815..ce5fa1f1fe1a5e66e4fc4cb9fc54f8d4de85c873 100644 (file)
@@ -29,7 +29,7 @@ fn bar(&self) {
         baz();
         //~^ ERROR: unresolved name `baz`. Did you mean to call `self.baz`?
         a;
-        //~^ ERROR: unresolved name `a`. Did you mean to call `BarTy::a`?
+        //~^ ERROR: unresolved name `a`
     }
 }
 
@@ -42,11 +42,11 @@ fn bar(&self) {
         y;
         //~^ ERROR: unresolved name `y`. Did you mean `self.y`?
         a;
-        //~^ ERROR: unresolved name `a`. Did you mean to call `BarTy::a`?
+        //~^ ERROR: unresolved name `a`
         bah;
         //~^ ERROR: unresolved name `bah`. Did you mean to call `Foo::bah`?
         b;
-        //~^ ERROR: unresolved name `b`. Did you mean to call `self.b`?
+        //~^ ERROR: unresolved name `b`
     }
 }
 
@@ -59,11 +59,11 @@ fn bar(&self) {
         y;
         //~^ ERROR: unresolved name `y`. Did you mean `self.y`?
         a;
-        //~^ ERROR: unresolved name `a`. Did you mean to call `BarTy::a`?
+        //~^ ERROR: unresolved name `a`
         bah;
         //~^ ERROR: unresolved name `bah`. Did you mean to call `Foo::bah`?
         b;
-        //~^ ERROR: unresolved name `b`. Did you mean to call `self.b`?
+        //~^ ERROR: unresolved name `b`
     }
 }
 
index bbc5ee6c8f36e336e453eb9c0920de56faf1e0fb..c6ff82364b3e7cd57c279b9e4772aab1d386c51f 100644 (file)
@@ -15,18 +15,11 @@ trait From<Src> {
 }
 
 trait To {
-    // This is a typo, the return type should be `<Dst as From<Self>>::Output`
-    fn to<Dst: From<Self>>(
-        self
-        //~^ error: the trait `core::marker::Sized` is not implemented
-    ) ->
+    fn to<Dst: From<Self>>(self) ->
         <Dst as From<Self>>::Dst
-        //~^ error: the trait `core::marker::Sized` is not implemented
+        //~^ ERROR use of undeclared associated type `From::Dst`
     {
-        From::from(
-            //~^ error: the trait `core::marker::Sized` is not implemented
-            self
-        )
+        From::from(self)
     }
 }
 
index 5c1de6dfc55b46a0e2ed3055093d869ab8e08540..05485008e51fddabce97136adf959f142d0fb3cf 100644 (file)
@@ -18,7 +18,7 @@ mod B {
     use crate1::A::Foo;
     fn bar(f: Foo) {
         Foo::foo(&f);
-        //~^ ERROR: function `foo` is private
+        //~^ ERROR: method `foo` is private
     }
 }
 
index f0ae0eb59f532f768622a6f249f078161b039992..48cc27e228940b74f93d71640562f64224e88f59 100644 (file)
@@ -36,7 +36,7 @@ fn shave(&self, other: usize) {
     shave(4);
     //~^ ERROR: unresolved name `shave`. Did you mean to call `Groom::shave`?
     purr();
-    //~^ ERROR: unresolved name `purr`. Did you mean to call `self.purr`?
+    //~^ ERROR: unresolved name `purr`
   }
 }
 
@@ -45,13 +45,13 @@ fn static_method() {}
 
     fn purr_louder() {
         static_method();
-        //~^ ERROR: unresolved name `static_method`. Did you mean to call `cat::static_method`
+        //~^ ERROR: unresolved name `static_method`
         purr();
-        //~^ ERROR: unresolved name `purr`. Did you mean to call `self.purr`?
+        //~^ ERROR: unresolved name `purr`
         purr();
-        //~^ ERROR: unresolved name `purr`. Did you mean to call `self.purr`?
+        //~^ ERROR: unresolved name `purr`
         purr();
-        //~^ ERROR: unresolved name `purr`. Did you mean to call `self.purr`?
+        //~^ ERROR: unresolved name `purr`
     }
 }
 
@@ -65,7 +65,7 @@ fn meow() {
 
   fn purr(&self) {
     grow_older();
-    //~^ ERROR: unresolved name `grow_older`. Did you mean to call `cat::grow_older`
+    //~^ ERROR: unresolved name `grow_older`
     shave();
     //~^ ERROR: unresolved name `shave`
   }
@@ -79,7 +79,7 @@ pub fn grow_older(other:usize) {
     whiskers = 4;
     //~^ ERROR: unresolved name `whiskers`. Did you mean `self.whiskers`?
     purr_louder();
-    //~^ ERROR: unresolved name `purr_louder`. Did you mean to call `cat::purr_louder`
+    //~^ ERROR: unresolved name `purr_louder`
   }
 }
 
index 678618d721692a9db1d3885679bba38fbacc1939..ad5bc4e445c9839b7ebc41064ef684f460087340 100644 (file)
@@ -11,7 +11,9 @@
 fn main() {
     let foo = 100;
 
-    static y: isize = foo + 1; //~ ERROR: attempt to use a non-constant value in a constant
+    static y: isize = foo + 1;
+    //~^ ERROR attempt to use a non-constant value in a constant
+    //~| ERROR unresolved name `foo`
 
     println!("{}", y);
 }
index c49959c16a62180c7c1b7276173585687d22c694..f06aa45ac38fd1848c106847d37e1e5421e717af 100644 (file)
@@ -13,7 +13,9 @@ fn main() {
 
     #[derive(Debug)]
     enum Stuff {
-        Bar = foo //~ ERROR attempt to use a non-constant value in a constant
+        Bar = foo
+        //~^ ERROR attempt to use a non-constant value in a constant
+        //~| ERROR unresolved name `foo`
     }
 
     println!("{}", Stuff::Bar);
index 0577b1527234d03b48c62f1d69ccc56909c7c9d9..a09c8090de06de5716e718d3d33e6291f7edfaf9 100644 (file)
@@ -9,7 +9,9 @@
 // except according to those terms.
 
 fn f(x:isize) {
-    static child: isize = x + 1; //~ ERROR attempt to use a non-constant value in a constant
+    static child: isize = x + 1;
+    //~^ ERROR attempt to use a non-constant value in a constant
+    //~| ERROR unresolved name `x`
 }
 
 fn main() {}
index 9c31dc1e38ef8ff312193b105a73e9346e9d0153..9b7476244f0d26a19e0d91639fea3c306c20406f 100644 (file)
@@ -17,6 +17,7 @@ impl PTrait for P {
    fn getChildOption(&self) -> Option<Box<P>> {
        static childVal: Box<P> = self.child.get();
        //~^ ERROR attempt to use a non-constant value in a constant
+       //~| ERROR unresolved name `self`
        panic!();
    }
 }
index e4f7521c33303cc340faabfacff70c593b767580..2652fb5dfc2fd6dc453f73f1d3d9094847ccbe86 100644 (file)
@@ -30,7 +30,5 @@ fn to_string(&self) -> String {
 
 fn main() {
     let p = Point::new(0.0, 0.0);
-    //~^ ERROR unresolved name `Point::new`
-    //~^^ ERROR failed to resolve. Use of undeclared type or module `Point`
     println!("{}", p.to_string());
 }
index b4bc7ecdc5f89693cb35bb449882fdc9693bb247..ab18e0bcddcf08ef7005c27a814343b131404578 100644 (file)
@@ -17,7 +17,7 @@ fn bar() {
         Foo { baz: 0 }.bar();
     }
 
-    fn bar() { //~ ERROR duplicate definition of value `bar`
+    fn bar() { //~ ERROR duplicate method in trait impl
     }
 }
 
index 48fc393d0da8e1cabeddd386cff78b130c727158..4ac901776099d0b0e4164e4d6296645ccbbd57b0 100644 (file)
@@ -8,13 +8,11 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// ignore-tidy-linelength
-
 struct Foo {
     x: isize
 }
 
-impl Fo { //~ERROR inherent implementations are not allowed for types not defined in the current module
+impl Fo { //~ ERROR use of undeclared type name `Fo`
     fn foo() {}
 }
 
diff --git a/src/test/compile-fail/issue-7607-2.rs b/src/test/compile-fail/issue-7607-2.rs
deleted file mode 100644 (file)
index 9541899..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// ignore-tidy-linelength
-
-pub mod a {
-    pub struct Foo { a: usize }
-}
-
-pub mod b {
-    use a::Foo;
-    impl Foo { //~ERROR inherent implementations are only allowed on types defined in the current module
-        fn bar(&self) { }
-    }
-}
-
-pub fn main() { }
-
-
index 6c5bac5e0cb34bce3fbc4e38c6c300b23adc661c..2ef0a75f77b5a9fb25b4b1784d24c98d24075861 100644 (file)
@@ -10,7 +10,7 @@
 
 // ignore-tidy-linelength
 
-impl B { //~ERROR inherent implementations are not allowed for types not defined in the current module
+impl B { //~ ERROR use of undeclared type name `B`
 }
 
 fn main() {
diff --git a/src/test/compile-fail/lint-stability-fields.rs b/src/test/compile-fail/lint-stability-fields.rs
new file mode 100644 (file)
index 0000000..c43ff19
--- /dev/null
@@ -0,0 +1,346 @@
+// 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:lint_stability_fields.rs
+#![deny(deprecated)]
+#![allow(dead_code)]
+#![feature(staged_api)]
+#![staged_api]
+
+mod cross_crate {
+    extern crate lint_stability_fields;
+
+    use self::lint_stability_fields::*;
+
+    pub fn foo() {
+        let x = Stable {
+            inherit: 1,
+            override1: 2, //~ WARN use of unstable
+            override2: 3,
+            //~^ ERROR use of deprecated item
+            //~^^ WARN use of unstable
+        };
+
+        let _ = x.inherit;
+        let _ = x.override1; //~ WARN use of unstable
+        let _ = x.override2;
+        //~^ ERROR use of deprecated item
+        //~^^ WARN use of unstable
+
+        let Stable {
+            inherit: _,
+            override1: _, //~ WARN use of unstable
+            override2: _
+            //~^ ERROR use of deprecated item
+            //~^^ WARN use of unstable
+        } = x;
+        // all fine
+        let Stable { .. } = x;
+
+        let x = Stable2(1, 2, 3);
+
+        let _ = x.0;
+        let _ = x.1; //~ WARN use of unstable
+        let _ = x.2;
+        //~^ ERROR use of deprecated item
+        //~^^ WARN use of unstable
+
+        let Stable2(_,
+                   _, //~ WARN use of unstable
+                   _)
+            //~^ ERROR use of deprecated item
+            //~^^ WARN use of unstable
+            = x;
+        // all fine
+        let Stable2(..) = x;
+
+
+        let x = Unstable { //~ WARN use of unstable
+            inherit: 1, //~ WARN use of unstable
+            override1: 2,
+            override2: 3,
+            //~^ ERROR use of deprecated item
+            //~^^ WARN use of unstable
+        };
+
+        let _ = x.inherit; //~ WARN use of unstable
+        let _ = x.override1;
+        let _ = x.override2;
+        //~^ ERROR use of deprecated item
+        //~^^ WARN use of unstable
+
+        let Unstable { //~ WARN use of unstable
+            inherit: _, //~ WARN use of unstable
+            override1: _,
+            override2: _
+            //~^ ERROR use of deprecated item
+            //~^^ WARN use of unstable
+        } = x;
+
+        let Unstable  //~ WARN use of unstable
+            // the patterns are all fine:
+            { .. } = x;
+
+
+        let x = Unstable2(1, 2, 3); //~ WARN use of unstable
+
+        let _ = x.0; //~ WARN use of unstable
+        let _ = x.1;
+        let _ = x.2;
+        //~^ ERROR use of deprecated item
+        //~^^ WARN use of unstable
+
+        let Unstable2  //~ WARN use of unstable
+            (_, //~ WARN use of unstable
+             _,
+             _)
+            //~^ ERROR use of deprecated item
+            //~^^ WARN use of unstable
+            = x;
+        let Unstable2 //~ WARN use of unstable
+            // the patterns are all fine:
+            (..) = x;
+
+
+        let x = Deprecated {
+            //~^ ERROR use of deprecated item
+            //~^^ WARN use of unstable
+            inherit: 1,
+            //~^ ERROR use of deprecated item
+            //~^^ WARN use of unstable
+            override1: 2,
+            override2: 3, //~ WARN use of unstable
+        };
+
+        let _ = x.inherit;
+        //~^ ERROR use of deprecated item
+        //~^^ WARN use of unstable
+        let _ = x.override1;
+        let _ = x.override2; //~ WARN use of unstable
+
+        let Deprecated {
+            //~^ ERROR use of deprecated item
+            //~^^ WARN use of unstable
+            inherit: _,
+            //~^ ERROR use of deprecated item
+            //~^^ WARN use of unstable
+            override1: _,
+            override2: _ //~ WARN use of unstable
+        } = x;
+
+        let Deprecated
+            //~^ ERROR use of deprecated item
+            //~^^ WARN use of unstable
+            // the patterns are all fine:
+            { .. } = x;
+
+        let x = Deprecated2(1, 2, 3);
+        //~^ ERROR use of deprecated item
+        //~^^ WARN use of unstable
+
+        let _ = x.0;
+        //~^ ERROR use of deprecated item
+        //~^^ WARN use of unstable
+        let _ = x.1;
+        let _ = x.2; //~ WARN use of unstable
+
+        let Deprecated2
+        //~^ ERROR use of deprecated item
+        //~^^ WARN use of unstable
+            (_,
+             //~^ ERROR use of deprecated item
+             //~^^ WARN use of unstable
+             _,
+             _) //~ WARN use of unstable
+            = x;
+        let Deprecated2
+        //~^ ERROR use of deprecated item
+        //~^^ WARN use of unstable
+            // the patterns are all fine:
+            (..) = x;
+    }
+}
+
+mod this_crate {
+    #[stable(feature = "rust1", since = "1.0.0")]
+    struct Stable {
+        inherit: u8,
+        #[unstable(feature = "test_feature")]
+        override1: u8,
+        #[deprecated(since = "1.0.0")]
+        #[unstable(feature = "test_feature")]
+        override2: u8,
+    }
+
+    #[stable(feature = "rust1", since = "1.0.0")]
+    struct Stable2(u8,
+                   #[stable(feature = "rust1", since = "1.0.0")] u8,
+                   #[unstable(feature = "test_feature")] #[deprecated(since = "1.0.0")] u8);
+
+    #[unstable(feature = "test_feature")]
+    struct Unstable {
+        inherit: u8,
+        #[stable(feature = "rust1", since = "1.0.0")]
+        override1: u8,
+        #[deprecated(since = "1.0.0")]
+        #[unstable(feature = "test_feature")]
+        override2: u8,
+    }
+
+    #[unstable(feature = "test_feature")]
+    struct Unstable2(u8,
+                     #[stable(feature = "rust1", since = "1.0.0")] u8,
+                     #[unstable(feature = "test_feature")] #[deprecated(since = "1.0.0")] u8);
+
+    #[unstable(feature = "test_feature")]
+    #[deprecated(feature = "rust1", since = "1.0.0")]
+    struct Deprecated {
+        inherit: u8,
+        #[stable(feature = "rust1", since = "1.0.0")]
+        override1: u8,
+        #[unstable(feature = "test_feature")]
+        override2: u8,
+    }
+
+    #[unstable(feature = "test_feature")]
+    #[deprecated(feature = "rust1", since = "1.0.0")]
+    struct Deprecated2(u8,
+                       #[stable(feature = "rust1", since = "1.0.0")] u8,
+                       #[unstable(feature = "test_feature")] u8);
+
+    pub fn foo() {
+        let x = Stable {
+            inherit: 1,
+            override1: 2,
+            override2: 3,
+            //~^ ERROR use of deprecated item
+        };
+
+        let _ = x.inherit;
+        let _ = x.override1;
+        let _ = x.override2;
+        //~^ ERROR use of deprecated item
+
+        let Stable {
+            inherit: _,
+            override1: _,
+            override2: _
+            //~^ ERROR use of deprecated item
+        } = x;
+        // all fine
+        let Stable { .. } = x;
+
+        let x = Stable2(1, 2, 3);
+
+        let _ = x.0;
+        let _ = x.1;
+        let _ = x.2;
+        //~^ ERROR use of deprecated item
+
+        let Stable2(_,
+                   _,
+                   _)
+            //~^ ERROR use of deprecated item
+            = x;
+        // all fine
+        let Stable2(..) = x;
+
+
+        let x = Unstable {
+            inherit: 1,
+            override1: 2,
+            override2: 3,
+            //~^ ERROR use of deprecated item
+        };
+
+        let _ = x.inherit;
+        let _ = x.override1;
+        let _ = x.override2;
+        //~^ ERROR use of deprecated item
+
+        let Unstable {
+            inherit: _,
+            override1: _,
+            override2: _
+            //~^ ERROR use of deprecated item
+        } = x;
+
+        let Unstable
+            // the patterns are all fine:
+            { .. } = x;
+
+
+        let x = Unstable2(1, 2, 3);
+
+        let _ = x.0;
+        let _ = x.1;
+        let _ = x.2;
+        //~^ ERROR use of deprecated item
+
+        let Unstable2
+            (_,
+             _,
+             _)
+            //~^ ERROR use of deprecated item
+            = x;
+        let Unstable2
+            // the patterns are all fine:
+            (..) = x;
+
+
+        let x = Deprecated {
+            //~^ ERROR use of deprecated item
+            inherit: 1,
+            //~^ ERROR use of deprecated item
+            override1: 2,
+            override2: 3,
+        };
+
+        let _ = x.inherit;
+        //~^ ERROR use of deprecated item
+        let _ = x.override1;
+        let _ = x.override2;
+
+        let Deprecated {
+            //~^ ERROR use of deprecated item
+            inherit: _,
+            //~^ ERROR use of deprecated item
+            override1: _,
+            override2: _
+        } = x;
+
+        let Deprecated
+            //~^ ERROR use of deprecated item
+            // the patterns are all fine:
+            { .. } = x;
+
+        let x = Deprecated2(1, 2, 3);
+        //~^ ERROR use of deprecated item
+
+        let _ = x.0;
+        //~^ ERROR use of deprecated item
+        let _ = x.1;
+        let _ = x.2;
+
+        let Deprecated2
+        //~^ ERROR use of deprecated item
+            (_,
+             //~^ ERROR use of deprecated item
+             _,
+             _)
+            = x;
+        let Deprecated2
+        //~^ ERROR use of deprecated item
+            // the patterns are all fine:
+            (..) = x;
+    }
+}
+
+fn main() {}
index 88f2cbdea6d7bf81332f15efb3caf5e1dc4e6d47..12548c4539618d73173b3a4b6d50c37faacc079d 100644 (file)
@@ -29,45 +29,104 @@ mod cross_crate {
     use lint_stability::*;
 
     fn test() {
+        type Foo = MethodTester;
         let foo = MethodTester;
 
         deprecated(); //~ ERROR use of deprecated item
         foo.method_deprecated(); //~ ERROR use of deprecated item
+        Foo::method_deprecated(&foo); //~ ERROR use of deprecated item
+        <Foo>::method_deprecated(&foo); //~ ERROR use of deprecated item
         foo.trait_deprecated(); //~ ERROR use of deprecated item
+        Trait::trait_deprecated(&foo); //~ ERROR use of deprecated item
+        <Foo>::trait_deprecated(&foo); //~ ERROR use of deprecated item
+        <Foo as Trait>::trait_deprecated(&foo); //~ ERROR use of deprecated item
 
         deprecated_text(); //~ ERROR use of deprecated item: text
         foo.method_deprecated_text(); //~ ERROR use of deprecated item: text
+        Foo::method_deprecated_text(&foo); //~ ERROR use of deprecated item: text
+        <Foo>::method_deprecated_text(&foo); //~ ERROR use of deprecated item: text
         foo.trait_deprecated_text(); //~ ERROR use of deprecated item: text
+        Trait::trait_deprecated_text(&foo); //~ ERROR use of deprecated item: text
+        <Foo>::trait_deprecated_text(&foo); //~ ERROR use of deprecated item: text
+        <Foo as Trait>::trait_deprecated_text(&foo); //~ ERROR use of deprecated item: text
 
         deprecated_unstable(); //~ ERROR use of deprecated item
         //~^ WARNING use of unstable library feature
         foo.method_deprecated_unstable(); //~ ERROR use of deprecated item
         //~^ WARNING use of unstable library feature
+        Foo::method_deprecated_unstable(&foo); //~ ERROR use of deprecated item
+        //~^ WARNING use of unstable library feature
+        <Foo>::method_deprecated_unstable(&foo); //~ ERROR use of deprecated item
+        //~^ WARNING use of unstable library feature
         foo.trait_deprecated_unstable(); //~ ERROR use of deprecated item
         //~^ WARNING use of unstable library feature
+        Trait::trait_deprecated_unstable(&foo); //~ ERROR use of deprecated item
+        //~^ WARNING use of unstable library feature
+        <Foo>::trait_deprecated_unstable(&foo); //~ ERROR use of deprecated item
+        //~^ WARNING use of unstable library feature
+        <Foo as Trait>::trait_deprecated_unstable(&foo); //~ ERROR use of deprecated item
+        //~^ WARNING use of unstable library feature
 
         deprecated_unstable_text(); //~ ERROR use of deprecated item: text
         //~^ WARNING use of unstable library feature
         foo.method_deprecated_unstable_text(); //~ ERROR use of deprecated item: text
         //~^ WARNING use of unstable library feature
+        Foo::method_deprecated_unstable_text(&foo); //~ ERROR use of deprecated item: text
+        //~^ WARNING use of unstable library feature
+        <Foo>::method_deprecated_unstable_text(&foo); //~ ERROR use of deprecated item: text
+        //~^ WARNING use of unstable library feature
         foo.trait_deprecated_unstable_text(); //~ ERROR use of deprecated item: text
         //~^ WARNING use of unstable library feature
+        Trait::trait_deprecated_unstable_text(&foo); //~ ERROR use of deprecated item: text
+        //~^ WARNING use of unstable library feature
+        <Foo>::trait_deprecated_unstable_text(&foo); //~ ERROR use of deprecated item: text
+        //~^ WARNING use of unstable library feature
+        <Foo as Trait>::trait_deprecated_unstable_text(&foo); //~ ERROR use of deprecated item: text
+        //~^ WARNING use of unstable library feature
 
         unstable(); //~ WARNING use of unstable library feature
         foo.method_unstable(); //~ WARNING use of unstable library feature
+        Foo::method_unstable(&foo); //~ WARNING use of unstable library feature
+        <Foo>::method_unstable(&foo); //~ WARNING use of unstable library feature
         foo.trait_unstable(); //~ WARNING use of unstable library feature
+        Trait::trait_unstable(&foo); //~ WARNING use of unstable library feature
+        <Foo>::trait_unstable(&foo); //~ WARNING use of unstable library feature
+        <Foo as Trait>::trait_unstable(&foo); //~ WARNING use of unstable library feature
 
-        unstable_text(); //~ WARNING use of unstable library feature 'test_feature': text
-        foo.method_unstable_text(); //~ WARNING use of unstable library feature 'test_feature': text
-        foo.trait_unstable_text(); //~ WARNING use of unstable library feature 'test_feature': text
+        unstable_text();
+        //~^ WARNING use of unstable library feature 'test_feature': text
+        foo.method_unstable_text();
+        //~^ WARNING use of unstable library feature 'test_feature': text
+        Foo::method_unstable_text(&foo);
+        //~^ WARNING use of unstable library feature 'test_feature': text
+        <Foo>::method_unstable_text(&foo);
+        //~^ WARNING use of unstable library feature 'test_feature': text
+        foo.trait_unstable_text();
+        //~^ WARNING use of unstable library feature 'test_feature': text
+        Trait::trait_unstable_text(&foo);
+        //~^ WARNING use of unstable library feature 'test_feature': text
+        <Foo>::trait_unstable_text(&foo);
+        //~^ WARNING use of unstable library feature 'test_feature': text
+        <Foo as Trait>::trait_unstable_text(&foo);
+        //~^ WARNING use of unstable library feature 'test_feature': text
 
         stable();
         foo.method_stable();
+        Foo::method_stable(&foo);
+        <Foo>::method_stable(&foo);
         foo.trait_stable();
+        Trait::trait_stable(&foo);
+        <Foo>::trait_stable(&foo);
+        <Foo as Trait>::trait_stable(&foo);
 
         stable_text();
         foo.method_stable_text();
+        Foo::method_stable_text(&foo);
+        <Foo>::method_stable_text(&foo);
         foo.trait_stable_text();
+        Trait::trait_stable_text(&foo);
+        <Foo>::trait_stable_text(&foo);
+        <Foo as Trait>::trait_stable_text(&foo);
 
         let _ = DeprecatedStruct { i: 0 }; //~ ERROR use of deprecated item
         let _ = DeprecatedUnstableStruct { i: 0 }; //~ ERROR use of deprecated item
@@ -104,16 +163,47 @@ fn test() {
         macro_test_arg!(macro_test_arg!(deprecated_text())); //~ ERROR use of deprecated item: text
     }
 
-    fn test_method_param<F: Trait>(foo: F) {
+    fn test_method_param<Foo: Trait>(foo: Foo) {
         foo.trait_deprecated(); //~ ERROR use of deprecated item
+        Trait::trait_deprecated(&foo); //~ ERROR use of deprecated item
+        <Foo>::trait_deprecated(&foo); //~ ERROR use of deprecated item
+        <Foo as Trait>::trait_deprecated(&foo); //~ ERROR use of deprecated item
         foo.trait_deprecated_text(); //~ ERROR use of deprecated item: text
+        Trait::trait_deprecated_text(&foo); //~ ERROR use of deprecated item: text
+        <Foo>::trait_deprecated_text(&foo); //~ ERROR use of deprecated item: text
+        <Foo as Trait>::trait_deprecated_text(&foo); //~ ERROR use of deprecated item: text
         foo.trait_deprecated_unstable(); //~ ERROR use of deprecated item
         //~^ WARNING use of unstable library feature
+        Trait::trait_deprecated_unstable(&foo); //~ ERROR use of deprecated item
+        //~^ WARNING use of unstable library feature
+        <Foo>::trait_deprecated_unstable(&foo); //~ ERROR use of deprecated item
+        //~^ WARNING use of unstable library feature
+        <Foo as Trait>::trait_deprecated_unstable(&foo); //~ ERROR use of deprecated item
+        //~^ WARNING use of unstable library feature
         foo.trait_deprecated_unstable_text(); //~ ERROR use of deprecated item: text
         //~^ WARNING use of unstable library feature
+        Trait::trait_deprecated_unstable_text(&foo); //~ ERROR use of deprecated item: text
+        //~^ WARNING use of unstable library feature
+        <Foo>::trait_deprecated_unstable_text(&foo); //~ ERROR use of deprecated item: text
+        //~^ WARNING use of unstable library feature
+        <Foo as Trait>::trait_deprecated_unstable_text(&foo); //~ ERROR use of deprecated item: text
+        //~^ WARNING use of unstable library feature
         foo.trait_unstable(); //~ WARNING use of unstable library feature
-        foo.trait_unstable_text(); //~ WARNING use of unstable library feature 'test_feature': text
+        Trait::trait_unstable(&foo); //~ WARNING use of unstable library feature
+        <Foo>::trait_unstable(&foo); //~ WARNING use of unstable library feature
+        <Foo as Trait>::trait_unstable(&foo); //~ WARNING use of unstable library feature
+        foo.trait_unstable_text();
+        //~^ WARNING use of unstable library feature 'test_feature': text
+        Trait::trait_unstable_text(&foo);
+        //~^ WARNING use of unstable library feature 'test_feature': text
+        <Foo>::trait_unstable_text(&foo);
+        //~^ WARNING use of unstable library feature 'test_feature': text
+        <Foo as Trait>::trait_unstable_text(&foo);
+        //~^ WARNING use of unstable library feature 'test_feature': text
         foo.trait_stable();
+        Trait::trait_stable(&foo);
+        <Foo>::trait_stable(&foo);
+        <Foo as Trait>::trait_stable(&foo);
     }
 
     fn test_method_object(foo: &Trait) {
@@ -124,7 +214,8 @@ fn test_method_object(foo: &Trait) {
         foo.trait_deprecated_unstable_text(); //~ ERROR use of deprecated item: text
         //~^ WARNING use of unstable library feature
         foo.trait_unstable(); //~ WARNING use of unstable library feature
-        foo.trait_unstable_text(); //~ WARNING use of unstable library feature 'test_feature': text
+        foo.trait_unstable_text();
+        //~^ WARNING use of unstable library feature 'test_feature': text
         foo.trait_stable();
     }
 
@@ -226,11 +317,17 @@ impl Trait for MethodTester {}
 
     #[unstable(feature = "test_feature")]
     #[deprecated(since = "1.0.0")]
-    pub struct DeprecatedStruct { i: isize }
+    pub struct DeprecatedStruct {
+        #[stable(feature = "test_feature", since = "1.0.0")] i: isize
+    }
     #[unstable(feature = "test_feature")]
-    pub struct UnstableStruct { i: isize }
+    pub struct UnstableStruct {
+        #[stable(feature = "test_feature", since = "1.0.0")] i: isize
+    }
     #[stable(feature = "rust1", since = "1.0.0")]
-    pub struct StableStruct { i: isize }
+    pub struct StableStruct {
+        #[stable(feature = "test_feature", since = "1.0.0")] i: isize
+    }
 
     #[unstable(feature = "test_feature")]
     #[deprecated(since = "1.0.0")]
@@ -264,31 +361,62 @@ fn test() {
         // errors, because other stability attributes now have meaning
         // only *across* crates, not within a single crate.
 
+        type Foo = MethodTester;
         let foo = MethodTester;
 
         deprecated(); //~ ERROR use of deprecated item
         foo.method_deprecated(); //~ ERROR use of deprecated item
+        Foo::method_deprecated(&foo); //~ ERROR use of deprecated item
+        <Foo>::method_deprecated(&foo); //~ ERROR use of deprecated item
         foo.trait_deprecated(); //~ ERROR use of deprecated item
+        Trait::trait_deprecated(&foo); //~ ERROR use of deprecated item
+        <Foo>::trait_deprecated(&foo); //~ ERROR use of deprecated item
+        <Foo as Trait>::trait_deprecated(&foo); //~ ERROR use of deprecated item
 
         deprecated_text(); //~ ERROR use of deprecated item: text
         foo.method_deprecated_text(); //~ ERROR use of deprecated item: text
+        Foo::method_deprecated_text(&foo); //~ ERROR use of deprecated item: text
+        <Foo>::method_deprecated_text(&foo); //~ ERROR use of deprecated item: text
         foo.trait_deprecated_text(); //~ ERROR use of deprecated item: text
+        Trait::trait_deprecated_text(&foo); //~ ERROR use of deprecated item: text
+        <Foo>::trait_deprecated_text(&foo); //~ ERROR use of deprecated item: text
+        <Foo as Trait>::trait_deprecated_text(&foo); //~ ERROR use of deprecated item: text
 
         unstable();
         foo.method_unstable();
+        Foo::method_unstable(&foo);
+        <Foo>::method_unstable(&foo);
         foo.trait_unstable();
+        Trait::trait_unstable(&foo);
+        <Foo>::trait_unstable(&foo);
+        <Foo as Trait>::trait_unstable(&foo);
 
         unstable_text();
         foo.method_unstable_text();
+        Foo::method_unstable_text(&foo);
+        <Foo>::method_unstable_text(&foo);
         foo.trait_unstable_text();
+        Trait::trait_unstable_text(&foo);
+        <Foo>::trait_unstable_text(&foo);
+        <Foo as Trait>::trait_unstable_text(&foo);
 
         stable();
         foo.method_stable();
+        Foo::method_stable(&foo);
+        <Foo>::method_stable(&foo);
         foo.trait_stable();
+        Trait::trait_stable(&foo);
+        <Foo>::trait_stable(&foo);
+        <Foo as Trait>::trait_stable(&foo);
 
         stable_text();
         foo.method_stable_text();
+        Foo::method_stable_text(&foo);
+        <Foo>::method_stable_text(&foo);
         foo.trait_stable_text();
+        Trait::trait_stable_text(&foo);
+        <Foo>::trait_stable_text(&foo);
+        <Foo as Trait>::trait_stable_text(&foo);
 
         let _ = DeprecatedStruct { i: 0 }; //~ ERROR use of deprecated item
         let _ = UnstableStruct { i: 0 };
@@ -307,12 +435,27 @@ fn test() {
         let _ = StableTupleStruct (1);
     }
 
-    fn test_method_param<F: Trait>(foo: F) {
+    fn test_method_param<Foo: Trait>(foo: Foo) {
         foo.trait_deprecated(); //~ ERROR use of deprecated item
+        Trait::trait_deprecated(&foo); //~ ERROR use of deprecated item
+        <Foo>::trait_deprecated(&foo); //~ ERROR use of deprecated item
+        <Foo as Trait>::trait_deprecated(&foo); //~ ERROR use of deprecated item
         foo.trait_deprecated_text(); //~ ERROR use of deprecated item: text
+        Trait::trait_deprecated_text(&foo); //~ ERROR use of deprecated item: text
+        <Foo>::trait_deprecated_text(&foo); //~ ERROR use of deprecated item: text
+        <Foo as Trait>::trait_deprecated_text(&foo); //~ ERROR use of deprecated item: text
         foo.trait_unstable();
+        Trait::trait_unstable(&foo);
+        <Foo>::trait_unstable(&foo);
+        <Foo as Trait>::trait_unstable(&foo);
         foo.trait_unstable_text();
+        Trait::trait_unstable_text(&foo);
+        <Foo>::trait_unstable_text(&foo);
+        <Foo as Trait>::trait_unstable_text(&foo);
         foo.trait_stable();
+        Trait::trait_stable(&foo);
+        <Foo>::trait_stable(&foo);
+        <Foo as Trait>::trait_stable(&foo);
     }
 
     fn test_method_object(foo: &Trait) {
index 7b17d8877572f14b6ee5b34474c7cb65c1f5164d..8440cf3a88e10adda62bc34751beb3a3d62e5548 100644 (file)
@@ -15,6 +15,8 @@
 use std::marker::PhantomFn;
 
 struct Bar;
+struct Bar2;
+struct Bar3;
 
 #[allow(unsafe_code)]
 mod allowed_unsafe {
@@ -46,6 +48,53 @@ unsafe fn baz(&self) {} //~ ERROR: implementation of an `unsafe` method
     unsafe fn provided_override(&self) {} //~ ERROR: implementation of an `unsafe` method
 }
 
+
+#[allow(unsafe_code)]
+trait A {
+    unsafe fn allowed_unsafe(&self);
+    unsafe fn allowed_unsafe_provided(&self) {}
+}
+
+#[allow(unsafe_code)]
+impl Baz for Bar2 {
+    unsafe fn baz(&self) {}
+    unsafe fn provided_override(&self) {}
+}
+
+impl Baz for Bar3 {
+    #[allow(unsafe_code)]
+    unsafe fn baz(&self) {}
+    unsafe fn provided_override(&self) {} //~ ERROR: implementation of an `unsafe` method
+}
+
+#[allow(unsafe_code)]
+unsafe trait B {
+    fn dummy(&self) {}
+}
+
+trait C {
+    #[allow(unsafe_code)]
+    unsafe fn baz(&self);
+    unsafe fn provided(&self) {} //~ ERROR: implementation of an `unsafe` method
+}
+
+impl C for Bar {
+    #[allow(unsafe_code)]
+    unsafe fn baz(&self) {}
+    unsafe fn provided(&self) {} //~ ERROR: implementation of an `unsafe` method
+}
+
+impl C for Bar2 {
+    unsafe fn baz(&self) {} //~ ERROR: implementation of an `unsafe` method
+}
+
+trait D {
+    #[allow(unsafe_code)]
+    unsafe fn unsafe_provided(&self) {}
+}
+
+impl D for Bar {}
+
 fn main() {
     unsafe {} //~ ERROR: usage of an `unsafe` block
 
index f4740492651ae03e4cd15a1412f8d8a8887bfccd..c9ef2df8e1326f01f26bb275f40bde1ce2f4d29d 100644 (file)
@@ -29,7 +29,7 @@ impl S {
 
     // Cause an error. It shouldn't have any macro backtrace frames.
     fn bar(&self) { }
-    fn bar(&self) { } //~ ERROR duplicate definition
+    fn bar(&self) { } //~ ERROR duplicate method
 }
 
 fn main() { }
index 2fb097f111db47f98727566112fc8e35047c49f0..526750257d2785c81f52b11599084aebf589cd16 100644 (file)
 mod foo {
     mod baz {
         struct Test;
-        impl Add for Test {} //~ ERROR: attempt to implement a nonexistent trait
-        impl Clone for Test {} //~ ERROR: attempt to implement a nonexistent trait
-        impl Iterator for Test {} //~ ERROR: attempt to implement a nonexistent trait
-        impl ToString for Test {} //~ ERROR: attempt to implement a nonexistent trait
-        impl Writer for Test {} //~ ERROR: attempt to implement a nonexistent trait
+        impl Add for Test {} //~ ERROR: use of undeclared trait
+        impl Clone for Test {} //~ ERROR: use of undeclared trait
+        impl Iterator for Test {} //~ ERROR: use of undeclared trait
+        impl ToString for Test {} //~ ERROR: use of undeclared trait
+        impl Writer for Test {} //~ ERROR: use of undeclared trait
 
         fn foo() {
             drop(2) //~ ERROR: unresolved name
@@ -30,11 +30,11 @@ fn foo() {
     }
 
     struct Test;
-    impl Add for Test {} //~ ERROR: attempt to implement a nonexistent trait
-    impl Clone for Test {} //~ ERROR: attempt to implement a nonexistent trait
-    impl Iterator for Test {} //~ ERROR: attempt to implement a nonexistent trait
-    impl ToString for Test {} //~ ERROR: attempt to implement a nonexistent trait
-    impl Writer for Test {} //~ ERROR: attempt to implement a nonexistent trait
+    impl Add for Test {} //~ ERROR: use of undeclared trait
+    impl Clone for Test {} //~ ERROR: use of undeclared trait
+    impl Iterator for Test {} //~ ERROR: use of undeclared trait
+    impl ToString for Test {} //~ ERROR: use of undeclared trait
+    impl Writer for Test {} //~ ERROR: use of undeclared trait
 
     fn foo() {
         drop(2) //~ ERROR: unresolved name
@@ -45,11 +45,11 @@ fn qux() {
     #[no_implicit_prelude]
     mod qux_inner {
         struct Test;
-        impl Add for Test {} //~ ERROR: attempt to implement a nonexistent trait
-        impl Clone for Test {} //~ ERROR: attempt to implement a nonexistent trait
-        impl Iterator for Test {} //~ ERROR: attempt to implement a nonexistent trait
-        impl ToString for Test {} //~ ERROR: attempt to implement a nonexistent trait
-        impl Writer for Test {} //~ ERROR: attempt to implement a nonexistent trait
+        impl Add for Test {} //~ ERROR: use of undeclared trait
+        impl Clone for Test {} //~ ERROR: use of undeclared trait
+        impl Iterator for Test {} //~ ERROR: use of undeclared trait
+        impl ToString for Test {} //~ ERROR: use of undeclared trait
+        impl Writer for Test {} //~ ERROR: use of undeclared trait
 
         fn foo() {
             drop(2) //~ ERROR: unresolved name
index c0f7bea25b57ad88fddc5f218e6c75bd06fa1cdb..c4bcd33b93bd0beb67f68e1bf121553ec12432c6 100644 (file)
 // fail with the same error message).
 
 struct Test;
-impl Add for Test {} //~ ERROR: attempt to implement a nonexistent trait
-impl Clone for Test {} //~ ERROR: attempt to implement a nonexistent trait
-impl Iterator for Test {} //~ ERROR: attempt to implement a nonexistent trait
-impl ToString for Test {} //~ ERROR: attempt to implement a nonexistent trait
-impl Writer for Test {} //~ ERROR: attempt to implement a nonexistent trait
+impl Add for Test {} //~ ERROR: use of undeclared trait
+impl Clone for Test {} //~ ERROR: use of undeclared trait
+impl Iterator for Test {} //~ ERROR: use of undeclared trait
+impl ToString for Test {} //~ ERROR: use of undeclared trait
+impl Writer for Test {} //~ ERROR: use of undeclared trait
 
 fn main() {
     drop(2) //~ ERROR: unresolved name
index 0d0dc0a05d12ad1f006745501e5b043deb476d8d..3983a84f6ad1795a8d0ffac46710870b32d3d3cd 100644 (file)
 
 
 trait NewTrait : SomeNonExistentTrait {}
-//~^ ERROR attempt to derive a nonexistent trait `SomeNonExistentTrait`
+//~^ ERROR use of undeclared trait name `SomeNonExistentTrait`
 
 impl SomeNonExistentTrait for isize {}
-//~^ ERROR attempt to implement a nonexistent trait `SomeNonExistentTrait`
+//~^ ERROR use of undeclared trait name `SomeNonExistentTrait`
 
 fn f<T:SomeNonExistentTrait>() {}
-//~^ ERROR attempt to bound type parameter with a nonexistent trait `SomeNonExistentTrait`
+//~^ ERROR use of undeclared trait name `SomeNonExistentTrait`
 
diff --git a/src/test/compile-fail/trait-impl-2.rs b/src/test/compile-fail/trait-impl-2.rs
deleted file mode 100644 (file)
index 303e3d9..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-// Test calling methods on an impl for a bare trait. This test checks trait impls
-// must be in the same module as the trait.
-
-mod Foo {
-    trait T {}
-}
-
-mod Bar {
-    impl<'a> ::Foo::T+'a { //~ERROR: inherent implementations may only be implemented in the same
-        fn foo(&self) {}
-    }
-}
-
-fn main() {}
index 28d20483c7e7bcc498d4580c91eb1542e4374d4e..969b6398fdb10d787ed9ef456c64273afc92ade3 100644 (file)
@@ -14,7 +14,7 @@ mod a {
 trait A {
 }
 
-impl A for a { //~ERROR found module name used as a type
+impl A for a { //~ ERROR use of undeclared type name `a`
 }
 
 fn main() {
index e621d77a65c8d37a11700abea70b0c91b9a600a1..3aec23a55b8118e9f4766c28ed7c5d2c9e02e5d5 100644 (file)
@@ -8,9 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// ignore-tidy-linelength
-
-impl<T> Option<T> { //~ERROR inherent implementations are not allowed for types not defined in the current module
+impl<T> Option<T> {
+//~^ ERROR cannot associate methods with a type outside the crate the type is defined in
     pub fn foo(&self) { }
 }
 
index f4e18265fd9901b528653a777f77ea31f6a55226..b3fe178dc455e83b0d8c40f7092b57cbee1090fd 100644 (file)
@@ -12,5 +12,5 @@
 
 fn main() {
     <String as IntoCow>::into_cow("foo".to_string());
-    //~^ ERROR wrong number of type arguments: expected 1, found 0
+    //~^ ERROR too few type parameters provided: expected 1 parameter(s)
 }
index 12f62d805e15a8235d47b5df91fbf50768fadd11..f28bf7acadd371240b0c3b3c1b77fa885ed95554 100644 (file)
@@ -10,7 +10,7 @@
 
 #![feature(unboxed_closures)]
 
-fn f<F:Nonexist(isize) -> isize>(x: F) {} //~ ERROR nonexistent trait `Nonexist`
+fn f<F:Nonexist(isize) -> isize>(x: F) {} //~ ERROR undeclared trait name `Nonexist`
 
 type Typedef = isize;
 
diff --git a/src/test/compile-fail/unsafe_no_drop_flag-gate.rs b/src/test/compile-fail/unsafe_no_drop_flag-gate.rs
new file mode 100644 (file)
index 0000000..542698f
--- /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.
+
+pub struct T;
+
+#[unsafe_no_drop_flag]
+//~^ ERROR unsafe_no_drop_flag has unstable semantics and may be removed
+pub struct S {
+    pub x: T,
+}
+
+impl Drop for S {
+    fn drop(&mut self) {}
+}
+
+pub fn main() {}
diff --git a/src/test/compile-fail/unused-macro-with-bad-frag-spec.rs b/src/test/compile-fail/unused-macro-with-bad-frag-spec.rs
new file mode 100644 (file)
index 0000000..b868b79
--- /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.
+
+// Issue #21370
+
+macro_rules! test {
+    ($wrong:t_ty) => () //~ ERROR invalid fragment specifier `t_ty`
+}
+
+fn main() { }
diff --git a/src/test/compile-fail/unused-macro-with-follow-violation.rs b/src/test/compile-fail/unused-macro-with-follow-violation.rs
new file mode 100644 (file)
index 0000000..e9d09bb
--- /dev/null
@@ -0,0 +1,15 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+macro_rules! test {
+    ($e:expr +) => () //~ ERROR not allowed for `expr` fragments
+}
+
+fn main() { }
index 2a97155dd2efb878eebba9b619663ceaf824553c..49d8622976bb2dfd43159d1ee1ce01c9d764591b 100644 (file)
@@ -11,7 +11,7 @@
 use Trait::foo;
 //~^ ERROR `foo` is not directly importable
 use Foo::new;
-//~^ ERROR `new` is not directly importable
+//~^ ERROR unresolved import `Foo::new`. Not a module `Foo`
 
 pub trait Trait {
     fn foo();
index c96210896fd652c94296e47b38ff632c5db31271..cff4d44910b3146d312c11a0d41958d79c3a22c8 100644 (file)
@@ -10,6 +10,7 @@
 
 extern crate rustc;
 extern crate rustc_driver;
+extern crate rustc_lint;
 extern crate syntax;
 
 use rustc::session::{build_session, Session};
@@ -46,6 +47,7 @@ fn basic_sess(sysroot: Path) -> Session {
 
     let descriptions = Registry::new(&rustc::diagnostics::DIAGNOSTICS);
     let sess = build_session(opts, None, descriptions);
+    rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess));
     sess
 }
 
diff --git a/src/test/run-make/rustdoc-extern-default-method/Makefile b/src/test/run-make/rustdoc-extern-default-method/Makefile
new file mode 100644 (file)
index 0000000..ffc4a08
--- /dev/null
@@ -0,0 +1,6 @@
+-include ../tools.mk
+
+all: lib.rs ext.rs
+       $(HOST_RPATH_ENV) $(RUSTC) ext.rs
+       $(HOST_RPATH_ENV) $(RUSTDOC) -L $(TMPDIR) -w html -o $(TMPDIR)/doc lib.rs
+       $(HTMLDOCCK) $(TMPDIR)/doc lib.rs
diff --git a/src/test/run-make/rustdoc-extern-default-method/ext.rs b/src/test/run-make/rustdoc-extern-default-method/ext.rs
new file mode 100644 (file)
index 0000000..8615627
--- /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.
+
+#![crate_type="lib"]
+
+pub trait Trait {
+    fn provided(&self) {}
+}
+
+pub struct Struct;
+
+impl Trait for Struct {
+    fn provided(&self) {}
+}
diff --git a/src/test/run-make/rustdoc-extern-default-method/lib.rs b/src/test/run-make/rustdoc-extern-default-method/lib.rs
new file mode 100644 (file)
index 0000000..df92764
--- /dev/null
@@ -0,0 +1,14 @@
+// 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.
+
+extern crate ext;
+
+// @count lib/struct.Struct.html '//*[@id="method.provided"]' 1
+pub use ext::Struct;
diff --git a/src/test/run-pass/associated-types-project-from-type-param-via-bound-in-where-clause.rs b/src/test/run-pass/associated-types-project-from-type-param-via-bound-in-where-clause.rs
new file mode 100644 (file)
index 0000000..2243e00
--- /dev/null
@@ -0,0 +1,107 @@
+// 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.
+
+// Various uses of `T::Item` syntax where the bound that supplies
+// `Item` originates in a where-clause, not the declaration of
+// `T`. Issue #20300.
+
+use std::marker::{MarkerTrait, PhantomData};
+use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT};
+use std::sync::atomic::Ordering::SeqCst;
+
+static COUNTER: AtomicUsize = ATOMIC_USIZE_INIT;
+
+// Preamble.
+trait Trait : MarkerTrait { type Item; }
+struct Struct;
+impl Trait for Struct {
+    type Item = u32;
+}
+
+// Where-clause attached on the method which declares `T`.
+struct A;
+impl A {
+    fn foo<T>(_x: T::Item) where T: Trait {
+        COUNTER.fetch_add(1, SeqCst);
+    }
+}
+
+// Where-clause attached on the method to a parameter from the struct.
+struct B<T>(PhantomData<T>);
+impl<T> B<T> {
+    fn foo(_x: T::Item) where T: Trait {
+        COUNTER.fetch_add(10, SeqCst);
+    }
+}
+
+// Where-clause attached to free fn.
+fn c<T>(_: T::Item) where T : Trait {
+    COUNTER.fetch_add(100, SeqCst);
+}
+
+// Where-clause attached to defaulted and non-defaulted trait method.
+trait AnotherTrait {
+    fn method<T>(&self, _: T::Item) where T: Trait;
+    fn default_method<T>(&self, _: T::Item) where T: Trait {
+        COUNTER.fetch_add(1000, SeqCst);
+    }
+}
+struct D;
+impl AnotherTrait for D {
+    fn method<T>(&self, _: T::Item) where T: Trait {
+        COUNTER.fetch_add(10000, SeqCst);
+    }
+}
+
+// Where-clause attached to trait and impl containing the method.
+trait YetAnotherTrait<T>
+    where T : Trait
+{
+    fn method(&self, _: T::Item);
+    fn default_method(&self, _: T::Item) {
+        COUNTER.fetch_add(100000, SeqCst);
+    }
+}
+struct E<T>(PhantomData<T>);
+impl<T> YetAnotherTrait<T> for E<T>
+    where T : Trait
+{
+    fn method(&self, _: T::Item) {
+        COUNTER.fetch_add(1000000, SeqCst);
+    }
+}
+
+// Where-clause attached to inherent impl containing the method.
+struct F<T>(PhantomData<T>);
+impl<T> F<T> where T : Trait {
+    fn method(&self, _: T::Item) {
+        COUNTER.fetch_add(10000000, SeqCst);
+    }
+}
+
+// Where-clause attached to struct.
+#[allow(dead_code)]
+struct G<T> where T : Trait {
+    data: T::Item,
+    phantom: PhantomData<T>,
+}
+
+fn main() {
+    A::foo::<Struct>(22);
+    B::<Struct>::foo(22);
+    c::<Struct>(22);
+    D.method::<Struct>(22);
+    D.default_method::<Struct>(22);
+    E(PhantomData::<Struct>).method(22);
+    E(PhantomData::<Struct>).default_method(22);
+    F(PhantomData::<Struct>).method(22);
+    G::<Struct> { data: 22, phantom: PhantomData };
+    assert_eq!(COUNTER.load(SeqCst), 11111111);
+}
index 652f21c2ae3f829aeaff85b54ab1871492d9656c..d2e9bc2efe7279c10a0a00d7c25b6b1522aea5d1 100644 (file)
@@ -23,5 +23,5 @@ pub fn main() {
     let mut v = vec!(1);
     v.push_val(2);
     v.push_val(3);
-    assert_eq!(v, vec!(1, 2, 3));
+    assert_eq!(v, [1, 2, 3]);
 }
index f87f2e07c9de0f0ee2507023a37286cb905f3bee..2473b4b674e5784a1fcf94cd65253014952ac748 100644 (file)
@@ -22,5 +22,5 @@ fn bar(v: &mut [uint]) {
 pub fn main() {
     let mut the_vec = vec!(1, 2, 3, 100);
     bar(&mut the_vec);
-    assert_eq!(the_vec, vec!(100, 3, 2, 1));
+    assert_eq!(the_vec, [100, 3, 2, 1]);
 }
index 4f97e6a20815d0014f06a8581abac69b50d8f69e..ea09bb3904de6b950f027f95b9094bd885ed66ef 100644 (file)
@@ -18,5 +18,5 @@ fn bar(v: &mut [uint]) {
 pub fn main() {
     let mut the_vec = vec!(1, 2, 3, 100);
     bar(&mut the_vec);
-    assert_eq!(the_vec, vec!(100, 3, 2, 1));
+    assert_eq!(the_vec, [100, 3, 2, 1]);
 }
diff --git a/src/test/run-pass/const-polymorphic-paths.rs b/src/test/run-pass/const-polymorphic-paths.rs
deleted file mode 100644 (file)
index dce1203..0000000
+++ /dev/null
@@ -1,107 +0,0 @@
-// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-#![feature(macro_rules)]
-
-use std::borrow::{Cow, IntoCow};
-use std::collections::BitVec;
-use std::default::Default;
-use std::iter::FromIterator;
-use std::ops::Add;
-use std::option::IntoIter as OptionIter;
-use std::rand::Rand;
-use std::rand::XorShiftRng as DummyRng;
-// FIXME the glob std::prelude::*; import of Vec is missing non-static inherent methods.
-use std::vec::Vec;
-
-#[derive(PartialEq, Eq)]
-struct Newt<T>(T);
-
-fn id<T>(x: T) -> T { x }
-fn eq<T: Eq>(a: T, b: T) -> bool { a == b }
-fn u8_as_i8(x: u8) -> i8 { x as i8 }
-fn odd(x: uint) -> bool { x % 2 == 1 }
-fn dummy_rng() -> DummyRng { DummyRng::new_unseeded() }
-
-trait Size: Sized {
-    fn size() -> uint { std::mem::size_of::<Self>() }
-}
-impl<T> Size for T {}
-
-macro_rules! tests {
-    ($($expr:expr, $ty:ty, ($($test:expr),*);)+) => (pub fn main() {$({
-        const C: $ty = $expr;
-        static S: $ty = $expr;
-        assert!(eq(C($($test),*), $expr($($test),*)));
-        assert!(eq(S($($test),*), $expr($($test),*)));
-        assert!(eq(C($($test),*), S($($test),*)));
-    })+})
-}
-
-tests! {
-    // Free function.
-    id, fn(int) -> int, (5);
-    id::<int>, fn(int) -> int, (5);
-
-    // Enum variant constructor.
-    Some, fn(int) -> Option<int>, (5);
-    Some::<int>, fn(int) -> Option<int>, (5);
-
-    // Tuple struct constructor.
-    Newt, fn(int) -> Newt<int>, (5);
-    Newt::<int>, fn(int) -> Newt<int>, (5);
-
-    // Inherent static methods.
-    Vec::new, fn() -> Vec<()>, ();
-    Vec::<()>::new, fn() -> Vec<()>, ();
-    Vec::with_capacity, fn(uint) -> Vec<()>, (5);
-    Vec::<()>::with_capacity, fn(uint) -> Vec<()>, (5);
-    BitVec::from_fn, fn(uint, fn(uint) -> bool) -> BitVec, (5, odd);
-    BitVec::from_fn::<fn(uint) -> bool>, fn(uint, fn(uint) -> bool) -> BitVec, (5, odd);
-
-    // Inherent non-static method.
-    Vec::map_in_place, fn(Vec<u8>, fn(u8) -> i8) -> Vec<i8>, (vec![b'f', b'o', b'o'], u8_as_i8);
-    Vec::map_in_place::<i8, fn(u8) -> i8>, fn(Vec<u8>, fn(u8) -> i8) -> Vec<i8>,
-        (vec![b'f', b'o', b'o'], u8_as_i8);
-    // FIXME these break with "type parameter might not appear here pointing at `<u8>`.
-    // Vec::<u8>::map_in_place: fn(Vec<u8>, fn(u8) -> i8) -> Vec<i8>
-    //    , (vec![b'f', b'o', b'o'], u8_as_i8);
-    // Vec::<u8>::map_in_place::<i8, fn(u8) -> i8>: fn(Vec<u8>, fn(u8) -> i8) -> Vec<i8>
-    //    , (vec![b'f', b'o', b'o'], u8_as_i8);
-
-    // Trait static methods.
-    <bool as Size>::size, fn() -> uint, ();
-    Default::default, fn() -> int, ();
-    <int as Default>::default, fn() -> int, ();
-    Rand::rand, fn(&mut DummyRng) -> int, (&mut dummy_rng());
-    <int as Rand>::rand, fn(&mut DummyRng) -> int, (&mut dummy_rng());
-    Rand::rand::<DummyRng>, fn(&mut DummyRng) -> int, (&mut dummy_rng());
-    <int as Rand>::rand::<DummyRng>, fn(&mut DummyRng) -> int, (&mut dummy_rng());
-
-    // Trait non-static methods.
-    Clone::clone, fn(&int) -> int, (&5);
-    <int as Clone>::clone, fn(&int) -> int, (&5);
-    FromIterator::from_iter, fn(OptionIter<int>) -> Vec<int>, (Some(5).into_iter());
-    <Vec<_> as FromIterator<_>>::from_iter, fn(OptionIter<int>) -> Vec<int>,
-        (Some(5).into_iter());
-    <Vec<int> as FromIterator<_>>::from_iter, fn(OptionIter<int>) -> Vec<int>,
-        (Some(5).into_iter());
-    FromIterator::from_iter::<OptionIter<int>>, fn(OptionIter<int>) -> Vec<int>,
-        (Some(5).into_iter());
-    <Vec<int> as FromIterator<_>>::from_iter::<OptionIter<int>>, fn(OptionIter<int>) -> Vec<int>,
-        (Some(5).into_iter());
-    Add::add, fn(i32, i32) -> i32, (5, 6);
-    <i32 as Add<_>>::add, fn(i32, i32) -> i32, (5, 6);
-    <i32 as Add<i32>>::add, fn(i32, i32) -> i32, (5, 6);
-    <String as IntoCow<_>>::into_cow, fn(String) -> Cow<'static, str>,
-        ("foo".to_string());
-    <String as IntoCow<'static, _>>::into_cow, fn(String) -> Cow<'static, str>,
-        ("foo".to_string());
-}
diff --git a/src/test/run-pass/cycle-generic-bound.rs b/src/test/run-pass/cycle-generic-bound.rs
new file mode 100644 (file)
index 0000000..2388a56
--- /dev/null
@@ -0,0 +1,18 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Regression test for #15477. This test just needs to compile.
+
+use std::marker::PhantomFn;
+
+trait Chromosome<X: Chromosome<i32>> : PhantomFn<(Self,X)> {
+}
+
+fn main() { }
diff --git a/src/test/run-pass/cycle-trait-type-trait.rs b/src/test/run-pass/cycle-trait-type-trait.rs
new file mode 100644 (file)
index 0000000..6e16e68
--- /dev/null
@@ -0,0 +1,23 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Test a case where a supertrait references a type that references
+// the original trait. This poses no problem at the moment.
+
+trait Chromosome: Get<Struct<i32>> {
+}
+
+trait Get<A> {
+    fn get(&self) -> A;
+}
+
+struct Struct<C:Chromosome> { c: C }
+
+fn main() { }
index eb3cb30594ea808880b998a5c1513c054f038cb8..6b365c348f782b52f26c1d6e1e57500a312ee3a5 100644 (file)
@@ -9,18 +9,18 @@
 // except according to those terms.
 
 use std::num::FromPrimitive;
-use std::int;
+use std::isize;
 
 #[derive(PartialEq, FromPrimitive, Debug)]
 enum A {
-    Foo = int::MAX,
+    Foo = isize::MAX,
     Bar = 1,
     Baz = 3,
     Qux,
 }
 
 pub fn main() {
-    let x: Option<A> = FromPrimitive::from_int(int::MAX);
+    let x: Option<A> = FromPrimitive::from_int(isize::MAX);
     assert_eq!(x, Some(A::Foo));
 
     let x: Option<A> = FromPrimitive::from_int(1);
index 0e1ab73c02d088ff73e275d7dd42998778e952d7..5d68a25a14ada73433012e8a3a13ccdf1c9c04f0 100644 (file)
@@ -9,13 +9,14 @@
 // except according to those terms.
 
 use std::env::*;
+use std::path::PathBuf;
 
 #[cfg(unix)]
 fn main() {
     let oldhome = var("HOME");
 
     set_var("HOME", "/home/MountainView");
-    assert!(home_dir() == Some(Path::new("/home/MountainView")));
+    assert!(home_dir() == Some(PathBuf::new("/home/MountainView")));
 
     remove_var("HOME");
     if cfg!(target_os = "android") {
@@ -36,14 +37,14 @@ fn main() {
     assert!(home_dir().is_some());
 
     set_var("HOME", "/home/MountainView");
-    assert!(home_dir() == Some(Path::new("/home/MountainView")));
+    assert!(home_dir() == Some(PathBuf::new("/home/MountainView")));
 
     remove_var("HOME");
 
     set_var("USERPROFILE", "/home/MountainView");
-    assert!(home_dir() == Some(Path::new("/home/MountainView")));
+    assert!(home_dir() == Some(PathBuf::new("/home/MountainView")));
 
     set_var("HOME", "/home/MountainView");
     set_var("USERPROFILE", "/home/PaloAlto");
-    assert!(home_dir() == Some(Path::new("/home/MountainView")));
+    assert!(home_dir() == Some(PathBuf::new("/home/MountainView")));
 }
index 7f84efcdd5de8862cd5d26eb93381ce1819838d9..010f54dd55934ea53c425066dd4bb67dde200c85 100644 (file)
@@ -24,5 +24,5 @@ fn map_<U, F>(x: &Vec<T> , mut f: F) -> Vec<U> where F: FnMut(&T) -> U {
 }
 
 pub fn main() {
-    assert_eq!(vec_utils::map_(&vec!(1,2,3), |&x| x+1), vec!(2,3,4));
+    assert_eq!(vec_utils::map_(&vec!(1,2,3), |&x| x+1), [2,3,4]);
 }
diff --git a/src/test/run-pass/impl-inherent-non-conflict.rs b/src/test/run-pass/impl-inherent-non-conflict.rs
new file mode 100644 (file)
index 0000000..663ed24
--- /dev/null
@@ -0,0 +1,31 @@
+// 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.
+
+// Ensure that an user-defined type admits multiple inherent methods
+// with the same name, which can be called on values that have a
+// precise enough type to allow distinguishing between the methods.
+
+struct Foo<T>(T);
+
+impl Foo<usize> {
+    fn bar(&self) -> i32 { self.0 as i32 }
+}
+
+impl Foo<isize> {
+    fn bar(&self) -> i32 { -(self.0 as i32) }
+}
+
+fn main() {
+    let foo_u = Foo::<usize>(5);
+    assert_eq!(foo_u.bar(), 5);
+
+    let foo_i = Foo::<isize>(3);
+    assert_eq!(foo_i.bar(), -3);
+}
diff --git a/src/test/run-pass/impl-inherent-prefer-over-trait.rs b/src/test/run-pass/impl-inherent-prefer-over-trait.rs
new file mode 100644 (file)
index 0000000..3031228
--- /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.
+
+struct Foo;
+
+trait Trait {
+    fn bar(&self);
+}
+
+// Inherent impls should be preferred over trait ones.
+impl Foo {
+    fn bar(&self) {}
+}
+
+impl Trait {
+    fn baz(_: &Foo) {}
+}
+
+impl Trait for Foo {
+    fn bar(&self) { panic!("wrong method called!") }
+}
+
+fn main() {
+    Foo.bar();
+    Foo::bar(&Foo);
+    <Foo>::bar(&Foo);
+
+    // Should work even if Trait::baz doesn't exist.
+    // N.B: `<Trait>::bar` would be ambiguous.
+    <Trait>::baz(&Foo);
+}
diff --git a/src/test/run-pass/impl-not-adjacent-to-type.rs b/src/test/run-pass/impl-not-adjacent-to-type.rs
new file mode 100644 (file)
index 0000000..c1dc68b
--- /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.
+
+mod foo {
+    pub struct Point {
+        pub x: i32,
+        pub y: i32,
+    }
+}
+
+impl foo::Point {
+    fn x(&self) -> i32 { self.x }
+}
+
+fn main() {
+    assert_eq!((foo::Point { x: 1, y: 3}).x(), 1);
+}
diff --git a/src/test/run-pass/issue-12729.rs b/src/test/run-pass/issue-12729.rs
new file mode 100644 (file)
index 0000000..09c0c86
--- /dev/null
@@ -0,0 +1,21 @@
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+pub struct Foo;
+
+mod bar {
+    use Foo;
+
+    impl Foo {
+        fn baz(&self) {}
+    }
+}
+fn main() {}
+
index aa176d5b0f04197fa482b9a929f3df414a539fc4..d995ecc492e3477f65d3ac466c4d30e8e00d100c 100644 (file)
@@ -1,5 +1,3 @@
-// no-prefer-dynamic
-
 // 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.
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use std::slice::SliceExt;
-use std::old_io::{fs, USER_RWX};
-use std::process;
+// no-prefer-dynamic
+
+#![feature(fs, process, env, path, rand)]
+
 use std::env;
-use std::old_path::BytesContainer;
+use std::fs;
+use std::process;
 use std::rand::random;
+use std::str;
 
 fn main() {
     // If we're the child, make sure we were invoked correctly
@@ -34,21 +35,20 @@ fn main() {
 fn test() {
     // If we're the parent, copy our own binary to a new directory.
     let my_path = env::current_exe().unwrap();
-    let my_dir  = my_path.dir_path();
+    let my_dir  = my_path.parent().unwrap();
 
     let random_u32: u32 = random();
-    let child_dir = Path::new(my_dir.join(format!("issue-15149-child-{}",
-                                                  random_u32)));
-    fs::mkdir(&child_dir, USER_RWX).unwrap();
+    let child_dir = my_dir.join(&format!("issue-15149-child-{}", random_u32));
+    fs::create_dir(&child_dir).unwrap();
 
-    let child_path = child_dir.join(format!("mytest{}",
-                                            env::consts::EXE_SUFFIX));
+    let child_path = child_dir.join(&format!("mytest{}",
+                                             env::consts::EXE_SUFFIX));
     fs::copy(&my_path, &child_path).unwrap();
 
     // Append the new directory to our own PATH.
     let path = {
         let mut paths: Vec<_> = env::split_paths(&env::var_os("PATH").unwrap()).collect();
-        paths.push(child_dir.clone());
+        paths.push(child_dir.to_path_buf());
         env::join_paths(paths.iter()).unwrap()
     };
 
@@ -58,9 +58,9 @@ fn test() {
 
     assert!(child_output.status.success(),
             format!("child assertion failed\n child stdout:\n {}\n child stderr:\n {}",
-                    child_output.stdout.container_as_str().unwrap(),
-                    child_output.stderr.container_as_str().unwrap()));
+                    str::from_utf8(&child_output.stdout).unwrap(),
+                    str::from_utf8(&child_output.stderr).unwrap()));
 
-    fs::rmdir_recursive(&child_dir).unwrap();
+    fs::remove_dir_all(&child_dir).unwrap();
 
 }
index 3bab78ab0df9f0ca3959ff1ea010a0f9a5ff0b0b..92d8dfa2cf9a975bc306078ebdfeebe5267c1f63 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use std::old_io::{process, Command};
+use std::process::Command;
 use std::env;
 
 fn main() {
@@ -22,10 +22,8 @@ fn main() {
 }
 
 fn test() {
-    let status = Command::new(env::current_exe().unwrap())
+    let status = Command::new(&env::current_exe().unwrap())
                          .arg("foo").arg("")
-                         .stdout(process::InheritFd(1))
-                         .stderr(process::InheritFd(2))
                          .status().unwrap();
     assert!(status.success());
 }
index ce5a0aa96e3d308493653125406e769e10e8bce1..aa53a7658e1291fd5985ac06abeb89ac5d765516 100644 (file)
@@ -25,9 +25,7 @@ fn main() {
     let mut dropped = false;
     {
         let leak = Leak { dropped: &mut dropped };
-        // FIXME(#21721) "hack" used to be () but that can cause
-        // certain LLVM versions to abort during optimizations.
-        for (_, leaked) in Some(("hack", leak)).into_iter() {}
+        for ((), leaked) in Some(((), leak)).into_iter() {}
     }
 
     assert!(dropped);
index 4d20e6360ad4fdda2654b0047b475e37b2fcdaac..ba107dd2cf9a2457b8b41db94e66834b9b56847f 100644 (file)
@@ -8,14 +8,19 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// ignore-windows currently windows requires UTF-8 for spawning processes
-
-use std::old_io::Command;
-use std::env;
-
+#[cfg(unix)]
 fn main() {
+    use std::process::Command;
+    use std::env;
+    use std::os::unix::prelude::*;
+    use std::ffi::OsStr;
+
     if env::args().len() == 1 {
-        assert!(Command::new(env::current_exe().unwrap()).arg(b"\xff")
+        assert!(Command::new(&env::current_exe().unwrap())
+                        .arg(<OsStr as OsStrExt>::from_bytes(b"\xff"))
                         .status().unwrap().success())
     }
 }
+
+#[cfg(windows)]
+fn main() {}
diff --git a/src/test/run-pass/issue-21721.rs b/src/test/run-pass/issue-21721.rs
new file mode 100644 (file)
index 0000000..fee1406
--- /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 main() {
+    static NONE: Option<((), &'static u8)> = None;
+    let ptr = unsafe {
+        *(&NONE as *const _ as *const *const u8)
+    };
+    assert!(ptr.is_null());
+}
diff --git a/src/test/run-pass/issue-22536-copy-mustnt-zero.rs b/src/test/run-pass/issue-22536-copy-mustnt-zero.rs
new file mode 100644 (file)
index 0000000..b349218
--- /dev/null
@@ -0,0 +1,34 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Regression test for Issue #22536: If a type implements Copy, then
+// moving it must not zero the original memory.
+
+trait Resources {
+    type Buffer: Copy;
+    fn foo(&self) {}
+}
+
+struct BufferHandle<R: Resources> {
+    raw: <R as Resources>::Buffer,
+}
+impl<R: Resources> Copy for BufferHandle<R> {}
+
+enum Res {}
+impl Resources for Res {
+    type Buffer = u32;
+}
+impl Copy for Res { }
+
+fn main() {
+    let b: BufferHandle<Res> = BufferHandle { raw: 1 };
+    let c = b;
+    assert_eq!(c.raw, b.raw)
+}
index 754412ea949381c7059b1a6d6472d9f7a76d2489..3f1a1c75d8a78c077fad6d1c1fceb651c5be0e82 100644 (file)
@@ -24,6 +24,6 @@ pub fn main() {
     let mut table = HashMap::new();
     table.insert("one".to_string(), 1);
     table.insert("two".to_string(), 2);
-    assert!(check_strs(&format!("{:?}", table), "HashMap {\"one\": 1, \"two\": 2}") ||
-            check_strs(&format!("{:?}", table), "HashMap {\"two\": 2, \"one\": 1}"));
+    assert!(check_strs(&format!("{:?}", table), "{\"one\": 1, \"two\": 2}") ||
+            check_strs(&format!("{:?}", table), "{\"two\": 2, \"one\": 1}"));
 }
diff --git a/src/test/run-pass/issue-7607-2.rs b/src/test/run-pass/issue-7607-2.rs
new file mode 100644 (file)
index 0000000..c52051f
--- /dev/null
@@ -0,0 +1,24 @@
+// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+pub mod a {
+    pub struct Foo { a: usize }
+}
+
+pub mod b {
+    use a::Foo;
+    impl Foo {
+        fn bar(&self) { }
+    }
+}
+
+pub fn main() { }
+
+
index 05c6aac90e39c9982830af973cf7a1b4119e9c5a..d2e27fc822eebe8323a641772db87038842e2e8c 100644 (file)
@@ -8,13 +8,11 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use std::uint;
-
 pub fn main() {
     // sometimes we have had trouble finding
     // the right type for f, as we unified
     // bot and u32 here
-    let f = match "1234".parse::<uint>().ok() {
+    let f = match "1234".parse::<usize>().ok() {
         None => return (),
         Some(num) => num as u32
     };
index 457c0a35fd70f9a963fccd81f224b1dff69f41cf..0d563f1a714c350cecbf0f18523c9a2c7fa993ad 100644 (file)
@@ -44,11 +44,11 @@ fn transform(x: Option<int>) -> Option<String> {
 pub fn main() {
     assert_eq!(transform(Some(10)), Some("11".to_string()));
     assert_eq!(transform(None), None);
-    assert!((vec!("hi".to_string()))
+    assert_eq!((vec!("hi".to_string()))
         .bind(|x| vec!(x.clone(), format!("{}!", x)) )
-        .bind(|x| vec!(x.clone(), format!("{}?", x)) ) ==
-        vec!("hi".to_string(),
-             "hi?".to_string(),
-             "hi!".to_string(),
-             "hi!?".to_string()));
+        .bind(|x| vec!(x.clone(), format!("{}?", x)) ),
+        ["hi".to_string(),
+         "hi?".to_string(),
+         "hi!".to_string(),
+         "hi!?".to_string()]);
 }
index f0b6a505929c66e9a67bcb6ec08034c3fbdcd4a9..b159b128333f0e39aea8386d3c20679d53825240 100644 (file)
@@ -14,6 +14,7 @@
 // aux-build:sepcomp_lib.rs
 // compile-flags: -C lto
 // no-prefer-dynamic
+// ignore-android FIXME #18800
 
 extern crate sepcomp_lib;
 use sepcomp_lib::a::one;
diff --git a/src/test/run-pass/std-sync-right-kind-impls.rs b/src/test/run-pass/std-sync-right-kind-impls.rs
new file mode 100644 (file)
index 0000000..d2d72ed
--- /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.
+
+use std::sync;
+
+fn assert_both<T: Sync + Send>() {}
+
+fn main() {
+    assert_both::<sync::StaticMutex>();
+    assert_both::<sync::StaticCondvar>();
+    assert_both::<sync::StaticRwLock>();
+    assert_both::<sync::Mutex<()>>();
+    assert_both::<sync::Condvar>();
+    assert_both::<sync::RwLock<()>>();
+    assert_both::<sync::Semaphore>();
+    assert_both::<sync::Barrier>();
+    assert_both::<sync::Arc<()>>();
+    assert_both::<sync::Weak<()>>();
+    assert_both::<sync::Once>();
+}
diff --git a/src/test/run-pass/sync-send-iterators-in-libcollections.rs b/src/test/run-pass/sync-send-iterators-in-libcollections.rs
new file mode 100644 (file)
index 0000000..6d29d5f
--- /dev/null
@@ -0,0 +1,98 @@
+// 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.
+
+#![allow(unused_mut)]
+#![feature(collections)]
+
+extern crate collections;
+
+use collections::BinaryHeap;
+use collections::{BitSet, BitVec};
+use collections::{BTreeMap, BTreeSet};
+use collections::EnumSet;
+use collections::LinkedList;
+use collections::Vec;
+use collections::VecDeque;
+use collections::VecMap;
+
+use collections::Bound::Included;
+use collections::enum_set::CLike;
+use std::mem;
+
+fn is_sync<T>(_: T) where T: Sync {}
+fn is_send<T>(_: T) where T: Send {}
+
+macro_rules! all_sync_send {
+    ($ctor:expr, $($iter:ident),+) => ({
+        $(
+            let mut x = $ctor;
+            is_sync(x.$iter());
+            let mut y = $ctor;
+            is_send(y.$iter());
+        )+
+    })
+}
+
+macro_rules! is_sync_send {
+    ($ctor:expr, $iter:ident($($param:expr),+)) => ({
+        let mut x = $ctor;
+        is_sync(x.$iter($( $param ),+));
+        let mut y = $ctor;
+        is_send(y.$iter($( $param ),+));
+    })
+}
+
+fn main() {
+    // The iterator "generator" list should exhaust what corresponding
+    // implementations have where `Sync` and `Send` semantics apply.
+    all_sync_send!(BinaryHeap::<usize>::new(), iter, drain, into_iter);
+
+    all_sync_send!(BitVec::new(), iter);
+
+    all_sync_send!(BitSet::new(), iter);
+    is_sync_send!(BitSet::new(), union(&BitSet::new()));
+    is_sync_send!(BitSet::new(), intersection(&BitSet::new()));
+    is_sync_send!(BitSet::new(), difference(&BitSet::new()));
+    is_sync_send!(BitSet::new(), symmetric_difference(&BitSet::new()));
+
+    all_sync_send!(BTreeMap::<usize, usize>::new(), iter, iter_mut, into_iter, keys, values);
+    is_sync_send!(BTreeMap::<usize, usize>::new(), range(Included(&0), Included(&9)));
+    is_sync_send!(BTreeMap::<usize, usize>::new(), range_mut(Included(&0), Included(&9)));
+
+    all_sync_send!(BTreeSet::<usize>::new(), iter, into_iter);
+    is_sync_send!(BTreeSet::<usize>::new(), range(Included(&0), Included(&9)));
+    is_sync_send!(BTreeSet::<usize>::new(), difference(&BTreeSet::<usize>::new()));
+    is_sync_send!(BTreeSet::<usize>::new(), symmetric_difference(&BTreeSet::<usize>::new()));
+    is_sync_send!(BTreeSet::<usize>::new(), intersection(&BTreeSet::<usize>::new()));
+    is_sync_send!(BTreeSet::<usize>::new(), union(&BTreeSet::<usize>::new()));
+
+    all_sync_send!(LinkedList::<usize>::new(), iter, iter_mut, into_iter);
+
+    #[derive(Copy)]
+    #[repr(usize)]
+    #[allow(dead_code)]
+    enum Foo { A, B, C }
+    impl CLike for Foo {
+        fn to_usize(&self) -> usize {
+            *self as usize
+        }
+
+        fn from_usize(v: usize) -> Foo {
+            unsafe { mem::transmute(v) }
+        }
+    }
+    all_sync_send!(EnumSet::<Foo>::new(), iter);
+
+    all_sync_send!(VecDeque::<usize>::new(), iter, iter_mut, drain, into_iter);
+
+    all_sync_send!(VecMap::<usize>::new(), iter, iter_mut, drain, into_iter, keys, values);
+
+    all_sync_send!(Vec::<usize>::new(), into_iter, drain);
+}
index 5f4b18df6e16b983f103a0fda7958b83c1648c6c..0dedf621a4f2887f0f6205142239e505e9e638bf 100644 (file)
@@ -44,9 +44,9 @@ fn bar<U:to_str,T:map<U>>(x: T) -> Vec<String> {
 }
 
 pub fn main() {
-    assert_eq!(foo(vec!(1)), vec!("hi".to_string()));
-    assert_eq!(bar::<int, Vec<int> >(vec!(4, 5)), vec!("4".to_string(), "5".to_string()));
+    assert_eq!(foo(vec!(1)), ["hi".to_string()]);
+    assert_eq!(bar::<int, Vec<int> >(vec!(4, 5)), ["4".to_string(), "5".to_string()]);
     assert_eq!(bar::<String, Vec<String> >(vec!("x".to_string(), "y".to_string())),
-               vec!("x".to_string(), "y".to_string()));
-    assert_eq!(bar::<(), Vec<()>>(vec!(())), vec!("()".to_string()));
+               ["x".to_string(), "y".to_string()]);
+    assert_eq!(bar::<(), Vec<()>>(vec!(())), ["()".to_string()]);
 }
diff --git a/src/test/run-pass/trait-impl-2.rs b/src/test/run-pass/trait-impl-2.rs
new file mode 100644 (file)
index 0000000..abc35bc
--- /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.
+
+pub mod Foo {
+    pub trait Trait {
+        fn foo(&self);
+    }
+}
+
+mod Bar {
+    impl<'a> ::Foo::Trait+'a {
+        fn bar(&self) { self.foo() }
+    }
+}
+
+fn main() {}
diff --git a/src/test/run-pass/traits-issue-22655.rs b/src/test/run-pass/traits-issue-22655.rs
new file mode 100644 (file)
index 0000000..18c7cfb
--- /dev/null
@@ -0,0 +1,29 @@
+// 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.
+
+// Regression test for issue #22655: This test should not lead to
+// infinite recursion.
+
+unsafe impl<T: Send + ?Sized> Send for Unique<T> { }
+
+pub struct Unique<T:?Sized> {
+    pointer: *const T,
+}
+
+pub struct Node<V> {
+    vals: V,
+    edges: Unique<Node<V>>,
+}
+
+fn is_send<T: Send>() {}
+
+fn main() {
+    is_send::<Node<&'static ()>>();
+}
diff --git a/src/test/run-pass/ufcs-polymorphic-paths.rs b/src/test/run-pass/ufcs-polymorphic-paths.rs
new file mode 100644 (file)
index 0000000..29b1c8f
--- /dev/null
@@ -0,0 +1,132 @@
+// 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.
+
+#![feature(macro_rules)]
+
+use std::borrow::{Cow, IntoCow};
+use std::collections::BitVec;
+use std::default::Default;
+use std::iter::FromIterator;
+use std::ops::Add;
+use std::option::IntoIter as OptionIter;
+use std::rand::Rand;
+use std::rand::XorShiftRng as DummyRng;
+// FIXME the glob std::prelude::*; import of Vec is missing non-static inherent methods.
+use std::vec::Vec;
+
+#[derive(PartialEq, Eq)]
+struct Newt<T>(T);
+
+fn id<T>(x: T) -> T { x }
+fn eq<T: Eq>(a: T, b: T) -> bool { a == b }
+fn u8_as_i8(x: u8) -> i8 { x as i8 }
+fn odd(x: usize) -> bool { x % 2 == 1 }
+fn dummy_rng() -> DummyRng { DummyRng::new_unseeded() }
+
+trait Size: Sized {
+    fn size() -> usize { std::mem::size_of::<Self>() }
+}
+impl<T> Size for T {}
+
+macro_rules! tests {
+    ($($expr:expr, $ty:ty, ($($test:expr),*);)+) => (pub fn main() {$({
+        const C: $ty = $expr;
+        static S: $ty = $expr;
+        assert!(eq(C($($test),*), $expr($($test),*)));
+        assert!(eq(S($($test),*), $expr($($test),*)));
+        assert!(eq(C($($test),*), S($($test),*)));
+    })+})
+}
+
+tests! {
+    // Free function.
+    id, fn(i32) -> i32, (5);
+    id::<i32>, fn(i32) -> i32, (5);
+
+    // Enum variant constructor.
+    Some, fn(i32) -> Option<i32>, (5);
+    Some::<i32>, fn(i32) -> Option<i32>, (5);
+
+    // Tuple struct constructor.
+    Newt, fn(i32) -> Newt<i32>, (5);
+    Newt::<i32>, fn(i32) -> Newt<i32>, (5);
+
+    // Inherent static methods.
+    Vec::new, fn() -> Vec<()>, ();
+    Vec::<()>::new, fn() -> Vec<()>, ();
+    <Vec<()>>::new, fn() -> Vec<()>, ();
+    Vec::with_capacity, fn(usize) -> Vec<()>, (5);
+    Vec::<()>::with_capacity, fn(usize) -> Vec<()>, (5);
+    <Vec<()>>::with_capacity, fn(usize) -> Vec<()>, (5);
+    BitVec::from_fn, fn(usize, fn(usize) -> bool) -> BitVec, (5, odd);
+    BitVec::from_fn::<fn(usize) -> bool>, fn(usize, fn(usize) -> bool) -> BitVec, (5, odd);
+
+    // Inherent non-static method.
+    Vec::map_in_place, fn(Vec<u8>, fn(u8) -> i8) -> Vec<i8>, (vec![b'f', b'o', b'o'], u8_as_i8);
+    Vec::map_in_place::<i8, fn(u8) -> i8>, fn(Vec<u8>, fn(u8) -> i8) -> Vec<i8>,
+        (vec![b'f', b'o', b'o'], u8_as_i8);
+    // FIXME these break with "type parameter might not appear here pointing at `<u8>`.
+    // Vec::<u8>::map_in_place: fn(Vec<u8>, fn(u8) -> i8) -> Vec<i8>
+    //    , (vec![b'f', b'o', b'o'], u8_as_i8);
+    // Vec::<u8>::map_in_place::<i8, fn(u8) -> i8>: fn(Vec<u8>, fn(u8) -> i8) -> Vec<i8>
+    //    , (vec![b'f', b'o', b'o'], u8_as_i8);
+
+    // Trait static methods.
+    bool::size, fn() -> usize, ();
+    <bool>::size, fn() -> usize, ();
+    <bool as Size>::size, fn() -> usize, ();
+
+    Default::default, fn() -> i32, ();
+    i32::default, fn() -> i32, ();
+    <i32>::default, fn() -> i32, ();
+    <i32 as Default>::default, fn() -> i32, ();
+
+    Rand::rand, fn(&mut DummyRng) -> i32, (&mut dummy_rng());
+    i32::rand, fn(&mut DummyRng) -> i32, (&mut dummy_rng());
+    <i32>::rand, fn(&mut DummyRng) -> i32, (&mut dummy_rng());
+    <i32 as Rand>::rand, fn(&mut DummyRng) -> i32, (&mut dummy_rng());
+    Rand::rand::<DummyRng>, fn(&mut DummyRng) -> i32, (&mut dummy_rng());
+    i32::rand::<DummyRng>, fn(&mut DummyRng) -> i32, (&mut dummy_rng());
+    <i32>::rand::<DummyRng>, fn(&mut DummyRng) -> i32, (&mut dummy_rng());
+    <i32 as Rand>::rand::<DummyRng>, fn(&mut DummyRng) -> i32, (&mut dummy_rng());
+
+    // Trait non-static methods.
+    Clone::clone, fn(&i32) -> i32, (&5);
+    i32::clone, fn(&i32) -> i32, (&5);
+    <i32>::clone, fn(&i32) -> i32, (&5);
+    <i32 as Clone>::clone, fn(&i32) -> i32, (&5);
+
+    FromIterator::from_iter, fn(OptionIter<i32>) -> Vec<i32>, (Some(5).into_iter());
+    Vec::from_iter, fn(OptionIter<i32>) -> Vec<i32>, (Some(5).into_iter());
+    <Vec<_>>::from_iter, fn(OptionIter<i32>) -> Vec<i32>, (Some(5).into_iter());
+    <Vec<_> as FromIterator<_>>::from_iter, fn(OptionIter<i32>) -> Vec<i32>,
+        (Some(5).into_iter());
+    <Vec<i32> as FromIterator<_>>::from_iter, fn(OptionIter<i32>) -> Vec<i32>,
+        (Some(5).into_iter());
+    FromIterator::from_iter::<OptionIter<i32>>, fn(OptionIter<i32>) -> Vec<i32>,
+        (Some(5).into_iter());
+    <Vec<i32> as FromIterator<_>>::from_iter::<OptionIter<i32>>, fn(OptionIter<i32>) -> Vec<i32>,
+        (Some(5).into_iter());
+
+    Add::add, fn(i32, i32) -> i32, (5, 6);
+    i32::add, fn(i32, i32) -> i32, (5, 6);
+    <i32>::add, fn(i32, i32) -> i32, (5, 6);
+    <i32 as Add<_>>::add, fn(i32, i32) -> i32, (5, 6);
+    <i32 as Add<i32>>::add, fn(i32, i32) -> i32, (5, 6);
+
+    String::into_cow, fn(String) -> Cow<'static, str>,
+        ("foo".to_string());
+    <String>::into_cow, fn(String) -> Cow<'static, str>,
+        ("foo".to_string());
+    <String as IntoCow<_>>::into_cow, fn(String) -> Cow<'static, str>,
+        ("foo".to_string());
+    <String as IntoCow<'static, _>>::into_cow, fn(String) -> Cow<'static, str>,
+        ("foo".to_string());
+}
index 087ef5dcf05e4a08bc529f342eb174f596269434..1401fe7470b0a1d71f0772e2d9217414625cdbde 100644 (file)
@@ -18,5 +18,5 @@ fn f<F: FnMut()>(mut f: F) {
 fn main() {
     let mut v: Vec<_> = vec![];
     f(|| v.push(0));
-    assert_eq!(v, vec![0]);
+    assert_eq!(v, [0]);
 }