]> git.lizzy.rs Git - rust.git/commitdiff
Rollup merge of #22788 - vadimcn:fix-precise_time_ns, r=pnkfelix
authorManish Goregaokar <manishsmail@gmail.com>
Fri, 27 Feb 2015 06:13:51 +0000 (11:43 +0530)
committerManish Goregaokar <manishsmail@gmail.com>
Fri, 27 Feb 2015 16:37:02 +0000 (22:07 +0530)
 which starts happening after ~2 hours of machine uptime.
Closes #17845

376 files changed:
src/doc/index.md
src/doc/reference.md
src/doc/rust.css
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/doc/trpl/pointers.md
src/doc/trpl/static-and-dynamic-dispatch.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/borrow.rs
src/libcollections/btree/map.rs
src/libcollections/btree/node.rs
src/libcollections/btree/set.rs
src/libcollections/enum_set.rs
src/libcollections/fmt.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/float.rs
src/libcore/fmt/mod.rs
src/libcore/fmt/num.rs
src/libcore/fmt/rt/v1.rs
src/libcore/hash/mod.rs
src/libcore/hash/sip.rs
src/libcore/intrinsics.rs
src/libcore/iter.rs
src/libcore/macros.rs
src/libcore/mem.rs
src/libcore/num/mod.rs
src/libcore/ops.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/str.rs
src/libflate/lib.rs
src/libfmt_macros/lib.rs
src/liblibc/lib.rs
src/liblog/macros.rs
src/librbml/io.rs
src/librustc/lib.rs
src/librustc/lint/builtin.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/cfg/graphviz.rs
src/librustc/middle/cfg/mod.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/dataflow.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/fast_reject.rs
src/librustc/middle/infer/combine.rs
src/librustc/middle/infer/error_reporting.rs
src/librustc/middle/infer/freshen.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/object_safety.rs
src/librustc/middle/traits/select.rs
src/librustc/middle/ty.rs
src/librustc/middle/ty_fold.rs
src/librustc/middle/ty_walk.rs
src/librustc/plugin/load.rs
src/librustc/session/config.rs
src/librustc/session/mod.rs
src/librustc/util/ppaux.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_back/target/openbsd_base.rs
src/librustc_borrowck/borrowck/mod.rs
src/librustc_borrowck/graphviz.rs
src/librustc_driver/driver.rs
src/librustc_driver/test.rs
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/adt.rs
src/librustc_trans/trans/base.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_trans/trans/type_.rs
src/librustc_trans/trans/type_of.rs
src/librustc_typeck/astconv.rs
src/librustc_typeck/check/_match.rs
src/librustc_typeck/check/implicator.rs
src/librustc_typeck/check/method/confirm.rs
src/librustc_typeck/check/method/mod.rs
src/librustc_typeck/check/method/probe.rs
src/librustc_typeck/check/method/suggest.rs
src/librustc_typeck/check/mod.rs
src/librustc_typeck/check/regionck.rs
src/librustc_typeck/check/vtable.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/html/format.rs
src/librustdoc/test.rs
src/librustdoc/visit_ast.rs
src/libserialize/json.rs
src/libstd/ascii.rs
src/libstd/collections/hash/map.rs
src/libstd/collections/hash/set.rs
src/libstd/collections/hash/state.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/impls.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/prelude/v1.rs
src/libstd/process.rs
src/libstd/rand/os.rs
src/libstd/sync/barrier.rs
src/libstd/sync/condvar.rs
src/libstd/sync/mod.rs
src/libstd/sync/mpsc/blocking.rs
src/libstd/sync/mpsc/mod.rs
src/libstd/sync/mpsc/oneshot.rs
src/libstd/sync/mpsc/select.rs
src/libstd/sync/mpsc/shared.rs
src/libstd/sync/mpsc/spsc_queue.rs
src/libstd/sync/mpsc/stream.rs
src/libstd/sync/mpsc/sync.rs
src/libstd/sync/mutex.rs
src/libstd/sync/once.rs
src/libstd/sync/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/fs2.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/tty.rs
src/libstd/thread.rs
src/libstd/thread_local/mod.rs
src/libstd/thread_local/scoped.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/format.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/rustbook/build.rs
src/rustbook/main.rs
src/rustbook/test.rs
src/snapshots.txt
src/test/auxiliary/cci_class_cast.rs
src/test/auxiliary/lint_stability.rs
src/test/auxiliary/lint_stability_fields.rs [new file with mode: 0644]
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/coherence-blanket-conflicts-with-blanket-implemented.rs
src/test/compile-fail/coherence-blanket-conflicts-with-blanket-unimplemented.rs
src/test/compile-fail/coherence-blanket-conflicts-with-specific-cross-crate.rs
src/test/compile-fail/coherence-blanket-conflicts-with-specific-multidispatch.rs
src/test/compile-fail/coherence-blanket-conflicts-with-specific.rs
src/test/compile-fail/coherence-tuple-conflict.rs
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/fn-trait-formatting.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/infinite-instantiation.rs
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-17441.rs
src/test/compile-fail/issue-18959.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-missing-doc.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/move-in-guard-1.rs [new file with mode: 0644]
src/test/compile-fail/move-in-guard-2.rs [new file with mode: 0644]
src/test/compile-fail/no-implicit-prelude-nested.rs
src/test/compile-fail/no-implicit-prelude.rs
src/test/compile-fail/object-safety-by-value-self-use.rs [new file with mode: 0644]
src/test/compile-fail/object-safety-by-value-self.rs
src/test/compile-fail/object-safety-generics.rs
src/test/compile-fail/object-safety-mentions-Self.rs
src/test/compile-fail/recursion.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/trait-test-2.rs
src/test/compile-fail/typeck-builtin-bound-type-parameters.rs [new file with mode: 0644]
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-after-move-implicity-coerced-object.rs
src/test/compile-fail/use-from-trait.rs
src/test/parse-fail/issue-22647.rs [new file with mode: 0644]
src/test/parse-fail/issue-22712.rs [new file with mode: 0644]
src/test/parse-fail/trailing-plus-in-bounds.rs
src/test/run-make/graphviz-flowgraph/f07.dot-expected.dot
src/test/run-make/graphviz-flowgraph/f13.dot-expected.dot
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/class-separate-impl.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/coherence-multidispatch-tuple.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/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-20091.rs
src/test/run-pass/issue-22536-copy-mustnt-zero.rs [new file with mode: 0644]
src/test/run-pass/issue-22577.rs [new file with mode: 0644]
src/test/run-pass/issue-3559.rs
src/test/run-pass/issue-3563-3.rs
src/test/run-pass/issue-7607-2.rs [new file with mode: 0644]
src/test/run-pass/monad.rs
src/test/run-pass/move-guard-const.rs [new file with mode: 0644]
src/test/run-pass/object-safety-sized-self-by-value-self.rs [new file with mode: 0644]
src/test/run-pass/object-safety-sized-self-generic-method.rs [new file with mode: 0644]
src/test/run-pass/object-safety-sized-self-return-Self.rs [new file with mode: 0644]
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/ufcs-polymorphic-paths.rs [new file with mode: 0644]
src/test/run-pass/unboxed-closures-infer-upvar.rs

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 357ff813fef3fcbea0297eb40eb0f0f82790124e..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*
@@ -2165,7 +2185,7 @@ fn needs_foo_or_bar() {
 
 // This function is only included when compiling for a unixish OS with a 32-bit
 // architecture
-#[cfg(all(unix, target_word_size = "32"))]
+#[cfg(all(unix, target_pointer_width = "32"))]
 fn on_32bit_unix() {
   // ...
 }
@@ -2193,9 +2213,9 @@ The following configurations must be defined by the implementation:
 * `target_os = "..."`. Operating system of the target, examples include
   `"win32"`, `"macos"`, `"linux"`, `"android"`, `"freebsd"`, `"dragonfly"`,
   `"bitrig"` or `"openbsd"`.
-* `target_word_size = "..."`. Target word size in bits. This is set to `"32"`
-  for targets with 32-bit pointers, and likewise set to `"64"` for 64-bit
-  pointers.
+* `target_pointer_width = "..."`. Target pointer width in bits. This is set
+  to `"32"` for targets with 32-bit pointers, and likewise set to `"64"` for
+  64-bit pointers.
 * `unix`. See `target_family`.
 * `windows`. See `target_family`.
 
index c2a25cd7a584ec39c85978737dc0e3c3770c2339..cd158283180a268381a35370837bd968f7753ed8 100644 (file)
@@ -56,6 +56,7 @@
 /* General structure */
 
 body {
+    background-color: white;
     margin: 0 auto;
     padding: 0 15px;
     font-family: "Source Serif Pro", Georgia, Times, "Times New Roman", serif;
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 332f299a67f3c421e44dc9feed706c600bb1511e..0f46b4da0d6f971b6ae3371d4850a5b8774493f0 100644 (file)
@@ -361,16 +361,16 @@ duration a *lifetime*. Let's try a more complex example:
 
 ```{rust}
 fn main() {
-    let x = &mut 5;
+    let mut x = 5;
 
-    if *x < 10 {
+    if x < 10 {
         let y = &x;
 
         println!("Oh no: {}", y);
         return;
     }
 
-    *x -= 1;
+    x -= 1;
 
     println!("Oh no: {}", x);
 }
@@ -382,17 +382,18 @@ mutated, and therefore, lets us pass. This wouldn't work:
 
 ```{rust,ignore}
 fn main() {
-    let x = &mut 5;
+    let mut x = 5;
 
-    if *x < 10 {
+    if x < 10 {
         let y = &x;
-        *x -= 1;
+
+        x -= 1;
 
         println!("Oh no: {}", y);
         return;
     }
 
-    *x -= 1;
+    x -= 1;
 
     println!("Oh no: {}", x);
 }
@@ -401,12 +402,12 @@ fn main() {
 It gives this error:
 
 ```text
-test.rs:5:8: 5:10 error: cannot assign to `*x` because it is borrowed
-test.rs:5         *x -= 1;
-                  ^~
-test.rs:4:16: 4:18 note: borrow of `*x` occurs here
-test.rs:4         let y = &x;
-                          ^~
+test.rs:7:9: 7:15 error: cannot assign to `x` because it is borrowed
+test.rs:7         x -= 1;
+                  ^~~~~~
+test.rs:5:18: 5:19 note: borrow of `x` occurs here
+test.rs:5         let y = &x;
+                           ^
 ```
 
 As you might guess, this kind of analysis is complex for a human, and therefore
index 1baf41329f561356238a63a37251744dd13046b2..fc1ab9bf9e8dca6278f004d521ed8382050866eb 100644 (file)
@@ -93,8 +93,8 @@ dynamic dispatch is sometimes more efficient.
 
 However, the common case is that it is more efficient to use static dispatch,
 and one can always have a thin statically-dispatched wrapper function that does
-a dynamic, but not vice versa, meaning static calls are more flexible. The
-standard library tries to be statically dispatched where possible for this
+a dynamic dispatch, but not vice versa, meaning static calls are more flexible.
+The standard library tries to be statically dispatched where possible for this
 reason. 
 
 ## Dynamic dispatch
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 e92f38741c9a0bd3abab4b3378e7b354b57f383d..f3c44a84ee50ac5f0fc7c210383bfa7d84e22c02 100644 (file)
@@ -132,7 +132,7 @@ fn to_owned(&self) -> T { self.clone() }
 /// ```rust
 /// use std::borrow::Cow;
 ///
-/// fn abs_all(input: &mut Cow<[int]>) {
+/// fn abs_all(input: &mut Cow<[i32]>) {
 ///     for i in 0..input.len() {
 ///         let v = input[i];
 ///         if v < 0 {
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 1b5018f4ad73df637c96ec9bd7bdb5ae2262f069..98673af3c68a84ab3b6e7b3a9cea8094ec8d2796 100644 (file)
 #![stable(feature = "rust1", since = "1.0.0")]
 
 pub use core::fmt::{Formatter, Result, Write, rt};
-pub use core::fmt::{Show, String, Octal, Binary};
+pub use core::fmt::{Octal, Binary};
 pub use core::fmt::{Display, Debug};
 pub use core::fmt::{LowerHex, UpperHex, Pointer};
 pub use core::fmt::{LowerExp, UpperExp};
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..d4c53739686142cfa6ffb16dc7db15bd840a4a95 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]
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..e18fa8c3082d103672a27aeb71addb2d0ac6cfad 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) {
@@ -505,10 +505,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 +531,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 +548,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 +569,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 +585,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 +603,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 +636,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 +674,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 +701,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 +718,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 +1019,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 +1036,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 +1057,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 +1085,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 +1121,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 +1755,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;
@@ -2105,7 +2108,7 @@ fn test_split_at_mut() {
             }
         }
 
-        assert!(values == vec![2, 3, 5, 6, 7]);
+        assert_eq!(values, [2, 3, 5, 6, 7]);
     }
 
     #[test]
@@ -2147,7 +2150,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 +2210,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 +2378,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 +2388,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 +2398,7 @@ fn test_move_items_zero_sized() {
         for i in vec {
             vec2.push(i);
         }
-        assert!(vec2 == vec![(), (), ()]);
+        assert_eq!(vec2, [(), (), ()]);
     }
 
     #[test]
@@ -2443,16 +2446,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 7f7264a04684b61426996c16ea82fd1683e3b913..f92e631c1f25c4becc028f0056484346b26fa603 100644 (file)
@@ -40,10 +40,10 @@ pub enum ExponentFormat {
 pub enum SignificantDigits {
     /// At most the given number of digits will be printed, truncating any
     /// trailing zeroes.
-    DigMax(uint),
+    DigMax(usize),
 
     /// Precisely the given number of digits will be printed.
-    DigExact(uint)
+    DigExact(usize)
 }
 
 /// How to emit the sign of a number.
@@ -240,27 +240,27 @@ pub fn float_to_str_bytes_common<T: Float, U, F>(
                     // If reached left end of number, have to
                     // insert additional digit:
                     if i < 0
-                    || buf[i as uint] == b'-'
-                    || buf[i as uint] == b'+' {
-                        for j in (i as uint + 1..end).rev() {
+                    || buf[i as usize] == b'-'
+                    || buf[i as usize] == b'+' {
+                        for j in (i as usize + 1..end).rev() {
                             buf[j + 1] = buf[j];
                         }
-                        buf[(i + 1) as uint] = value2ascii(1);
+                        buf[(i + 1) as usize] = value2ascii(1);
                         end += 1;
                         break;
                     }
 
                     // Skip the '.'
-                    if buf[i as uint] == b'.' { i -= 1; continue; }
+                    if buf[i as usize] == b'.' { i -= 1; continue; }
 
                     // Either increment the digit,
                     // or set to 0 if max and carry the 1.
-                    let current_digit = ascii2value(buf[i as uint]);
+                    let current_digit = ascii2value(buf[i as usize]);
                     if current_digit < (radix - 1) {
-                        buf[i as uint] = value2ascii(current_digit+1);
+                        buf[i as usize] = value2ascii(current_digit+1);
                         break;
                     } else {
-                        buf[i as uint] = value2ascii(0);
+                        buf[i as usize] = value2ascii(0);
                         i -= 1;
                     }
                 }
@@ -311,7 +311,7 @@ pub fn float_to_str_bytes_common<T: Float, U, F>(
 
             struct Filler<'a> {
                 buf: &'a mut [u8],
-                end: &'a mut uint,
+                end: &'a mut usize,
             }
 
             impl<'a> fmt::Write for Filler<'a> {
index a2c1bbc03317e9da08451e0b2b2d6194d385568b..117b829fdff9b5bf79ed6e4d686cfa45239b21b4 100644 (file)
@@ -110,11 +110,11 @@ fn write_fmt(&mut self, args: Arguments) -> Result {
 /// traits.
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct Formatter<'a> {
-    flags: uint,
+    flags: u32,
     fill: char,
     align: rt::v1::Alignment,
-    width: Option<uint>,
-    precision: Option<uint>,
+    width: Option<usize>,
+    precision: Option<usize>,
 
     buf: &'a mut (Write+'a),
     curarg: slice::Iter<'a, ArgumentV1<'a>>,
@@ -140,7 +140,7 @@ pub struct ArgumentV1<'a> {
 
 impl<'a> ArgumentV1<'a> {
     #[inline(never)]
-    fn show_uint(x: &uint, f: &mut Formatter) -> Result {
+    fn show_usize(x: &usize, f: &mut Formatter) -> Result {
         Display::fmt(x, f)
     }
 
@@ -158,13 +158,13 @@ pub fn new<'b, T>(x: &'b T,
 
     #[doc(hidden)]
     #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn from_uint(x: &uint) -> ArgumentV1 {
-        ArgumentV1::new(x, ArgumentV1::show_uint)
+    pub fn from_usize(x: &usize) -> ArgumentV1 {
+        ArgumentV1::new(x, ArgumentV1::show_usize)
     }
 
-    fn as_uint(&self) -> Option<uint> {
-        if self.formatter as uint == ArgumentV1::show_uint as uint {
-            Some(unsafe { *(self.value as *const _ as *const uint) })
+    fn as_usize(&self) -> Option<usize> {
+        if self.formatter as usize == ArgumentV1::show_usize as usize {
+            Some(unsafe { *(self.value as *const _ as *const usize) })
         } else {
             None
         }
@@ -194,7 +194,7 @@ pub fn new_v1(pieces: &'a [&'a str],
     /// The `pieces` array must be at least as long as `fmt` to construct
     /// a valid Arguments structure. Also, any `Count` within `fmt` that is
     /// `CountIsParam` or `CountIsNextParam` has to point to an argument
-    /// created with `argumentuint`. However, failing to do so doesn't cause
+    /// created with `argumentusize`. However, failing to do so doesn't cause
     /// unsafety, but will ignore invalid .
     #[doc(hidden)] #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -246,16 +246,6 @@ fn fmt(&self, fmt: &mut Formatter) -> Result {
     }
 }
 
-/// Format trait for the `:?` format. Useful for debugging, all types
-/// should implement this.
-#[deprecated(since = "1.0.0", reason = "renamed to Debug")]
-#[unstable(feature = "old_fmt")]
-pub trait Show {
-    /// Formats the value using the given formatter.
-    #[stable(feature = "rust1", since = "1.0.0")]
-    fn fmt(&self, &mut Formatter) -> Result;
-}
-
 /// Format trait for the `:?` format. Useful for debugging, all types
 /// should implement this.
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -269,22 +259,6 @@ pub trait Debug {
     fn fmt(&self, &mut Formatter) -> Result;
 }
 
-#[allow(deprecated)]
-impl<T: Show + ?Sized> Debug for T {
-    #[allow(deprecated)]
-    fn fmt(&self, f: &mut Formatter) -> Result { Show::fmt(self, f) }
-}
-
-/// When a value can be semantically expressed as a String, this trait may be
-/// used. It corresponds to the default format, `{}`.
-#[deprecated(since = "1.0.0", reason = "renamed to Display")]
-#[unstable(feature = "old_fmt")]
-pub trait String {
-    /// Formats the value using the given formatter.
-    #[stable(feature = "rust1", since = "1.0.0")]
-    fn fmt(&self, &mut Formatter) -> Result;
-}
-
 /// When a value can be semantically expressed as a String, this trait may be
 /// used. It corresponds to the default format, `{}`.
 #[rustc_on_unimplemented = "`{Self}` cannot be formatted with the default \
@@ -297,12 +271,6 @@ pub trait Display {
     fn fmt(&self, &mut Formatter) -> Result;
 }
 
-#[allow(deprecated)]
-impl<T: String + ?Sized> Display for T {
-    #[allow(deprecated)]
-    fn fmt(&self, f: &mut Formatter) -> Result { String::fmt(self, f) }
-}
-
 /// Format trait for the `o` character
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait Octal {
@@ -434,15 +402,15 @@ fn run(&mut self, arg: &rt::v1::Argument) -> Result {
         (value.formatter)(value.value, self)
     }
 
-    fn getcount(&mut self, cnt: &rt::v1::Count) -> Option<uint> {
+    fn getcount(&mut self, cnt: &rt::v1::Count) -> Option<usize> {
         match *cnt {
             rt::v1::Count::Is(n) => Some(n),
             rt::v1::Count::Implied => None,
             rt::v1::Count::Param(i) => {
-                self.args[i].as_uint()
+                self.args[i].as_usize()
             }
             rt::v1::Count::NextParam => {
-                self.curarg.next().and_then(|arg| arg.as_uint())
+                self.curarg.next().and_then(|arg| arg.as_usize())
             }
         }
     }
@@ -476,12 +444,12 @@ pub fn pad_integral(&mut self,
         let mut sign = None;
         if !is_positive {
             sign = Some('-'); width += 1;
-        } else if self.flags & (1 << (FlagV1::SignPlus as uint)) != 0 {
+        } else if self.flags & (1 << (FlagV1::SignPlus as u32)) != 0 {
             sign = Some('+'); width += 1;
         }
 
         let mut prefixed = false;
-        if self.flags & (1 << (FlagV1::Alternate as uint)) != 0 {
+        if self.flags & (1 << (FlagV1::Alternate as u32)) != 0 {
             prefixed = true; width += prefix.char_len();
         }
 
@@ -511,7 +479,7 @@ pub fn pad_integral(&mut self,
             }
             // The sign and prefix goes before the padding if the fill character
             // is zero
-            Some(min) if self.flags & (1 << (FlagV1::SignAwareZeroPad as uint)) != 0 => {
+            Some(min) if self.flags & (1 << (FlagV1::SignAwareZeroPad as u32)) != 0 => {
                 self.fill = '0';
                 try!(write_prefix(self));
                 self.with_padding(min - width, Alignment::Right, |f| {
@@ -581,7 +549,7 @@ pub fn pad(&mut self, s: &str) -> Result {
 
     /// Runs a callback, emitting the correct padding either before or
     /// afterwards depending on whether right or left alignment is requested.
-    fn with_padding<F>(&mut self, padding: uint, default: Alignment,
+    fn with_padding<F>(&mut self, padding: usize, default: Alignment,
                        f: F) -> Result
         where F: FnOnce(&mut Formatter) -> Result,
     {
@@ -629,7 +597,7 @@ pub fn write_fmt(&mut self, fmt: Arguments) -> Result {
 
     /// Flags for formatting (packed version of rt::Flag)
     #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn flags(&self) -> usize { self.flags }
+    pub fn flags(&self) -> u32 { self.flags }
 
     /// Character used as 'fill' whenever there is alignment
     #[unstable(feature = "core", reason = "method was just created")]
@@ -641,11 +609,11 @@ pub fn align(&self) -> Alignment { self.align }
 
     /// Optionally specified integer width that the output should be
     #[unstable(feature = "core", reason = "method was just created")]
-    pub fn width(&self) -> Option<uint> { self.width }
+    pub fn width(&self) -> Option<usize> { self.width }
 
     /// Optionally specified precision for numeric types
     #[unstable(feature = "core", reason = "method was just created")]
-    pub fn precision(&self) -> Option<uint> { self.precision }
+    pub fn precision(&self) -> Option<usize> { self.precision }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -731,9 +699,9 @@ fn fmt(&self, f: &mut Formatter) -> Result {
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T> Pointer for *const T {
     fn fmt(&self, f: &mut Formatter) -> Result {
-        f.flags |= 1 << (FlagV1::Alternate as uint);
-        let ret = LowerHex::fmt(&(*self as uint), f);
-        f.flags &= !(1 << (FlagV1::Alternate as uint));
+        f.flags |= 1 << (FlagV1::Alternate as u32);
+        let ret = LowerHex::fmt(&(*self as u32), f);
+        f.flags &= !(1 << (FlagV1::Alternate as u32));
         ret
     }
 }
@@ -889,7 +857,7 @@ fn fmt(&self, f: &mut Formatter) -> Result { f.pad("&Any") }
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T: Debug> Debug for [T] {
     fn fmt(&self, f: &mut Formatter) -> Result {
-        if f.flags & (1 << (FlagV1::Alternate as uint)) == 0 {
+        if f.flags & (1 << (FlagV1::Alternate as u32)) == 0 {
             try!(write!(f, "["));
         }
         let mut is_first = true;
@@ -901,7 +869,7 @@ fn fmt(&self, f: &mut Formatter) -> Result {
             }
             try!(write!(f, "{:?}", *x))
         }
-        if f.flags & (1 << (FlagV1::Alternate as uint)) == 0 {
+        if f.flags & (1 << (FlagV1::Alternate as u32)) == 0 {
             try!(write!(f, "]"));
         }
         Ok(())
index 1222126b5e0cdef73c0a3bccc4ce5dff3630c90f..0175e21c8da6152b47bfbbae924118a19bc3bc64 100644 (file)
@@ -214,7 +214,7 @@ macro_rules! integer {
         show! { $Uint with $SU }
     }
 }
-integer! { int, uint, "i", "u" }
+integer! { isize, usize, "i", "u" }
 integer! { i8, u8 }
 integer! { i16, u16 }
 integer! { i32, u32 }
index 0c9bb6316e0d805ecbcc08a05c1c6bb2fa67bc5e..7f6dea905dafd45ec351f20d8e1a21de91356e29 100644 (file)
@@ -33,7 +33,7 @@ pub struct FormatSpec {
     #[stable(feature = "rust1", since = "1.0.0")]
     pub align: Alignment,
     #[stable(feature = "rust1", since = "1.0.0")]
-    pub flags: uint,
+    pub flags: u32,
     #[stable(feature = "rust1", since = "1.0.0")]
     pub precision: Count,
     #[stable(feature = "rust1", since = "1.0.0")]
index ed48903a7c2550ab31b5c415f71b389f331bb9f7..edc4b7e10ee49b04b024a3b3076d2f425f12358a 100644 (file)
@@ -20,7 +20,7 @@
 //!
 //! #[derive(Hash)]
 //! struct Person {
-//!     id: uint,
+//!     id: u32,
 //!     name: String,
 //!     phone: u64,
 //! }
@@ -38,7 +38,7 @@
 //! use std::hash::{hash, Hash, Hasher, SipHasher};
 //!
 //! struct Person {
-//!     id: uint,
+//!     id: u32,
 //!     name: String,
 //!     phone: u64,
 //! }
index 6f24fc7067344c3cb848a0f645142f90c4d9a24f..39bcbacdff182c23b137037d007099a58ca17ed8 100644 (file)
 pub struct SipHasher {
     k0: u64,
     k1: u64,
-    length: uint, // how many bytes we've processed
+    length: usize, // how many bytes we've processed
     v0: u64,      // hash state
     v1: u64,
     v2: u64,
     v3: u64,
     tail: u64, // unprocessed bytes le
-    ntail: uint,  // how many bytes in tail are valid
+    ntail: usize,  // how many bytes in tail are valid
 }
 
 // sadly, these macro definitions can't appear later,
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 2d50bbb641363373a3e25a1ecdde6b79fdf5ef9c..8f767e62678e6b92788181b23e70542daf15b1cb 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
@@ -86,6 +86,7 @@
 #[rustc_on_unimplemented = "`{Self}` is not an iterator; maybe try calling `.iter()` or a similar \
                             method"]
 pub trait Iterator {
+    /// The type of the elements being iterated
     #[stable(feature = "rust1", since = "1.0.0")]
     type Item;
 
@@ -122,9 +123,11 @@ pub trait FromIterator<A> {
 /// Conversion into an `Iterator`
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait IntoIterator {
+    /// The type of the elements being iterated
     #[stable(feature = "rust1", since = "1.0.0")]
     type Item;
 
+    /// A container for iterating over elements of type Item
     #[stable(feature = "rust1", since = "1.0.0")]
     type IntoIter: Iterator<Item=Self::Item>;
 
@@ -579,8 +582,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")]
@@ -978,7 +981,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 }
     }
@@ -1783,6 +1786,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 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 fbd7f840da6e15748e2972899771deaa7b5307d5..c382ac46d5db9895a99241e95d32291f3da1650e 100644 (file)
@@ -184,6 +184,7 @@ fn $method(self, other: &'a $u) -> <$t as $imp<$u>>::Output {
 #[lang="add"]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait Add<RHS=Self> {
+    /// The resulting type after applying the `+` operator
     #[stable(feature = "rust1", since = "1.0.0")]
     type Output;
 
@@ -237,6 +238,7 @@ fn add(self, other: $t) -> $t { self + other }
 #[lang="sub"]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait Sub<RHS=Self> {
+    /// The resulting type after applying the `-` operator
     #[stable(feature = "rust1", since = "1.0.0")]
     type Output;
 
@@ -290,6 +292,7 @@ fn sub(self, other: $t) -> $t { self - other }
 #[lang="mul"]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait Mul<RHS=Self> {
+    /// The resulting type after applying the `*` operator
     #[stable(feature = "rust1", since = "1.0.0")]
     type Output;
 
@@ -343,6 +346,7 @@ fn mul(self, other: $t) -> $t { self * other }
 #[lang="div"]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait Div<RHS=Self> {
+    /// The resulting type after applying the `/` operator
     #[stable(feature = "rust1", since = "1.0.0")]
     type Output;
 
@@ -396,6 +400,7 @@ fn div(self, other: $t) -> $t { self / other }
 #[lang="rem"]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait Rem<RHS=Self> {
+    /// The resulting type after applying the `%` operator
     #[stable(feature = "rust1", since = "1.0.0")]
     type Output = Self;
 
@@ -468,6 +473,7 @@ fn rem(self, other: $t) -> $t {
 #[lang="neg"]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait Neg {
+    /// The resulting type after applying the `-` operator
     #[stable(feature = "rust1", since = "1.0.0")]
     type Output;
 
@@ -544,6 +550,7 @@ fn neg(self) -> $t { -(self as $t_signed) as $t }
 #[lang="not"]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait Not {
+    /// The resulting type after applying the `!` operator
     #[stable(feature = "rust1", since = "1.0.0")]
     type Output;
 
@@ -597,6 +604,7 @@ fn not(self) -> $t { !self }
 #[lang="bitand"]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait BitAnd<RHS=Self> {
+    /// The resulting type after applying the `&` operator
     #[stable(feature = "rust1", since = "1.0.0")]
     type Output;
 
@@ -650,6 +658,7 @@ fn bitand(self, rhs: $t) -> $t { self & rhs }
 #[lang="bitor"]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait BitOr<RHS=Self> {
+    /// The resulting type after applying the `|` operator
     #[stable(feature = "rust1", since = "1.0.0")]
     type Output;
 
@@ -703,6 +712,7 @@ fn bitor(self, rhs: $t) -> $t { self | rhs }
 #[lang="bitxor"]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait BitXor<RHS=Self> {
+    /// The resulting type after applying the `^` operator
     #[stable(feature = "rust1", since = "1.0.0")]
     type Output;
 
@@ -756,6 +766,7 @@ fn bitxor(self, other: $t) -> $t { self ^ other }
 #[lang="shl"]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait Shl<RHS> {
+    /// The resulting type after applying the `<<` operator
     #[stable(feature = "rust1", since = "1.0.0")]
     type Output;
 
@@ -827,6 +838,7 @@ macro_rules! shl_impl_all {
 #[lang="shr"]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait Shr<RHS> {
+    /// The resulting type after applying the `>>` operator
     #[stable(feature = "rust1", since = "1.0.0")]
     type Output;
 
@@ -900,6 +912,7 @@ macro_rules! shr_impl_all {
 #[rustc_on_unimplemented = "the type `{Self}` cannot be indexed by `{Idx}`"]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait Index<Idx: ?Sized> {
+    /// The returned type after indexing
     type Output: ?Sized;
 
     /// The method for the indexing (`Foo[Bar]`) operation
@@ -1047,6 +1060,7 @@ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
 #[lang="deref"]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait Deref {
+    /// The resulting type after dereferencing
     #[stable(feature = "rust1", since = "1.0.0")]
     type Target: ?Sized;
 
@@ -1122,6 +1136,7 @@ fn deref_mut(&mut self) -> &mut T { *self }
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_paren_sugar]
 pub trait Fn<Args> {
+    /// The returned type after the call operator is used.
     type Output;
 
     /// This is called when the call operator is used.
@@ -1133,6 +1148,7 @@ pub trait Fn<Args> {
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_paren_sugar]
 pub trait FnMut<Args> {
+    /// The returned type after the call operator is used.
     type Output;
 
     /// This is called when the call operator is used.
@@ -1144,6 +1160,7 @@ pub trait FnMut<Args> {
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_paren_sugar]
 pub trait FnOnce<Args> {
+    /// The returned type after the call operator is used.
     type Output;
 
     /// This is called when the call operator is used.
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 16b84dcf18e24aed5952b17cfbf1b7f45b1648c0..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,8 +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 {
-    type Target;
+pub trait PtrExt {
+    /// The type which is being pointed at
+    type Target: ?Sized;
 
     /// Returns true if the pointer is null.
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -278,13 +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 {
-    type Target;
+    /// The type which is being pointed at
+    type Target: ?Sized;
 
     /// Returns `None` if the pointer is null, or else returns a mutable
     /// reference to the value wrapped in `Some`.
@@ -300,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]
@@ -309,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)
     }
 
@@ -327,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]
@@ -336,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
     }
 
@@ -354,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]
@@ -372,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
@@ -406,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
@@ -450,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 {
@@ -464,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))
@@ -484,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 {
@@ -498,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))
@@ -525,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>,
 }
@@ -535,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..bca73782491bf5fe30571f61665babdbf2163767 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")]
index 2debcaa5813421c0951b434f85c8b01f44001c1d..91cad4330f20464441fdf623ee39219dcf81f58c 100644 (file)
@@ -51,7 +51,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;
@@ -740,6 +740,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 +833,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 +1505,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 +1519,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 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 be77622ac1db7c52335525cefd8753423177258f..4e25e51e9a466075c58b49ae0207413b88a8b426 100644 (file)
@@ -24,7 +24,6 @@
        html_root_url = "http://doc.rust-lang.org/nightly/",
        html_playground_url = "http://play.rust-lang.org/")]
 
-#![feature(int_uint)]
 #![feature(staged_api)]
 #![feature(unicode)]
 
@@ -65,7 +64,7 @@ pub struct FormatSpec<'a> {
     /// Optionally specified alignment
     pub align: Alignment,
     /// Packed version of various flags provided
-    pub flags: uint,
+    pub flags: u32,
     /// The integer precision to use
     pub precision: Count<'a>,
     /// The string width requested for the resulting format
@@ -82,7 +81,7 @@ pub enum Position<'a> {
     /// The argument will be in the next position. This is the default.
     ArgumentNext,
     /// The argument is located at a specific index.
-    ArgumentIs(uint),
+    ArgumentIs(usize),
     /// The argument has a name.
     ArgumentNamed(&'a str),
 }
@@ -121,11 +120,11 @@ pub enum Flag {
 #[derive(Copy, PartialEq)]
 pub enum Count<'a> {
     /// The count is specified explicitly.
-    CountIs(uint),
+    CountIs(usize),
     /// The count is specified by the argument with the given name.
     CountIsName(&'a str),
     /// The count is specified by the argument at the given index.
-    CountIsParam(uint),
+    CountIsParam(usize),
     /// The count is specified by the next parameter.
     CountIsNextParam,
     /// The count is implied and cannot be explicitly specified.
@@ -237,7 +236,7 @@ fn ws(&mut self) {
 
     /// Parses all of a string which is to be considered a "raw literal" in a
     /// format string. This is everything outside of the braces.
-    fn string(&mut self, start: uint) -> &'a str {
+    fn string(&mut self, start: usize) -> &'a str {
         loop {
             // we may not consume the character, so clone the iterator
             match self.cur.clone().next() {
@@ -314,13 +313,13 @@ fn format(&mut self) -> FormatSpec<'a> {
         }
         // Sign flags
         if self.consume('+') {
-            spec.flags |= 1 << (FlagSignPlus as uint);
+            spec.flags |= 1 << (FlagSignPlus as u32);
         } else if self.consume('-') {
-            spec.flags |= 1 << (FlagSignMinus as uint);
+            spec.flags |= 1 << (FlagSignMinus as u32);
         }
         // Alternate marker
         if self.consume('#') {
-            spec.flags |= 1 << (FlagAlternate as uint);
+            spec.flags |= 1 << (FlagAlternate as u32);
         }
         // Width and precision
         let mut havewidth = false;
@@ -333,7 +332,7 @@ fn format(&mut self) -> FormatSpec<'a> {
                 spec.width = CountIsParam(0);
                 havewidth = true;
             } else {
-                spec.flags |= 1 << (FlagSignAwareZeroPad as uint);
+                spec.flags |= 1 << (FlagSignAwareZeroPad as u32);
             }
         }
         if !havewidth {
@@ -413,7 +412,7 @@ fn word(&mut self) -> &'a str {
 
     /// Optionally parses an integer at the current position. This doesn't deal
     /// with overflow at all, it's just accumulating digits.
-    fn integer(&mut self) -> Option<uint> {
+    fn integer(&mut self) -> Option<usize> {
         let mut cur = 0;
         let mut found = false;
         loop {
@@ -617,7 +616,7 @@ fn format_flags() {
             format: FormatSpec {
                 fill: None,
                 align: AlignUnknown,
-                flags: (1 << FlagSignMinus as uint),
+                flags: (1 << FlagSignMinus as u32),
                 precision: CountImplied,
                 width: CountImplied,
                 ty: "",
@@ -628,7 +627,7 @@ fn format_flags() {
             format: FormatSpec {
                 fill: None,
                 align: AlignUnknown,
-                flags: (1 << FlagSignPlus as uint) | (1 << FlagAlternate as uint),
+                flags: (1 << FlagSignPlus as u32) | (1 << FlagAlternate as u32),
                 precision: CountImplied,
                 width: CountImplied,
                 ty: "",
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 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..26cb4f917c5669d5114364f506625fc1476043bc 100644 (file)
@@ -40,6 +40,7 @@
 #![feature(staged_api)]
 #![feature(std_misc)]
 #![feature(unicode)]
+#![feature(os)]
 #![cfg_attr(test, feature(test))]
 
 extern crate arena;
index 3c06bae177cef775de6d2c8fc64062985a98b4e1..0bd7f83b9595e003956a173bd7dd2b2009ac7255 100644 (file)
@@ -405,8 +405,8 @@ struct ImproperCTypesVisitor<'a, 'tcx: 'a> {
 }
 
 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() {
+    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 \
@@ -418,7 +418,7 @@ fn check_def(&mut self, sp: Span, ty_id: ast::NodeId, path_id: ast::NodeId) {
                                    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) {
+                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!")
                 };
@@ -437,9 +437,8 @@ fn check_def(&mut self, sp: Span, ty_id: ast::NodeId, path_id: ast::NodeId) {
 
 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),
-            _ => (),
+        if let ast::TyPath(..) = ty.node {
+            self.check_def(ty.span, ty.id);
         }
         visit::walk_ty(self, ty);
     }
@@ -683,8 +682,8 @@ 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"),
+                    ast::ExprPath(..) => cx.span_lint(PATH_STATEMENTS, s.span,
+                                                      "path statement with no effect"),
                     _ => ()
                 }
             }
@@ -1001,7 +1000,8 @@ fn check_lifetime_def(&mut self, cx: &Context, t: &ast::LifetimeDef) {
 
     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) {
+            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);
             }
         }
@@ -1066,8 +1066,8 @@ fn check_item(&mut self, cx: &Context, it: &ast::Item) {
 
     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(..))) => {
+        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);
             }
@@ -1227,10 +1227,13 @@ fn get_lints(&self) -> LintArray {
     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))) {
+            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,
@@ -1292,46 +1295,36 @@ fn check_expr(&mut self, cx: &Context, e: &ast::Expr) {
     }
 
     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(ast::Unsafety::Unsafe, _, _, _) =>
+                cx.span_lint(UNSAFE_CODE, it.span, "declaration of an `unsafe` trait"),
 
-            ast::ItemTrait(trait_safety, _, _, ref items) => {
-                if trait_safety == 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"),
 
-                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),
-                        _ => (),
-                    }
-                }
-            },
+            _ => return,
+        }
+    }
 
-            ast::ItemImpl(impl_safety, _, _, _, _, ref impls) => {
-                if impl_safety == Unsafe {
-                    cx.span_lint(UNSAFE_CODE, it.span, "implementation of an `unsafe` trait");
-                }
+    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"),
 
-                for item in impls {
-                    if let ast::ImplItem::MethodImplItem(ref meth) = *item {
-                        check_method(cx, meth);
-                    }
+            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")
                 }
             },
 
-            _ => return,
+            _ => (),
+        }
+    }
+
+    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")
         }
     }
 }
@@ -1577,6 +1570,14 @@ fn check_ty_method(&mut self, cx: &Context, tm: &ast::TypeMethod) {
                                      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 {
@@ -1770,6 +1771,11 @@ 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! {
@@ -1848,7 +1854,7 @@ fn check_fn(&mut self, cx: &Context, fn_kind: visit::FnKind, _: &ast::FnDecl,
                 continue
             }
             visited.insert(cfg_id);
-            let node_id = cfg.graph.node_data(idx).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) {
@@ -1901,10 +1907,7 @@ fn id_refers_to_this_fn<'tcx>(tcx: &ty::ctxt<'tcx>,
                                       _: 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
-                })
+                .map_or(false, |def| def.def_id() == ast_util::local_def(fn_id))
         }
 
         // check if the method call `id` refers to method `method_id`
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 e1e9d49dd05859d3df5e3ff67b98c2f6d17ef0cf..76a365259aa5713a3eb952a9a3eadfffeefb0bba 100644 (file)
@@ -153,9 +153,6 @@ pub fn enc_ty<'a, 'tcx>(w: &mut SeekableMemWriter, cx: &ctxt<'a, 'tcx>, t: Ty<'t
         ty::ty_err => {
             mywrite!(w, "e");
         }
-        ty::ty_open(_) => {
-            cx.diag.handler().bug("unexpected type in enc_sty (ty_open)");
-        }
     }
 
     let end = w.tell().unwrap();
@@ -389,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");
@@ -407,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..17fd80ceaea428063654da274aef672114ca5b89 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 d95dfb6feaec40eed64bbec4b21dbe1985d7bcca..24c54b53590c04f57a4ff6eafe82f3179b9d3cfa 100644 (file)
 use middle::cfg::*;
 use middle::def;
 use middle::graph;
+use middle::pat_util;
 use middle::region::CodeExtent;
 use middle::ty;
 use syntax::ast;
 use syntax::ast_util;
 use syntax::ptr::P;
-use util::nodemap::NodeMap;
 
 struct CFGBuilder<'a, 'tcx: 'a> {
     tcx: &'a ty::ctxt<'tcx>,
-    exit_map: NodeMap<CFGIndex>,
     graph: CFGGraph,
     fn_exit: CFGIndex,
     loop_scopes: Vec<LoopScope>,
@@ -36,17 +35,16 @@ struct LoopScope {
 pub fn construct(tcx: &ty::ctxt,
                  blk: &ast::Block) -> CFG {
     let mut graph = graph::Graph::new();
-    let entry = add_initial_dummy_node(&mut graph);
+    let entry = graph.add_node(CFGNodeData::Entry);
 
     // `fn_exit` is target of return exprs, which lies somewhere
     // outside input `blk`. (Distinguishing `fn_exit` and `block_exit`
     // also resolves chicken-and-egg problem that arises if you try to
     // have return exprs jump to `block_exit` during construction.)
-    let fn_exit = add_initial_dummy_node(&mut graph);
+    let fn_exit = graph.add_node(CFGNodeData::Exit);
     let block_exit;
 
     let mut cfg_builder = CFGBuilder {
-        exit_map: NodeMap(),
         graph: graph,
         fn_exit: fn_exit,
         tcx: tcx,
@@ -54,17 +52,12 @@ pub fn construct(tcx: &ty::ctxt,
     };
     block_exit = cfg_builder.block(blk, entry);
     cfg_builder.add_contained_edge(block_exit, fn_exit);
-    let CFGBuilder {exit_map, graph, ..} = cfg_builder;
-    CFG {exit_map: exit_map,
-         graph: graph,
+    let CFGBuilder {graph, ..} = cfg_builder;
+    CFG {graph: graph,
          entry: entry,
          exit: fn_exit}
 }
 
-fn add_initial_dummy_node(g: &mut CFGGraph) -> CFGIndex {
-    g.add_node(CFGNodeData { id: ast::DUMMY_NODE_ID })
-}
-
 impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
     fn block(&mut self, blk: &ast::Block, pred: CFGIndex) -> CFGIndex {
         let mut stmts_exit = pred;
@@ -74,19 +67,19 @@ fn block(&mut self, blk: &ast::Block, pred: CFGIndex) -> CFGIndex {
 
         let expr_exit = self.opt_expr(&blk.expr, stmts_exit);
 
-        self.add_node(blk.id, &[expr_exit])
+        self.add_ast_node(blk.id, &[expr_exit])
     }
 
     fn stmt(&mut self, stmt: &ast::Stmt, pred: CFGIndex) -> CFGIndex {
         match stmt.node {
             ast::StmtDecl(ref decl, id) => {
                 let exit = self.decl(&**decl, pred);
-                self.add_node(id, &[exit])
+                self.add_ast_node(id, &[exit])
             }
 
             ast::StmtExpr(ref expr, id) | ast::StmtSemi(ref expr, id) => {
                 let exit = self.expr(&**expr, pred);
-                self.add_node(id, &[exit])
+                self.add_ast_node(id, &[exit])
             }
 
             ast::StmtMac(..) => {
@@ -115,33 +108,33 @@ fn pat(&mut self, pat: &ast::Pat, pred: CFGIndex) -> CFGIndex {
             ast::PatLit(..) |
             ast::PatRange(..) |
             ast::PatWild(_) => {
-                self.add_node(pat.id, &[pred])
+                self.add_ast_node(pat.id, &[pred])
             }
 
             ast::PatBox(ref subpat) |
             ast::PatRegion(ref subpat, _) |
             ast::PatIdent(_, _, Some(ref subpat)) => {
                 let subpat_exit = self.pat(&**subpat, pred);
-                self.add_node(pat.id, &[subpat_exit])
+                self.add_ast_node(pat.id, &[subpat_exit])
             }
 
             ast::PatEnum(_, Some(ref subpats)) |
             ast::PatTup(ref subpats) => {
                 let pats_exit = self.pats_all(subpats.iter(), pred);
-                self.add_node(pat.id, &[pats_exit])
+                self.add_ast_node(pat.id, &[pats_exit])
             }
 
             ast::PatStruct(_, ref subpats, _) => {
                 let pats_exit =
                     self.pats_all(subpats.iter().map(|f| &f.node.pat), pred);
-                self.add_node(pat.id, &[pats_exit])
+                self.add_ast_node(pat.id, &[pats_exit])
             }
 
             ast::PatVec(ref pre, ref vec, ref post) => {
                 let pre_exit = self.pats_all(pre.iter(), pred);
                 let vec_exit = self.pats_all(vec.iter(), pre_exit);
                 let post_exit = self.pats_all(post.iter(), vec_exit);
-                self.add_node(pat.id, &[post_exit])
+                self.add_ast_node(pat.id, &[post_exit])
             }
 
             ast::PatMac(_) => {
@@ -157,28 +150,11 @@ fn pats_all<'b, I: Iterator<Item=&'b P<ast::Pat>>>(&mut self,
         pats.fold(pred, |pred, pat| self.pat(&**pat, pred))
     }
 
-    fn pats_any(&mut self,
-                pats: &[P<ast::Pat>],
-                pred: CFGIndex) -> CFGIndex {
-        //! Handles case where just one of the patterns must match.
-
-        if pats.len() == 1 {
-            self.pat(&*pats[0], pred)
-        } else {
-            let collect = self.add_dummy_node(&[]);
-            for pat in pats {
-                let pat_exit = self.pat(&**pat, pred);
-                self.add_contained_edge(pat_exit, collect);
-            }
-            collect
-        }
-    }
-
     fn expr(&mut self, expr: &ast::Expr, pred: CFGIndex) -> CFGIndex {
         match expr.node {
             ast::ExprBlock(ref blk) => {
                 let blk_exit = self.block(&**blk, pred);
-                self.add_node(expr.id, &[blk_exit])
+                self.add_ast_node(expr.id, &[blk_exit])
             }
 
             ast::ExprIf(ref cond, ref then, None) => {
@@ -198,7 +174,7 @@ fn expr(&mut self, expr: &ast::Expr, pred: CFGIndex) -> CFGIndex {
                 //
                 let cond_exit = self.expr(&**cond, pred);                // 1
                 let then_exit = self.block(&**then, cond_exit);          // 2
-                self.add_node(expr.id, &[cond_exit, then_exit])          // 3,4
+                self.add_ast_node(expr.id, &[cond_exit, then_exit])      // 3,4
             }
 
             ast::ExprIf(ref cond, ref then, Some(ref otherwise)) => {
@@ -219,7 +195,7 @@ fn expr(&mut self, expr: &ast::Expr, pred: CFGIndex) -> CFGIndex {
                 let cond_exit = self.expr(&**cond, pred);                // 1
                 let then_exit = self.block(&**then, cond_exit);          // 2
                 let else_exit = self.expr(&**otherwise, cond_exit);      // 3
-                self.add_node(expr.id, &[then_exit, else_exit])          // 4, 5
+                self.add_ast_node(expr.id, &[then_exit, else_exit])      // 4, 5
             }
 
             ast::ExprIfLet(..) => {
@@ -247,7 +223,7 @@ fn expr(&mut self, expr: &ast::Expr, pred: CFGIndex) -> CFGIndex {
                 // Is the condition considered part of the loop?
                 let loopback = self.add_dummy_node(&[pred]);              // 1
                 let cond_exit = self.expr(&**cond, loopback);             // 2
-                let expr_exit = self.add_node(expr.id, &[cond_exit]);     // 3
+                let expr_exit = self.add_ast_node(expr.id, &[cond_exit]); // 3
                 self.loop_scopes.push(LoopScope {
                     loop_id: expr.id,
                     continue_index: loopback,
@@ -283,7 +259,7 @@ fn expr(&mut self, expr: &ast::Expr, pred: CFGIndex) -> CFGIndex {
                 // may cause additional edges.
 
                 let loopback = self.add_dummy_node(&[pred]);              // 1
-                let expr_exit = self.add_node(expr.id, &[]);              // 2
+                let expr_exit = self.add_ast_node(expr.id, &[]);          // 2
                 self.loop_scopes.push(LoopScope {
                     loop_id: expr.id,
                     continue_index: loopback,
@@ -296,45 +272,7 @@ fn expr(&mut self, expr: &ast::Expr, pred: CFGIndex) -> CFGIndex {
             }
 
             ast::ExprMatch(ref discr, ref arms, _) => {
-                //
-                //     [pred]
-                //       |
-                //       v 1
-                //    [discr]
-                //       |
-                //       v 2
-                //    [cond1]
-                //      /  \
-                //     |    \
-                //     v 3   \
-                //  [pat1]    \
-                //     |       |
-                //     v 4     |
-                //  [guard1]   |
-                //     |       |
-                //     |       |
-                //     v 5     v
-                //  [body1]  [cond2]
-                //     |      /  \
-                //     |    ...  ...
-                //     |     |    |
-                //     v 6   v    v
-                //  [.....expr.....]
-                //
-                let discr_exit = self.expr(&**discr, pred);              // 1
-
-                let expr_exit = self.add_node(expr.id, &[]);
-                let mut cond_exit = discr_exit;
-                for arm in arms {
-                    cond_exit = self.add_dummy_node(&[cond_exit]);        // 2
-                    let pats_exit = self.pats_any(&arm.pats,
-                                                  cond_exit);            // 3
-                    let guard_exit = self.opt_expr(&arm.guard,
-                                                   pats_exit);           // 4
-                    let body_exit = self.expr(&*arm.body, guard_exit);   // 5
-                    self.add_contained_edge(body_exit, expr_exit);       // 6
-                }
-                expr_exit
+                self.match_(expr.id, &discr, &arms, pred)
             }
 
             ast::ExprBinary(op, ref l, ref r) if ast_util::lazy_binop(op.node) => {
@@ -354,30 +292,30 @@ fn expr(&mut self, expr: &ast::Expr, pred: CFGIndex) -> CFGIndex {
                 //
                 let l_exit = self.expr(&**l, pred);                      // 1
                 let r_exit = self.expr(&**r, l_exit);                    // 2
-                self.add_node(expr.id, &[l_exit, r_exit])                 // 3,4
+                self.add_ast_node(expr.id, &[l_exit, r_exit])            // 3,4
             }
 
             ast::ExprRet(ref v) => {
                 let v_exit = self.opt_expr(v, pred);
-                let b = self.add_node(expr.id, &[v_exit]);
+                let b = self.add_ast_node(expr.id, &[v_exit]);
                 self.add_returning_edge(expr, b);
-                self.add_node(ast::DUMMY_NODE_ID, &[])
+                self.add_unreachable_node()
             }
 
             ast::ExprBreak(label) => {
                 let loop_scope = self.find_scope(expr, label);
-                let b = self.add_node(expr.id, &[pred]);
+                let b = self.add_ast_node(expr.id, &[pred]);
                 self.add_exiting_edge(expr, b,
                                       loop_scope, loop_scope.break_index);
-                self.add_node(ast::DUMMY_NODE_ID, &[])
+                self.add_unreachable_node()
             }
 
             ast::ExprAgain(label) => {
                 let loop_scope = self.find_scope(expr, label);
-                let a = self.add_node(expr.id, &[pred]);
+                let a = self.add_ast_node(expr.id, &[pred]);
                 self.add_exiting_edge(expr, a,
                                       loop_scope, loop_scope.continue_index);
-                self.add_node(ast::DUMMY_NODE_ID, &[])
+                self.add_unreachable_node()
             }
 
             ast::ExprVec(ref elems) => {
@@ -454,14 +392,13 @@ fn expr(&mut self, expr: &ast::Expr, pred: CFGIndex) -> CFGIndex {
                     let &(_, ref expr, _) = a;
                     &**expr
                 }), post_inputs);
-                self.add_node(expr.id, &[post_outputs])
+                self.add_ast_node(expr.id, &[post_outputs])
             }
 
             ast::ExprMac(..) |
             ast::ExprClosure(..) |
             ast::ExprLit(..) |
-            ast::ExprPath(..) |
-            ast::ExprQPath(..) => {
+            ast::ExprPath(..) => {
                 self.straightline(expr, pred, None::<ast::Expr>.iter())
             }
         }
@@ -481,7 +418,7 @@ fn call<'b, I: Iterator<Item=&'b ast::Expr>>(&mut self,
         let func_or_rcvr_exit = self.expr(func_or_rcvr, pred);
         let ret = self.straightline(call_expr, func_or_rcvr_exit, args);
         if return_ty.diverges() {
-            self.add_node(ast::DUMMY_NODE_ID, &[])
+            self.add_unreachable_node()
         } else {
             ret
         }
@@ -508,20 +445,126 @@ fn straightline<'b, I: Iterator<Item=&'b ast::Expr>>(&mut self,
         //! Handles case of an expression that evaluates `subexprs` in order
 
         let subexprs_exit = self.exprs(subexprs, pred);
-        self.add_node(expr.id, &[subexprs_exit])
+        self.add_ast_node(expr.id, &[subexprs_exit])
+    }
+
+    fn match_(&mut self, id: ast::NodeId, discr: &ast::Expr,
+              arms: &[ast::Arm], pred: CFGIndex) -> CFGIndex {
+        // The CFG for match expression is quite complex, so no ASCII
+        // art for it (yet).
+        //
+        // The CFG generated below matches roughly what trans puts
+        // out. Each pattern and guard is visited in parallel, with
+        // arms containing multiple patterns generating multiple nodes
+        // for the same guard expression. The guard expressions chain
+        // into each other from top to bottom, with a specific
+        // exception to allow some additional valid programs
+        // (explained below). Trans differs slightly in that the
+        // pattern matching may continue after a guard but the visible
+        // behaviour should be the same.
+        //
+        // What is going on is explained in further comments.
+
+        // Visit the discriminant expression
+        let discr_exit = self.expr(discr, pred);
+
+        // Add a node for the exit of the match expression as a whole.
+        let expr_exit = self.add_ast_node(id, &[]);
+
+        // Keep track of the previous guard expressions
+        let mut prev_guards = Vec::new();
+        // Track if the previous pattern contained bindings or wildcards
+        let mut prev_has_bindings = false;
+
+        for arm in arms {
+            // Add an exit node for when we've visited all the
+            // patterns and the guard (if there is one) in the arm.
+            let arm_exit = self.add_dummy_node(&[]);
+
+            for pat in &arm.pats {
+                // Visit the pattern, coming from the discriminant exit
+                let mut pat_exit = self.pat(&**pat, discr_exit);
+
+                // If there is a guard expression, handle it here
+                if let Some(ref guard) = arm.guard {
+                    // Add a dummy node for the previous guard
+                    // expression to target
+                    let guard_start = self.add_dummy_node(&[pat_exit]);
+                    // Visit the guard expression
+                    let guard_exit = self.expr(&**guard, guard_start);
+
+                    let this_has_bindings = pat_util::pat_contains_bindings_or_wild(
+                        &self.tcx.def_map, &**pat);
+
+                    // If both this pattern and the previous pattern
+                    // were free of bindings, they must consist only
+                    // of "constant" patterns. Note we cannot match an
+                    // all-constant pattern, fail the guard, and then
+                    // match *another* all-constant pattern. This is
+                    // because if the previous pattern matches, then
+                    // we *cannot* match this one, unless all the
+                    // constants are the same (which is rejected by
+                    // `check_match`).
+                    //
+                    // We can use this to be smarter about the flow
+                    // along guards. If the previous pattern matched,
+                    // then we know we will not visit the guard in
+                    // this one (whether or not the guard succeeded),
+                    // if the previous pattern failed, then we know
+                    // the guard for that pattern will not have been
+                    // visited. Thus, it is not possible to visit both
+                    // the previous guard and the current one when
+                    // both patterns consist only of constant
+                    // sub-patterns.
+                    //
+                    // However, if the above does not hold, then all
+                    // previous guards need to be wired to visit the
+                    // current guard pattern.
+                    if prev_has_bindings || this_has_bindings {
+                        while let Some(prev) = prev_guards.pop() {
+                            self.add_contained_edge(prev, guard_start);
+                        }
+                    }
+
+                    prev_has_bindings = this_has_bindings;
+
+                    // Push the guard onto the list of previous guards
+                    prev_guards.push(guard_exit);
+
+                    // Update the exit node for the pattern
+                    pat_exit = guard_exit;
+                }
+
+                // Add an edge from the exit of this pattern to the
+                // exit of the arm
+                self.add_contained_edge(pat_exit, arm_exit);
+            }
+
+            // Visit the body of this arm
+            let body_exit = self.expr(&arm.body, arm_exit);
+
+            // Link the body to the exit of the expression
+            self.add_contained_edge(body_exit, expr_exit);
+        }
+
+        expr_exit
     }
 
     fn add_dummy_node(&mut self, preds: &[CFGIndex]) -> CFGIndex {
-        self.add_node(ast::DUMMY_NODE_ID, preds)
+        self.add_node(CFGNodeData::Dummy, preds)
     }
 
-    fn add_node(&mut self, id: ast::NodeId, preds: &[CFGIndex]) -> CFGIndex {
-        assert!(!self.exit_map.contains_key(&id));
-        let node = self.graph.add_node(CFGNodeData {id: id});
-        if id != ast::DUMMY_NODE_ID {
-            assert!(!self.exit_map.contains_key(&id));
-            self.exit_map.insert(id, node);
-        }
+    fn add_ast_node(&mut self, id: ast::NodeId, preds: &[CFGIndex]) -> CFGIndex {
+        assert!(id != ast::DUMMY_NODE_ID);
+        self.add_node(CFGNodeData::AST(id), preds)
+    }
+
+    fn add_unreachable_node(&mut self) -> CFGIndex {
+        self.add_node(CFGNodeData::Unreachable, &[])
+    }
+
+    fn add_node(&mut self, data: CFGNodeData, preds: &[CFGIndex]) -> CFGIndex {
+        let node = self.graph.add_node(data);
         for &pred in preds {
             self.add_contained_edge(pred, node);
         }
@@ -566,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 14c6ff01e0e66d9384732a159c0eda97647052bb..0c5eca3c12968ee3b93d6b31371109271ef572c0 100644 (file)
@@ -65,10 +65,10 @@ fn node_label(&'a self, &(i, n): &Node<'a>) -> dot::LabelText<'a> {
             dot::LabelText::LabelStr("entry".into_cow())
         } else if i == self.cfg.exit {
             dot::LabelText::LabelStr("exit".into_cow())
-        } else if n.data.id == ast::DUMMY_NODE_ID {
+        } else if n.data.id() == ast::DUMMY_NODE_ID {
             dot::LabelText::LabelStr("(dummy_node)".into_cow())
         } else {
-            let s = self.ast_map.node_to_string(n.data.id);
+            let s = self.ast_map.node_to_string(n.data.id());
             // left-aligns the lines
             let s = replace_newline_with_backslash_l(s);
             dot::LabelText::EscStr(s.into_cow())
index 0ca146a295e139a95712377578205699febcae97..e8a99f59b1e95b365c9c0e4184757608978b8638 100644 (file)
 use middle::graph;
 use middle::ty;
 use syntax::ast;
-use util::nodemap::NodeMap;
 
 mod construct;
 pub mod graphviz;
 
 pub struct CFG {
-    pub exit_map: NodeMap<CFGIndex>,
     pub graph: CFGGraph,
     pub entry: CFGIndex,
     pub exit: CFGIndex,
 }
 
-#[derive(Copy)]
-pub struct CFGNodeData {
-    pub id: ast::NodeId
+#[derive(Copy, PartialEq)]
+pub enum CFGNodeData {
+    AST(ast::NodeId),
+    Entry,
+    Exit,
+    Dummy,
+    Unreachable,
+}
+
+impl CFGNodeData {
+    pub fn id(&self) -> ast::NodeId {
+        if let CFGNodeData::AST(id) = *self {
+            id
+        } else {
+            ast::DUMMY_NODE_ID
+        }
+    }
 }
 
 pub struct CFGEdgeData {
@@ -50,6 +62,6 @@ pub fn new(tcx: &ty::ctxt,
     }
 
     pub fn node_is_reachable(&self, id: ast::NodeId) -> bool {
-        self.graph.depth_traverse(self.entry).any(|node| node.id == id)
+        self.graph.depth_traverse(self.entry).any(|node| node.id() == id)
     }
 }
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 cf33cd71365789ccd6b62d32b5c28ff225662dcf..1718df702553f0f94886f0b365fd880ad55ad439 100644 (file)
@@ -53,7 +53,7 @@ pub struct DataFlowContext<'a, 'tcx: 'a, O> {
 
     // mapping from node to cfg node index
     // FIXME (#6298): Shouldn't this go with CFG?
-    nodeid_to_index: NodeMap<CFGIndex>,
+    nodeid_to_index: NodeMap<Vec<CFGIndex>>,
 
     // Bit sets per cfg node.  The following three fields (`gens`, `kills`,
     // and `on_entry`) all have the same structure. For each id in
@@ -88,11 +88,9 @@ struct PropagationContext<'a, 'b: 'a, 'tcx: 'b, O: 'a> {
     changed: bool
 }
 
-fn to_cfgidx_or_die(id: ast::NodeId, index: &NodeMap<CFGIndex>) -> CFGIndex {
-    let opt_cfgindex = index.get(&id).cloned();
-    opt_cfgindex.unwrap_or_else(|| {
-        panic!("nodeid_to_index does not have entry for NodeId {}", id);
-    })
+fn get_cfg_indices<'a>(id: ast::NodeId, index: &'a NodeMap<Vec<CFGIndex>>) -> &'a [CFGIndex] {
+    let opt_indices = index.get(&id);
+    opt_indices.map(|v| &v[..]).unwrap_or(&[])
 }
 
 impl<'a, 'tcx, O:DataFlowOperator> DataFlowContext<'a, 'tcx, O> {
@@ -114,9 +112,13 @@ fn pre(&self,
             pprust::NodePat(pat) => pat.id
         };
 
-        if self.has_bitset_for_nodeid(id) {
-            assert!(self.bits_per_id > 0);
-            let cfgidx = to_cfgidx_or_die(id, &self.nodeid_to_index);
+        if !self.has_bitset_for_nodeid(id) {
+            return Ok(());
+        }
+
+        assert!(self.bits_per_id > 0);
+        let indices = get_cfg_indices(id, &self.nodeid_to_index);
+        for &cfgidx in indices {
             let (start, end) = self.compute_id_range(cfgidx);
             let on_entry = &self.on_entry[start.. end];
             let entry_str = bits_to_string(on_entry);
@@ -144,7 +146,7 @@ fn pre(&self,
 }
 
 fn build_nodeid_to_index(decl: Option<&ast::FnDecl>,
-                         cfg: &cfg::CFG) -> NodeMap<CFGIndex> {
+                         cfg: &cfg::CFG) -> NodeMap<Vec<CFGIndex>> {
     let mut index = NodeMap();
 
     // FIXME (#6298): Would it be better to fold formals from decl
@@ -157,28 +159,38 @@ fn build_nodeid_to_index(decl: Option<&ast::FnDecl>,
     }
 
     cfg.graph.each_node(|node_idx, node| {
-        if node.data.id != ast::DUMMY_NODE_ID {
-            index.insert(node.data.id, node_idx);
+        if let cfg::CFGNodeData::AST(id) = node.data {
+            match index.entry(id).get() {
+                Ok(v) => v.push(node_idx),
+                Err(e) => {
+                    e.insert(vec![node_idx]);
+                }
+            }
         }
         true
     });
 
     return index;
 
-    fn add_entries_from_fn_decl(index: &mut NodeMap<CFGIndex>,
+    fn add_entries_from_fn_decl(index: &mut NodeMap<Vec<CFGIndex>>,
                                 decl: &ast::FnDecl,
                                 entry: CFGIndex) {
         //! add mappings from the ast nodes for the formal bindings to
         //! the entry-node in the graph.
         struct Formals<'a> {
             entry: CFGIndex,
-            index: &'a mut NodeMap<CFGIndex>,
+            index: &'a mut NodeMap<Vec<CFGIndex>>,
         }
         let mut formals = Formals { entry: entry, index: index };
         visit::walk_fn_decl(&mut formals, decl);
         impl<'a, 'v> visit::Visitor<'v> for Formals<'a> {
             fn visit_pat(&mut self, p: &ast::Pat) {
-                self.index.insert(p.id, self.entry);
+                match self.index.entry(p.id).get() {
+                    Ok(v) => v.push(self.entry),
+                    Err(e) => {
+                        e.insert(vec![self.entry]);
+                    }
+                }
                 visit::walk_pat(self, p)
             }
         }
@@ -230,10 +242,12 @@ pub fn add_gen(&mut self, id: ast::NodeId, bit: uint) {
         assert!(self.nodeid_to_index.contains_key(&id));
         assert!(self.bits_per_id > 0);
 
-        let cfgidx = to_cfgidx_or_die(id, &self.nodeid_to_index);
-        let (start, end) = self.compute_id_range(cfgidx);
-        let gens = &mut self.gens[start.. end];
-        set_bit(gens, bit);
+        let indices = get_cfg_indices(id, &self.nodeid_to_index);
+        for &cfgidx in indices {
+            let (start, end) = self.compute_id_range(cfgidx);
+            let gens = &mut self.gens[start.. end];
+            set_bit(gens, bit);
+        }
     }
 
     pub fn add_kill(&mut self, id: ast::NodeId, bit: uint) {
@@ -243,10 +257,12 @@ pub fn add_kill(&mut self, id: ast::NodeId, bit: uint) {
         assert!(self.nodeid_to_index.contains_key(&id));
         assert!(self.bits_per_id > 0);
 
-        let cfgidx = to_cfgidx_or_die(id, &self.nodeid_to_index);
-        let (start, end) = self.compute_id_range(cfgidx);
-        let kills = &mut self.kills[start.. end];
-        set_bit(kills, bit);
+        let indices = get_cfg_indices(id, &self.nodeid_to_index);
+        for &cfgidx in indices {
+            let (start, end) = self.compute_id_range(cfgidx);
+            let kills = &mut self.kills[start.. end];
+            set_bit(kills, bit);
+        }
     }
 
     fn apply_gen_kill(&self, cfgidx: CFGIndex, bits: &mut [uint]) {
@@ -279,7 +295,7 @@ fn compute_id_range(&self, cfgidx: CFGIndex) -> (uint, uint) {
     }
 
 
-    pub fn each_bit_on_entry<F>(&self, id: ast::NodeId, f: F) -> bool where
+    pub fn each_bit_on_entry<F>(&self, id: ast::NodeId, mut f: F) -> bool where
         F: FnMut(uint) -> bool,
     {
         //! Iterates through each bit that is set on entry to `id`.
@@ -287,8 +303,13 @@ pub fn each_bit_on_entry<F>(&self, id: ast::NodeId, f: F) -> bool where
         if !self.has_bitset_for_nodeid(id) {
             return true;
         }
-        let cfgidx = to_cfgidx_or_die(id, &self.nodeid_to_index);
-        self.each_bit_for_node(Entry, cfgidx, f)
+        let indices = get_cfg_indices(id, &self.nodeid_to_index);
+        for &cfgidx in indices {
+            if !self.each_bit_for_node(Entry, cfgidx, |i| f(i)) {
+                return false;
+            }
+        }
+        return true;
     }
 
     pub fn each_bit_for_node<F>(&self, e: EntryOrExit, cfgidx: CFGIndex, f: F) -> bool where
@@ -320,7 +341,7 @@ pub fn each_bit_for_node<F>(&self, e: EntryOrExit, cfgidx: CFGIndex, f: F) -> bo
         self.each_bit(slice, f)
     }
 
-    pub fn each_gen_bit<F>(&self, id: ast::NodeId, f: F) -> bool where
+    pub fn each_gen_bit<F>(&self, id: ast::NodeId, mut f: F) -> bool where
         F: FnMut(uint) -> bool,
     {
         //! Iterates through each bit in the gen set for `id`.
@@ -334,12 +355,17 @@ pub fn each_gen_bit<F>(&self, id: ast::NodeId, f: F) -> bool where
             return true;
         }
 
-        let cfgidx = to_cfgidx_or_die(id, &self.nodeid_to_index);
-        let (start, end) = self.compute_id_range(cfgidx);
-        let gens = &self.gens[start.. end];
-        debug!("{} each_gen_bit(id={}, gens={})",
-               self.analysis_name, id, bits_to_string(gens));
-        self.each_bit(gens, f)
+        let indices = get_cfg_indices(id, &self.nodeid_to_index);
+        for &cfgidx in indices {
+            let (start, end) = self.compute_id_range(cfgidx);
+            let gens = &self.gens[start.. end];
+            debug!("{} each_gen_bit(id={}, gens={})",
+                   self.analysis_name, id, bits_to_string(gens));
+            if !self.each_bit(gens, |i| f(i)) {
+                return false;
+            }
+        }
+        return true;
     }
 
     fn each_bit<F>(&self, words: &[uint], mut f: F) -> bool where
@@ -400,13 +426,15 @@ pub fn add_kills_from_flow_exits(&mut self, cfg: &cfg::CFG) {
 
             let mut changed = false;
             for &node_id in &edge.data.exiting_scopes {
-                let opt_cfg_idx = self.nodeid_to_index.get(&node_id).cloned();
+                let opt_cfg_idx = self.nodeid_to_index.get(&node_id);
                 match opt_cfg_idx {
-                    Some(cfg_idx) => {
-                        let (start, end) = self.compute_id_range(cfg_idx);
-                        let kills = &self.kills[start.. end];
-                        if bitwise(&mut orig_kills, kills, &Union) {
-                            changed = true;
+                    Some(indices) => {
+                        for &cfg_idx in indices {
+                            let (start, end) = self.compute_id_range(cfg_idx);
+                            let kills = &self.kills[start.. end];
+                            if bitwise(&mut orig_kills, kills, &Union) {
+                                changed = true;
+                            }
                         }
                     }
                     None => {
@@ -482,7 +510,7 @@ fn walk_cfg(&mut self,
 
         cfg.graph.each_node(|node_index, node| {
             debug!("DataFlowContext::walk_cfg idx={:?} id={} begin in_out={}",
-                   node_index, node.data.id, bits_to_string(in_out));
+                   node_index, node.data.id(), bits_to_string(in_out));
 
             let (start, end) = self.dfcx.compute_id_range(node_index);
 
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 b33e5a802f1582f6a639431938abaf3c026d8709..7584a2e44cc7c0b3316be2718c153705e530ec03 100644 (file)
@@ -93,7 +93,7 @@ pub fn simplify_type(tcx: &ty::ctxt,
                 None
             }
         }
-        ty::ty_open(_) | ty::ty_infer(_) | ty::ty_err => None,
+        ty::ty_infer(_) | ty::ty_err => None,
     }
 }
 
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 1b7e6c33c0575f723d341ec8373005765a0c5147..e41b949d5df1d75cb98d80b57fccc83bb79a76eb 100644 (file)
@@ -135,7 +135,6 @@ fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
                 t
             }
 
-            ty::ty_open(..) |
             ty::ty_bool |
             ty::ty_char |
             ty::ty_int(..) |
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 01dc55c3eeec0433b41fe45073e8231cb55cfcb8..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
             }
         }
@@ -119,6 +119,21 @@ pub fn pat_contains_bindings(dm: &DefMap, pat: &ast::Pat) -> bool {
     contains_bindings
 }
 
+/// Checks if the pattern contains any patterns that bind something to
+/// an ident or wildcard, e.g. `foo`, or `Foo(_)`, `foo @ Bar(..)`,
+pub fn pat_contains_bindings_or_wild(dm: &DefMap, pat: &ast::Pat) -> bool {
+    let mut contains_bindings = false;
+    walk_pat(pat, |p| {
+        if pat_is_binding_or_wild(dm, p) {
+            contains_bindings = true;
+            false // there's at least one binding/wildcard, can short circuit now.
+        } else {
+            true
+        }
+    });
+    contains_bindings
+}
+
 pub fn simple_identifier<'a>(pat: &'a ast::Pat) -> Option<&'a ast::Ident> {
     match pat.node {
         ast::PatIdent(ast::BindByValue(_), ref path1, None) => {
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 9ef4a436b8d027b7093178d05c11338bc37ba9f0..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
@@ -194,7 +211,6 @@ fn ty_is_local_constructor<'tcx>(tcx: &ty::ctxt<'tcx>, ty: Ty<'tcx>) -> bool {
 
         ty::ty_closure(..) |
         ty::ty_infer(..) |
-        ty::ty_open(..) |
         ty::ty_err => {
             tcx.sess.bug(
                 &format!("ty_is_local invoked on unexpected type: {}",
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 f10f7eb3951c7a0468a3a5e86367e9d4c024060f..64835a666faef46d6fe23c518d88108d5dbe7663 100644 (file)
@@ -42,9 +42,6 @@ pub enum ObjectSafetyViolation<'tcx> {
 /// Reasons a method might not be object-safe.
 #[derive(Copy,Clone,Debug)]
 pub enum MethodViolationCode {
-    /// e.g., `fn(self)`
-    ByValueSelf,
-
     /// e.g., `fn foo()`
     StaticMethod,
 
@@ -157,6 +154,16 @@ fn supertraits_reference_self<'tcx>(tcx: &ty::ctxt<'tcx>,
 fn trait_has_sized_self<'tcx>(tcx: &ty::ctxt<'tcx>,
                               trait_def_id: ast::DefId)
                               -> bool
+{
+    let trait_def = ty::lookup_trait_def(tcx, trait_def_id);
+    let trait_predicates = ty::lookup_predicates(tcx, trait_def_id);
+    generics_require_sized_self(tcx, &trait_def.generics, &trait_predicates)
+}
+
+fn generics_require_sized_self<'tcx>(tcx: &ty::ctxt<'tcx>,
+                                     generics: &ty::Generics<'tcx>,
+                                     predicates: &ty::GenericPredicates<'tcx>)
+                                     -> bool
 {
     let sized_def_id = match tcx.lang_items.sized_trait() {
         Some(def_id) => def_id,
@@ -164,12 +171,8 @@ fn trait_has_sized_self<'tcx>(tcx: &ty::ctxt<'tcx>,
     };
 
     // Search for a predicate like `Self : Sized` amongst the trait bounds.
-    let trait_def = ty::lookup_trait_def(tcx, trait_def_id);
-    let free_substs = ty::construct_free_substs(tcx, &trait_def.generics, ast::DUMMY_NODE_ID);
-
-    let trait_predicates = ty::lookup_predicates(tcx, trait_def_id);
-    let predicates = trait_predicates.instantiate(tcx, &free_substs).predicates.into_vec();
-
+    let free_substs = ty::construct_free_substs(tcx, generics, ast::DUMMY_NODE_ID);
+    let predicates = predicates.instantiate(tcx, &free_substs).predicates.into_vec();
     elaborate_predicates(tcx, predicates)
         .any(|predicate| {
             match predicate {
@@ -192,17 +195,21 @@ fn object_safety_violations_for_method<'tcx>(tcx: &ty::ctxt<'tcx>,
                                              method: &ty::Method<'tcx>)
                                              -> Option<MethodViolationCode>
 {
-    // The method's first parameter must be something that derefs to
-    // `&self`. For now, we only accept `&self` and `Box<Self>`.
-    match method.explicit_self {
-        ty::ByValueExplicitSelfCategory => {
-            return Some(MethodViolationCode::ByValueSelf);
-        }
+    // Any method that has a `Self : Sized` requisite is otherwise
+    // exempt from the regulations.
+    if generics_require_sized_self(tcx, &method.generics, &method.predicates) {
+        return None;
+    }
 
+    // The method's first parameter must be something that derefs (or
+    // autorefs) to `&self`. For now, we only accept `self`, `&self`
+    // and `Box<Self>`.
+    match method.explicit_self {
         ty::StaticExplicitSelfCategory => {
             return Some(MethodViolationCode::StaticMethod);
         }
 
+        ty::ByValueExplicitSelfCategory |
         ty::ByReferenceExplicitSelfCategory(..) |
         ty::ByBoxExplicitSelfCategory => {
         }
index daf7e50e1bc9abee31e9c790378b88a31d52aec1..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,31 +1602,10 @@ fn builtin_bound(&mut self,
                 Ok(AmbiguousBuiltin)
             }
 
-            ty::ty_open(ty) => {
-                // these only crop up in trans, and represent an
-                // "opened" unsized/existential type (one that has
-                // been dereferenced)
-                match bound {
-                    ty::BoundCopy => {
-                        Ok(If(vec!(ty)))
-                    }
-
-                    ty::BoundSized => {
-                        Err(Unimplemented)
-                    }
-
-                    ty::BoundSync |
-                    ty::BoundSend => {
-                        self.tcx().sess.bug("Send/Sync shouldn't occur in builtin_bounds()");
-                    }
-                }
-            }
-            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: {}",
@@ -1660,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 {
@@ -1711,15 +1666,13 @@ 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>
                 Some(vec![referent_ty])
             }
 
-            ty::ty_open(element_ty) => {Some(vec![element_ty])},
-
             ty::ty_ptr(ty::mt { ty: element_ty, ..}) |
             ty::ty_rptr(_, ty::mt { ty: element_ty, ..}) => {
                 Some(vec![element_ty])
@@ -1930,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());
@@ -1958,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())));
             }
         }
     }
@@ -2244,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",
@@ -2294,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,
@@ -2353,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())
     }
 
@@ -2472,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(),
         }
     }
 
@@ -2570,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))
             }
@@ -2603,9 +2544,7 @@ fn next(&mut self) -> Option<&'o TraitObligationStack<'o, 'tcx>> {
                 *self = o.previous;
                 Some(o)
             }
-            None => {
-                None
-            }
+            None => None
         }
     }
 }
@@ -2620,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 a461297dd95534b3cff50054f351dc97894a9f9a..17ac7605741bfc205c4f74b784aa40b3237c0fc7 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
@@ -930,7 +930,7 @@ pub fn print_debug_stats(&self) {
         sty_debug_print!(
             self,
             ty_enum, ty_uniq, ty_vec, ty_ptr, ty_rptr, ty_bare_fn, ty_trait,
-            ty_struct, ty_closure, ty_tup, ty_param, ty_open, ty_infer, ty_projection);
+            ty_struct, ty_closure, ty_tup, ty_param, ty_infer, ty_projection);
 
         println!("Substs interner: #{}", self.substs_interner.borrow().len());
         println!("BareFnTy interner: #{}", self.bare_fn_interner.borrow().len());
@@ -1374,12 +1374,6 @@ pub enum sty<'tcx> {
     ty_projection(ProjectionTy<'tcx>),
     ty_param(ParamTy), // type parameter
 
-    ty_open(Ty<'tcx>), // A deref'ed fat pointer, i.e., a dynamically sized value
-                       // and its size. Only ever used in trans. It is not necessary
-                       // earlier since we don't need to distinguish a DST with its
-                       // size (e.g., in a deref) vs a DST with the size elsewhere (
-                       // e.g., in a field).
-
     ty_infer(InferTy), // something used only during inference/typeck
     ty_err, // Also only used during inference/typeck, to represent
             // the type of an erroneous expression (helps cut down
@@ -1756,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>,
 }
@@ -2429,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>,
@@ -2451,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()),
@@ -2552,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,
@@ -2689,7 +2689,7 @@ fn add_sty(&mut self, st: &sty) {
                 self.add_bounds(bounds);
             }
 
-            &ty_uniq(tt) | &ty_vec(tt, _) | &ty_open(tt) => {
+            &ty_uniq(tt) | &ty_vec(tt, _) => {
                 self.add_ty(tt)
             }
 
@@ -2964,8 +2964,6 @@ pub fn mk_param_from_def<'tcx>(cx: &ctxt<'tcx>, def: &TypeParameterDef) -> Ty<'t
     mk_param(cx, def.space, def.index, def.name)
 }
 
-pub fn mk_open<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> { mk_t(cx, ty_open(ty)) }
-
 impl<'tcx> TyS<'tcx> {
     /// Iterator that walks `self` and any types reachable from
     /// `self`, in depth-first order. Note that just walks the types
@@ -3004,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)
@@ -3164,7 +3169,6 @@ pub fn sequence_element_type<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> {
     match ty.sty {
         ty_vec(ty, _) => ty,
         ty_str => mk_mach_uint(cx, ast::TyU8),
-        ty_open(ty) => sequence_element_type(cx, ty),
         _ => cx.sess.bug(&format!("sequence_element_type called on non-sequence value: {}",
                                  ty_to_string(cx, ty))),
     }
@@ -3583,12 +3587,6 @@ fn tc_ty<'tcx>(cx: &ctxt<'tcx>,
                 TC::All
             }
 
-            ty_open(ty) => {
-                let result = tc_ty(cx, ty, cache);
-                assert!(!result.is_sized(cx));
-                result.unsafe_pointer() | TC::Nonsized
-            }
-
             ty_infer(_) |
             ty_err => {
                 cx.sess.bug("asked to compute contents of error type");
@@ -3747,7 +3745,7 @@ fn subtypes_require<'tcx>(cx: &ctxt<'tcx>, seen: &mut Vec<DefId>,
             ty_vec(_, None) => {
                 false
             }
-            ty_uniq(typ) | ty_open(typ) => {
+            ty_uniq(typ) => {
                 type_requires(cx, seen, r_ty, typ)
             }
             ty_rptr(_, ref mt) => {
@@ -4106,14 +4104,6 @@ pub fn deref<'tcx>(ty: Ty<'tcx>, explicit: bool) -> Option<mt<'tcx>> {
     }
 }
 
-pub fn close_type<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> {
-    match ty.sty {
-        ty_open(ty) => mk_rptr(cx, cx.mk_region(ReStatic), mt {ty: ty, mutbl:ast::MutImmutable}),
-        _ => cx.sess.bug(&format!("Trying to close a non-open type {}",
-                                 ty_to_string(cx, ty)))
-    }
-}
-
 pub fn type_content<'tcx>(ty: Ty<'tcx>) -> Ty<'tcx> {
     match ty.sty {
         ty_uniq(ty) => ty,
@@ -4122,14 +4112,6 @@ pub fn type_content<'tcx>(ty: Ty<'tcx>) -> Ty<'tcx> {
     }
 }
 
-// Extract the unsized type in an open type (or just return ty if it is not open).
-pub fn unopen_type<'tcx>(ty: Ty<'tcx>) -> Ty<'tcx> {
-    match ty.sty {
-        ty_open(ty) => ty,
-        _ => ty
-    }
-}
-
 // Returns the type of ty[i]
 pub fn index<'tcx>(ty: Ty<'tcx>) -> Option<Ty<'tcx>> {
     match ty.sty {
@@ -4205,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)))
     }
 }
@@ -4316,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.
@@ -4533,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));
@@ -4581,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);
@@ -4612,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
@@ -4716,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 {
@@ -4802,7 +4786,6 @@ pub fn ty_sort_string<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> String {
             }
         }
         ty_err => "type error".to_string(),
-        ty_open(_) => "opened DST".to_string(),
     }
 }
 
@@ -5148,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)
@@ -5175,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(
@@ -5880,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,
                     ..
@@ -6328,16 +6299,15 @@ macro_rules! hash { ($e:expr) => { $e.hash(state) }  }
                     hash!(p.idx);
                     hash!(token::get_name(p.name));
                 }
-                ty_open(_) => byte!(22),
                 ty_infer(_) => unreachable!(),
-                ty_err => byte!(23),
+                ty_err => byte!(21),
                 ty_closure(d, r, _) => {
-                    byte!(24);
+                    byte!(22);
                     did(state, d);
                     region(state, *r);
                 }
                 ty_projection(ref data) => {
-                    byte!(25);
+                    byte!(23);
                     did(state, data.trait_ref.def_id);
                     hash!(token::get_name(data.item_name));
                 }
@@ -6666,7 +6636,6 @@ pub fn accumulate_lifetimes_in_type(accumulator: &mut Vec<ty::Region>,
             ty_projection(_) |
             ty_param(_) |
             ty_infer(_) |
-            ty_open(_) |
             ty_err => {
             }
         }
index 92b0ea905accf96e1dc831ce3fec05ec333e9dd9..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),
         }
@@ -626,9 +625,6 @@ pub fn super_fold_ty<'tcx, T: TypeFolder<'tcx>>(this: &mut T,
         ty::ty_vec(typ, sz) => {
             ty::ty_vec(typ.fold_with(this), sz)
         }
-        ty::ty_open(typ) => {
-            ty::ty_open(typ.fold_with(this))
-        }
         ty::ty_enum(tid, ref substs) => {
             let substs = substs.fold_with(this);
             ty::ty_enum(tid, this.tcx().mk_substs(substs))
index 40dfd479364a6c18c76f960518bef48a3e87777b..3336e7ee8bf71e6186107a989782913d8dd13f2f 100644 (file)
@@ -28,7 +28,7 @@ fn push_subtypes(&mut self, parent_ty: Ty<'tcx>) {
             ty::ty_bool | ty::ty_char | ty::ty_int(_) | ty::ty_uint(_) | ty::ty_float(_) |
             ty::ty_str | ty::ty_infer(_) | ty::ty_param(_) | ty::ty_err => {
             }
-            ty::ty_uniq(ty) | ty::ty_vec(ty, _) | ty::ty_open(ty) => {
+            ty::ty_uniq(ty) | ty::ty_vec(ty, _) => {
                 self.stack.push(ty);
             }
             ty::ty_ptr(ref mt) | ty::ty_rptr(_, ref mt) => {
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..99b2fce0607686193070e53e859611f6f4efd639 100644 (file)
@@ -27,8 +27,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 +74,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 +356,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 +379,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()),
index 23b63bc26657c6519e0ed39b295ec09f0d33e019..15b3c6d9d0602c7ed65a0ce39c560de1e99f4414 100644 (file)
@@ -20,7 +20,7 @@
 use middle::ty::{mt, Ty, ParamTy};
 use middle::ty::{ty_bool, ty_char, ty_struct, ty_enum};
 use middle::ty::{ty_err, ty_str, ty_vec, ty_float, ty_bare_fn};
-use middle::ty::{ty_param, ty_ptr, ty_rptr, ty_tup, ty_open};
+use middle::ty::{ty_param, ty_ptr, ty_rptr, ty_tup};
 use middle::ty::{ty_closure};
 use middle::ty::{ty_uniq, ty_trait, ty_int, ty_uint, ty_infer};
 use middle::ty;
@@ -369,8 +369,6 @@ fn infer_ty_to_string(cx: &ctxt, ty: ty::InferTy) -> String {
             buf.push_str(&mt_to_string(cx, tm));
             buf
         }
-        ty_open(typ) =>
-            format!("opened<{}>", ty_to_string(cx, typ)),
         ty_tup(ref elems) => {
             let strs = elems
                 .iter()
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 42220a87bd414891ea17830790cdfcdeefeaeb9d..759147b939cb850a5f84279de7d8859e850c9c9d 100644 (file)
@@ -20,6 +20,11 @@ pub fn opts() -> TargetOptions {
         linker_is_gnu: true,
         has_rpath: true,
         pre_link_args: vec!(
+            // GNU-style linkers will use this to omit linking to libraries
+            // which don't actually fulfill any relocations, but only for
+            // libraries which follow this flag.  Thus, use it before
+            // specifying libraries to link to.
+            "-Wl,--as-needed".to_string(),
         ),
         position_independent_executables: true,
         .. Default::default()
index fd7880212f10b24e292a738d94fdcaaec4a36993..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.
@@ -612,13 +612,26 @@ pub fn report_use_of_moved_value<'b>(&self,
                 };
                 let (suggestion, _) =
                     move_suggestion(param_env, expr_span, expr_ty, ("moved by default", ""));
-                self.tcx.sess.span_note(
-                    expr_span,
-                    &format!("`{}` moved here{} because it has type `{}`, which is {}",
-                            ol,
-                            moved_lp_msg,
-                            expr_ty.user_string(self.tcx),
-                            suggestion));
+                // If the two spans are the same, it's because the expression will be evaluated
+                // multiple times. Avoid printing the same span and adjust the wording so it makes
+                // more sense that it's from multiple evalutations.
+                if expr_span == use_span {
+                    self.tcx.sess.note(
+                        &format!("`{}` was previously moved here{} because it has type `{}`, \
+                                  which is {}",
+                                 ol,
+                                 moved_lp_msg,
+                                 expr_ty.user_string(self.tcx),
+                                 suggestion));
+                } else {
+                    self.tcx.sess.span_note(
+                        expr_span,
+                        &format!("`{}` moved here{} because it has type `{}`, which is {}",
+                                 ol,
+                                 moved_lp_msg,
+                                 expr_ty.user_string(self.tcx),
+                                 suggestion));
+                }
             }
 
             move_data::MovePat => {
index 4465000d8d81e1298111ca0129d58034aa96e98b..a2c9930c0ed2fdc36f4469af01af05eb292f4c28 100644 (file)
@@ -52,7 +52,7 @@ pub struct DataflowLabeller<'a, 'tcx: 'a> {
 
 impl<'a, 'tcx> DataflowLabeller<'a, 'tcx> {
     fn dataflow_for(&self, e: EntryOrExit, n: &Node<'a>) -> String {
-        let id = n.1.data.id;
+        let id = n.1.data.id();
         debug!("dataflow_for({:?}, id={}) {:?}", e, id, self.variants);
         let mut sets = "".to_string();
         let mut seen_one = false;
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 cdcc9850e423e3477d919246999a3deb5c2ee943..d9cedc482985155e84445cc947292d222e412359 100644 (file)
@@ -806,11 +806,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);
     })
 }
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..95523be68c3bf9ffa3ec594ca0c3202db98e267f 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 1a24b3fabf898c8de62de4cd0fb3a591de07847a..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);
@@ -678,7 +678,7 @@ fn bind_subslice_pat(bcx: Block,
 }
 
 fn extract_vec_elems<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
-                                 left_ty: Ty,
+                                 left_ty: Ty<'tcx>,
                                  before: uint,
                                  after: uint,
                                  val: ValueRef)
@@ -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 903de940207702062ecce6312bf7a1318688979c..3ea14d3c58929dd5967c0a9893bb29a7e1233ca8 100644 (file)
@@ -699,7 +699,7 @@ fn struct_llfields<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, st: &Struct<'tcx>,
         st.fields.iter().filter(|&ty| !dst || type_is_sized(cx.tcx(), *ty))
             .map(|&ty| type_of::sizing_type_of(cx, ty)).collect()
     } else {
-        st.fields.iter().map(|&ty| type_of::type_of(cx, ty)).collect()
+        st.fields.iter().map(|&ty| type_of::in_memory_type_of(cx, ty)).collect()
     }
 }
 
index 35b6ca7f0f5114770e90555d0b47926c6bcad8d4..b18b7b75d32fc1fc65acd2980779716b1d74ec33 100644 (file)
@@ -676,8 +676,7 @@ fn iter_variant<'blk, 'tcx, F>(cx: Block<'blk, 'tcx>,
                   let val = if common::type_is_sized(cx.tcx(), field_ty) {
                       llfld_a
                   } else {
-                      let boxed_ty = ty::mk_open(cx.tcx(), field_ty);
-                      let scratch = datum::rvalue_scratch_datum(cx, boxed_ty, "__fat_ptr_iter");
+                      let scratch = datum::rvalue_scratch_datum(cx, field_ty, "__fat_ptr_iter");
                       Store(cx, llfld_a, GEPi(cx, scratch.val, &[0, abi::FAT_PTR_ADDR]));
                       Store(cx, info.unwrap(), GEPi(cx, scratch.val, &[0, abi::FAT_PTR_EXTRA]));
                       scratch.val
@@ -1353,7 +1352,7 @@ fn build_cfg(tcx: &ty::ctxt, id: ast::NodeId) -> (ast::NodeId, Option<cfg::CFG>)
 // the clobbering of the existing value in the return slot.
 fn has_nested_returns(tcx: &ty::ctxt, cfg: &cfg::CFG, blk_id: ast::NodeId) -> bool {
     for n in cfg.graph.depth_traverse(cfg.entry) {
-        match tcx.map.find(n.id) {
+        match tcx.map.find(n.id()) {
             Some(ast_map::NodeExpr(ex)) => {
                 if let ast::ExprRet(Some(ref ret_expr)) = ex.node {
                     let mut visitor = FindNestedReturn::new();
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 e92960ec7cdca9b6968ff52a2a57b5f393786a95..ec7ed2fe89017476a9ed7290c906128365b92a82 100644 (file)
@@ -120,14 +120,16 @@ fn fold_substs(&mut self,
 // Is the type's representation size known at compile time?
 pub fn type_is_sized<'tcx>(tcx: &ty::ctxt<'tcx>, ty: Ty<'tcx>) -> bool {
     let param_env = ty::empty_parameter_environment(tcx);
-    ty::type_is_sized(&param_env, DUMMY_SP, ty)
-}
-
-pub fn lltype_is_sized<'tcx>(cx: &ty::ctxt<'tcx>, ty: Ty<'tcx>) -> bool {
-    match ty.sty {
-        ty::ty_open(_) => true,
-        _ => type_is_sized(cx, ty),
+    // FIXME(#4287) This can cause errors due to polymorphic recursion,
+    // a better span should be provided, if available.
+    let err_count = tcx.sess.err_count();
+    let is_sized = ty::type_is_sized(&param_env, DUMMY_SP, ty);
+    // Those errors aren't fatal, but an incorrect result can later
+    // trip over asserts in both rustc's trans and LLVM.
+    if err_count < tcx.sess.err_count() {
+        tcx.sess.abort_if_errors();
     }
+    is_sized
 }
 
 pub fn type_is_fat_ptr<'tcx>(cx: &ty::ctxt<'tcx>, ty: Ty<'tcx>) -> bool {
@@ -211,10 +213,43 @@ fn type_needs_unwind_cleanup_<'tcx>(tcx: &ty::ctxt<'tcx>,
     }
 }
 
-pub fn type_needs_drop<'tcx>(cx: &ty::ctxt<'tcx>,
-                         ty: Ty<'tcx>)
-                         -> bool {
-    ty::type_contents(cx, ty).needs_drop(cx)
+/// 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 {
+    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 3c0024712b23acc9110302be1bf9c88e90b4f1ad..c1d22cc973c240c209b88dce5d1d5c8728c2eb70 100644 (file)
@@ -146,8 +146,8 @@ fn const_deref<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                 (const_deref_ptr(cx, v), mt.ty)
             } else {
                 // Derefing a fat pointer does not change the representation,
-                // just the type to ty_open.
-                (v, ty::mk_open(cx.tcx(), mt.ty))
+                // just the type to the unsized contents.
+                (v, mt.ty)
             }
         }
         None => {
@@ -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) {
@@ -290,15 +290,7 @@ pub fn const_expr<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                         // an optimisation, it is necessary for mutable vectors to
                         // work properly.
                         ty = match ty::deref(ty, true) {
-                            Some(mt) => {
-                                if type_is_sized(cx.tcx(), mt.ty) {
-                                    mt.ty
-                                } else {
-                                    // Derefing a fat pointer does not change the representation,
-                                    // just the type to ty_open.
-                                    ty::mk_open(cx.tcx(), mt.ty)
-                                }
-                            }
+                            Some(mt) => mt.ty,
                             None => {
                                 cx.sess().bug(&format!("unexpected dereferenceable type {}",
                                                        ty_to_string(cx.tcx(), ty)))
@@ -319,11 +311,12 @@ pub fn const_expr<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                     llconst = addr_of(cx, llconst, "autoref", e.id);
                 }
                 Some(box ty::AutoUnsize(ref k)) => {
-                    let unsized_ty = ty::unsize_ty(cx.tcx(), ty, k, e.span);
                     let info = expr::unsized_info(cx, k, e.id, ty, param_substs,
                         |t| ty::mk_imm_rptr(cx.tcx(), cx.tcx().mk_region(ty::ReStatic), t));
 
-                    let base = ptrcast(llconst, type_of::type_of(cx, unsized_ty).ptr_to());
+                    let unsized_ty = ty::unsize_ty(cx.tcx(), ty, k, e.span);
+                    let ptr_ty = type_of::in_memory_type_of(cx, unsized_ty).ptr_to();
+                    let base = ptrcast(llconst, ptr_ty);
                     let prev_const = cx.const_unsized().borrow_mut()
                                        .insert(base, llconst);
                     assert!(prev_const.is_none() || prev_const == Some(llconst));
@@ -366,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)
           }
@@ -386,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) }
@@ -440,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
               }
@@ -477,16 +470,10 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
               };
               let (arr, len) = match bt.sty {
                   ty::ty_vec(_, Some(u)) => (bv, C_uint(cx, u)),
-                  ty::ty_open(ty) => match ty.sty {
-                      ty::ty_vec(_, None) | ty::ty_str => {
-                          let e1 = const_get_elt(cx, bv, &[0]);
-                          (const_deref_ptr(cx, e1), const_get_elt(cx, bv, &[1]))
-                      },
-                      _ => cx.sess().span_bug(base.span,
-                                              &format!("index-expr base must be a vector \
-                                                       or string type, found {}",
-                                                      ty_to_string(cx.tcx(), bt)))
-                  },
+                  ty::ty_vec(_, None) | ty::ty_str => {
+                      let e1 = const_get_elt(cx, bv, &[0]);
+                      (const_deref_ptr(cx, e1), const_get_elt(cx, bv, &[1]))
+                  }
                   ty::ty_rptr(_, mt) => match mt.ty.sty {
                       ty::ty_vec(_, Some(u)) => {
                           (const_deref_ptr(cx, bv), C_uint(cx, u))
@@ -527,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;
@@ -595,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);
@@ -676,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) => {
@@ -714,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(_)) => {
@@ -753,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 e0598583a1954f61ac2e33854f95f64fa81b684c..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
@@ -492,8 +493,6 @@ pub fn to_lvalue_datum<'blk>(self,
                                  -> DatumBlock<'blk, 'tcx, Lvalue> {
         debug!("to_lvalue_datum self: {}", self.to_string(bcx.ccx()));
 
-        assert!(lltype_is_sized(bcx.tcx(), self.ty),
-                "Trying to convert unsized value to lval");
         self.match_kind(
             |l| DatumBlock::new(bcx, l),
             |r| {
@@ -549,15 +548,10 @@ pub fn get_element<'blk, F>(&self, bcx: Block<'blk, 'tcx>, ty: Ty<'tcx>,
                                 -> Datum<'tcx, Lvalue> where
         F: FnOnce(ValueRef) -> ValueRef,
     {
-        let val = match self.ty.sty {
-            _ if type_is_sized(bcx.tcx(), self.ty) => gep(self.val),
-            ty::ty_open(_) => {
-                let base = Load(bcx, expr::get_dataptr(bcx, self.val));
-                gep(base)
-            }
-            _ => bcx.tcx().sess.bug(
-                &format!("Unexpected unsized type in get_element: {}",
-                        bcx.ty_to_string(self.ty)))
+        let val = if type_is_sized(bcx.tcx(), self.ty) {
+            gep(self.val)
+        } else {
+            gep(Load(bcx, expr::get_dataptr(bcx, self.val)))
         };
         Datum {
             val: val,
@@ -566,7 +560,8 @@ pub fn get_element<'blk, F>(&self, bcx: Block<'blk, 'tcx>, ty: Ty<'tcx>,
         }
     }
 
-    pub fn get_vec_base_and_len(&self, bcx: Block) -> (ValueRef, ValueRef) {
+    pub fn get_vec_base_and_len<'blk>(&self, bcx: Block<'blk, 'tcx>)
+                                      -> (ValueRef, ValueRef) {
         //! Converts a vector into the slice pair.
 
         tvec::get_base_and_len(bcx, self.val, self.ty)
@@ -662,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 b5cba9b67406cee1c6c7f04ab16a05840b3fed2a..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)  |
@@ -3828,7 +3827,6 @@ fn push_debuginfo_type_name<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
         }
         ty::ty_err |
         ty::ty_infer(_) |
-        ty::ty_open(_) |
         ty::ty_projection(..) |
         ty::ty_param(_) => {
             cx.sess().bug(&format!("debuginfo: Trying to create type name for \
index 78992959a6f2288f39c5c734988d0561baa041c6..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);
@@ -451,8 +451,6 @@ fn unsize_expr<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
         let datum_ty = datum.ty;
         let unsized_ty = ty::unsize_ty(tcx, datum_ty, k, expr.span);
         debug!("unsized_ty={}", unsized_ty.repr(bcx.tcx()));
-        let dest_ty = ty::mk_open(tcx, unsized_ty);
-        debug!("dest_ty={}", unsized_ty.repr(bcx.tcx()));
 
         let info = unsized_info(bcx.ccx(), k, expr.id, datum_ty, bcx.fcx.param_substs,
                                 |t| ty::mk_imm_rptr(tcx, tcx.mk_region(ty::ReStatic), t));
@@ -462,20 +460,16 @@ fn unsize_expr<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                                  datum.to_lvalue_datum(bcx, "into_fat_ptr", expr.id));
         // Compute the base pointer. This doesn't change the pointer value,
         // but merely its type.
-        let base = match *k {
-            ty::UnsizeStruct(..) | ty::UnsizeVtable(..) => {
-                PointerCast(bcx, lval.val, type_of::type_of(bcx.ccx(), unsized_ty).ptr_to())
-            }
-            ty::UnsizeLength(..) => {
-                GEPi(bcx, lval.val, &[0, 0])
-            }
-        };
+        let ptr_ty = type_of::in_memory_type_of(bcx.ccx(), unsized_ty).ptr_to();
+        let base = PointerCast(bcx, lval.val, ptr_ty);
 
-        let scratch = rvalue_scratch_datum(bcx, dest_ty, "__fat_ptr");
-        Store(bcx, base, get_dataptr(bcx, scratch.val));
-        Store(bcx, info, get_len(bcx, scratch.val));
+        let llty = type_of::type_of(bcx.ccx(), unsized_ty);
+        // HACK(eddyb) get around issues with lifetime intrinsics.
+        let scratch = alloca_no_lifetime(bcx, llty, "__fat_ptr");
+        Store(bcx, base, get_dataptr(bcx, scratch));
+        Store(bcx, info, get_len(bcx, scratch));
 
-        DatumBlock::new(bcx, scratch.to_expr_datum())
+        DatumBlock::new(bcx, Datum::new(scratch, unsized_ty, LvalueExpr))
     }
 
     fn unsize_unique_vec<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
@@ -635,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) => {
@@ -711,7 +705,7 @@ fn trans_field<'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>,
     let _icx = push_ctxt("trans_rec_field");
 
     let base_datum = unpack_datum!(bcx, trans_to_lvalue(bcx, base, "field"));
-    let bare_ty = ty::unopen_type(base_datum.ty);
+    let bare_ty = base_datum.ty;
     let repr = adt::represent_type(bcx.ccx(), bare_ty);
     with_field_tys(bcx.tcx(), bare_ty, None, move |discr, field_tys| {
         let ix = get_idx(bcx.tcx(), field_tys);
@@ -723,7 +717,7 @@ fn trans_field<'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>,
         if type_is_sized(bcx.tcx(), d.ty) {
             DatumBlock { datum: d.to_expr_datum(), bcx: bcx }
         } else {
-            let scratch = rvalue_scratch_datum(bcx, ty::mk_open(bcx.tcx(), d.ty), "");
+            let scratch = rvalue_scratch_datum(bcx, d.ty, "");
             Store(bcx, d.val, get_dataptr(bcx, scratch.val));
             let info = Load(bcx, get_len(bcx, base_datum.val));
             Store(bcx, info, get_len(bcx, scratch.val));
@@ -809,7 +803,7 @@ fn trans_index<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
             if type_is_sized(bcx.tcx(), elt_ty) {
                 Datum::new(datum.to_llscalarish(bcx), elt_ty, LvalueExpr)
             } else {
-                Datum::new(datum.val, ty::mk_open(bcx.tcx(), elt_ty), LvalueExpr)
+                Datum::new(datum.val, elt_ty, LvalueExpr)
             }
         }
         None => {
@@ -881,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);
@@ -980,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:
@@ -1039,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) => {
@@ -1281,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)
@@ -1371,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(
@@ -1506,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"),
@@ -1671,7 +1663,7 @@ fn trans_uniq_expr<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
 fn ref_fat_ptr<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                            lval: Datum<'tcx, Lvalue>)
                            -> DatumBlock<'blk, 'tcx, Expr> {
-    let dest_ty = ty::close_type(bcx.tcx(), lval.ty);
+    let dest_ty = ty::mk_imm_rptr(bcx.tcx(), bcx.tcx().mk_region(ty::ReStatic), lval.ty);
     let scratch = rvalue_scratch_datum(bcx, dest_ty, "__fat_ptr");
     memcpy_ty(bcx, scratch.val, lval.val, scratch.ty);
 
@@ -1685,16 +1677,13 @@ fn trans_addr_of<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
     let _icx = push_ctxt("trans_addr_of");
     let mut bcx = bcx;
     let sub_datum = unpack_datum!(bcx, trans_to_lvalue(bcx, subexpr, "addr_of"));
-    match sub_datum.ty.sty {
-        ty::ty_open(_) => {
-            // Opened DST value, close to a fat pointer
-            ref_fat_ptr(bcx, sub_datum)
-        }
-        _ => {
-            // Sized value, ref to a thin pointer
-            let ty = expr_ty(bcx, expr);
-            immediate_rvalue_bcx(bcx, sub_datum.val, ty).to_expr_datumblock()
-        }
+    if !type_is_sized(bcx.tcx(), sub_datum.ty) {
+        // DST lvalue, close to a fat pointer
+        ref_fat_ptr(bcx, sub_datum)
+    } else {
+        // Sized value, ref to a thin pointer
+        let ty = expr_ty(bcx, expr);
+        immediate_rvalue_bcx(bcx, sub_datum.val, ty).to_expr_datumblock()
     }
 }
 
@@ -2127,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);
 
@@ -2234,16 +2223,15 @@ fn deref_once<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
             if type_is_sized(bcx.tcx(), content_ty) {
                 deref_owned_pointer(bcx, expr, datum, content_ty)
             } else {
-                // A fat pointer and an opened DST value have the same
-                // representation just different types. Since there is no
-                // temporary for `*e` here (because it is unsized), we cannot
-                // emulate the sized object code path for running drop glue and
-                // free. Instead, we schedule cleanup for `e`, turning it into
-                // an lvalue.
+                // A fat pointer and a DST lvalue have the same representation
+                // just different types. Since there is no temporary for `*e`
+                // here (because it is unsized), we cannot emulate the sized
+                // object code path for running drop glue and free. Instead,
+                // we schedule cleanup for `e`, turning it into an lvalue.
                 let datum = unpack_datum!(
                     bcx, datum.to_lvalue_datum(bcx, "deref", expr.id));
 
-                let datum = Datum::new(datum.val, ty::mk_open(bcx.tcx(), content_ty), LvalueExpr);
+                let datum = Datum::new(datum.val, content_ty, LvalueExpr);
                 DatumBlock::new(bcx, datum)
             }
         }
@@ -2260,11 +2248,9 @@ fn deref_once<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                 // owner (or, in the case of *T, by the user).
                 DatumBlock::new(bcx, Datum::new(ptr, content_ty, LvalueExpr))
             } else {
-                // A fat pointer and an opened DST value have the same representation
+                // A fat pointer and a DST lvalue have the same representation
                 // just different types.
-                DatumBlock::new(bcx, Datum::new(datum.val,
-                                                ty::mk_open(bcx.tcx(), content_ty),
-                                                LvalueExpr))
+                DatumBlock::new(bcx, Datum::new(datum.val, content_ty, LvalueExpr))
             }
         }
 
index 20956bf795b8537ed94987d632ad1bc0fe04f108..9491c8377a655fdbe10eee9e63cc2200f29092f2 100644 (file)
@@ -34,7 +34,7 @@
 use trans::machine::*;
 use trans::tvec;
 use trans::type_::Type;
-use trans::type_of::{type_of, sizing_type_of, align_of};
+use trans::type_of::{self, type_of, sizing_type_of, align_of};
 use middle::ty::{self, Ty};
 use util::ppaux::{ty_to_short_str, Repr};
 use util::ppaux;
@@ -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);
@@ -265,8 +275,7 @@ fn trans_struct_drop<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
         assert_eq!(params.len(), 1);
         let self_arg = if type_is_fat_ptr(bcx.tcx(), self_ty) {
             // The dtor expects a fat pointer, so make one, even if we have to fake it.
-            let boxed_ty = ty::mk_open(bcx.tcx(), t);
-            let scratch = datum::rvalue_scratch_datum(bcx, boxed_ty, "__fat_ptr_drop_self");
+            let scratch = datum::rvalue_scratch_datum(bcx, t, "__fat_ptr_drop_self");
             Store(bcx, value, GEPi(bcx, scratch.val, &[0, abi::FAT_PTR_ADDR]));
             Store(bcx,
                   // If we just had a thin pointer, make a fat pointer by sticking
@@ -284,20 +293,18 @@ fn trans_struct_drop<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
         // Add all the fields as a value which needs to be cleaned at the end of
         // this scope. Iterate in reverse order so a Drop impl doesn't reverse
         // the order in which fields get dropped.
-        for (i, ty) in st.fields.iter().enumerate().rev() {
+        for (i, &ty) in st.fields.iter().enumerate().rev() {
             let llfld_a = adt::struct_field_ptr(variant_cx, &*st, value, i, false);
 
-            let val = if type_is_sized(bcx.tcx(), *ty) {
+            let val = if type_is_sized(bcx.tcx(), ty) {
                 llfld_a
             } else {
-                let boxed_ty = ty::mk_open(bcx.tcx(), *ty);
-                let scratch = datum::rvalue_scratch_datum(bcx, boxed_ty, "__fat_ptr_drop_field");
+                let scratch = datum::rvalue_scratch_datum(bcx, ty, "__fat_ptr_drop_field");
                 Store(bcx, llfld_a, GEPi(bcx, scratch.val, &[0, abi::FAT_PTR_ADDR]));
                 Store(bcx, info.unwrap(), GEPi(bcx, scratch.val, &[0, abi::FAT_PTR_EXTRA]));
                 scratch.val
             };
-            variant_cx.fcx.schedule_drop_mem(cleanup::CustomScope(field_scope),
-                                             val, *ty);
+            variant_cx.fcx.schedule_drop_mem(cleanup::CustomScope(field_scope), val, ty);
         }
 
         let dtor_ty = ty::mk_ctor_fn(bcx.tcx(),
@@ -483,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,
@@ -502,7 +509,10 @@ pub fn declare_tydesc<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>)
     // tydescs.
     assert!(!ccx.finished_tydescs().get());
 
-    let llty = type_of(ccx, t);
+    // This really shouldn't be like this, size/align will be wrong for
+    // unsized types (i.e. [T] will have the size/align of T).
+    // But we need it until we split this out into a "type name" intrinsic.
+    let llty = type_of::in_memory_type_of(ccx, t);
 
     if ccx.sess().count_type_sizes() {
         println!("{}\t{}", llsize_of_real(ccx, llty),
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 7644ecf2cfde69382f0b2c3694390181f5042435..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"));
 
@@ -818,9 +818,6 @@ fn emit_vtable_methods<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
                         param_substs,
                         substs.clone()).val;
 
-                    // currently, at least, by-value self is not object safe
-                    assert!(m.explicit_self != ty::ByValueExplicitSelfCategory);
-
                     Some(fn_ref).into_iter()
                 }
             }
index 7b59e0258ee224c4ec6cdd91e4c012afa800c072..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,
@@ -372,38 +371,31 @@ pub fn get_fixed_base_and_len(bcx: Block,
     (base, len)
 }
 
-fn get_slice_base_and_len(bcx: Block,
-                          llval: ValueRef)
-                          -> (ValueRef, ValueRef) {
-    let base = Load(bcx, GEPi(bcx, llval, &[0, abi::FAT_PTR_ADDR]));
-    let len = Load(bcx, GEPi(bcx, llval, &[0, abi::FAT_PTR_EXTRA]));
-    (base, len)
-}
-
 /// Converts a vector into the slice pair.  The vector should be stored in `llval` which should be
 /// by-reference.  If you have a datum, you would probably prefer to call
 /// `Datum::get_base_and_len()` which will handle any conversions for you.
-pub fn get_base_and_len(bcx: Block,
-                        llval: ValueRef,
-                        vec_ty: Ty)
-                        -> (ValueRef, ValueRef) {
+pub fn get_base_and_len<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
+                                    llval: ValueRef,
+                                    vec_ty: Ty<'tcx>)
+                                    -> (ValueRef, ValueRef) {
     let ccx = bcx.ccx();
 
     match vec_ty.sty {
         ty::ty_vec(_, Some(n)) => get_fixed_base_and_len(bcx, llval, n),
-        ty::ty_open(ty) => match ty.sty {
-            ty::ty_vec(_, None) | ty::ty_str => get_slice_base_and_len(bcx, llval),
-            _ => ccx.sess().bug("unexpected type in get_base_and_len")
-        },
+        ty::ty_vec(_, None) | ty::ty_str => {
+            let base = Load(bcx, expr::get_dataptr(bcx, llval));
+            let len = Load(bcx, expr::get_len(bcx, llval));
+            (base, len)
+        }
 
         // Only used for pattern matching.
-        ty::ty_uniq(ty) | ty::ty_rptr(_, ty::mt{ty, ..}) => match ty.sty {
-            ty::ty_vec(_, None) | ty::ty_str => get_slice_base_and_len(bcx, llval),
-            ty::ty_vec(_, Some(n)) => {
-                let base = GEPi(bcx, Load(bcx, llval), &[0, 0]);
-                (base, C_uint(ccx, n))
-            }
-            _ => ccx.sess().bug("unexpected type in get_base_and_len"),
+        ty::ty_uniq(ty) | ty::ty_rptr(_, ty::mt{ty, ..}) => {
+            let inner = if type_is_sized(bcx.tcx(), ty) {
+                Load(bcx, llval)
+            } else {
+                llval
+            };
+            get_base_and_len(bcx, inner, ty)
         },
         _ => ccx.sess().bug("unexpected type in get_base_and_len"),
     }
index 0c69a7132a77be8b9855dc1b5b4a7c578445a0e5..d5ec18e641b7963de9a11ff5cfb71f36f785c8e2 100644 (file)
@@ -232,14 +232,6 @@ pub fn vtable_ptr(ccx: &CrateContext) -> Type {
         Type::glue_fn(ccx, Type::i8p(ccx)).ptr_to().ptr_to()
     }
 
-    pub fn opaque_trait(ccx: &CrateContext) -> Type {
-        Type::struct_(ccx, &[Type::opaque_trait_data(ccx).ptr_to(), Type::vtable_ptr(ccx)], false)
-    }
-
-    pub fn opaque_trait_data(ccx: &CrateContext) -> Type {
-        Type::i8(ccx)
-    }
-
     pub fn kind(&self) -> TypeKind {
         unsafe {
             llvm::LLVMGetTypeKind(self.to_ref())
index b53ea79804c08f3815ab27ad53087c118cbf983b..97278eb0512e226ea0018c27258bbe79ed42ccd1 100644 (file)
@@ -10,8 +10,6 @@
 
 #![allow(non_camel_case_types)]
 
-pub use self::named_ty::*;
-
 use middle::subst;
 use trans::adt;
 use trans::common::*;
@@ -183,9 +181,8 @@ pub fn sizing_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Typ
     }
 
     let llsizingty = match t.sty {
-        _ if !lltype_is_sized(cx.tcx(), t) => {
-            cx.sess().bug(&format!("trying to take the sizing type of {}, an unsized type",
-                                  ppaux::ty_to_string(cx.tcx(), t)))
+        _ if !type_is_sized(cx.tcx(), t) => {
+            Type::struct_(cx, &[Type::i8p(cx), Type::i8p(cx)], false)
         }
 
         ty::ty_bool => Type::bool(cx),
@@ -232,15 +229,11 @@ pub fn sizing_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Typ
             }
         }
 
-        ty::ty_open(_) => {
-            Type::struct_(cx, &[Type::i8p(cx), Type::i8p(cx)], false)
-        }
-
         ty::ty_projection(..) | ty::ty_infer(..) | ty::ty_param(..) | ty::ty_err(..) => {
             cx.sess().bug(&format!("fictitious type {} in sizing_type_of()",
                                   ppaux::ty_to_string(cx.tcx(), t)))
         }
-        ty::ty_vec(_, None) | ty::ty_trait(..) | ty::ty_str => panic!("unreachable")
+        ty::ty_vec(_, None) | ty::ty_trait(..) | ty::ty_str => unreachable!()
     };
 
     cx.llsizingtypes().borrow_mut().insert(t, llsizingty);
@@ -270,25 +263,37 @@ pub fn arg_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Type {
     }
 }
 
-// NB: If you update this, be sure to update `sizing_type_of()` as well.
-pub fn type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Type {
-    fn type_of_unsize_info<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Type {
-        // It is possible to end up here with a sized type. This happens with a
-        // struct which might be unsized, but is monomorphised to a sized type.
-        // In this case we'll fake a fat pointer with no unsize info (we use 0).
-        // However, its still a fat pointer, so we need some type use.
-        if type_is_sized(cx.tcx(), t) {
-            return Type::i8p(cx);
-        }
-
-        match unsized_part_of_type(cx.tcx(), t).sty {
-            ty::ty_str | ty::ty_vec(..) => Type::uint_from_ty(cx, ast::TyUs(false)),
-            ty::ty_trait(_) => Type::vtable_ptr(cx),
-            _ => panic!("Unexpected type returned from unsized_part_of_type : {}",
-                       t.repr(cx.tcx()))
-        }
-    }
+/// Get the LLVM type corresponding to a Rust type, i.e. `middle::ty::Ty`.
+/// This is the right LLVM type for an alloca containg a value of that type,
+/// and the pointee of an Lvalue Datum (which is always a LLVM pointer).
+/// For unsized types, the returned type is a fat pointer, thus the resulting
+/// LLVM type for a `Trait` Lvalue is `{ i8*, void(i8*)** }*`, which is a double
+/// indirection to the actual data, unlike a `i8` Lvalue, which is just `i8*`.
+/// This is needed due to the treatment of immediate values, as a fat pointer
+/// is too large for it to be placed in SSA value (by our rules).
+/// For the raw type without far pointer indirection, see `in_memory_type_of`.
+pub fn type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, ty: Ty<'tcx>) -> Type {
+    let ty = if !type_is_sized(cx.tcx(), ty) {
+        ty::mk_imm_ptr(cx.tcx(), ty)
+    } else {
+        ty
+    };
+    in_memory_type_of(cx, ty)
+}
 
+/// Get the LLVM type corresponding to a Rust type, i.e. `middle::ty::Ty`.
+/// This is the right LLVM type for a field/array element of that type,
+/// and is the same as `type_of` for all Sized types.
+/// Unsized types, however, are represented by a "minimal unit", e.g.
+/// `[T]` becomes `T`, while `str` and `Trait` turn into `i8` - this
+/// is useful for indexing slices, as `&[T]`'s data pointer is `T*`.
+/// If the type is an unsized struct, the regular layout is generated,
+/// with the inner-most trailing unsized field using the "minimal unit"
+/// of that field's type - this is useful for taking the address of
+/// that field and ensuring the struct has the right alignment.
+/// For the LLVM type of a value as a whole, see `type_of`.
+/// NB: If you update this, be sure to update `sizing_type_of()` as well.
+pub fn in_memory_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Type {
     // Check the cache.
     match cx.lltypes().borrow().get(&t) {
         Some(&llty) => return llty,
@@ -307,7 +312,7 @@ fn type_of_unsize_info<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Ty
     let t_norm = erase_regions(cx.tcx(), &t);
 
     if t != t_norm {
-        let llty = type_of(cx, t_norm);
+        let llty = in_memory_type_of(cx, t_norm);
         debug!("--> normalized {} {:?} to {} {:?} llty={}",
                 t.repr(cx.tcx()),
                 t,
@@ -331,10 +336,10 @@ fn type_of_unsize_info<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Ty
           // of the enum's variants refers to the enum itself.
           let repr = adt::represent_type(cx, t);
           let tps = substs.types.get_slice(subst::TypeSpace);
-          let name = llvm_type_name(cx, an_enum, did, tps);
+          let name = llvm_type_name(cx, did, tps);
           adt::incomplete_type_of(cx, &*repr, &name[..])
       }
-      ty::ty_closure(did, _, ref substs) => {
+      ty::ty_closure(..) => {
           // Only create the named struct, but don't fill it in. We
           // fill it in *after* placing it into the type cache.
           let repr = adt::represent_type(cx, t);
@@ -342,41 +347,47 @@ fn type_of_unsize_info<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Ty
           // inherited from their environment, so we use entire
           // contents of the VecPerParamSpace to to construct the llvm
           // name
-          let name = llvm_type_name(cx, a_closure, did, substs.types.as_slice());
-          adt::incomplete_type_of(cx, &*repr, &name[..])
+          adt::incomplete_type_of(cx, &*repr, "closure")
       }
 
       ty::ty_uniq(ty) | ty::ty_rptr(_, ty::mt{ty, ..}) | ty::ty_ptr(ty::mt{ty, ..}) => {
-          match ty.sty {
-              ty::ty_str => {
+          if !type_is_sized(cx.tcx(), ty) {
+              if let ty::ty_str = ty.sty {
                   // This means we get a nicer name in the output (str is always
                   // unsized).
                   cx.tn().find_type("str_slice").unwrap()
+              } else {
+                  let ptr_ty = in_memory_type_of(cx, ty).ptr_to();
+                  let unsized_part = unsized_part_of_type(cx.tcx(), ty);
+                  let info_ty = match unsized_part.sty {
+                      ty::ty_str | ty::ty_vec(..) => {
+                          Type::uint_from_ty(cx, ast::TyUs(false))
+                      }
+                      ty::ty_trait(_) => Type::vtable_ptr(cx),
+                      _ => panic!("Unexpected type returned from \
+                                   unsized_part_of_type: {} for ty={}",
+                                  unsized_part.repr(cx.tcx()), ty.repr(cx.tcx()))
+                  };
+                  Type::struct_(cx, &[ptr_ty, info_ty], false)
               }
-              ty::ty_trait(..) => Type::opaque_trait(cx),
-              _ if !type_is_sized(cx.tcx(), ty) => {
-                  let p_ty = type_of(cx, ty).ptr_to();
-                  Type::struct_(cx, &[p_ty, type_of_unsize_info(cx, ty)], false)
-              }
-              _ => type_of(cx, ty).ptr_to(),
+          } else {
+              in_memory_type_of(cx, ty).ptr_to()
           }
       }
 
       ty::ty_vec(ty, Some(size)) => {
           let size = size as u64;
-          let llty = type_of(cx, ty);
+          let llty = in_memory_type_of(cx, ty);
           ensure_array_fits_in_address_space(cx, llty, size, t);
           Type::array(&llty, size)
       }
-      ty::ty_vec(ty, None) => {
-          type_of(cx, ty)
-      }
 
-      ty::ty_trait(..) => {
-          Type::opaque_trait_data(cx)
-      }
-
-      ty::ty_str => Type::i8(cx),
+      // Unsized slice types (and str) have the type of their element, and
+      // traits have the type of u8. This is so that the data pointer inside
+      // fat pointers is of the right type (e.g. for array accesses), even
+      // when taking the address of an unsized field in a struct.
+      ty::ty_vec(ty, None) => in_memory_type_of(cx, ty),
+      ty::ty_str | ty::ty_trait(..) => Type::i8(cx),
 
       ty::ty_bare_fn(..) => {
           type_of_fn_from_ty(cx, t).ptr_to()
@@ -388,7 +399,7 @@ fn type_of_unsize_info<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Ty
       }
       ty::ty_struct(did, ref substs) => {
           if ty::type_is_simd(cx.tcx(), t) {
-              let llet = type_of(cx, ty::simd_type(cx.tcx(), t));
+              let llet = in_memory_type_of(cx, ty::simd_type(cx.tcx(), t));
               let n = ty::simd_size(cx.tcx(), t) as u64;
               ensure_array_fits_in_address_space(cx, llet, n, t);
               Type::vector(&llet, n)
@@ -398,29 +409,11 @@ fn type_of_unsize_info<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Ty
               // infinite recursion with recursive struct types.
               let repr = adt::represent_type(cx, t);
               let tps = substs.types.get_slice(subst::TypeSpace);
-              let name = llvm_type_name(cx, a_struct, did, tps);
+              let name = llvm_type_name(cx, did, tps);
               adt::incomplete_type_of(cx, &*repr, &name[..])
           }
       }
 
-      ty::ty_open(t) => match t.sty {
-          ty::ty_struct(..) => {
-              let p_ty = type_of(cx, t).ptr_to();
-              Type::struct_(cx, &[p_ty, type_of_unsize_info(cx, t)], false)
-          }
-          ty::ty_vec(ty, None) => {
-              let p_ty = type_of(cx, ty).ptr_to();
-              Type::struct_(cx, &[p_ty, type_of_unsize_info(cx, t)], false)
-          }
-          ty::ty_str => {
-              let p_ty = Type::i8p(cx);
-              Type::struct_(cx, &[p_ty, type_of_unsize_info(cx, t)], false)
-          }
-          ty::ty_trait(..) => Type::opaque_trait(cx),
-          _ => cx.sess().bug(&format!("ty_open with sized type: {}",
-                                     ppaux::ty_to_string(cx.tcx(), t)))
-      },
-
       ty::ty_infer(..) => cx.sess().bug("type_of with ty_infer"),
       ty::ty_projection(..) => cx.sess().bug("type_of with ty_projection"),
       ty::ty_param(..) => cx.sess().bug("type_of with ty_param"),
@@ -444,7 +437,7 @@ fn type_of_unsize_info<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Ty
         _ => ()
     }
 
-    return llty;
+    llty
 }
 
 pub fn align_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>)
@@ -453,37 +446,22 @@ pub fn align_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>)
     machine::llalign_of_min(cx, llty)
 }
 
-// Want refinements! (Or case classes, I guess
-#[derive(Copy)]
-pub enum named_ty {
-    a_struct,
-    an_enum,
-    a_closure,
-}
-
-pub fn llvm_type_name<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
-                                what: named_ty,
-                                did: ast::DefId,
-                                tps: &[Ty<'tcx>])
-                                -> String {
-    let name = match what {
-        a_struct => "struct",
-        an_enum => "enum",
-        a_closure => return "closure".to_string(),
-    };
-
+fn llvm_type_name<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
+                            did: ast::DefId,
+                            tps: &[Ty<'tcx>])
+                            -> String {
     let base = ty::item_path_str(cx.tcx(), did);
     let strings: Vec<String> = tps.iter().map(|t| t.repr(cx.tcx())).collect();
     let tstr = if strings.is_empty() {
         base
     } else {
-        format!("{}<{:?}>", base, strings)
+        format!("{}<{}>", base, strings.connect(", "))
     };
 
     if did.krate == 0 {
-        format!("{}.{}", name, tstr)
+        tstr
     } else {
-        format!("{}.{}[{}{}]", name, tstr, "#", did.krate)
+        format!("{}.{}", did.krate, tstr)
     }
 }
 
index ff397d994304d4f2a83e5e4b31dc4cccfc3a0284..844635117b5e988545db9576d2c9cc6d7858a428 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, span: Span, id: ast::DefId)
+                     -> Result<Rc<ty::TraitDef<'tcx>>, ErrorReported>;
 
-    fn get_trait_def(&self, id: ast::DefId) -> Rc<ty::TraitDef<'tcx>>;
+    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,
@@ -305,9 +322,9 @@ fn create_region_substs<'tcx>(
             rscope.anon_regions(span, expected_num_region_params);
 
         if supplied_num_region_params != 0 || anon_regions.is_err() {
-            span_err!(tcx.sess, span, E0107,
-                      "wrong number of lifetime parameters: expected {}, found {}",
-                      expected_num_region_params, supplied_num_region_params);
+            report_lifetime_number_error(tcx, span,
+                                         supplied_num_region_params,
+                                         expected_num_region_params);
         }
 
         match anon_regions {
@@ -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,38 +366,29 @@ 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);
+
     if supplied_ty_param_count < required_ty_param_count {
-        let expected = if required_ty_param_count < formal_ty_param_count {
-            "expected at least"
-        } else {
-            "expected"
-        };
-        span_err!(this.tcx().sess, span, E0243,
-                  "wrong number of type arguments: {} {}, found {}",
-                  expected,
-                  required_ty_param_count,
-                  supplied_ty_param_count);
         while type_substs.len() < required_ty_param_count {
             type_substs.push(tcx.types.err);
         }
     } else if supplied_ty_param_count > formal_ty_param_count {
-        let expected = if required_ty_param_count < formal_ty_param_count {
-            "expected at most"
-        } else {
-            "expected"
-        };
-        span_err!(this.tcx().sess, span, E0244,
-                  "wrong number of type arguments: {} {}, found {}",
-                  expected,
-                  formal_ty_param_count,
-                  supplied_ty_param_count);
         type_substs.truncate(formal_ty_param_count);
     }
     assert!(type_substs.len() >= required_ty_param_count &&
@@ -431,7 +440,7 @@ fn create_substs_for_ast_path<'tcx>(
         }
     }
 
-    return substs;
+    substs
 }
 
 struct ConvertedBinding<'tcx> {
@@ -591,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));
@@ -611,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()));
         }
     }
 }
@@ -638,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>
 {
@@ -650,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
@@ -661,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,
@@ -835,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 }
-}
-
-/// 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 (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;
+        }
+    };
 
-    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
-            };
+    let substs = ast_path_substs_for_ty(this, rscope,
+                                        span, param_mode,
+                                        &generics, item_segment);
 
-            // 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>>);
@@ -929,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))
                 }
@@ -1000,44 +992,60 @@ fn trait_ref_to_object_type<'tcx>(this: &AstConv<'tcx>,
 }
 
 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 {
+        span_err!(tcx.sess, span, E0223,
+                "ambiguous associated type; specify the type using the syntax \
+                `<{} as Trait>::{}`",
+                ty.user_string(tcx), 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()));
@@ -1045,7 +1053,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,
@@ -1060,31 +1093,43 @@ 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();
+
+    check_path_args(tcx, slice::ref_slice(item_segment), NO_TPS | NO_REGIONS);
 
-    let self_type = ast_ty_to_ty(this, rscope, &*qpath.self_type);
+    let self_ty = if let Some(ty) = opt_self_ty {
+        ty
+    } else {
+        let path_str = ty::item_path_str(tcx, trait_def_id);
+        span_err!(tcx.sess, span, E0223,
+                  "ambiguous associated type; specify the type using the syntax \
+                   `<Type as {}>::{}`",
+                   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
@@ -1120,6 +1165,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>,
@@ -1146,173 +1281,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;
@@ -1820,8 +1910,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
@@ -1847,7 +1937,16 @@ pub fn partition_bounds<'a>(tcx: &ty::ctxt,
                         if ty::try_add_builtin_trait(tcx,
                                                      trait_did,
                                                      &mut builtin_bounds) {
-                            // FIXME(#20302) -- we should check for things like Copy<T>
+                            let segments = &b.trait_ref.path.segments;
+                            let parameters = &segments[segments.len() - 1].parameters;
+                            if parameters.types().len() > 0 {
+                                check_type_argument_count(tcx, b.trait_ref.path.span,
+                                                          parameters.types().len(), 0, 0);
+                            }
+                            if parameters.lifetimes().len() > 0{
+                                report_lifetime_number_error(tcx, b.trait_ref.path.span,
+                                                             parameters.lifetimes().len(), 0);
+                            }
                             continue; // success
                         }
                     }
@@ -1880,3 +1979,34 @@ fn prohibit_projections<'tcx>(tcx: &ty::ctxt<'tcx>,
             "associated type bindings are not allowed here");
     }
 }
+
+fn check_type_argument_count(tcx: &ty::ctxt, span: Span, supplied: usize,
+                             required: usize, accepted: usize) {
+    if supplied < required {
+        let expected = if required < accepted {
+            "expected at least"
+        } else {
+            "expected"
+        };
+        span_err!(tcx.sess, span, E0243,
+                  "wrong number of type arguments: {} {}, found {}",
+                  expected, required, supplied);
+    } else if supplied > accepted {
+        let expected = if required < accepted {
+            "expected at most"
+        } else {
+            "expected"
+        };
+        span_err!(tcx.sess, span, E0244,
+                  "wrong number of type arguments: {} {}, found {}",
+                  expected,
+                  accepted,
+                  supplied);
+    }
+}
+
+fn report_lifetime_number_error(tcx: &ty::ctxt, span: Span, number: usize, expected: usize) {
+    span_err!(tcx.sess, span, E0107,
+              "wrong number of lifetime parameters: expected {}, found {}",
+              expected, number);
+}
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 998a4504088a330394d69157cf5ec74687b9f2af..f65e585d23edd3c8c11e2ac3c11db443db9bd7ed 100644 (file)
@@ -161,12 +161,6 @@ fn accumulate_from_ty(&mut self, ty: Ty<'tcx>) {
                 //   entering the fn check. We should do this after
                 //   the fn check, then we can call this case a bug().
             }
-
-            ty::ty_open(_) => {
-                self.tcx().sess.bug(
-                    &format!("Unexpected type encountered while doing wf check: {}",
-                            ty.repr(self.tcx())));
-            }
         }
     }
 
index 53976df75d6160e5530a3c481c703afeb5e47cf1..d7db21f3a2f762350f94f0636886695f8b203fbf 100644 (file)
@@ -404,26 +404,9 @@ fn instantiate_method_sig(&mut self,
                all_substs.repr(self.tcx()));
 
         // Instantiate the bounds on the method with the
-        // type/early-bound-regions substitutions performed.  The only
-        // late-bound-regions that can appear in bounds are from the
-        // impl, and those were already instantiated above.
-        //
-        // FIXME(DST). Super hack. For a method on a trait object
-        // `Trait`, the generic signature requires that
-        // `Self:Trait`. Since, for an object, we bind `Self` to the
-        // type `Trait`, this leads to an obligation
-        // `Trait:Trait`. Until such time we DST is fully implemented,
-        // that obligation is not necessarily satisfied. (In the
-        // future, it would be.) But we know that the true `Self` DOES implement
-        // the trait. So we just delete this requirement. Hack hack hack.
-        let mut method_predicates = pick.method_ty.predicates.instantiate(self.tcx(), &all_substs);
-        match pick.kind {
-            probe::ObjectPick(..) => {
-                assert_eq!(method_predicates.predicates.get_slice(subst::SelfSpace).len(), 1);
-                method_predicates.predicates.pop(subst::SelfSpace);
-            }
-            _ => { }
-        }
+        // type/early-bound-regions substitutions performed. There can
+        // be no late-bound regions appearing here.
+        let method_predicates = pick.method_ty.predicates.instantiate(self.tcx(), &all_substs);
         let method_predicates = self.fcx.normalize_associated_types_in(self.span,
                                                                        &method_predicates);
 
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 3666b69d1c678ac4cc6a64d60118b794f4bdf449..630530cf11f841186dcb2e0c899e2b6d1ab28661 100644 (file)
@@ -133,14 +133,6 @@ pub fn check_object_safety<'tcx>(tcx: &ty::ctxt<'tcx>,
                      in the supertrait listing");
             }
 
-            ObjectSafetyViolation::Method(method, MethodViolationCode::ByValueSelf) => {
-                tcx.sess.span_note(
-                    span,
-                    &format!("method `{}` has a receiver type of `Self`, \
-                              which cannot be used with a trait object",
-                             method.name.user_string(tcx)));
-            }
-
             ObjectSafetyViolation::Method(method, MethodViolationCode::StaticMethod) => {
                 tcx.sess.span_note(
                     span,
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 7215ab01b02dec250d1e7b22509b6a10dc9be742..1913b55f1d8e69d03da3fc0b368345b055522ed5 100644 (file)
@@ -25,7 +25,7 @@
 use middle::ty::{Ty, ty_bool, ty_char, ty_enum, ty_err};
 use middle::ty::{ty_param, TypeScheme, ty_ptr};
 use middle::ty::{ty_rptr, ty_struct, ty_trait, ty_tup};
-use middle::ty::{ty_str, ty_vec, ty_float, ty_infer, ty_int, ty_open};
+use middle::ty::{ty_str, ty_vec, ty_float, ty_infer, ty_int};
 use middle::ty::{ty_uint, ty_closure, ty_uniq, ty_bare_fn};
 use middle::ty::{ty_projection};
 use middle::ty;
@@ -75,7 +75,7 @@ fn get_base_type_def_id<'a, 'tcx>(inference_context: &InferCtxt<'a, 'tcx>,
 
         ty_bool | ty_char | ty_int(..) | ty_uint(..) | ty_float(..) |
         ty_str(..) | ty_vec(..) | ty_bare_fn(..) | ty_tup(..) |
-        ty_param(..) | ty_err | ty_open(..) |
+        ty_param(..) | ty_err |
         ty_ptr(_) | ty_rptr(_, _) | ty_projection(..) => {
             None
         }
@@ -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 93d9ce3df84ed7b0c747c9b3668141e3660b9c16..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);
+                        }
                     }
                 }
             }
@@ -849,7 +910,7 @@ fn add_constraints_from_ty(&mut self,
                 self.add_constraints_from_mt(generics, mt, variance);
             }
 
-            ty::ty_uniq(typ) | ty::ty_vec(typ, _) | ty::ty_open(typ) => {
+            ty::ty_uniq(typ) | ty::ty_vec(typ, _) => {
                 self.add_constraints_from_ty(generics, typ, variance);
             }
 
@@ -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 d8ef3194e837e9d74ca639cf4f626a6ae5aba6c5..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))
             },
@@ -1619,22 +1622,11 @@ fn clean(&self, cx: &DocContext) -> Type {
             ty::ty_closure(..) => Tuple(vec![]), // FIXME(pcwalton)
 
             ty::ty_infer(..) => panic!("ty_infer"),
-            ty::ty_open(..) => panic!("ty_open"),
             ty::ty_err => panic!("ty_err"),
         }
     }
 }
 
-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
@@ -2393,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")
     };
 
@@ -2419,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);
@@ -2431,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),
@@ -2460,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 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 bf14b86ebd1e39e21189cd0097dff9072a15fcd7..78f126dcf6a827d438057e6cd074c2a7a47e853e 100644 (file)
@@ -13,7 +13,7 @@
 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;
@@ -46,7 +46,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(),
@@ -113,7 +113,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),
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..05d4e0f59fefc4d1732c83ec6ff588deda10df5d 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]
index 4d38d17576ddb2a15ee7fe13624ff1a993a979e6..94457a5d71441b784dc52e9969f6d5e77703ea60 100644 (file)
@@ -37,6 +37,7 @@ pub trait OwnedAsciiExt {
 /// Extension methods for ASCII-subset only operations on string slices
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait AsciiExt {
+    /// Container type for copied ASCII characters.
     #[stable(feature = "rust1", since = "1.0.0")]
     type Owned;
 
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 7e6dd45b51e48f69f553388787dc490f1f843e03..3a06d2d03bf3f7046ec7c74479f9936abb704be8 100644 (file)
@@ -27,6 +27,7 @@
 /// to `Default` when asked to create a hasher.
 #[unstable(feature = "std_misc", reason = "hasher stuff is unclear")]
 pub trait HashState {
+    /// Type of the hasher that will be created.
     type Hasher: hash::Hasher;
 
     /// Creates a new hasher based on the given state of this object.
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 7f3ce7924c1caaa0fe8bfefdcf4968c80e95d201..82b69ddebff68630fcf70bf1da0d61c342ed754b 100644 (file)
 
 use boxed::Box;
 use cmp;
-use io::{self, SeekFrom, Read, Write, Seek, BufRead};
+use io::{self, SeekFrom, Read, Write, Seek, BufRead, Error, ErrorKind};
+use fmt;
 use mem;
 use slice;
+use string::String;
 use vec::Vec;
 
 // =============================================================================
 
 impl<'a, R: Read + ?Sized> Read for &'a mut R {
     fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { (**self).read(buf) }
+
+    fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<()> { (**self).read_to_end(buf) }
+
+    fn read_to_string(&mut self, buf: &mut String) -> io::Result<()> {
+        (**self).read_to_string(buf)
+    }
 }
 impl<'a, W: Write + ?Sized> Write for &'a mut W {
     fn write(&mut self, buf: &[u8]) -> io::Result<usize> { (**self).write(buf) }
+
+    fn write_all(&mut self, buf: &[u8]) -> io::Result<()> { (**self).write_all(buf) }
+
+    fn write_fmt(&mut self, fmt: fmt::Arguments) -> io::Result<()> { (**self).write_fmt(fmt) }
+
     fn flush(&mut self) -> io::Result<()> { (**self).flush() }
 }
 impl<'a, S: Seek + ?Sized> Seek for &'a mut S {
@@ -32,7 +45,14 @@ fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> { (**self).seek(pos) }
 }
 impl<'a, B: BufRead + ?Sized> BufRead for &'a mut B {
     fn fill_buf(&mut self) -> io::Result<&[u8]> { (**self).fill_buf() }
+
     fn consume(&mut self, amt: usize) { (**self).consume(amt) }
+
+    fn read_until(&mut self, byte: u8, buf: &mut Vec<u8>) -> io::Result<()> {
+        (**self).read_until(byte, buf)
+    }
+
+    fn read_line(&mut self, buf: &mut String) -> io::Result<()> { (**self).read_line(buf) }
 }
 
 impl<R: Read + ?Sized> Read for Box<R> {
@@ -76,6 +96,15 @@ fn write(&mut self, data: &[u8]) -> io::Result<usize> {
         *self = b;
         Ok(amt)
     }
+
+    fn write_all(&mut self, data: &[u8]) -> io::Result<()> {
+        if try!(self.write(data)) == data.len() {
+            Ok(())
+        } else {
+            Err(Error::new(ErrorKind::WriteZero, "failed to write whole buffer", None))
+        }
+    }
+
     fn flush(&mut self) -> io::Result<()> { Ok(()) }
 }
 
@@ -84,5 +113,11 @@ fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
         self.push_all(buf);
         Ok(buf.len())
     }
+
+    fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
+        try!(self.write(buf));
+        Ok(())
+    }
+
     fn flush(&mut self) -> io::Result<()> { Ok(()) }
 }
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 d2dc33451200f5f866973f03939eecf2523613c5..dad0ff0a15e299424d265b076d15f20f229c525b 100644 (file)
@@ -23,7 +23,6 @@
 #[doc(no_inline)] pub use mem::drop;
 
 // Reexported types and traits
-
 #[stable(feature = "rust1", since = "1.0.0")]
 #[doc(no_inline)] pub use boxed::Box;
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -45,9 +44,7 @@
 #[stable(feature = "rust1", since = "1.0.0")]
 #[doc(no_inline)] pub use result::Result::{self, Ok, Err};
 #[stable(feature = "rust1", since = "1.0.0")]
-#[doc(no_inline)] pub use slice::AsSlice;
-#[stable(feature = "rust1", since = "1.0.0")]
-#[doc(no_inline)] pub use slice::{SliceExt, SliceConcatExt};
+#[doc(no_inline)] pub use slice::{SliceExt, SliceConcatExt, AsSlice};
 #[stable(feature = "rust1", since = "1.0.0")]
 #[doc(no_inline)] pub use str::{Str, StrExt};
 #[stable(feature = "rust1", since = "1.0.0")]
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 b036177af153a50da6ff9f4951ae7ea69d4cdffa..f697d10d5dfab14ad5f85ee1db0a45569f89fc52 100644 (file)
 pub struct Barrier {
     lock: Mutex<BarrierState>,
     cvar: Condvar,
-    num_threads: uint,
+    num_threads: usize,
 }
 
 // The inner state of a double barrier
 struct BarrierState {
-    count: uint,
-    generation_id: uint,
+    count: usize,
+    generation_id: usize,
 }
 
 /// A result returned from wait.
@@ -54,7 +54,7 @@ impl Barrier {
     /// A barrier will block `n`-1 threads which call `wait` and then wake up
     /// all threads at once when the `n`th thread calls `wait`.
     #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn new(n: uint) -> Barrier {
+    pub fn new(n: usize) -> Barrier {
         Barrier {
             lock: Mutex::new(BarrierState {
                 count: 0,
@@ -115,7 +115,7 @@ mod tests {
 
     #[test]
     fn test_barrier() {
-        const N: uint = 10;
+        const N: usize = 10;
 
         let barrier = Arc::new(Barrier::new(N));
         let (tx, rx) = channel();
index 52561d482c39dcc4b5acf9a05de030865870b91d..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")]
@@ -327,7 +321,7 @@ pub unsafe fn destroy(&'static self) {
     }
 
     fn verify(&self, mutex: &sys_mutex::Mutex) {
-        let addr = mutex as *const _ as uint;
+        let addr = mutex as *const _ as usize;
         match self.mutex.compare_and_swap(0, addr, Ordering::SeqCst) {
             // If we got out 0, then we have successfully bound the mutex to
             // this cvar.
@@ -388,7 +382,7 @@ fn notify_one() {
 
     #[test]
     fn notify_all() {
-        const N: uint = 10;
+        const N: usize = 10;
 
         let data = Arc::new((Mutex::new(0), Condvar::new()));
         let (tx, rx) = channel();
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 69b1e242b154d472857c032aab0ff00cdec3366c..2e4155ea35128d070c7854e304a40b58a30a87ac 100644 (file)
@@ -61,17 +61,17 @@ pub fn signal(&self) -> bool {
         wake
     }
 
-    /// Convert to an unsafe uint value. Useful for storing in a pipe's state
+    /// Convert to an unsafe usize value. Useful for storing in a pipe's state
     /// flag.
     #[inline]
-    pub unsafe fn cast_to_uint(self) -> uint {
+    pub unsafe fn cast_to_usize(self) -> usize {
         mem::transmute(self.inner)
     }
 
-    /// Convert from an unsafe uint value. Useful for retrieving a pipe's state
+    /// Convert from an unsafe usize value. Useful for retrieving a pipe's state
     /// flag.
     #[inline]
-    pub unsafe fn cast_from_uint(signal_ptr: uint) -> SignalToken {
+    pub unsafe fn cast_from_usize(signal_ptr: usize) -> SignalToken {
         SignalToken { inner: mem::transmute(signal_ptr) }
     }
 
index b437549a044920a7b923fba757d4c2634576ba1e..1310d476f8ee20f15540b6bc75f7df4a64eb7acc 100644 (file)
@@ -94,7 +94,7 @@
 //!
 //! // The call to recv() will return an error because the channel has already
 //! // hung up (or been deallocated)
-//! let (tx, rx) = channel::<int>();
+//! let (tx, rx) = channel::<i32>();
 //! drop(tx);
 //! assert!(rx.recv().is_err());
 //! ```
 //! use std::thread;
 //! use std::sync::mpsc::sync_channel;
 //!
-//! let (tx, rx) = sync_channel::<int>(0);
+//! let (tx, rx) = sync_channel::<i32>(0);
 //! thread::spawn(move|| {
 //!     // This will wait for the parent task to start receiving
 //!     tx.send(53).unwrap();
 //! use std::old_io::timer::Timer;
 //! use std::time::Duration;
 //!
-//! let (tx, rx) = channel::<int>();
+//! let (tx, rx) = channel::<i32>();
 //! let mut timer = Timer::new().unwrap();
 //! let timeout = timer.oneshot(Duration::seconds(10));
 //!
 //! use std::old_io::timer::Timer;
 //! use std::time::Duration;
 //!
-//! let (tx, rx) = channel::<int>();
+//! let (tx, rx) = channel::<i32>();
 //! let mut timer = Timer::new().unwrap();
 //!
 //! loop {
@@ -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`.
 ///
@@ -525,7 +525,7 @@ pub fn channel<T: Send>() -> (Sender<T>, Receiver<T>) {
 /// assert_eq!(rx.recv().unwrap(), 2);
 /// ```
 #[stable(feature = "rust1", since = "1.0.0")]
-pub fn sync_channel<T: Send>(bound: uint) -> (SyncSender<T>, Receiver<T>) {
+pub fn sync_channel<T: Send>(bound: usize) -> (SyncSender<T>, Receiver<T>) {
     let a = Arc::new(UnsafeCell::new(sync::Packet::new(bound)));
     (SyncSender::new(a.clone()), Receiver::new(Flavor::Sync(a)))
 }
@@ -1028,7 +1028,7 @@ mod test {
     use super::*;
     use thread;
 
-    pub fn stress_factor() -> uint {
+    pub fn stress_factor() -> usize {
         match env::var("RUST_TEST_STRESS") {
             Ok(val) => val.parse().unwrap(),
             Err(..) => 1,
@@ -1037,7 +1037,7 @@ pub fn stress_factor() -> uint {
 
     #[test]
     fn smoke() {
-        let (tx, rx) = channel::<int>();
+        let (tx, rx) = channel::<i32>();
         tx.send(1).unwrap();
         assert_eq!(rx.recv().unwrap(), 1);
     }
@@ -1058,7 +1058,7 @@ fn drop_full_shared() {
 
     #[test]
     fn smoke_shared() {
-        let (tx, rx) = channel::<int>();
+        let (tx, rx) = channel::<i32>();
         tx.send(1).unwrap();
         assert_eq!(rx.recv().unwrap(), 1);
         let tx = tx.clone();
@@ -1068,7 +1068,7 @@ fn smoke_shared() {
 
     #[test]
     fn smoke_threads() {
-        let (tx, rx) = channel::<int>();
+        let (tx, rx) = channel::<i32>();
         let _t = thread::spawn(move|| {
             tx.send(1).unwrap();
         });
@@ -1077,21 +1077,21 @@ fn smoke_threads() {
 
     #[test]
     fn smoke_port_gone() {
-        let (tx, rx) = channel::<int>();
+        let (tx, rx) = channel::<i32>();
         drop(rx);
         assert!(tx.send(1).is_err());
     }
 
     #[test]
     fn smoke_shared_port_gone() {
-        let (tx, rx) = channel::<int>();
+        let (tx, rx) = channel::<i32>();
         drop(rx);
         assert!(tx.send(1).is_err())
     }
 
     #[test]
     fn smoke_shared_port_gone2() {
-        let (tx, rx) = channel::<int>();
+        let (tx, rx) = channel::<i32>();
         drop(rx);
         let tx2 = tx.clone();
         drop(tx);
@@ -1100,7 +1100,7 @@ fn smoke_shared_port_gone2() {
 
     #[test]
     fn port_gone_concurrent() {
-        let (tx, rx) = channel::<int>();
+        let (tx, rx) = channel::<i32>();
         let _t = thread::spawn(move|| {
             rx.recv().unwrap();
         });
@@ -1109,7 +1109,7 @@ fn port_gone_concurrent() {
 
     #[test]
     fn port_gone_concurrent_shared() {
-        let (tx, rx) = channel::<int>();
+        let (tx, rx) = channel::<i32>();
         let tx2 = tx.clone();
         let _t = thread::spawn(move|| {
             rx.recv().unwrap();
@@ -1119,7 +1119,7 @@ fn port_gone_concurrent_shared() {
 
     #[test]
     fn smoke_chan_gone() {
-        let (tx, rx) = channel::<int>();
+        let (tx, rx) = channel::<i32>();
         drop(tx);
         assert!(rx.recv().is_err());
     }
@@ -1135,7 +1135,7 @@ fn smoke_chan_gone_shared() {
 
     #[test]
     fn chan_gone_concurrent() {
-        let (tx, rx) = channel::<int>();
+        let (tx, rx) = channel::<i32>();
         let _t = thread::spawn(move|| {
             tx.send(1).unwrap();
             tx.send(1).unwrap();
@@ -1145,7 +1145,7 @@ fn chan_gone_concurrent() {
 
     #[test]
     fn stress() {
-        let (tx, rx) = channel::<int>();
+        let (tx, rx) = channel::<i32>();
         let t = thread::spawn(move|| {
             for _ in 0..10000 { tx.send(1).unwrap(); }
         });
@@ -1157,9 +1157,9 @@ fn stress() {
 
     #[test]
     fn stress_shared() {
-        static AMT: uint = 10000;
-        static NTHREADS: uint = 8;
-        let (tx, rx) = channel::<int>();
+        static AMT: u32 = 10000;
+        static NTHREADS: u32 = 8;
+        let (tx, rx) = channel::<i32>();
 
         let t = thread::spawn(move|| {
             for _ in 0..AMT * NTHREADS {
@@ -1184,7 +1184,7 @@ fn stress_shared() {
     #[test]
     fn send_from_outside_runtime() {
         let (tx1, rx1) = channel::<()>();
-        let (tx2, rx2) = channel::<int>();
+        let (tx2, rx2) = channel::<i32>();
         let t1 = thread::spawn(move|| {
             tx1.send(()).unwrap();
             for _ in 0..40 {
@@ -1203,7 +1203,7 @@ fn send_from_outside_runtime() {
 
     #[test]
     fn recv_from_outside_runtime() {
-        let (tx, rx) = channel::<int>();
+        let (tx, rx) = channel::<i32>();
         let t = thread::spawn(move|| {
             for _ in 0..40 {
                 assert_eq!(rx.recv().unwrap(), 1);
@@ -1217,8 +1217,8 @@ fn recv_from_outside_runtime() {
 
     #[test]
     fn no_runtime() {
-        let (tx1, rx1) = channel::<int>();
-        let (tx2, rx2) = channel::<int>();
+        let (tx1, rx1) = channel::<i32>();
+        let (tx2, rx2) = channel::<i32>();
         let t1 = thread::spawn(move|| {
             assert_eq!(rx1.recv().unwrap(), 1);
             tx2.send(2).unwrap();
@@ -1234,21 +1234,21 @@ fn no_runtime() {
     #[test]
     fn oneshot_single_thread_close_port_first() {
         // Simple test of closing without sending
-        let (_tx, rx) = channel::<int>();
+        let (_tx, rx) = channel::<i32>();
         drop(rx);
     }
 
     #[test]
     fn oneshot_single_thread_close_chan_first() {
         // Simple test of closing without sending
-        let (tx, _rx) = channel::<int>();
+        let (tx, _rx) = channel::<i32>();
         drop(tx);
     }
 
     #[test]
     fn oneshot_single_thread_send_port_close() {
         // Testing that the sender cleans up the payload if receiver is closed
-        let (tx, rx) = channel::<Box<int>>();
+        let (tx, rx) = channel::<Box<i32>>();
         drop(rx);
         assert!(tx.send(box 0).is_err());
     }
@@ -1257,7 +1257,7 @@ fn oneshot_single_thread_send_port_close() {
     fn oneshot_single_thread_recv_chan_close() {
         // Receiving on a closed chan will panic
         let res = thread::spawn(move|| {
-            let (tx, rx) = channel::<int>();
+            let (tx, rx) = channel::<i32>();
             drop(tx);
             rx.recv().unwrap();
         }).join();
@@ -1267,42 +1267,42 @@ fn oneshot_single_thread_recv_chan_close() {
 
     #[test]
     fn oneshot_single_thread_send_then_recv() {
-        let (tx, rx) = channel::<Box<int>>();
+        let (tx, rx) = channel::<Box<i32>>();
         tx.send(box 10).unwrap();
         assert!(rx.recv().unwrap() == box 10);
     }
 
     #[test]
     fn oneshot_single_thread_try_send_open() {
-        let (tx, rx) = channel::<int>();
+        let (tx, rx) = channel::<i32>();
         assert!(tx.send(10).is_ok());
         assert!(rx.recv().unwrap() == 10);
     }
 
     #[test]
     fn oneshot_single_thread_try_send_closed() {
-        let (tx, rx) = channel::<int>();
+        let (tx, rx) = channel::<i32>();
         drop(rx);
         assert!(tx.send(10).is_err());
     }
 
     #[test]
     fn oneshot_single_thread_try_recv_open() {
-        let (tx, rx) = channel::<int>();
+        let (tx, rx) = channel::<i32>();
         tx.send(10).unwrap();
         assert!(rx.recv() == Ok(10));
     }
 
     #[test]
     fn oneshot_single_thread_try_recv_closed() {
-        let (tx, rx) = channel::<int>();
+        let (tx, rx) = channel::<i32>();
         drop(tx);
         assert!(rx.recv().is_err());
     }
 
     #[test]
     fn oneshot_single_thread_peek_data() {
-        let (tx, rx) = channel::<int>();
+        let (tx, rx) = channel::<i32>();
         assert_eq!(rx.try_recv(), Err(TryRecvError::Empty));
         tx.send(10).unwrap();
         assert_eq!(rx.try_recv(), Ok(10));
@@ -1310,7 +1310,7 @@ fn oneshot_single_thread_peek_data() {
 
     #[test]
     fn oneshot_single_thread_peek_close() {
-        let (tx, rx) = channel::<int>();
+        let (tx, rx) = channel::<i32>();
         drop(tx);
         assert_eq!(rx.try_recv(), Err(TryRecvError::Disconnected));
         assert_eq!(rx.try_recv(), Err(TryRecvError::Disconnected));
@@ -1318,13 +1318,13 @@ fn oneshot_single_thread_peek_close() {
 
     #[test]
     fn oneshot_single_thread_peek_open() {
-        let (_tx, rx) = channel::<int>();
+        let (_tx, rx) = channel::<i32>();
         assert_eq!(rx.try_recv(), Err(TryRecvError::Empty));
     }
 
     #[test]
     fn oneshot_multi_task_recv_then_send() {
-        let (tx, rx) = channel::<Box<int>>();
+        let (tx, rx) = channel::<Box<i32>>();
         let _t = thread::spawn(move|| {
             assert!(rx.recv().unwrap() == box 10);
         });
@@ -1334,7 +1334,7 @@ fn oneshot_multi_task_recv_then_send() {
 
     #[test]
     fn oneshot_multi_task_recv_then_close() {
-        let (tx, rx) = channel::<Box<int>>();
+        let (tx, rx) = channel::<Box<i32>>();
         let _t = thread::spawn(move|| {
             drop(tx);
         });
@@ -1347,7 +1347,7 @@ fn oneshot_multi_task_recv_then_close() {
     #[test]
     fn oneshot_multi_thread_close_stress() {
         for _ in 0..stress_factor() {
-            let (tx, rx) = channel::<int>();
+            let (tx, rx) = channel::<i32>();
             let _t = thread::spawn(move|| {
                 drop(rx);
             });
@@ -1358,7 +1358,7 @@ fn oneshot_multi_thread_close_stress() {
     #[test]
     fn oneshot_multi_thread_send_close_stress() {
         for _ in 0..stress_factor() {
-            let (tx, rx) = channel::<int>();
+            let (tx, rx) = channel::<i32>();
             let _t = thread::spawn(move|| {
                 drop(rx);
             });
@@ -1371,7 +1371,7 @@ fn oneshot_multi_thread_send_close_stress() {
     #[test]
     fn oneshot_multi_thread_recv_close_stress() {
         for _ in 0..stress_factor() {
-            let (tx, rx) = channel::<int>();
+            let (tx, rx) = channel::<i32>();
             thread::spawn(move|| {
                 let res = thread::spawn(move|| {
                     rx.recv().unwrap();
@@ -1405,7 +1405,7 @@ fn stream_send_recv_stress() {
             send(tx, 0);
             recv(rx, 0);
 
-            fn send(tx: Sender<Box<int>>, i: int) {
+            fn send(tx: Sender<Box<i32>>, i: i32) {
                 if i == 10 { return }
 
                 thread::spawn(move|| {
@@ -1414,7 +1414,7 @@ fn send(tx: Sender<Box<int>>, i: int) {
                 });
             }
 
-            fn recv(rx: Receiver<Box<int>>, i: int) {
+            fn recv(rx: Receiver<Box<i32>>, i: i32) {
                 if i == 10 { return }
 
                 thread::spawn(move|| {
@@ -1451,8 +1451,8 @@ fn shared_chan_stress() {
 
     #[test]
     fn test_nested_recv_iter() {
-        let (tx, rx) = channel::<int>();
-        let (total_tx, total_rx) = channel::<int>();
+        let (tx, rx) = channel::<i32>();
+        let (total_tx, total_rx) = channel::<i32>();
 
         let _t = thread::spawn(move|| {
             let mut acc = 0;
@@ -1471,7 +1471,7 @@ fn test_nested_recv_iter() {
 
     #[test]
     fn test_recv_iter_break() {
-        let (tx, rx) = channel::<int>();
+        let (tx, rx) = channel::<i32>();
         let (count_tx, count_rx) = channel();
 
         let _t = thread::spawn(move|| {
@@ -1496,7 +1496,7 @@ fn test_recv_iter_break() {
 
     #[test]
     fn try_recv_states() {
-        let (tx1, rx1) = channel::<int>();
+        let (tx1, rx1) = channel::<i32>();
         let (tx2, rx2) = channel::<()>();
         let (tx3, rx3) = channel::<()>();
         let _t = thread::spawn(move|| {
@@ -1550,7 +1550,7 @@ mod sync_tests {
     use thread;
     use super::*;
 
-    pub fn stress_factor() -> uint {
+    pub fn stress_factor() -> usize {
         match env::var("RUST_TEST_STRESS") {
             Ok(val) => val.parse().unwrap(),
             Err(..) => 1,
@@ -1559,7 +1559,7 @@ pub fn stress_factor() -> uint {
 
     #[test]
     fn smoke() {
-        let (tx, rx) = sync_channel::<int>(1);
+        let (tx, rx) = sync_channel::<i32>(1);
         tx.send(1).unwrap();
         assert_eq!(rx.recv().unwrap(), 1);
     }
@@ -1572,7 +1572,7 @@ fn drop_full() {
 
     #[test]
     fn smoke_shared() {
-        let (tx, rx) = sync_channel::<int>(1);
+        let (tx, rx) = sync_channel::<i32>(1);
         tx.send(1).unwrap();
         assert_eq!(rx.recv().unwrap(), 1);
         let tx = tx.clone();
@@ -1582,7 +1582,7 @@ fn smoke_shared() {
 
     #[test]
     fn smoke_threads() {
-        let (tx, rx) = sync_channel::<int>(0);
+        let (tx, rx) = sync_channel::<i32>(0);
         let _t = thread::spawn(move|| {
             tx.send(1).unwrap();
         });
@@ -1591,14 +1591,14 @@ fn smoke_threads() {
 
     #[test]
     fn smoke_port_gone() {
-        let (tx, rx) = sync_channel::<int>(0);
+        let (tx, rx) = sync_channel::<i32>(0);
         drop(rx);
         assert!(tx.send(1).is_err());
     }
 
     #[test]
     fn smoke_shared_port_gone2() {
-        let (tx, rx) = sync_channel::<int>(0);
+        let (tx, rx) = sync_channel::<i32>(0);
         drop(rx);
         let tx2 = tx.clone();
         drop(tx);
@@ -1607,7 +1607,7 @@ fn smoke_shared_port_gone2() {
 
     #[test]
     fn port_gone_concurrent() {
-        let (tx, rx) = sync_channel::<int>(0);
+        let (tx, rx) = sync_channel::<i32>(0);
         let _t = thread::spawn(move|| {
             rx.recv().unwrap();
         });
@@ -1616,7 +1616,7 @@ fn port_gone_concurrent() {
 
     #[test]
     fn port_gone_concurrent_shared() {
-        let (tx, rx) = sync_channel::<int>(0);
+        let (tx, rx) = sync_channel::<i32>(0);
         let tx2 = tx.clone();
         let _t = thread::spawn(move|| {
             rx.recv().unwrap();
@@ -1626,7 +1626,7 @@ fn port_gone_concurrent_shared() {
 
     #[test]
     fn smoke_chan_gone() {
-        let (tx, rx) = sync_channel::<int>(0);
+        let (tx, rx) = sync_channel::<i32>(0);
         drop(tx);
         assert!(rx.recv().is_err());
     }
@@ -1642,7 +1642,7 @@ fn smoke_chan_gone_shared() {
 
     #[test]
     fn chan_gone_concurrent() {
-        let (tx, rx) = sync_channel::<int>(0);
+        let (tx, rx) = sync_channel::<i32>(0);
         thread::spawn(move|| {
             tx.send(1).unwrap();
             tx.send(1).unwrap();
@@ -1652,7 +1652,7 @@ fn chan_gone_concurrent() {
 
     #[test]
     fn stress() {
-        let (tx, rx) = sync_channel::<int>(0);
+        let (tx, rx) = sync_channel::<i32>(0);
         thread::spawn(move|| {
             for _ in 0..10000 { tx.send(1).unwrap(); }
         });
@@ -1663,9 +1663,9 @@ fn stress() {
 
     #[test]
     fn stress_shared() {
-        static AMT: uint = 1000;
-        static NTHREADS: uint = 8;
-        let (tx, rx) = sync_channel::<int>(0);
+        static AMT: u32 = 1000;
+        static NTHREADS: u32 = 8;
+        let (tx, rx) = sync_channel::<i32>(0);
         let (dtx, drx) = sync_channel::<()>(0);
 
         thread::spawn(move|| {
@@ -1692,21 +1692,21 @@ fn stress_shared() {
     #[test]
     fn oneshot_single_thread_close_port_first() {
         // Simple test of closing without sending
-        let (_tx, rx) = sync_channel::<int>(0);
+        let (_tx, rx) = sync_channel::<i32>(0);
         drop(rx);
     }
 
     #[test]
     fn oneshot_single_thread_close_chan_first() {
         // Simple test of closing without sending
-        let (tx, _rx) = sync_channel::<int>(0);
+        let (tx, _rx) = sync_channel::<i32>(0);
         drop(tx);
     }
 
     #[test]
     fn oneshot_single_thread_send_port_close() {
         // Testing that the sender cleans up the payload if receiver is closed
-        let (tx, rx) = sync_channel::<Box<int>>(0);
+        let (tx, rx) = sync_channel::<Box<i32>>(0);
         drop(rx);
         assert!(tx.send(box 0).is_err());
     }
@@ -1715,7 +1715,7 @@ fn oneshot_single_thread_send_port_close() {
     fn oneshot_single_thread_recv_chan_close() {
         // Receiving on a closed chan will panic
         let res = thread::spawn(move|| {
-            let (tx, rx) = sync_channel::<int>(0);
+            let (tx, rx) = sync_channel::<i32>(0);
             drop(tx);
             rx.recv().unwrap();
         }).join();
@@ -1725,48 +1725,48 @@ fn oneshot_single_thread_recv_chan_close() {
 
     #[test]
     fn oneshot_single_thread_send_then_recv() {
-        let (tx, rx) = sync_channel::<Box<int>>(1);
+        let (tx, rx) = sync_channel::<Box<i32>>(1);
         tx.send(box 10).unwrap();
         assert!(rx.recv().unwrap() == box 10);
     }
 
     #[test]
     fn oneshot_single_thread_try_send_open() {
-        let (tx, rx) = sync_channel::<int>(1);
+        let (tx, rx) = sync_channel::<i32>(1);
         assert_eq!(tx.try_send(10), Ok(()));
         assert!(rx.recv().unwrap() == 10);
     }
 
     #[test]
     fn oneshot_single_thread_try_send_closed() {
-        let (tx, rx) = sync_channel::<int>(0);
+        let (tx, rx) = sync_channel::<i32>(0);
         drop(rx);
         assert_eq!(tx.try_send(10), Err(TrySendError::Disconnected(10)));
     }
 
     #[test]
     fn oneshot_single_thread_try_send_closed2() {
-        let (tx, _rx) = sync_channel::<int>(0);
+        let (tx, _rx) = sync_channel::<i32>(0);
         assert_eq!(tx.try_send(10), Err(TrySendError::Full(10)));
     }
 
     #[test]
     fn oneshot_single_thread_try_recv_open() {
-        let (tx, rx) = sync_channel::<int>(1);
+        let (tx, rx) = sync_channel::<i32>(1);
         tx.send(10).unwrap();
         assert!(rx.recv() == Ok(10));
     }
 
     #[test]
     fn oneshot_single_thread_try_recv_closed() {
-        let (tx, rx) = sync_channel::<int>(0);
+        let (tx, rx) = sync_channel::<i32>(0);
         drop(tx);
         assert!(rx.recv().is_err());
     }
 
     #[test]
     fn oneshot_single_thread_peek_data() {
-        let (tx, rx) = sync_channel::<int>(1);
+        let (tx, rx) = sync_channel::<i32>(1);
         assert_eq!(rx.try_recv(), Err(TryRecvError::Empty));
         tx.send(10).unwrap();
         assert_eq!(rx.try_recv(), Ok(10));
@@ -1774,7 +1774,7 @@ fn oneshot_single_thread_peek_data() {
 
     #[test]
     fn oneshot_single_thread_peek_close() {
-        let (tx, rx) = sync_channel::<int>(0);
+        let (tx, rx) = sync_channel::<i32>(0);
         drop(tx);
         assert_eq!(rx.try_recv(), Err(TryRecvError::Disconnected));
         assert_eq!(rx.try_recv(), Err(TryRecvError::Disconnected));
@@ -1782,13 +1782,13 @@ fn oneshot_single_thread_peek_close() {
 
     #[test]
     fn oneshot_single_thread_peek_open() {
-        let (_tx, rx) = sync_channel::<int>(0);
+        let (_tx, rx) = sync_channel::<i32>(0);
         assert_eq!(rx.try_recv(), Err(TryRecvError::Empty));
     }
 
     #[test]
     fn oneshot_multi_task_recv_then_send() {
-        let (tx, rx) = sync_channel::<Box<int>>(0);
+        let (tx, rx) = sync_channel::<Box<i32>>(0);
         let _t = thread::spawn(move|| {
             assert!(rx.recv().unwrap() == box 10);
         });
@@ -1798,7 +1798,7 @@ fn oneshot_multi_task_recv_then_send() {
 
     #[test]
     fn oneshot_multi_task_recv_then_close() {
-        let (tx, rx) = sync_channel::<Box<int>>(0);
+        let (tx, rx) = sync_channel::<Box<i32>>(0);
         let _t = thread::spawn(move|| {
             drop(tx);
         });
@@ -1811,7 +1811,7 @@ fn oneshot_multi_task_recv_then_close() {
     #[test]
     fn oneshot_multi_thread_close_stress() {
         for _ in 0..stress_factor() {
-            let (tx, rx) = sync_channel::<int>(0);
+            let (tx, rx) = sync_channel::<i32>(0);
             let _t = thread::spawn(move|| {
                 drop(rx);
             });
@@ -1822,7 +1822,7 @@ fn oneshot_multi_thread_close_stress() {
     #[test]
     fn oneshot_multi_thread_send_close_stress() {
         for _ in 0..stress_factor() {
-            let (tx, rx) = sync_channel::<int>(0);
+            let (tx, rx) = sync_channel::<i32>(0);
             let _t = thread::spawn(move|| {
                 drop(rx);
             });
@@ -1835,7 +1835,7 @@ fn oneshot_multi_thread_send_close_stress() {
     #[test]
     fn oneshot_multi_thread_recv_close_stress() {
         for _ in 0..stress_factor() {
-            let (tx, rx) = sync_channel::<int>(0);
+            let (tx, rx) = sync_channel::<i32>(0);
             let _t = thread::spawn(move|| {
                 let res = thread::spawn(move|| {
                     rx.recv().unwrap();
@@ -1853,7 +1853,7 @@ fn oneshot_multi_thread_recv_close_stress() {
     #[test]
     fn oneshot_multi_thread_send_recv_stress() {
         for _ in 0..stress_factor() {
-            let (tx, rx) = sync_channel::<Box<int>>(0);
+            let (tx, rx) = sync_channel::<Box<i32>>(0);
             let _t = thread::spawn(move|| {
                 tx.send(box 10).unwrap();
             });
@@ -1864,12 +1864,12 @@ fn oneshot_multi_thread_send_recv_stress() {
     #[test]
     fn stream_send_recv_stress() {
         for _ in 0..stress_factor() {
-            let (tx, rx) = sync_channel::<Box<int>>(0);
+            let (tx, rx) = sync_channel::<Box<i32>>(0);
 
             send(tx, 0);
             recv(rx, 0);
 
-            fn send(tx: SyncSender<Box<int>>, i: int) {
+            fn send(tx: SyncSender<Box<i32>>, i: i32) {
                 if i == 10 { return }
 
                 thread::spawn(move|| {
@@ -1878,7 +1878,7 @@ fn send(tx: SyncSender<Box<int>>, i: int) {
                 });
             }
 
-            fn recv(rx: Receiver<Box<int>>, i: int) {
+            fn recv(rx: Receiver<Box<i32>>, i: i32) {
                 if i == 10 { return }
 
                 thread::spawn(move|| {
@@ -1915,8 +1915,8 @@ fn shared_chan_stress() {
 
     #[test]
     fn test_nested_recv_iter() {
-        let (tx, rx) = sync_channel::<int>(0);
-        let (total_tx, total_rx) = sync_channel::<int>(0);
+        let (tx, rx) = sync_channel::<i32>(0);
+        let (total_tx, total_rx) = sync_channel::<i32>(0);
 
         let _t = thread::spawn(move|| {
             let mut acc = 0;
@@ -1935,7 +1935,7 @@ fn test_nested_recv_iter() {
 
     #[test]
     fn test_recv_iter_break() {
-        let (tx, rx) = sync_channel::<int>(0);
+        let (tx, rx) = sync_channel::<i32>(0);
         let (count_tx, count_rx) = sync_channel(0);
 
         let _t = thread::spawn(move|| {
@@ -1960,7 +1960,7 @@ fn test_recv_iter_break() {
 
     #[test]
     fn try_recv_states() {
-        let (tx1, rx1) = sync_channel::<int>(1);
+        let (tx1, rx1) = sync_channel::<i32>(1);
         let (tx2, rx2) = sync_channel::<()>(1);
         let (tx3, rx3) = sync_channel::<()>(1);
         let _t = thread::spawn(move|| {
@@ -2007,21 +2007,21 @@ fn destroy_upgraded_shared_port_when_sender_still_active() {
 
     #[test]
     fn send1() {
-        let (tx, rx) = sync_channel::<int>(0);
+        let (tx, rx) = sync_channel::<i32>(0);
         let _t = thread::spawn(move|| { rx.recv().unwrap(); });
         assert_eq!(tx.send(1), Ok(()));
     }
 
     #[test]
     fn send2() {
-        let (tx, rx) = sync_channel::<int>(0);
+        let (tx, rx) = sync_channel::<i32>(0);
         let _t = thread::spawn(move|| { drop(rx); });
         assert!(tx.send(1).is_err());
     }
 
     #[test]
     fn send3() {
-        let (tx, rx) = sync_channel::<int>(1);
+        let (tx, rx) = sync_channel::<i32>(1);
         assert_eq!(tx.send(1), Ok(()));
         let _t =thread::spawn(move|| { drop(rx); });
         assert!(tx.send(1).is_err());
@@ -2029,7 +2029,7 @@ fn send3() {
 
     #[test]
     fn send4() {
-        let (tx, rx) = sync_channel::<int>(0);
+        let (tx, rx) = sync_channel::<i32>(0);
         let tx2 = tx.clone();
         let (done, donerx) = channel();
         let done2 = done.clone();
@@ -2048,20 +2048,20 @@ fn send4() {
 
     #[test]
     fn try_send1() {
-        let (tx, _rx) = sync_channel::<int>(0);
+        let (tx, _rx) = sync_channel::<i32>(0);
         assert_eq!(tx.try_send(1), Err(TrySendError::Full(1)));
     }
 
     #[test]
     fn try_send2() {
-        let (tx, _rx) = sync_channel::<int>(1);
+        let (tx, _rx) = sync_channel::<i32>(1);
         assert_eq!(tx.try_send(1), Ok(()));
         assert_eq!(tx.try_send(1), Err(TrySendError::Full(1)));
     }
 
     #[test]
     fn try_send3() {
-        let (tx, rx) = sync_channel::<int>(1);
+        let (tx, rx) = sync_channel::<i32>(1);
         assert_eq!(tx.try_send(1), Ok(()));
         drop(rx);
         assert_eq!(tx.try_send(1), Err(TrySendError::Disconnected(1)));
index eb45681fa626d6e3018447c676efe23b688ce478..f287712d9d45d59bdc2eb7745ed4ddd468092fe0 100644 (file)
@@ -22,7 +22,7 @@
 ///
 /// # Implementation
 ///
-/// Oneshots are implemented around one atomic uint variable. This variable
+/// Oneshots are implemented around one atomic usize variable. This variable
 /// indicates both the state of the port/chan but also contains any tasks
 /// blocked on the port. All atomic operations happen on this one word.
 ///
@@ -45,9 +45,9 @@
 use sync::atomic::{AtomicUsize, Ordering};
 
 // Various states you can find a port in.
-const EMPTY: uint = 0;          // initial state: no data, no blocked receiver
-const DATA: uint = 1;           // data ready for receiver to take
-const DISCONNECTED: uint = 2;   // channel is disconnected OR upgraded
+const EMPTY: usize = 0;          // initial state: no data, no blocked receiver
+const DATA: usize = 1;           // data ready for receiver to take
+const DISCONNECTED: usize = 2;   // channel is disconnected OR upgraded
 // Any other value represents a pointer to a SignalToken value. The
 // protocol ensures that when the state moves *to* a pointer,
 // ownership of the token is given to the packet, and when the state
@@ -123,7 +123,7 @@ pub fn send(&mut self, t: T) -> Result<(), T> {
             // There is a thread waiting on the other end. We leave the 'DATA'
             // state inside so it'll pick it up on the other end.
             ptr => unsafe {
-                SignalToken::cast_from_uint(ptr).signal();
+                SignalToken::cast_from_usize(ptr).signal();
                 Ok(())
             }
         }
@@ -143,7 +143,7 @@ pub fn recv(&mut self) -> Result<T, Failure<T>> {
         // like we're not empty, then immediately go through to `try_recv`.
         if self.state.load(Ordering::SeqCst) == EMPTY {
             let (wait_token, signal_token) = blocking::tokens();
-            let ptr = unsafe { signal_token.cast_to_uint() };
+            let ptr = unsafe { signal_token.cast_to_usize() };
 
             // race with senders to enter the blocking state
             if self.state.compare_and_swap(EMPTY, ptr, Ordering::SeqCst) == EMPTY {
@@ -151,7 +151,7 @@ pub fn recv(&mut self) -> Result<T, Failure<T>> {
                 debug_assert!(self.state.load(Ordering::SeqCst) != EMPTY);
             } else {
                 // drop the signal token, since we never blocked
-                drop(unsafe { SignalToken::cast_from_uint(ptr) });
+                drop(unsafe { SignalToken::cast_from_usize(ptr) });
             }
         }
 
@@ -220,7 +220,7 @@ pub fn upgrade(&mut self, up: Receiver<T>) -> UpgradeResult {
             DISCONNECTED => { self.upgrade = prev; UpDisconnected }
 
             // If someone's waiting, we gotta wake them up
-            ptr => UpWoke(unsafe { SignalToken::cast_from_uint(ptr) })
+            ptr => UpWoke(unsafe { SignalToken::cast_from_usize(ptr) })
         }
     }
 
@@ -230,7 +230,7 @@ pub fn drop_chan(&mut self) {
 
             // If someone's waiting, we gotta wake them up
             ptr => unsafe {
-                SignalToken::cast_from_uint(ptr).signal();
+                SignalToken::cast_from_usize(ptr).signal();
             }
         }
     }
@@ -283,15 +283,15 @@ pub fn can_recv(&mut self) -> Result<bool, Receiver<T>> {
     // Attempts to start selection on this port. This can either succeed, fail
     // because there is data, or fail because there is an upgrade pending.
     pub fn start_selection(&mut self, token: SignalToken) -> SelectionResult<T> {
-        let ptr = unsafe { token.cast_to_uint() };
+        let ptr = unsafe { token.cast_to_usize() };
         match self.state.compare_and_swap(EMPTY, ptr, Ordering::SeqCst) {
             EMPTY => SelSuccess,
             DATA => {
-                drop(unsafe { SignalToken::cast_from_uint(ptr) });
+                drop(unsafe { SignalToken::cast_from_usize(ptr) });
                 SelCanceled
             }
             DISCONNECTED if self.data.is_some() => {
-                drop(unsafe { SignalToken::cast_from_uint(ptr) });
+                drop(unsafe { SignalToken::cast_from_usize(ptr) });
                 SelCanceled
             }
             DISCONNECTED => {
@@ -300,7 +300,7 @@ pub fn start_selection(&mut self, token: SignalToken) -> SelectionResult<T> {
                     // propagate upwards whether the upgrade can receive
                     // data
                     GoUp(upgrade) => {
-                        SelUpgraded(unsafe { SignalToken::cast_from_uint(ptr) }, upgrade)
+                        SelUpgraded(unsafe { SignalToken::cast_from_usize(ptr) }, upgrade)
                     }
 
                     // If the other end disconnected without sending an
@@ -308,7 +308,7 @@ pub fn start_selection(&mut self, token: SignalToken) -> SelectionResult<T> {
                     // disconnected).
                     up => {
                         self.upgrade = up;
-                        drop(unsafe { SignalToken::cast_from_uint(ptr) });
+                        drop(unsafe { SignalToken::cast_from_usize(ptr) });
                         SelCanceled
                     }
                 }
@@ -360,7 +360,7 @@ pub fn abort_selection(&mut self) -> Result<bool, Receiver<T>> {
 
             // We woke ourselves up from select.
             ptr => unsafe {
-                drop(SignalToken::cast_from_uint(ptr));
+                drop(SignalToken::cast_from_usize(ptr));
                 Ok(false)
             }
         }
index db8efe19dc1df973e3f37968c5ca138c47c46d9f..8de5bbc6206658c10d740bc67974e19edb00434f 100644 (file)
@@ -71,7 +71,7 @@
 pub struct Select {
     head: *mut Handle<'static, ()>,
     tail: *mut Handle<'static, ()>,
-    next_id: Cell<uint>,
+    next_id: Cell<usize>,
 }
 
 impl !marker::Send for Select {}
@@ -82,7 +82,7 @@ impl !marker::Send for Select {}
 pub struct Handle<'rx, T:'rx> {
     /// The ID of this handle, used to compare against the return value of
     /// `Select::wait()`
-    id: uint,
+    id: usize,
     selector: &'rx Select,
     next: *mut Handle<'static, ()>,
     prev: *mut Handle<'static, ()>,
@@ -154,12 +154,12 @@ pub fn handle<'a, T: Send>(&'a self, rx: &'a Receiver<T>) -> Handle<'a, T> {
     /// the matching `id` will have some sort of event available on it. The
     /// event could either be that data is available or the corresponding
     /// channel has been closed.
-    pub fn wait(&self) -> uint {
+    pub fn wait(&self) -> usize {
         self.wait2(true)
     }
 
     /// Helper method for skipping the preflight checks during testing
-    fn wait2(&self, do_preflight_checks: bool) -> uint {
+    fn wait2(&self, do_preflight_checks: bool) -> usize {
         // Note that this is currently an inefficient implementation. We in
         // theory have knowledge about all receivers in the set ahead of time,
         // so this method shouldn't really have to iterate over all of them yet
@@ -254,7 +254,7 @@ fn iter(&self) -> Packets { Packets { cur: self.head } }
 impl<'rx, T: Send> Handle<'rx, T> {
     /// Retrieve the id of this handle.
     #[inline]
-    pub fn id(&self) -> uint { self.id }
+    pub fn id(&self) -> usize { self.id }
 
     /// Block to receive a value on the underlying receiver, returning `Some` on
     /// success or `None` if the channel disconnects. This function has the same
@@ -369,8 +369,8 @@ macro_rules! select {
 
     #[test]
     fn smoke() {
-        let (tx1, rx1) = channel::<int>();
-        let (tx2, rx2) = channel::<int>();
+        let (tx1, rx1) = channel::<i32>();
+        let (tx2, rx2) = channel::<i32>();
         tx1.send(1).unwrap();
         select! {
             foo = rx1.recv() => { assert_eq!(foo.unwrap(), 1); },
@@ -394,11 +394,11 @@ fn smoke() {
 
     #[test]
     fn smoke2() {
-        let (_tx1, rx1) = channel::<int>();
-        let (_tx2, rx2) = channel::<int>();
-        let (_tx3, rx3) = channel::<int>();
-        let (_tx4, rx4) = channel::<int>();
-        let (tx5, rx5) = channel::<int>();
+        let (_tx1, rx1) = channel::<i32>();
+        let (_tx2, rx2) = channel::<i32>();
+        let (_tx3, rx3) = channel::<i32>();
+        let (_tx4, rx4) = channel::<i32>();
+        let (tx5, rx5) = channel::<i32>();
         tx5.send(4).unwrap();
         select! {
             _foo = rx1.recv() => { panic!("1") },
@@ -411,8 +411,8 @@ fn smoke2() {
 
     #[test]
     fn closed() {
-        let (_tx1, rx1) = channel::<int>();
-        let (tx2, rx2) = channel::<int>();
+        let (_tx1, rx1) = channel::<i32>();
+        let (tx2, rx2) = channel::<i32>();
         drop(tx2);
 
         select! {
@@ -423,9 +423,9 @@ fn closed() {
 
     #[test]
     fn unblocks() {
-        let (tx1, rx1) = channel::<int>();
-        let (_tx2, rx2) = channel::<int>();
-        let (tx3, rx3) = channel::<int>();
+        let (tx1, rx1) = channel::<i32>();
+        let (_tx2, rx2) = channel::<i32>();
+        let (tx3, rx3) = channel::<i32>();
 
         let _t = thread::spawn(move|| {
             for _ in 0..20 { thread::yield_now(); }
@@ -447,8 +447,8 @@ fn unblocks() {
 
     #[test]
     fn both_ready() {
-        let (tx1, rx1) = channel::<int>();
-        let (tx2, rx2) = channel::<int>();
+        let (tx1, rx1) = channel::<i32>();
+        let (tx2, rx2) = channel::<i32>();
         let (tx3, rx3) = channel::<()>();
 
         let _t = thread::spawn(move|| {
@@ -473,9 +473,9 @@ fn both_ready() {
 
     #[test]
     fn stress() {
-        static AMT: int = 10000;
-        let (tx1, rx1) = channel::<int>();
-        let (tx2, rx2) = channel::<int>();
+        static AMT: i32 = 10000;
+        let (tx1, rx1) = channel::<i32>();
+        let (tx2, rx2) = channel::<i32>();
         let (tx3, rx3) = channel::<()>();
 
         let _t = thread::spawn(move|| {
@@ -500,8 +500,8 @@ fn stress() {
 
     #[test]
     fn cloning() {
-        let (tx1, rx1) = channel::<int>();
-        let (_tx2, rx2) = channel::<int>();
+        let (tx1, rx1) = channel::<i32>();
+        let (_tx2, rx2) = channel::<i32>();
         let (tx3, rx3) = channel::<()>();
 
         let _t = thread::spawn(move|| {
@@ -522,8 +522,8 @@ fn cloning() {
 
     #[test]
     fn cloning2() {
-        let (tx1, rx1) = channel::<int>();
-        let (_tx2, rx2) = channel::<int>();
+        let (tx1, rx1) = channel::<i32>();
+        let (_tx2, rx2) = channel::<i32>();
         let (tx3, rx3) = channel::<()>();
 
         let _t = thread::spawn(move|| {
@@ -716,7 +716,7 @@ fn shared_data_waiting() {
 
     #[test]
     fn sync1() {
-        let (tx, rx) = sync_channel::<int>(1);
+        let (tx, rx) = sync_channel::<i32>(1);
         tx.send(1).unwrap();
         select! {
             n = rx.recv() => { assert_eq!(n.unwrap(), 1); }
@@ -725,7 +725,7 @@ fn sync1() {
 
     #[test]
     fn sync2() {
-        let (tx, rx) = sync_channel::<int>(0);
+        let (tx, rx) = sync_channel::<i32>(0);
         let _t = thread::spawn(move|| {
             for _ in 0..100 { thread::yield_now() }
             tx.send(1).unwrap();
@@ -737,8 +737,8 @@ fn sync2() {
 
     #[test]
     fn sync3() {
-        let (tx1, rx1) = sync_channel::<int>(0);
-        let (tx2, rx2): (Sender<int>, Receiver<int>) = channel();
+        let (tx1, rx1) = sync_channel::<i32>(0);
+        let (tx2, rx2): (Sender<i32>, Receiver<i32>) = channel();
         let _t = thread::spawn(move|| { tx1.send(1).unwrap(); });
         let _t = thread::spawn(move|| { tx2.send(2).unwrap(); });
         select! {
index 729e7991f97cfb2cb03c97c2854c253ee8dd0f7d..8d14824d37feed09e3e0c9916b2b2431b8897b4b 100644 (file)
@@ -101,7 +101,7 @@ pub fn inherit_blocker(&mut self,
         token.map(|token| {
             assert_eq!(self.cnt.load(Ordering::SeqCst), 0);
             assert_eq!(self.to_wake.load(Ordering::SeqCst), 0);
-            self.to_wake.store(unsafe { token.cast_to_uint() }, Ordering::SeqCst);
+            self.to_wake.store(unsafe { token.cast_to_usize() }, Ordering::SeqCst);
             self.cnt.store(-1, Ordering::SeqCst);
 
             // This store is a little sketchy. What's happening here is that
@@ -241,7 +241,7 @@ pub fn recv(&mut self) -> Result<T, Failure> {
     // Returns true if blocking should proceed.
     fn decrement(&mut self, token: SignalToken) -> StartResult {
         assert_eq!(self.to_wake.load(Ordering::SeqCst), 0);
-        let ptr = unsafe { token.cast_to_uint() };
+        let ptr = unsafe { token.cast_to_usize() };
         self.to_wake.store(ptr, Ordering::SeqCst);
 
         let steals = self.steals;
@@ -258,7 +258,7 @@ fn decrement(&mut self, token: SignalToken) -> StartResult {
         }
 
         self.to_wake.store(0, Ordering::SeqCst);
-        drop(unsafe { SignalToken::cast_from_uint(ptr) });
+        drop(unsafe { SignalToken::cast_from_usize(ptr) });
         Abort
     }
 
@@ -380,7 +380,7 @@ fn take_to_wake(&mut self) -> SignalToken {
         let ptr = self.to_wake.load(Ordering::SeqCst);
         self.to_wake.store(0, Ordering::SeqCst);
         assert!(ptr != 0);
-        unsafe { SignalToken::cast_from_uint(ptr) }
+        unsafe { SignalToken::cast_from_usize(ptr) }
     }
 
     ////////////////////////////////////////////////////////////////////////////
index 7b5c614536df98617c32c33af432ad9b7c75e7c7..ce40fa2672ab32555339aca56e87deed24dbf4a9 100644 (file)
@@ -69,7 +69,7 @@ pub struct Queue<T> {
 
     // Cache maintenance fields. Additions and subtractions are stored
     // separately in order to allow them to use nonatomic addition/subtraction.
-    cache_bound: uint,
+    cache_bound: usize,
     cache_additions: AtomicUsize,
     cache_subtractions: AtomicUsize,
 }
@@ -107,7 +107,7 @@ impl<T: Send> Queue<T> {
     ///               cache (if desired). If the value is 0, then the cache has
     ///               no bound. Otherwise, the cache will never grow larger than
     ///               `bound` (although the queue itself could be much larger.
-    pub unsafe fn new(bound: uint) -> Queue<T> {
+    pub unsafe fn new(bound: usize) -> Queue<T> {
         let n1 = Node::new();
         let n2 = Node::new();
         (*n1).next.store(n2, Ordering::Relaxed);
@@ -319,7 +319,7 @@ fn stress() {
             stress_bound(1);
         }
 
-        unsafe fn stress_bound(bound: uint) {
+        unsafe fn stress_bound(bound: usize) {
             let q = Arc::new(Queue::new(bound));
 
             let (tx, rx) = channel();
index 2d528662f64fc9dd3fa2f725cb7934bcaf3303c2..5a1e05f9c1565e1e28512f51685cc5b59849b20a 100644 (file)
@@ -43,7 +43,7 @@ pub struct Packet<T> {
     queue: spsc::Queue<Message<T>>, // internal queue for all message
 
     cnt: AtomicIsize, // How many items are on this channel
-    steals: int, // How many times has a port received without blocking?
+    steals: isize, // How many times has a port received without blocking?
     to_wake: AtomicUsize, // SignalToken for the blocked thread to wake up
 
     port_dropped: AtomicBool, // flag if the channel has been destroyed.
@@ -146,7 +146,7 @@ fn take_to_wake(&mut self) -> SignalToken {
         let ptr = self.to_wake.load(Ordering::SeqCst);
         self.to_wake.store(0, Ordering::SeqCst);
         assert!(ptr != 0);
-        unsafe { SignalToken::cast_from_uint(ptr) }
+        unsafe { SignalToken::cast_from_usize(ptr) }
     }
 
     // Decrements the count on the channel for a sleeper, returning the sleeper
@@ -154,7 +154,7 @@ fn take_to_wake(&mut self) -> SignalToken {
     // steals into account.
     fn decrement(&mut self, token: SignalToken) -> Result<(), SignalToken> {
         assert_eq!(self.to_wake.load(Ordering::SeqCst), 0);
-        let ptr = unsafe { token.cast_to_uint() };
+        let ptr = unsafe { token.cast_to_usize() };
         self.to_wake.store(ptr, Ordering::SeqCst);
 
         let steals = self.steals;
@@ -171,7 +171,7 @@ fn decrement(&mut self, token: SignalToken) -> Result<(), SignalToken> {
         }
 
         self.to_wake.store(0, Ordering::SeqCst);
-        Err(unsafe { SignalToken::cast_from_uint(ptr) })
+        Err(unsafe { SignalToken::cast_from_usize(ptr) })
     }
 
     pub fn recv(&mut self) -> Result<T, Failure<T>> {
@@ -350,7 +350,7 @@ pub fn can_recv(&mut self) -> Result<bool, Receiver<T>> {
     }
 
     // increment the count on the channel (used for selection)
-    fn bump(&mut self, amt: int) -> int {
+    fn bump(&mut self, amt: isize) -> isize {
         match self.cnt.fetch_add(amt, Ordering::SeqCst) {
             DISCONNECTED => {
                 self.cnt.store(DISCONNECTED, Ordering::SeqCst);
index 36b50b0d4af01fcad7a80b771e56e00a5b70fa79..33c1614e1b297dfe7037782d6533c6c6fe19a943 100644 (file)
@@ -64,7 +64,7 @@ struct State<T> {
     queue: Queue,       // queue of senders waiting to send data
     blocker: Blocker,   // currently blocked task on this channel
     buf: Buffer<T>,     // storage for buffered messages
-    cap: uint,          // capacity of this channel
+    cap: usize,         // capacity of this channel
 
     /// A curious flag used to indicate whether a sender failed or succeeded in
     /// blocking. This is used to transmit information back to the task that it
@@ -101,8 +101,8 @@ unsafe impl Send for Node {}
 /// A simple ring-buffer
 struct Buffer<T> {
     buf: Vec<Option<T>>,
-    start: uint,
-    size: uint,
+    start: usize,
+    size: usize,
 }
 
 #[derive(Debug)]
@@ -137,7 +137,7 @@ fn wakeup<T>(token: SignalToken, guard: MutexGuard<State<T>>) {
 }
 
 impl<T: Send> Packet<T> {
-    pub fn new(cap: uint) -> Packet<T> {
+    pub fn new(cap: usize) -> Packet<T> {
         Packet {
             channels: AtomicUsize::new(1),
             lock: Mutex::new(State {
@@ -442,8 +442,8 @@ fn dequeue(&mut self) -> T {
         result.take().unwrap()
     }
 
-    fn size(&self) -> uint { self.size }
-    fn cap(&self) -> uint { self.buf.len() }
+    fn size(&self) -> usize { self.size }
+    fn cap(&self) -> usize { self.buf.len() }
 }
 
 ////////////////////////////////////////////////////////////////////////////////
index b71cc0c26536474db76f2501e061da337ff8b23c..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
 ///
@@ -50,7 +51,7 @@
 /// use std::thread;
 /// use std::sync::mpsc::channel;
 ///
-/// const N: uint = 10;
+/// const N: usize = 10;
 ///
 /// // Spawn a few threads to increment a shared variable (non-atomically), and
 /// // let the main thread know once all increments are done.
@@ -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: () });
@@ -377,9 +389,9 @@ fn smoke_static() {
     #[test]
     fn lots_and_lots() {
         static M: StaticMutex = MUTEX_INIT;
-        static mut CNT: uint = 0;
-        static J: uint = 1000;
-        static K: uint = 3;
+        static mut CNT: u32 = 0;
+        static J: u32 = 1000;
+        static K: u32 = 3;
 
         fn inc() {
             for _ in 0..J {
@@ -501,7 +513,7 @@ fn test_mutex_arc_access_in_unwind() {
         let arc2 = arc.clone();
         let _ = thread::spawn(move|| -> () {
             struct Unwinder {
-                i: Arc<Mutex<int>>,
+                i: Arc<Mutex<i32>>,
             }
             impl Drop for Unwinder {
                 fn drop(&mut self) {
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 a45048be24c06a9e0eb37cba43cb7af6ab2b7017..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::*;
 
@@ -89,7 +91,7 @@ impl TaskPool {
     /// # Panics
     ///
     /// This function will panic if `threads` is 0.
-    pub fn new(threads: uint) -> TaskPool {
+    pub fn new(threads: usize) -> TaskPool {
         assert!(threads >= 1);
 
         let (tx, rx) = channel::<Thunk>();
@@ -142,7 +144,7 @@ mod test {
     use super::*;
     use sync::mpsc::channel;
 
-    const TEST_TASKS: uint = 4;
+    const TEST_TASKS: usize = 4;
 
     #[test]
     fn test_works() {
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 6f07dea5279fdcaf72e95b207a918d07e6651ff5..6267792ba745e5ffa82bcca807c959d8ed4dd2a5 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;
@@ -327,7 +328,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 92a47c6c3850df3a34b3ac132e83f72314db86d6..72e0b8dd36c66151eab686d374a2f44f928c42d3 100644 (file)
@@ -18,7 +18,7 @@
 use mem;
 use path::{Path, PathBuf};
 use ptr;
-use rc::Rc;
+use sync::Arc;
 use sys::fd::FileDesc;
 use sys::{c, cvt, cvt_r};
 use sys_common::FromInner;
@@ -31,14 +31,18 @@ pub struct FileAttr {
 }
 
 pub struct ReadDir {
-    dirp: *mut libc::DIR,
-    root: Rc<PathBuf>,
+    dirp: Dir,
+    root: Arc<PathBuf>,
 }
 
+struct Dir(*mut libc::DIR);
+
+unsafe impl Send for Dir {}
+unsafe impl Sync for Dir {}
+
 pub struct DirEntry {
-    buf: Vec<u8>,
-    dirent: *mut libc::dirent_t,
-    root: Rc<PathBuf>,
+    buf: Vec<u8>, // actually *mut libc::dirent_t
+    root: Arc<PathBuf>,
 }
 
 #[derive(Clone)]
@@ -86,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 {
@@ -109,7 +114,7 @@ fn next(&mut self) -> Option<io::Result<DirEntry>> {
 
         let mut entry_ptr = ptr::null_mut();
         loop {
-            if unsafe { libc::readdir_r(self.dirp, ptr, &mut entry_ptr) != 0 } {
+            if unsafe { libc::readdir_r(self.dirp.0, ptr, &mut entry_ptr) != 0 } {
                 return Some(Err(Error::last_os_error()))
             }
             if entry_ptr.is_null() {
@@ -118,7 +123,6 @@ fn next(&mut self) -> Option<io::Result<DirEntry>> {
 
             let entry = DirEntry {
                 buf: buf,
-                dirent: entry_ptr,
                 root: self.root.clone()
             };
             if entry.name_bytes() == b"." || entry.name_bytes() == b".." {
@@ -130,9 +134,9 @@ fn next(&mut self) -> Option<io::Result<DirEntry>> {
     }
 }
 
-impl Drop for ReadDir {
+impl Drop for Dir {
     fn drop(&mut self) {
-        let r = unsafe { libc::closedir(self.dirp) };
+        let r = unsafe { libc::closedir(self.0) };
         debug_assert_eq!(r, 0);
     }
 }
@@ -147,9 +151,13 @@ fn name_bytes(&self) -> &[u8] {
             fn rust_list_dir_val(ptr: *mut libc::dirent_t) -> *const c_char;
         }
         unsafe {
-            CStr::from_ptr(rust_list_dir_val(self.dirent)).to_bytes()
+            CStr::from_ptr(rust_list_dir_val(self.dirent())).to_bytes()
         }
     }
+
+    fn dirent(&self) -> *mut libc::dirent_t {
+        self.buf.as_ptr() as *mut _
+    }
 }
 
 impl OpenOptions {
@@ -279,14 +287,14 @@ pub fn mkdir(p: &Path) -> io::Result<()> {
 }
 
 pub fn readdir(p: &Path) -> io::Result<ReadDir> {
-    let root = Rc::new(p.to_path_buf());
+    let root = Arc::new(p.to_path_buf());
     let p = try!(cstr(p));
     unsafe {
         let ptr = libc::opendir(p.as_ptr());
         if ptr.is_null() {
             Err(Error::last_os_error())
         } else {
-            Ok(ReadDir { dirp: ptr, root: root })
+            Ok(ReadDir { dirp: Dir(ptr), root: root })
         }
     }
 }
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 8abcd90efe8578a6cab8523babf818b1a12e8b44..117f819eeeb3fd870ac36dc485d6874630ad0ced 100644 (file)
@@ -19,6 +19,7 @@
 use mem;
 use path::{Path, PathBuf};
 use ptr;
+use sync::Arc;
 use sys::handle::Handle as RawHandle;
 use sys::{c, cvt};
 use vec::Vec;
@@ -27,12 +28,20 @@ pub struct File { handle: RawHandle }
 pub struct FileAttr { data: c::WIN32_FILE_ATTRIBUTE_DATA }
 
 pub struct ReadDir {
-    handle: libc::HANDLE,
-    root: PathBuf,
+    handle: FindNextFileHandle,
+    root: Arc<PathBuf>,
     first: Option<libc::WIN32_FIND_DATAW>,
 }
 
-pub struct DirEntry { path: PathBuf }
+struct FindNextFileHandle(libc::HANDLE);
+
+unsafe impl Send for FindNextFileHandle {}
+unsafe impl Sync for FindNextFileHandle {}
+
+pub struct DirEntry {
+    root: Arc<PathBuf>,
+    data: libc::WIN32_FIND_DATAW,
+}
 
 #[derive(Clone, Default)]
 pub struct OpenOptions {
@@ -61,7 +70,7 @@ fn next(&mut self) -> Option<io::Result<DirEntry>> {
         unsafe {
             let mut wfd = mem::zeroed();
             loop {
-                if libc::FindNextFileW(self.handle, &mut wfd) == 0 {
+                if libc::FindNextFileW(self.handle.0, &mut wfd) == 0 {
                     if libc::GetLastError() ==
                         c::ERROR_NO_MORE_FILES as libc::DWORD {
                         return None
@@ -77,15 +86,15 @@ fn next(&mut self) -> Option<io::Result<DirEntry>> {
     }
 }
 
-impl Drop for ReadDir {
+impl Drop for FindNextFileHandle {
     fn drop(&mut self) {
-        let r = unsafe { libc::FindClose(self.handle) };
+        let r = unsafe { libc::FindClose(self.0) };
         debug_assert!(r != 0);
     }
 }
 
 impl DirEntry {
-    fn new(root: &Path, wfd: &libc::WIN32_FIND_DATAW) -> Option<DirEntry> {
+    fn new(root: &Arc<PathBuf>, wfd: &libc::WIN32_FIND_DATAW) -> Option<DirEntry> {
         match &wfd.cFileName[0..3] {
             // check for '.' and '..'
             [46, 0, ..] |
@@ -93,13 +102,15 @@ fn new(root: &Path, wfd: &libc::WIN32_FIND_DATAW) -> Option<DirEntry> {
             _ => {}
         }
 
-        let filename = super::truncate_utf16_at_nul(&wfd.cFileName);
-        let filename: OsString = OsStringExt::from_wide(filename);
-        Some(DirEntry { path: root.join(&filename) })
+        Some(DirEntry {
+            root: root.clone(),
+            data: *wfd,
+        })
     }
 
     pub fn path(&self) -> PathBuf {
-        self.path.clone()
+        let filename = super::truncate_utf16_at_nul(&self.data.cFileName);
+        self.root.join(&<OsString as OsStringExt>::from_wide(filename))
     }
 }
 
@@ -312,7 +323,11 @@ pub fn readdir(p: &Path) -> io::Result<ReadDir> {
         let mut wfd = mem::zeroed();
         let find_handle = libc::FindFirstFileW(path.as_ptr(), &mut wfd);
         if find_handle != libc::INVALID_HANDLE_VALUE {
-            Ok(ReadDir { handle: find_handle, root: root, first: Some(wfd) })
+            Ok(ReadDir {
+                handle: FindNextFileHandle(find_handle),
+                root: Arc::new(root),
+                first: Some(wfd),
+            })
         } else {
             Err(Error::last_os_error())
         }
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 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 1f70e1526a096c61c5b0c50d1d14704d9d6c0a27..6aad2bbcc7f08b47ab57f6dbd0f097cedbd2ce08 100644 (file)
@@ -342,12 +342,15 @@ fn spawn_inner<T: Send>(self, f: Thunk<(), T>) -> io::Result<JoinInner<T>> {
     }
 }
 
-/// Spawn a new, returning a join handle for it.
+/// Spawn a new thread, returning a `JoinHandle` for it.
 ///
-/// The child thread may outlive the parent (unless the parent thread
-/// is the main thread; the whole process is terminated when the main
-/// thread finishes.) The join handle can be used to block on
-/// termination of the child thread, including recovering its panics.
+/// The join handle will implicitly *detach* the child thread upon being
+/// dropped. In this case, the child thread may outlive the parent (unless
+/// the parent thread is the main thread; the whole process is terminated when
+/// the main thread finishes.) Additionally, the join handle provides a `join`
+/// method that can be used to join the child thread. If the child thread
+/// panics, `join` will return an `Err` containing the argument given to
+/// `panic`.
 ///
 /// # Panics
 ///
index cdd71d440fe4f014f82fce90fd2475bb5612f56b..764c7d730cb0e448d4c20c390c08769e3624fa49 100644 (file)
@@ -74,7 +74,7 @@ pub mod __impl {
 /// use std::cell::RefCell;
 /// use std::thread;
 ///
-/// thread_local!(static FOO: RefCell<uint> = RefCell::new(1));
+/// thread_local!(static FOO: RefCell<u32> = RefCell::new(1));
 ///
 /// FOO.with(|f| {
 ///     assert_eq!(*f.borrow(), 1);
@@ -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,
 }
 
@@ -503,7 +505,7 @@ pub unsafe fn get(&'static self) -> Option<&'static T> {
         unsafe fn ptr(&'static self) -> Option<*mut T> {
             let ptr = self.os.get() as *mut Value<T>;
             if !ptr.is_null() {
-                if ptr as uint == 1 {
+                if ptr as usize == 1 {
                     return None
                 }
                 return Some(&mut (*ptr).value as *mut T);
@@ -563,7 +565,7 @@ fn drop(&mut self) {
 
     #[test]
     fn smoke_no_dtor() {
-        thread_local!(static FOO: UnsafeCell<int> = UnsafeCell { value: 1 });
+        thread_local!(static FOO: UnsafeCell<i32> = UnsafeCell { value: 1 });
 
         FOO.with(|f| unsafe {
             assert_eq!(*f.get(), 1);
@@ -632,7 +634,7 @@ fn circular() {
         thread_local!(static K2: UnsafeCell<Option<S2>> = UnsafeCell {
             value: None
         });
-        static mut HITS: uint = 0;
+        static mut HITS: u32 = 0;
 
         impl Drop for S1 {
             fn drop(&mut self) {
@@ -723,8 +725,8 @@ mod dynamic_tests {
 
     #[test]
     fn smoke() {
-        fn square(i: int) -> int { i * i }
-        thread_local!(static FOO: int = square(3));
+        fn square(i: i32) -> i32 { i * i }
+        thread_local!(static FOO: i32 = square(3));
 
         FOO.with(|f| {
             assert_eq!(*f, 9);
@@ -733,12 +735,12 @@ fn square(i: int) -> int { i * i }
 
     #[test]
     fn hashmap() {
-        fn map() -> RefCell<HashMap<int, int>> {
+        fn map() -> RefCell<HashMap<i32, i32>> {
             let mut m = HashMap::new();
             m.insert(1, 2);
             RefCell::new(m)
         }
-        thread_local!(static FOO: RefCell<HashMap<int, int>> = map());
+        thread_local!(static FOO: RefCell<HashMap<i32, i32>> = map());
 
         FOO.with(|map| {
             assert_eq!(map.borrow()[1], 2);
@@ -747,7 +749,7 @@ fn map() -> RefCell<HashMap<int, int>> {
 
     #[test]
     fn refcell_vec() {
-        thread_local!(static FOO: RefCell<Vec<uint>> = RefCell::new(vec![1, 2, 3]));
+        thread_local!(static FOO: RefCell<Vec<u32>> = RefCell::new(vec![1, 2, 3]));
 
         FOO.with(|vec| {
             assert_eq!(vec.borrow().len(), 3);
index 01220e7bc1fe1d0baf0460af5dab84a342b94e4a..a2a5d8b81f40458e43b018fe77bb9d5426ee294d 100644 (file)
@@ -24,7 +24,7 @@
 //! # Example
 //!
 //! ```
-//! scoped_thread_local!(static FOO: uint);
+//! scoped_thread_local!(static FOO: u32);
 //!
 //! // Initially each scoped slot is empty.
 //! assert!(!FOO.is_set());
@@ -140,7 +140,7 @@ impl<T> Key<T> {
     /// # Example
     ///
     /// ```
-    /// scoped_thread_local!(static FOO: uint);
+    /// scoped_thread_local!(static FOO: u32);
     ///
     /// FOO.set(&100, || {
     ///     let val = FOO.with(|v| *v);
@@ -192,7 +192,7 @@ fn drop(&mut self) {
     /// # Example
     ///
     /// ```no_run
-    /// scoped_thread_local!(static FOO: uint);
+    /// scoped_thread_local!(static FOO: u32);
     ///
     /// FOO.with(|slot| {
     ///     // work with `slot`
@@ -269,11 +269,11 @@ mod tests {
     use cell::Cell;
     use prelude::v1::*;
 
-    scoped_thread_local!(static FOO: uint);
+    scoped_thread_local!(static FOO: u32);
 
     #[test]
     fn smoke() {
-        scoped_thread_local!(static BAR: uint);
+        scoped_thread_local!(static BAR: u32);
 
         assert!(!BAR.is_set());
         BAR.set(&1, || {
@@ -287,7 +287,7 @@ fn smoke() {
 
     #[test]
     fn cell_allowed() {
-        scoped_thread_local!(static BAR: Cell<uint>);
+        scoped_thread_local!(static BAR: Cell<u32>);
 
         BAR.set(&Cell::new(1), || {
             BAR.with(|slot| {
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..79f0433761da531ec4a01d34401a344ce1efed58 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,
index c79b510ae2dde92db1bd0fd2148732a76f1567ca..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> {
@@ -702,12 +702,12 @@ fn expr_int(&self, sp: Span, i: isize) -> P<ast::Expr> {
         self.expr_lit(sp, ast::LitInt(i as u64, ast::SignedIntLit(ast::TyIs(false),
                                                                   ast::Sign::new(i))))
     }
-    fn expr_u8(&self, sp: Span, u: u8) -> P<ast::Expr> {
-        self.expr_lit(sp, ast::LitInt(u as u64, ast::UnsignedIntLit(ast::TyU8)))
-    }
     fn expr_u32(&self, sp: Span, u: u32) -> P<ast::Expr> {
         self.expr_lit(sp, ast::LitInt(u as u64, ast::UnsignedIntLit(ast::TyU32)))
     }
+    fn expr_u8(&self, sp: Span, u: u8) -> P<ast::Expr> {
+        self.expr_lit(sp, ast::LitInt(u as u64, ast::UnsignedIntLit(ast::TyU8)))
+    }
     fn expr_bool(&self, sp: Span, value: bool) -> P<ast::Expr> {
         self.expr_lit(sp, ast::LitBool(value))
     }
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 1c2374e31f13037820596790264e98aeea593981..91262556abd706f72ee4bcc91b90d279d1292221 100644 (file)
@@ -417,7 +417,7 @@ fn trans_piece(&mut self, piece: &parse::Piece) -> Option<P<ast::Expr>> {
                     parse::AlignUnknown => align("Unknown"),
                 };
                 let align = self.ecx.expr_path(align);
-                let flags = self.ecx.expr_usize(sp, arg.format.flags);
+                let flags = self.ecx.expr_u32(sp, arg.format.flags);
                 let prec = self.trans_count(arg.format.precision);
                 let width = self.trans_count(arg.format.width);
                 let path = self.ecx.path_global(sp, Context::rtpath(self.ecx, "FormatSpec"));
@@ -610,7 +610,7 @@ fn format_arg(ecx: &ExtCtxt, sp: Span,
                         ecx.ident_of_std("core"),
                         ecx.ident_of("fmt"),
                         ecx.ident_of("ArgumentV1"),
-                        ecx.ident_of("from_uint")], vec![arg])
+                        ecx.ident_of("from_usize")], vec![arg])
             }
         };
 
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 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 dd272bf639b9723cb53da920f1c2502b250266ac..96a06968c5fa3cc961496cba8a20ee33163eddc7 100644 (file)
@@ -17,7 +17,7 @@ pub struct cat {
       pub name : String,
     }
 
-    impl fmt::String for cat {
+    impl fmt::Display for cat {
         fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
             write!(f, "{}", self.name)
         }
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);
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() {
+}
index d4decb713498df2e3e35eff101178d59b87af488..98a9c713e84c331c9d305a63ff0ffa0cb79cec4f 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use std::fmt::Show;
+use std::fmt::Debug;
 use std::default::Default;
 use std::marker::MarkerTrait;
 
index b1ee1762b6e71ab2d9c722de3564acc3da722821..57d25a3bf586dcab40fe8df4857095ca8db25ed7 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use std::fmt::Show;
+use std::fmt::Debug;
 use std::default::Default;
 
 // Test that two blanket impls conflict (at least without negative
index 1f6bb08871c76db6ff94850c8fb35d2c3be3548f..b3ef79c6cc01e98474df89b02339b3406df1f5fa 100644 (file)
@@ -13,7 +13,7 @@
 extern crate go_trait;
 
 use go_trait::{Go,GoMut};
-use std::fmt::Show;
+use std::fmt::Debug;
 use std::default::Default;
 
 struct MyThingy;
index c3563792ce3c7d2e5b9f8c17a183560838ff5f9a..7b60a5ecbd71f4ac8533599cfb20cb73c4b42a71 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use std::fmt::Show;
+use std::fmt::Debug;
 use std::default::Default;
 
 // Test that a blank impl for all T conflicts with an impl for some
index 980e4256d2b854d635c4ccdaff00a97a4d710025..d218b64af05270f0dec430b4b1001d410edfd0e9 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use std::fmt::Show;
+use std::fmt::Debug;
 use std::default::Default;
 
 // Test that a blank impl for all T conflicts with an impl for some
index 9673fb6a21392dd3e619715beaa4c51b98fa31c2..87b007fdd698239d3af23c2558975c29ad994eb2 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use std::fmt::Show;
+use std::fmt::Debug;
 use std::default::Default;
 
 // Test that a blank impl for all T conflicts with an impl for some
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 71e1f7091b2c99094e9459e64ba25fe261906ecc..d682ef7d70c9db931e5cbb28f74bee4b2c3ed41c 100644 (file)
@@ -15,8 +15,7 @@ fn needs_fn<F>(x: F) where F: Fn(isize) -> isize {}
 
 fn main() {
     let _: () = (box |_: isize| {}) as Box<FnOnce(isize)>;
-    //~^ ERROR object-safe
-    //~| ERROR mismatched types
+    //~^ ERROR mismatched types
     //~| expected `()`
     //~| found `Box<core::ops::FnOnce(isize)>`
     //~| expected ()
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 2642ac6204ce4d8490f021c563994e7dd52c3b58..d39efa3c2ab78f909815c6db507a9a0be4a6419a 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
+// 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.
 //
@@ -8,28 +8,34 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// error-pattern: reached the recursion limit during monomorphization
-// issue 2258
+//~^^^^^^^^^^ ERROR overflow
+//
+// We get an error message at the top of file (dummy span).
+// This is not helpful, but also kind of annoying to prevent,
+// so for now just live with it.
+// This test case was originally for issue #2258.
 
-trait to_opt {
+trait ToOpt {
     fn to_option(&self) -> Option<Self>;
 }
 
-impl to_opt for usize {
+impl ToOpt for usize {
     fn to_option(&self) -> Option<usize> {
         Some(*self)
     }
 }
 
-impl<T:Clone> to_opt for Option<T> {
+impl<T:Clone> ToOpt for Option<T> {
     fn to_option(&self) -> Option<Option<T>> {
         Some((*self).clone())
     }
 }
 
-fn function<T:to_opt + Clone>(counter: usize, t: T) {
+fn function<T:ToOpt + Clone>(counter: usize, t: T) {
     if counter > 0_usize {
         function(counter - 1_usize, t.to_option());
+        // FIXME(#4287) Error message should be here. It should be
+        // a type error to instantiate `test` at a type other than T.
     }
 }
 
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 321b8b260daa9c6c04d2285889b108cce1c08dba..9f76f360f26ba7db9cf81f7def9321c8110111ad 100644 (file)
@@ -14,11 +14,11 @@ fn main() {
     let _foo = &[1_usize, 2] as [usize];
     //~^ ERROR cast to unsized type: `&[usize; 2]` as `[usize]`
     //~^^ HELP consider using an implicit coercion to `&[usize]` instead
-    let _bar = box 1_usize as std::fmt::Show;
-    //~^ ERROR cast to unsized type: `Box<usize>` as `core::fmt::Show`
-    //~^^ HELP did you mean `Box<core::fmt::Show>`?
-    let _baz = 1_usize as std::fmt::Show;
-    //~^ ERROR cast to unsized type: `usize` as `core::fmt::Show`
+    let _bar = box 1_usize as std::fmt::Debug;
+    //~^ ERROR cast to unsized type: `Box<usize>` as `core::fmt::Debug`
+    //~^^ HELP did you mean `Box<core::fmt::Debug>`?
+    let _baz = 1_usize as std::fmt::Debug;
+    //~^ ERROR cast to unsized type: `usize` as `core::fmt::Debug`
     //~^^ HELP consider using a box or reference as appropriate
     let _quux = [1_usize, 2] as [usize];
     //~^ ERROR cast to unsized type: `[usize; 2]` as `[usize]`
index 368f3c16f5188c47debf096ae1caedd17426be68..8fb543fb96703cda1a50fc7c0731dfc11288656f 100644 (file)
@@ -17,7 +17,11 @@ impl Foo for Thing {
     fn foo<T>(&self, _: &T) {}
 }
 
-#[inline(never)] fn foo(b: &Bar) { b.foo(&0_usize) }
+#[inline(never)]
+fn foo(b: &Bar) {
+    b.foo(&0usize)
+    //~^ ERROR the trait `Foo` is not implemented for the type `Bar`
+}
 
 fn main() {
     let mut thing = Thing;
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() {
index 73a58741bbbbc42ddbcf7efa384d9d578f86fed4..cb2d4e10e6e7166237e4e459a2c35b08f4c7ec50 100644 (file)
 #![doc="More garbage"]
 
 type Typedef = String;
-pub type PubTypedef = String; //~ ERROR: missing documentation
+pub type PubTypedef = String; //~ ERROR: missing documentation for a type alias
 
 struct Foo {
     a: isize,
     b: isize,
 }
 
-pub struct PubFoo { //~ ERROR: missing documentation
-    pub a: isize,      //~ ERROR: missing documentation
+pub struct PubFoo { //~ ERROR: missing documentation for a struct
+    pub a: isize,      //~ ERROR: missing documentation for a struct field
     b: isize,
 }
 
@@ -36,11 +36,11 @@ pub struct PubFoo2 {
 }
 
 mod module_no_dox {}
-pub mod pub_module_no_dox {} //~ ERROR: missing documentation
+pub mod pub_module_no_dox {} //~ ERROR: missing documentation for a module
 
 /// dox
 pub fn foo() {}
-pub fn foo2() {} //~ ERROR: missing documentation
+pub fn foo2() {} //~ ERROR: missing documentation for a function
 fn foo3() {}
 #[allow(missing_docs)] pub fn foo4() {}
 
@@ -58,9 +58,9 @@ trait B {
     fn foo_with_impl(&self) {}
 }
 
-pub trait C { //~ ERROR: missing documentation
-    fn foo(&self); //~ ERROR: missing documentation
-    fn foo_with_impl(&self) {} //~ ERROR: missing documentation
+pub trait C { //~ ERROR: missing documentation for a trait
+    fn foo(&self); //~ ERROR: missing documentation for a type method
+    fn foo_with_impl(&self) {} //~ ERROR: missing documentation for a method
 }
 
 #[allow(missing_docs)]
@@ -68,13 +68,26 @@ pub trait D {
     fn dummy(&self) { }
 }
 
+/// dox
+pub trait E {
+    type AssociatedType; //~ ERROR: missing documentation for an associated type
+    type AssociatedTypeDef = Self; //~ ERROR: missing documentation for an associated type
+
+    /// dox
+    type DocumentedType;
+    /// dox
+    type DocumentedTypeDef = Self;
+    /// dox
+    fn dummy(&self) {}
+}
+
 impl Foo {
     pub fn foo() {}
     fn bar() {}
 }
 
 impl PubFoo {
-    pub fn foo() {} //~ ERROR: missing documentation
+    pub fn foo() {} //~ ERROR: missing documentation for a method
     /// dox
     pub fn foo1() {}
     fn foo2() {}
@@ -111,9 +124,9 @@ enum Baz {
     BarB
 }
 
-pub enum PubBaz { //~ ERROR: missing documentation
-    PubBazA { //~ ERROR: missing documentation
-        a: isize, //~ ERROR: missing documentation
+pub enum PubBaz { //~ ERROR: missing documentation for an enum
+    PubBazA { //~ ERROR: missing documentation for a variant
+        a: isize, //~ ERROR: missing documentation for a struct field
     },
 }
 
@@ -139,14 +152,14 @@ pub fn baz() {}
 mod internal_impl {
     /// dox
     pub fn documented() {}
-    pub fn undocumented1() {} //~ ERROR: missing documentation
-    pub fn undocumented2() {} //~ ERROR: missing documentation
+    pub fn undocumented1() {} //~ ERROR: missing documentation for a function
+    pub fn undocumented2() {} //~ ERROR: missing documentation for a function
     fn undocumented3() {}
     /// dox
     pub mod globbed {
         /// dox
         pub fn also_documented() {}
-        pub fn also_undocumented1() {} //~ ERROR: missing documentation
+        pub fn also_undocumented1() {} //~ ERROR: missing documentation for a function
         fn also_undocumented2() {}
     }
 }
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() { }
diff --git a/src/test/compile-fail/move-in-guard-1.rs b/src/test/compile-fail/move-in-guard-1.rs
new file mode 100644 (file)
index 0000000..5d29d0e
--- /dev/null
@@ -0,0 +1,25 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(box_syntax)]
+
+pub fn main() {
+    let x = box 1;
+
+    let v = (1, 2);
+
+    match v {
+        (1, _) if take(x) => (),
+        (_, 2) if take(x) => (), //~ ERROR use of moved value: `x`
+        _ => (),
+    }
+}
+
+fn take<T>(_: T) -> bool { false }
diff --git a/src/test/compile-fail/move-in-guard-2.rs b/src/test/compile-fail/move-in-guard-2.rs
new file mode 100644 (file)
index 0000000..23af257
--- /dev/null
@@ -0,0 +1,25 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(box_syntax)]
+
+pub fn main() {
+    let x = box 1;
+
+    let v = (1, 2);
+
+    match v {
+        (1, _) |
+        (_, 2) if take(x) => (), //~ ERROR use of moved value: `x`
+        _ => (),
+    }
+}
+
+fn take<T>(_: T) -> bool { false }
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
diff --git a/src/test/compile-fail/object-safety-by-value-self-use.rs b/src/test/compile-fail/object-safety-by-value-self-use.rs
new file mode 100644 (file)
index 0000000..1b20a90
--- /dev/null
@@ -0,0 +1,29 @@
+// 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 while a trait with by-value self is object-safe, we
+// can't actually invoke it from an object (yet...?).
+
+#![feature(rustc_attrs)]
+
+trait Bar {
+    fn bar(self);
+}
+
+trait Baz {
+    fn baz(self: Self);
+}
+
+fn use_bar(t: Box<Bar>) {
+    t.bar() //~ ERROR cannot move a value of type Bar
+}
+
+fn main() { }
+
index 5ebcc8516ca0516610c34ab2d470b2674c8c7136..976717249e8eb2400fe6e307b625bd0fc8e73e18 100644 (file)
@@ -8,8 +8,10 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// Check that we correctly prevent users from making trait objects
-// from traits with a `fn(self)` method.
+// Check that a trait with by-value self is considered object-safe.
+
+#![feature(rustc_attrs)]
+#![allow(dead_code)]
 
 trait Bar {
     fn bar(self);
@@ -19,29 +21,35 @@ trait Baz {
     fn baz(self: Self);
 }
 
+trait Quux {
+    // Legal because of the where clause:
+    fn baz(self: Self) where Self : Sized;
+}
+
 fn make_bar<T:Bar>(t: &T) -> &Bar {
-    t
-        //~^ ERROR `Bar` is not object-safe
-        //~| NOTE method `bar` has a receiver type of `Self`
+    t // legal
 }
 
 fn make_bar_explicit<T:Bar>(t: &T) -> &Bar {
-    t as &Bar
-        //~^ ERROR `Bar` is not object-safe
-        //~| NOTE method `bar` has a receiver type of `Self`
+    t as &Bar // legal
 }
 
 fn make_baz<T:Baz>(t: &T) -> &Baz {
-    t
-        //~^ ERROR `Baz` is not object-safe
-        //~| NOTE method `baz` has a receiver type of `Self`
+    t // legal
 }
 
 fn make_baz_explicit<T:Baz>(t: &T) -> &Baz {
-    t as &Baz
-        //~^ ERROR `Baz` is not object-safe
-        //~| NOTE method `baz` has a receiver type of `Self`
+    t as &Baz // legal
+}
+
+fn make_quux<T:Quux>(t: &T) -> &Quux {
+    t
+}
+
+fn make_quux_explicit<T:Quux>(t: &T) -> &Quux {
+    t as &Quux
 }
 
-fn main() {
+#[rustc_error]
+fn main() { //~ ERROR compilation successful
 }
index 0ca706404c1f309028b36775d7d3d16daa237841..fd20accfa1e6b562bd319e86b3a987a86baefcaf 100644 (file)
@@ -9,12 +9,18 @@
 // except according to those terms.
 
 // Check that we correctly prevent users from making trait objects
-// from traits with generic methods.
+// from traits with generic methods, unless `where Self : Sized` is
+// present.
 
 trait Bar {
     fn bar<T>(&self, t: T);
 }
 
+trait Quux {
+    fn bar<T>(&self, t: T)
+        where Self : Sized;
+}
+
 fn make_bar<T:Bar>(t: &T) -> &Bar {
     t
         //~^ ERROR `Bar` is not object-safe
@@ -27,5 +33,13 @@ fn make_bar_explicit<T:Bar>(t: &T) -> &Bar {
         //~| NOTE method `bar` has generic type parameters
 }
 
+fn make_quux<T:Quux>(t: &T) -> &Quux {
+    t
+}
+
+fn make_quux_explicit<T:Quux>(t: &T) -> &Quux {
+    t as &Quux
+}
+
 fn main() {
 }
index df0f44c1391580898084e7484bf3d06e75686225..b546774ccbd8cae8deb49bb638bf3e8fa886fac1 100644 (file)
@@ -9,7 +9,8 @@
 // except according to those terms.
 
 // Check that we correctly prevent users from making trait objects
-// form traits that make use of `Self` in an argument or return position.
+// form traits that make use of `Self` in an argument or return
+// position, unless `where Self : Sized` is present..
 
 trait Bar {
     fn bar(&self, x: &Self);
@@ -19,6 +20,10 @@ trait Baz {
     fn bar(&self) -> Self;
 }
 
+trait Quux {
+    fn get(&self, s: &Self) -> Self where Self : Sized;
+}
+
 fn make_bar<T:Bar>(t: &T) -> &Bar {
     t
         //~^ ERROR `Bar` is not object-safe
@@ -43,5 +48,13 @@ fn make_baz_explicit<T:Baz>(t: &T) -> &Baz {
         //~| NOTE method `bar` references the `Self` type in its arguments or return type
 }
 
+fn make_quux<T:Quux>(t: &T) -> &Quux {
+    t
+}
+
+fn make_quux_explicit<T:Quux>(t: &T) -> &Quux {
+    t as &Quux
+}
+
 fn main() {
 }
index ffc21a5ce612326c9ef5e895a6526628679a841c..55f3b995336534c5e7cf8e9424ceb167bf2387b5 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
+// 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.
 //
 
 //~^^^^^^^^^^ ERROR overflow
 //
-// We also get a second error message at the top of file (dummy
-// span). This is not helpful, but also kind of annoying to prevent,
-// so for now just live with it, since we also get a second message
-// that is more helpful.
+// We get an error message at the top of file (dummy span).
+// This is not helpful, but also kind of annoying to prevent,
+// so for now just live with it.
 
 enum Nil {NilValue}
 struct Cons<T> {head:isize, tail:T}
@@ -28,9 +27,8 @@ fn dot(&self, other:Cons<T>) -> isize {
 }
 fn test<T:Dot> (n:isize, i:isize, first:T, second:T) ->isize {
   match n {    0 => {first.dot(second)}
-      //~^ ERROR: reached the recursion limit during monomorphization
-      // Error message should be here. It should be a type error
-      // to instantiate `test` at a type other than T. (See #4287)
+      // FIXME(#4287) Error message should be here. It should be
+      // a type error to instantiate `test` at a type other than T.
     _ => {test (n-1, i+1, Cons {head:2*i+1, tail:first}, Cons{head:i*i, tail:second})}
   }
 }
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 d8b3176787c040b1f75efdc2b741c05686522092..b09b10ffa0aad9dc22572e47f9348b44d7d7e7ac 100644 (file)
@@ -18,4 +18,5 @@ fn main() {
     10.dup::<i32>(); //~ ERROR does not take type parameters
     10.blah::<i32, i32>(); //~ ERROR incorrect number of type parameters
     (box 10 as Box<bar>).dup(); //~ ERROR cannot convert to a trait object
+    //~^ ERROR the trait `bar` is not implemented for the type `bar`
 }
diff --git a/src/test/compile-fail/typeck-builtin-bound-type-parameters.rs b/src/test/compile-fail/typeck-builtin-bound-type-parameters.rs
new file mode 100644 (file)
index 0000000..fb6c43a
--- /dev/null
@@ -0,0 +1,28 @@
+// 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 foo1<T:Copy<U>, U>(x: T) {}
+//~^ ERROR: wrong number of type arguments: expected 0, found 1
+
+trait Trait: Copy<Send> {}
+//~^ ERROR: wrong number of type arguments: expected 0, found 1
+
+struct MyStruct1<T: Copy<T>>;
+//~^ ERROR wrong number of type arguments: expected 0, found 1
+
+struct MyStruct2<'a, T: Copy<'a>>;
+//~^ ERROR: wrong number of lifetime parameters: expected 0, found 1
+
+fn foo2<'a, T:Copy<'a, U>, U>(x: T) {}
+//~^ ERROR: wrong number of type arguments: expected 0, found 1
+//~^^ ERROR: wrong number of lifetime parameters: expected 0, found 1
+
+fn main() {
+}
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 d8a82d8fbf0467863cf201616693610afce9c8db..1998f8ab15529e5cc110fcd28462a8e6ab0d4b74 100644 (file)
@@ -18,7 +18,7 @@ struct Number {
     n: i64
 }
 
-impl fmt::String for Number {
+impl fmt::Display for Number {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         write!(f, "{}", self.n)
     }
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();
diff --git a/src/test/parse-fail/issue-22647.rs b/src/test/parse-fail/issue-22647.rs
new file mode 100644 (file)
index 0000000..5de8627
--- /dev/null
@@ -0,0 +1,25 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn main() {
+    let caller<F> = |f: F|  //~ ERROR unexpected token: `<`
+    where F: Fn() -> i32
+    {
+        let x = f();
+        println!("Y {}",x);
+        return x;
+    };
+
+    caller(bar_handler);
+}
+
+fn bar_handler() -> i32 {
+    5
+}
diff --git a/src/test/parse-fail/issue-22712.rs b/src/test/parse-fail/issue-22712.rs
new file mode 100644 (file)
index 0000000..abc9e59
--- /dev/null
@@ -0,0 +1,19 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+struct Foo<B> {
+    buffer: B
+}
+
+fn bar() {
+    let Foo<Vec<u8>>  //~ ERROR unexpected token: `<`
+}
+
+fn main() {}
index e8f9ed4d2cfc8d760da40f213ef332a7043c8552..8febbf8309ea78cb046705b4c04ad9d3c7d5b0be 100644 (file)
@@ -8,11 +8,10 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use std::fmt::Show;
+use std::fmt::Debug;
 
 fn main() {
-    let x: Box<Show+> = box 3 as Box<Show+>;
+    let x: Box<Debug+> = box 3 as Box<Debug+>;
     //~^ ERROR at least one type parameter bound must be specified
     //~^^ ERROR at least one type parameter bound must be specified
 }
-
index bee4a120d5909fd2b0f375c81518071f9c986d03..51c6b14e1deedb01fed39975d73f22ed15b113cf 100644 (file)
@@ -22,12 +22,12 @@ digraph block {
     N3 -> N4;
     N4 -> N5;
     N5 -> N6;
-    N6 -> N8;
-    N8 -> N9;
+    N6 -> N9;
     N9 -> N10;
     N10 -> N11;
     N11 -> N12;
-    N12 -> N13;
+    N12 -> N8;
+    N8 -> N13;
     N13 -> N14;
     N14 -> N15;
     N15 -> N7;
index 76e66513515622c71406b246e371b26feab9e3bc..fb7d2ad97bd5f553277f80ae09dfcba4cbd3f1bd 100644 (file)
@@ -32,16 +32,16 @@ digraph block {
     N6 -> N7;
     N7 -> N8;
     N8 -> N9;
-    N9 -> N11;
-    N11 -> N12;
-    N12 -> N13;
+    N9 -> N12;
+    N12 -> N11;
+    N11 -> N13;
     N13 -> N14;
     N14 -> N15;
     N15 -> N10;
-    N11 -> N16;
-    N16 -> N17;
+    N9 -> N17;
     N17 -> N18;
-    N18 -> N19;
+    N18 -> N16;
+    N16 -> N19;
     N19 -> N20;
     N20 -> N21;
     N21 -> N22;
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 575c32baeac24782509cec1adde66b5fe4b377af..daff321efcfd9d39299fb7c03e35b30934635d8c 100644 (file)
@@ -54,7 +54,7 @@ fn cat(in_x : uint, in_y : int, in_name: String) -> cat {
     }
 }
 
-impl fmt::String for cat {
+impl fmt::Display for cat {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         write!(f, "{}", self.name)
     }
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]);
 }
index 04a69bbf3a2bc1b1748db4324e605c193f1804f4..b16b033c22fccafc6854593e9f4cbb553a63cb98 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use std::fmt::Show;
+use std::fmt::Debug;
 use std::default::Default;
 
 // Test that an impl for homogeneous pairs does not conflict with a
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 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 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-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)
+}
diff --git a/src/test/run-pass/issue-22577.rs b/src/test/run-pass/issue-22577.rs
new file mode 100644 (file)
index 0000000..1ecdd39
--- /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.
+
+use std::{fs, net};
+
+fn assert_both<T: Send + Sync>() {}
+
+fn main() {
+    assert_both::<fs::File>();
+    assert_both::<fs::Metadata>();
+    assert_both::<fs::ReadDir>();
+    assert_both::<fs::DirEntry>();
+    assert_both::<fs::WalkDir>();
+    assert_both::<fs::OpenOptions>();
+    assert_both::<fs::Permissions>();
+
+    assert_both::<net::TcpStream>();
+    assert_both::<net::TcpListener>();
+    assert_both::<net::UdpSocket>();
+    assert_both::<net::SocketAddr>();
+    assert_both::<net::IpAddr>();
+}
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}"));
 }
index f4b85e03eaeac031dfb37f2e8de0f9cb7effcdbe..be4d475229591bc7c5b178dc6f2b5c2eef25c53e 100644 (file)
@@ -101,7 +101,7 @@ fn add_pt(&mut self, x: int, y: int) {
 
 // Allows AsciiArt to be converted to a string using the libcore ToString trait.
 // Note that the %s fmt! specifier will not call this automatically.
-impl fmt::String for AsciiArt {
+impl fmt::Display for AsciiArt {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         // Convert each line into a string.
         let lines = self.lines.iter()
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 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()]);
 }
diff --git a/src/test/run-pass/move-guard-const.rs b/src/test/run-pass/move-guard-const.rs
new file mode 100644 (file)
index 0000000..64c4f1f
--- /dev/null
@@ -0,0 +1,25 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(box_syntax)]
+
+fn main() {
+    let x = box 1;
+
+    let v = (1, 2);
+
+    match v {
+        (2, 1) if take(x) => (),
+        (1, 2) if take(x) => (),
+        _ => (),
+    }
+}
+
+fn take<T>(_: T) -> bool { false }
diff --git a/src/test/run-pass/object-safety-sized-self-by-value-self.rs b/src/test/run-pass/object-safety-sized-self-by-value-self.rs
new file mode 100644 (file)
index 0000000..ae09233
--- /dev/null
@@ -0,0 +1,46 @@
+// 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 a trait is still object-safe (and usable) if it has
+// methods with by-value self so long as they require `Self : Sized`.
+
+trait Counter {
+    fn tick(&mut self) -> u32;
+    fn get(self) -> u32 where Self : Sized;
+}
+
+struct CCounter {
+    c: u32
+}
+
+impl Counter for CCounter {
+    fn tick(&mut self) -> u32 { self.c += 1; self.c }
+    fn get(self) -> u32 where Self : Sized { self.c }
+}
+
+fn tick1<C:Counter>(mut c: C) -> u32 {
+    tick2(&mut c);
+    c.get()
+}
+
+fn tick2(c: &mut Counter) {
+    tick3(c);
+}
+
+fn tick3<C:?Sized+Counter>(c: &mut C) {
+    c.tick();
+    c.tick();
+}
+
+fn main() {
+    let mut c = CCounter { c: 0 };
+    let value = tick1(c);
+    assert_eq!(value, 2);
+}
diff --git a/src/test/run-pass/object-safety-sized-self-generic-method.rs b/src/test/run-pass/object-safety-sized-self-generic-method.rs
new file mode 100644 (file)
index 0000000..1a42c4b
--- /dev/null
@@ -0,0 +1,46 @@
+// 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 a trait is still object-safe (and usable) if it has
+// generic methods so long as they require `Self : Sized`.
+
+trait Counter {
+    fn tick(&mut self) -> u32;
+    fn with<F:FnOnce(u32)>(&self, f: F) where Self : Sized;
+}
+
+struct CCounter {
+    c: u32
+}
+
+impl Counter for CCounter {
+    fn tick(&mut self) -> u32 { self.c += 1; self.c }
+    fn with<F:FnOnce(u32)>(&self, f: F) { f(self.c); }
+}
+
+fn tick1<C:Counter>(c: &mut C) {
+    tick2(c);
+    c.with(|i| ());
+}
+
+fn tick2(c: &mut Counter) {
+    tick3(c);
+}
+
+fn tick3<C:?Sized+Counter>(c: &mut C) {
+    c.tick();
+    c.tick();
+}
+
+fn main() {
+    let mut c = CCounter { c: 0 };
+    tick1(&mut c);
+    assert_eq!(c.tick(), 3);
+}
diff --git a/src/test/run-pass/object-safety-sized-self-return-Self.rs b/src/test/run-pass/object-safety-sized-self-return-Self.rs
new file mode 100644 (file)
index 0000000..7f075bb
--- /dev/null
@@ -0,0 +1,47 @@
+// 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 a trait is still object-safe (and usable) if it has
+// methods that return `Self` so long as they require `Self : Sized`.
+
+trait Counter {
+    fn new() -> Self where Self : Sized;
+    fn tick(&mut self) -> u32;
+}
+
+struct CCounter {
+    c: u32
+}
+
+impl Counter for CCounter {
+    fn new() -> CCounter { CCounter { c: 0 } }
+    fn tick(&mut self) -> u32 { self.c += 1; self.c }
+}
+
+fn preticked<C:Counter>() -> C {
+    let mut c: C = Counter::new();
+    tick(&mut c);
+    c
+}
+
+fn tick(c: &mut Counter) {
+    tick_generic(c);
+}
+
+fn tick_generic<C:?Sized+Counter>(c: &mut C) {
+    c.tick();
+    c.tick();
+}
+
+fn main() {
+    let mut c = preticked::<CCounter>();
+    tick(&mut c);
+    assert_eq!(c.tick(), 5);
+}
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/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]);
 }