]> git.lizzy.rs Git - rust.git/commitdiff
Auto merge of #23359 - erickt:quote, r=pnkfelix
authorbors <bors@rust-lang.org>
Thu, 26 Mar 2015 18:43:56 +0000 (18:43 +0000)
committerbors <bors@rust-lang.org>
Thu, 26 Mar 2015 18:43:56 +0000 (18:43 +0000)
This PR allows the quote macros to unquote trait items, impl items, where clauses, and paths.

276 files changed:
mk/tests.mk
src/doc/reference.md
src/doc/trpl/SUMMARY.md
src/doc/trpl/associated-types.md [new file with mode: 0644]
src/doc/trpl/ownership.md
src/doc/trpl/unsafe.md
src/etc/libc.c
src/liballoc/arc.rs
src/libarena/lib.rs
src/libcollections/binary_heap.rs
src/libcollections/lib.rs
src/libcollections/slice.rs
src/libcollections/str.rs
src/libcollections/vec.rs
src/libcollectionstest/btree/set.rs
src/libcore/any.rs
src/libcore/cell.rs
src/libcore/clone.rs
src/libcore/fmt/mod.rs
src/libcore/fmt/num.rs
src/libcore/hash/mod.rs
src/libcore/mem.rs
src/libcore/num/i16.rs
src/libcore/num/i32.rs
src/libcore/num/i64.rs
src/libcore/num/i8.rs
src/libcore/num/int_macros.rs
src/libcore/num/isize.rs
src/libcore/num/mod.rs
src/libcore/num/u16.rs
src/libcore/num/u32.rs
src/libcore/num/u64.rs
src/libcore/num/u8.rs
src/libcore/num/uint_macros.rs
src/libcore/num/usize.rs
src/libcore/ops.rs
src/libcore/ptr.rs
src/libcore/str/mod.rs
src/libcoretest/mem.rs
src/libcoretest/ptr.rs
src/liblibc/lib.rs
src/liblog/lib.rs
src/librand/distributions/range.rs
src/librand/isaac.rs
src/librbml/lib.rs
src/librustc/lib.rs
src/librustc/lint/builtin.rs
src/librustc/metadata/creader.rs
src/librustc/middle/infer/error_reporting.rs
src/librustc/middle/infer/higher_ranked/mod.rs
src/librustc/middle/infer/mod.rs
src/librustc/middle/traits/project.rs
src/librustc/middle/traits/select.rs
src/librustc/middle/ty.rs
src/librustc_lint/builtin.rs
src/librustc_lint/lib.rs
src/librustc_llvm/lib.rs
src/librustc_trans/lib.rs
src/librustc_trans/save/mod.rs
src/librustc_trans/trans/_match.rs
src/librustc_trans/trans/callee.rs
src/librustc_trans/trans/closure.rs
src/librustc_trans/trans/datum.rs
src/librustc_trans/trans/expr.rs
src/librustc_trans/trans/meth.rs
src/librustc_typeck/astconv.rs
src/librustc_typeck/check/closure.rs
src/librustc_typeck/check/coercion.rs
src/librustc_typeck/check/demand.rs
src/librustc_typeck/check/dropck.rs
src/librustc_typeck/check/method/probe.rs
src/librustc_typeck/check/mod.rs
src/librustc_typeck/check/vtable.rs
src/librustc_typeck/collect.rs
src/librustc_typeck/diagnostics.rs
src/librustdoc/html/markdown.rs
src/librustdoc/visit_ast.rs
src/libserialize/json.rs
src/libstd/fs/mod.rs
src/libstd/io/buffered.rs
src/libstd/io/impls.rs
src/libstd/io/lazy.rs
src/libstd/io/mod.rs
src/libstd/io/prelude.rs
src/libstd/lib.rs
src/libstd/net/addr.rs
src/libstd/net/ip.rs
src/libstd/net/mod.rs
src/libstd/net/udp.rs
src/libstd/old_io/buffered.rs
src/libstd/old_io/stdio.rs
src/libstd/process.rs
src/libstd/rt/at_exit_imp.rs
src/libstd/rt/mod.rs
src/libstd/sync/mpsc/mod.rs
src/libstd/sync/mpsc/mpsc_queue.rs
src/libstd/sync/mpsc/oneshot.rs
src/libstd/sync/mpsc/select.rs
src/libstd/sync/mpsc/shared.rs
src/libstd/sync/mpsc/spsc_queue.rs
src/libstd/sync/mpsc/stream.rs
src/libstd/sync/mpsc/sync.rs
src/libstd/sync/mutex.rs
src/libstd/sys/common/helper_thread.rs
src/libstd/sys/common/net2.rs
src/libstd/sys/unix/os.rs
src/libstd/sys/windows/net.rs
src/libstd/sys/windows/os.rs
src/libstd/sys/windows/thread_local.rs
src/libstd/thread/local.rs
src/libstd/thread/mod.rs
src/libsyntax/ast.rs
src/libsyntax/codemap.rs
src/libsyntax/ext/base.rs
src/libsyntax/ext/deriving/generic/mod.rs
src/libsyntax/ext/quote.rs
src/libsyntax/ext/tt/macro_rules.rs
src/libsyntax/parse/lexer/mod.rs
src/libsyntax/parse/mod.rs
src/libsyntax/parse/obsolete.rs
src/libsyntax/parse/parser.rs
src/libsyntax/print/pprust.rs
src/libsyntax/std_inject.rs
src/libterm/lib.rs
src/libterm/terminfo/mod.rs
src/libterm/terminfo/parser/compiled.rs
src/libterm/win.rs
src/libtest/lib.rs
src/rustbook/subcommand.rs
src/test/auxiliary/coherence-lib.rs [deleted file]
src/test/auxiliary/coherence-orphan-lib.rs [deleted file]
src/test/auxiliary/coherence_lib.rs [new file with mode: 0644]
src/test/auxiliary/coherence_orphan_lib.rs [new file with mode: 0644]
src/test/auxiliary/issue-11224.rs
src/test/auxiliary/issue-11680.rs [deleted file]
src/test/auxiliary/issue-12612-1.rs [deleted file]
src/test/auxiliary/issue-12612-2.rs [deleted file]
src/test/auxiliary/issue-16725.rs [deleted file]
src/test/auxiliary/issue-17718-const-privacy.rs [deleted file]
src/test/auxiliary/issue-21202.rs [deleted file]
src/test/auxiliary/issue-2526.rs
src/test/auxiliary/issue_11680.rs [new file with mode: 0644]
src/test/auxiliary/issue_12612_1.rs [new file with mode: 0644]
src/test/auxiliary/issue_12612_2.rs [new file with mode: 0644]
src/test/auxiliary/issue_16725.rs [new file with mode: 0644]
src/test/auxiliary/issue_17718_const_privacy.rs [new file with mode: 0644]
src/test/auxiliary/issue_21202.rs [new file with mode: 0644]
src/test/auxiliary/lint-unused-extern-crate.rs [deleted file]
src/test/auxiliary/lint_unused_extern_crate.rs [new file with mode: 0644]
src/test/auxiliary/privacy-tuple-struct.rs [deleted file]
src/test/auxiliary/privacy_tuple_struct.rs [new file with mode: 0644]
src/test/auxiliary/regions-bounded-method-type-parameters-cross-crate-lib.rs [deleted file]
src/test/auxiliary/regions_bounded_method_type_parameters_cross_crate_lib.rs [new file with mode: 0644]
src/test/auxiliary/struct-field-privacy.rs [deleted file]
src/test/auxiliary/struct_field_privacy.rs [new file with mode: 0644]
src/test/auxiliary/struct_variant_xc_aux.rs
src/test/auxiliary/trait-safety-lib.rs [deleted file]
src/test/auxiliary/trait_safety_lib.rs [new file with mode: 0644]
src/test/auxiliary/typeck-default-trait-impl-cross-crate-coherence-lib.rs [deleted file]
src/test/auxiliary/typeck_default_trait_impl_cross_crate_coherence_lib.rs [new file with mode: 0644]
src/test/auxiliary/unreachable-variant.rs [deleted file]
src/test/auxiliary/unreachable_variant.rs [new file with mode: 0644]
src/test/compile-fail/bad-crate-id.rs
src/test/compile-fail/bad-crate-id2.rs
src/test/compile-fail/borrowck-overloaded-call.rs
src/test/compile-fail/coerce-unsafe-to-closure.rs
src/test/compile-fail/coherence-all-remote.rs
src/test/compile-fail/coherence-bigint-param.rs
src/test/compile-fail/coherence-cow-no-cover.rs
src/test/compile-fail/coherence-lone-type-parameter.rs
src/test/compile-fail/coherence-orphan.rs
src/test/compile-fail/coherence-overlapping-pairs.rs
src/test/compile-fail/coherence-pair-covered-uncovered-1.rs
src/test/compile-fail/coherence-pair-covered-uncovered.rs
src/test/compile-fail/derive-assoc-type-not-impl.rs [new file with mode: 0644]
src/test/compile-fail/derive-no-std-not-supported.rs
src/test/compile-fail/extern-wrong-value-type.rs
src/test/compile-fail/feature-gate-unboxed-closures-manual-impls.rs
src/test/compile-fail/fn-trait-formatting.rs
src/test/compile-fail/fn-variance-1.rs
src/test/compile-fail/issue-11680.rs
src/test/compile-fail/issue-12612.rs
src/test/compile-fail/issue-14845.rs
src/test/compile-fail/issue-15094.rs
src/test/compile-fail/issue-16538.rs
src/test/compile-fail/issue-16725.rs
src/test/compile-fail/issue-17718-const-privacy.rs
src/test/compile-fail/issue-20225.rs
src/test/compile-fail/issue-21202.rs
src/test/compile-fail/issue-5543.rs [deleted file]
src/test/compile-fail/kindck-impl-type-params.rs
src/test/compile-fail/lint-dead-code-3.rs
src/test/compile-fail/lint-unnecessary-casts.rs [deleted file]
src/test/compile-fail/lint-unused-extern-crate.rs
src/test/compile-fail/liveness-unused.rs
src/test/compile-fail/object-safety-by-value-self.rs
src/test/compile-fail/overloaded-calls-bad.rs
src/test/compile-fail/overloaded-calls-nontuple.rs
src/test/compile-fail/privacy5.rs
src/test/compile-fail/regions-bounded-method-type-parameters-cross-crate.rs
src/test/compile-fail/regions-close-object-into-object-5.rs
src/test/compile-fail/regions-close-over-type-parameter-1.rs
src/test/compile-fail/reject-specialized-drops-8142.rs [new file with mode: 0644]
src/test/compile-fail/static-array-across-crate.rs
src/test/compile-fail/struct-field-privacy.rs
src/test/compile-fail/suggest-private-fields.rs
src/test/compile-fail/trait-safety-trait-impl-cc.rs
src/test/compile-fail/trivial_casts.rs [new file with mode: 0644]
src/test/compile-fail/type-parameter-defaults-referencing-Self-ppaux.rs
src/test/compile-fail/typeck-default-trait-impl-cross-crate-coherence.rs
src/test/compile-fail/unboxed-closures-fnmut-as-fn.rs
src/test/compile-fail/unboxed-closures-recursive-fn-using-fn-mut.rs
src/test/compile-fail/unboxed-closures-unsafe-extern-fn.rs
src/test/compile-fail/unboxed-closures-wrong-abi.rs
src/test/compile-fail/unboxed-closures-wrong-arg-type-extern-fn.rs
src/test/compile-fail/unreachable-variant.rs
src/test/compile-fail/vector-cast-weirdness.rs
src/test/debuginfo/c-style-enum.rs
src/test/debuginfo/issue12886.rs
src/test/debuginfo/type-names.rs
src/test/parse-fail/bad-lit-suffixes.rs
src/test/parse-fail/extern-crate-as-no-string-help.rs [deleted file]
src/test/parse-fail/extern-foreign-crate.rs
src/test/pretty/issue-4264.pp
src/test/pretty/path-type-bounds.rs
src/test/pretty/raw-str-nonexpr.rs
src/test/run-make/symbols-are-reasonable/lib.rs
src/test/run-make/weird-output-filenames/Makefile
src/test/run-pass/autoderef-method-on-trait.rs
src/test/run-pass/cast-region-to-uint.rs
src/test/run-pass/coherence-bigint-int.rs
src/test/run-pass/coherence-bigint-vecint.rs
src/test/run-pass/coherence-blanket.rs
src/test/run-pass/coherence-covered-type-parameter.rs
src/test/run-pass/coherence-cow-1.rs
src/test/run-pass/coherence-cow-2.rs
src/test/run-pass/coherence-iterator-vec-any-elem.rs
src/test/run-pass/coherence-iterator-vec.rs
src/test/run-pass/coherence-local-1.rs
src/test/run-pass/coherence-local-2.rs
src/test/run-pass/deriving-associated-types.rs [new file with mode: 0644]
src/test/run-pass/extern-call-deep2.rs
src/test/run-pass/infer-container-across-object-cast.rs [deleted file]
src/test/run-pass/issue-12612.rs
src/test/run-pass/issue-13655.rs
src/test/run-pass/issue-14958.rs
src/test/run-pass/issue-14959.rs
src/test/run-pass/issue-15763.rs
src/test/run-pass/issue-15858.rs
src/test/run-pass/issue-15924.rs
src/test/run-pass/issue-16739.rs
src/test/run-pass/issue-19982.rs
src/test/run-pass/issue-23037.rs [new file with mode: 0644]
src/test/run-pass/issue-2718.rs
src/test/run-pass/issue-4252.rs
src/test/run-pass/issue-5708.rs
src/test/run-pass/issue-9719.rs
src/test/run-pass/match-reassign.rs [new file with mode: 0644]
src/test/run-pass/method-two-traits-distinguished-via-where-clause.rs
src/test/run-pass/object-one-type-two-traits.rs
src/test/run-pass/objects-coerce-freeze-borrored.rs
src/test/run-pass/overloaded-calls-param-vtables.rs
src/test/run-pass/overloaded-calls-simple.rs
src/test/run-pass/overloaded-calls-zero-args.rs
src/test/run-pass/regions-early-bound-trait-param.rs
src/test/run-pass/sigpipe-should-be-ignored.rs
src/test/run-pass/stable-addr-of.rs
src/test/run-pass/task-spawn-move-and-copy.rs
src/test/run-pass/trait-safety-ok-cc.rs
src/test/run-pass/trivial_casts.rs [new file with mode: 0644]
src/test/run-pass/typeck_type_placeholder_1.rs
src/test/run-pass/unboxed-closures-fn-as-fnmut-and-fnonce.rs
src/test/run-pass/unboxed-closures-fnmut-as-fnonce.rs
src/test/run-pass/unboxed-closures-infer-recursive-fn.rs
src/test/run-pass/unboxed-closures-manual-impl.rs
src/test/run-pass/zero_sized_subslice_match.rs

index 2fb33eb7db898bc9300e2e190f1a5de547b05619..e9f1baa8d4ef00db9326d22917e0f2082440be8d 100644 (file)
@@ -569,6 +569,11 @@ ifeq ($(CFG_OSTYPE),apple-darwin)
 CTEST_DISABLE_debuginfo-gdb = "gdb on darwin needs root"
 endif
 
+ifeq ($(findstring android, $(CFG_TARGET)), android)
+CTEST_DISABLE_debuginfo-gdb =
+CTEST_DISABLE_debuginfo-lldb = "lldb tests are disabled on android"
+endif
+
 # CTEST_DISABLE_NONSELFHOST_$(TEST_GROUP), if set, will cause that
 # test group to be disabled *unless* the target is able to build a
 # compiler (i.e. when the target triple is in the set of of host
index 07df3bdad34900ff00de2e1a6e6ed8c03ae2130e..32088b2ab67bf9dbed624557bd0e12ad30eb23e6 100644 (file)
@@ -1265,7 +1265,7 @@ be undesired.
 * Sending signals
 * Accessing/modifying the file system
 * Unsigned integer overflow (well-defined as wrapping)
-* Signed integer overflow (well-defined as two's complement representation
+* Signed integer overflow (well-defined as two’s complement representation
   wrapping)
 
 #### Diverging functions
@@ -2961,10 +2961,10 @@ meaning of the operators on standard types is given here.
   : Exclusive or.
     Calls the `bitxor` method of the `std::ops::BitXor` trait.
 * `<<`
-  : Logical left shift.
+  : Left shift.
     Calls the `shl` method of the `std::ops::Shl` trait.
 * `>>`
-  : Logical right shift.
+  : Right shift.
     Calls the `shr` method of the `std::ops::Shr` trait.
 
 #### Lazy boolean operators
index 76f8b6c97381818dc3a79b4e7aa87696d58a8377..70c74825a072cd7fac01e1b772f70ad659d7dba1 100644 (file)
@@ -22,6 +22,7 @@
     * [More Strings](more-strings.md)
     * [Patterns](patterns.md)
     * [Method Syntax](method-syntax.md)
+    * [Associated Types](associated-types.md)
     * [Closures](closures.md)
     * [Iterators](iterators.md)
     * [Generics](generics.md)
diff --git a/src/doc/trpl/associated-types.md b/src/doc/trpl/associated-types.md
new file mode 100644 (file)
index 0000000..f36c2c5
--- /dev/null
@@ -0,0 +1,202 @@
+% Associated Types
+
+Associated types are a powerful part of Rust's type system. They're related to
+the idea of a 'type family', in other words, grouping multiple types together. That
+description is a bit abstract, so let's dive right into an example. If you want
+to write a `Graph` trait, you have two types to be generic over: the node type
+and the edge type. So you might write a trait, `Graph<N, E>`, that looks like
+this:
+
+```rust
+trait Graph<N, E> {
+    fn has_edge(&self, &N, &N) -> bool;
+    fn edges(&self, &N) -> Vec<E>;
+    // etc
+}
+```
+
+While this sort of works, it ends up being awkward. For example, any function
+that wants to take a `Graph` as a parameter now _also_ needs to be generic over
+the `N`ode and `E`dge types too:
+
+```rust,ignore
+fn distance<N, E, G: Graph<N, E>>(graph: &G, start: &N, end: &N) -> u32 { ... }
+```
+
+Our distance calculation works regardless of our `Edge` type, so the `E` stuff in
+this signature is just a distraction.
+
+What we really want to say is that a certain `E`dge and `N`ode type come together
+to form each kind of `Graph`. We can do that with associated types:
+
+```rust
+trait Graph {
+    type N;
+    type E;
+
+    fn has_edge(&self, &Self::N, &Self::N) -> bool;
+    fn edges(&self, &Self::N) -> Vec<Self::E>;
+    // etc
+}
+```
+
+Now, our clients can be abstract over a given `Graph`:
+
+```rust,ignore
+fn distance<G: Graph>(graph: &G, start: &G::N, end: &G::N) -> uint { ... }
+```
+
+No need to deal with the `E`dge type here!
+
+Let's go over all this in more detail.
+
+## Defining associated types
+
+Let's build that `Graph` trait. Here's the definition:
+
+```rust
+trait Graph {
+    type N;
+    type E;
+
+    fn has_edge(&self, &Self::N, &Self::N) -> bool;
+    fn edges(&self, &Self::N) -> Vec<Self::E>;
+}
+```
+
+Simple enough. Associated types use the `type` keyword, and go inside the body
+of the trait, with the functions.
+
+These `type` declarations can have all the same thing as functions do. For example,
+if we wanted our `N` type to implement `Display`, so we can print the nodes out,
+we could do this:
+
+```rust
+use std::fmt;
+
+trait Graph {
+    type N: fmt::Display;
+    type E;
+
+    fn has_edge(&self, &Self::N, &Self::N) -> bool;
+    fn edges(&self, &Self::N) -> Vec<Self::E>;
+}
+```
+
+## Implementing associated types
+
+Just like any trait, traits that use associated types use the `impl` keyword to
+provide implementations. Here's a simple implementation of Graph:
+
+```rust
+# trait Graph {
+#     type N;
+#     type E;
+#     fn has_edge(&self, &Self::N, &Self::N) -> bool;
+#     fn edges(&self, &Self::N) -> Vec<Self::E>;
+# }
+struct Node;
+
+struct Edge;
+
+struct MyGraph;
+
+impl Graph for MyGraph {
+    type N = Node;
+    type E = Edge;
+
+    fn has_edge(&self, n1: &Node, n2: &Node) -> bool {
+        true
+    }
+
+    fn edges(&self, n: &Node) -> Vec<Edge> {
+        Vec::new()
+    }
+}
+```
+
+This silly implementation always returns `true` and an empty `Vec<Edge>`, but it
+gives you an idea of how to implement this kind of thing. We first need three
+`struct`s, one for the graph, one for the node, and one for the edge. If it made
+more sense to use a different type, that would work as well, we're just going to
+use `struct`s for all three here.
+
+Next is the `impl` line, which is just like implementing any other trait.
+
+From here, we use `=` to define our associated types. The name the trait uses
+goes on the left of the `=`, and the concrete type we're `impl`ementing this
+for goes on the right. Finally, we use the concrete types in our function
+declarations.
+
+## Trait objects with associated types
+
+There’s one more bit of syntax we should talk about: trait objects. If you
+try to create a trait object from an associated type, like this:
+
+```rust,ignore
+# trait Graph {
+#     type N;
+#     type E;
+#     fn has_edge(&self, &Self::N, &Self::N) -> bool;
+#     fn edges(&self, &Self::N) -> Vec<Self::E>;
+# }
+# struct Node;
+# struct Edge;
+# struct MyGraph;
+# impl Graph for MyGraph {
+#     type N = Node;
+#     type E = Edge;
+#     fn has_edge(&self, n1: &Node, n2: &Node) -> bool {
+#         true
+#     }
+#     fn edges(&self, n: &Node) -> Vec<Edge> {
+#         Vec::new()
+#     }
+# }
+let graph = MyGraph;
+let obj = Box::new(graph) as Box<Graph>;
+```
+
+You’ll get two errors:
+
+```text
+error: the value of the associated type `E` (from the trait `main::Graph`) must
+be specified [E0191]
+let obj = Box::new(graph) as Box<Graph>;
+          ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+24:44 error: the value of the associated type `N` (from the trait
+`main::Graph`) must be specified [E0191]
+let obj = Box::new(graph) as Box<Graph>;
+          ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+```
+
+We can’t create a trait object like this, becuase we don’t know the associated
+types. Instead, we can write this:
+
+```rust
+# trait Graph {
+#     type N;
+#     type E;
+#     fn has_edge(&self, &Self::N, &Self::N) -> bool;
+#     fn edges(&self, &Self::N) -> Vec<Self::E>;
+# }
+# struct Node;
+# struct Edge;
+# struct MyGraph;
+# impl Graph for MyGraph {
+#     type N = Node;
+#     type E = Edge;
+#     fn has_edge(&self, n1: &Node, n2: &Node) -> bool {
+#         true
+#     }
+#     fn edges(&self, n: &Node) -> Vec<Edge> {
+#         Vec::new()
+#     }
+# }
+let graph = MyGraph;
+let obj = Box::new(graph) as Box<Graph<N=Node, E=Edge>>;
+```
+
+The `N=Node` syntax allows us to provide a concrete type, `Node`, for the `N`
+type parameter. Same with `E=Edge`. If we didn’t proide this constraint, we
+couldn’t be sure which `impl` to match this trait object to.
index 6aced23ede08effc8c9f3f01b5c110cb5e6a421a..b851f19d22dc39327da7ad296619121c8e5faa7c 100644 (file)
@@ -513,8 +513,8 @@ Otherwise, it is an error to elide an output lifetime.
 
 ### Examples
 
-Here are some examples of functions with elided lifetimes, and the version of
-what the elided lifetimes are expand to:
+Here are some examples of functions with elided lifetimes.  We've paired each
+example of an elided lifetime with its expanded form.
 
 ```{rust,ignore}
 fn print(s: &str); // elided
index 2116976d55a4d56764bad679633c3cbb27d14533..dbf0cae6f4ba84b852e771e978b94ae84bbb99c5 100644 (file)
@@ -197,15 +197,16 @@ use std::ptr;
 
 // Define a wrapper around the handle returned by the foreign code.
 // Unique<T> has the same semantics as Box<T>
-pub struct Unique<T> {
+//
+// NB: For simplicity and correctness, we require that T has kind Send
+// (owned boxes relax this restriction).
+pub struct Unique<T: Send> {
     // It contains a single raw, mutable pointer to the object in question.
     ptr: *mut T
 }
 
 // Implement methods for creating and using the values in the box.
 
-// NB: For simplicity and correctness, we require that T has kind Send
-// (owned boxes relax this restriction).
 impl<T: Send> Unique<T> {
     pub fn new(value: T) -> Unique<T> {
         unsafe {
@@ -239,11 +240,11 @@ impl<T: Send> Unique<T> {
 // Unique<T>, making the struct manage the raw pointer: when the
 // struct goes out of scope, it will automatically free the raw pointer.
 //
-// NB: This is an unsafe destructor, because rustc will not normally
-// allow destructors to be associated with parameterized types, due to
-// bad interaction with managed boxes. (With the Send restriction,
-// we don't have this problem.) Note that the `#[unsafe_destructor]`
-// feature gate is required to use unsafe destructors.
+// NB: This is an unsafe destructor; rustc will not normally allow
+// destructors to be associated with parameterized types (due to
+// historically failing to check them soundly).  Note that the
+// `#[unsafe_destructor]` feature gate is currently required to use
+// unsafe destructors.
 #[unsafe_destructor]
 impl<T: Send> Drop for Unique<T> {
     fn drop(&mut self) {
index 2bf919d7e2cce794e2378feb49cda5cfd2c31907..249b5d22b6b23ad763df4d8a586abb33ae82cc79 100644 (file)
@@ -165,6 +165,16 @@ void posix88_consts() {
   put_const(S_IWUSR, int);
   put_const(S_IRUSR, int);
 
+  put_const(S_IRWXG, int);
+  put_const(S_IXGRP, int);
+  put_const(S_IWGRP, int);
+  put_const(S_IRGRP, int);
+
+  put_const(S_IRWXO, int);
+  put_const(S_IXOTH, int);
+  put_const(S_IWOTH, int);
+  put_const(S_IROTH, int);
+
 #ifdef F_OK
   put_const(F_OK, int);
 #endif
index c9bbc0d74cddc8d745dedf6c2382767e0ceacbd8..b5d16d29272850843e9204749c68e6be9165d56d 100644 (file)
@@ -321,7 +321,7 @@ pub fn make_unique(&mut self) -> &mut T {
 
 #[unsafe_destructor]
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<T: Sync + Send> Drop for Arc<T> {
+impl<T> Drop for Arc<T> {
     /// Drops the `Arc<T>`.
     ///
     /// This will decrement the strong reference count. If the strong reference
@@ -388,7 +388,7 @@ fn drop(&mut self) {
 
 #[unstable(feature = "alloc",
            reason = "Weak pointers may not belong in this module.")]
-impl<T: Sync + Send> Weak<T> {
+impl<T> Weak<T> {
     /// Upgrades a weak reference to a strong reference.
     ///
     /// Upgrades the `Weak<T>` reference to an `Arc<T>`, if possible.
@@ -454,7 +454,7 @@ fn clone(&self) -> Weak<T> {
 
 #[unsafe_destructor]
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<T: Sync + Send> Drop for Weak<T> {
+impl<T> Drop for Weak<T> {
     /// Drops the `Weak<T>`.
     ///
     /// This will decrement the weak reference count.
index 1b0356b88b08dcdb9e3bf1a386f67052170b22f1..7843be0b483ebd8750e7eab20e73ae1014ea04b7 100644 (file)
@@ -429,7 +429,8 @@ unsafe fn destroy(&mut self, len: usize) {
         // Destroy the next chunk.
         let next = self.next;
         let size = calculate_size::<T>(self.capacity);
-        deallocate(self as *mut TypedArenaChunk<T> as *mut u8, size,
+        let self_ptr: *mut TypedArenaChunk<T> = self;
+        deallocate(self_ptr as *mut u8, size,
                    mem::min_align_of::<TypedArenaChunk<T>>());
         if !next.is_null() {
             let capacity = (*next).capacity;
index 6edee82dc30afe6e5d26ef498761197a9fb15739..e4bc6a393c4918dc4110f4d619c76c8729061823 100644 (file)
@@ -563,6 +563,8 @@ pub fn len(&self) -> usize { self.data.len() }
     pub fn is_empty(&self) -> bool { self.len() == 0 }
 
     /// Clears the binary heap, returning an iterator over the removed elements.
+    ///
+    /// The elements are removed in arbitrary order.
     #[inline]
     #[unstable(feature = "collections",
                reason = "matches collection reform specification, waiting for dust to settle")]
index da2c61b6fd394a47cb1946a149376655c582010f..6a65c991c95037b5d45be79dd7c191277a74960a 100644 (file)
@@ -24,6 +24,8 @@
        html_playground_url = "http://play.rust-lang.org/")]
 #![doc(test(no_crate_inject))]
 
+#![allow(trivial_casts)]
+#![allow(trivial_numeric_casts)]
 #![feature(alloc)]
 #![feature(box_syntax)]
 #![feature(box_patterns)]
index 2a668b0869d2529ab61a18611a59ba5bc5d976bf..688d730e2528744c03f49903d7928a0610384a29 100644 (file)
 //! The `slice` module contains useful code to help work with slice values.
 //! Slices are a view into a block of memory represented as a pointer and a length.
 //!
-//! ```rust
-//! # #![feature(core)]
+//! ```
 //! // slicing a Vec
-//! let vec = vec!(1, 2, 3);
-//! let int_slice = vec.as_slice();
+//! let vec = vec![1, 2, 3];
+//! let int_slice = &vec[..];
 //! // coercing an array to a slice
 //! let str_slice: &[&str] = &["one", "two", "three"];
 //! ```
 //!
 //! Slices are either mutable or shared. The shared slice type is `&[T]`,
-//! while the mutable slice type is `&mut[T]`. For example, you can mutate the
-//! block of memory that a mutable slice points to:
+//! while the mutable slice type is `&mut [T]`, where `T` represents the element
+//! type. For example, you can mutate the block of memory that a mutable slice
+//! points to:
 //!
-//! ```rust
-//! let x: &mut[i32] = &mut [1, 2, 3];
+//! ```
+//! let x = &mut [1, 2, 3];
 //! x[1] = 7;
-//! assert_eq!(x[0], 1);
-//! assert_eq!(x[1], 7);
-//! assert_eq!(x[2], 3);
+//! assert_eq!(x, &[1, 7, 3]);
 //! ```
 //!
 //! Here are some of the things this module contains:
 //! There are several structs that are useful for slices, such as `Iter`, which
 //! represents iteration over a slice.
 //!
-//! ## Traits
-//!
-//! A number of traits add methods that allow you to accomplish tasks
-//! with slices, the most important being `SliceExt`. Other traits
-//! apply only to slices of elements satisfying certain bounds (like
-//! `Ord`).
-//!
-//! An example is the `slice` method which enables slicing syntax `[a..b]` that
-//! returns an immutable "view" into a `Vec` or another slice from the index
-//! interval `[a, b)`:
-//!
-//! ```rust
-//! fn main() {
-//!     let numbers = [0, 1, 2];
-//!     let last_numbers = &numbers[1..3];
-//!     // last_numbers is now &[1, 2]
-//! }
-//! ```
-//!
-//! ## Implementations of other traits
+//! ## Trait Implementations
 //!
 //! There are several implementations of common traits for slices. Some examples
 //! include:
 //!
 //! * `Clone`
-//! * `Eq`, `Ord` - for immutable slices whose element type are `Eq` or `Ord`.
+//! * `Eq`, `Ord` - for slices whose element type are `Eq` or `Ord`.
 //! * `Hash` - for slices whose element type is `Hash`
 //!
 //! ## Iteration
 //!
-//! The method `iter()` returns an iteration value for a slice. The iterator
-//! yields references to the slice's elements, so if the element
-//! type of the slice is `isize`, the element type of the iterator is `&isize`.
+//! The slices implement `IntoIterator`. The iterators of yield references
+//! to the slice elements.
 //!
-//! ```rust
-//! let numbers = [0, 1, 2];
-//! for &x in numbers.iter() {
-//!     println!("{} is a number!", x);
+//! ```
+//! let numbers = &[0, 1, 2];
+//! for n in numbers {
+//!     println!("{} is a number!", n);
 //! }
 //! ```
 //!
-//! * `.iter_mut()` returns an iterator that allows modifying each value.
-//! * Further iterators exist that split, chunk or permute the slice.
+//! The mutable slice yields mutable references to the elements:
+//!
+//! ```
+//! let mut scores = [7, 8, 9];
+//! for score in &mut scores[..] {
+//!     *score += 1;
+//! }
+//! ```
+//!
+//! This iterator yields mutable references to the slice's elements, so while the element
+//! type of the slice is `i32`, the element type of the iterator is `&mut i32`.
+//!
+//! * `.iter()` and `.iter_mut()` are the explicit methods to return the default
+//!   iterators.
+//! * Further methods that return iterators are `.split()`, `.splitn()`,
+//!   `.chunks()`, `.windows()` and more.
 
 #![doc(primitive = "slice")]
 #![stable(feature = "rust1", since = "1.0.0")]
index ca2786e843e97031c56e1d37d7b63aa443d096ab..aaa73badcac99a1b0c21bf7794b803a82317549f 100644 (file)
@@ -19,7 +19,7 @@
 //! are owned elsewhere.
 //!
 //! Basic operations are implemented directly by the compiler, but more advanced
-//! operations are defined on the [`StrExt`](trait.StrExt.html) trait.
+//! operations are defined as methods on the `str` type.
 //!
 //! # Examples
 //!
index 59819d01bc601aeb2f651d4d332474b743c74f7d..e71077c96c774a4acbfb7bdf5174138ae39dd08e 100644 (file)
@@ -646,6 +646,20 @@ pub fn retain<F>(&mut self, mut f: F) where F: FnMut(&T) -> bool {
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn push(&mut self, value: T) {
+        #[cold]
+        #[inline(never)]
+        fn resize<T>(vec: &mut Vec<T>) {
+            let old_size = vec.cap * mem::size_of::<T>();
+            let size = max(old_size, 2 * mem::size_of::<T>()) * 2;
+            if old_size > size { panic!("capacity overflow") }
+            unsafe {
+                let ptr = alloc_or_realloc(*vec.ptr, old_size, size);
+                if ptr.is_null() { ::alloc::oom() }
+                vec.ptr = Unique::new(ptr);
+            }
+            vec.cap = max(vec.cap, 2) * 2;
+        }
+
         if mem::size_of::<T>() == 0 {
             // zero-size types consume no memory, so we can't rely on the
             // address space running out
@@ -653,16 +667,9 @@ pub fn push(&mut self, value: T) {
             unsafe { mem::forget(value); }
             return
         }
+
         if self.len == self.cap {
-            let old_size = self.cap * mem::size_of::<T>();
-            let size = max(old_size, 2 * mem::size_of::<T>()) * 2;
-            if old_size > size { panic!("capacity overflow") }
-            unsafe {
-                let ptr = alloc_or_realloc(*self.ptr, old_size, size);
-                if ptr.is_null() { ::alloc::oom() }
-                self.ptr = Unique::new(ptr);
-            }
-            self.cap = max(self.cap, 2) * 2;
+            resize(self);
         }
 
         unsafe {
@@ -1199,8 +1206,8 @@ pub fn dedup(&mut self) {
 
             // Avoid bounds checks by using unsafe pointers.
             let p = self.as_mut_ptr();
-            let mut r = 1;
-            let mut w = 1;
+            let mut r: usize = 1;
+            let mut w: usize = 1;
 
             while r < ln {
                 let p_r = p.offset(r as isize);
index 488f0d756d329ef2374a097a83315ec99077298c..234cd6e0fd21ec23994810de197661005891dc0a 100644 (file)
@@ -43,8 +43,6 @@ struct Counter<'a, 'b> {
 }
 
 impl<'a, 'b, 'c> FnMut<(&'c i32,)> for Counter<'a, 'b> {
-    type Output = bool;
-
     extern "rust-call" fn call_mut(&mut self, (&x,): (&'c i32,)) -> bool {
         assert_eq!(x, self.expected[*self.i]);
         *self.i += 1;
@@ -52,6 +50,14 @@ extern "rust-call" fn call_mut(&mut self, (&x,): (&'c i32,)) -> bool {
     }
 }
 
+impl<'a, 'b, 'c> FnOnce<(&'c i32,)> for Counter<'a, 'b> {
+    type Output = bool;
+
+    extern "rust-call" fn call_once(mut self, args: (&'c i32,)) -> bool {
+        self.call_mut(args)
+    }
+}
+
 fn check<F>(a: &[i32], b: &[i32], expected: &[i32], f: F) where
     // FIXME Replace Counter with `Box<FnMut(_) -> _>`
     F: FnOnce(&BTreeSet<i32>, &BTreeSet<i32>, Counter) -> bool,
index 3938a610668b7c979046fbf5d763a27a9375be68..c94d8e2ed0c8d8d5ee79f0743ff6a826c30968cd 100644 (file)
 // Any trait
 ///////////////////////////////////////////////////////////////////////////////
 
-/// The `Any` trait is implemented by all `'static` types, and can be used for
-/// dynamic typing
+/// A type to emulate dynamic typing. See the [module-level documentation][mod] for more details.
 ///
-/// Every type with no non-`'static` references implements `Any`, so `Any` can
-/// be used as a trait object to emulate the effects dynamic typing.
+/// Every type with no non-`'static` references implements `Any`.
+///
+/// [mod]: ../index.html
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait Any: 'static {
     /// Get the `TypeId` of `self`
index a9c5de23d948bcbcde2650ae9833ecd172670fe7..9e6dbce0325935da3737fe1c10cbf511c7afaa68 100644 (file)
@@ -713,7 +713,11 @@ pub fn new(value: T) -> UnsafeCell<T> {
     /// ```
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
-    pub fn get(&self) -> *mut T { &self.value as *const T as *mut T }
+    pub fn get(&self) -> *mut T {
+        // FIXME(#23542) Replace with type ascription.
+        #![allow(trivial_casts)]
+        &self.value as *const T as *mut T
+    }
 
     /// Unwraps the value
     ///
index 058eff121e63300daef084435917f9b6131fb130..85e5bde48598eee8bde8ee706fc365e60f19104c 100644 (file)
 #[stable(feature = "rust1", since = "1.0.0")]
 pub trait Clone : Sized {
     /// Returns a copy of the value.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let hello = "Hello"; // &str implements Clone
+    ///
+    /// assert_eq!("Hello", hello.clone());
+    /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     fn clone(&self) -> Self;
 
index cf427c16588d9add3682c30ff51449be8380151f..aa0d0a1539a30e045ba424a52b1f4861da689629 100644 (file)
@@ -833,6 +833,8 @@ fn fmt(&self, f: &mut Formatter) -> Result {
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T> Pointer for *mut T {
     fn fmt(&self, f: &mut Formatter) -> Result {
+        // FIXME(#23542) Replace with type ascription.
+        #![allow(trivial_casts)]
         Pointer::fmt(&(*self as *const T), f)
     }
 }
@@ -840,6 +842,8 @@ fn fmt(&self, f: &mut Formatter) -> Result {
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, T> Pointer for &'a T {
     fn fmt(&self, f: &mut Formatter) -> Result {
+        // FIXME(#23542) Replace with type ascription.
+        #![allow(trivial_casts)]
         Pointer::fmt(&(*self as *const T), f)
     }
 }
@@ -847,6 +851,8 @@ fn fmt(&self, f: &mut Formatter) -> Result {
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, T> Pointer for &'a mut T {
     fn fmt(&self, f: &mut Formatter) -> Result {
+        // FIXME(#23542) Replace with type ascription.
+        #![allow(trivial_casts)]
         Pointer::fmt(&(&**self as *const T), f)
     }
 }
index 49da99b97cb206571b768a1e88e94b6ae86a6d1e..56d2eabc095a3f0f4aa538481a590fe12504df55 100644 (file)
@@ -13,6 +13,7 @@
 // FIXME: #6220 Implement floating point formatting
 
 #![allow(unsigned_negation)]
+#![allow(trivial_numeric_casts)]
 
 use fmt;
 use iter::IteratorExt;
index 1d5e174a8dc99ebf1fe59d769951ea8a2b7497e8..2feb2f8b1e36372d8121b54f2167b631c2d04879 100644 (file)
@@ -182,6 +182,8 @@ fn hash<H: Hasher>(&self, state: &mut H) {
                 }
 
                 fn hash_slice<H: Hasher>(data: &[$ty], state: &mut H) {
+                    // FIXME(#23542) Replace with type ascription.
+                    #![allow(trivial_casts)]
                     let newlen = data.len() * ::$ty::BYTES as usize;
                     let ptr = data.as_ptr() as *const u8;
                     state.write(unsafe { slice::from_raw_parts(ptr, newlen) })
index 551f97ead12d8262f1f2f30860ea91a410e9eb74..1e6fb51a8a528e9d75bac0d6fa36da598104f057 100644 (file)
@@ -313,6 +313,8 @@ pub fn drop<T>(_x: T) { }
 #[inline]
 #[stable(feature = "rust1", since = "1.0.0")]
 pub unsafe fn transmute_copy<T, U>(src: &T) -> U {
+    // FIXME(#23542) Replace with type ascription.
+    #![allow(trivial_casts)]
     ptr::read(src as *const T as *const U)
 }
 
index 5ea60d0d96d29f44943a0c751cf760d7c7deef0c..efafce3fdefb04537a4b455af99ee20941e00ed9 100644 (file)
@@ -12,5 +12,6 @@
 
 #![stable(feature = "rust1", since = "1.0.0")]
 #![doc(primitive = "i16")]
+#![allow(trivial_numeric_casts)]
 
 int_module! { i16, 16 }
index 7d9faa998c12e87769a8519d416b7085d802dcbf..72b0236a8d2a4c12814ab55febe6f2cda730bbbe 100644 (file)
@@ -12,5 +12,6 @@
 
 #![stable(feature = "rust1", since = "1.0.0")]
 #![doc(primitive = "i32")]
+#![allow(trivial_numeric_casts)]
 
 int_module! { i32, 32 }
index 5a70911387b9b7192ab7a86fae52a90e77ddaa7b..a64a4febd5a963448fab5c413646509871a896a6 100644 (file)
@@ -12,5 +12,6 @@
 
 #![stable(feature = "rust1", since = "1.0.0")]
 #![doc(primitive = "i64")]
+#![allow(trivial_numeric_casts)]
 
 int_module! { i64, 64 }
index 1d7d78ffa6c2352a20ad49cbfda99a0b3fc7ce17..459814875ee0ee1686bfe88b502784a9139ce70a 100644 (file)
@@ -12,5 +12,6 @@
 
 #![stable(feature = "rust1", since = "1.0.0")]
 #![doc(primitive = "i8")]
+#![allow(trivial_numeric_casts)]
 
 int_module! { i8, 8 }
index fe0d6d13c4c06483649bdbf737fe89c68048cf43..675f568a96099e7c8728f498d5168845c64d5292 100644 (file)
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 #![doc(hidden)]
+#![allow(trivial_numeric_casts)]
 
 macro_rules! int_module { ($T:ty, $bits:expr) => (
 
index 0fd0d90b12501ea87b257bb523b56a1c6d0f1b47..9af51a36748263a2474b26e4c9fc5f7878afe3c8 100644 (file)
@@ -16,6 +16,7 @@
 
 #![stable(feature = "rust1", since = "1.0.0")]
 #![doc(primitive = "isize")]
+#![allow(trivial_numeric_casts)]
 
 #[cfg(target_pointer_width = "32")]
 int_module! { isize, 32 }
index 9ca7b48fbe5ef05b9a125ea7323266ce44cb0b4d..0eec875afc3bb15a47e1734bb62468f2bc6d8479 100644 (file)
@@ -14,6 +14,7 @@
 
 #![stable(feature = "rust1", since = "1.0.0")]
 #![allow(missing_docs)]
+#![allow(trivial_numeric_casts)]
 
 use self::wrapping::{OverflowingOps, WrappingOps};
 
index 21635799a77a26a458619bcd3b3431ce2ae0c7ba..289c5dbd08ea0eb02bf6c028ff2ec62e79ca4e80 100644 (file)
@@ -12,5 +12,6 @@
 
 #![stable(feature = "rust1", since = "1.0.0")]
 #![doc(primitive = "u16")]
+#![allow(trivial_numeric_casts)]
 
 uint_module! { u16, i16, 16 }
index 7d520770503d4b2507cb483afc8bcf04204ca443..6d0b6b0e5eaf9799a4f472bbc2efbbff8c8ea2c5 100644 (file)
@@ -12,5 +12,6 @@
 
 #![stable(feature = "rust1", since = "1.0.0")]
 #![doc(primitive = "u32")]
+#![allow(trivial_numeric_casts)]
 
 uint_module! { u32, i32, 32 }
index f10822077dc7511e3e44d12596e6e2198e0e941d..bf8747fdb6e2f45461a50eeea9795a97e85ecb33 100644 (file)
@@ -12,5 +12,6 @@
 
 #![stable(feature = "rust1", since = "1.0.0")]
 #![doc(primitive = "u64")]
+#![allow(trivial_numeric_casts)]
 
 uint_module! { u64, i64, 64 }
index 3d6922b07b19407b325941dd14888e4fea334214..05199735d4acb3f6aee6963963896308dab95ebd 100644 (file)
@@ -12,5 +12,6 @@
 
 #![stable(feature = "rust1", since = "1.0.0")]
 #![doc(primitive = "u8")]
+#![allow(trivial_numeric_casts)]
 
 uint_module! { u8, i8, 8 }
index d0c4885ad00b77ebbfaef418cb230976e6955f21..c22f31cc57ea84efba5238460fee13f32afd64ee 100644 (file)
@@ -9,6 +9,7 @@
 // except according to those terms.
 
 #![doc(hidden)]
+#![allow(trivial_numeric_casts)]
 
 macro_rules! uint_module { ($T:ty, $T_SIGNED:ty, $bits:expr) => (
 
index 602ef4fe45e734e0f1a931a2a50c98ce98e0511a..82dd3312782c554fdebaadb100d1d1c7df08d90f 100644 (file)
@@ -16,5 +16,6 @@
 
 #![stable(feature = "rust1", since = "1.0.0")]
 #![doc(primitive = "usize")]
+#![allow(trivial_numeric_casts)]
 
 uint_module! { usize, isize, ::isize::BITS }
index 6e6f97a7af7d9e1d2595309f78ef918885ba4965..16d03901239b3ea417ba47c69c9987c13174933a 100644 (file)
@@ -995,8 +995,10 @@ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct Range<Idx> {
     /// The lower bound of the range (inclusive).
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub start: Idx,
     /// The upper bound of the range (exclusive).
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub end: Idx,
 }
 
@@ -1013,11 +1015,10 @@ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct RangeFrom<Idx> {
     /// The lower bound of the range (inclusive).
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub start: Idx,
 }
 
-
-
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<Idx: fmt::Debug> fmt::Debug for RangeFrom<Idx> {
     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
@@ -1031,6 +1032,7 @@ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct RangeTo<Idx> {
     /// The upper bound of the range (exclusive).
+    #[stable(feature = "rust1", since = "1.0.0")]
     pub end: Idx,
 }
 
@@ -1041,7 +1043,6 @@ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
     }
 }
 
-
 /// The `Deref` trait is used to specify the functionality of dereferencing
 /// operations like `*v`.
 ///
@@ -1148,6 +1149,7 @@ fn deref_mut(&mut self) -> &mut T { *self }
 #[lang="fn"]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_paren_sugar]
+#[cfg(stage0)]
 pub trait Fn<Args> {
     /// The returned type after the call operator is used.
     type Output;
@@ -1156,10 +1158,21 @@ pub trait Fn<Args> {
     extern "rust-call" fn call(&self, args: Args) -> Self::Output;
 }
 
+/// A version of the call operator that takes an immutable receiver.
+#[lang="fn"]
+#[stable(feature = "rust1", since = "1.0.0")]
+#[rustc_paren_sugar]
+#[cfg(not(stage0))]
+pub trait Fn<Args> : FnMut<Args> {
+    /// This is called when the call operator is used.
+    extern "rust-call" fn call(&self, args: Args) -> Self::Output;
+}
+
 /// A version of the call operator that takes a mutable receiver.
 #[lang="fn_mut"]
 #[stable(feature = "rust1", since = "1.0.0")]
 #[rustc_paren_sugar]
+#[cfg(stage0)]
 pub trait FnMut<Args> {
     /// The returned type after the call operator is used.
     type Output;
@@ -1168,6 +1181,16 @@ pub trait FnMut<Args> {
     extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output;
 }
 
+/// A version of the call operator that takes a mutable receiver.
+#[lang="fn_mut"]
+#[stable(feature = "rust1", since = "1.0.0")]
+#[rustc_paren_sugar]
+#[cfg(not(stage0))]
+pub trait FnMut<Args> : FnOnce<Args> {
+    /// This is called when the call operator is used.
+    extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output;
+}
+
 /// A version of the call operator that takes a by-value receiver.
 #[lang="fn_once"]
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -1180,6 +1203,7 @@ pub trait FnOnce<Args> {
     extern "rust-call" fn call_once(self, args: Args) -> Self::Output;
 }
 
+#[cfg(stage0)]
 impl<F: ?Sized, A> FnMut<A> for F
     where F : Fn<A>
 {
@@ -1190,6 +1214,7 @@ extern "rust-call" fn call_mut(&mut self, args: A) -> <F as Fn<A>>::Output {
     }
 }
 
+#[cfg(stage0)]
 impl<F,A> FnOnce<A> for F
     where F : FnMut<A>
 {
index d92622eeb70e3c4e83c1db5de34c765fe3a8c211..9b3ee3ef5e0c28fb1a402d0b6100bf1af5ad2288 100644 (file)
@@ -529,7 +529,7 @@ impl<T: ?Sized> Unique<T> {
     /// Create a new `Unique`.
     #[unstable(feature = "unique")]
     pub unsafe fn new(ptr: *mut T) -> Unique<T> {
-        Unique { pointer: NonZero::new(ptr as *const T), _marker: PhantomData }
+        Unique { pointer: NonZero::new(ptr), _marker: PhantomData }
     }
 
     /// Dereference the content.
index b7285d30a7309cc9451a22aef5e4ba7170a3c250..a629e0308e98299611940545977f165618499ac2 100644 (file)
@@ -28,8 +28,9 @@
 use iter::{Map, Iterator, IteratorExt, DoubleEndedIterator};
 use marker::Sized;
 use mem;
+#[allow(deprecated)]
 use num::Int;
-use ops::{Fn, FnMut};
+use ops::{Fn, FnMut, FnOnce};
 use option::Option::{self, None, Some};
 use raw::{Repr, Slice};
 use result::Result::{self, Ok, Err};
@@ -164,8 +165,7 @@ impl FromStr for bool {
     /// assert!(<bool as FromStr>::from_str("not even a boolean").is_err());
     /// ```
     ///
-    /// Note, in many cases, the StrExt::parse() which is based on
-    /// this FromStr::from_str() is more proper.
+    /// Note, in many cases, the `.parse()` method on `str` is more proper.
     ///
     /// ```
     /// assert_eq!("true".parse(), Ok(true));
@@ -261,7 +261,7 @@ pub unsafe fn from_utf8_unchecked<'a>(v: &'a [u8]) -> &'a str {
              reason = "use std::ffi::c_str_to_bytes + str::from_utf8")]
 pub unsafe fn from_c_str(s: *const i8) -> &'static str {
     let s = s as *const u8;
-    let mut len = 0;
+    let mut len: usize = 0;
     while *s.offset(len as isize) != 0 {
         len += 1;
     }
@@ -530,7 +530,7 @@ fn next_back(&mut self) -> Option<(usize, char)> {
 /// External iterator for a string's bytes.
 /// Use with the `std::iter` module.
 ///
-/// Created with `StrExt::bytes`
+/// Created with `str::bytes`
 #[stable(feature = "rust1", since = "1.0.0")]
 #[derive(Clone)]
 pub struct Bytes<'a>(Map<slice::Iter<'a, u8>, BytesDeref>);
@@ -541,6 +541,7 @@ fn next_back(&mut self) -> Option<(usize, char)> {
 #[derive(Copy, Clone)]
 struct BytesDeref;
 
+#[cfg(stage0)]
 impl<'a> Fn<(&'a u8,)> for BytesDeref {
     type Output = u8;
 
@@ -550,6 +551,32 @@ extern "rust-call" fn call(&self, (ptr,): (&'a u8,)) -> u8 {
     }
 }
 
+#[cfg(not(stage0))]
+impl<'a> Fn<(&'a u8,)> for BytesDeref {
+    #[inline]
+    extern "rust-call" fn call(&self, (ptr,): (&'a u8,)) -> u8 {
+        *ptr
+    }
+}
+
+#[cfg(not(stage0))]
+impl<'a> FnMut<(&'a u8,)> for BytesDeref {
+    #[inline]
+    extern "rust-call" fn call_mut(&mut self, (ptr,): (&'a u8,)) -> u8 {
+        Fn::call(&*self, (ptr,))
+    }
+}
+
+#[cfg(not(stage0))]
+impl<'a> FnOnce<(&'a u8,)> for BytesDeref {
+    type Output = u8;
+
+    #[inline]
+    extern "rust-call" fn call_once(self, (ptr,): (&'a u8,)) -> u8 {
+        Fn::call(&self, (ptr,))
+    }
+}
+
 /// An iterator over the substrings of a string, separated by `sep`.
 struct CharSplits<'a, P: Pattern<'a>> {
     /// The slice remaining to be iterated
@@ -1461,27 +1488,27 @@ impl<'a, S: ?Sized> Str for &'a S where S: Str {
     fn as_slice(&self) -> &str { Str::as_slice(*self) }
 }
 
-/// Return type of `StrExt::split`
+/// Return type of `str::split`
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct Split<'a, P: Pattern<'a>>(CharSplits<'a, P>);
 delegate_iter!{pattern &'a str : Split<'a, P>}
 
-/// Return type of `StrExt::split_terminator`
+/// Return type of `str::split_terminator`
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct SplitTerminator<'a, P: Pattern<'a>>(CharSplits<'a, P>);
 delegate_iter!{pattern &'a str : SplitTerminator<'a, P>}
 
-/// Return type of `StrExt::splitn`
+/// Return type of `str::splitn`
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct SplitN<'a, P: Pattern<'a>>(CharSplitsN<'a, P>);
 delegate_iter!{pattern forward &'a str : SplitN<'a, P>}
 
-/// Return type of `StrExt::rsplit`
+/// Return type of `str::rsplit`
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct RSplit<'a, P: Pattern<'a>>(RCharSplits<'a, P>);
 delegate_iter!{pattern reverse &'a str : RSplit<'a, P>}
 
-/// Return type of `StrExt::rsplitn`
+/// Return type of `str::rsplitn`
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct RSplitN<'a, P: Pattern<'a>>(RCharSplitsN<'a, P>);
 delegate_iter!{pattern reverse &'a str : RSplitN<'a, P>}
index bf3e1cf03cbddfb516fe2137b43d44e63d9b89a6..17d6b684c50e80a1111ee80cc5e47a1b329f347d 100644 (file)
@@ -95,7 +95,7 @@ fn test_transmute() {
     trait Foo { fn dummy(&self) { } }
     impl Foo for int {}
 
-    let a = box 100 as Box<Foo>;
+    let a = box 100isize as Box<Foo>;
     unsafe {
         let x: ::core::raw::TraitObject = transmute(a);
         assert!(*(x.data as *const int) == 100);
index adc15b9fbc27ffcd6bf38f74d4d9ec8246850baf..4f5f269d4375d0c0a6e2ec2c24ad3f19b476a065 100644 (file)
@@ -84,9 +84,9 @@ fn test_as_ref() {
         assert_eq!(q.as_ref().unwrap(), &2);
 
         // Lifetime inference
-        let u = 2;
+        let u = 2isize;
         {
-            let p: *const int = &u as *const _;
+            let p = &u as *const int;
             assert_eq!(p.as_ref().unwrap(), &2);
         }
     }
@@ -102,9 +102,9 @@ fn test_as_mut() {
         assert!(q.as_mut().unwrap() == &mut 2);
 
         // Lifetime inference
-        let mut u = 2;
+        let mut u = 2isize;
         {
-            let p: *mut int = &mut u as *mut _;
+            let p = &mut u as *mut int;
             assert!(p.as_mut().unwrap() == &mut 2);
         }
     }
@@ -170,9 +170,9 @@ fn test_set_memory() {
 
 #[test]
 fn test_unsized_unique() {
-    let xs: &mut [_] = &mut [1, 2, 3];
-    let ptr = unsafe { Unique::new(xs as *mut [_]) };
+    let xs: &mut [i32] = &mut [1, 2, 3];
+    let ptr = unsafe { Unique::new(xs as *mut [i32]) };
     let ys = unsafe { &mut **ptr };
-    let zs: &mut [_] = &mut [1, 2, 3];
+    let zs: &mut [i32] = &mut [1, 2, 3];
     assert!(ys == zs);
 }
index 0043f574cc90dbb237738ae33e725c0f6c3d44eb..89843979cd01583346aef92808b3edafe843d9b0 100644 (file)
@@ -2439,6 +2439,7 @@ pub mod c99 {
         }
         pub mod posix88 {
             use types::os::arch::c95::c_int;
+            use types::os::arch::posix88::mode_t;
 
             pub const O_RDONLY : c_int = 0;
             pub const O_WRONLY : c_int = 1;
@@ -2461,6 +2462,14 @@ pub mod posix88 {
             pub const S_IXUSR : c_int = 64;
             pub const S_IWUSR : c_int = 128;
             pub const S_IRUSR : c_int = 256;
+            pub const S_IRWXG : mode_t = 56;
+            pub const S_IXGRP : mode_t = 8;
+            pub const S_IWGRP : mode_t = 16;
+            pub const S_IRGRP : mode_t = 32;
+            pub const S_IRWXO : mode_t = 7;
+            pub const S_IXOTH : mode_t = 1;
+            pub const S_IWOTH : mode_t = 2;
+            pub const S_IROTH : mode_t = 4;
             pub const F_OK : c_int = 0;
             pub const R_OK : c_int = 4;
             pub const W_OK : c_int = 2;
@@ -2811,6 +2820,14 @@ pub mod posix88 {
             pub const S_IXUSR : mode_t = 64;
             pub const S_IWUSR : mode_t = 128;
             pub const S_IRUSR : mode_t = 256;
+            pub const S_IRWXG : mode_t = 56;
+            pub const S_IXGRP : mode_t = 8;
+            pub const S_IWGRP : mode_t = 16;
+            pub const S_IRGRP : mode_t = 32;
+            pub const S_IRWXO : mode_t = 7;
+            pub const S_IXOTH : mode_t = 1;
+            pub const S_IWOTH : mode_t = 2;
+            pub const S_IROTH : mode_t = 4;
             pub const F_OK : c_int = 0;
             pub const R_OK : c_int = 4;
             pub const W_OK : c_int = 2;
@@ -3024,6 +3041,14 @@ pub mod posix88 {
             pub const S_IXUSR : mode_t = 64;
             pub const S_IWUSR : mode_t = 128;
             pub const S_IRUSR : mode_t = 256;
+            pub const S_IRWXG : mode_t = 56;
+            pub const S_IXGRP : mode_t = 8;
+            pub const S_IWGRP : mode_t = 16;
+            pub const S_IRGRP : mode_t = 32;
+            pub const S_IRWXO : mode_t = 7;
+            pub const S_IXOTH : mode_t = 1;
+            pub const S_IWOTH : mode_t = 2;
+            pub const S_IROTH : mode_t = 4;
             pub const F_OK : c_int = 0;
             pub const R_OK : c_int = 4;
             pub const W_OK : c_int = 2;
@@ -3752,6 +3777,14 @@ pub mod posix88 {
             pub const S_IXUSR : mode_t = 64;
             pub const S_IWUSR : mode_t = 128;
             pub const S_IRUSR : mode_t = 256;
+            pub const S_IRWXG : mode_t = 56;
+            pub const S_IXGRP : mode_t = 8;
+            pub const S_IWGRP : mode_t = 16;
+            pub const S_IRGRP : mode_t = 32;
+            pub const S_IRWXO : mode_t = 7;
+            pub const S_IXOTH : mode_t = 1;
+            pub const S_IWOTH : mode_t = 2;
+            pub const S_IROTH : mode_t = 4;
             pub const F_OK : c_int = 0;
             pub const R_OK : c_int = 4;
             pub const W_OK : c_int = 2;
@@ -4198,6 +4231,14 @@ pub mod posix88 {
             pub const S_IXUSR : mode_t = 64;
             pub const S_IWUSR : mode_t = 128;
             pub const S_IRUSR : mode_t = 256;
+            pub const S_IRWXG : mode_t = 56;
+            pub const S_IXGRP : mode_t = 8;
+            pub const S_IWGRP : mode_t = 16;
+            pub const S_IRGRP : mode_t = 32;
+            pub const S_IRWXO : mode_t = 7;
+            pub const S_IXOTH : mode_t = 1;
+            pub const S_IWOTH : mode_t = 2;
+            pub const S_IROTH : mode_t = 4;
             pub const F_OK : c_int = 0;
             pub const R_OK : c_int = 4;
             pub const W_OK : c_int = 2;
@@ -4610,6 +4651,14 @@ pub mod posix88 {
             pub const S_IXUSR : mode_t = 64;
             pub const S_IWUSR : mode_t = 128;
             pub const S_IRUSR : mode_t = 256;
+            pub const S_IRWXG : mode_t = 56;
+            pub const S_IXGRP : mode_t = 8;
+            pub const S_IWGRP : mode_t = 16;
+            pub const S_IRGRP : mode_t = 32;
+            pub const S_IRWXO : mode_t = 7;
+            pub const S_IXOTH : mode_t = 1;
+            pub const S_IWOTH : mode_t = 2;
+            pub const S_IROTH : mode_t = 4;
             pub const F_OK : c_int = 0;
             pub const R_OK : c_int = 4;
             pub const W_OK : c_int = 2;
index 4537fc763c9536caa7a6ba3ba6312cdff8b71ef4..7ccd5401fdea47b58419244621a473b813d7e7e1 100644 (file)
@@ -304,10 +304,10 @@ pub fn log(level: u32, loc: &'static LogLocation, args: fmt::Arguments) {
     // Completely remove the local logger from TLS in case anyone attempts to
     // frob the slot while we're doing the logging. This will destroy any logger
     // set during logging.
-    let mut logger = LOCAL_LOGGER.with(|s| {
+    let mut logger: Box<Logger + Send> = LOCAL_LOGGER.with(|s| {
         s.borrow_mut().take()
     }).unwrap_or_else(|| {
-        box DefaultLogger { handle: io::stderr() } as Box<Logger + Send>
+        box DefaultLogger { handle: io::stderr() }
     });
     logger.log(&LogRecord {
         level: LogLevel(level),
@@ -443,7 +443,7 @@ fn init() {
         DIRECTIVES = boxed::into_raw(box directives);
 
         // Schedule the cleanup for the globals for when the runtime exits.
-        rt::at_exit(move || {
+        let _ = rt::at_exit(move || {
             let _g = LOCK.lock();
             assert!(!DIRECTIVES.is_null());
             let _directives = Box::from_raw(DIRECTIVES);
index e6f27a28ffa7ca118d7d6595c33afe8ae54b5b51..a682fa8584176977d02ccb2b942fd91b4e62e2ab 100644 (file)
@@ -10,6 +10,8 @@
 
 //! Generating numbers between two others.
 
+#![allow(trivial_numeric_casts)]
+
 // this is surprisingly complicated to be both generic & correct
 
 use core::prelude::{PartialOrd};
index 7ea62b7fd3f413b62d35b1d365872e645d3cc4ee..14bebe0cd915cf167803a01a40d41227e389c387 100644 (file)
@@ -447,6 +447,7 @@ fn next_u32(&mut self) -> u32 {
 
     #[inline]
     fn next_u64(&mut self) -> u64 {
+        #![allow(trivial_numeric_casts)]
         if self.cnt == 0 {
             // make some more numbers
             self.isaac64();
index 1a794f56f802c62c3a9c371f47acf6583e568111..1ffc6001af5721b3163bac4e575a7c3dc21df67f 100644 (file)
@@ -352,8 +352,8 @@ pub fn vuint_at(data: &[u8], start: uint) -> DecodeResult<Res> {
             let i = (val >> 28) as uint;
             let (shift, mask) = SHIFT_MASK_TABLE[i];
             Ok(Res {
-                val: ((val >> shift) & mask) as uint,
-                next: start + (((32 - shift) >> 3) as uint)
+                val: ((val >> shift) & mask) as usize,
+                next: start + ((32 - shift) >> 3),
             })
         }
     }
@@ -573,7 +573,7 @@ fn _next_int(&mut self,
                     0 => doc_as_u8(r_doc) as u64,
                     1 => doc_as_u16(r_doc) as u64,
                     2 => doc_as_u32(r_doc) as u64,
-                    3 => doc_as_u64(r_doc) as u64,
+                    3 => doc_as_u64(r_doc),
                     _ => unreachable!(),
                 }
             } else {
index 793eff6a9da6fc9763c02e68a72ee7ccecd5a5f6..e8af07e43815919ef4a23410a662770d90047409 100644 (file)
@@ -47,6 +47,9 @@
 #![feature(into_cow)]
 #![cfg_attr(test, feature(test))]
 
+#![allow(trivial_casts)]
+#![allow(trivial_numeric_casts)]
+
 extern crate arena;
 extern crate flate;
 extern crate fmt_macros;
index 44718d1c5251dbfff6cfe42f55d9e7ee67d31df4..2cc47f258f0764db771e1a7dd1feb00b51e9f092 100644 (file)
     "detects transmutes of fat pointers"
 }
 
+declare_lint! {
+    pub TRIVIAL_CASTS,
+    Warn,
+    "detects trivial casts which could be removed"
+}
+
+declare_lint! {
+    pub TRIVIAL_NUMERIC_CASTS,
+    Warn,
+    "detects trivial casts of numeric types which could be removed"
+}
 /// Does nothing as a lint pass, but registers some `Lint`s
 /// which are used by other parts of the compiler.
 #[derive(Copy)]
@@ -121,7 +132,9 @@ fn get_lints(&self) -> LintArray {
             STABLE_FEATURES,
             UNKNOWN_CRATE_TYPES,
             VARIANT_SIZE_DIFFERENCES,
-            FAT_PTR_TRANSMUTES
+            FAT_PTR_TRANSMUTES,
+            TRIVIAL_CASTS,
+            TRIVIAL_NUMERIC_CASTS
         )
     }
 }
index 00a47ce17dae070a76d2a001265b1056563a9968..7d8789c3cd1a81873f6a32c5ecb25781a6bbe9af 100644 (file)
@@ -73,22 +73,24 @@ struct CrateInfo {
 }
 
 pub fn validate_crate_name(sess: Option<&Session>, s: &str, sp: Option<Span>) {
-    let err = |s: &str| {
+    let say = |s: &str, warn: bool| {
         match (sp, sess) {
             (_, None) => panic!("{}", s),
+            (Some(sp), Some(sess)) if warn => sess.span_warn(sp, s),
             (Some(sp), Some(sess)) => sess.span_err(sp, s),
+            (None, Some(sess)) if warn => sess.warn(s),
             (None, Some(sess)) => sess.err(s),
         }
     };
     if s.len() == 0 {
-        err("crate name must not be empty");
-    } else if s.char_at(0) == '-' {
-        err(&format!("crate name cannot start with a hyphen: {}", s));
+        say("crate name must not be empty", false);
+    } else if s.contains("-") {
+        say(&format!("crate names soon cannot contain hyphens: {}", s), true);
     }
     for c in s.chars() {
         if c.is_alphanumeric() { continue }
         if c == '_' || c == '-' { continue }
-        err(&format!("invalid character `{}` in crate name: `{}`", c, s));
+        say(&format!("invalid character `{}` in crate name: `{}`", c, s), false);
     }
     match sess {
         Some(sess) => sess.abort_if_errors(),
@@ -153,8 +155,9 @@ pub fn new(sess: &'a Session) -> CrateReader<'a> {
         }
     }
 
-    // Traverses an AST, reading all the information about use'd crates and extern
-    // libraries necessary for later resolving, typechecking, linking, etc.
+    // Traverses an AST, reading all the information about use'd crates and
+    // extern libraries necessary for later resolving, typechecking, linking,
+    // etc.
     pub fn read_crates(&mut self, krate: &ast::Crate) {
         self.process_crate(krate);
         visit::walk_crate(self, krate);
@@ -184,11 +187,10 @@ fn extract_crate_info(&self, i: &ast::Item) -> Option<CrateInfo> {
                 debug!("resolving extern crate stmt. ident: {} path_opt: {:?}",
                        ident, path_opt);
                 let name = match *path_opt {
-                    Some((ref path_str, _)) => {
-                        let name = path_str.to_string();
-                        validate_crate_name(Some(self.sess), &name[..],
+                    Some(name) => {
+                        validate_crate_name(Some(self.sess), name.as_str(),
                                             Some(i.span));
-                        name
+                        name.as_str().to_string()
                     }
                     None => ident.to_string(),
                 };
@@ -304,7 +306,13 @@ fn existing_match(&self, name: &str, hash: Option<&Svh>, kind: PathKind)
                       -> Option<ast::CrateNum> {
         let mut ret = None;
         self.sess.cstore.iter_crate_data(|cnum, data| {
-            if data.name != name { return }
+            // For now we do a "fuzzy match" on crate names by considering
+            // hyphens equal to underscores. This is purely meant to be a
+            // transitionary feature while we deprecate the quote syntax of
+            // `extern crate` statements.
+            if data.name != name.replace("-", "_") {
+                return
+            }
 
             match hash {
                 Some(hash) if *hash == data.hash() => { ret = Some(cnum); return }
index 1ca56596a014732f6840441a3987b3d5d7ab85d0..80e8ed47d305299a24db2908d4e9fc3fb1e7ec92 100644 (file)
@@ -357,23 +357,9 @@ fn report_type_error(&self, trace: TypeTrace<'tcx>, terr: &ty::type_err<'tcx>) {
             }
         };
 
-        let message_root_str = match trace.origin {
-            infer::Misc(_) => "mismatched types",
-            infer::MethodCompatCheck(_) => "method not compatible with trait",
-            infer::ExprAssignable(_) => "mismatched types",
-            infer::RelateTraitRefs(_) => "mismatched traits",
-            infer::RelateSelfType(_) => "mismatched types",
-            infer::RelateOutputImplTypes(_) => "mismatched types",
-            infer::MatchExpressionArm(_, _) => "match arms have incompatible types",
-            infer::IfExpression(_) => "if and else have incompatible types",
-            infer::IfExpressionWithNoElse(_) => "if may be missing an else clause",
-            infer::RangeExpression(_) => "start and end of range have incompatible types",
-            infer::EquatePredicate(_) => "equality predicate not satisfied",
-        };
-
         span_err!(self.tcx.sess, trace.origin.span(), E0308,
             "{}: {} ({})",
-                 message_root_str,
+                 trace.origin,
                  expected_found_str,
                  ty::type_err_to_str(self.tcx, terr));
 
@@ -1495,38 +1481,38 @@ fn note_region_origin(&self, origin: &SubregionOrigin<'tcx>) {
             infer::Subtype(ref trace) => {
                 let desc = match trace.origin {
                     infer::Misc(_) => {
-                        format!("types are compatible")
+                        "types are compatible"
                     }
                     infer::MethodCompatCheck(_) => {
-                        format!("method type is compatible with trait")
+                        "method type is compatible with trait"
                     }
                     infer::ExprAssignable(_) => {
-                        format!("expression is assignable")
+                        "expression is assignable"
                     }
                     infer::RelateTraitRefs(_) => {
-                        format!("traits are compatible")
+                        "traits are compatible"
                     }
                     infer::RelateSelfType(_) => {
-                        format!("self type matches impl self type")
+                        "self type matches impl self type"
                     }
                     infer::RelateOutputImplTypes(_) => {
-                        format!("trait type parameters matches those \
-                                 specified on the impl")
+                        "trait type parameters matches those \
+                                 specified on the impl"
                     }
                     infer::MatchExpressionArm(_, _) => {
-                        format!("match arms have compatible types")
+                        "match arms have compatible types"
                     }
                     infer::IfExpression(_) => {
-                        format!("if and else have compatible types")
+                        "if and else have compatible types"
                     }
                     infer::IfExpressionWithNoElse(_) => {
-                        format!("if may be missing an else clause")
+                        "if may be missing an else clause"
                     }
                     infer::RangeExpression(_) => {
-                        format!("start and end of range have compatible types")
+                        "start and end of range have compatible types"
                     }
                     infer::EquatePredicate(_) => {
-                        format!("equality where clause is satisfied")
+                        "equality where clause is satisfied"
                     }
                 };
 
@@ -1666,8 +1652,8 @@ fn note_region_origin(&self, origin: &SubregionOrigin<'tcx>) {
             infer::RelateRegionParamBound(span) => {
                 self.tcx.sess.span_note(
                     span,
-                    &format!("...so that the declared lifetime parameter bounds \
-                                are satisfied"));
+                    "...so that the declared lifetime parameter bounds \
+                                are satisfied");
             }
             infer::SafeDestructor(span) => {
                 self.tcx.sess.span_note(
index 7d789bedc50b5c7f869ff943cda25c3315dfec65..16b387330b9efea402867d39e78c64e76cbeefeb 100644 (file)
@@ -14,6 +14,7 @@
 use super::{CombinedSnapshot, cres, InferCtxt, HigherRankedType, SkolemizationMap};
 use super::combine::{Combine, Combineable};
 
+use middle::subst;
 use middle::ty::{self, Binder};
 use middle::ty_fold::{self, TypeFoldable};
 use syntax::codemap::Span;
@@ -455,6 +456,63 @@ fn region_vars_confined_to_snapshot(&self,
     }
 }
 
+/// Constructs and returns a substitution that, for a given type
+/// scheme parameterized by `generics`, will replace every generic
+/// parmeter in the type with a skolemized type/region (which one can
+/// think of as a "fresh constant", except at the type/region level of
+/// reasoning).
+///
+/// Since we currently represent bound/free type parameters in the
+/// same way, this only has an effect on regions.
+///
+/// (Note that unlike a substitution from `ty::construct_free_substs`,
+/// this inserts skolemized regions rather than free regions; this
+/// allows one to use `fn leak_check` to catch attmepts to unify the
+/// skolemized regions with e.g. the `'static` lifetime)
+pub fn construct_skolemized_substs<'a,'tcx>(infcx: &InferCtxt<'a,'tcx>,
+                                            generics: &ty::Generics<'tcx>,
+                                            snapshot: &CombinedSnapshot)
+                                            -> (subst::Substs<'tcx>, SkolemizationMap)
+{
+    let mut map = FnvHashMap();
+
+    // map T => T
+    let mut types = subst::VecPerParamSpace::empty();
+    push_types_from_defs(infcx.tcx, &mut types, generics.types.as_slice());
+
+    // map early- or late-bound 'a => fresh 'a
+    let mut regions = subst::VecPerParamSpace::empty();
+    push_region_params(infcx, &mut map, &mut regions, generics.regions.as_slice(), snapshot);
+
+    let substs = subst::Substs { types: types,
+                                 regions: subst::NonerasedRegions(regions) };
+    return (substs, map);
+
+    fn push_region_params<'a,'tcx>(infcx: &InferCtxt<'a,'tcx>,
+                                   map: &mut SkolemizationMap,
+                                   regions: &mut subst::VecPerParamSpace<ty::Region>,
+                                   region_params: &[ty::RegionParameterDef],
+                                   snapshot: &CombinedSnapshot)
+    {
+        for r in region_params {
+            let br = r.to_bound_region();
+            let skol_var = infcx.region_vars.new_skolemized(br, &snapshot.region_vars_snapshot);
+            let sanity_check = map.insert(br, skol_var);
+            assert!(sanity_check.is_none());
+            regions.push(r.space, skol_var);
+        }
+    }
+
+    fn push_types_from_defs<'tcx>(tcx: &ty::ctxt<'tcx>,
+                                  types: &mut subst::VecPerParamSpace<ty::Ty<'tcx>>,
+                                  defs: &[ty::TypeParameterDef<'tcx>]) {
+        for def in defs {
+            let ty = ty::mk_param_from_def(tcx, def);
+            types.push(def.space, ty);
+        }
+    }
+}
+
 pub fn skolemize_late_bound_regions<'a,'tcx,T>(infcx: &InferCtxt<'a,'tcx>,
                                                binder: &ty::Binder<T>,
                                                snapshot: &CombinedSnapshot)
index 835964828d419c468785a2722902c113086febdb..8bd3ca826a6b202561d9a041ef26d70313c3ec01 100644 (file)
@@ -29,6 +29,7 @@
 use middle::ty::{self, Ty};
 use middle::ty_fold::{TypeFolder, TypeFoldable};
 use std::cell::{RefCell};
+use std::fmt;
 use std::rc::Rc;
 use syntax::ast;
 use syntax::codemap;
@@ -128,6 +129,30 @@ pub enum TypeOrigin {
     EquatePredicate(Span),
 }
 
+impl TypeOrigin {
+    fn as_str(&self) -> &'static str {
+        match self {
+            &TypeOrigin::Misc(_) |
+            &TypeOrigin::RelateSelfType(_) |
+            &TypeOrigin::RelateOutputImplTypes(_) |
+            &TypeOrigin::ExprAssignable(_) => "mismatched types",
+            &TypeOrigin::RelateTraitRefs(_) => "mismatched traits",
+            &TypeOrigin::MethodCompatCheck(_) => "method not compatible with trait",
+            &TypeOrigin::MatchExpressionArm(_, _) => "match arms have incompatible types",
+            &TypeOrigin::IfExpression(_) => "if and else have incompatible types",
+            &TypeOrigin::IfExpressionWithNoElse(_) => "if may be missing an else clause",
+            &TypeOrigin::RangeExpression(_) => "start and end of range have incompatible types",
+            &TypeOrigin::EquatePredicate(_) => "equality predicate not satisfied",
+        }
+    }
+}
+
+impl fmt::Display for TypeOrigin {
+    fn fmt(&self, f: &mut fmt::Formatter) -> Result<(),fmt::Error> {
+        fmt::Display::fmt(self.as_str(), f)
+    }
+}
+
 /// See `error_reporting.rs` for more details
 #[derive(Clone, Debug)]
 pub enum ValuePairs<'tcx> {
@@ -726,6 +751,15 @@ pub fn sub_poly_trait_refs(&self,
         })
     }
 
+    pub fn construct_skolemized_subst(&self,
+                                      generics: &ty::Generics<'tcx>,
+                                      snapshot: &CombinedSnapshot)
+                                      -> (subst::Substs<'tcx>, SkolemizationMap) {
+        /*! See `higher_ranked::construct_skolemized_subst` */
+
+        higher_ranked::construct_skolemized_substs(self, generics, snapshot)
+    }
+
     pub fn skolemize_late_bound_regions<T>(&self,
                                            value: &ty::Binder<T>,
                                            snapshot: &CombinedSnapshot)
index 92d54887308d645e1de0e11c96b388aca2721060..2232bb7bcdbf3698510c56e4f40808c205664dc0 100644 (file)
@@ -789,10 +789,13 @@ fn confirm_callable_candidate<'cx,'tcx>(
            obligation.repr(tcx),
            fn_sig.repr(tcx));
 
+    // the `Output` associated type is declared on `FnOnce`
+    let fn_once_def_id = tcx.lang_items.fn_once_trait().unwrap();
+
     // Note: we unwrap the binder here but re-create it below (1)
     let ty::Binder((trait_ref, ret_type)) =
         util::closure_trait_ref_and_return_type(tcx,
-                                                obligation.predicate.trait_ref.def_id,
+                                                fn_once_def_id,
                                                 obligation.predicate.trait_ref.self_ty(),
                                                 fn_sig,
                                                 flag);
index 9878661c9f69c414221e9378eab8ba2d69812592..0d6a1f7df5e564cd8d26bf8d7beebec1ba9f4201 100644 (file)
@@ -1069,7 +1069,7 @@ fn assemble_closure_candidates(&mut self,
         match self.closure_typer.closure_kind(closure_def_id) {
             Some(closure_kind) => {
                 debug!("assemble_unboxed_candidates: closure_kind = {:?}", closure_kind);
-                if closure_kind == kind {
+                if closure_kind.extends(kind) {
                     candidates.vec.push(ClosureCandidate(closure_def_id, substs.clone()));
                 }
             }
@@ -1088,10 +1088,8 @@ fn assemble_fn_pointer_candidates(&mut self,
                                       candidates: &mut SelectionCandidateSet<'tcx>)
                                       -> Result<(),SelectionError<'tcx>>
     {
-        // We provide a `Fn` impl for fn pointers. There is no need to provide
-        // the other traits (e.g. `FnMut`) since those are provided by blanket
-        // impls.
-        if Some(obligation.predicate.def_id()) != self.tcx().lang_items.fn_trait() {
+        // We provide impl of all fn traits for fn pointers.
+        if self.tcx().lang_items.fn_trait_kind(obligation.predicate.def_id()).is_none() {
             return Ok(());
         }
 
index e5e89c3fbd4b9802ed729631f7ad8dbafec6195f..92b444e85d8c3f5fa713bfc632c1272b50acf01f 100644 (file)
@@ -968,7 +968,7 @@ impl<'tcx> Eq for TyS<'tcx> {}
 
 impl<'tcx> Hash for TyS<'tcx> {
     fn hash<H: Hasher>(&self, s: &mut H) {
-        (self as *const _).hash(s)
+        (self as *const TyS).hash(s)
     }
 }
 
@@ -1793,6 +1793,9 @@ impl RegionParameterDef {
     pub fn to_early_bound_region(&self) -> ty::Region {
         ty::ReEarlyBound(self.def_id.node, self.space, self.index, self.name)
     }
+    pub fn to_bound_region(&self) -> ty::BoundRegion {
+        ty::BoundRegion::BrNamed(self.def_id, self.name)
+    }
 }
 
 /// Information about the formal type/lifetime parameters associated
@@ -2462,8 +2465,11 @@ pub struct ItemSubsts<'tcx> {
     pub substs: Substs<'tcx>,
 }
 
-#[derive(Clone, Copy, PartialEq, Eq, Debug, RustcEncodable, RustcDecodable)]
+#[derive(Clone, Copy, PartialOrd, Ord, PartialEq, Eq, Debug, RustcEncodable, RustcDecodable)]
 pub enum ClosureKind {
+    // Warning: Ordering is significant here! The ordering is chosen
+    // because the trait Fn is a subtrait of FnMut and so in turn, and
+    // hence we order it so that Fn < FnMut < FnOnce.
     FnClosureKind,
     FnMutClosureKind,
     FnOnceClosureKind,
@@ -2485,6 +2491,20 @@ pub fn trait_did(&self, cx: &ctxt) -> ast::DefId {
             Err(err) => cx.sess.fatal(&err[..]),
         }
     }
+
+    /// True if this a type that impls this closure kind
+    /// must also implement `other`.
+    pub fn extends(self, other: ty::ClosureKind) -> bool {
+        match (self, other) {
+            (FnClosureKind, FnClosureKind) => true,
+            (FnClosureKind, FnMutClosureKind) => true,
+            (FnClosureKind, FnOnceClosureKind) => true,
+            (FnMutClosureKind, FnMutClosureKind) => true,
+            (FnMutClosureKind, FnOnceClosureKind) => true,
+            (FnOnceClosureKind, FnOnceClosureKind) => true,
+            _ => false,
+        }
+    }
 }
 
 pub trait ClosureTyper<'tcx> {
@@ -2721,7 +2741,7 @@ fn intern_ty<'tcx>(type_arena: &'tcx TypedArena<TyS<'tcx>>,
     };
 
     debug!("Interned type: {:?} Pointer: {:?}",
-           ty, ty as *const _);
+           ty, ty as *const TyS);
 
     interner.insert(InternedTy { ty: ty }, ty);
 
@@ -4806,32 +4826,6 @@ pub fn expr_kind(tcx: &ctxt, expr: &ast::Expr) -> ExprKind {
             RvalueDpsExpr
         }
 
-        ast::ExprCast(..) => {
-            match tcx.node_types.borrow().get(&expr.id) {
-                Some(&ty) => {
-                    if type_is_trait(ty) {
-                        RvalueDpsExpr
-                    } else {
-                        RvalueDatumExpr
-                    }
-                }
-                None => {
-                    // Technically, it should not happen that the expr is not
-                    // present within the table.  However, it DOES happen
-                    // during type check, because the final types from the
-                    // expressions are not yet recorded in the tcx.  At that
-                    // time, though, we are only interested in knowing lvalue
-                    // vs rvalue.  It would be better to base this decision on
-                    // the AST type in cast node---but (at the time of this
-                    // writing) it's not easy to distinguish casts to traits
-                    // from other casts based on the AST.  This should be
-                    // easier in the future, when casts to traits
-                    // would like @Foo, Box<Foo>, or &Foo.
-                    RvalueDatumExpr
-                }
-            }
-        }
-
         ast::ExprBreak(..) |
         ast::ExprAgain(..) |
         ast::ExprRet(..) |
@@ -4847,7 +4841,8 @@ pub fn expr_kind(tcx: &ctxt, expr: &ast::Expr) -> ExprKind {
         ast::ExprUnary(..) |
         ast::ExprBox(None, _) |
         ast::ExprAddrOf(..) |
-        ast::ExprBinary(..) => {
+        ast::ExprBinary(..) |
+        ast::ExprCast(..) => {
             RvalueDatumExpr
         }
 
index e65fe904dd29af28eb5e1a3e1dad8e836afde366..8b57a48f3ce728355e345cb4b3415009ab00e885 100644 (file)
@@ -84,30 +84,6 @@ fn check_expr(&mut self, cx: &Context, e: &ast::Expr) {
     }
 }
 
-declare_lint! {
-    UNUSED_TYPECASTS,
-    Allow,
-    "detects unnecessary type casts that can be removed"
-}
-
-#[derive(Copy)]
-pub struct UnusedCasts;
-
-impl LintPass for UnusedCasts {
-    fn get_lints(&self) -> LintArray {
-        lint_array!(UNUSED_TYPECASTS)
-    }
-
-    fn check_expr(&mut self, cx: &Context, e: &ast::Expr) {
-        if let ast::ExprCast(ref expr, ref ty) = e.node {
-            let t_t = ty::expr_ty(cx.tcx, e);
-            if ty::expr_ty(cx.tcx, &**expr) == t_t {
-                cx.span_lint(UNUSED_TYPECASTS, ty.span, "unnecessary type cast");
-            }
-        }
-    }
-}
-
 declare_lint! {
     UNSIGNED_NEGATION,
     Warn,
@@ -1804,6 +1780,9 @@ fn get_lints(&self) -> LintArray {
 
     fn check_fn(&mut self, cx: &Context, fn_kind: visit::FnKind, _: &ast::FnDecl,
                 blk: &ast::Block, sp: Span, id: ast::NodeId) {
+        // FIXME(#23542) Replace with type ascription.
+        #![allow(trivial_casts)]
+
         type F = for<'tcx> fn(&ty::ctxt<'tcx>,
                               ast::NodeId, ast::NodeId, ast::Ident, ast::NodeId) -> bool;
 
index ef65acf8b13f4838d5f848de3e0051f86eb17aa0..e158541cd1cfffe8471fc3a9662070de078949c1 100644 (file)
@@ -56,7 +56,7 @@
 pub use rustc::util as util;
 
 use session::Session;
-use lint::{LintPassObject, LintId};
+use lint::LintId;
 
 mod builtin;
 
@@ -67,7 +67,7 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) {
     macro_rules! add_builtin {
         ($sess:ident, $($name:ident),*,) => (
             {$(
-                store.register_pass($sess, false, box builtin::$name as LintPassObject);
+                store.register_pass($sess, false, box builtin::$name);
                 )*}
             )
     }
@@ -75,7 +75,7 @@ macro_rules! add_builtin {
     macro_rules! add_builtin_with_new {
         ($sess:ident, $($name:ident),*,) => (
             {$(
-                store.register_pass($sess, false, box builtin::$name::new() as LintPassObject);
+                store.register_pass($sess, false, box builtin::$name::new());
                 )*}
             )
     }
@@ -89,7 +89,6 @@ macro_rules! add_lint_group {
     add_builtin!(sess,
                  HardwiredLints,
                  WhileTrue,
-                 UnusedCasts,
                  ImproperCTypes,
                  BoxPointers,
                  UnusedAttributes,
@@ -129,7 +128,7 @@ macro_rules! add_lint_group {
                     UNUSED_UNSAFE, PATH_STATEMENTS);
 
     // We have one lint pass defined specially
-    store.register_pass(sess, false, box lint::GatherNodeLevels as LintPassObject);
+    store.register_pass(sess, false, box lint::GatherNodeLevels);
 
     // Insert temporary renamings for a one-time deprecation
     store.register_renamed("raw_pointer_deriving", "raw_pointer_derive");
index 506bf4a058fc6f155e10b3b8a7a5ec4709c97d3f..9d564fa56f54d88391f62a02fbe7690870f38d93 100644 (file)
@@ -14,6 +14,8 @@
 #![allow(non_camel_case_types)]
 #![allow(non_snake_case)]
 #![allow(dead_code)]
+#![allow(trivial_casts)]
+#![allow(trivial_numeric_casts)]
 
 #![crate_name = "rustc_llvm"]
 #![unstable(feature = "rustc_private")]
index b9ec22b86f0769e5b4ebf25c6fdecee6e365f55f..99a64156d667b96d89a3cef297d4500ed0f6c33c 100644 (file)
@@ -43,6 +43,9 @@
 #![feature(convert)]
 #![feature(path_relative_from)]
 
+#![allow(trivial_casts)]
+#![allow(trivial_numeric_casts)]
+
 extern crate arena;
 extern crate flate;
 extern crate getopts;
index 53aa6d44fe7e86f014df2b7a65737af761883975..327e5ab38822950ed2433a544687345e9fcc4e90 100644 (file)
@@ -1165,7 +1165,7 @@ fn visit_item(&mut self, item: &ast::Item) {
                 let name = get_ident(item.ident);
                 let name = &name;
                 let location = match *s {
-                    Some((ref s, _)) => s.to_string(),
+                    Some(s) => s.to_string(),
                     None => name.to_string(),
                 };
                 let alias_span = self.span.span_for_last_ident(item.span);
index eb759393ac6eca125f2432641e792c9d37575c2d..c48b63cdcb6c4bccc640fff215ce3a650a90c720 100644 (file)
@@ -1352,12 +1352,12 @@ fn decl_without_init(&mut self, _: ast::NodeId, _: Span) {}
     fn mutate(&mut self, _: ast::NodeId, _: Span, cmt: mc::cmt, _: euv::MutateMode) {
         match cmt.cat {
             mc::cat_upvar(mc::Upvar { id: ty::UpvarId { var_id: vid, .. }, .. }) |
-            mc::cat_local(vid) => self.reassigned = self.node == vid,
+            mc::cat_local(vid) => self.reassigned |= self.node == vid,
             mc::cat_interior(ref base_cmt, mc::InteriorField(field)) => {
                 match base_cmt.cat {
                     mc::cat_upvar(mc::Upvar { id: ty::UpvarId { var_id: vid, .. }, .. }) |
                     mc::cat_local(vid) => {
-                        self.reassigned = self.node == vid && Some(field) == self.field
+                        self.reassigned |= self.node == vid && Some(field) == self.field
                     },
                     _ => {}
                 }
index 088a34857e753a8991be403b55d93da17de960b4..e7911d5cc197006942987d85575ad302488b5037 100644 (file)
@@ -264,14 +264,29 @@ fn trans_fn_ref_with_substs_to_callee<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
 /// but for the bare function type given.
 pub fn trans_fn_pointer_shim<'a, 'tcx>(
     ccx: &'a CrateContext<'a, 'tcx>,
+    closure_kind: ty::ClosureKind,
     bare_fn_ty: Ty<'tcx>)
     -> ValueRef
 {
     let _icx = push_ctxt("trans_fn_pointer_shim");
     let tcx = ccx.tcx();
 
+    // Normalize the type for better caching.
     let bare_fn_ty = common::erase_regions(tcx, &bare_fn_ty);
-    match ccx.fn_pointer_shims().borrow().get(&bare_fn_ty) {
+
+    // If this is an impl of `Fn` or `FnMut` trait, the receiver is `&self`.
+    let is_by_ref = match closure_kind {
+        ty::FnClosureKind | ty::FnMutClosureKind => true,
+        ty::FnOnceClosureKind => false,
+    };
+    let bare_fn_ty_maybe_ref = if is_by_ref {
+        ty::mk_imm_rptr(tcx, tcx.mk_region(ty::ReStatic), bare_fn_ty)
+    } else {
+        bare_fn_ty
+    };
+
+    // Check if we already trans'd this shim.
+    match ccx.fn_pointer_shims().borrow().get(&bare_fn_ty_maybe_ref) {
         Some(&llval) => { return llval; }
         None => { }
     }
@@ -279,9 +294,6 @@ pub fn trans_fn_pointer_shim<'a, 'tcx>(
     debug!("trans_fn_pointer_shim(bare_fn_ty={})",
            bare_fn_ty.repr(tcx));
 
-    // This is an impl of `Fn` trait, so receiver is `&self`.
-    let bare_fn_ty_ref = ty::mk_imm_rptr(tcx, tcx.mk_region(ty::ReStatic), bare_fn_ty);
-
     // Construct the "tuply" version of `bare_fn_ty`. It takes two arguments: `self`,
     // which is the fn pointer, and `args`, which is the arguments tuple.
     let (opt_def_id, sig) =
@@ -306,7 +318,7 @@ pub fn trans_fn_pointer_shim<'a, 'tcx>(
                                          unsafety: ast::Unsafety::Normal,
                                          abi: synabi::RustCall,
                                          sig: ty::Binder(ty::FnSig {
-                                             inputs: vec![bare_fn_ty_ref,
+                                             inputs: vec![bare_fn_ty_maybe_ref,
                                                           tuple_input_ty],
                                              output: sig.output,
                                              variadic: false
@@ -337,8 +349,11 @@ pub fn trans_fn_pointer_shim<'a, 'tcx>(
     let mut bcx = init_function(&fcx, false, sig.output);
 
     // the first argument (`self`) will be ptr to the the fn pointer
-    let llfnpointer =
-        Load(bcx, get_param(fcx.llfn, fcx.arg_pos(0) as u32));
+    let llfnpointer = if is_by_ref {
+        Load(bcx, get_param(fcx.llfn, fcx.arg_pos(0) as u32))
+    } else {
+        get_param(fcx.llfn, fcx.arg_pos(0) as u32)
+    };
 
     // the remaining arguments will be the untupled values
     let llargs: Vec<_> =
@@ -361,7 +376,7 @@ pub fn trans_fn_pointer_shim<'a, 'tcx>(
 
     finish_fn(&fcx, bcx, sig.output, DebugLoc::None);
 
-    ccx.fn_pointer_shims().borrow_mut().insert(bare_fn_ty, llfn);
+    ccx.fn_pointer_shims().borrow_mut().insert(bare_fn_ty_maybe_ref, llfn);
 
     llfn
 }
index c1bc7219ad8253942eb826dcdbbc22aa739ac9b4..5a48b8e4bce1d37acb4ae77844ff80a2e674c864 100644 (file)
@@ -8,24 +8,27 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use back::link::mangle_internal_name_by_path_and_seq;
-use llvm::ValueRef;
+use arena::TypedArena;
+use back::link::{self, mangle_internal_name_by_path_and_seq};
+use llvm::{ValueRef, get_param};
 use middle::mem_categorization::Typer;
 use trans::adt;
 use trans::base::*;
 use trans::build::*;
-use trans::cleanup::{CleanupMethods, ScopeId};
+use trans::callee::{self, ArgVals, Callee, TraitItem, MethodData};
+use trans::cleanup::{CleanupMethods, CustomScope, ScopeId};
 use trans::common::*;
-use trans::datum::{Datum, rvalue_scratch_datum};
-use trans::datum::{Rvalue, ByValue};
-use trans::debuginfo;
+use trans::datum::{self, Datum, rvalue_scratch_datum, Rvalue, ByValue};
+use trans::debuginfo::{self, DebugLoc};
 use trans::expr;
 use trans::monomorphize::{self, MonoId};
 use trans::type_of::*;
 use middle::ty::{self, ClosureTyper};
 use middle::subst::{Substs};
 use session::config::FullDebugInfo;
+use util::ppaux::Repr;
 
+use syntax::abi::RustCall;
 use syntax::ast;
 use syntax::ast_util;
 
@@ -239,11 +242,7 @@ pub fn trans_closure_expr<'a, 'tcx>(dest: Dest<'a, 'tcx>,
     // Create the closure.
     for (i, freevar) in freevars.iter().enumerate() {
         let datum = expr::trans_local_var(bcx, freevar.def);
-        let upvar_slot_dest = adt::trans_field_ptr(bcx,
-                                                   &*repr,
-                                                   dest_addr,
-                                                   0,
-                                                   i);
+        let upvar_slot_dest = adt::trans_field_ptr(bcx, &*repr, dest_addr, 0, i);
         let upvar_id = ty::UpvarId { var_id: freevar.def.local_node_id(),
                                      closure_expr_id: id };
         match tcx.upvar_capture(upvar_id).unwrap() {
@@ -259,3 +258,186 @@ pub fn trans_closure_expr<'a, 'tcx>(dest: Dest<'a, 'tcx>,
 
     Some(bcx)
 }
+
+pub fn trans_closure_method<'a, 'tcx>(ccx: &'a CrateContext<'a, 'tcx>,
+                                      closure_def_id: ast::DefId,
+                                      substs: Substs<'tcx>,
+                                      node: ExprOrMethodCall,
+                                      param_substs: &'tcx Substs<'tcx>,
+                                      trait_closure_kind: ty::ClosureKind)
+                                      -> ValueRef
+{
+    // The substitutions should have no type parameters remaining
+    // after passing through fulfill_obligation
+    let llfn = callee::trans_fn_ref_with_substs(ccx,
+                                                closure_def_id,
+                                                node,
+                                                param_substs,
+                                                substs.clone()).val;
+
+    // If the closure is a Fn closure, but a FnOnce is needed (etc),
+    // then adapt the self type
+    let closure_kind = ccx.tcx().closure_kind(closure_def_id);
+    trans_closure_adapter_shim(ccx,
+                               closure_def_id,
+                               substs,
+                               closure_kind,
+                               trait_closure_kind,
+                               llfn)
+}
+
+fn trans_closure_adapter_shim<'a, 'tcx>(
+    ccx: &'a CrateContext<'a, 'tcx>,
+    closure_def_id: ast::DefId,
+    substs: Substs<'tcx>,
+    llfn_closure_kind: ty::ClosureKind,
+    trait_closure_kind: ty::ClosureKind,
+    llfn: ValueRef)
+    -> ValueRef
+{
+    let _icx = push_ctxt("trans_closure_adapter_shim");
+    let tcx = ccx.tcx();
+
+    debug!("trans_closure_adapter_shim(llfn_closure_kind={:?}, \
+           trait_closure_kind={:?}, \
+           llfn={})",
+           llfn_closure_kind,
+           trait_closure_kind,
+           ccx.tn().val_to_string(llfn));
+
+    match (llfn_closure_kind, trait_closure_kind) {
+        (ty::FnClosureKind, ty::FnClosureKind) |
+        (ty::FnMutClosureKind, ty::FnMutClosureKind) |
+        (ty::FnOnceClosureKind, ty::FnOnceClosureKind) => {
+            // No adapter needed.
+            llfn
+        }
+        (ty::FnClosureKind, ty::FnMutClosureKind) => {
+            // The closure fn `llfn` is a `fn(&self, ...)`.  We want a
+            // `fn(&mut self, ...)`. In fact, at trans time, these are
+            // basically the same thing, so we can just return llfn.
+            llfn
+        }
+        (ty::FnClosureKind, ty::FnOnceClosureKind) |
+        (ty::FnMutClosureKind, ty::FnOnceClosureKind) => {
+            // The closure fn `llfn` is a `fn(&self, ...)` or `fn(&mut
+            // self, ...)`.  We want a `fn(self, ...)`. We can produce
+            // this by doing something like:
+            //
+            //     fn call_once(self, ...) { call_mut(&self, ...) }
+            //     fn call_once(mut self, ...) { call_mut(&mut self, ...) }
+            //
+            // These are both the same at trans time.
+            trans_fn_once_adapter_shim(ccx, closure_def_id, substs, llfn)
+        }
+        _ => {
+            tcx.sess.bug(&format!("trans_closure_adapter_shim: cannot convert {:?} to {:?}",
+                                  llfn_closure_kind,
+                                  trait_closure_kind));
+        }
+    }
+}
+
+fn trans_fn_once_adapter_shim<'a, 'tcx>(
+    ccx: &'a CrateContext<'a, 'tcx>,
+    closure_def_id: ast::DefId,
+    substs: Substs<'tcx>,
+    llreffn: ValueRef)
+    -> ValueRef
+{
+    debug!("trans_fn_once_adapter_shim(closure_def_id={}, substs={}, llreffn={})",
+           closure_def_id.repr(ccx.tcx()),
+           substs.repr(ccx.tcx()),
+           ccx.tn().val_to_string(llreffn));
+
+    let tcx = ccx.tcx();
+    let typer = NormalizingClosureTyper::new(tcx);
+
+    // Find a version of the closure type. Substitute static for the
+    // region since it doesn't really matter.
+    let substs = tcx.mk_substs(substs);
+    let closure_ty = ty::mk_closure(tcx, closure_def_id, substs);
+    let ref_closure_ty = ty::mk_imm_rptr(tcx, tcx.mk_region(ty::ReStatic), closure_ty);
+
+    // Make a version with the type of by-ref closure.
+    let ty::ClosureTy { unsafety, abi, mut sig } = typer.closure_type(closure_def_id, substs);
+    sig.0.inputs.insert(0, ref_closure_ty); // sig has no self type as of yet
+    let llref_bare_fn_ty = tcx.mk_bare_fn(ty::BareFnTy { unsafety: unsafety,
+                                                               abi: abi,
+                                                               sig: sig.clone() });
+    let llref_fn_ty = ty::mk_bare_fn(tcx, None, llref_bare_fn_ty);
+    debug!("trans_fn_once_adapter_shim: llref_fn_ty={}",
+           llref_fn_ty.repr(tcx));
+
+    // Make a version of the closure type with the same arguments, but
+    // with argument #0 being by value.
+    assert_eq!(abi, RustCall);
+    sig.0.inputs[0] = closure_ty;
+    let llonce_bare_fn_ty = tcx.mk_bare_fn(ty::BareFnTy { unsafety: unsafety,
+                                                                abi: abi,
+                                                                sig: sig });
+    let llonce_fn_ty = ty::mk_bare_fn(tcx, None, llonce_bare_fn_ty);
+
+    // Create the by-value helper.
+    let function_name = link::mangle_internal_name_by_type_and_seq(ccx, llonce_fn_ty, "once_shim");
+    let lloncefn = decl_internal_rust_fn(ccx, llonce_fn_ty, &function_name);
+
+    let sig = ty::erase_late_bound_regions(tcx, &llonce_bare_fn_ty.sig);
+    let (block_arena, fcx): (TypedArena<_>, FunctionContext);
+    block_arena = TypedArena::new();
+    fcx = new_fn_ctxt(ccx,
+                      lloncefn,
+                      ast::DUMMY_NODE_ID,
+                      false,
+                      sig.output,
+                      substs,
+                      None,
+                      &block_arena);
+    let mut bcx = init_function(&fcx, false, sig.output);
+
+    // the first argument (`self`) will be the (by value) closure env.
+    let self_scope = fcx.push_custom_cleanup_scope();
+    let self_scope_id = CustomScope(self_scope);
+    let rvalue_mode = datum::appropriate_rvalue_mode(ccx, closure_ty);
+    let llself = get_param(lloncefn, fcx.arg_pos(0) as u32);
+    let env_datum = Datum::new(llself, closure_ty, Rvalue::new(rvalue_mode));
+    let env_datum = unpack_datum!(bcx,
+                                  env_datum.to_lvalue_datum_in_scope(bcx, "self",
+                                                                     self_scope_id));
+
+    debug!("trans_fn_once_adapter_shim: env_datum={}",
+           bcx.val_to_string(env_datum.val));
+
+    // the remaining arguments will be packed up in a tuple.
+    let input_tys = match sig.inputs[1].sty {
+        ty::ty_tup(ref tys) => &**tys,
+        _ => bcx.sess().bug(&format!("trans_fn_once_adapter_shim: not rust-call! \
+                                      closure_def_id={}",
+                                     closure_def_id.repr(tcx)))
+    };
+    let llargs: Vec<_> =
+        input_tys.iter()
+                 .enumerate()
+                 .map(|(i, _)| get_param(lloncefn, fcx.arg_pos(i+1) as u32))
+                 .collect();
+
+    let dest =
+        fcx.llretslotptr.get().map(
+            |_| expr::SaveIn(fcx.get_ret_slot(bcx, sig.output, "ret_slot")));
+
+    let callee_data = TraitItem(MethodData { llfn: llreffn,
+                                             llself: env_datum.val });
+
+    bcx = callee::trans_call_inner(bcx,
+                                   DebugLoc::None,
+                                   llref_fn_ty,
+                                   |bcx, _| Callee { bcx: bcx, data: callee_data },
+                                   ArgVals(&llargs),
+                                   dest).bcx;
+
+    fcx.pop_custom_cleanup_scope(self_scope);
+
+    finish_fn(&fcx, bcx, sig.output, DebugLoc::None);
+
+    lloncefn
+}
index e181df545e6fc06aa63f4b0e2a39f2ea835d9dea..15738d1e61ac14122f0161df205f0d536ebca146 100644 (file)
@@ -471,15 +471,6 @@ pub fn add_clean_if_rvalue<'blk>(self,
             })
     }
 
-    /// Ensures that `self` will get cleaned up, if it is not an lvalue already.
-    pub fn clean<'blk>(self,
-                       bcx: Block<'blk, 'tcx>,
-                       name: &'static str,
-                       expr_id: ast::NodeId)
-                       -> Block<'blk, 'tcx> {
-        self.to_lvalue_datum(bcx, name, expr_id).bcx
-    }
-
     pub fn to_lvalue_datum<'blk>(self,
                                  bcx: Block<'blk, 'tcx>,
                                  name: &str,
index ceb9a29efa8879a9d30ad4544d812c579e87f97f..ba8de6da42f72210abebe59610ea99cec0d99617 100644 (file)
@@ -1227,22 +1227,9 @@ fn make_field(field_name: &str, expr: P<ast::Expr>) -> ast::Field {
             trans_overloaded_op(bcx, expr, MethodCall::expr(expr.id), base,
                                 vec![(idx_datum, idx.id)], Some(dest), true).bcx
         }
-        ast::ExprCast(ref val, _) => {
-            // DPS output mode means this is a trait cast:
-            if ty::type_is_trait(node_id_type(bcx, expr.id)) {
-                let trait_ref =
-                    bcx.tcx().object_cast_map.borrow()
-                                             .get(&expr.id)
-                                             .cloned()
-                                             .unwrap();
-                let trait_ref = bcx.monomorphize(&trait_ref);
-                let datum = unpack_datum!(bcx, trans(bcx, &**val));
-                meth::trans_trait_cast(bcx, datum, expr.id,
-                                       trait_ref, dest)
-            } else {
-                bcx.tcx().sess.span_bug(expr.span,
-                                        "expr_cast of non-trait");
-            }
+        ast::ExprCast(..) => {
+            // Trait casts used to come this way, now they should be coercions.
+            bcx.tcx().sess.span_bug(expr.span, "DPS expr_cast (residual trait cast?)")
         }
         ast::ExprAssignOp(op, ref dst, ref src) => {
             trans_assign_op(bcx, expr, op, &**dst, &**src)
@@ -1779,6 +1766,8 @@ fn trans_eager_binop<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
       ast::BiAdd => {
         if is_float {
             FAdd(bcx, lhs, rhs, binop_debug_loc)
+        } else if is_simd {
+            Add(bcx, lhs, rhs, binop_debug_loc)
         } else {
             let (newbcx, res) = with_overflow_check(
                 bcx, OverflowOp::Add, info, lhs_t, lhs, rhs, binop_debug_loc);
@@ -1789,6 +1778,8 @@ fn trans_eager_binop<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
       ast::BiSub => {
         if is_float {
             FSub(bcx, lhs, rhs, binop_debug_loc)
+        } else if is_simd {
+            Sub(bcx, lhs, rhs, binop_debug_loc)
         } else {
             let (newbcx, res) = with_overflow_check(
                 bcx, OverflowOp::Sub, info, lhs_t, lhs, rhs, binop_debug_loc);
@@ -1799,6 +1790,8 @@ fn trans_eager_binop<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
       ast::BiMul => {
         if is_float {
             FMul(bcx, lhs, rhs, binop_debug_loc)
+        } else if is_simd {
+            Mul(bcx, lhs, rhs, binop_debug_loc)
         } else {
             let (newbcx, res) = with_overflow_check(
                 bcx, OverflowOp::Mul, info, lhs_t, lhs, rhs, binop_debug_loc);
@@ -2091,7 +2084,7 @@ fn trans_imm_cast<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
     let mut bcx = bcx;
     let ccx = bcx.ccx();
 
-    let t_in = expr_ty(bcx, expr);
+    let t_in = expr_ty_adjusted(bcx, expr);
     let t_out = node_id_type(bcx, id);
     let k_in = cast_type_kind(bcx.tcx(), t_in);
     let k_out = cast_type_kind(bcx.tcx(), t_out);
@@ -2103,7 +2096,8 @@ fn trans_imm_cast<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
     // by-value as appropriate given its type:
     let mut datum = unpack_datum!(bcx, trans(bcx, expr));
 
-    if cast_is_noop(datum.ty, t_out) {
+    let datum_ty = monomorphize_type(bcx, datum.ty);
+    if cast_is_noop(datum_ty, t_out) {
         datum.ty = t_out;
         return DatumBlock::new(bcx, datum);
     }
index 4da17972c55fb68e4eda4207eb20911b0c67374c..1a38b3d142676f1a717c395a702d4a6a5302e0fe 100644 (file)
 use middle::subst::VecPerParamSpace;
 use middle::subst;
 use middle::traits;
+use middle::ty::ClosureTyper;
 use trans::base::*;
 use trans::build::*;
 use trans::callee::*;
 use trans::callee;
 use trans::cleanup;
+use trans::closure;
 use trans::common::*;
 use trans::consts;
 use trans::datum::*;
 use trans::debuginfo::DebugLoc;
-use trans::expr::{SaveIn, Ignore};
+use trans::expr::SaveIn;
 use trans::expr;
 use trans::glue;
 use trans::machine;
@@ -358,19 +360,21 @@ fn trans_monomorphized_callee<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
         traits::VtableClosure(closure_def_id, substs) => {
             // The substitutions should have no type parameters remaining
             // after passing through fulfill_obligation
-            let llfn = trans_fn_ref_with_substs(bcx.ccx(),
-                                                closure_def_id,
-                                                MethodCallKey(method_call),
-                                                bcx.fcx.param_substs,
-                                                substs).val;
-
+            let trait_closure_kind = bcx.tcx().lang_items.fn_trait_kind(trait_id).unwrap();
+            let llfn = closure::trans_closure_method(bcx.ccx(),
+                                                     closure_def_id,
+                                                     substs,
+                                                     MethodCallKey(method_call),
+                                                     bcx.fcx.param_substs,
+                                                     trait_closure_kind);
             Callee {
                 bcx: bcx,
                 data: Fn(llfn),
             }
         }
         traits::VtableFnPointer(fn_ty) => {
-            let llfn = trans_fn_pointer_shim(bcx.ccx(), fn_ty);
+            let trait_closure_kind = bcx.tcx().lang_items.fn_trait_kind(trait_id).unwrap();
+            let llfn = trans_fn_pointer_shim(bcx.ccx(), trait_closure_kind, fn_ty);
             Callee { bcx: bcx, data: Fn(llfn) }
         }
         traits::VtableObject(ref data) => {
@@ -645,9 +649,6 @@ pub fn trans_object_shim<'a, 'tcx>(
 
     assert!(!fcx.needs_ret_allocas);
 
-    let sig =
-        ty::erase_late_bound_regions(bcx.tcx(), &fty.sig);
-
     let dest =
         fcx.llretslotptr.get().map(
             |_| expr::SaveIn(fcx.get_ret_slot(bcx, sig.output, "ret_slot")));
@@ -714,17 +715,18 @@ pub fn get_vtable<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
                 emit_vtable_methods(ccx, id, substs, param_substs).into_iter()
             }
             traits::VtableClosure(closure_def_id, substs) => {
-                let llfn = trans_fn_ref_with_substs(
-                    ccx,
-                    closure_def_id,
-                    ExprId(0),
-                    param_substs,
-                    substs).val;
-
+                let trait_closure_kind = tcx.lang_items.fn_trait_kind(trait_ref.def_id()).unwrap();
+                let llfn = closure::trans_closure_method(ccx,
+                                                         closure_def_id,
+                                                         substs,
+                                                         ExprId(0),
+                                                         param_substs,
+                                                         trait_closure_kind);
                 vec![llfn].into_iter()
             }
             traits::VtableFnPointer(bare_fn_ty) => {
-                vec![trans_fn_pointer_shim(ccx, bare_fn_ty)].into_iter()
+                let trait_closure_kind = tcx.lang_items.fn_trait_kind(trait_ref.def_id()).unwrap();
+                vec![trans_fn_pointer_shim(ccx, trait_closure_kind, bare_fn_ty)].into_iter()
             }
             traits::VtableObject(ref data) => {
                 // this would imply that the Self type being erased is
@@ -861,44 +863,6 @@ fn emit_vtable_methods<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
         .collect()
 }
 
-/// Generates the code to convert from a pointer (`Box<T>`, `&T`, etc) into an object
-/// (`Box<Trait>`, `&Trait`, etc). This means creating a pair where the first word is the vtable
-/// and the second word is the pointer.
-pub fn trans_trait_cast<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
-                                    datum: Datum<'tcx, Expr>,
-                                    id: ast::NodeId,
-                                    trait_ref: ty::PolyTraitRef<'tcx>,
-                                    dest: expr::Dest)
-                                    -> Block<'blk, 'tcx> {
-    let mut bcx = bcx;
-    let _icx = push_ctxt("meth::trans_trait_cast");
-
-    let lldest = match dest {
-        Ignore => {
-            return datum.clean(bcx, "trait_trait_cast", id);
-        }
-        SaveIn(dest) => dest
-    };
-
-    debug!("trans_trait_cast: trait_ref={}",
-           trait_ref.repr(bcx.tcx()));
-
-    let llty = type_of(bcx.ccx(), datum.ty);
-
-    // Store the pointer into the first half of pair.
-    let llboxdest = GEPi(bcx, lldest, &[0, abi::FAT_PTR_ADDR]);
-    let llboxdest = PointerCast(bcx, llboxdest, llty.ptr_to());
-    bcx = datum.store_to(bcx, llboxdest);
-
-    // Store the vtable into the second half of pair.
-    let vtable = get_vtable(bcx.ccx(), trait_ref, bcx.fcx.param_substs);
-    let llvtabledest = GEPi(bcx, lldest, &[0, abi::FAT_PTR_EXTRA]);
-    let llvtabledest = PointerCast(bcx, llvtabledest, val_ty(vtable).ptr_to());
-    Store(bcx, vtable, llvtabledest);
-
-    bcx
-}
-
 /// Replace the self type (&Self or Box<Self>) with an opaque pointer.
 pub fn opaque_method_ty<'tcx>(tcx: &ty::ctxt<'tcx>, method_ty: &ty::BareFnTy<'tcx>)
         -> &'tcx ty::BareFnTy<'tcx> {
index 71900855266e9f4e7fc1b411d13cd65909460e11..e9de8bd879e202342cbe00df6e0d61ec3adf812c 100644 (file)
@@ -55,7 +55,7 @@
 use middle::privacy::{AllPublic, LastMod};
 use middle::subst::{FnSpace, TypeSpace, SelfSpace, Subst, Substs};
 use middle::traits;
-use middle::ty::{self, RegionEscape, ToPolyTraitRef, Ty};
+use middle::ty::{self, RegionEscape, Ty};
 use rscope::{self, UnelidableRscope, RegionScope, ElidableRscope,
              ObjectLifetimeDefaultRscope, ShiftedRscope, BindingRscope};
 use util::common::{ErrorReported, FN_OUTPUT_NAME};
@@ -608,24 +608,16 @@ pub fn instantiate_poly_trait_ref<'tcx>(
     poly_projections: &mut Vec<ty::PolyProjectionPredicate<'tcx>>)
     -> ty::PolyTraitRef<'tcx>
 {
-    let mut projections = Vec::new();
-
-    // The trait reference introduces a binding level here, so
-    // we need to shift the `rscope`. It'd be nice if we could
-    // do away with this rscope stuff and work this knowledge
-    // into resolve_lifetimes, as we do with non-omitted
-    // 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,
-                                          None, self_ty, Some(&mut projections));
-
-    for projection in projections {
-        poly_projections.push(ty::Binder(projection));
-    }
-
-    ty::Binder(trait_ref)
+    let trait_ref = &ast_trait_ref.trait_ref;
+    let trait_def_id = trait_def_id(this, trait_ref);
+    ast_path_to_poly_trait_ref(this,
+                               rscope,
+                               trait_ref.path.span,
+                               PathParamMode::Explicit,
+                               trait_def_id,
+                               self_ty,
+                               trait_ref.path.segments.last().unwrap(),
+                               poly_projections)
 }
 
 /// Instantiates the path for the given trait reference, assuming that it's
@@ -634,31 +626,27 @@ pub fn instantiate_poly_trait_ref<'tcx>(
 ///
 /// If the `projections` argument is `None`, then assoc type bindings like `Foo<T=X>`
 /// are disallowed. Otherwise, they are pushed onto the vector given.
-pub fn instantiate_trait_ref<'tcx>(
+pub fn instantiate_mono_trait_ref<'tcx>(
     this: &AstConv<'tcx>,
     rscope: &RegionScope,
     trait_ref: &ast::TraitRef,
-    impl_id: Option<ast::NodeId>,
-    self_ty: Option<Ty<'tcx>>,
-    projections: Option<&mut Vec<ty::ProjectionPredicate<'tcx>>>)
+    self_ty: Option<Ty<'tcx>>)
     -> Rc<ty::TraitRef<'tcx>>
 {
+    let trait_def_id = trait_def_id(this, trait_ref);
+    ast_path_to_mono_trait_ref(this,
+                               rscope,
+                               trait_ref.path.span,
+                               PathParamMode::Explicit,
+                               trait_def_id,
+                               self_ty,
+                               trait_ref.path.segments.last().unwrap())
+}
+
+fn trait_def_id<'tcx>(this: &AstConv<'tcx>, trait_ref: &ast::TraitRef) -> ast::DefId {
     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,
-                                                  path.segments.last().unwrap(),
-                                                  projections);
-            if let Some(id) = impl_id {
-                this.tcx().impl_trait_refs.borrow_mut().insert(id, trait_ref.clone());
-            }
-            trait_ref
-        }
+        def::DefTrait(trait_def_id) => trait_def_id,
         _ => {
             span_fatal!(this.tcx().sess, path.span, E0245, "`{}` is not a trait",
                         path.user_string(this.tcx()));
@@ -676,24 +664,17 @@ fn object_path_to_poly_trait_ref<'a,'tcx>(
     mut projections: &mut Vec<ty::PolyProjectionPredicate<'tcx>>)
     -> ty::PolyTraitRef<'tcx>
 {
-    // we are introducing a binder here, so shift the
-    // anonymous regions depth to account for that
-    let shifted_rscope = ShiftedRscope::new(rscope);
-
-    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,
-                                                     trait_segment,
-                                                     Some(&mut tmp)));
-    projections.extend(tmp.into_iter().map(ty::Binder));
-    trait_ref
+    ast_path_to_poly_trait_ref(this,
+                               rscope,
+                               span,
+                               param_mode,
+                               trait_def_id,
+                               None,
+                               trait_segment,
+                               projections)
 }
 
-fn ast_path_to_trait_ref<'a,'tcx>(
+fn ast_path_to_poly_trait_ref<'a,'tcx>(
     this: &AstConv<'tcx>,
     rscope: &RegionScope,
     span: Span,
@@ -701,10 +682,78 @@ fn ast_path_to_trait_ref<'a,'tcx>(
     trait_def_id: ast::DefId,
     self_ty: Option<Ty<'tcx>>,
     trait_segment: &ast::PathSegment,
-    mut projections: Option<&mut Vec<ty::ProjectionPredicate<'tcx>>>)
-    -> Rc<ty::TraitRef<'tcx>>
+    poly_projections: &mut Vec<ty::PolyProjectionPredicate<'tcx>>)
+    -> ty::PolyTraitRef<'tcx>
+{
+    // The trait reference introduces a binding level here, so
+    // we need to shift the `rscope`. It'd be nice if we could
+    // do away with this rscope stuff and work this knowledge
+    // into resolve_lifetimes, as we do with non-omitted
+    // lifetimes. Oh well, not there yet.
+    let shifted_rscope = &ShiftedRscope::new(rscope);
+
+    let (substs, assoc_bindings) =
+        create_substs_for_ast_trait_ref(this,
+                                        shifted_rscope,
+                                        span,
+                                        param_mode,
+                                        trait_def_id,
+                                        self_ty,
+                                        trait_segment);
+    let poly_trait_ref = ty::Binder(Rc::new(ty::TraitRef::new(trait_def_id, substs)));
+
+    {
+        let converted_bindings =
+            assoc_bindings
+            .iter()
+            .filter_map(|binding| {
+                // specify type to assert that error was already reported in Err case:
+                let predicate: Result<_, ErrorReported> =
+                    ast_type_binding_to_poly_projection_predicate(this,
+                                                                  poly_trait_ref.clone(),
+                                                                  self_ty,
+                                                                  binding);
+                predicate.ok() // ok to ignore Err() because ErrorReported (see above)
+            });
+        poly_projections.extend(converted_bindings);
+    }
+
+    poly_trait_ref
+}
+
+fn ast_path_to_mono_trait_ref<'a,'tcx>(this: &AstConv<'tcx>,
+                                       rscope: &RegionScope,
+                                       span: Span,
+                                       param_mode: PathParamMode,
+                                       trait_def_id: ast::DefId,
+                                       self_ty: Option<Ty<'tcx>>,
+                                       trait_segment: &ast::PathSegment)
+                                       -> Rc<ty::TraitRef<'tcx>>
 {
-    debug!("ast_path_to_trait_ref {:?}", trait_segment);
+    let (substs, assoc_bindings) =
+        create_substs_for_ast_trait_ref(this,
+                                        rscope,
+                                        span,
+                                        param_mode,
+                                        trait_def_id,
+                                        self_ty,
+                                        trait_segment);
+    prohibit_projections(this.tcx(), &assoc_bindings);
+    Rc::new(ty::TraitRef::new(trait_def_id, substs))
+}
+
+fn create_substs_for_ast_trait_ref<'a,'tcx>(this: &AstConv<'tcx>,
+                                            rscope: &RegionScope,
+                                            span: Span,
+                                            param_mode: PathParamMode,
+                                            trait_def_id: ast::DefId,
+                                            self_ty: Option<Ty<'tcx>>,
+                                            trait_segment: &ast::PathSegment)
+                                            -> (&'tcx Substs<'tcx>, Vec<ConvertedBinding<'tcx>>)
+{
+    debug!("create_substs_for_ast_trait_ref(trait_segment={:?})",
+           trait_segment);
+
     let trait_def = match this.get_trait_def(span, trait_def_id) {
         Ok(trait_def) => trait_def,
         Err(ErrorReported) => {
@@ -752,34 +801,16 @@ fn ast_path_to_trait_ref<'a,'tcx>(
                                             self_ty,
                                             types,
                                             regions);
-    let substs = this.tcx().mk_substs(substs);
 
-    let trait_ref = Rc::new(ty::TraitRef::new(trait_def_id, substs));
-
-    match projections {
-        None => {
-            prohibit_projections(this.tcx(), &assoc_bindings);
-        }
-        Some(ref mut v) => {
-            for binding in &assoc_bindings {
-                match ast_type_binding_to_projection_predicate(this, trait_ref.clone(),
-                                                               self_ty, binding) {
-                    Ok(pp) => { v.push(pp); }
-                    Err(ErrorReported) => { }
-                }
-            }
-        }
-    }
-
-    trait_ref
+    (this.tcx().mk_substs(substs), assoc_bindings)
 }
 
-fn ast_type_binding_to_projection_predicate<'tcx>(
+fn ast_type_binding_to_poly_projection_predicate<'tcx>(
     this: &AstConv<'tcx>,
-    mut trait_ref: Rc<ty::TraitRef<'tcx>>,
+    mut trait_ref: ty::PolyTraitRef<'tcx>,
     self_ty: Option<Ty<'tcx>>,
     binding: &ConvertedBinding<'tcx>)
-    -> Result<ty::ProjectionPredicate<'tcx>, ErrorReported>
+    -> Result<ty::PolyProjectionPredicate<'tcx>, ErrorReported>
 {
     let tcx = this.tcx();
 
@@ -800,14 +831,14 @@ fn ast_type_binding_to_projection_predicate<'tcx>(
     // We want to produce `<B as SuperTrait<int>>::T == foo`.
 
     // Simple case: X is defined in the current trait.
-    if this.trait_defines_associated_type_named(trait_ref.def_id, binding.item_name) {
-        return Ok(ty::ProjectionPredicate {
-            projection_ty: ty::ProjectionTy {
-                trait_ref: trait_ref,
+    if this.trait_defines_associated_type_named(trait_ref.def_id(), binding.item_name) {
+        return Ok(ty::Binder(ty::ProjectionPredicate {      // <-------------------+
+            projection_ty: ty::ProjectionTy {               //                     |
+                trait_ref: trait_ref.skip_binder().clone(), // Binder moved here --+
                 item_name: binding.item_name,
             },
             ty: binding.ty,
-        });
+        }));
     }
 
     // Otherwise, we have to walk through the supertraits to find
@@ -820,17 +851,17 @@ fn ast_type_binding_to_projection_predicate<'tcx>(
 
     let dummy_self_ty = ty::mk_infer(tcx, ty::FreshTy(0));
     if self_ty.is_none() { // if converting for an object type
-        let mut dummy_substs = trait_ref.substs.clone();
-        assert!(dummy_substs.self_ty().is_none());
-        dummy_substs.types.push(SelfSpace, dummy_self_ty);
-        trait_ref = Rc::new(ty::TraitRef::new(trait_ref.def_id,
-                                              tcx.mk_substs(dummy_substs)));
+        let mut dummy_substs = trait_ref.skip_binder().substs.clone(); // binder moved here -+
+        assert!(dummy_substs.self_ty().is_none());                     //                    |
+        dummy_substs.types.push(SelfSpace, dummy_self_ty);             //                    |
+        trait_ref = ty::Binder(Rc::new(ty::TraitRef::new(trait_ref.def_id(), // <------------+
+                                                         tcx.mk_substs(dummy_substs))));
     }
 
-    try!(this.ensure_super_predicates(binding.span, trait_ref.def_id));
+    try!(this.ensure_super_predicates(binding.span, trait_ref.def_id()));
 
     let mut candidates: Vec<ty::PolyTraitRef> =
-        traits::supertraits(tcx, trait_ref.to_poly_trait_ref())
+        traits::supertraits(tcx, trait_ref.clone())
         .filter(|r| this.trait_defines_associated_type_named(r.def_id(), binding.item_name))
         .collect();
 
@@ -865,21 +896,13 @@ fn ast_type_binding_to_projection_predicate<'tcx>(
         }
     };
 
-    if ty::binds_late_bound_regions(tcx, &candidate) {
-        span_err!(tcx.sess, binding.span, E0219,
-            "associated type `{}` defined in higher-ranked supertrait `{}`",
-                    token::get_name(binding.item_name),
-                    candidate.user_string(tcx));
-        return Err(ErrorReported);
-    }
-
-    Ok(ty::ProjectionPredicate {
-        projection_ty: ty::ProjectionTy {
-            trait_ref: candidate.0,
+    Ok(ty::Binder(ty::ProjectionPredicate {             // <-------------------------+
+        projection_ty: ty::ProjectionTy {               //                           |
+            trait_ref: candidate.skip_binder().clone(), // binder is moved up here --+
             item_name: binding.item_name,
         },
         ty: binding.ty,
-    })
+    }))
 }
 
 fn ast_path_to_ty<'tcx>(
@@ -1134,14 +1157,14 @@ fn qpath_to_ty<'tcx>(this: &AstConv<'tcx>,
 
     debug!("qpath_to_ty: self_type={}", self_ty.repr(tcx));
 
-    let trait_ref = ast_path_to_trait_ref(this,
-                                          rscope,
-                                          span,
-                                          param_mode,
-                                          trait_def_id,
-                                          Some(self_ty),
-                                          trait_segment,
-                                          None);
+    let trait_ref =
+        ast_path_to_mono_trait_ref(this,
+                                   rscope,
+                                   span,
+                                   param_mode,
+                                   trait_def_id,
+                                   Some(self_ty),
+                                   trait_segment);
 
     debug!("qpath_to_ty: trait_ref={}", trait_ref.repr(tcx));
 
index 32f91a175f3c3eed8d9eb73355aea543127124a8..d2a06fcf9909138d1a1b354350c9dc1ea903b5ce 100644 (file)
@@ -16,6 +16,7 @@
 use middle::region;
 use middle::subst;
 use middle::ty::{self, ToPolyTraitRef, Ty};
+use std::cmp;
 use syntax::abi;
 use syntax::ast;
 use syntax::ast_util;
@@ -109,15 +110,11 @@ fn deduce_expectations_from_expected_type<'a,'tcx>(
         ty::ty_trait(ref object_type) => {
             let proj_bounds = object_type.projection_bounds_with_self_ty(fcx.tcx(),
                                                                          fcx.tcx().types.err);
-            let expectations =
-                proj_bounds.iter()
-                           .filter_map(|pb| deduce_expectations_from_projection(fcx, pb))
-                           .next();
-
-            match expectations {
-                Some((sig, kind)) => (Some(sig), Some(kind)),
-                None => (None, None)
-            }
+            let sig = proj_bounds.iter()
+                                 .filter_map(|pb| deduce_sig_from_projection(fcx, pb))
+                                 .next();
+            let kind = fcx.tcx().lang_items.fn_trait_kind(object_type.principal_def_id());
+            (sig, kind)
         }
         ty::ty_infer(ty::TyVar(vid)) => {
             deduce_expectations_from_obligations(fcx, vid)
@@ -136,7 +133,7 @@ fn deduce_expectations_from_obligations<'a,'tcx>(
     let fulfillment_cx = fcx.inh.fulfillment_cx.borrow();
     // Here `expected_ty` is known to be a type inference variable.
 
-    let expected_sig_and_kind =
+    let expected_sig =
         fulfillment_cx
         .pending_obligations()
         .iter()
@@ -150,7 +147,7 @@ fn deduce_expectations_from_obligations<'a,'tcx>(
                 ty::Predicate::Projection(ref proj_predicate) => {
                     let trait_ref = proj_predicate.to_poly_trait_ref();
                     self_type_matches_expected_vid(fcx, trait_ref, expected_vid)
-                        .and_then(|_| deduce_expectations_from_projection(fcx, proj_predicate))
+                        .and_then(|_| deduce_sig_from_projection(fcx, proj_predicate))
                 }
                 _ => {
                     None
@@ -159,14 +156,10 @@ fn deduce_expectations_from_obligations<'a,'tcx>(
         })
         .next();
 
-    match expected_sig_and_kind {
-        Some((sig, kind)) => { return (Some(sig), Some(kind)); }
-        None => { }
-    }
-
     // Even if we can't infer the full signature, we may be able to
     // infer the kind. This can occur if there is a trait-reference
-    // like `F : Fn<A>`.
+    // like `F : Fn<A>`. Note that due to subtyping we could encounter
+    // many viable options, so pick the most restrictive.
     let expected_kind =
         fulfillment_cx
         .pending_obligations()
@@ -183,54 +176,61 @@ fn deduce_expectations_from_obligations<'a,'tcx>(
                 .and_then(|trait_ref| self_type_matches_expected_vid(fcx, trait_ref, expected_vid))
                 .and_then(|trait_ref| fcx.tcx().lang_items.fn_trait_kind(trait_ref.def_id()))
         })
-        .next();
+        .fold(None, pick_most_restrictive_closure_kind);
+
+    (expected_sig, expected_kind)
+}
 
-    (None, expected_kind)
+fn pick_most_restrictive_closure_kind(best: Option<ty::ClosureKind>,
+                                      cur: ty::ClosureKind)
+                                      -> Option<ty::ClosureKind>
+{
+    match best {
+        None => Some(cur),
+        Some(best) => Some(cmp::min(best, cur))
+    }
 }
 
 /// Given a projection like "<F as Fn(X)>::Result == Y", we can deduce
 /// everything we need to know about a closure.
-fn deduce_expectations_from_projection<'a,'tcx>(
+fn deduce_sig_from_projection<'a,'tcx>(
     fcx: &FnCtxt<'a,'tcx>,
     projection: &ty::PolyProjectionPredicate<'tcx>)
-    -> Option<(ty::FnSig<'tcx>, ty::ClosureKind)>
+    -> Option<ty::FnSig<'tcx>>
 {
     let tcx = fcx.tcx();
 
-    debug!("deduce_expectations_from_projection({})",
+    debug!("deduce_sig_from_projection({})",
            projection.repr(tcx));
 
     let trait_ref = projection.to_poly_trait_ref();
 
-    let kind = match tcx.lang_items.fn_trait_kind(trait_ref.def_id()) {
-        Some(k) => k,
-        None => { return None; }
-    };
-
-    debug!("found object type {:?}", kind);
+    if tcx.lang_items.fn_trait_kind(trait_ref.def_id()).is_none() {
+        return None;
+    }
 
     let arg_param_ty = *trait_ref.substs().types.get(subst::TypeSpace, 0);
     let arg_param_ty = fcx.infcx().resolve_type_vars_if_possible(&arg_param_ty);
-    debug!("arg_param_ty {}", arg_param_ty.repr(tcx));
+    debug!("deduce_sig_from_projection: arg_param_ty {}", arg_param_ty.repr(tcx));
 
     let input_tys = match arg_param_ty.sty {
         ty::ty_tup(ref tys) => { (*tys).clone() }
         _ => { return None; }
     };
-    debug!("input_tys {}", input_tys.repr(tcx));
+    debug!("deduce_sig_from_projection: input_tys {}", input_tys.repr(tcx));
 
     let ret_param_ty = projection.0.ty;
     let ret_param_ty = fcx.infcx().resolve_type_vars_if_possible(&ret_param_ty);
-    debug!("ret_param_ty {}", ret_param_ty.repr(tcx));
+    debug!("deduce_sig_from_projection: ret_param_ty {}", ret_param_ty.repr(tcx));
 
     let fn_sig = ty::FnSig {
         inputs: input_tys,
         output: ty::FnConverging(ret_param_ty),
         variadic: false
     };
-    debug!("fn_sig {}", fn_sig.repr(tcx));
+    debug!("deduce_sig_from_projection: fn_sig {}", fn_sig.repr(tcx));
 
-    return Some((fn_sig, kind));
+    Some(fn_sig)
 }
 
 fn self_type_matches_expected_vid<'a,'tcx>(
index f731507ba906dbeb7f0af6bfbc8bf6ea17ac875b..ae1dbbb1b00ad2ca0dc0d619344fc5aaea99e8e5 100644 (file)
@@ -258,70 +258,64 @@ fn coerce_unsized(&self,
 
         match (&a.sty, &b.sty) {
             (&ty::ty_rptr(_, ty::mt{ty: t_a, mutbl: mutbl_a}), &ty::ty_rptr(_, mt_b)) => {
-                self.unpack_actual_value(t_a, |a| {
-                    match self.unsize_ty(t_a, a, mt_b.ty) {
-                        Some((ty, kind)) => {
-                            if !can_coerce_mutbls(mutbl_a, mt_b.mutbl) {
-                                return Err(ty::terr_mutability);
-                            }
-
-                            let coercion = Coercion(self.trace.clone());
-                            let r_borrow = self.fcx.infcx().next_region_var(coercion);
-                            let ty = ty::mk_rptr(self.tcx(),
-                                                 self.tcx().mk_region(r_borrow),
-                                                 ty::mt{ty: ty, mutbl: mt_b.mutbl});
-                            try!(self.fcx.infcx().try(|_| self.subtype(ty, b)));
-                            debug!("Success, coerced with AutoDerefRef(1, \
-                                    AutoPtr(AutoUnsize({:?})))", kind);
-                            Ok(Some(AdjustDerefRef(AutoDerefRef {
-                                autoderefs: 1,
-                                autoref: Some(ty::AutoPtr(r_borrow, mt_b.mutbl,
-                                                          Some(box AutoUnsize(kind))))
-                            })))
+                match self.unsize_ty(t_a, mt_b.ty) {
+                    Some((ty, kind)) => {
+                        if !can_coerce_mutbls(mutbl_a, mt_b.mutbl) {
+                            return Err(ty::terr_mutability);
                         }
-                        _ => Err(ty::terr_mismatch)
+
+                        let coercion = Coercion(self.trace.clone());
+                        let r_borrow = self.fcx.infcx().next_region_var(coercion);
+                        let ty = ty::mk_rptr(self.tcx(),
+                                             self.tcx().mk_region(r_borrow),
+                                             ty::mt{ty: ty, mutbl: mt_b.mutbl});
+                        try!(self.fcx.infcx().try(|_| self.subtype(ty, b)));
+                        debug!("Success, coerced with AutoDerefRef(1, \
+                                AutoPtr(AutoUnsize({:?})))", kind);
+                        Ok(Some(AdjustDerefRef(AutoDerefRef {
+                            autoderefs: 1,
+                            autoref: Some(ty::AutoPtr(r_borrow, mt_b.mutbl,
+                                                      Some(box AutoUnsize(kind))))
+                        })))
                     }
-                })
+                    _ => Err(ty::terr_mismatch)
+                }
             }
             (&ty::ty_rptr(_, ty::mt{ty: t_a, mutbl: mutbl_a}), &ty::ty_ptr(mt_b)) => {
-                self.unpack_actual_value(t_a, |a| {
-                    match self.unsize_ty(t_a, a, mt_b.ty) {
-                        Some((ty, kind)) => {
-                            if !can_coerce_mutbls(mutbl_a, mt_b.mutbl) {
-                                return Err(ty::terr_mutability);
-                            }
-
-                            let ty = ty::mk_ptr(self.tcx(),
-                                                 ty::mt{ty: ty, mutbl: mt_b.mutbl});
-                            try!(self.fcx.infcx().try(|_| self.subtype(ty, b)));
-                            debug!("Success, coerced with AutoDerefRef(1, \
-                                    AutoPtr(AutoUnsize({:?})))", kind);
-                            Ok(Some(AdjustDerefRef(AutoDerefRef {
-                                autoderefs: 1,
-                                autoref: Some(ty::AutoUnsafe(mt_b.mutbl,
-                                                             Some(box AutoUnsize(kind))))
-                            })))
+                match self.unsize_ty(t_a, mt_b.ty) {
+                    Some((ty, kind)) => {
+                        if !can_coerce_mutbls(mutbl_a, mt_b.mutbl) {
+                            return Err(ty::terr_mutability);
                         }
-                        _ => Err(ty::terr_mismatch)
+
+                        let ty = ty::mk_ptr(self.tcx(),
+                                             ty::mt{ty: ty, mutbl: mt_b.mutbl});
+                        try!(self.fcx.infcx().try(|_| self.subtype(ty, b)));
+                        debug!("Success, coerced with AutoDerefRef(1, \
+                                AutoPtr(AutoUnsize({:?})))", kind);
+                        Ok(Some(AdjustDerefRef(AutoDerefRef {
+                            autoderefs: 1,
+                            autoref: Some(ty::AutoUnsafe(mt_b.mutbl,
+                                                         Some(box AutoUnsize(kind))))
+                        })))
                     }
-                })
+                    _ => Err(ty::terr_mismatch)
+                }
             }
             (&ty::ty_uniq(t_a), &ty::ty_uniq(t_b)) => {
-                self.unpack_actual_value(t_a, |a| {
-                    match self.unsize_ty(t_a, a, t_b) {
-                        Some((ty, kind)) => {
-                            let ty = ty::mk_uniq(self.tcx(), ty);
-                            try!(self.fcx.infcx().try(|_| self.subtype(ty, b)));
-                            debug!("Success, coerced with AutoDerefRef(1, \
-                                    AutoUnsizeUniq({:?}))", kind);
-                            Ok(Some(AdjustDerefRef(AutoDerefRef {
-                                autoderefs: 1,
-                                autoref: Some(ty::AutoUnsizeUniq(kind))
-                            })))
-                        }
-                        _ => Err(ty::terr_mismatch)
+                match self.unsize_ty(t_a, t_b) {
+                    Some((ty, kind)) => {
+                        let ty = ty::mk_uniq(self.tcx(), ty);
+                        try!(self.fcx.infcx().try(|_| self.subtype(ty, b)));
+                        debug!("Success, coerced with AutoDerefRef(1, \
+                                AutoUnsizeUniq({:?}))", kind);
+                        Ok(Some(AdjustDerefRef(AutoDerefRef {
+                            autoderefs: 1,
+                            autoref: Some(ty::AutoUnsizeUniq(kind))
+                        })))
                     }
-                })
+                    _ => Err(ty::terr_mismatch)
+                }
             }
             _ => Err(ty::terr_mismatch)
         }
@@ -332,113 +326,112 @@ fn coerce_unsized(&self,
     // E.g., `[T, ..n]` -> `([T], UnsizeLength(n))`
     fn unsize_ty(&self,
                  ty_a: Ty<'tcx>,
-                 a: Ty<'tcx>,
                  ty_b: Ty<'tcx>)
-                 -> Option<(Ty<'tcx>, ty::UnsizeKind<'tcx>)> {
-        debug!("unsize_ty(a={:?}, ty_b={})", a, ty_b.repr(self.tcx()));
-
+                 -> Option<(Ty<'tcx>, ty::UnsizeKind<'tcx>)>
+    {
         let tcx = self.tcx();
 
-        self.unpack_actual_value(ty_b, |b|
-            match (&a.sty, &b.sty) {
-                (&ty::ty_vec(t_a, Some(len)), &ty::ty_vec(_, None)) => {
-                    let ty = ty::mk_vec(tcx, t_a, None);
-                    Some((ty, ty::UnsizeLength(len)))
-                }
-                (&ty::ty_trait(ref data_a), &ty::ty_trait(ref data_b)) => {
-                    // Upcasts permit two things:
-                    //
-                    // 1. Dropping builtin bounds, e.g. `Foo+Send` to `Foo`
-                    // 2. Tightening the region bound, e.g. `Foo+'a` to `Foo+'b` if `'a : 'b`
-                    //
-                    // Note that neither of these changes requires any
-                    // change at runtime.  Eventually this will be
-                    // generalized.
-                    //
-                    // We always upcast when we can because of reason
-                    // #2 (region bounds).
-                    if data_a.bounds.builtin_bounds.is_superset(&data_b.bounds.builtin_bounds) {
-                        // construct a type `a1` which is a version of
-                        // `a` using the upcast bounds from `b`
-                        let bounds_a1 = ty::ExistentialBounds {
-                            // From type b
-                            region_bound: data_b.bounds.region_bound,
-                            builtin_bounds: data_b.bounds.builtin_bounds,
-
-                            // From type a
-                            projection_bounds: data_a.bounds.projection_bounds.clone(),
-                        };
-                        let ty_a1 = ty::mk_trait(tcx, data_a.principal.clone(), bounds_a1);
-
-                        // relate `a1` to `b`
-                        let result = self.fcx.infcx().try(|_| {
-                            // it's ok to upcast from Foo+'a to Foo+'b so long as 'a : 'b
-                            try!(self.outlives(data_a.bounds.region_bound,
-                                               data_b.bounds.region_bound));
-                            self.subtype(ty_a1, ty_b)
-                        });
-
-                        // if that was successful, we have a coercion
-                        match result {
-                            Ok(_) => Some((ty_b, ty::UnsizeUpcast(ty_b))),
-                            Err(_) => None,
-                        }
-                    } else {
-                        None
+        self.unpack_actual_value(ty_a, |a| {
+            self.unpack_actual_value(ty_b, |b| {
+                debug!("unsize_ty(a={}, b={})", a.repr(self.tcx()), b.repr(self.tcx()));
+                match (&a.sty, &b.sty) {
+                    (&ty::ty_vec(t_a, Some(len)), &ty::ty_vec(_, None)) => {
+                        let ty = ty::mk_vec(tcx, t_a, None);
+                        Some((ty, ty::UnsizeLength(len)))
                     }
-                }
-                (_, &ty::ty_trait(ref data)) => {
-                    Some((ty_b, ty::UnsizeVtable(ty::TyTrait { principal: data.principal.clone(),
-                                                               bounds: data.bounds.clone() },
-                                                 ty_a)))
-                }
-                (&ty::ty_struct(did_a, substs_a), &ty::ty_struct(did_b, substs_b))
-                  if did_a == did_b => {
-                    debug!("unsizing a struct");
-                    // Try unsizing each type param in turn to see if we end up with ty_b.
-                    let ty_substs_a = substs_a.types.get_slice(subst::TypeSpace);
-                    let ty_substs_b = substs_b.types.get_slice(subst::TypeSpace);
-                    assert!(ty_substs_a.len() == ty_substs_b.len());
-
-                    let mut result = None;
-                    let tps = ty_substs_a.iter().zip(ty_substs_b.iter()).enumerate();
-                    for (i, (tp_a, tp_b)) in tps {
-                        if self.fcx.infcx().try(|_| self.subtype(*tp_a, *tp_b)).is_ok() {
-                            continue;
+                    (&ty::ty_trait(ref data_a), &ty::ty_trait(ref data_b)) => {
+                        // Upcasts permit two things:
+                        //
+                        // 1. Dropping builtin bounds, e.g. `Foo+Send` to `Foo`
+                        // 2. Tightening the region bound, e.g. `Foo+'a` to `Foo+'b` if `'a : 'b`
+                        //
+                        // Note that neither of these changes requires any
+                        // change at runtime.  Eventually this will be
+                        // generalized.
+                        //
+                        // We always upcast when we can because of reason
+                        // #2 (region bounds).
+                        if data_a.bounds.builtin_bounds.is_superset(&data_b.bounds.builtin_bounds) {
+                            // construct a type `a1` which is a version of
+                            // `a` using the upcast bounds from `b`
+                            let bounds_a1 = ty::ExistentialBounds {
+                                // From type b
+                                region_bound: data_b.bounds.region_bound,
+                                builtin_bounds: data_b.bounds.builtin_bounds,
+
+                                // From type a
+                                projection_bounds: data_a.bounds.projection_bounds.clone(),
+                            };
+                            let ty_a1 = ty::mk_trait(tcx, data_a.principal.clone(), bounds_a1);
+
+                            // relate `a1` to `b`
+                            let result = self.fcx.infcx().try(|_| {
+                                // it's ok to upcast from Foo+'a to Foo+'b so long as 'a : 'b
+                                try!(self.outlives(data_a.bounds.region_bound,
+                                                   data_b.bounds.region_bound));
+                                self.subtype(ty_a1, ty_b)
+                            });
+
+                            // if that was successful, we have a coercion
+                            match result {
+                                Ok(_) => Some((ty_b, ty::UnsizeUpcast(ty_b))),
+                                Err(_) => None,
+                            }
+                        } else {
+                            None
                         }
-                        match
-                            self.unpack_actual_value(
-                                *tp_a,
-                                |tp| self.unsize_ty(*tp_a, tp, *tp_b))
-                        {
-                            Some((new_tp, k)) => {
-                                // Check that the whole types match.
-                                let mut new_substs = substs_a.clone();
-                                new_substs.types.get_mut_slice(subst::TypeSpace)[i] = new_tp;
-                                let ty = ty::mk_struct(tcx, did_a, tcx.mk_substs(new_substs));
-                                if self.fcx.infcx().try(|_| self.subtype(ty, ty_b)).is_err() {
-                                    debug!("Unsized type parameter '{}', but still \
-                                            could not match types {} and {}",
-                                           ppaux::ty_to_string(tcx, *tp_a),
-                                           ppaux::ty_to_string(tcx, ty),
-                                           ppaux::ty_to_string(tcx, ty_b));
-                                    // We can only unsize a single type parameter, so
-                                    // if we unsize one and it doesn't give us the
-                                    // type we want, then we won't succeed later.
+                    }
+                    (_, &ty::ty_trait(ref data)) => {
+                        Some((ty_b, ty::UnsizeVtable(ty::TyTrait {
+                                                         principal: data.principal.clone(),
+                                                         bounds: data.bounds.clone()
+                                                     },
+                                                     ty_a)))
+                    }
+                    (&ty::ty_struct(did_a, substs_a), &ty::ty_struct(did_b, substs_b))
+                      if did_a == did_b => {
+                        debug!("unsizing a struct");
+                        // Try unsizing each type param in turn to see if we end up with ty_b.
+                        let ty_substs_a = substs_a.types.get_slice(subst::TypeSpace);
+                        let ty_substs_b = substs_b.types.get_slice(subst::TypeSpace);
+                        assert!(ty_substs_a.len() == ty_substs_b.len());
+
+                        let mut result = None;
+                        let tps = ty_substs_a.iter().zip(ty_substs_b.iter()).enumerate();
+                        for (i, (tp_a, tp_b)) in tps {
+                            if self.fcx.infcx().try(|_| self.subtype(*tp_a, *tp_b)).is_ok() {
+                                continue;
+                            }
+                            match self.unsize_ty(*tp_a, *tp_b) {
+                                Some((new_tp, k)) => {
+                                    // Check that the whole types match.
+                                    let mut new_substs = substs_a.clone();
+                                    new_substs.types.get_mut_slice(subst::TypeSpace)[i] = new_tp;
+                                    let ty = ty::mk_struct(tcx, did_a, tcx.mk_substs(new_substs));
+                                    if self.fcx.infcx().try(|_| self.subtype(ty, ty_b)).is_err() {
+                                        debug!("Unsized type parameter '{}', but still \
+                                                could not match types {} and {}",
+                                               ppaux::ty_to_string(tcx, *tp_a),
+                                               ppaux::ty_to_string(tcx, ty),
+                                               ppaux::ty_to_string(tcx, ty_b));
+                                        // We can only unsize a single type parameter, so
+                                        // if we unsize one and it doesn't give us the
+                                        // type we want, then we won't succeed later.
+                                        break;
+                                    }
+
+                                    result = Some((ty, ty::UnsizeStruct(box k, i)));
                                     break;
                                 }
-
-                                result = Some((ty, ty::UnsizeStruct(box k, i)));
-                                break;
+                                None => {}
                             }
-                            None => {}
                         }
+                        result
                     }
-                    result
+                    _ => None
                 }
-                _ => None
-            }
-        )
+            })
+        })
     }
 
     fn coerce_from_fn_pointer(&self,
index 6f2d0cb3667418023cc69a0d954305d84bab85cb..cd6a1226e00c9d639d8c83d38891caaf13122e85 100644 (file)
@@ -53,9 +53,11 @@ pub fn eqtype<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, sp: Span,
     }
 }
 
-// Checks that the type `actual` can be coerced to `expected`.
-pub fn coerce<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, sp: Span,
-                        expected: Ty<'tcx>, expr: &ast::Expr) {
+// Checks that the type of `expr` can be coerced to `expected`.
+pub fn coerce<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
+                        sp: Span,
+                        expected: Ty<'tcx>,
+                        expr: &ast::Expr) {
     let expr_ty = fcx.expr_ty(expr);
     debug!("demand::coerce(expected = {}, expr_ty = {})",
            expected.repr(fcx.ccx.tcx),
index 9c48ac43ee468bb94c38cd3adb65b4766202981b..c48033cab897f612c1a371d365340655c634dcda 100644 (file)
 
 use middle::infer;
 use middle::region;
-use middle::subst;
+use middle::subst::{self, Subst};
 use middle::ty::{self, Ty};
 use util::ppaux::{Repr, UserString};
 
 use syntax::ast;
-use syntax::codemap::Span;
+use syntax::codemap::{self, Span};
+
+/// check_drop_impl confirms that the Drop implementation identfied by
+/// `drop_impl_did` is not any more specialized than the type it is
+/// attached to (Issue #8142).
+///
+/// This means:
+///
+/// 1. The self type must be nominal (this is already checked during
+///    coherence),
+///
+/// 2. The generic region/type parameters of the impl's self-type must
+///    all be parameters of the Drop impl itself (i.e. no
+///    specialization like `impl Drop for Foo<i32>`), and,
+///
+/// 3. Any bounds on the generic parameters must be reflected in the
+///    struct/enum definition for the nominal type itself (i.e.
+///    cannot do `struct S<T>; impl<T:Clone> Drop for S<T> { ... }`).
+///
+pub fn check_drop_impl(tcx: &ty::ctxt, drop_impl_did: ast::DefId) -> Result<(), ()> {
+    let ty::TypeScheme { generics: ref dtor_generics,
+                         ty: ref dtor_self_type } = ty::lookup_item_type(tcx, drop_impl_did);
+    let dtor_predicates = ty::lookup_predicates(tcx, drop_impl_did);
+    match dtor_self_type.sty {
+        ty::ty_enum(self_type_did, self_to_impl_substs) |
+        ty::ty_struct(self_type_did, self_to_impl_substs) |
+        ty::ty_closure(self_type_did, self_to_impl_substs) => {
+            try!(ensure_drop_params_and_item_params_correspond(tcx,
+                                                               drop_impl_did,
+                                                               dtor_generics,
+                                                               dtor_self_type,
+                                                               self_type_did));
+
+            ensure_drop_predicates_are_implied_by_item_defn(tcx,
+                                                            drop_impl_did,
+                                                            &dtor_predicates,
+                                                            self_type_did,
+                                                            self_to_impl_substs)
+        }
+        _ => {
+            // Destructors only work on nominal types.  This was
+            // already checked by coherence, so we can panic here.
+            let span = tcx.map.def_id_span(drop_impl_did, codemap::DUMMY_SP);
+            tcx.sess.span_bug(
+                span, &format!("should have been rejected by coherence check: {}",
+                               dtor_self_type.repr(tcx)));
+        }
+    }
+}
+
+fn ensure_drop_params_and_item_params_correspond<'tcx>(
+    tcx: &ty::ctxt<'tcx>,
+    drop_impl_did: ast::DefId,
+    drop_impl_generics: &ty::Generics<'tcx>,
+    drop_impl_ty: &ty::Ty<'tcx>,
+    self_type_did: ast::DefId) -> Result<(), ()>
+{
+    // New strategy based on review suggestion from nikomatsakis.
+    //
+    // (In the text and code below, "named" denotes "struct/enum", and
+    // "generic params" denotes "type and region params")
+    //
+    // 1. Create fresh skolemized type/region "constants" for each of
+    //    the named type's generic params.  Instantiate the named type
+    //    with the fresh constants, yielding `named_skolem`.
+    //
+    // 2. Create unification variables for each of the Drop impl's
+    //    generic params.  Instantiate the impl's Self's type with the
+    //    unification-vars, yielding `drop_unifier`.
+    //
+    // 3. Attempt to unify Self_unif with Type_skolem.  If unification
+    //    succeeds, continue (i.e. with the predicate checks).
+
+    let ty::TypeScheme { generics: ref named_type_generics,
+                         ty: named_type } =
+        ty::lookup_item_type(tcx, self_type_did);
+
+    let infcx = infer::new_infer_ctxt(tcx);
+    infcx.try(|snapshot| {
+        let (named_type_to_skolem, skol_map) =
+            infcx.construct_skolemized_subst(named_type_generics, snapshot);
+        let named_type_skolem = named_type.subst(tcx, &named_type_to_skolem);
+
+        let drop_impl_span = tcx.map.def_id_span(drop_impl_did, codemap::DUMMY_SP);
+        let drop_to_unifier =
+            infcx.fresh_substs_for_generics(drop_impl_span, drop_impl_generics);
+        let drop_unifier = drop_impl_ty.subst(tcx, &drop_to_unifier);
+
+        if let Ok(()) = infer::mk_eqty(&infcx, true, infer::TypeOrigin::Misc(drop_impl_span),
+                                       named_type_skolem, drop_unifier) {
+            // Even if we did manage to equate the types, the process
+            // may have just gathered unsolvable region constraints
+            // like `R == 'static` (represented as a pair of subregion
+            // constraints) for some skolemization constant R.
+            //
+            // However, the leak_check method allows us to confirm
+            // that no skolemized regions escaped (i.e. were related
+            // to other regions in the constraint graph).
+            if let Ok(()) = infcx.leak_check(&skol_map, snapshot) {
+                return Ok(())
+            }
+        }
+
+        span_err!(tcx.sess, drop_impl_span, E0366,
+                  "Implementations of Drop cannot be specialized");
+        let item_span = tcx.map.span(self_type_did.node);
+        tcx.sess.span_note(item_span,
+                           "Use same sequence of generic type and region \
+                            parameters that is on the struct/enum definition");
+        return Err(());
+    })
+}
+
+/// Confirms that every predicate imposed by dtor_predicates is
+/// implied by assuming the predicates attached to self_type_did.
+fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>(
+    tcx: &ty::ctxt<'tcx>,
+    drop_impl_did: ast::DefId,
+    dtor_predicates: &ty::GenericPredicates<'tcx>,
+    self_type_did: ast::DefId,
+    self_to_impl_substs: &subst::Substs<'tcx>) -> Result<(), ()> {
+
+    // Here is an example, analogous to that from
+    // `compare_impl_method`.
+    //
+    // Consider a struct type:
+    //
+    //     struct Type<'c, 'b:'c, 'a> {
+    //         x: &'a Contents            // (contents are irrelevant;
+    //         y: &'c Cell<&'b Contents>, //  only the bounds matter for our purposes.)
+    //     }
+    //
+    // and a Drop impl:
+    //
+    //     impl<'z, 'y:'z, 'x:'y> Drop for P<'z, 'y, 'x> {
+    //         fn drop(&mut self) { self.y.set(self.x); } // (only legal if 'x: 'y)
+    //     }
+    //
+    // We start out with self_to_impl_substs, that maps the generic
+    // parameters of Type to that of the Drop impl.
+    //
+    //     self_to_impl_substs = {'c => 'z, 'b => 'y, 'a => 'x}
+    //
+    // Applying this to the predicates (i.e. assumptions) provided by the item
+    // definition yields the instantiated assumptions:
+    //
+    //     ['y : 'z]
+    //
+    // We then check all of the predicates of the Drop impl:
+    //
+    //     ['y:'z, 'x:'y]
+    //
+    // and ensure each is in the list of instantiated
+    // assumptions. Here, `'y:'z` is present, but `'x:'y` is
+    // absent. So we report an error that the Drop impl injected a
+    // predicate that is not present on the struct definition.
+
+    assert_eq!(self_type_did.krate, ast::LOCAL_CRATE);
+
+    let drop_impl_span = tcx.map.def_id_span(drop_impl_did, codemap::DUMMY_SP);
+
+    // We can assume the predicates attached to struct/enum definition
+    // hold.
+    let generic_assumptions = ty::lookup_predicates(tcx, self_type_did);
+
+    let assumptions_in_impl_context = generic_assumptions.instantiate(tcx, &self_to_impl_substs);
+    assert!(assumptions_in_impl_context.predicates.is_empty_in(subst::SelfSpace));
+    assert!(assumptions_in_impl_context.predicates.is_empty_in(subst::FnSpace));
+    let assumptions_in_impl_context =
+        assumptions_in_impl_context.predicates.get_slice(subst::TypeSpace);
+
+    // An earlier version of this code attempted to do this checking
+    // via the traits::fulfill machinery. However, it ran into trouble
+    // since the fulfill machinery merely turns outlives-predicates
+    // 'a:'b and T:'b into region inference constraints. It is simpler
+    // just to look for all the predicates directly.
+
+    assert!(dtor_predicates.predicates.is_empty_in(subst::SelfSpace));
+    assert!(dtor_predicates.predicates.is_empty_in(subst::FnSpace));
+    let predicates = dtor_predicates.predicates.get_slice(subst::TypeSpace);
+    for predicate in predicates {
+        // (We do not need to worry about deep analysis of type
+        // expressions etc because the Drop impls are already forced
+        // to take on a structure that is roughly a alpha-renaming of
+        // the generic parameters of the item definition.)
+
+        // This path now just checks *all* predicates via the direct
+        // lookup, rather than using fulfill machinery.
+        //
+        // However, it may be more efficient in the future to batch
+        // the analysis together via the fulfill , rather than the
+        // repeated `contains` calls.
+
+        if !assumptions_in_impl_context.contains(&predicate) {
+            let item_span = tcx.map.span(self_type_did.node);
+            let req = predicate.user_string(tcx);
+            span_err!(tcx.sess, drop_impl_span, E0367,
+                      "The requirement `{}` is added only by the Drop impl.", req);
+            tcx.sess.span_note(item_span,
+                               "The same requirement must be part of \
+                                the struct/enum definition");
+        }
+    }
+
+    if tcx.sess.has_errors() {
+        return Err(());
+    }
+    Ok(())
+}
 
+/// check_safety_of_destructor_if_necessary confirms that the type
+/// expression `typ` conforms to the "Drop Check Rule" from the Sound
+/// Generic Drop (RFC 769).
+///
+/// ----
+///
+/// The Drop Check Rule is the following:
+///
+/// Let `v` be some value (either temporary or named) and 'a be some
+/// lifetime (scope). If the type of `v` owns data of type `D`, where
+///
+///   (1.) `D` has a lifetime- or type-parametric Drop implementation, and
+///   (2.) the structure of `D` can reach a reference of type `&'a _`, and
+///   (3.) either:
+///
+///     (A.) the Drop impl for `D` instantiates `D` at 'a directly,
+///          i.e. `D<'a>`, or,
+///
+///     (B.) the Drop impl for `D` has some type parameter with a
+///          trait bound `T` where `T` is a trait that has at least
+///          one method,
+///
+/// then 'a must strictly outlive the scope of v.
+///
+/// ----
+///
+/// This function is meant to by applied to the type for every
+/// expression in the program.
 pub fn check_safety_of_destructor_if_necessary<'a, 'tcx>(rcx: &mut Rcx<'a, 'tcx>,
                                                      typ: ty::Ty<'tcx>,
                                                      span: Span,
index bc581a6af4154c516b2279fb0079a5e02e412243..b95e0ce8cb3c59e512d65101884e5fbd1d9b1697 100644 (file)
@@ -725,7 +725,7 @@ fn assemble_closure_candidates(&mut self,
             };
 
             // this closure doesn't implement the right kind of `Fn` trait
-            if closure_kind != kind {
+            if !closure_kind.extends(kind) {
                 continue;
             }
 
index c3f4937d26b045d9e788bfee33102aaebc456f41..1e38a7d2d9f944222403095c82f24ddf733b20d1 100644 (file)
@@ -184,6 +184,8 @@ pub struct Inherited<'a, 'tcx: 'a> {
     // def-id of the closure, so that once we decide, we can easily go
     // back and process them.
     deferred_call_resolutions: RefCell<DefIdMap<Vec<DeferredCallResolutionHandler<'tcx>>>>,
+
+    deferred_cast_checks: RefCell<Vec<CastCheck<'tcx>>>,
 }
 
 trait DeferredCallResolution<'tcx> {
@@ -192,6 +194,15 @@ trait DeferredCallResolution<'tcx> {
 
 type DeferredCallResolutionHandler<'tcx> = Box<DeferredCallResolution<'tcx>+'tcx>;
 
+/// Reifies a cast check to be checked once we have full type information for
+/// a function context.
+struct CastCheck<'tcx> {
+    expr: ast::Expr,
+    expr_ty: Ty<'tcx>,
+    cast_ty: Ty<'tcx>,
+    span: Span,
+}
+
 /// When type-checking an expression, we propagate downward
 /// whatever type hint we are able in the form of an `Expectation`.
 #[derive(Copy)]
@@ -399,6 +410,7 @@ fn new(tcx: &'a ty::ctxt<'tcx>,
             fn_sig_map: RefCell::new(NodeMap()),
             fulfillment_cx: RefCell::new(traits::FulfillmentContext::new()),
             deferred_call_resolutions: RefCell::new(DefIdMap()),
+            deferred_cast_checks: RefCell::new(Vec::new()),
         }
     }
 
@@ -478,6 +490,20 @@ pub fn check_item_types(ccx: &CrateCtxt) {
     visit::walk_crate(&mut visit, krate);
 
     ccx.tcx.sess.abort_if_errors();
+
+    for drop_method_did in ccx.tcx.destructors.borrow().iter() {
+        if drop_method_did.krate == ast::LOCAL_CRATE {
+            let drop_impl_did = ccx.tcx.map.get_parent_did(drop_method_did.node);
+            match dropck::check_drop_impl(ccx.tcx, drop_impl_did) {
+                Ok(()) => {}
+                Err(()) => {
+                    assert!(ccx.tcx.sess.has_errors());
+                }
+            }
+        }
+    }
+
+    ccx.tcx.sess.abort_if_errors();
 }
 
 fn check_bare_fn<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
@@ -508,6 +534,7 @@ fn check_bare_fn<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
             vtable::select_all_fcx_obligations_and_apply_defaults(&fcx);
             upvar::closure_analyze_fn(&fcx, fn_id, decl, body);
             vtable::select_all_fcx_obligations_or_error(&fcx);
+            fcx.check_casts();
             regionck::regionck_fn(&fcx, fn_id, fn_span, decl, body);
             writeback::resolve_type_vars_in_fn(&fcx, decl, body);
         }
@@ -1053,11 +1080,7 @@ fn report_cast_to_unsized_type<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
 }
 
 
-fn check_cast_inner<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
-                              span: Span,
-                              t_1: Ty<'tcx>,
-                              t_e: Ty<'tcx>,
-                              e: &ast::Expr) {
+fn check_cast<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, cast: &CastCheck<'tcx>) {
     fn cast_through_integer_err<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                                           span: Span,
                                           t_1: Ty<'tcx>,
@@ -1070,6 +1093,33 @@ fn cast_through_integer_err<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
         }, t_e, None);
     }
 
+    let span = cast.span;
+    let e = &cast.expr;
+    let t_e = structurally_resolved_type(fcx, span, cast.expr_ty);
+    let t_1 = structurally_resolved_type(fcx, span, cast.cast_ty);
+
+    // Check for trivial casts.
+    if !ty::type_has_ty_infer(t_1) {
+        if let Ok(()) = coercion::mk_assignty(fcx, e, t_e, t_1) {
+            if ty::type_is_numeric(t_1) && ty::type_is_numeric(t_e) {
+                fcx.tcx().sess.add_lint(lint::builtin::TRIVIAL_NUMERIC_CASTS,
+                                        e.id,
+                                        span,
+                                        format!("trivial numeric cast: `{}` as `{}`",
+                                                fcx.infcx().ty_to_string(t_e),
+                                                fcx.infcx().ty_to_string(t_1)));
+            } else {
+                fcx.tcx().sess.add_lint(lint::builtin::TRIVIAL_CASTS,
+                                        e.id,
+                                        span,
+                                        format!("trivial cast: `{}` as `{}`",
+                                                fcx.infcx().ty_to_string(t_e),
+                                                fcx.infcx().ty_to_string(t_1)));
+            }
+            return;
+        }
+    }
+
     let t_e_is_bare_fn_item = ty::type_is_bare_fn_item(t_e);
     let t_e_is_scalar = ty::type_is_scalar(t_e);
     let t_e_is_integral = ty::type_is_integral(t_e);
@@ -1085,18 +1135,17 @@ fn cast_through_integer_err<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
     let t_1_is_trivial = t_1_is_scalar && !t_1_is_char && !t_1_is_bare_fn;
 
     if t_e_is_bare_fn_item && t_1_is_bare_fn {
-        demand::coerce(fcx, e.span, t_1, &*e);
+        demand::coerce(fcx, e.span, t_1, &e);
     } else if t_1_is_char {
         let t_e = fcx.infcx().shallow_resolve(t_e);
         if t_e.sty != ty::ty_uint(ast::TyU8) {
             fcx.type_error_message(span, |actual| {
-                format!("only `u8` can be cast as \
-                         `char`, not `{}`", actual)
+                format!("only `u8` can be cast as `char`, not `{}`", actual)
             }, t_e, None);
         }
     } else if t_1.sty == ty::ty_bool {
         span_err!(fcx.tcx().sess, span, E0054,
-            "cannot cast as `bool`, compare with zero instead");
+                  "cannot cast as `bool`, compare with zero instead");
     } else if t_1_is_float && (t_e_is_scalar || t_e_is_c_enum) && !(
         t_e_is_integral || t_e_is_float || t_e.sty == ty::ty_bool) {
         // Casts to float must go through an integer or boolean
@@ -1145,7 +1194,7 @@ fn types_compatible<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, sp: Span,
                 /* this case is allowed */
             }
             _ => {
-                demand::coerce(fcx, e.span, t_1, &*e);
+                demand::coerce(fcx, e.span, t_1, &e);
             }
         }
     } else if !(t_e_is_scalar && t_1_is_trivial) {
@@ -1162,49 +1211,6 @@ fn types_compatible<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, sp: Span,
     }
 }
 
-fn check_cast<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
-                       cast_expr: &ast::Expr,
-                       e: &'tcx ast::Expr,
-                       t: &ast::Ty) {
-    let id = cast_expr.id;
-    let span = cast_expr.span;
-
-    // Find the type of `e`. Supply hints based on the type we are casting to,
-    // if appropriate.
-    let t_1 = fcx.to_ty(t);
-    let t_1 = structurally_resolved_type(fcx, span, t_1);
-
-    check_expr_with_expectation(fcx, e, ExpectCastableToType(t_1));
-
-    let t_e = fcx.expr_ty(e);
-
-    debug!("t_1={}", fcx.infcx().ty_to_string(t_1));
-    debug!("t_e={}", fcx.infcx().ty_to_string(t_e));
-
-    if ty::type_is_error(t_e) {
-        fcx.write_error(id);
-        return
-    }
-
-    if !fcx.type_is_known_to_be_sized(t_1, cast_expr.span) {
-        report_cast_to_unsized_type(fcx, span, t.span, e.span, t_1, t_e, id);
-        return
-    }
-
-    if ty::type_is_trait(t_1) {
-        // This will be looked up later on.
-        vtable::check_object_cast(fcx, cast_expr, e, t_1);
-        fcx.write_ty(id, t_1);
-        return
-    }
-
-    let t_1 = structurally_resolved_type(fcx, span, t_1);
-    let t_e = structurally_resolved_type(fcx, span, t_e);
-
-    check_cast_inner(fcx, span, t_1, t_e, e);
-    fcx.write_ty(id, t_1);
-}
-
 impl<'a, 'tcx> AstConv<'tcx> for FnCtxt<'a, 'tcx> {
     fn tcx(&self) -> &ty::ctxt<'tcx> { self.ccx.tcx }
 
@@ -1372,7 +1378,8 @@ fn remove_deferred_call_resolutions(&self,
     }
 
     pub fn tag(&self) -> String {
-        format!("{:?}", self as *const FnCtxt)
+        let self_ptr: *const FnCtxt = self;
+        format!("{:?}", self_ptr)
     }
 
     pub fn local_ty(&self, span: Span, nid: ast::NodeId) -> Ty<'tcx> {
@@ -1416,14 +1423,6 @@ pub fn write_ty(&self, node_id: ast::NodeId, ty: Ty<'tcx>) {
         self.inh.node_types.borrow_mut().insert(node_id, ty);
     }
 
-    pub fn write_object_cast(&self,
-                             key: ast::NodeId,
-                             trait_ref: ty::PolyTraitRef<'tcx>) {
-        debug!("write_object_cast key={} trait_ref={}",
-               key, trait_ref.repr(self.tcx()));
-        self.inh.object_cast_map.borrow_mut().insert(key, trait_ref);
-    }
-
     pub fn write_substs(&self, node_id: ast::NodeId, substs: ty::ItemSubsts<'tcx>) {
         if !substs.substs.is_noop() {
             debug!("write_substs({}, {}) in fcx {}",
@@ -1923,6 +1922,15 @@ pub fn lookup_tup_field_ty(&self,
         o_field.map(|f| ty::lookup_field_type(self.tcx(), class_id, f.id, substs))
                .map(|t| self.normalize_associated_types_in(span, &t))
     }
+
+    fn check_casts(&self) {
+        let mut deferred_cast_checks = self.inh.deferred_cast_checks.borrow_mut();
+        for check in deferred_cast_checks.iter() {
+            check_cast(self, check);
+        }
+
+        deferred_cast_checks.clear();
+    }
 }
 
 impl<'a, 'tcx> RegionScope for FnCtxt<'a, 'tcx> {
@@ -3828,7 +3836,33 @@ fn check_struct_fields_on_error<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
         if let ast::TyFixedLengthVec(_, ref count_expr) = t.node {
             check_expr_with_hint(fcx, &**count_expr, tcx.types.uint);
         }
-        check_cast(fcx, expr, &**e, &**t);
+
+        // Find the type of `e`. Supply hints based on the type we are casting to,
+        // if appropriate.
+        let t_1 = fcx.to_ty(t);
+        let t_1 = structurally_resolved_type(fcx, expr.span, t_1);
+        check_expr_with_expectation(fcx, e, ExpectCastableToType(t_1));
+        let t_e = fcx.expr_ty(e);
+
+        // Eagerly check for some obvious errors.
+        if ty::type_is_error(t_e) {
+            fcx.write_error(id);
+        } else if !fcx.type_is_known_to_be_sized(t_1, expr.span) {
+            report_cast_to_unsized_type(fcx, expr.span, t.span, e.span, t_1, t_e, id);
+        } else {
+            // Write a type for the whole expression, assuming everything is going
+            // to work out Ok.
+            fcx.write_ty(id, t_1);
+
+            // Defer other checks until we're done type checking.
+            let mut deferred_cast_checks = fcx.inh.deferred_cast_checks.borrow_mut();
+            deferred_cast_checks.push(CastCheck {
+                expr: (**e).clone(),
+                expr_ty: t_e,
+                cast_ty: t_1,
+                span: expr.span,
+            });
+        }
       }
       ast::ExprVec(ref args) => {
         let uty = expected.to_option(fcx).and_then(|uty| {
@@ -4461,6 +4495,7 @@ fn check_const_with_ty<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
     check_expr_with_hint(fcx, e, declty);
     demand::coerce(fcx, e.span, declty, e);
     vtable::select_all_fcx_obligations_or_error(fcx);
+    fcx.check_casts();
     regionck::regionck_expr(fcx, e);
     writeback::resolve_type_vars_in_expr(fcx, e);
 }
@@ -4560,6 +4595,8 @@ fn disr_in_range(ccx: &CrateCtxt,
                      ty: attr::IntType,
                      disr: ty::Disr) -> bool {
         fn uint_in_range(ccx: &CrateCtxt, ty: ast::UintTy, disr: ty::Disr) -> bool {
+            #![allow(trivial_numeric_casts)]
+
             match ty {
                 ast::TyU8 => disr as u8 as Disr == disr,
                 ast::TyU16 => disr as u16 as Disr == disr,
@@ -4588,6 +4625,7 @@ fn do_check<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                           id: ast::NodeId,
                           hint: attr::ReprAttr)
                           -> Vec<Rc<ty::VariantInfo<'tcx>>> {
+        #![allow(trivial_numeric_casts)]
         use std::num::Int;
 
         let rty = ty::node_id_to_type(ccx.tcx, id);
index 963be9aa2e2d2b0cb77e2320f19796e5ebdb2c1e..2858dc9b569fe1adaa22ffb7cde199e4e375404a 100644 (file)
@@ -9,7 +9,6 @@
 // except according to those terms.
 
 use check::{FnCtxt};
-use check::demand;
 use middle::traits::{self, ObjectSafetyViolation, MethodViolationCode};
 use middle::traits::{Obligation, ObligationCause};
 use middle::traits::report_fulfillment_errors;
 use util::nodemap::FnvHashSet;
 use util::ppaux::{Repr, UserString};
 
-pub fn check_object_cast<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
-                                   cast_expr: &ast::Expr,
-                                   source_expr: &ast::Expr,
-                                   target_object_ty: Ty<'tcx>)
-{
-    let tcx = fcx.tcx();
-    debug!("check_object_cast(cast_expr={}, target_object_ty={})",
-           cast_expr.repr(tcx),
-           target_object_ty.repr(tcx));
-
-    // Look up vtables for the type we're casting to,
-    // passing in the source and target type.  The source
-    // must be a pointer type suitable to the object sigil,
-    // e.g.: `&x as &Trait` or `box x as Box<Trait>`
-
-    // First, construct a fresh type that we can feed into `<expr>`
-    // within `<expr> as <type>` to inform type inference (e.g. to
-    // tell it that we are expecting a `Box<_>` or an `&_`).
-    let fresh_ty = fcx.infcx().next_ty_var();
-    let (object_trait_ty, source_expected_ty) = match target_object_ty.sty {
-        ty::ty_uniq(object_trait_ty) => {
-            (object_trait_ty, ty::mk_uniq(fcx.tcx(), fresh_ty))
-        }
-        ty::ty_rptr(target_region, ty::mt { ty: object_trait_ty,
-                                            mutbl: target_mutbl }) => {
-            (object_trait_ty,
-             ty::mk_rptr(fcx.tcx(),
-                         target_region, ty::mt { ty: fresh_ty,
-                                                 mutbl: target_mutbl }))
-        }
-        _ => {
-            fcx.tcx().sess.span_bug(source_expr.span, "expected object type");
-        }
-    };
-
-    let source_ty = fcx.expr_ty(source_expr);
-    debug!("check_object_cast pre unify source_ty={}", source_ty.repr(tcx));
-
-    // This ensures that the source_ty <: source_expected_ty, which
-    // will ensure e.g. that &'a T <: &'b T when doing `&'a T as &'b Trait`
-    //
-    // FIXME (pnkfelix): do we need to use suptype_with_fn in order to
-    // override the error message emitted when the types do not work
-    // out in the manner desired?
-    demand::suptype(fcx, source_expr.span, source_expected_ty, source_ty);
-
-    debug!("check_object_cast postunify source_ty={}", source_ty.repr(tcx));
-
-    let object_trait = object_trait(&object_trait_ty);
-
-    // Ensure that if Ptr<T> is cast to Ptr<Trait>, then T : Trait.
-    push_cast_obligation(fcx, cast_expr, object_trait, fresh_ty);
-    check_object_safety(tcx, object_trait, source_expr.span);
-
-    fn object_trait<'a, 'tcx>(t: &'a Ty<'tcx>) -> &'a ty::TyTrait<'tcx> {
-        match t.sty {
-            ty::ty_trait(ref ty_trait) => &**ty_trait,
-            _ => panic!("expected ty_trait")
-        }
-    }
-
-    fn push_cast_obligation<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
-                                      cast_expr: &ast::Expr,
-                                      object_trait: &ty::TyTrait<'tcx>,
-                                      referent_ty: Ty<'tcx>) {
-        let object_trait_ref =
-            register_object_cast_obligations(fcx,
-                                             cast_expr.span,
-                                             object_trait,
-                                             referent_ty);
-
-        // Finally record the object_trait_ref for use during trans
-        // (it would prob be better not to do this, but it's just kind
-        // of a pain to have to reconstruct it).
-        fcx.write_object_cast(cast_expr.id, object_trait_ref);
-    }
-}
 
 // Check that a trait is 'object-safe'. This should be checked whenever a trait object
 // is created (by casting or coercion, etc.). A trait is object-safe if all its
index 5efc26825eab19ef63b9c939aa5ee9c2ad588980..5816fe58bc9b1b25948ae56670bb2032fb94470e 100644 (file)
@@ -784,14 +784,15 @@ fn convert_item(ccx: &CrateCtxt, it: &ast::Item) {
                                    &enum_definition.variants);
         },
         ast::ItemDefaultImpl(_, ref ast_trait_ref) => {
-            let trait_ref = astconv::instantiate_trait_ref(&ccx.icx(&()),
-                                                           &ExplicitRscope,
-                                                           ast_trait_ref,
-                                                           Some(it.id),
-                                                           None,
-                                                           None);
+            let trait_ref =
+                astconv::instantiate_mono_trait_ref(&ccx.icx(&()),
+                                                    &ExplicitRscope,
+                                                    ast_trait_ref,
+                                                    None);
 
             ty::record_trait_has_default_impl(tcx, trait_ref.def_id);
+
+            tcx.impl_trait_refs.borrow_mut().insert(it.id, trait_ref);
         }
         ast::ItemImpl(_, _,
                       ref generics,
@@ -890,13 +891,14 @@ fn convert_item(ccx: &CrateCtxt, it: &ast::Item) {
                 }
             }
 
-            if let Some(ref trait_ref) = *opt_trait_ref {
-                astconv::instantiate_trait_ref(&ccx.icx(&ty_predicates),
-                                               &ExplicitRscope,
-                                               trait_ref,
-                                               Some(it.id),
-                                               Some(selfty),
-                                               None);
+            if let Some(ref ast_trait_ref) = *opt_trait_ref {
+                let trait_ref =
+                    astconv::instantiate_mono_trait_ref(&ccx.icx(&ty_predicates),
+                                                        &ExplicitRscope,
+                                                        ast_trait_ref,
+                                                        Some(selfty));
+
+                tcx.impl_trait_refs.borrow_mut().insert(it.id, trait_ref);
             }
 
             enforce_impl_ty_params_are_constrained(tcx,
index 396d060de9e9017d40282758553a4f84ca6a0f9e..95e06879fb2235a066c2aa83104fe7ec9ca643b0 100644 (file)
     E0319, // trait impls for defaulted traits allowed just for structs/enums
     E0320, // recursive overflow during dropck
     E0321, // extended coherence rules for defaulted traits violated
-    E0322  // cannot implement Sized explicitly
+    E0322, // cannot implement Sized explicitly
+    E0366, // dropck forbid specialization to concrete type or region
+    E0367  // dropck forbid specialization to predicate not in struct/enum
 }
 
 __build_diagnostic_array! { DIAGNOSTICS }
index cdd8457687ac60d1b6cf9866303cb34083453d44..cfa84de5ca7c9f37577877f1bc6f38ea347300ca 100644 (file)
@@ -308,8 +308,8 @@ pub fn render(w: &mut fmt::Formatter, s: &str, print_toc: bool) -> fmt::Result {
         };
         (*((*renderer).opaque as *mut hoedown_html_renderer_state)).opaque
                 = &mut opaque as *mut _ as *mut libc::c_void;
-        (*renderer).blockcode = Some(block as blockcodefn);
-        (*renderer).header = Some(header as headerfn);
+        (*renderer).blockcode = Some(block);
+        (*renderer).header = Some(header);
 
         let document = hoedown_document_new(renderer, HOEDOWN_EXTENSIONS, 16);
         hoedown_document_render(document, ob, s.as_ptr(),
@@ -380,8 +380,8 @@ pub fn find_testable_code(doc: &str, tests: &mut ::test::Collector) {
     unsafe {
         let ob = hoedown_buffer_new(DEF_OUNIT);
         let renderer = hoedown_html_renderer_new(0, 0);
-        (*renderer).blockcode = Some(block as blockcodefn);
-        (*renderer).header = Some(header as headerfn);
+        (*renderer).blockcode = Some(block);
+        (*renderer).header = Some(header);
         (*((*renderer).opaque as *mut hoedown_html_renderer_state)).opaque
                 = tests as *mut _ as *mut libc::c_void;
 
@@ -501,10 +501,10 @@ pub fn plain_summary_line(md: &str) -> String {
     unsafe {
         let ob = hoedown_buffer_new(DEF_OUNIT);
         let mut plain_renderer: hoedown_renderer = ::std::mem::zeroed();
-        let renderer = &mut plain_renderer as *mut hoedown_renderer;
+        let renderer: *mut hoedown_renderer = &mut plain_renderer;
         (*renderer).opaque = ob as *mut libc::c_void;
-        (*renderer).link = Some(link as linkfn);
-        (*renderer).normal_text = Some(normal_text as normaltextfn);
+        (*renderer).link = Some(link);
+        (*renderer).normal_text = Some(normal_text);
 
         let document = hoedown_document_new(renderer, HOEDOWN_EXTENSIONS, 16);
         hoedown_document_render(document, ob, md.as_ptr(),
index 11e10cc2aa7a16cf004fdb8933d7e47283df978d..3f813b30ecc1d748aad6cf52d173a93adc861de7 100644 (file)
@@ -237,7 +237,7 @@ pub fn visit_item(&mut self, item: &ast::Item,
             ast::ItemExternCrate(ref p) => {
                 let path = match *p {
                     None => None,
-                    Some((ref x, _)) => Some(x.to_string()),
+                    Some(x) => Some(x.to_string()),
                 };
                 om.extern_crates.push(ExternCrate {
                     name: name,
index abbfc82319f5b30e24035442aedaaa532c0e80a4..0d6ed91d5298139b1cdf5800d3e6ac20c08aaab4 100644 (file)
@@ -2429,7 +2429,10 @@ pub trait ToJson {
 macro_rules! to_json_impl_i64 {
     ($($t:ty), +) => (
         $(impl ToJson for $t {
-            fn to_json(&self) -> Json { Json::I64(*self as i64) }
+            fn to_json(&self) -> Json {
+                #![allow(trivial_numeric_casts)]
+                Json::I64(*self as i64)
+            }
         })+
     )
 }
@@ -2439,7 +2442,10 @@ fn to_json(&self) -> Json { Json::I64(*self as i64) }
 macro_rules! to_json_impl_u64 {
     ($($t:ty), +) => (
         $(impl ToJson for $t {
-            fn to_json(&self) -> Json { Json::U64(*self as u64) }
+            fn to_json(&self) -> Json {
+                #![allow(trivial_numeric_casts)]
+                Json::U64(*self as u64)
+            }
         })+
     )
 }
index 2546aace2659c562f1329f4b696334bc5e2c6f1b..c1253706832df6e87667aeafbc1901b17962e5aa 100644 (file)
@@ -128,6 +128,17 @@ impl File {
     ///
     /// This function will return an error if `path` does not already exist.
     /// Other errors may also be returned according to `OpenOptions::open`.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::fs::File;
+    ///
+    /// # fn foo() -> std::io::Result<()> {
+    /// let mut f = try!(File::open("foo.txt"));
+    /// # Ok(())
+    /// # }
+    /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn open<P: AsRef<Path>>(path: P) -> io::Result<File> {
         OpenOptions::new().read(true).open(path)
@@ -139,6 +150,17 @@ pub fn open<P: AsRef<Path>>(path: P) -> io::Result<File> {
     /// and will truncate it if it does.
     ///
     /// See the `OpenOptions::open` function for more details.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::fs::File;
+    ///
+    /// # fn foo() -> std::io::Result<()> {
+    /// let mut f = try!(File::create("foo.txt"));
+    /// # Ok(())
+    /// # }
+    /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn create<P: AsRef<Path>>(path: P) -> io::Result<File> {
         OpenOptions::new().write(true).create(true).truncate(true).open(path)
@@ -156,6 +178,21 @@ pub fn path(&self) -> Option<&Path> {
     ///
     /// This function will attempt to ensure that all in-core data reaches the
     /// filesystem before returning.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::fs::File;
+    /// use std::io::prelude::*;
+    ///
+    /// # fn foo() -> std::io::Result<()> {
+    /// let mut f = try!(File::create("foo.txt"));
+    /// try!(f.write_all(b"Hello, world!"));
+    ///
+    /// try!(f.sync_all());
+    /// # Ok(())
+    /// # }
+    /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn sync_all(&self) -> io::Result<()> {
         self.inner.fsync()
@@ -170,6 +207,21 @@ pub fn sync_all(&self) -> io::Result<()> {
     ///
     /// Note that some platforms may simply implement this in terms of
     /// `sync_all`.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::fs::File;
+    /// use std::io::prelude::*;
+    ///
+    /// # fn foo() -> std::io::Result<()> {
+    /// let mut f = try!(File::create("foo.txt"));
+    /// try!(f.write_all(b"Hello, world!"));
+    ///
+    /// try!(f.sync_data());
+    /// # Ok(())
+    /// # }
+    /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn sync_data(&self) -> io::Result<()> {
         self.inner.datasync()
@@ -182,12 +234,36 @@ pub fn sync_data(&self) -> io::Result<()> {
     /// 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.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::fs::File;
+    ///
+    /// # fn foo() -> std::io::Result<()> {
+    /// let mut f = try!(File::open("foo.txt"));
+    /// try!(f.set_len(0));
+    /// # Ok(())
+    /// # }
+    /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn set_len(&self, size: u64) -> io::Result<()> {
         self.inner.truncate(size)
     }
 
     /// Queries metadata about the underlying file.
+    ///
+    /// # Examples
+    ///
+    /// ```no_run
+    /// use std::fs::File;
+    ///
+    /// # fn foo() -> std::io::Result<()> {
+    /// let mut f = try!(File::open("foo.txt"));
+    /// let metadata = try!(f.metadata());
+    /// # Ok(())
+    /// # }
+    /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn metadata(&self) -> io::Result<Metadata> {
         self.inner.file_attr().map(Metadata)
index 4def601f1c0e7657f6a3e7da1c057ec3c53da99a..2a1294f23b20e9a33384abf6d83f14b5ab548a12 100644 (file)
@@ -120,7 +120,7 @@ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
 ///
 /// The buffer will be written out when the writer is dropped.
 #[stable(feature = "rust1", since = "1.0.0")]
-pub struct BufWriter<W> {
+pub struct BufWriter<W: Write> {
     inner: Option<W>,
     buf: Vec<u8>,
 }
@@ -220,7 +220,7 @@ fn flush(&mut self) -> io::Result<()> {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<W> fmt::Debug for BufWriter<W> where W: fmt::Debug {
+impl<W: Write> fmt::Debug for BufWriter<W> where W: fmt::Debug {
     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
         write!(fmt, "BufWriter {{ writer: {:?}, buffer: {}/{} }}",
                self.inner.as_ref().unwrap(), self.buf.len(), self.buf.capacity())
@@ -276,7 +276,7 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
 ///
 /// The buffer will be written out when the writer is dropped.
 #[stable(feature = "rust1", since = "1.0.0")]
-pub struct LineWriter<W> {
+pub struct LineWriter<W: Write> {
     inner: BufWriter<W>,
 }
 
@@ -335,7 +335,7 @@ fn flush(&mut self) -> io::Result<()> { self.inner.flush() }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<W> fmt::Debug for LineWriter<W> where W: fmt::Debug {
+impl<W: Write> fmt::Debug for LineWriter<W> where W: fmt::Debug {
     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
         write!(fmt, "LineWriter {{ writer: {:?}, buffer: {}/{} }}",
                self.inner.inner, self.inner.buf.len(),
@@ -343,16 +343,16 @@ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
     }
 }
 
-struct InternalBufWriter<W>(BufWriter<W>);
+struct InternalBufWriter<W: Write>(BufWriter<W>);
 
-impl<W> InternalBufWriter<W> {
+impl<W: Read + Write> InternalBufWriter<W> {
     fn get_mut(&mut self) -> &mut BufWriter<W> {
         let InternalBufWriter(ref mut w) = *self;
         return w;
     }
 }
 
-impl<W: Read> Read for InternalBufWriter<W> {
+impl<W: Read + Write> Read for InternalBufWriter<W> {
     fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
         self.get_mut().inner.as_mut().unwrap().read(buf)
     }
@@ -367,7 +367,7 @@ fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
 ///
 /// The output buffer will be written out when this stream is dropped.
 #[stable(feature = "rust1", since = "1.0.0")]
-pub struct BufStream<S> {
+pub struct BufStream<S: Write> {
     inner: BufReader<InternalBufWriter<S>>
 }
 
@@ -448,7 +448,7 @@ fn flush(&mut self) -> io::Result<()> {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<S> fmt::Debug for BufStream<S> where S: fmt::Debug {
+impl<S: Write> fmt::Debug for BufStream<S> where S: fmt::Debug {
     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
         let reader = &self.inner;
         let writer = &self.inner.inner.0;
index 16298240acfbed7e9968ade38f5f875c7f70e9a2..ce03e26866b7dd1376393290fc2f29ef078ce09a 100644 (file)
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, R: Read + ?Sized> Read for &'a mut R {
+    #[inline]
     fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
         (**self).read(buf)
     }
+
+    #[inline]
     fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
         (**self).read_to_end(buf)
     }
+
+    #[inline]
     fn read_to_string(&mut self, buf: &mut String) -> io::Result<usize> {
         (**self).read_to_string(buf)
     }
 }
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, W: Write + ?Sized> Write for &'a mut W {
+    #[inline]
     fn write(&mut self, buf: &[u8]) -> io::Result<usize> { (**self).write(buf) }
+
+    #[inline]
     fn flush(&mut self) -> io::Result<()> { (**self).flush() }
+
+    #[inline]
     fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
         (**self).write_all(buf)
     }
+
+    #[inline]
     fn write_fmt(&mut self, fmt: fmt::Arguments) -> io::Result<()> {
         (**self).write_fmt(fmt)
     }
 }
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, S: Seek + ?Sized> Seek for &'a mut S {
+    #[inline]
     fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> { (**self).seek(pos) }
 }
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<'a, B: BufRead + ?Sized> BufRead for &'a mut B {
+    #[inline]
     fn fill_buf(&mut self) -> io::Result<&[u8]> { (**self).fill_buf() }
+
+    #[inline]
     fn consume(&mut self, amt: usize) { (**self).consume(amt) }
+
+    #[inline]
     fn read_until(&mut self, byte: u8, buf: &mut Vec<u8>) -> io::Result<usize> {
         (**self).read_until(byte, buf)
     }
+
+    #[inline]
     fn read_line(&mut self, buf: &mut String) -> io::Result<usize> {
         (**self).read_line(buf)
     }
@@ -63,38 +83,58 @@ fn read_line(&mut self, buf: &mut String) -> io::Result<usize> {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<R: Read + ?Sized> Read for Box<R> {
+    #[inline]
     fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
         (**self).read(buf)
     }
+
+    #[inline]
     fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
         (**self).read_to_end(buf)
     }
+
+    #[inline]
     fn read_to_string(&mut self, buf: &mut String) -> io::Result<usize> {
         (**self).read_to_string(buf)
     }
 }
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<W: Write + ?Sized> Write for Box<W> {
+    #[inline]
     fn write(&mut self, buf: &[u8]) -> io::Result<usize> { (**self).write(buf) }
+
+    #[inline]
     fn flush(&mut self) -> io::Result<()> { (**self).flush() }
+
+    #[inline]
     fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
         (**self).write_all(buf)
     }
+
+    #[inline]
     fn write_fmt(&mut self, fmt: fmt::Arguments) -> io::Result<()> {
         (**self).write_fmt(fmt)
     }
 }
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<S: Seek + ?Sized> Seek for Box<S> {
+    #[inline]
     fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> { (**self).seek(pos) }
 }
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<B: BufRead + ?Sized> BufRead for Box<B> {
+    #[inline]
     fn fill_buf(&mut self) -> io::Result<&[u8]> { (**self).fill_buf() }
+
+    #[inline]
     fn consume(&mut self, amt: usize) { (**self).consume(amt) }
+
+    #[inline]
     fn read_until(&mut self, byte: u8, buf: &mut Vec<u8>) -> io::Result<usize> {
         (**self).read_until(byte, buf)
     }
+
+    #[inline]
     fn read_line(&mut self, buf: &mut String) -> io::Result<usize> {
         (**self).read_line(buf)
     }
@@ -105,6 +145,7 @@ fn read_line(&mut self, buf: &mut String) -> io::Result<usize> {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<'a> Read for &'a [u8] {
+    #[inline]
     fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
         let amt = cmp::min(buf.len(), self.len());
         let (a, b) = self.split_at(amt);
@@ -116,12 +157,16 @@ fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<'a> BufRead for &'a [u8] {
+    #[inline]
     fn fill_buf(&mut self) -> io::Result<&[u8]> { Ok(*self) }
+
+    #[inline]
     fn consume(&mut self, amt: usize) { *self = &self[amt..]; }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<'a> Write for &'a mut [u8] {
+    #[inline]
     fn write(&mut self, data: &[u8]) -> io::Result<usize> {
         let amt = cmp::min(data.len(), self.len());
         let (a, b) = mem::replace(self, &mut []).split_at_mut(amt);
@@ -130,6 +175,7 @@ fn write(&mut self, data: &[u8]) -> io::Result<usize> {
         Ok(amt)
     }
 
+    #[inline]
     fn write_all(&mut self, data: &[u8]) -> io::Result<()> {
         if try!(self.write(data)) == data.len() {
             Ok(())
@@ -138,20 +184,87 @@ fn write_all(&mut self, data: &[u8]) -> io::Result<()> {
         }
     }
 
+    #[inline]
     fn flush(&mut self) -> io::Result<()> { Ok(()) }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
 impl Write for Vec<u8> {
+    #[inline]
     fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
         self.push_all(buf);
         Ok(buf.len())
     }
 
+    #[inline]
     fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
         self.push_all(buf);
         Ok(())
     }
 
+    #[inline]
     fn flush(&mut self) -> io::Result<()> { Ok(()) }
 }
+
+#[cfg(test)]
+mod tests {
+    use io::prelude::*;
+    use vec::Vec;
+    use test;
+
+    #[bench]
+    fn bench_read_slice(b: &mut test::Bencher) {
+        let buf = [5; 1024];
+        let mut dst = [0; 128];
+
+        b.iter(|| {
+            let mut rd = &buf[..];
+            for _ in (0 .. 8) {
+                let _ = rd.read(&mut dst);
+                test::black_box(&dst);
+            }
+        })
+    }
+
+    #[bench]
+    fn bench_write_slice(b: &mut test::Bencher) {
+        let mut buf = [0; 1024];
+        let src = [5; 128];
+
+        b.iter(|| {
+            let mut wr = &mut buf[..];
+            for _ in (0 .. 8) {
+                let _ = wr.write_all(&src);
+                test::black_box(&wr);
+            }
+        })
+    }
+
+    #[bench]
+    fn bench_read_vec(b: &mut test::Bencher) {
+        let buf = vec![5; 1024];
+        let mut dst = [0; 128];
+
+        b.iter(|| {
+            let mut rd = &buf[..];
+            for _ in (0 .. 8) {
+                let _ = rd.read(&mut dst);
+                test::black_box(&dst);
+            }
+        })
+    }
+
+    #[bench]
+    fn bench_write_vec(b: &mut test::Bencher) {
+        let mut buf = Vec::with_capacity(1024);
+        let src = [5; 128];
+
+        b.iter(|| {
+            let mut wr = &mut buf[..];
+            for _ in (0 .. 8) {
+                let _ = wr.write_all(&src);
+                test::black_box(&wr);
+            }
+        })
+    }
+}
index c9b105f72a53943ab0d8e9ff6dbab3071b1ab993..df280dab37d467221afff885df9cdd78004e01ba 100644 (file)
@@ -35,25 +35,33 @@ impl<T: Send + Sync + 'static> Lazy<T> {
     pub fn get(&'static self) -> Option<Arc<T>> {
         let _g = self.lock.lock();
         unsafe {
-            let mut ptr = *self.ptr.get();
+            let ptr = *self.ptr.get();
             if ptr.is_null() {
-                ptr = boxed::into_raw(self.init());
-                *self.ptr.get() = ptr;
+                Some(self.init())
             } else if ptr as usize == 1 {
-                return None
+                None
+            } else {
+                Some((*ptr).clone())
             }
-            Some((*ptr).clone())
         }
     }
 
-    fn init(&'static self) -> Box<Arc<T>> {
-        rt::at_exit(move || unsafe {
+    unsafe fn init(&'static self) -> Arc<T> {
+        // If we successfully register an at exit handler, then we cache the
+        // `Arc` allocation in our own internal box (it will get deallocated by
+        // the at exit handler). Otherwise we just return the freshly allocated
+        // `Arc`.
+        let registered = rt::at_exit(move || {
             let g = self.lock.lock();
             let ptr = *self.ptr.get();
             *self.ptr.get() = 1 as *mut _;
             drop(g);
             drop(Box::from_raw(ptr))
         });
-        Box::new((self.init)())
+        let ret = (self.init)();
+        if registered.is_ok() {
+            *self.ptr.get() = boxed::into_raw(Box::new(ret.clone()));
+        }
+        return ret
     }
 }
index 39c718c96b38a014583a3f557b8c8cdfff9f3fb6..0ed6d07bf79185331c6fb8a383cd99a44b96541b 100644 (file)
 use unicode::str as core_str;
 use error as std_error;
 use fmt;
-use iter::Iterator;
+use iter::{self, Iterator, IteratorExt, Extend};
 use marker::Sized;
 use ops::{Drop, FnOnce};
 use option::Option::{self, Some, None};
 use result::Result::{Ok, Err};
 use result;
-use slice;
 use string::String;
 use str;
 use vec::Vec;
 const DEFAULT_BUF_SIZE: usize = 64 * 1024;
 
 // Acquires a slice of the vector `v` from its length to its capacity
-// (uninitialized data), reads into it, and then updates the length.
+// (after initializing the data), reads into it, and then updates the length.
 //
 // This function is leveraged to efficiently read some bytes into a destination
 // vector without extra copying and taking advantage of the space that's already
 // in `v`.
-//
-// The buffer we're passing down, however, is pointing at uninitialized data
-// (the end of a `Vec`), and many operations will be *much* faster if we don't
-// have to zero it out. In order to prevent LLVM from generating an `undef`
-// value when reads happen from this uninitialized memory, we force LLVM to
-// think it's initialized by sending it through a black box. This should prevent
-// actual undefined behavior after optimizations.
 fn with_end_to_cap<F>(v: &mut Vec<u8>, f: F) -> Result<usize>
     where F: FnOnce(&mut [u8]) -> Result<usize>
 {
-    unsafe {
-        let n = try!(f({
-            let base = v.as_mut_ptr().offset(v.len() as isize);
-            black_box(slice::from_raw_parts_mut(base,
-                                                v.capacity() - v.len()))
-        }));
-
-        // If the closure (typically a `read` implementation) reported that it
-        // read a larger number of bytes than the vector actually has, we need
-        // to be sure to clamp the vector to at most its capacity.
-        let new_len = cmp::min(v.capacity(), v.len() + n);
-        v.set_len(new_len);
-        return Ok(n);
-    }
-
-    // Semi-hack used to prevent LLVM from retaining any assumptions about
-    // `dummy` over this function call
-    unsafe fn black_box<T>(mut dummy: T) -> T {
-        asm!("" :: "r"(&mut dummy) : "memory");
-        dummy
+    let len = v.len();
+    let new_area = v.capacity() - len;
+    v.extend(iter::repeat(0).take(new_area));
+    match f(&mut v[len..]) {
+        Ok(n) => {
+            v.truncate(len + n);
+            Ok(n)
+        }
+        Err(e) => {
+            v.truncate(len);
+            Err(e)
+        }
     }
 }
 
@@ -647,14 +631,14 @@ fn lines(self) -> Lines<Self> where Self: Sized {
 
 /// A `Write` adaptor which will write data to multiple locations.
 ///
-/// For more information, see `WriteExt::broadcast`.
-#[unstable(feature = "io", reason = "awaiting stability of WriteExt::broadcast")]
+/// For more information, see `Write::broadcast`.
+#[unstable(feature = "io", reason = "awaiting stability of Write::broadcast")]
 pub struct Broadcast<T, U> {
     first: T,
     second: U,
 }
 
-#[unstable(feature = "io", reason = "awaiting stability of WriteExt::broadcast")]
+#[unstable(feature = "io", reason = "awaiting stability of Write::broadcast")]
 impl<T: Write, U: Write> Write for Broadcast<T, U> {
     fn write(&mut self, data: &[u8]) -> Result<usize> {
         let n = try!(self.first.write(data));
@@ -670,7 +654,7 @@ fn flush(&mut self) -> Result<()> {
 
 /// Adaptor to chain together two instances of `Read`.
 ///
-/// For more information, see `ReadExt::chain`.
+/// For more information, see `Read::chain`.
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct Chain<T, U> {
     first: T,
@@ -693,7 +677,7 @@ fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
 
 /// Reader adaptor which limits the bytes read from an underlying reader.
 ///
-/// For more information, see `ReadExt::take`.
+/// For more information, see `Read::take`.
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct Take<T> {
     inner: T,
@@ -746,14 +730,14 @@ fn consume(&mut self, amt: usize) {
 
 /// An adaptor which will emit all read data to a specified writer as well.
 ///
-/// For more information see `ReadExt::tee`
-#[unstable(feature = "io", reason = "awaiting stability of ReadExt::tee")]
+/// For more information see `Read::tee`
+#[unstable(feature = "io", reason = "awaiting stability of Read::tee")]
 pub struct Tee<R, W> {
     reader: R,
     writer: W,
 }
 
-#[unstable(feature = "io", reason = "awaiting stability of ReadExt::tee")]
+#[unstable(feature = "io", reason = "awaiting stability of Read::tee")]
 impl<R: Read, W: Write> Read for Tee<R, W> {
     fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
         let n = try!(self.reader.read(buf));
@@ -765,7 +749,7 @@ fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
 
 /// A bridge from implementations of `Read` to an `Iterator` of `u8`.
 ///
-/// See `ReadExt::bytes` for more information.
+/// See `Read::bytes` for more information.
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct Bytes<R> {
     inner: R,
@@ -787,8 +771,8 @@ fn next(&mut self) -> Option<Result<u8>> {
 
 /// A bridge from implementations of `Read` to an `Iterator` of `char`.
 ///
-/// See `ReadExt::chars` for more information.
-#[unstable(feature = "io", reason = "awaiting stability of ReadExt::chars")]
+/// See `Read::chars` for more information.
+#[unstable(feature = "io", reason = "awaiting stability of Read::chars")]
 pub struct Chars<R> {
     inner: R,
 }
@@ -796,7 +780,7 @@ pub struct Chars<R> {
 /// An enumeration of possible errors that can be generated from the `Chars`
 /// adapter.
 #[derive(PartialEq, Clone, Debug)]
-#[unstable(feature = "io", reason = "awaiting stability of ReadExt::chars")]
+#[unstable(feature = "io", reason = "awaiting stability of Read::chars")]
 pub enum CharsError {
     /// Variant representing that the underlying stream was read successfully
     /// but it did not contain valid utf8 data.
@@ -806,7 +790,7 @@ pub enum CharsError {
     Other(Error),
 }
 
-#[unstable(feature = "io", reason = "awaiting stability of ReadExt::chars")]
+#[unstable(feature = "io", reason = "awaiting stability of Read::chars")]
 impl<R: Read> Iterator for Chars<R> {
     type Item = result::Result<char, CharsError>;
 
@@ -838,7 +822,7 @@ fn next(&mut self) -> Option<result::Result<char, CharsError>> {
     }
 }
 
-#[unstable(feature = "io", reason = "awaiting stability of ReadExt::chars")]
+#[unstable(feature = "io", reason = "awaiting stability of Read::chars")]
 impl std_error::Error for CharsError {
     fn description(&self) -> &str {
         match *self {
@@ -854,7 +838,7 @@ fn cause(&self) -> Option<&std_error::Error> {
     }
 }
 
-#[unstable(feature = "io", reason = "awaiting stability of ReadExt::chars")]
+#[unstable(feature = "io", reason = "awaiting stability of Read::chars")]
 impl fmt::Display for CharsError {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         match *self {
index a2ceacbe1f897ba62c6d4ba46b3daf2ecd4884d9..333ae8f26a0d7fa028429ebedeca4218b96cb6a6 100644 (file)
@@ -18,7 +18,7 @@
 //! ```
 //!
 //! This module contains reexports of many core I/O traits such as `Read`,
-//! `Write`, `ReadExt`, and `WriteExt`. Structures and functions are not
+//! `Write` and `BufRead`. Structures and functions are not
 //! contained in this module.
 
 #![stable(feature = "rust1", since = "1.0.0")]
index 90eca6168f266cd8c4c82ba8de0f76a5f58c914b..cca6bb747d43c5f2e66f0f43dcd2883fbc18345b 100644 (file)
 #![feature(no_std)]
 #![no_std]
 
+#![allow(trivial_casts)]
+#![allow(trivial_numeric_casts)]
 #![deny(missing_docs)]
 
 #[cfg(test)] extern crate test;
index e8187dc2c402720453e8083195224bb6f4010d25..dafca974bec0eacf96d39c766cb466fa68024996 100644 (file)
@@ -15,7 +15,7 @@
 use io;
 use libc::{self, socklen_t, sa_family_t};
 use mem;
-use net::{lookup_host, ntoh, hton, Ipv4Addr, Ipv6Addr};
+use net::{lookup_host, ntoh, hton, IpAddr, Ipv4Addr, Ipv6Addr};
 use option;
 use sys_common::{FromInner, AsInner, IntoInner};
 use vec;
@@ -47,6 +47,15 @@ pub struct SocketAddrV4 { inner: libc::sockaddr_in }
 pub struct SocketAddrV6 { inner: libc::sockaddr_in6 }
 
 impl SocketAddr {
+    /// Gets the IP address associated with this socket address.
+    #[unstable(feature = "ip_addr", reason = "recent addition")]
+    pub fn ip(&self) -> IpAddr {
+        match *self {
+            SocketAddr::V4(ref a) => IpAddr::V4(*a.ip()),
+            SocketAddr::V6(ref a) => IpAddr::V6(*a.ip()),
+        }
+    }
+
     /// Gets the port number associated with this socket address
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn port(&self) -> u16 {
@@ -333,6 +342,18 @@ fn to_socket_addrs(&self) -> io::Result<option::IntoIter<SocketAddr>> {
     }
 }
 
+#[stable(feature = "rust1", since = "1.0.0")]
+impl ToSocketAddrs for (IpAddr, u16) {
+    type Iter = option::IntoIter<SocketAddr>;
+    fn to_socket_addrs(&self) -> io::Result<option::IntoIter<SocketAddr>> {
+        let (ip, port) = *self;
+        match ip {
+            IpAddr::V4(ref a) => (*a, port).to_socket_addrs(),
+            IpAddr::V6(ref a) => (*a, port).to_socket_addrs(),
+        }
+    }
+}
+
 #[stable(feature = "rust1", since = "1.0.0")]
 impl ToSocketAddrs for (Ipv4Addr, u16) {
     type Iter = option::IntoIter<SocketAddr>;
index d737ad17ff8ecf7220cdb3d894b735ef3246b151..c8b1928747705765c1cc1923b8a2ea6a60b0d6d1 100644 (file)
 use sys_common::{AsInner, FromInner};
 use net::{hton, ntoh};
 
+/// An IP address, either a IPv4 or IPv6 address.
+#[unstable(feature = "ip_addr", reason = "recent addition")]
+#[derive(Copy, Clone, Eq, PartialEq, Debug, Hash, PartialOrd, Ord)]
+pub enum IpAddr {
+    /// Representation of an IPv4 address.
+    V4(Ipv4Addr),
+    /// Representation of an IPv6 address.
+    V6(Ipv6Addr),
+}
+
 /// Representation of an IPv4 address.
 #[derive(Copy)]
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -139,6 +149,16 @@ pub fn to_ipv6_mapped(&self) -> Ipv6Addr {
 
 }
 
+#[stable(feature = "rust1", since = "1.0.0")]
+impl fmt::Display for IpAddr {
+    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+        match *self {
+            IpAddr::V4(ref a) => a.fmt(fmt),
+            IpAddr::V6(ref a) => a.fmt(fmt),
+        }
+    }
+}
+
 #[stable(feature = "rust1", since = "1.0.0")]
 impl fmt::Display for Ipv4Addr {
     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
index 48b3247f2127abd143646e0243add745cb9129bd..7f51b1cba3fe796a8ef66bd4aab1ac06f792525f 100644 (file)
@@ -21,7 +21,7 @@
 use num::Int;
 use sys_common::net2 as net_imp;
 
-pub use self::ip::{Ipv4Addr, Ipv6Addr, Ipv6MulticastScope};
+pub use self::ip::{IpAddr, Ipv4Addr, Ipv6Addr, Ipv6MulticastScope};
 pub use self::addr::{SocketAddr, SocketAddrV4, SocketAddrV6, ToSocketAddrs};
 pub use self::tcp::{TcpStream, TcpListener};
 pub use self::udp::UdpSocket;
@@ -74,10 +74,14 @@ fn each_addr<A: ToSocketAddrs, F, T>(addr: A, mut f: F) -> io::Result<T>
 }
 
 /// An iterator over `SocketAddr` values returned from a host lookup operation.
-#[stable(feature = "rust1", since = "1.0.0")]
+#[unstable(feature = "lookup_host", reason = "unsure about the returned \
+                                              iterator and returning socket \
+                                              addresses")]
 pub struct LookupHost(net_imp::LookupHost);
 
-#[stable(feature = "rust1", since = "1.0.0")]
+#[unstable(feature = "lookup_host", reason = "unsure about the returned \
+                                              iterator and returning socket \
+                                              addresses")]
 impl Iterator for LookupHost {
     type Item = io::Result<SocketAddr>;
     fn next(&mut self) -> Option<io::Result<SocketAddr>> { self.0.next() }
@@ -91,7 +95,7 @@ fn next(&mut self) -> Option<io::Result<SocketAddr>> { self.0.next() }
 /// # Examples
 ///
 /// ```no_run
-/// # #![feature(net)]
+/// # #![feature(lookup_host)]
 /// use std::net;
 ///
 /// # fn foo() -> std::io::Result<()> {
@@ -101,7 +105,9 @@ fn next(&mut self) -> Option<io::Result<SocketAddr>> { self.0.next() }
 /// # Ok(())
 /// # }
 /// ```
-#[stable(feature = "rust1", since = "1.0.0")]
+#[unstable(feature = "lookup_host", reason = "unsure about the returned \
+                                              iterator and returning socket \
+                                              addresses")]
 pub fn lookup_host(host: &str) -> io::Result<LookupHost> {
     net_imp::lookup_host(host).map(LookupHost)
 }
index e593bbe8e489b526e67eb1e94da25dd25c9d378d..811511149628e640a2254600c7f301e3bc4e54c1 100644 (file)
@@ -14,7 +14,7 @@
 use prelude::v1::*;
 
 use io::{self, Error, ErrorKind};
-use net::{ToSocketAddrs, SocketAddr};
+use net::{ToSocketAddrs, SocketAddr, IpAddr};
 use sys_common::net2 as net_imp;
 use sys_common::AsInner;
 
@@ -116,12 +116,12 @@ pub fn set_multicast_loop(&self, on: bool) -> io::Result<()> {
     }
 
     /// Joins a multicast IP address (becomes a member of it)
-    pub fn join_multicast(&self, multi: &SocketAddr) -> io::Result<()> {
+    pub fn join_multicast(&self, multi: &IpAddr) -> io::Result<()> {
         self.0.join_multicast(multi)
     }
 
     /// Leaves a multicast IP address (drops membership from it)
-    pub fn leave_multicast(&self, multi: &SocketAddr) -> io::Result<()> {
+    pub fn leave_multicast(&self, multi: &IpAddr) -> io::Result<()> {
         self.0.leave_multicast(multi)
     }
 
index cb67d709a143ab6d289a8750ef65768cb28e302f..9a9d421dfe1f02700d12a855837c7d1370e19699 100644 (file)
@@ -148,14 +148,14 @@ fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> {
 /// writer.write_str("hello, world").unwrap();
 /// writer.flush().unwrap();
 /// ```
-pub struct BufferedWriter<W> {
+pub struct BufferedWriter<W: Writer> {
     inner: Option<W>,
     buf: Vec<u8>,
     pos: uint
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<W> fmt::Debug for BufferedWriter<W> where W: fmt::Debug {
+impl<W: Writer> fmt::Debug for BufferedWriter<W> where W: fmt::Debug {
     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
         write!(fmt, "BufferedWriter {{ writer: {:?}, buffer: {}/{} }}",
                self.inner.as_ref().unwrap(), self.pos, self.buf.len())
@@ -250,12 +250,12 @@ fn drop(&mut self) {
 /// `'\n'`) is detected.
 ///
 /// This writer will be flushed when it is dropped.
-pub struct LineBufferedWriter<W> {
+pub struct LineBufferedWriter<W: Writer> {
     inner: BufferedWriter<W>,
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<W> fmt::Debug for LineBufferedWriter<W> where W: fmt::Debug {
+impl<W: Writer> fmt::Debug for LineBufferedWriter<W> where W: fmt::Debug {
     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
         write!(fmt, "LineBufferedWriter {{ writer: {:?}, buffer: {}/{} }}",
                self.inner.inner, self.inner.pos, self.inner.buf.len())
@@ -299,16 +299,16 @@ fn write_all(&mut self, buf: &[u8]) -> IoResult<()> {
     fn flush(&mut self) -> IoResult<()> { self.inner.flush() }
 }
 
-struct InternalBufferedWriter<W>(BufferedWriter<W>);
+struct InternalBufferedWriter<W: Writer>(BufferedWriter<W>);
 
-impl<W> InternalBufferedWriter<W> {
+impl<W: Writer> InternalBufferedWriter<W> {
     fn get_mut<'a>(&'a mut self) -> &'a mut BufferedWriter<W> {
         let InternalBufferedWriter(ref mut w) = *self;
         return w;
     }
 }
 
-impl<W: Reader> Reader for InternalBufferedWriter<W> {
+impl<W: Reader + Writer> Reader for InternalBufferedWriter<W> {
     fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> {
         self.get_mut().inner.as_mut().unwrap().read(buf)
     }
@@ -343,12 +343,12 @@ fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> {
 ///     Err(e) => println!("error reading: {}", e)
 /// }
 /// ```
-pub struct BufferedStream<S> {
+pub struct BufferedStream<S: Writer> {
     inner: BufferedReader<InternalBufferedWriter<S>>
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<S> fmt::Debug for BufferedStream<S> where S: fmt::Debug {
+impl<S: Writer> fmt::Debug for BufferedStream<S> where S: fmt::Debug {
     fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
         let reader = &self.inner;
         let writer = &self.inner.inner.0;
index ef811f832b394133a47b69f3591624db41ed8160..90d270849114186f57d96fed9290e4c50b124feb 100644 (file)
@@ -240,7 +240,7 @@ pub fn stdin() -> StdinReader {
             STDIN = boxed::into_raw(box stdin);
 
             // Make sure to free it at exit
-            rt::at_exit(|| {
+            let _ = rt::at_exit(|| {
                 Box::from_raw(STDIN);
                 STDIN = ptr::null_mut();
             });
@@ -337,10 +337,10 @@ pub fn set_stderr(_stderr: Box<Writer + Send>) -> Option<Box<Writer + Send>> {
 //      })
 //  })
 fn with_task_stdout<F>(f: F) where F: FnOnce(&mut Writer) -> IoResult<()> {
-    let mut my_stdout = LOCAL_STDOUT.with(|slot| {
+    let mut my_stdout: Box<Writer + Send> = LOCAL_STDOUT.with(|slot| {
         slot.borrow_mut().take()
     }).unwrap_or_else(|| {
-        box stdout() as Box<Writer + Send>
+        box stdout()
     });
     let result = f(&mut *my_stdout);
     let mut var = Some(my_stdout);
index 553412c83712f6dcf4b44c275f62f628ef0109cc..6a36ecefcf4466ef1bf033f7d651f2e46e8b6e59 100644 (file)
@@ -748,6 +748,7 @@ pub fn pwd_cmd() -> Command {
         cmd
     }
 
+    #[cfg(not(target_arch = "aarch64"))]
     #[test]
     fn test_keep_current_working_dir() {
         use os;
index 9fa12b1ef30239472e35a3dc2b948ebc4950b782..9079c0aaffb7d3669e6bd57ecce4dde8d7b8c6c2 100644 (file)
 //!
 //! Documentation can be found on the `rt::at_exit` function.
 
+// FIXME: switch this to use atexit. Currently this
+// segfaults (the queue's memory is mysteriously gone), so
+// instead the cleanup is tied to the `std::rt` entry point.
+
 use boxed;
 use boxed::Box;
 use vec::Vec;
 static LOCK: Mutex = MUTEX_INIT;
 static mut QUEUE: *mut Queue = 0 as *mut Queue;
 
-unsafe fn init() {
+// The maximum number of times the cleanup routines will be run. While running
+// the at_exit closures new ones may be registered, and this count is the number
+// of times the new closures will be allowed to register successfully. After
+// this number of iterations all new registrations will return `false`.
+const ITERS: usize = 10;
+
+unsafe fn init() -> bool {
     if QUEUE.is_null() {
         let state: Box<Queue> = box Vec::new();
         QUEUE = boxed::into_raw(state);
-    } else {
+    } else if QUEUE as usize == 1 {
         // can't re-init after a cleanup
-        rtassert!(QUEUE as uint != 1);
+        return false
     }
 
-    // FIXME: switch this to use atexit as below. Currently this
-    // segfaults (the queue's memory is mysteriously gone), so
-    // instead the cleanup is tied to the `std::rt` entry point.
-    //
-    // ::libc::atexit(cleanup);
+    return true
 }
 
 pub fn cleanup() {
-    unsafe {
-        LOCK.lock();
-        let queue = QUEUE;
-        QUEUE = 1 as *mut _;
-        LOCK.unlock();
+    for i in 0..ITERS {
+        unsafe {
+            LOCK.lock();
+            let queue = QUEUE;
+            QUEUE = if i == ITERS - 1 {1} else {0} as *mut _;
+            LOCK.unlock();
 
-        // make sure we're not recursively cleaning up
-        rtassert!(queue as uint != 1);
+            // make sure we're not recursively cleaning up
+            rtassert!(queue as usize != 1);
 
-        // If we never called init, not need to cleanup!
-        if queue as uint != 0 {
-            let queue: Box<Queue> = Box::from_raw(queue);
-            for to_run in *queue {
-                to_run.invoke(());
+            // If we never called init, not need to cleanup!
+            if queue as usize != 0 {
+                let queue: Box<Queue> = Box::from_raw(queue);
+                for to_run in *queue {
+                    to_run.invoke(());
+                }
             }
         }
     }
 }
 
-pub fn push(f: Thunk<'static>) {
+pub fn push(f: Thunk<'static>) -> bool {
+    let mut ret = true;
     unsafe {
         LOCK.lock();
-        init();
-        (*QUEUE).push(f);
+        if init() {
+            (*QUEUE).push(f);
+        } else {
+            ret = false;
+        }
         LOCK.unlock();
     }
+    return ret
 }
index e52e68dad23faec8358bd4c7f63b501eb1e39e49..497076cc6ac34795e763897cdee911c6f9fba400 100644 (file)
 //! time being.
 
 #![unstable(feature = "std_misc")]
-
-// FIXME: this should not be here.
 #![allow(missing_docs)]
 
-#![allow(dead_code)]
-
-use marker::Send;
-use ops::FnOnce;
+use prelude::v1::*;
 use sys;
 use thunk::Thunk;
 use usize;
@@ -73,7 +68,7 @@ fn lang_start(main: *const u8, argc: int, argv: *const *const u8) -> int {
     use thread::Thread;
 
     let something_around_the_top_of_the_stack = 1;
-    let addr = &something_around_the_top_of_the_stack as *const int;
+    let addr = &something_around_the_top_of_the_stack as *const _ as *const int;
     let my_stack_top = addr as uint;
 
     // FIXME #11359 we just assume that this thread has a stack of a
@@ -149,13 +144,16 @@ fn lang_start(main: *const u8, argc: int, argv: *const *const u8) -> int {
 
 /// Enqueues a procedure to run when the main thread exits.
 ///
-/// It is forbidden for procedures to register more `at_exit` handlers when they
-/// are running, and doing so will lead to a process abort.
+/// Currently these closures are only run once the main *Rust* thread exits.
+/// Once the `at_exit` handlers begin running, more may be enqueued, but not
+/// infinitely so. Eventually a handler registration will be forced to fail.
 ///
-/// Note that other threads may still be running when `at_exit` routines start
-/// running.
-pub fn at_exit<F: FnOnce() + Send + 'static>(f: F) {
-    at_exit_imp::push(Thunk::new(f));
+/// Returns `Ok` if the handler was successfully registered, meaning that the
+/// closure will be run once the main thread exits. Returns `Err` to indicate
+/// that the closure could not be registered, meaning that it is not scheduled
+/// to be rune.
+pub fn at_exit<F: FnOnce() + Send + 'static>(f: F) -> Result<(), ()> {
+    if at_exit_imp::push(Thunk::new(f)) {Ok(())} else {Err(())}
 }
 
 /// One-time runtime cleanup.
index 7adfd9154acf86bae7f5d19812de347d3b848bf1..eb421fe55a4d093ad80337808a5b61333232bd11 100644 (file)
 /// The receiving-half of Rust's channel type. This half can only be owned by
 /// one task
 #[stable(feature = "rust1", since = "1.0.0")]
-pub struct Receiver<T> {
+pub struct Receiver<T:Send> {
     inner: UnsafeCell<Flavor<T>>,
 }
 
@@ -354,14 +354,14 @@ unsafe impl<T: Send> Send for Receiver<T> { }
 /// whenever `next` is called, waiting for a new message, and `None` will be
 /// returned when the corresponding channel has hung up.
 #[stable(feature = "rust1", since = "1.0.0")]
-pub struct Iter<'a, T:'a> {
+pub struct Iter<'a, T:Send+'a> {
     rx: &'a Receiver<T>
 }
 
 /// The sending-half of Rust's asynchronous channel type. This half can only be
 /// owned by one task, but it can be cloned to send to other tasks.
 #[stable(feature = "rust1", since = "1.0.0")]
-pub struct Sender<T> {
+pub struct Sender<T:Send> {
     inner: UnsafeCell<Flavor<T>>,
 }
 
@@ -372,7 +372,7 @@ unsafe impl<T: Send> Send for Sender<T> { }
 /// The sending-half of Rust's synchronous channel type. This half can only be
 /// owned by one task, but it can be cloned to send to other tasks.
 #[stable(feature = "rust1", since = "1.0.0")]
-pub struct SyncSender<T> {
+pub struct SyncSender<T: Send> {
     inner: Arc<UnsafeCell<sync::Packet<T>>>,
 }
 
@@ -433,7 +433,7 @@ pub enum TrySendError<T> {
     Disconnected(T),
 }
 
-enum Flavor<T> {
+enum Flavor<T:Send> {
     Oneshot(Arc<UnsafeCell<oneshot::Packet<T>>>),
     Stream(Arc<UnsafeCell<stream::Packet<T>>>),
     Shared(Arc<UnsafeCell<shared::Packet<T>>>),
@@ -441,7 +441,7 @@ enum Flavor<T> {
 }
 
 #[doc(hidden)]
-trait UnsafeFlavor<T> {
+trait UnsafeFlavor<T:Send> {
     fn inner_unsafe<'a>(&'a self) -> &'a UnsafeCell<Flavor<T>>;
     unsafe fn inner_mut<'a>(&'a self) -> &'a mut Flavor<T> {
         &mut *self.inner_unsafe().get()
@@ -450,12 +450,12 @@ unsafe fn inner<'a>(&'a self) -> &'a Flavor<T> {
         &*self.inner_unsafe().get()
     }
 }
-impl<T> UnsafeFlavor<T> for Sender<T> {
+impl<T:Send> UnsafeFlavor<T> for Sender<T> {
     fn inner_unsafe<'a>(&'a self) -> &'a UnsafeCell<Flavor<T>> {
         &self.inner
     }
 }
-impl<T> UnsafeFlavor<T> for Receiver<T> {
+impl<T:Send> UnsafeFlavor<T> for Receiver<T> {
     fn inner_unsafe<'a>(&'a self) -> &'a UnsafeCell<Flavor<T>> {
         &self.inner
     }
index 14ed253d8e27ef8f056d7c1e62a4dd5edeb7be09..1be8b0dd8628a217e57fdcaaaeb48c0c65cdc9e9 100644 (file)
@@ -72,7 +72,7 @@ struct Node<T> {
 /// The multi-producer single-consumer structure. This is not cloneable, but it
 /// may be safely shared so long as it is guaranteed that there is only one
 /// popper at a time (many pushers are allowed).
-pub struct Queue<T> {
+pub struct Queue<T: Send> {
     head: AtomicPtr<Node<T>>,
     tail: UnsafeCell<*mut Node<T>>,
 }
index f287712d9d45d59bdc2eb7745ed4ddd468092fe0..13578ce0517911393e106c941ea30e73ce6845a8 100644 (file)
@@ -54,7 +54,7 @@
 // moves *from* a pointer, ownership of the token is transferred to
 // whoever changed the state.
 
-pub struct Packet<T> {
+pub struct Packet<T:Send> {
     // Internal state of the chan/port pair (stores the blocked task as well)
     state: AtomicUsize,
     // One-shot data slot location
@@ -64,7 +64,7 @@ pub struct Packet<T> {
     upgrade: MyUpgrade<T>,
 }
 
-pub enum Failure<T> {
+pub enum Failure<T:Send> {
     Empty,
     Disconnected,
     Upgraded(Receiver<T>),
@@ -76,13 +76,13 @@ pub enum UpgradeResult {
     UpWoke(SignalToken),
 }
 
-pub enum SelectionResult<T> {
+pub enum SelectionResult<T:Send> {
     SelCanceled,
     SelUpgraded(SignalToken, Receiver<T>),
     SelSuccess,
 }
 
-enum MyUpgrade<T> {
+enum MyUpgrade<T:Send> {
     NothingSent,
     SendUsed,
     GoUp(Receiver<T>),
index 0f936641cdc75bb5081f3bf63a09b3d9e8e58f39..b509b3472ee413276ecf52c78c64da05e97f4e2b 100644 (file)
@@ -80,7 +80,7 @@ impl !marker::Send for Select {}
 /// A handle to a receiver which is currently a member of a `Select` set of
 /// receivers.  This handle is used to keep the receiver in the set as well as
 /// interact with the underlying receiver.
-pub struct Handle<'rx, T:'rx> {
+pub struct Handle<'rx, T:Send+'rx> {
     /// The ID of this handle, used to compare against the return value of
     /// `Select::wait()`
     id: usize,
index 8d14824d37feed09e3e0c9916b2b2431b8897b4b..f3930a8a5d632756f52f93d61a1e7b91a47a1939 100644 (file)
@@ -40,7 +40,7 @@
 #[cfg(not(test))]
 const MAX_STEALS: isize = 1 << 20;
 
-pub struct Packet<T> {
+pub struct Packet<T: Send> {
     queue: mpsc::Queue<T>,
     cnt: AtomicIsize, // How many items are on this channel
     steals: isize, // How many times has a port received without blocking?
index 3fb13739aa75af4b0a4cc766791a73fc7b39da81..cd6d1ee05c788bb453b6ceba4f5112c03f9aef42 100644 (file)
@@ -57,7 +57,7 @@ struct Node<T> {
 /// but it can be safely shared in an Arc if it is guaranteed that there
 /// is only one popper and one pusher touching the queue at any one point in
 /// time.
-pub struct Queue<T> {
+pub struct Queue<T: Send> {
     // consumer fields
     tail: UnsafeCell<*mut Node<T>>, // where to pop from
     tail_prev: AtomicPtr<Node<T>>, // where to pop from
index 5a1e05f9c1565e1e28512f51685cc5b59849b20a..a5a73314a6db3d36e29cd08540744954ee986c1e 100644 (file)
@@ -39,7 +39,7 @@
 #[cfg(not(test))]
 const MAX_STEALS: isize = 1 << 20;
 
-pub struct Packet<T> {
+pub struct Packet<T:Send> {
     queue: spsc::Queue<Message<T>>, // internal queue for all message
 
     cnt: AtomicIsize, // How many items are on this channel
@@ -49,7 +49,7 @@ pub struct Packet<T> {
     port_dropped: AtomicBool, // flag if the channel has been destroyed.
 }
 
-pub enum Failure<T> {
+pub enum Failure<T:Send> {
     Empty,
     Disconnected,
     Upgraded(Receiver<T>),
@@ -61,7 +61,7 @@ pub enum UpgradeResult {
     UpWoke(SignalToken),
 }
 
-pub enum SelectionResult<T> {
+pub enum SelectionResult<T:Send> {
     SelSuccess,
     SelCanceled,
     SelUpgraded(SignalToken, Receiver<T>),
@@ -69,7 +69,7 @@ pub enum SelectionResult<T> {
 
 // Any message could contain an "upgrade request" to a new shared port, so the
 // internal queue it's a queue of T, but rather Message<T>
-enum Message<T> {
+enum Message<T:Send> {
     Data(T),
     GoUp(Receiver<T>),
 }
index 33c1614e1b297dfe7037782d6533c6c6fe19a943..71236269487ef8c803ce2fc1af7d01572cb025a9 100644 (file)
@@ -47,7 +47,7 @@
 use sync::mpsc::select::StartResult::{self, Installed, Abort};
 use sync::{Mutex, MutexGuard};
 
-pub struct Packet<T> {
+pub struct Packet<T: Send> {
     /// Only field outside of the mutex. Just done for kicks, but mainly because
     /// the other shared channel already had the code implemented
     channels: AtomicUsize,
index 2bf75cf1d3764c97ea0c89fba9e2bd206f6340f8..b24cfbb6899a9c655d794958259477a7f8217e11 100644 (file)
 /// *guard += 1;
 /// ```
 #[stable(feature = "rust1", since = "1.0.0")]
-pub struct Mutex<T> {
+pub struct Mutex<T: Send> {
     // Note that this static mutex is in a *box*, not inlined into the struct
     // itself. Once a native mutex has been used once, its address can never
     // change (it can't be moved). This mutex type can be safely moved at any
@@ -366,7 +366,7 @@ mod test {
     use sync::{Arc, Mutex, StaticMutex, MUTEX_INIT, Condvar};
     use thread;
 
-    struct Packet<T>(Arc<(Mutex<T>, Condvar)>);
+    struct Packet<T: Send>(Arc<(Mutex<T>, Condvar)>);
 
     unsafe impl<T: Send> Send for Packet<T> {}
     unsafe impl<T> Sync for Packet<T> {}
index 2a852fbcd57e37d3a9399776d34015d83e486f84..10077dfd1b86517f5bcf64ddb37c5bf6eef73178 100644 (file)
@@ -38,7 +38,7 @@
 ///
 /// The fields of this helper are all public, but they should not be used, this
 /// is for static initialization.
-pub struct Helper<M> {
+pub struct Helper<M:Send> {
     /// Internal lock which protects the remaining fields
     pub lock: StaticMutex,
     pub cond: StaticCondvar,
@@ -112,7 +112,7 @@ pub fn boot<T, F>(&'static self, f: F, helper: fn(helper_signal::signal, Receive
                     self.cond.notify_one()
                 });
 
-                rt::at_exit(move || { self.shutdown() });
+                let _ = rt::at_exit(move || { self.shutdown() });
                 *self.initialized.get() = true;
             } else if *self.chan.get() as uint == 1 {
                 panic!("cannot continue usage after shutdown");
index 25aeab1b4ff74074a716f811f1b02bf37151923a..e213a86644fe1ee5fd7f14e976b53874def7342f 100644 (file)
@@ -14,7 +14,7 @@
 use io::{self, Error, ErrorKind};
 use libc::{self, c_int, c_char, c_void, socklen_t};
 use mem;
-use net::{SocketAddr, Shutdown};
+use net::{SocketAddr, Shutdown, IpAddr};
 use sys::c;
 use sys::net::{cvt, cvt_r, cvt_gai, Socket, init, wrlen_t};
 use sys_common::{AsInner, FromInner, IntoInner};
@@ -334,39 +334,39 @@ pub fn set_multicast_loop(&self, on: bool) -> io::Result<()> {
                    libc::IP_MULTICAST_LOOP, on as c_int)
     }
 
-    pub fn join_multicast(&self, multi: &SocketAddr) -> io::Result<()> {
+    pub fn join_multicast(&self, multi: &IpAddr) -> io::Result<()> {
         match *multi {
-            SocketAddr::V4(..) => {
+            IpAddr::V4(..) => {
                 self.set_membership(multi, libc::IP_ADD_MEMBERSHIP)
             }
-            SocketAddr::V6(..) => {
+            IpAddr::V6(..) => {
                 self.set_membership(multi, libc::IPV6_ADD_MEMBERSHIP)
             }
         }
     }
-    pub fn leave_multicast(&self, multi: &SocketAddr) -> io::Result<()> {
+    pub fn leave_multicast(&self, multi: &IpAddr) -> io::Result<()> {
         match *multi {
-            SocketAddr::V4(..) => {
+            IpAddr::V4(..) => {
                 self.set_membership(multi, libc::IP_DROP_MEMBERSHIP)
             }
-            SocketAddr::V6(..) => {
+            IpAddr::V6(..) => {
                 self.set_membership(multi, libc::IPV6_DROP_MEMBERSHIP)
             }
         }
     }
-    fn set_membership(&self, addr: &SocketAddr, opt: c_int) -> io::Result<()> {
+    fn set_membership(&self, addr: &IpAddr, opt: c_int) -> io::Result<()> {
         match *addr {
-            SocketAddr::V4(ref addr) => {
+            IpAddr::V4(ref addr) => {
                 let mreq = libc::ip_mreq {
-                    imr_multiaddr: *addr.ip().as_inner(),
+                    imr_multiaddr: *addr.as_inner(),
                     // interface == INADDR_ANY
                     imr_interface: libc::in_addr { s_addr: 0x0 },
                 };
                 setsockopt(&self.inner, libc::IPPROTO_IP, opt, mreq)
             }
-            SocketAddr::V6(ref addr) => {
+            IpAddr::V6(ref addr) => {
                 let mreq = libc::ip6_mreq {
-                    ipv6mr_multiaddr: *addr.ip().as_inner(),
+                    ipv6mr_multiaddr: *addr.as_inner(),
                     ipv6mr_interface: 0,
                 };
                 setsockopt(&self.inner, libc::IPPROTO_IPV6, opt, mreq)
index 6c191689255bc123ac0517fa676300ef5051f128..c73d30d543ac5ebb93419d0d2e9ef1b6d9520fef 100644 (file)
@@ -206,7 +206,7 @@ pub fn current_exe() -> io::Result<PathBuf> {
         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(PathBuf::new::<OsString>(OsStringExt::from_vec(v)))
+        Ok(PathBuf::from(OsString::from_vec(v)))
     }
 }
 
@@ -232,7 +232,7 @@ pub fn current_exe() -> io::Result<PathBuf> {
             Err(io::Error::last_os_error())
         } else {
             let vec = CStr::from_ptr(v).to_bytes().to_vec();
-            Ok(PathBuf::new::<OsString>(OsStringExt::from_vec(vec)))
+            Ok(PathBuf::from(OsString::from_vec(vec)))
         }
     }
 }
@@ -345,7 +345,7 @@ pub fn args() -> Args {
             let utf_c_str: *const libc::c_char =
                 mem::transmute(objc_msgSend(tmp, utf8_sel));
             let bytes = CStr::from_ptr(utf_c_str).to_bytes();
-            res.push(OsString::from_str(str::from_utf8(bytes).unwrap()))
+            res.push(OsString::from(str::from_utf8(bytes).unwrap()))
         }
     }
 
index e092faf4935dbc3d3e542168cd34389db5a7041b..734268c70ac9ccd1c0e906d77df44aee4708d370 100644 (file)
@@ -36,7 +36,7 @@ pub fn init() {
                                 &mut data);
         assert_eq!(ret, 0);
 
-        rt::at_exit(|| { c::WSACleanup(); })
+        let _ = rt::at_exit(|| { c::WSACleanup(); });
     });
 }
 
index 83d0637173444c56cb4dbb46a7dfc1f715b712a4..167db1e8ac2d790b056c05af6bd78b8bdb8cdb86 100644 (file)
@@ -109,7 +109,7 @@ fn next(&mut self) -> Option<(OsString, OsString)> {
             if *self.cur == 0 { return None }
             let p = &*self.cur;
             let mut len = 0;
-            while *(p as *const _).offset(len) != 0 {
+            while *(p as *const u16).offset(len) != 0 {
                 len += 1;
             }
             let p = p as *const u16;
index 1359803070af384d03033e2df2fd0a229cae48e7..c908c791247d1b3bc47b8379778b380926078fb7 100644 (file)
@@ -133,9 +133,8 @@ unsafe fn init_dtors() {
     if !DTORS.is_null() { return }
 
     let dtors = box Vec::<(Key, Dtor)>::new();
-    DTORS = boxed::into_raw(dtors);
 
-    rt::at_exit(move|| {
+    let res = rt::at_exit(move|| {
         DTOR_LOCK.lock();
         let dtors = DTORS;
         DTORS = 1 as *mut _;
@@ -143,6 +142,11 @@ unsafe fn init_dtors() {
         assert!(DTORS as uint == 1); // can't re-init after destructing
         DTOR_LOCK.unlock();
     });
+    if res.is_ok() {
+        DTORS = boxed::into_raw(dtors);
+    } else {
+        DTORS = 1 as *mut _;
+    }
 }
 
 unsafe fn register_dtor(key: Key, dtor: Dtor) {
index 1bf1b09681c4a360b03232187b31610730f7200a..a2b824bb016ffa401255a488249e480e0d56eaf8 100644 (file)
@@ -176,6 +176,7 @@ macro_rules! __thread_local_inner {
             }
         };
 
+        #[allow(trivial_casts)]
         #[cfg(any(not(any(target_os = "macos", target_os = "linux")), target_arch = "aarch64"))]
         const _INIT: ::std::thread::__local::__impl::KeyInner<$t> = {
             ::std::thread::__local::__impl::KeyInner {
index 57baeb1fb74860a8573a47c36ae4db07b51b79c5..27b50fc9aaa60ca0312245161eb46c48b8a8f61e 100644 (file)
@@ -698,7 +698,7 @@ fn drop(&mut self) {
 /// permission.
 #[must_use = "thread will be immediately joined if `JoinGuard` is not used"]
 #[stable(feature = "rust1", since = "1.0.0")]
-pub struct JoinGuard<'a, T: 'a> {
+pub struct JoinGuard<'a, T: Send + 'a> {
     inner: JoinInner<T>,
     _marker: PhantomData<&'a T>,
 }
index 704abc43f10da3f8e614bf4612ac894988ecb5a2..fec67c7aef48f56213af98901842687da63e0c6d 100644 (file)
@@ -1771,8 +1771,8 @@ pub struct Item {
 pub enum Item_ {
     /// An`extern crate` item, with optional original crate name,
     ///
-    /// e.g. `extern crate foo` or `extern crate "foo-bar" as foo`
-    ItemExternCrate(Option<(InternedString, StrStyle)>),
+    /// e.g. `extern crate foo` or `extern crate foo_bar as foo`
+    ItemExternCrate(Option<Name>),
     /// A `use` or `pub use` item
     ItemUse(P<ViewPath>),
 
index 1abe8d0a3c1b1352e77100adb0f246b130981a04..6a00fff186002f4383ec2b0e24da9556d3b25dcd 100644 (file)
@@ -284,7 +284,7 @@ pub struct ExpnInfo {
 
 impl ExpnId {
     pub fn from_llvm_cookie(cookie: c_uint) -> ExpnId {
-        ExpnId(cookie as u32)
+        ExpnId(cookie)
     }
 
     pub fn to_llvm_cookie(self) -> i32 {
@@ -376,7 +376,7 @@ fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
                         match bytes_per_diff {
                             1 => for diff in diff_iter { try! { (diff.0 as u8).encode(s) } },
                             2 => for diff in diff_iter { try! { (diff.0 as u16).encode(s) } },
-                            4 => for diff in diff_iter { try! { (diff.0 as u32).encode(s) } },
+                            4 => for diff in diff_iter { try! { diff.0.encode(s) } },
                             _ => unreachable!()
                         }
                     }
@@ -650,7 +650,7 @@ pub fn span_to_lines(&self, sp: Span) -> FileLines {
         let lo = self.lookup_char_pos(sp.lo);
         let hi = self.lookup_char_pos(sp.hi);
         let mut lines = Vec::new();
-        for i in lo.line - 1..hi.line as usize {
+        for i in lo.line - 1..hi.line {
             lines.push(i);
         };
         FileLines {file: lo.file, lines: lines}
index 35449bde0b2e086e870198f5874dc882838a8e23..b679456b3537ba00ea448ec2ca0706e7da07bbd3 100644 (file)
@@ -264,7 +264,7 @@ pub fn $fld(v: $t) -> Box<MacResult> {
                     box MacEager {
                         $fld: Some(v),
                         ..Default::default()
-                    } as Box<MacResult>
+                    }
                 }
             )*
         }
@@ -330,7 +330,7 @@ impl DummyResult {
     /// Use this as a return value after hitting any errors and
     /// calling `span_err`.
     pub fn any(sp: Span) -> Box<MacResult+'static> {
-        box DummyResult { expr_only: false, span: sp } as Box<MacResult+'static>
+        box DummyResult { expr_only: false, span: sp }
     }
 
     /// Create a default MacResult that can only be an expression.
@@ -339,7 +339,7 @@ pub fn any(sp: Span) -> Box<MacResult+'static> {
     /// if an error is encountered internally, the user will receive
     /// an error that they also used it in the wrong place.
     pub fn expr(sp: Span) -> Box<MacResult+'static> {
-        box DummyResult { expr_only: true, span: sp } as Box<MacResult+'static>
+        box DummyResult { expr_only: true, span: sp }
     }
 
     /// A plain dummy expression.
index 58b6d96607df777454cb9b841e60fddc4c77848e..0c5e4d67642acc08a82fdbd838ef4dbf21de7dec 100644 (file)
@@ -332,6 +332,46 @@ pub fn combine_substructure<'a>(f: CombineSubstructureFunc<'a>)
     RefCell::new(f)
 }
 
+/// This method helps to extract all the type parameters referenced from a
+/// type. For a type parameter `<T>`, it looks for either a `TyPath` that
+/// is not global and starts with `T`, or a `TyQPath`.
+fn find_type_parameters(ty: &ast::Ty, ty_param_names: &[ast::Name]) -> Vec<P<ast::Ty>> {
+    use visit;
+
+    struct Visitor<'a> {
+        ty_param_names: &'a [ast::Name],
+        types: Vec<P<ast::Ty>>,
+    }
+
+    impl<'a> visit::Visitor<'a> for Visitor<'a> {
+        fn visit_ty(&mut self, ty: &'a ast::Ty) {
+            match ty.node {
+                ast::TyPath(_, ref path) if !path.global => {
+                    match path.segments.first() {
+                        Some(segment) => {
+                            if self.ty_param_names.contains(&segment.identifier.name) {
+                                self.types.push(P(ty.clone()));
+                            }
+                        }
+                        None => {}
+                    }
+                }
+                _ => {}
+            }
+
+            visit::walk_ty(self, ty)
+        }
+    }
+
+    let mut visitor = Visitor {
+        ty_param_names: ty_param_names,
+        types: Vec::new(),
+    };
+
+    visit::Visitor::visit_ty(&mut visitor, ty);
+
+    visitor.types
+}
 
 impl<'a> TraitDef<'a> {
     pub fn expand<F>(&self,
@@ -374,18 +414,42 @@ pub fn expand<F>(&self,
         }))
     }
 
-    /// Given that we are deriving a trait `Tr` for a type `T<'a, ...,
-    /// 'z, A, ..., Z>`, creates an impl like:
+    /// Given that we are deriving a trait `DerivedTrait` for a type like:
     ///
     /// ```ignore
-    /// impl<'a, ..., 'z, A:Tr B1 B2, ..., Z: Tr B1 B2> Tr for T<A, ..., Z> { ... }
+    /// struct Struct<'a, ..., 'z, A, B: DeclaredTrait, C, ..., Z> where C: WhereTrait {
+    ///     a: A,
+    ///     b: B::Item,
+    ///     b1: <B as DeclaredTrait>::Item,
+    ///     c1: <C as WhereTrait>::Item,
+    ///     c2: Option<<C as WhereTrait>::Item>,
+    ///     ...
+    /// }
+    /// ```
+    ///
+    /// create an impl like:
+    ///
+    /// ```ignore
+    /// impl<'a, ..., 'z, A, B: DeclaredTrait, C, ...  Z> where
+    ///     C:                       WhereTrait,
+    ///     A: DerivedTrait + B1 + ... + BN,
+    ///     B: DerivedTrait + B1 + ... + BN,
+    ///     C: DerivedTrait + B1 + ... + BN,
+    ///     B::Item:                 DerivedTrait + B1 + ... + BN,
+    ///     <C as WhereTrait>::Item: DerivedTrait + B1 + ... + BN,
+    ///     ...
+    /// {
+    ///     ...
+    /// }
     /// ```
     ///
-    /// where B1, B2, ... are the bounds given by `bounds_paths`.'
+    /// where B1, ..., BN are the bounds given by `bounds_paths`.'. Z is a phantom type, and
+    /// therefore does not get bound by the derived trait.
     fn create_derived_impl(&self,
                            cx: &mut ExtCtxt,
                            type_ident: Ident,
                            generics: &Generics,
+                           field_tys: Vec<P<ast::Ty>>,
                            methods: Vec<P<ast::ImplItem>>) -> P<ast::Item> {
         let trait_path = self.path.to_path(cx, self.span, type_ident, generics);
 
@@ -466,6 +530,35 @@ fn create_derived_impl(&self,
             }
         }));
 
+        if !ty_params.is_empty() {
+            let ty_param_names: Vec<ast::Name> = ty_params.iter()
+                .map(|ty_param| ty_param.ident.name)
+                .collect();
+
+            for field_ty in field_tys.into_iter() {
+                let tys = find_type_parameters(&*field_ty, &ty_param_names);
+
+                for ty in tys.into_iter() {
+                    let mut bounds: Vec<_> = self.additional_bounds.iter().map(|p| {
+                        cx.typarambound(p.to_path(cx, self.span, type_ident, generics))
+                    }).collect();
+
+                    // require the current trait
+                    bounds.push(cx.typarambound(trait_path.clone()));
+
+                    let predicate = ast::WhereBoundPredicate {
+                        span: self.span,
+                        bound_lifetimes: vec![],
+                        bounded_ty: ty,
+                        bounds: OwnedSlice::from_vec(bounds),
+                    };
+
+                    let predicate = ast::WherePredicate::BoundPredicate(predicate);
+                    where_clause.predicates.push(predicate);
+                }
+            }
+        }
+
         let trait_generics = Generics {
             lifetimes: lifetimes,
             ty_params: OwnedSlice::from_vec(ty_params),
@@ -518,6 +611,10 @@ fn expand_struct_def(&self,
                          struct_def: &StructDef,
                          type_ident: Ident,
                          generics: &Generics) -> P<ast::Item> {
+        let field_tys: Vec<P<ast::Ty>> = struct_def.fields.iter()
+            .map(|field| field.node.ty.clone())
+            .collect();
+
         let methods = self.methods.iter().map(|method_def| {
             let (explicit_self, self_args, nonself_args, tys) =
                 method_def.split_self_nonself_args(
@@ -550,7 +647,7 @@ fn expand_struct_def(&self,
                                      body)
         }).collect();
 
-        self.create_derived_impl(cx, type_ident, generics, methods)
+        self.create_derived_impl(cx, type_ident, generics, field_tys, methods)
     }
 
     fn expand_enum_def(&self,
@@ -558,6 +655,21 @@ fn expand_enum_def(&self,
                        enum_def: &EnumDef,
                        type_ident: Ident,
                        generics: &Generics) -> P<ast::Item> {
+        let mut field_tys = Vec::new();
+
+        for variant in enum_def.variants.iter() {
+            match variant.node.kind {
+                ast::VariantKind::TupleVariantKind(ref args) => {
+                    field_tys.extend(args.iter()
+                        .map(|arg| arg.ty.clone()));
+                }
+                ast::VariantKind::StructVariantKind(ref args) => {
+                    field_tys.extend(args.fields.iter()
+                        .map(|field| field.node.ty.clone()));
+                }
+            }
+        }
+
         let methods = self.methods.iter().map(|method_def| {
             let (explicit_self, self_args, nonself_args, tys) =
                 method_def.split_self_nonself_args(cx, self,
@@ -590,7 +702,7 @@ fn expand_enum_def(&self,
                                      body)
         }).collect();
 
-        self.create_derived_impl(cx, type_ident, generics, methods)
+        self.create_derived_impl(cx, type_ident, generics, field_tys, methods)
     }
 }
 
index 2f609d86f39ffdb1d82bee877d44ef7ec2a7a690..5bbcdea879dff3d90d64303daa33c0fdb71ff40a 100644 (file)
@@ -264,6 +264,7 @@ fn to_source_with_hygiene(&self) -> String {
         (unsigned, $t:ty, $tag:expr) => (
             impl ToSource for $t {
                 fn to_source(&self) -> String {
+                    #![allow(trivial_numeric_casts)]
                     let lit = ast::LitInt(*self as u64, ast::UnsignedIntLit($tag));
                     pprust::lit_to_string(&dummy_spanned(lit))
                 }
index 5940b791843797cacf97c7225dd9a413e27d74c8..1e53db6030143bbcad443e12b866da8fa706c273 100644 (file)
@@ -169,7 +169,7 @@ fn generic_extension<'cx>(cx: &'cx ExtCtxt,
                 // Weird, but useful for X-macros.
                 return box ParserAnyMacro {
                     parser: RefCell::new(p),
-                } as Box<MacResult+'cx>
+                }
               }
               Failure(sp, ref msg) => if sp.lo >= best_fail_spot.lo {
                 best_fail_spot = sp;
index e0953a8ace68d5c646ee23fa436766fca91b9ad5..0843713681bbdaad8b27502a7b8c34956ba151de 100644 (file)
@@ -758,7 +758,7 @@ fn scan_hex_digits(&mut self,
                 self.err_span_char(self.last_pos, self.pos,
                               "illegal character in numeric character escape", c);
                 0
-            }) as u32;
+            });
             self.bump();
         }
 
@@ -887,7 +887,7 @@ fn scan_unicode_escape(&mut self, delim: char) -> bool {
                     self.fatal_span_char(self.last_pos, self.pos,
                                    "illegal character in unicode escape", c);
                 }
-            }) as u32;
+            });
             self.bump();
             count += 1;
         }
index 968d2fd7e2a47c6e216845b527b97e82a8548a79..4e85176121221debe0a40f2ffa89fe8fd5daaa91 100644 (file)
@@ -1060,7 +1060,7 @@ fn parser_done(p: Parser){
         let vitem_s = item_to_string(&*vitem);
         assert_eq!(&vitem_s[..], ex_s);
 
-        let ex_s = "extern crate \"foo\" as bar;";
+        let ex_s = "extern crate foo as bar;";
         let vitem = string_to_item(ex_s.to_string()).unwrap();
         let vitem_s = item_to_string(&*vitem);
         assert_eq!(&vitem_s[..], ex_s);
index 7da0a6de5479cb7594fbd37a7f743c46c7b7ccfd..276be73823a421dec63d6a22791bfd239f634d43 100644 (file)
@@ -24,6 +24,7 @@
 pub enum ObsoleteSyntax {
     ClosureKind,
     EmptyIndex,
+    ExternCrateString,
 }
 
 pub trait ParserObsoleteMethods {
@@ -56,6 +57,11 @@ fn obsolete(&mut self, sp: Span, kind: ObsoleteSyntax) {
                 "write `[..]` instead",
                 false, // warning for now
             ),
+            ObsoleteSyntax::ExternCrateString => (
+                "\"crate-name\"",
+                "use an identifier not in quotes instead",
+                false, // warning for now
+            ),
         };
 
         self.report(sp, kind, kind_str, desc, error);
index 023f6e69945aba4fe028b4c8b168414f05985673..786970ce252965f652cedb01d6c2c5e419e159ac 100644 (file)
@@ -865,7 +865,7 @@ pub fn bump(&mut self) {
         } else {
             // Avoid token copies with `replace`.
             let buffer_start = self.buffer_start as usize;
-            let next_index = (buffer_start + 1) & 3 as usize;
+            let next_index = (buffer_start + 1) & 3;
             self.buffer_start = next_index as isize;
 
             let placeholder = TokenAndSpan {
@@ -4993,37 +4993,28 @@ fn parse_item_extern_crate(&mut self,
                                 attrs: Vec<Attribute>)
                                 -> P<Item> {
 
-        let span = self.span;
         let (maybe_path, ident) = match self.token {
             token::Ident(..) => {
-                let the_ident = self.parse_ident();
-                let path = if self.eat_keyword_noexpect(keywords::As) {
-                    // skip the ident if there is one
-                    if self.token.is_ident() { self.bump(); }
-
-                    self.span_err(span, "expected `;`, found `as`");
-                    self.fileline_help(span,
-                                   &format!("perhaps you meant to enclose the crate name `{}` in \
-                                           a string?",
-                                          the_ident.as_str()));
-                    None
+                let crate_name = self.parse_ident();
+                if self.eat_keyword(keywords::As) {
+                    (Some(crate_name.name), self.parse_ident())
                 } else {
-                    None
-                };
-                self.expect(&token::Semi);
-                (path, the_ident)
+                    (None, crate_name)
+                }
             },
-            token::Literal(token::Str_(..), suf) | token::Literal(token::StrRaw(..), suf) => {
+            token::Literal(token::Str_(..), suf) |
+            token::Literal(token::StrRaw(..), suf) => {
                 let sp = self.span;
                 self.expect_no_suffix(sp, "extern crate name", suf);
                 // forgo the internal suffix check of `parse_str` to
                 // avoid repeats (this unwrap will always succeed due
                 // to the restriction of the `match`)
-                let (s, style, _) = self.parse_optional_str().unwrap();
+                let (s, _, _) = self.parse_optional_str().unwrap();
                 self.expect_keyword(keywords::As);
                 let the_ident = self.parse_ident();
-                self.expect(&token::Semi);
-                (Some((s, style)), the_ident)
+                self.obsolete(sp, ObsoleteSyntax::ExternCrateString);
+                let s = token::intern(&s);
+                (Some(s), the_ident)
             },
             _ => {
                 let span = self.span;
@@ -5034,6 +5025,7 @@ fn parse_item_extern_crate(&mut self,
                                         token_str));
             }
         };
+        self.expect(&token::Semi);
 
         let last_span = self.last_span;
         self.mk_item(lo,
index ddcdcf4e1b8fa0952e136c578fc195bbcf827753..da1b7a7bdde50e93ec50a11aac7702b4db45b759 100644 (file)
@@ -825,8 +825,13 @@ pub fn print_item(&mut self, item: &ast::Item) -> io::Result<()> {
             ast::ItemExternCrate(ref optional_path) => {
                 try!(self.head(&visibility_qualified(item.vis,
                                                      "extern crate")));
-                if let Some((ref p, style)) = *optional_path {
-                    try!(self.print_string(p, style));
+                if let Some(p) = *optional_path {
+                    let val = token::get_name(p);
+                    if val.contains("-") {
+                        try!(self.print_string(&val, ast::CookedStr));
+                    } else {
+                        try!(self.print_name(p));
+                    }
                     try!(space(&mut self.s));
                     try!(word(&mut self.s, "as"));
                     try!(space(&mut self.s));
@@ -2832,7 +2837,7 @@ pub fn print_literal(&mut self, lit: &ast::Lit) -> io::Result<()> {
             ast::LitBinary(ref v) => {
                 let mut escaped: String = String::new();
                 for &ch in &**v {
-                    escaped.extend(ascii::escape_default(ch as u8)
+                    escaped.extend(ascii::escape_default(ch)
                                          .map(|c| c as char));
                 }
                 word(&mut self.s, &format!("b\"{}\"", escaped))
index ac7cdb1b4130703ba30b7150a4eb25331b6cc7e8..0fa7e4f902c6c63dad243bd548c04e0d902212f8 100644 (file)
@@ -54,8 +54,8 @@ fn fold_crate(&mut self, mut krate: ast::Crate) -> ast::Crate {
 
         // The name to use in `extern crate "name" as std;`
         let actual_crate_name = match self.alt_std_name {
-            Some(ref s) => token::intern_and_get_ident(&s[..]),
-            None => token::intern_and_get_ident("std"),
+            Some(ref s) => token::intern(&s),
+            None => token::intern("std"),
         };
 
         krate.module.items.insert(0, P(ast::Item {
@@ -64,7 +64,7 @@ fn fold_crate(&mut self, mut krate: ast::Crate) -> ast::Crate {
             attrs: vec!(
                 attr::mk_attr_outer(attr::mk_attr_id(), attr::mk_word_item(
                         InternedString::new("macro_use")))),
-            node: ast::ItemExternCrate(Some((actual_crate_name, ast::CookedStr))),
+            node: ast::ItemExternCrate(Some(actual_crate_name)),
             vis: ast::Inherited,
             span: DUMMY_SP
         }));
index c907b87bc3c66e9f3ec9f5a9dd81abf8cadd559c..41e066cc94a92b2aab65ea336f0c2b16639bffe6 100644 (file)
@@ -103,7 +103,7 @@ fn flush(&mut self) -> io::Result<()> {
 /// opened.
 pub fn stdout() -> Option<Box<Terminal<WriterWrapper> + Send>> {
     TerminfoTerminal::new(WriterWrapper {
-        wrapped: box std::io::stdout() as Box<Write + Send>,
+        wrapped: box std::io::stdout(),
     })
 }
 
@@ -112,14 +112,14 @@ pub fn stdout() -> Option<Box<Terminal<WriterWrapper> + Send>> {
 /// opened.
 pub fn stdout() -> Option<Box<Terminal<WriterWrapper> + Send>> {
     let ti = TerminfoTerminal::new(WriterWrapper {
-        wrapped: box std::io::stdout() as Box<Write + Send>,
+        wrapped: box std::io::stdout(),
     });
 
     match ti {
         Some(t) => Some(t),
         None => {
             WinConsole::new(WriterWrapper {
-                wrapped: box std::io::stdout() as Box<Write + Send>,
+                wrapped: box std::io::stdout(),
             })
         }
     }
@@ -130,7 +130,7 @@ pub fn stdout() -> Option<Box<Terminal<WriterWrapper> + Send>> {
 /// opened.
 pub fn stderr() -> Option<Box<Terminal<WriterWrapper> + Send>> {
     TerminfoTerminal::new(WriterWrapper {
-        wrapped: box std::io::stderr() as Box<Write + Send>,
+        wrapped: box std::io::stderr(),
     })
 }
 
@@ -139,14 +139,14 @@ pub fn stderr() -> Option<Box<Terminal<WriterWrapper> + Send>> {
 /// opened.
 pub fn stderr() -> Option<Box<Terminal<WriterWrapper> + Send>> {
     let ti = TerminfoTerminal::new(WriterWrapper {
-        wrapped: box std::io::stderr() as Box<Write + Send>,
+        wrapped: box std::io::stderr(),
     });
 
     match ti {
         Some(t) => Some(t),
         None => {
             WinConsole::new(WriterWrapper {
-                wrapped: box std::io::stderr() as Box<Write + Send>,
+                wrapped: box std::io::stderr(),
             })
         }
     }
index 309320b52ffe4aa641abdf485537f5452eb7f64a..1d6657d5932c0d5a410282254e8a7056571dc148 100644 (file)
@@ -190,7 +190,7 @@ pub fn new(out: T) -> Option<Box<Terminal<T>+Send+'static>> {
                         out: out,
                         ti: msys_terminfo(),
                         num_colors: 8,
-                    } as Box<Terminal<T>+Send>)
+                    })
                 },
                 _ => {
                     debug!("error finding terminfo entry: {:?}", err);
@@ -213,7 +213,7 @@ pub fn new(out: T) -> Option<Box<Terminal<T>+Send+'static>> {
 
         return Some(box TerminfoTerminal {out: out,
                                           ti: inf,
-                                          num_colors: nc} as Box<Terminal<T>+Send>);
+                                          num_colors: nc});
     }
 
     fn dim_if_necessary(&self, color: color::Color) -> color::Color {
index cc9a2880b5d07d10b5f8502315b1f9e9951f0798..8d0a9e6e9717d502d2e7b17fa1dd34dceddc90e4 100644 (file)
@@ -186,7 +186,7 @@ macro_rules! try { ($e:expr) => (
     let magic = try!(read_le_u16(file));
     if magic != 0x011A {
         return Err(format!("invalid magic number: expected {:x}, found {:x}",
-                           0x011A as usize, magic as usize));
+                           0x011A_usize, magic as usize));
     }
 
     let names_bytes          = try!(read_le_u16(file)) as int;
index e29e0e27394db93a3103fc149c9baf424cbf930f..001313db6769f133b8f8166b16c61428ead730a4 100644 (file)
@@ -126,7 +126,7 @@ pub fn new(out: T) -> Option<Box<Terminal<T>+Send+'static>> {
         }
         Some(box WinConsole { buf: out,
                               def_foreground: fg, def_background: bg,
-                              foreground: fg, background: bg } as Box<Terminal<T>+Send>)
+                              foreground: fg, background: bg })
     }
 }
 
index 402774321bfcbccbd1475b2b46a7b86915c8ab2e..c48c7e413d03baa961ec62c60a07b19e82da678c 100644 (file)
@@ -1021,7 +1021,7 @@ pub fn fmt_metrics(&self) -> String {
         let MetricMap(ref mm) = *self;
         let v : Vec<String> = mm.iter()
             .map(|(k,v)| format!("{}: {} (+/- {})", *k,
-                                 v.value as f64, v.noise as f64))
+                                 v.value, v.noise))
             .collect();
         v.connect(", ")
     }
index 473739c919d64ee27fc4e3e3e40a85e3b0e29426..44af43be7877344cfd878700984662adb9f60058 100644 (file)
@@ -32,11 +32,11 @@ pub trait Subcommand {
 
 /// Create a Subcommand object based on its name.
 pub fn parse_name(name: &str) -> Option<Box<Subcommand>> {
-    for parser in [
-        help::parse_cmd as fn(&str) -> Option<Box<Subcommand>>,
-        build::parse_cmd as fn(&str) -> Option<Box<Subcommand>>,
-        serve::parse_cmd as fn(&str) -> Option<Box<Subcommand>>,
-        test::parse_cmd as fn(&str) -> Option<Box<Subcommand>>].iter() {
+    let cmds: [fn(&str) -> Option<Box<Subcommand>>; 4] = [help::parse_cmd,
+                                                          build::parse_cmd,
+                                                          serve::parse_cmd,
+                                                          test::parse_cmd];
+    for parser in cmds.iter() {
         let parsed = (*parser)(name);
         if parsed.is_some() { return parsed }
     }
diff --git a/src/test/auxiliary/coherence-lib.rs b/src/test/auxiliary/coherence-lib.rs
deleted file mode 100644 (file)
index daa1238..0000000
+++ /dev/null
@@ -1,25 +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.
-
-#![crate_type="lib"]
-
-pub trait Remote {
-    fn foo(&self) { }
-}
-
-pub trait Remote1<T> {
-    fn foo(&self, t: T) { }
-}
-
-pub trait Remote2<T, U> {
-    fn foo(&self, t: T, u: U) { }
-}
-
-pub struct Pair<T,U>(T,U);
diff --git a/src/test/auxiliary/coherence-orphan-lib.rs b/src/test/auxiliary/coherence-orphan-lib.rs
deleted file mode 100644 (file)
index 93d8fd3..0000000
+++ /dev/null
@@ -1,13 +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.
-
-pub trait TheTrait<T> : ::std::marker::PhantomFn<T> {
-    fn the_fn(&self);
-}
diff --git a/src/test/auxiliary/coherence_lib.rs b/src/test/auxiliary/coherence_lib.rs
new file mode 100644 (file)
index 0000000..daa1238
--- /dev/null
@@ -0,0 +1,25 @@
+// 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.
+
+#![crate_type="lib"]
+
+pub trait Remote {
+    fn foo(&self) { }
+}
+
+pub trait Remote1<T> {
+    fn foo(&self, t: T) { }
+}
+
+pub trait Remote2<T, U> {
+    fn foo(&self, t: T, u: U) { }
+}
+
+pub struct Pair<T,U>(T,U);
diff --git a/src/test/auxiliary/coherence_orphan_lib.rs b/src/test/auxiliary/coherence_orphan_lib.rs
new file mode 100644 (file)
index 0000000..93d8fd3
--- /dev/null
@@ -0,0 +1,13 @@
+// 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.
+
+pub trait TheTrait<T> : ::std::marker::PhantomFn<T> {
+    fn the_fn(&self);
+}
index 560844332a128d4718362b8a7debb61deb7436a0..d66cfe9bf636b716867370a728bd5f52091142c6 100644 (file)
@@ -21,6 +21,6 @@ fn f() {}
 }
 
 pub fn foo() {
-    let a = &1 as &inner::Trait;
+    let a = &1i as &inner::Trait;
     a.f();
 }
diff --git a/src/test/auxiliary/issue-11680.rs b/src/test/auxiliary/issue-11680.rs
deleted file mode 100644 (file)
index 249a1ba..0000000
+++ /dev/null
@@ -1,19 +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.
-
-enum Foo {
-    Bar(int)
-}
-
-pub mod test {
-    enum Foo {
-        Bar(int)
-    }
-}
diff --git a/src/test/auxiliary/issue-12612-1.rs b/src/test/auxiliary/issue-12612-1.rs
deleted file mode 100644 (file)
index a0234c1..0000000
+++ /dev/null
@@ -1,13 +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.
-
-pub mod bar {
-    pub fn foo() {}
-}
diff --git a/src/test/auxiliary/issue-12612-2.rs b/src/test/auxiliary/issue-12612-2.rs
deleted file mode 100644 (file)
index b4ae437..0000000
+++ /dev/null
@@ -1,11 +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.
-
-pub fn baz() {}
diff --git a/src/test/auxiliary/issue-16725.rs b/src/test/auxiliary/issue-16725.rs
deleted file mode 100644 (file)
index b3b04b4..0000000
+++ /dev/null
@@ -1,13 +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.
-
-extern {
-    fn bar();
-}
diff --git a/src/test/auxiliary/issue-17718-const-privacy.rs b/src/test/auxiliary/issue-17718-const-privacy.rs
deleted file mode 100644 (file)
index 3657d39..0000000
+++ /dev/null
@@ -1,18 +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.
-
-pub use foo::FOO2;
-
-pub const FOO: uint = 3;
-const BAR: uint = 3;
-
-mod foo {
-    pub const FOO2: uint = 3;
-}
diff --git a/src/test/auxiliary/issue-21202.rs b/src/test/auxiliary/issue-21202.rs
deleted file mode 100644 (file)
index afdbf78..0000000
+++ /dev/null
@@ -1,16 +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.
-
-pub mod A {
-    pub struct Foo;
-    impl Foo {
-        fn foo(&self) { }
-    }
-}
index 89b3b56121a1614961297566eb8088c21a5808ef..832665abdc2d762ab48ac265c3a54e3a674eea43 100644 (file)
@@ -15,7 +15,7 @@
 
 use std::marker;
 
-struct arc_destruct<T> {
+struct arc_destruct<T: Sync> {
     _data: int,
     _marker: marker::PhantomData<T>
 }
diff --git a/src/test/auxiliary/issue_11680.rs b/src/test/auxiliary/issue_11680.rs
new file mode 100644 (file)
index 0000000..249a1ba
--- /dev/null
@@ -0,0 +1,19 @@
+// 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.
+
+enum Foo {
+    Bar(int)
+}
+
+pub mod test {
+    enum Foo {
+        Bar(int)
+    }
+}
diff --git a/src/test/auxiliary/issue_12612_1.rs b/src/test/auxiliary/issue_12612_1.rs
new file mode 100644 (file)
index 0000000..a0234c1
--- /dev/null
@@ -0,0 +1,13 @@
+// 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.
+
+pub mod bar {
+    pub fn foo() {}
+}
diff --git a/src/test/auxiliary/issue_12612_2.rs b/src/test/auxiliary/issue_12612_2.rs
new file mode 100644 (file)
index 0000000..b4ae437
--- /dev/null
@@ -0,0 +1,11 @@
+// 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.
+
+pub fn baz() {}
diff --git a/src/test/auxiliary/issue_16725.rs b/src/test/auxiliary/issue_16725.rs
new file mode 100644 (file)
index 0000000..b3b04b4
--- /dev/null
@@ -0,0 +1,13 @@
+// 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.
+
+extern {
+    fn bar();
+}
diff --git a/src/test/auxiliary/issue_17718_const_privacy.rs b/src/test/auxiliary/issue_17718_const_privacy.rs
new file mode 100644 (file)
index 0000000..3657d39
--- /dev/null
@@ -0,0 +1,18 @@
+// 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.
+
+pub use foo::FOO2;
+
+pub const FOO: uint = 3;
+const BAR: uint = 3;
+
+mod foo {
+    pub const FOO2: uint = 3;
+}
diff --git a/src/test/auxiliary/issue_21202.rs b/src/test/auxiliary/issue_21202.rs
new file mode 100644 (file)
index 0000000..afdbf78
--- /dev/null
@@ -0,0 +1,16 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+pub mod A {
+    pub struct Foo;
+    impl Foo {
+        fn foo(&self) { }
+    }
+}
diff --git a/src/test/auxiliary/lint-unused-extern-crate.rs b/src/test/auxiliary/lint-unused-extern-crate.rs
deleted file mode 100644 (file)
index 2661b1f..0000000
+++ /dev/null
@@ -1,11 +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.
-
-pub fn foo() {}
diff --git a/src/test/auxiliary/lint_unused_extern_crate.rs b/src/test/auxiliary/lint_unused_extern_crate.rs
new file mode 100644 (file)
index 0000000..2661b1f
--- /dev/null
@@ -0,0 +1,11 @@
+// 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.
+
+pub fn foo() {}
diff --git a/src/test/auxiliary/privacy-tuple-struct.rs b/src/test/auxiliary/privacy-tuple-struct.rs
deleted file mode 100644 (file)
index 2fb9d99..0000000
+++ /dev/null
@@ -1,14 +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.
-
-pub struct A(());
-pub struct B(int);
-pub struct C(pub int, int);
-pub struct D(pub int);
diff --git a/src/test/auxiliary/privacy_tuple_struct.rs b/src/test/auxiliary/privacy_tuple_struct.rs
new file mode 100644 (file)
index 0000000..2fb9d99
--- /dev/null
@@ -0,0 +1,14 @@
+// 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.
+
+pub struct A(());
+pub struct B(int);
+pub struct C(pub int, int);
+pub struct D(pub int);
diff --git a/src/test/auxiliary/regions-bounded-method-type-parameters-cross-crate-lib.rs b/src/test/auxiliary/regions-bounded-method-type-parameters-cross-crate-lib.rs
deleted file mode 100644 (file)
index 9c0716e..0000000
+++ /dev/null
@@ -1,42 +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.
-
-// Check that method bounds declared on traits/impls in a cross-crate
-// scenario work. This is the library portion of the test.
-
-pub enum MaybeOwned<'a> {
-    Owned(int),
-    Borrowed(&'a int)
-}
-
-pub struct Inv<'a> { // invariant w/r/t 'a
-    x: &'a mut &'a int
-}
-
-// I encountered a bug at some point with encoding the IntoMaybeOwned
-// trait, so I'll use that as the template for this test.
-pub trait IntoMaybeOwned<'a> {
-    fn into_maybe_owned(self) -> MaybeOwned<'a>;
-
-    // Note: without this `into_inv` method, the trait is
-    // contravariant w/r/t `'a`, since if you look strictly at the
-    // interface, it only returns `'a`. This complicates the
-    // downstream test since it wants invariance to force an error.
-    // Hence we add this method.
-    fn into_inv(self) -> Inv<'a>;
-
-    fn bigger_region<'b:'a>(self, b: Inv<'b>);
-}
-
-impl<'a> IntoMaybeOwned<'a> for Inv<'a> {
-    fn into_maybe_owned(self) -> MaybeOwned<'a> { panic!() }
-    fn into_inv(self) -> Inv<'a> { panic!() }
-    fn bigger_region<'b:'a>(self, b: Inv<'b>) { panic!() }
-}
diff --git a/src/test/auxiliary/regions_bounded_method_type_parameters_cross_crate_lib.rs b/src/test/auxiliary/regions_bounded_method_type_parameters_cross_crate_lib.rs
new file mode 100644 (file)
index 0000000..9c0716e
--- /dev/null
@@ -0,0 +1,42 @@
+// 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 method bounds declared on traits/impls in a cross-crate
+// scenario work. This is the library portion of the test.
+
+pub enum MaybeOwned<'a> {
+    Owned(int),
+    Borrowed(&'a int)
+}
+
+pub struct Inv<'a> { // invariant w/r/t 'a
+    x: &'a mut &'a int
+}
+
+// I encountered a bug at some point with encoding the IntoMaybeOwned
+// trait, so I'll use that as the template for this test.
+pub trait IntoMaybeOwned<'a> {
+    fn into_maybe_owned(self) -> MaybeOwned<'a>;
+
+    // Note: without this `into_inv` method, the trait is
+    // contravariant w/r/t `'a`, since if you look strictly at the
+    // interface, it only returns `'a`. This complicates the
+    // downstream test since it wants invariance to force an error.
+    // Hence we add this method.
+    fn into_inv(self) -> Inv<'a>;
+
+    fn bigger_region<'b:'a>(self, b: Inv<'b>);
+}
+
+impl<'a> IntoMaybeOwned<'a> for Inv<'a> {
+    fn into_maybe_owned(self) -> MaybeOwned<'a> { panic!() }
+    fn into_inv(self) -> Inv<'a> { panic!() }
+    fn bigger_region<'b:'a>(self, b: Inv<'b>) { panic!() }
+}
diff --git a/src/test/auxiliary/struct-field-privacy.rs b/src/test/auxiliary/struct-field-privacy.rs
deleted file mode 100644 (file)
index e2c16ae..0000000
+++ /dev/null
@@ -1,19 +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.
-
-struct A {
-    a: int,
-    pub b: int,
-}
-
-pub struct B {
-    pub a: int,
-    b: int,
-}
diff --git a/src/test/auxiliary/struct_field_privacy.rs b/src/test/auxiliary/struct_field_privacy.rs
new file mode 100644 (file)
index 0000000..e2c16ae
--- /dev/null
@@ -0,0 +1,19 @@
+// 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.
+
+struct A {
+    a: int,
+    pub b: int,
+}
+
+pub struct B {
+    pub a: int,
+    b: int,
+}
index 76fd619f689648adba8e8cc2c444c3e50c8f3099..8670cd96fc6de7f406f85439d8532b21a9464089 100644 (file)
@@ -11,6 +11,7 @@
 #![crate_name="struct_variant_xc_aux"]
 #![crate_type = "lib"]
 
+#[derive(Copy)]
 pub enum Enum {
     Variant(u8),
     StructVariant { arg: u8 }
diff --git a/src/test/auxiliary/trait-safety-lib.rs b/src/test/auxiliary/trait-safety-lib.rs
deleted file mode 100644 (file)
index d543769..0000000
+++ /dev/null
@@ -1,19 +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.
-
-// Simple smoke test that unsafe traits can be compiled etc.
-
-pub unsafe trait Foo {
-    fn foo(&self) -> int;
-}
-
-unsafe impl Foo for int {
-    fn foo(&self) -> int { *self }
-}
diff --git a/src/test/auxiliary/trait_safety_lib.rs b/src/test/auxiliary/trait_safety_lib.rs
new file mode 100644 (file)
index 0000000..d543769
--- /dev/null
@@ -0,0 +1,19 @@
+// 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.
+
+// Simple smoke test that unsafe traits can be compiled etc.
+
+pub unsafe trait Foo {
+    fn foo(&self) -> int;
+}
+
+unsafe impl Foo for int {
+    fn foo(&self) -> int { *self }
+}
diff --git a/src/test/auxiliary/typeck-default-trait-impl-cross-crate-coherence-lib.rs b/src/test/auxiliary/typeck-default-trait-impl-cross-crate-coherence-lib.rs
deleted file mode 100644 (file)
index 5a7a3e7..0000000
+++ /dev/null
@@ -1,19 +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.
-
-#![feature(optin_builtin_traits, core)]
-#![crate_type = "rlib"]
-
-use std::marker::MarkerTrait;
-
-pub trait DefaultedTrait : MarkerTrait { }
-impl DefaultedTrait for .. { }
-
-pub struct Something<T> { t: T }
diff --git a/src/test/auxiliary/typeck_default_trait_impl_cross_crate_coherence_lib.rs b/src/test/auxiliary/typeck_default_trait_impl_cross_crate_coherence_lib.rs
new file mode 100644 (file)
index 0000000..5a7a3e7
--- /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.
+
+#![feature(optin_builtin_traits, core)]
+#![crate_type = "rlib"]
+
+use std::marker::MarkerTrait;
+
+pub trait DefaultedTrait : MarkerTrait { }
+impl DefaultedTrait for .. { }
+
+pub struct Something<T> { t: T }
diff --git a/src/test/auxiliary/unreachable-variant.rs b/src/test/auxiliary/unreachable-variant.rs
deleted file mode 100644 (file)
index 8ca85f2..0000000
+++ /dev/null
@@ -1,15 +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.
-
-mod super_sekrit {
-    pub enum sooper_sekrit {
-        quux, baz
-    }
-}
diff --git a/src/test/auxiliary/unreachable_variant.rs b/src/test/auxiliary/unreachable_variant.rs
new file mode 100644 (file)
index 0000000..8ca85f2
--- /dev/null
@@ -0,0 +1,15 @@
+// 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.
+
+mod super_sekrit {
+    pub enum sooper_sekrit {
+        quux, baz
+    }
+}
index 71e3ce9a35abe7bb4e970c058477271f4afa5a96..193666f826932f9bbf28fe51220c919824ba26a8 100644 (file)
@@ -9,5 +9,6 @@
 // except according to those terms.
 
 extern crate "" as foo; //~ ERROR: crate name must not be empty
+//~^ WARNING: obsolete syntax
 
 fn main() {}
index 6425908672d12d3ee74a6d3dbffca2ab17870b6d..29df0fa705e1a72c57624b3260078eac9d9a25ac 100644 (file)
@@ -9,5 +9,6 @@
 // except according to those terms.
 
 extern crate "#a" as bar; //~ ERROR: invalid character `#` in crate name: `#a`
+//~^ WARNING: obsolete syntax
 
 fn main() {}
index 673c025e86345098b695e0d832673a7777d315ac..93c37524bf565294dd07c4fba3c4ec794c49bd7a 100644 (file)
@@ -18,26 +18,36 @@ struct SFn {
 }
 
 impl Fn<(isize,)> for SFn {
-    type Output = isize;
-
     extern "rust-call" fn call(&self, (z,): (isize,)) -> isize {
         self.x * self.y * z
     }
 }
 
+impl FnMut<(isize,)> for SFn {
+    extern "rust-call" fn call_mut(&mut self, args: (isize,)) -> isize { self.call(args) }
+}
+
+impl FnOnce<(isize,)> for SFn {
+    type Output = isize;
+    extern "rust-call" fn call_once(self, args: (isize,)) -> isize { self.call(args) }
+}
+
 struct SFnMut {
     x: isize,
     y: isize,
 }
 
 impl FnMut<(isize,)> for SFnMut {
-    type Output = isize;
-
     extern "rust-call" fn call_mut(&mut self, (z,): (isize,)) -> isize {
         self.x * self.y * z
     }
 }
 
+impl FnOnce<(isize,)> for SFnMut {
+    type Output = isize;
+    extern "rust-call" fn call_once(mut self, args: (isize,)) -> isize { self.call_mut(args) }
+}
+
 struct SFnOnce {
     x: String,
 }
index fe7635f065cdc5ee969fe64c792b991de8fe45a6..27b4a04054f073f203503b5ef9a01298e864a622 100644 (file)
@@ -10,5 +10,6 @@
 
 fn main() {
     let x: Option<&[u8]> = Some("foo").map(std::mem::transmute);
-    //~^ ERROR: is not implemented for the type
+    //~^ ERROR E0277
+    //~| ERROR E0277
 }
index 1e3b7f6dbd22f94b819466d1dea00b9aced81b14..7a5340041c21bd911f3eaa8646bcd9df766eb70d 100644 (file)
@@ -8,9 +8,9 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// aux-build:coherence-lib.rs
+// aux-build:coherence_lib.rs
 
-extern crate "coherence-lib" as lib;
+extern crate coherence_lib as lib;
 use lib::Remote1;
 
 impl<T> Remote1<T> for isize { }
index b7ca499be736623db82a570eccbda76c7718a28e..32c5b6693814ecada9787e5c319975b574acdd7f 100644 (file)
@@ -8,9 +8,9 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// aux-build:coherence-lib.rs
+// aux-build:coherence_lib.rs
 
-extern crate "coherence-lib" as lib;
+extern crate coherence_lib as lib;
 use lib::Remote1;
 
 pub struct BigInt;
index 1bec97de53386a4020f4ef071327b69a8a51f28a..475d7df1fdb4f7acb5ce91f7b5640f359813c5bd 100644 (file)
@@ -8,11 +8,11 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// aux-build:coherence-lib.rs
+// aux-build:coherence_lib.rs
 
 // Test that it's not ok for U to appear uncovered
 
-extern crate "coherence-lib" as lib;
+extern crate coherence_lib as lib;
 use lib::{Remote,Pair};
 
 pub struct Cover<T>(T);
index 9f7481f12f2f7d3201c3b0bcf629b8f34615194d..e78f392b386bbb0841a281e5e302ed2467b10ce7 100644 (file)
@@ -8,9 +8,9 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// aux-build:coherence-lib.rs
+// aux-build:coherence_lib.rs
 
-extern crate "coherence-lib" as lib;
+extern crate coherence_lib as lib;
 use lib::Remote;
 
 impl<T> Remote for T { }
index 97dffec2dd9bd4758db4a11f9f89107d00581b72..2243a0507f2d14cc4a32d8f70cbaf5ed2d79d55e 100644 (file)
@@ -9,11 +9,11 @@
 // except according to those terms.
 
 // ignore-tidy-linelength
-// aux-build:coherence-orphan-lib.rs
+// aux-build:coherence_orphan_lib.rs
 
 #![feature(optin_builtin_traits)]
 
-extern crate "coherence-orphan-lib" as lib;
+extern crate coherence_orphan_lib as lib;
 
 use lib::TheTrait;
 
index 9878bdec2c36ffc56100fbffe72ad6c1716389f7..ba9dc53e8680f6d683591f3a4b45e2193501e205 100644 (file)
@@ -8,9 +8,9 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// aux-build:coherence-lib.rs
+// aux-build:coherence_lib.rs
 
-extern crate "coherence-lib" as lib;
+extern crate coherence_lib as lib;
 use lib::Remote;
 
 struct Foo;
index 2bdcc346f70d3055193c616afa1324ece4c7f08e..f55efef14fade3b47adc5d4825f500310211f1a7 100644 (file)
@@ -11,9 +11,9 @@
 // Test that the same coverage rules apply even if the local type appears in the
 // list of type parameters, not the self type.
 
-// aux-build:coherence-lib.rs
+// aux-build:coherence_lib.rs
 
-extern crate "coherence-lib" as lib;
+extern crate coherence_lib as lib;
 use lib::{Remote1, Pair};
 
 pub struct Local<T>(T);
index 881494f009f1576784b3f10d345ffa88e94d83bb..0642dff4b28257baa2d9caf866fd3b28b0c2877e 100644 (file)
@@ -8,9 +8,9 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// aux-build:coherence-lib.rs
+// aux-build:coherence_lib.rs
 
-extern crate "coherence-lib" as lib;
+extern crate coherence_lib as lib;
 use lib::{Remote, Pair};
 
 struct Local<T>(T);
diff --git a/src/test/compile-fail/derive-assoc-type-not-impl.rs b/src/test/compile-fail/derive-assoc-type-not-impl.rs
new file mode 100644 (file)
index 0000000..3799f2f
--- /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.
+
+trait Foo {
+    type X;
+    fn method(&self) {}
+}
+
+#[derive(Clone)]
+struct Bar<T: Foo> {
+    x: T::X,
+}
+
+struct NotClone;
+
+impl Foo for NotClone {
+    type X = i8;
+}
+
+fn main() {
+    Bar::<NotClone> { x: 1 }.clone(); //~ ERROR
+}
index f82e7f3e36a8ac7bbd7cce6b52606ddff2b5c19b..d0cb4f23a8c2844a27094dd0a19db8393d5b0b86 100644 (file)
@@ -13,7 +13,7 @@
 
 extern crate core;
 extern crate rand;
-extern crate "serialize" as rustc_serialize;
+extern crate serialize as rustc_serialize;
 
 #[derive(Rand)]  //~ ERROR this trait cannot be derived
 //~^ WARNING `#[derive(Rand)]` is deprecated
index db3373ea02772285a8300795963091b2e992609b..d1abed9b2627c0a636bd9f1eb96ceb6ce7c3f008 100644 (file)
@@ -18,5 +18,5 @@ fn main() {
     let _x: extern "C" fn() = f; // OK
     is_fn(f);
     //~^ ERROR the trait `core::ops::Fn<()>` is not implemented for the type `extern "C" fn()
-    //~| ERROR the trait `core::ops::Fn<()>` is not implemented for the type `extern "C" fn()
+    //~| ERROR the trait `core::ops::FnOnce<()>` is not implemented for the type `extern "C" fn()
 }
index e5e5ddadafccf8014d09b675f53a1b093c896e4c..d86c5d211dc5fa2e339d1fa06582655ee0b44d3f 100644 (file)
 struct Foo;
 impl Fn<()> for Foo {
     //~^ ERROR angle-bracket notation is not stable when used with the `Fn` family of traits
-    type Output = ();
-
-    extern "rust-call" fn call(&self, args: ()) -> () {}
+    extern "rust-call" fn call(self, args: ()) -> () {}
 }
 struct Foo1;
-impl Fn() for Foo1 {
+impl FnOnce() for Foo1 {
     //~^ ERROR associated type bindings are not allowed here
-
-    extern "rust-call" fn call(&self, args: ()) -> () {}
+    extern "rust-call" fn call_once(self, args: ()) -> () {}
 }
 struct Bar;
 impl FnMut<()> for Bar {
     //~^ ERROR angle-bracket notation is not stable when used with the `Fn` family of traits
-    type Output = ();
-
     extern "rust-call" fn call_mut(&self, args: ()) -> () {}
 }
 struct Baz;
 impl FnOnce<()> for Baz {
     //~^ ERROR angle-bracket notation is not stable when used with the `Fn` family of traits
-    type Output = ();
-
     extern "rust-call" fn call_once(&self, args: ()) -> () {}
 }
 
index 35c551931366d28c732260ef2d523197a14c4759..6433255bd4d2fcb7e3dd05894e669f8a38b0b945 100644 (file)
@@ -35,5 +35,5 @@ fn main() {
 
     needs_fn(1);
     //~^ ERROR `core::ops::Fn<(isize,)>`
-    //~| ERROR `core::ops::Fn<(isize,)>`
+    //~| ERROR `core::ops::FnOnce<(isize,)>`
 }
index 838e65e1d0574718d893ed2856e2daab64c0d057..8e1e88a92e452c09d0200806c4bfe2cdc7386394 100644 (file)
@@ -17,9 +17,13 @@ fn apply<T, F>(t: T, f: F) where F: FnOnce(T) {
 }
 
 fn main() {
-    apply(&3, takes_mut); //~ ERROR (values differ in mutability)
     apply(&3, takes_imm);
+    apply(&3, takes_mut);
+    //~^ ERROR (values differ in mutability)
+    //~| ERROR (values differ in mutability)
 
     apply(&mut 3, takes_mut);
-    apply(&mut 3, takes_imm); //~ ERROR (values differ in mutability)
+    apply(&mut 3, takes_imm);
+    //~^ ERROR (values differ in mutability)
+    //~| ERROR (values differ in mutability)
 }
index 0f30243b39a1942ad54ddfa30fb7c05441d07498..1bd7b0aa1c27913f4b6537354d0022d9736fb83e 100644 (file)
@@ -8,9 +8,9 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// aux-build:issue-11680.rs
+// aux-build:issue_11680.rs
 
-extern crate "issue-11680" as other;
+extern crate issue_11680 as other;
 
 fn main() {
     let _b = other::Foo::Bar(1);
index 41cd38630013891204a37132626df3a426ed795e..f76d12d93fdf68cf9227aa2c3a5e97bb792861d9 100644 (file)
@@ -8,9 +8,9 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// aux-build:issue-12612-1.rs
+// aux-build:issue_12612_1.rs
 
-extern crate "issue-12612-1" as foo;
+extern crate issue_12612_1 as foo;
 
 use foo::bar;
 
index d7bb806999c74abe7291eac8f090a492a53ac417..3f994102a173e0853f052c0b7ba9f3d65e0864bc 100644 (file)
@@ -22,11 +22,11 @@ fn main() {
     //~| expected u8
     //~| found array of 1 elements
 
-    let local = [0];
+    let local: [u8; 1] = [0];
     let _v = &local as *mut u8;
     //~^ ERROR mismatched types
     //~| expected `*mut u8`
-    //~| found `&[_; 1]`
+    //~| found `&[u8; 1]`
     //~| expected u8,
     //~| found array of 1 elements
 }
index 8f79022405ebe40139c5784530c59061018c5bfe..3853434e128ebd0b9465747277150ddf0c9fc41b 100644 (file)
@@ -16,11 +16,10 @@ struct Debuger<T> {
     x: T
 }
 
-impl<T: fmt::Debug> ops::Fn<(),> for Debuger<T> {
+impl<T: fmt::Debug> ops::FnOnce<(),> for Debuger<T> {
     type Output = ();
-
-    fn call(&self, _args: ()) {
-//~^ ERROR `call` has an incompatible type for trait: expected "rust-call" fn, found "Rust" fn
+    fn call_once(self, _args: ()) {
+//~^ ERROR `call_once` has an incompatible type for trait: expected "rust-call" fn, found "Rust" fn
         println!("{:?}", self.x);
     }
 }
index 6d2cfcab04e36aa757cf40418f7127e917453590..a4e0f69b63b39e0b55c2353ca65c1d95221c6180 100644 (file)
@@ -19,8 +19,7 @@ fn foo(value: *const X) -> *const X {
 }
 
 static foo: *const Y::X = Y::foo(Y::x as *const Y::X);
-//~^ ERROR cannot refer to other statics by value
-//~| ERROR the trait `core::marker::Sync` is not implemented for the type
+//~^ ERROR the trait `core::marker::Sync` is not implemented for the type
 //~| ERROR function calls in statics are limited to struct and enum constructors
 
 fn main() {}
index 67fcd820429ce5d6f309f525de8dc200f7f10501..cadf602a4cfc4aa962c34d062c130b721c7c7610 100644 (file)
@@ -8,9 +8,9 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// aux-build:issue-16725.rs
+// aux-build:issue_16725.rs
 
-extern crate "issue-16725" as foo;
+extern crate issue_16725 as foo;
 
 fn main() {
     unsafe { foo::bar(); }
index a9af30a3ff03db38ad4de825081c1754b1df4bac..021edbee566ba526514ac87f515df1bb23c716fa 100644 (file)
@@ -8,9 +8,9 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// aux-build:issue-17718-const-privacy.rs
+// aux-build:issue_17718_const_privacy.rs
 
-extern crate "issue-17718-const-privacy" as other;
+extern crate issue_17718_const_privacy as other;
 
 use a::B; //~ ERROR: const `B` is private
 use other::{
index e4bedbbb7e1e54d4b4c25f718304954a0f82b4a3..fe427e02451af6a0587f2c7ae49cfc2f98dfa75e 100644 (file)
 struct Foo;
 
 impl<'a, T> Fn<(&'a T,)> for Foo {
+  extern "rust-call" fn call(&self, (_,): (T,)) {}
+  //~^ ERROR: has an incompatible type for trait: expected &-ptr
+}
+
+impl<'a, T> FnMut<(&'a T,)> for Foo {
+  extern "rust-call" fn call_mut(&mut self, (_,): (T,)) {}
+  //~^ ERROR: has an incompatible type for trait: expected &-ptr
+}
+
+impl<'a, T> FnOnce<(&'a T,)> for Foo {
   type Output = ();
 
-  extern "rust-call" fn call(&self, (_,): (T,)) {}
+  extern "rust-call" fn call_once(self, (_,): (T,)) {}
   //~^ ERROR: has an incompatible type for trait: expected &-ptr
 }
 
index 05485008e51fddabce97136adf959f142d0fb3cf..2bce838c1cfdc926bc32f1643b67666322a16a71 100644 (file)
@@ -8,9 +8,9 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// aux-build:issue-21202.rs
+// aux-build:issue_21202.rs
 
-extern crate "issue-21202" as crate1;
+extern crate issue_21202 as crate1;
 
 use crate1::A;
 
diff --git a/src/test/compile-fail/issue-5543.rs b/src/test/compile-fail/issue-5543.rs
deleted file mode 100644 (file)
index c27362e..0000000
+++ /dev/null
@@ -1,19 +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.
-
-trait Foo { fn foo(&self) {} }
-impl Foo for u8 {}
-
-fn main() {
-    // FIXME (#22405): Replace `Box::new` with `box` here when/if possible.
-    let r: Box<Foo> = Box::new(5);
-    let _m: Box<Foo> = r as Box<Foo>;
-    //~^ ERROR `core::marker::Sized` is not implemented for the type `Foo`
-}
index dffc8fa2abd70d95def12e4df2eb40fdf247cea3..71494fd5f38dcef2116756b89e57a7c6edabdb7f 100644 (file)
@@ -28,6 +28,7 @@ fn f<T>(val: T) {
     let a = &t as &Gettable<T>;
     //~^ ERROR the trait `core::marker::Send` is not implemented
     //~^^ ERROR the trait `core::marker::Copy` is not implemented
+    //~^^^ ERROR the parameter type `T` may not live long enough
 }
 
 fn g<T>(val: T) {
index 13ee3f163616e8ccf207d9f283bed3fbebd30a4b..ba1b7f03b0f419b2fe15570b7594b77bf4a93f7d 100644 (file)
@@ -86,6 +86,6 @@ fn f() {}
 }
 
 pub fn foo() {
-    let a = &1 as &inner::Trait;
+    let a: &inner::Trait = &1_isize;
     a.f();
 }
diff --git a/src/test/compile-fail/lint-unnecessary-casts.rs b/src/test/compile-fail/lint-unnecessary-casts.rs
deleted file mode 100644 (file)
index b3cf825..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-// Copyright 2013 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.
-
-#![forbid(unused_typecasts)]
-
-fn foo_i32(_: i32) {}
-
-fn foo_u64(a: u64) {
-    let b: i32 = a as i32;
-    foo_i32(b as i32); //~ ERROR: unnecessary type cast
-}
-
-fn main() {
-    let x: u64 = 1;
-    let y: u64 = x as u64; //~ ERROR: unnecessary type cast
-    foo_u64(y as u64); //~ ERROR: unnecessary type cast
-}
index ada0cd2bc98f82cf035e817aa62697cebecdb9af..854c51d0769e71bfb6f31bcd8a8d21cc2fdd17eb 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// aux-build:lint-unused-extern-crate.rs
+// aux-build:lint_unused_extern_crate.rs
 
 #![deny(unused_extern_crates)]
 #![allow(unused_variables)]
 
 extern crate libc; //~ ERROR: unused extern crate
 
-extern crate "collections" as collecs; // no error, it is used
+extern crate collections as collecs; // no error, it is used
 
 extern crate rand; // no error, the use marks it as used
                    // even if imported objects aren't used
 
-extern crate "lint-unused-extern-crate" as other; // no error, the use * marks it as used
+extern crate lint_unused_extern_crate as other; // no error, the use * marks it as used
 
 #[allow(unused_imports)]
 use rand::isaac::IsaacRng;
index ac4b8a5f3090b09102e7452c2af3277ebe1b339c..0fee48a8c6c662ddeda75093ea52daf124096aae 100644 (file)
@@ -10,7 +10,7 @@
 
 #![deny(unused_variables)]
 #![deny(unused_assignments)]
-#![allow(dead_code, non_camel_case_types)]
+#![allow(dead_code, non_camel_case_types, trivial_numeric_casts)]
 
 fn f1(x: isize) {
     //~^ ERROR unused variable: `x`
index 976717249e8eb2400fe6e307b625bd0fc8e73e18..5a8772d61425fcb9176c7c69abe6368a900c34c1 100644 (file)
@@ -12,6 +12,7 @@
 
 #![feature(rustc_attrs)]
 #![allow(dead_code)]
+#![allow(trivial_casts)]
 
 trait Bar {
     fn bar(self);
index 61752e62abdefe90e80100478f48b9f6c5246bba..77ac97bc8b89951427bf7aaa9d69d0e45675f55a 100644 (file)
@@ -18,13 +18,18 @@ struct S {
 }
 
 impl FnMut<(isize,)> for S {
-    type Output = isize;
-
     extern "rust-call" fn call_mut(&mut self, (z,): (isize,)) -> isize {
         self.x * self.y * z
     }
 }
 
+impl FnOnce<(isize,)> for S {
+    type Output = isize;
+    extern "rust-call" fn call_once(mut self, (z,): (isize,)) -> isize {
+        self.call_mut((z,))
+    }
+}
+
 fn main() {
     let mut s = S {
         x: 3,
index c4019fa22097a92391cb533d7fd144df0101eefa..ea47d676412098c04e54399afc0a05d7187a7be7 100644 (file)
@@ -18,12 +18,16 @@ struct S {
 }
 
 impl FnMut<isize> for S {
-    type Output = isize;
     extern "rust-call" fn call_mut(&mut self, z: isize) -> isize {
         self.x + self.y + z
     }
 }
 
+impl FnOnce<isize> for S {
+    type Output = isize;
+    extern "rust-call" fn call_once(mut self, z: isize) -> isize { self.call_mut(z) }
+}
+
 fn main() {
     let mut s = S {
         x: 1,
index a7f6a514b96af53082fcc7d33396c0d7c0b25061..4ca37fc2ad209f6fd1eaab56f01bf0e80b156759 100644 (file)
@@ -8,9 +8,9 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// aux-build:privacy-tuple-struct.rs
+// aux-build:privacy_tuple_struct.rs
 
-extern crate "privacy-tuple-struct" as other;
+extern crate privacy_tuple_struct as other;
 
 mod a {
     pub struct A(());
@@ -101,30 +101,30 @@ fn xcrate() {
     let c = other::C(2, 3); //~ ERROR: cannot invoke tuple struct constructor
     let d = other::D(4);
 
-    let other::A(()) = a; //~ ERROR: field #1 of struct `privacy-tuple-struct::A` is private
+    let other::A(()) = a; //~ ERROR: field #1 of struct `privacy_tuple_struct::A` is private
     let other::A(_) = a;
     match a { other::A(()) => {} }
-    //~^ ERROR: field #1 of struct `privacy-tuple-struct::A` is private
+    //~^ ERROR: field #1 of struct `privacy_tuple_struct::A` is private
     match a { other::A(_) => {} }
 
     let other::B(_) = b;
-    let other::B(_b) = b; //~ ERROR: field #1 of struct `privacy-tuple-struct::B` is private
+    let other::B(_b) = b; //~ ERROR: field #1 of struct `privacy_tuple_struct::B` is private
     match b { other::B(_) => {} }
     match b { other::B(_b) => {} }
-    //~^ ERROR: field #1 of struct `privacy-tuple-struct::B` is private
+    //~^ ERROR: field #1 of struct `privacy_tuple_struct::B` is private
     match b { other::B(1) => {} other::B(_) => {} }
-    //~^ ERROR: field #1 of struct `privacy-tuple-struct::B` is private
+    //~^ ERROR: field #1 of struct `privacy_tuple_struct::B` is private
 
     let other::C(_, _) = c;
     let other::C(_a, _) = c;
-    let other::C(_, _b) = c; //~ ERROR: field #2 of struct `privacy-tuple-struct::C` is private
-    let other::C(_a, _b) = c; //~ ERROR: field #2 of struct `privacy-tuple-struct::C` is private
+    let other::C(_, _b) = c; //~ ERROR: field #2 of struct `privacy_tuple_struct::C` is private
+    let other::C(_a, _b) = c; //~ ERROR: field #2 of struct `privacy_tuple_struct::C` is private
     match c { other::C(_, _) => {} }
     match c { other::C(_a, _) => {} }
     match c { other::C(_, _b) => {} }
-    //~^ ERROR: field #2 of struct `privacy-tuple-struct::C` is private
+    //~^ ERROR: field #2 of struct `privacy_tuple_struct::C` is private
     match c { other::C(_a, _b) => {} }
-    //~^ ERROR: field #2 of struct `privacy-tuple-struct::C` is private
+    //~^ ERROR: field #2 of struct `privacy_tuple_struct::C` is private
 
     let other::D(_) = d;
     let other::D(_d) = d;
index 1705cfec6e2beba63ac0b9a55ea012cd9fe783c7..82d05c5d716aabe1238e3f95d3f0faf085ecddd2 100644 (file)
@@ -8,11 +8,11 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// aux-build:regions-bounded-method-type-parameters-cross-crate-lib.rs
+// aux-build:regions_bounded_method_type_parameters_cross_crate_lib.rs
 
 // Check explicit region bounds on methods in the cross crate case.
 
-extern crate "regions-bounded-method-type-parameters-cross-crate-lib" as lib;
+extern crate regions_bounded_method_type_parameters_cross_crate_lib as lib;
 
 use lib::Inv;
 use lib::MaybeOwned;
index f3b5ccabe79eb7afef291eea61b5b03b2e599f17..253132e5f07d02ed93ea98fcb613cb440934a750 100644 (file)
@@ -24,6 +24,7 @@ impl<'a, T> X for B<'a, T> {}
 
 fn f<'a, T, U>(v: Box<A<T>+'static>) -> Box<X+'static> {
     box B(&*v) as Box<X> //~ ERROR the parameter type `T` may not live long enough
+        //~^ ERROR the parameter type `T` may not live long enough
 }
 
 fn main() {}
index fc18095fc8336585a582c9e0d51edf0fa3ab340d..924044647d84a08473c547d8da2366d2bb8b34b6 100644 (file)
@@ -19,6 +19,7 @@
 fn make_object1<A:SomeTrait>(v: A) -> Box<SomeTrait+'static> {
     box v as Box<SomeTrait+'static>
         //~^ ERROR the parameter type `A` may not live long enough
+        //~^^ ERROR the parameter type `A` may not live long enough
 }
 
 fn make_object2<'a,A:SomeTrait+'a>(v: A) -> Box<SomeTrait+'a> {
@@ -28,6 +29,7 @@ fn make_object2<'a,A:SomeTrait+'a>(v: A) -> Box<SomeTrait+'a> {
 fn make_object3<'a,'b,A:SomeTrait+'a>(v: A) -> Box<SomeTrait+'b> {
     box v as Box<SomeTrait+'b>
         //~^ ERROR the parameter type `A` may not live long enough
+        //~^^ ERROR the parameter type `A` may not live long enough
 }
 
 fn main() { }
diff --git a/src/test/compile-fail/reject-specialized-drops-8142.rs b/src/test/compile-fail/reject-specialized-drops-8142.rs
new file mode 100644 (file)
index 0000000..30264c9
--- /dev/null
@@ -0,0 +1,79 @@
+// 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 8142: Test that Drop impls cannot be specialized beyond the
+// predicates attached to the struct/enum definition itself.
+
+#![feature(unsafe_destructor)]
+
+trait Bound { fn foo(&self) { } }
+struct K<'l1,'l2> { x: &'l1 i8, y: &'l2 u8 }
+struct L<'l1,'l2> { x: &'l1 i8, y: &'l2 u8 }
+struct M<'m> { x: &'m i8 }
+struct N<'n> { x: &'n i8 }
+struct O<To> { x: *const To }
+struct P<Tp> { x: *const Tp }
+struct Q<Tq> { x: *const Tq }
+struct R<Tr> { x: *const Tr }
+struct S<Ts:Bound> { x: *const Ts }
+struct T<'t,Ts:'t> { x: &'t Ts }
+struct U;
+struct V<Tva, Tvb> { x: *const Tva, y: *const Tvb }
+struct W<'l1, 'l2> { x: &'l1 i8, y: &'l2 u8 }
+
+#[unsafe_destructor]
+impl<'al,'adds_bnd:'al> Drop for K<'al,'adds_bnd> {                        // REJECT
+    //~^ ERROR The requirement `'adds_bnd : 'al` is added only by the Drop impl.
+    fn drop(&mut self) { } }
+
+#[unsafe_destructor]
+impl<'al,'adds_bnd>     Drop for L<'al,'adds_bnd> where 'adds_bnd:'al {    // REJECT
+    //~^ ERROR The requirement `'adds_bnd : 'al` is added only by the Drop impl.
+    fn drop(&mut self) { } }
+
+#[unsafe_destructor]
+impl<'ml>               Drop for M<'ml>         { fn drop(&mut self) { } } // ACCEPT
+
+#[unsafe_destructor]
+impl                    Drop for N<'static>     { fn drop(&mut self) { } } // REJECT
+//~^ ERROR Implementations of Drop cannot be specialized
+
+#[unsafe_destructor]
+impl<Cok_nobound> Drop for O<Cok_nobound> { fn drop(&mut self) { } } // ACCEPT
+
+#[unsafe_destructor]
+impl              Drop for P<i8>          { fn drop(&mut self) { } } // REJECT
+//~^ ERROR Implementations of Drop cannot be specialized
+
+#[unsafe_destructor]
+impl<Adds_bnd:Bound> Drop for Q<Adds_bnd> { fn drop(&mut self) { } } // REJECT
+//~^ ERROR The requirement `Adds_bnd : Bound` is added only by the Drop impl.
+
+#[unsafe_destructor]
+impl<'rbnd,Adds_rbnd:'rbnd> Drop for R<Adds_rbnd> { fn drop(&mut self) { } } // REJECT
+//~^ ERROR The requirement `Adds_rbnd : 'rbnd` is added only by the Drop impl.
+
+#[unsafe_destructor]
+impl<Bs:Bound>    Drop for S<Bs>          { fn drop(&mut self) { } } // ACCEPT
+
+#[unsafe_destructor]
+impl<'t,Bt:'t>    Drop for T<'t,Bt>       { fn drop(&mut self) { } } // ACCEPT
+
+impl              Drop for U              { fn drop(&mut self) { } } // ACCEPT
+
+#[unsafe_destructor]
+impl<One>         Drop for V<One,One>     { fn drop(&mut self) { } } // REJECT
+//~^ERROR Implementations of Drop cannot be specialized
+
+#[unsafe_destructor]
+impl<'lw>         Drop for W<'lw,'lw>     { fn drop(&mut self) { } } // REJECT
+//~^ERROR Implementations of Drop cannot be specialized
+
+pub fn main() { }
index 422cf630429ca85c835c3bb1f9ce309f8e9b388f..04a731e847ad3801eaa1dffe167266973c4dfe0c 100644 (file)
@@ -10,7 +10,7 @@
 
 // aux-build:pub_static_array.rs
 
-extern crate "pub_static_array" as array;
+extern crate pub_static_array as array;
 
 use array::ARRAY;
 
index 667e944f92c5627c5888f430fff88d75b61f37fa..a1b6b9a744c72c56da60b731c7d86318f7ea5044 100644 (file)
@@ -8,9 +8,9 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// aux-build:struct-field-privacy.rs
+// aux-build:struct_field_privacy.rs
 
-extern crate "struct-field-privacy" as xc;
+extern crate struct_field_privacy as xc;
 
 struct A {
     a: isize,
@@ -37,11 +37,11 @@ fn test(a: A, b: inner::A, c: inner::B, d: xc::A, e: xc::B) {
     c.a;
     c.b; //~ ERROR: field `b` of struct `inner::B` is private
 
-    d.a; //~ ERROR: field `a` of struct `struct-field-privacy::A` is private
+    d.a; //~ ERROR: field `a` of struct `struct_field_privacy::A` is private
     d.b;
 
     e.a;
-    e.b; //~ ERROR: field `b` of struct `struct-field-privacy::B` is private
+    e.b; //~ ERROR: field `b` of struct `struct_field_privacy::B` is private
 }
 
 fn main() {}
index 30648498ba88589db46d0e9b2b89a268083de59e..f987257d4eea93fc06ac32c7818c6e9d5dad25da 100644 (file)
@@ -8,9 +8,9 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// aux-build:struct-field-privacy.rs
+// aux-build:struct_field_privacy.rs
 
-extern crate "struct-field-privacy" as xc;
+extern crate struct_field_privacy as xc;
 
 use xc::B;
 
@@ -22,9 +22,9 @@ struct A {
 fn main () {
     // external crate struct
     let k = B {
-        aa: 20, //~ ERROR structure `struct-field-privacy::B` has no field named `aa`
+        aa: 20, //~ ERROR structure `struct_field_privacy::B` has no field named `aa`
         //~^ HELP did you mean `a`?
-        bb: 20, //~ ERROR structure `struct-field-privacy::B` has no field named `bb`
+        bb: 20, //~ ERROR structure `struct_field_privacy::B` has no field named `bb`
     };
     // local crate struct
     let l = A {
index 032deb2e017ac59bf01c2ee0caf050c8ddadba20..6050b549b656f5bf5f228686136a98ab014ed14b 100644 (file)
@@ -8,12 +8,12 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// aux-build:trait-safety-lib.rs
+// aux-build:trait_safety_lib.rs
 
 // Check that unsafe traits require unsafe impls and that inherent
 // impls cannot be unsafe.
 
-extern crate "trait-safety-lib" as lib;
+extern crate trait_safety_lib as lib;
 
 struct Bar;
 impl lib::Foo for Bar { //~ ERROR requires an `unsafe impl` declaration
diff --git a/src/test/compile-fail/trivial_casts.rs b/src/test/compile-fail/trivial_casts.rs
new file mode 100644 (file)
index 0000000..3119b86
--- /dev/null
@@ -0,0 +1,94 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Test the trivial_casts and trivial_numeric_casts lints. For each error we also
+// check that the cast can be done using just coercion.
+
+#![deny(trivial_casts, trivial_numeric_casts)]
+
+trait Foo {
+    fn foo(&self) {}
+}
+
+pub struct Bar;
+
+impl Foo for Bar {}
+
+pub fn main() {
+    // Numeric
+    let _ = 42_i32 as i32; //~ ERROR trivial numeric cast: `i32` as `i32`
+    let _: i32 = 42_i32;
+
+    let _ = 42_u8 as u8; //~ ERROR trivial numeric cast: `u8` as `u8`
+    let _: u8 = 42_u8;
+
+    // & to * pointers
+    let x: &u32 = &42;
+    let _ = x as *const u32; //~ERROR trivial cast: `&u32` as `*const u32`
+    let _: *const u32 = x;
+
+    let x: &mut u32 = &mut 42;
+    let _ = x as *mut u32; //~ERROR trivial cast: `&mut u32` as `*mut u32`
+    let _: *mut u32 = x;
+
+    // unsize array
+    let x: &[u32; 3] = &[42, 43, 44];
+    let _ = x as &[u32]; //~ERROR trivial cast: `&[u32; 3]` as `&[u32]`
+    let _ = x as *const [u32]; //~ERROR trivial cast: `&[u32; 3]` as `*const [u32]`
+    let _: &[u32] = x;
+    let _: *const [u32] = x;
+
+    let x: &mut [u32; 3] = &mut [42, 43, 44];
+    let _ = x as &mut [u32]; //~ERROR trivial cast: `&mut [u32; 3]` as `&mut [u32]`
+    let _ = x as *mut [u32]; //~ERROR trivial cast: `&mut [u32; 3]` as `*mut [u32]`
+    let _: &mut [u32] = x;
+    let _: *mut [u32] = x;
+
+    let x: Box<[u32; 3]> = Box::new([42, 43, 44]);
+    let _ = x as Box<[u32]>; //~ERROR trivial cast: `Box<[u32; 3]>` as `Box<[u32]>`
+    let x: Box<[u32; 3]> = Box::new([42, 43, 44]);
+    let _: Box<[u32]> = x;
+
+    // unsize trait
+    let x: &Bar = &Bar;
+    let _ = x as &Foo; //~ERROR trivial cast: `&Bar` as `&Foo`
+    let _ = x as *const Foo; //~ERROR trivial cast: `&Bar` as `*const Foo`
+    let _: &Foo = x;
+    let _: *const Foo = x;
+
+    let x: &mut Bar = &mut Bar;
+    let _ = x as &mut Foo; //~ERROR trivial cast: `&mut Bar` as `&mut Foo`
+    let _ = x as *mut Foo; //~ERROR trivial cast: `&mut Bar` as `*mut Foo`
+    let _: &mut Foo = x;
+    let _: *mut Foo = x;
+
+    let x: Box<Bar> = Box::new(Bar);
+    let _ = x as Box<Foo>; //~ERROR trivial cast: `Box<Bar>` as `Box<Foo>`
+    let x: Box<Bar> = Box::new(Bar);
+    let _: Box<Foo> = x;
+
+    // functions
+    fn baz(_x: i32) {}
+    let _ = &baz as &Fn(i32); //~ERROR trivial cast: `&fn(i32) {main::baz}` as `&core::ops::Fn(i32)`
+    let _: &Fn(i32) = &baz;
+    let x = |_x: i32| {};
+    let _ = &x as &Fn(i32); //~ERROR trivial cast
+    let _: &Fn(i32) = &x;
+}
+
+// subtyping
+pub fn test_subtyping<'a, 'b: 'a>(a: &'a Bar, b: &'b Bar) {
+    let _ = a as &'a Bar; //~ERROR trivial cast
+    let _: &'a Bar = a;
+    let _ = b as &'a Bar; //~ERROR trivial cast
+    let _: &'a Bar = b;
+    let _ = b as &'b Bar; //~ERROR trivial cast
+    let _: &'b Bar = b;
+}
index 8ff514e04e360fbcef36cf6b39a4d61089b44214..8cc531625d17956c0d01223736884c2601774dc1 100644 (file)
@@ -20,7 +20,7 @@ fn add(&self, other: &i32) -> i32 { *self + *other }
 }
 
 fn main() {
-    let x = 5;
+    let x: i32 = 5;
     let y = x as MyAdd<i32>;
     //~^ ERROR as `MyAdd<i32>`
 }
index 3a29bb9c2277cfe0395c11e1ee89b0c9fb6583a0..7d25c04882f24e0a459ab38aaabaf73c2e6edabe 100644 (file)
@@ -8,14 +8,14 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// aux-build:typeck-default-trait-impl-cross-crate-coherence-lib.rs
+// aux-build:typeck_default_trait_impl_cross_crate_coherence_lib.rs
 
 // Test that we do not consider associated types to be sendable without
 // some applicable trait bound (and we don't ICE).
 
 #![feature(optin_builtin_traits)]
 
-extern crate "typeck-default-trait-impl-cross-crate-coherence-lib" as lib;
+extern crate typeck_default_trait_impl_cross_crate_coherence_lib as lib;
 
 use lib::DefaultedTrait;
 
index 92e6affa4c2027f4dd28f9fa80664a3c9cf96c73..93498ac7f83514c1768d1babc95dcd640c3435e2 100644 (file)
 struct S;
 
 impl FnMut<(isize,)> for S {
-    type Output = isize;
-
     extern "rust-call" fn call_mut(&mut self, (x,): (isize,)) -> isize {
         x * x
     }
 }
 
+impl FnOnce<(isize,)> for S {
+    type Output = isize;
+
+    extern "rust-call" fn call_once(mut self, args: (isize,)) -> isize { self.call_mut(args) }
+}
+
 fn call_it<F:Fn(isize)->isize>(f: &F, x: isize) -> isize {
     f.call((x,))
 }
@@ -33,5 +37,4 @@ fn call_it<F:Fn(isize)->isize>(f: &F, x: isize) -> isize {
 fn main() {
     let x = call_it(&S, 22);
     //~^ ERROR not implemented
-    //~| ERROR not implemented
 }
index 713b64b1349fcc5893ac455a2755aa9449a203ef..2dcd7a97d8977eec83fc37a53c8dd016bc3b31fa 100644 (file)
@@ -28,14 +28,19 @@ fn new(f: F) -> YCombinator<F,A,R> {
 }
 
 impl<A,R,F : FnMut(&mut FnMut(A) -> R, A) -> R> FnMut<(A,)> for YCombinator<F,A,R> {
-    type Output = R;
-
     extern "rust-call" fn call_mut(&mut self, (arg,): (A,)) -> R {
         (self.func)(self, arg)
             //~^ ERROR cannot borrow `*self` as mutable more than once at a time
     }
 }
 
+impl<A,R,F : FnMut(&mut FnMut(A) -> R, A) -> R> FnOnce<(A,)> for YCombinator<F,A,R> {
+    type Output = R;
+    extern "rust-call" fn call_once(mut self, args: (A,)) -> R {
+        self.call_mut(args)
+    }
+}
+
 fn main() {
     let mut counter = 0;
     let factorial = |recur: &mut FnMut(u32) -> u32, arg: u32| -> u32 {
index 23f7ee2b0101d78cca2d2db9fcaa4702ac8e33bd..dc7c70ba649d8b0524766893a060679a1714c511 100644 (file)
@@ -27,11 +27,15 @@ fn a() {
 }
 
 fn b() {
-    let y = call_it_mut(&mut square, 22); //~ ERROR not implemented
+    let y = call_it_mut(&mut square, 22);
+    //~^ ERROR not implemented
+    //~| ERROR not implemented
 }
 
 fn c() {
-    let z = call_it_once(square, 22); //~ ERROR not implemented
+    let z = call_it_once(square, 22);
+    //~^ ERROR not implemented
+    //~| ERROR not implemented
 }
 
 fn main() { }
index 40655f8a3cec4e0be973a4bc8cf76a2d2d0fd7b9..cdcb435b65a6acfcc8cdc3700d420022234385bb 100644 (file)
@@ -27,11 +27,15 @@ fn a() {
 }
 
 fn b() {
-    let y = call_it_mut(&mut square, 22); //~ ERROR not implemented
+    let y = call_it_mut(&mut square, 22);
+    //~^ ERROR not implemented
+    //~| ERROR not implemented
 }
 
 fn c() {
-    let z = call_it_once(square, 22); //~ ERROR not implemented
+    let z = call_it_once(square, 22);
+    //~^ ERROR not implemented
+    //~| ERROR not implemented
 }
 
 fn main() { }
index ebcbdbbc006df83585ba4d02dad8817285a1109d..150bf36dcc286db2befd582b8dd6fa055495e1b8 100644 (file)
@@ -28,11 +28,15 @@ fn a() {
 }
 
 fn b() {
-    let y = call_it_mut(&mut square, 22); //~ ERROR not implemented
+    let y = call_it_mut(&mut square, 22);
+    //~^ ERROR not implemented
+    //~| ERROR not implemented
 }
 
 fn c() {
-    let z = call_it_once(square, 22); //~ ERROR not implemented
+    let z = call_it_once(square, 22);
+    //~^ ERROR not implemented
+    //~| ERROR not implemented
 }
 
 fn main() { }
index ef991d8533737d646f9606ba53e4b89264e1db51..5983c83f8b401b59646632d17de96c19d0d6d3c4 100644 (file)
@@ -8,9 +8,9 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// aux-build:unreachable-variant.rs
+// aux-build:unreachable_variant.rs
 
-extern crate "unreachable-variant" as other;
+extern crate unreachable_variant as other;
 
 fn main() {
     let _x = other::super_sekrit::sooper_sekrit::baz; //~ ERROR is private
index 97e67cd2eae273b1e9b06c03ef53138059305e94..cac52306d6ae0e1a4d08dfd13763c4552f6099a7 100644 (file)
@@ -10,6 +10,8 @@
 
 // Issue #14893. Tests that casts from vectors don't behave strangely in the
 // presence of the `_` type shorthand notation.
+// Update: after a change to the way casts are done, we have more type information
+// around and so the errors here are no longer exactly the same.
 
 struct X {
     y: [u8; 2],
@@ -18,12 +20,14 @@ struct X {
 fn main() {
     let x1 = X { y: [0, 0] };
 
-    let p1: *const u8 = &x1.y as *const _;  //~ ERROR mismatched types
+    // No longer a type mismatch - the `_` can be fully resolved by type inference.
+    let p1: *const u8 = &x1.y as *const _;
     let t1: *const [u8; 2] = &x1.y as *const _;
     let h1: *const [u8; 2] = &x1.y as *const [u8; 2];
 
     let mut x1 = X { y: [0, 0] };
 
+    // This is still an error since we don't allow casts from &mut [T; n] to *mut T.
     let p1: *mut u8 = &mut x1.y as *mut _;  //~ ERROR mismatched types
     let t1: *mut [u8; 2] = &mut x1.y as *mut _;
     let h1: *mut [u8; 2] = &mut x1.y as *mut [u8; 2];
index 2305d7bc5c245039cc603c631ca2ddf6107d1807..766105881cedfca70391de16cf81e9011323f3a1 100644 (file)
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+// ignore-aarch64
 // min-lldb-version: 310
 
 // compile-flags:-g
index 424ba50e3c97836da80f1dbaae9e0a2386de9bdc..3c2e7f10d16116b1b9e8a51520ffc83a3ecb0deb 100644 (file)
 
 // ignore-windows failing on 64-bit bots FIXME #17638
 // ignore-lldb
+// ignore-aarch64
 
 // compile-flags:-g
 
 // gdb-command:run
 // gdb-command:next
-// gdb-check:[...]33[...]s
+// gdb-check:[...]34[...]s
 // gdb-command:continue
 
 #![omit_gdb_pretty_printer_section]
index bf26fc23d3c16a1607af005ebe04e6cb26aad378..d4cbd255e34c2861bcc35fee75c15dc6134a9038 100644 (file)
@@ -291,15 +291,15 @@ fn main() {
     let slice2 = &*vec2;
 
     // Trait Objects
-    let box_trait = (box 0) as Box<Trait1>;
-    let ref_trait = &0 as &Trait1;
-    let mut mut_int1 = 0;
+    let box_trait = (box 0_isize) as Box<Trait1>;
+    let ref_trait = &0_isize as &Trait1;
+    let mut mut_int1 = 0_isize;
     let mut_ref_trait = (&mut mut_int1) as &mut Trait1;
 
-    let generic_box_trait = (box 0) as Box<Trait2<i32, Mod1::Struct2>>;
-    let generic_ref_trait  = (&0) as &Trait2<Struct1, Struct1>;
+    let generic_box_trait = (box 0_isize) as Box<Trait2<i32, Mod1::Struct2>>;
+    let generic_ref_trait  = (&0_isize) as &Trait2<Struct1, Struct1>;
 
-    let mut generic_mut_ref_trait_impl = 0;
+    let mut generic_mut_ref_trait_impl = 0_isize;
     let generic_mut_ref_trait = (&mut generic_mut_ref_trait_impl) as
         &mut Trait2<Mod1::Mod2::Struct3, GenericStruct<usize, isize>>;
 
index d10337e768c71a06090136348d55510084fe5e0b..9e5fe4ab8a986e8b8b3068afb7192677ee6a6ee4 100644 (file)
@@ -11,6 +11,7 @@
 
 extern crate
     "foo"suffix //~ ERROR extern crate name with a suffix is illegal
+                //~^ WARNING: obsolete syntax
      as foo;
 
 extern
diff --git a/src/test/parse-fail/extern-crate-as-no-string-help.rs b/src/test/parse-fail/extern-crate-as-no-string-help.rs
deleted file mode 100644 (file)
index 5cc52f6..0000000
+++ /dev/null
@@ -1,15 +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.
-
-// Tests that the proper help is displayed in the error message
-
-extern crate foo as bar;
-//~^ ERROR expected `;`, found `as`
-//~^^ HELP perhaps you meant to enclose the crate name `foo` in a string?
index 24b978b0a21ffeb8597d8a8fd13eec017da226e3..1ff4368dac5e2fac4824caf06e11d4b2657266be 100644 (file)
@@ -11,4 +11,4 @@
 // Verifies that the expected token errors for `extern crate` are
 // raised
 
-extern crate foo {} //~ERROR expected `;`, found `{`
+extern crate foo {} //~ERROR expected one of `;` or `as`, found `{`
index 58cd19059c0d7ce63abea716c306fe555e48e323..c2ed10ce6a18746d07edd9bf7d11f44537459f6d 100644 (file)
@@ -3,7 +3,7 @@
 #[prelude_import]
 use std::prelude::v1::*;
 #[macro_use]
-extern crate "std" as std;
+extern crate std as std;
 // 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.
index 0a20300e4f4de797ebe8dbd3eccba7fd3ed28547..42b2fe806e95f605bbd91febc4a4737d8fa117e4 100644 (file)
@@ -21,5 +21,5 @@ fn foo<'a>(x: Box<Tr+ Sync + 'a>) -> Box<Tr+ Sync + 'a> { x }
 fn main() {
     let x: Box<Tr+ Sync>;
 
-    Box::new(1) as Box<Tr+ Sync>;
+    Box::new(1isize) as Box<Tr+ Sync>;
 }
index 965b1760f1ff16f7c4b1cd21464d14419b7a04db..bce78e4f4c1f8cff3ce5d94c870e981bbb278ce8 100644 (file)
@@ -13,6 +13,6 @@
 #![feature(asm)]
 
 #[cfg(foo = r#"just parse this"#)]
-extern crate r##"blah"## as blah;
+extern crate blah as blah;
 
 fn main() { unsafe { asm!(r###"blah"###); } }
index f81d4803f8fa491f686137f91f428b85dc5e507a..474a6782b616b3af1ea845be56b948c662cda0b6 100644 (file)
@@ -16,5 +16,5 @@ impl Foo for uint {}
 
 pub fn dummy() {
     // force the vtable to be created
-    let _x = &1 as &Foo;
+    let _x = &1u as &Foo;
 }
index 3d57a2263e1ef188994635c0ad1698b81b04d4db..2172ed888b1423c69ce20b32f0e8fff483660596 100644 (file)
@@ -12,4 +12,4 @@ all:
                | grep "invalid character.*in crate name:"
        cp foo.rs $(TMPDIR)/-foo.rs
        $(RUSTC) $(TMPDIR)/-foo.rs 2>&1 \
-               | grep "crate name cannot start with a hyphen:"
+               | grep "soon cannot contain hyphens:"
index 6a038927f4a486016b69128b6a1d48b0a4340e9d..0bec3af4273afad2819f79523f6bba194425dae8 100644 (file)
@@ -22,6 +22,6 @@ fn double(self: Box<uint>) -> uint { *self * 2 }
 }
 
 pub fn main() {
-    let x: Box<_> = box() (box 3 as Box<double>);
+    let x: Box<_> = box() (box 3u as Box<double>);
     assert_eq!(x.double(), 6);
 }
index a298a08a1b7a099bcce4a7e20e38168a0269a735..deb0c0d0dc0df884c4c0c2ba01d3df22e309b47e 100644 (file)
@@ -9,6 +9,6 @@
 // except according to those terms.
 
 pub fn main() {
-    let x = 3;
+    let x: int = 3;
     println!("&x={:x}", (&x as *const int as uint));
 }
index cbfe30906a73feb39506a09a6f187ef205ec1431..9ad4f6b9d75c732c384efa422ee0cfb73575b6e5 100644 (file)
@@ -8,11 +8,11 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// aux-build:coherence-lib.rs
+// aux-build:coherence_lib.rs
 
 // pretty-expanded FIXME #23616
 
-extern crate "coherence-lib" as lib;
+extern crate coherence_lib as lib;
 use lib::Remote1;
 
 pub struct BigInt;
index 8537c1bb002896115ab41d33fdcc6a4c06582168..ac4b98cfc8c8186c5f4bf094fcf423fe7068dba5 100644 (file)
@@ -8,11 +8,11 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// aux-build:coherence-lib.rs
+// aux-build:coherence_lib.rs
 
 // pretty-expanded FIXME #23616
 
-extern crate "coherence-lib" as lib;
+extern crate coherence_lib as lib;
 use lib::Remote1;
 
 pub struct BigInt;
index 2f2709698a040cfa82b57398e063f7eb85893c3a..32743aafa823669a2280ad55a8016d54ee6d9fe8 100644 (file)
@@ -8,11 +8,11 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// aux-build:coherence-lib.rs
+// aux-build:coherence_lib.rs
 
 // pretty-expanded FIXME #23616
 
-extern crate "coherence-lib" as lib;
+extern crate coherence_lib as lib;
 use lib::Remote1;
 
 pub trait Local {
index 7bb3a01ccf8f763098a1bb47d41452aa2bc974e7..890470d8ac242e5f51f721b1d889774a8c42b504 100644 (file)
@@ -8,11 +8,11 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// aux-build:coherence-lib.rs
+// aux-build:coherence_lib.rs
 
 // pretty-expanded FIXME #23616
 
-extern crate "coherence-lib" as lib;
+extern crate coherence_lib as lib;
 use lib::Remote;
 
 struct Foo<T>(T);
index 4d76f482b4e5abff92f2316921af6a8e07bd735b..31f6c9af0202433693e8ff734c0901a6ac18e5b5 100644 (file)
@@ -8,14 +8,14 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// aux-build:coherence-lib.rs
+// aux-build:coherence_lib.rs
 
 // Test that it's ok for T to appear first in the self-type, as long
 // as it's covered somewhere.
 
 // pretty-expanded FIXME #23616
 
-extern crate "coherence-lib" as lib;
+extern crate coherence_lib as lib;
 use lib::{Remote,Pair};
 
 pub struct Cover<T>(T);
index 685432ad1cff4c9c7fb3a36561b844ff29fa0164..ccda8440ea228d5bad2fd424cdd407bbd8bf31f6 100644 (file)
@@ -8,14 +8,14 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// aux-build:coherence-lib.rs
+// aux-build:coherence_lib.rs
 
 // Test that it's ok for T to appear second in the self-type, as long
 // as it's covered somewhere.
 
 // pretty-expanded FIXME #23616
 
-extern crate "coherence-lib" as lib;
+extern crate coherence_lib as lib;
 use lib::{Remote,Pair};
 
 pub struct Cover<T>(T);
index e807b6ca3bc1132d58976be5ecc9e292d038955c..04a6cd58827893c14d6e95f2612a0df543e95248 100644 (file)
@@ -8,11 +8,11 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// aux-build:coherence-lib.rs
+// aux-build:coherence_lib.rs
 
 // pretty-expanded FIXME #23616
 
-extern crate "coherence-lib" as lib;
+extern crate coherence_lib as lib;
 use lib::Remote1;
 
 struct Foo<T>(T);
index 3cb3efe8e7bf6fb9bb029c7556a6c7d5cd37fd37..8a3301dee273dbf32ef931a6b984a0d5d59ad309 100644 (file)
@@ -8,11 +8,11 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// aux-build:coherence-lib.rs
+// aux-build:coherence_lib.rs
 
 // pretty-expanded FIXME #23616
 
-extern crate "coherence-lib" as lib;
+extern crate coherence_lib as lib;
 use lib::Remote1;
 
 struct Foo<T>(T);
index 172066abb2b848ed145583b726e3cad165a228d4..21faa30245d9a55549eb559d590f0d968994150b 100644 (file)
@@ -8,11 +8,11 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// aux-build:coherence-lib.rs
+// aux-build:coherence_lib.rs
 
 // pretty-expanded FIXME #23616
 
-extern crate "coherence-lib" as lib;
+extern crate coherence_lib as lib;
 use lib::Remote;
 
 struct Local;
index afdea4e6b7f13abd11a84eab4ad97a2f2ffed8a5..5fd3e8ca86ef791d8e0eb740c1e8df959c44b096 100644 (file)
@@ -8,11 +8,11 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// aux-build:coherence-lib.rs
+// aux-build:coherence_lib.rs
 
 // pretty-expanded FIXME #23616
 
-extern crate "coherence-lib" as lib;
+extern crate coherence_lib as lib;
 use lib::Remote;
 
 struct Local<T>(T);
diff --git a/src/test/run-pass/deriving-associated-types.rs b/src/test/run-pass/deriving-associated-types.rs
new file mode 100644 (file)
index 0000000..59eb550
--- /dev/null
@@ -0,0 +1,210 @@
+// 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(core, debug_builders)]
+
+pub trait DeclaredTrait {
+    type Type;
+}
+
+impl DeclaredTrait for i32 {
+    type Type = i32;
+}
+
+pub trait WhereTrait {
+    type Type;
+}
+
+impl WhereTrait for i32 {
+    type Type = i32;
+}
+
+// Make sure we don't add a bound that just shares a name with an associated
+// type.
+pub mod module {
+    pub type Type = i32;
+}
+
+#[derive(PartialEq, Debug)]
+struct PrivateStruct<T>(T);
+
+#[derive(PartialEq, Debug)]
+struct TupleStruct<A, B: DeclaredTrait, C>(
+    module::Type,
+    Option<module::Type>,
+    A,
+    PrivateStruct<A>,
+    B,
+    B::Type,
+    Option<B::Type>,
+    <B as DeclaredTrait>::Type,
+    Option<<B as DeclaredTrait>::Type>,
+    C,
+    C::Type,
+    Option<C::Type>,
+    <C as WhereTrait>::Type,
+    Option<<C as WhereTrait>::Type>,
+    <i32 as DeclaredTrait>::Type,
+) where C: WhereTrait;
+
+#[derive(PartialEq, Debug)]
+pub struct Struct<A, B: DeclaredTrait, C> where C: WhereTrait {
+    m1: module::Type,
+    m2: Option<module::Type>,
+    a1: A,
+    a2: PrivateStruct<A>,
+    b: B,
+    b1: B::Type,
+    b2: Option<B::Type>,
+    b3: <B as DeclaredTrait>::Type,
+    b4: Option<<B as DeclaredTrait>::Type>,
+    c: C,
+    c1: C::Type,
+    c2: Option<C::Type>,
+    c3: <C as WhereTrait>::Type,
+    c4: Option<<C as WhereTrait>::Type>,
+    d: <i32 as DeclaredTrait>::Type,
+}
+
+#[derive(PartialEq, Debug)]
+enum Enum<A, B: DeclaredTrait, C> where C: WhereTrait {
+    Unit,
+    Seq(
+        module::Type,
+        Option<module::Type>,
+        A,
+        PrivateStruct<A>,
+        B,
+        B::Type,
+        Option<B::Type>,
+        <B as DeclaredTrait>::Type,
+        Option<<B as DeclaredTrait>::Type>,
+        C,
+        C::Type,
+        Option<C::Type>,
+        <C as WhereTrait>::Type,
+        Option<<C as WhereTrait>::Type>,
+        <i32 as DeclaredTrait>::Type,
+    ),
+    Map {
+        m1: module::Type,
+        m2: Option<module::Type>,
+        a1: A,
+        a2: PrivateStruct<A>,
+        b: B,
+        b1: B::Type,
+        b2: Option<B::Type>,
+        b3: <B as DeclaredTrait>::Type,
+        b4: Option<<B as DeclaredTrait>::Type>,
+        c: C,
+        c1: C::Type,
+        c2: Option<C::Type>,
+        c3: <C as WhereTrait>::Type,
+        c4: Option<<C as WhereTrait>::Type>,
+        d: <i32 as DeclaredTrait>::Type,
+    },
+}
+
+fn main() {
+    let e: TupleStruct<
+        i32,
+        i32,
+        i32,
+    > = TupleStruct(
+        0,
+        None,
+        0,
+        PrivateStruct(0),
+        0,
+        0,
+        None,
+        0,
+        None,
+        0,
+        0,
+        None,
+        0,
+        None,
+        0,
+    );
+    assert_eq!(e, e);
+
+    let e: Struct<
+        i32,
+        i32,
+        i32,
+    > = Struct {
+        m1: 0,
+        m2: None,
+        a1: 0,
+        a2: PrivateStruct(0),
+        b: 0,
+        b1: 0,
+        b2: None,
+        b3: 0,
+        b4: None,
+        c: 0,
+        c1: 0,
+        c2: None,
+        c3: 0,
+        c4: None,
+        d: 0,
+    };
+    assert_eq!(e, e);
+
+    let e = Enum::Unit::<i32, i32, i32>;
+    assert_eq!(e, e);
+
+    let e: Enum<
+        i32,
+        i32,
+        i32,
+    > = Enum::Seq(
+        0,
+        None,
+        0,
+        PrivateStruct(0),
+        0,
+        0,
+        None,
+        0,
+        None,
+        0,
+        0,
+        None,
+        0,
+        None,
+        0,
+    );
+    assert_eq!(e, e);
+
+    let e: Enum<
+        i32,
+        i32,
+        i32,
+    > = Enum::Map {
+        m1: 0,
+        m2: None,
+        a1: 0,
+        a2: PrivateStruct(0),
+        b: 0,
+        b1: 0,
+        b2: None,
+        b3: 0,
+        b4: None,
+        c: 0,
+        c1: 0,
+        c2: None,
+        c3: 0,
+        c4: None,
+        d: 0,
+    };
+    assert_eq!(e, e);
+}
index 7bbed563a99fe9dde207298ed904a2546da2008d..198745f5b19fe7a11a96e5949d447057c920e124 100644 (file)
@@ -8,10 +8,10 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#![feature(std_misc, libc)]
+#![feature(libc)]
 
 extern crate libc;
-use std::thread::Thread;
+use std::thread;
 
 mod rustrt {
     extern crate libc;
@@ -42,9 +42,9 @@ fn count(n: libc::uintptr_t) -> libc::uintptr_t {
 pub fn main() {
     // Make sure we're on a task with small Rust stacks (main currently
     // has a large stack)
-    let _t = Thread::spawn(move|| {
+    thread::scoped(move|| {
         let result = count(1000);
         println!("result = {}", result);
         assert_eq!(result, 1000);
-    });
+    }).join();
 }
diff --git a/src/test/run-pass/infer-container-across-object-cast.rs b/src/test/run-pass/infer-container-across-object-cast.rs
deleted file mode 100644 (file)
index 7347ded..0000000
+++ /dev/null
@@ -1,61 +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.
-
-// Given `<expr> as Box<Trait>`, we should be able to infer that a
-// `Box<_>` is the expected type.
-
-// pretty-expanded FIXME #23616
-
-trait Foo { fn foo(&self) -> u32; }
-impl Foo for u32 { fn foo(&self) -> u32 { *self } }
-
-// (another impl to ensure trait-matching cannot just choose from a singleton set)
-impl Foo for  () { fn foo(&self) -> u32 { -176 } }
-
-trait Boxed { fn make() -> Self; }
-impl Boxed for Box<u32> { fn make() -> Self { Box::new(7) } }
-
-// (another impl to ensure trait-matching cannot just choose from a singleton set)
-impl Boxed for () { fn make() -> Self { () } }
-
-fn boxed_foo() {
-    let b7 = Boxed::make() as Box<Foo>;
-    assert_eq!(b7.foo(), 7);
-}
-
-trait Refed<'a,T> { fn make(&'a T) -> Self; }
-impl<'a> Refed<'a, u32> for &'a u32 { fn make(x: &'a u32) -> Self { x } }
-
-// (another impl to ensure trait-matching cannot just choose from a singleton set)
-impl<'a,'b> Refed<'a, ()> for &'b () { fn make(_: &'a ()) -> Self { static U: () = (); &U } }
-
-fn refed_foo() {
-    let a = 8;
-    let b7 = Refed::make(&a) as &Foo;
-    assert_eq!(b7.foo(), 8);
-}
-
-fn check_subtyping_works() {
-    fn inner<'short, 'long:'short>(_s: &'short u32,
-                                   l: &'long u32) -> &'short (Foo+'short) {
-        Refed::make(l) as &Foo
-    }
-
-    let a = 9;
-    let b = 10;
-    let r = inner(&b, &a);
-    assert_eq!(r.foo(), 9);
-}
-
-pub fn main() {
-    boxed_foo();
-    refed_foo();
-    check_subtyping_works();
-}
index 8a23e43d59ed08a6ac4ce1a855f5bf13b9385c93..bdf8f84a9597d711411dce041997ef19ee20ff04 100644 (file)
@@ -8,13 +8,13 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// aux-build:issue-12612-1.rs
-// aux-build:issue-12612-2.rs
+// aux-build:issue_12612_1.rs
+// aux-build:issue_12612_2.rs
 
 // pretty-expanded FIXME #23616
 
-extern crate "issue-12612-1" as foo;
-extern crate "issue-12612-2" as bar;
+extern crate issue_12612_1 as foo;
+extern crate issue_12612_2 as bar;
 
 mod test {
     use bar::baz;
index cd5da3844e10f2007491c5e8e892c4b7e4dcc876..11219b04f2b97003e55434f34b4f1312af2fe1c2 100644 (file)
@@ -14,7 +14,6 @@
 struct Foo<T>(T);
 
 impl<T: Copy> Fn<()> for Foo<T> {
-    type Output = T;
     extern "rust-call" fn call(&self, _: ()) -> T {
       match *self {
         Foo(t) => t
@@ -22,6 +21,20 @@ extern "rust-call" fn call(&self, _: ()) -> T {
     }
 }
 
+impl<T: Copy> FnMut<()> for Foo<T> {
+    extern "rust-call" fn call_mut(&mut self, _: ()) -> T {
+        self.call(())
+    }
+}
+
+impl<T: Copy> FnOnce<()> for Foo<T> {
+    type Output = T;
+
+    extern "rust-call" fn call_once(self, _: ()) -> T {
+        self.call(())
+    }
+}
+
 fn main() {
   let t: u8 = 1;
   println!("{}", Foo(t)());
index be13d0bc80c4b7b249ea3df136b3092731514f96..ec482a776def32f4e3bf940b0a09272130179b91 100644 (file)
@@ -17,10 +17,18 @@ trait Foo { fn dummy(&self) { }}
 struct Bar;
 
 impl<'a> std::ops::Fn<(&'a (Foo+'a),)> for Bar {
-    type Output = ();
     extern "rust-call" fn call(&self, _: (&'a Foo,)) {}
 }
 
+impl<'a> std::ops::FnMut<(&'a (Foo+'a),)> for Bar {
+    extern "rust-call" fn call_mut(&mut self, a: (&'a Foo,)) { self.call(a) }
+}
+
+impl<'a> std::ops::FnOnce<(&'a (Foo+'a),)> for Bar {
+    type Output = ();
+    extern "rust-call" fn call_once(self, a: (&'a Foo,)) { self.call(a) }
+}
+
 struct Baz;
 
 impl Foo for Baz {}
index d6fdd9f230ad4f6c89cedf24d11656d456e3317f..5accaf363490fae2b1e45692d78e2e9156ef7941 100644 (file)
@@ -36,9 +36,21 @@ fn find<T>(&self) -> Option<T> {
 }
 
 impl<'b> Fn<(&'b mut (Response+'b),)> for SendFile {
+    extern "rust-call" fn call(&self, (_res,): (&'b mut (Response+'b),)) {}
+}
+
+impl<'b> FnMut<(&'b mut (Response+'b),)> for SendFile {
+    extern "rust-call" fn call_mut(&mut self, (_res,): (&'b mut (Response+'b),)) {
+        self.call((_res,))
+    }
+}
+
+impl<'b> FnOnce<(&'b mut (Response+'b),)> for SendFile {
     type Output = ();
 
-    extern "rust-call" fn call(&self, (_res,): (&'b mut (Response+'b),)) {}
+    extern "rust-call" fn call_once(self, (_res,): (&'b mut (Response+'b),)) {
+        self.call((_res,))
+    }
 }
 
 impl<Rq: Request, Rs: Response> Ingot<Rq, Rs> for HelloWorld {
index 7bfd8e0ab718942444aef42f8adf76889799e924..f30991a19635251797a88dc08e06e72980789f41 100644 (file)
@@ -87,12 +87,12 @@ fn main() {
     assert_eq!(cc().unwrap(), 3);
     assert_eq!(dd().unwrap(), 3);
 
-    let i = box 32 as Box<A>;
+    let i = box 32i as Box<A>;
     assert_eq!(i.aaa(), 3);
-    let i = box 32 as Box<A>;
+    let i = box 32i as Box<A>;
     assert_eq!(i.bbb(), 3);
-    let i = box 32 as Box<A>;
+    let i = box 32i as Box<A>;
     assert_eq!(i.ccc().unwrap(), 3);
-    let i = box 32 as Box<A>;
+    let i = box 32i as Box<A>;
     assert_eq!(i.ddd().unwrap(), 3);
 }
index 9b300deaa497ef99d649137277d0f6349041582c..265db3fe1336a6520a4d92dfd0e63e3c96c3f014 100644 (file)
@@ -25,7 +25,7 @@ fn do_something(&mut self) {}
 }
 
 
-struct Foo<B>(B);
+struct Foo<B: Bar>(B);
 
 #[unsafe_destructor]
 impl<B: Bar> Drop for Foo<B> {
index 6af07c422ef56baefcf2cde9d87d10f712f49e0a..e544585745de3dfc21839f252614879bc2e19d44 100644 (file)
@@ -18,7 +18,7 @@
 use serialize::{Encoder, Encodable};
 use serialize::json;
 
-struct Foo<T> {
+struct Foo<T: Encodable> {
     v: T,
 }
 
index 5270ef9268c596361fdb6370cfba8719796db2da..99ddaba4e5514513291796aa2d90198757bf776d 100644 (file)
 struct Foo { foo: u32 }
 
 impl FnMut<()> for Foo {
-    type Output = u32;
     extern "rust-call" fn call_mut(&mut self, _: ()) -> u32 { self.foo }
 }
 
-impl FnMut<(u32,)> for Foo {
+impl FnOnce<()> for Foo {
     type Output = u32;
+    extern "rust-call" fn call_once(mut self, _: ()) -> u32 { self.call_mut(()) }
+}
+
+/////////////////////////////////////////////////////////////////////////
+
+impl FnMut<(u32,)> for Foo {
     extern "rust-call" fn call_mut(&mut self, (x,): (u32,)) -> u32 { self.foo + x }
 }
 
-impl FnMut<(u32,u32)> for Foo {
+impl FnOnce<(u32,)> for Foo {
     type Output = u32;
+    extern "rust-call" fn call_once(mut self, args: (u32,)) -> u32 { self.call_mut(args) }
+}
+
+/////////////////////////////////////////////////////////////////////////
+
+impl FnMut<(u32,u32)> for Foo {
     extern "rust-call" fn call_mut(&mut self, (x, y): (u32, u32)) -> u32 { self.foo + x + y }
 }
 
+impl FnOnce<(u32,u32)> for Foo {
+    type Output = u32;
+    extern "rust-call" fn call_once(mut self, args: (u32,u32)) -> u32 { self.call_mut(args) }
+}
+
 fn main() {
     let mut f = box Foo { foo: 42 } as Box<FnMut() -> u32>;
     assert_eq!(f.call_mut(()), 42);
index 41d202c463503167f1a2bbd205e31cae936cb182..9442b039bc6cbecd1bc3573123e38f156c09d2a0 100644 (file)
 struct Foo;
 
 impl<'a> Fn<(&'a (),)> for Foo {
+    extern "rust-call" fn call(&self, (_,): (&(),)) {}
+}
+
+impl<'a> FnMut<(&'a (),)> for Foo {
+    extern "rust-call" fn call_mut(&mut self, (_,): (&(),)) {}
+}
+
+impl<'a> FnOnce<(&'a (),)> for Foo {
     type Output = ();
 
-    extern "rust-call" fn call(&self, (_,): (&(),)) {}
+    extern "rust-call" fn call_once(self, (_,): (&(),)) {}
 }
 
 fn main() {}
diff --git a/src/test/run-pass/issue-23037.rs b/src/test/run-pass/issue-23037.rs
new file mode 100644 (file)
index 0000000..5257daa
--- /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.
+
+#![feature(core)]
+
+use std::simd::i32x4;
+fn main() {
+    let foo = i32x4(1,2,3,4);
+    let bar = i32x4(40,30,20,10);
+    let baz = foo + bar;
+    assert!(baz.0 == 41 && baz.1 == 32 && baz.2 == 23 && baz.3 == 14);
+}
index 8d0e06549335c3595ce2d6aac589c6e8ec23f3a7..7ca0ee01015b89f2c0db75779ff2ee1bd6afe691 100644 (file)
@@ -162,7 +162,7 @@ pub fn receiver_terminate<T:Send>(p: *const packet<T>) {
         }
     }
 
-    pub struct send_packet<T> {
+    pub struct send_packet<T:Send> {
         p: Option<*const packet<T>>,
     }
 
@@ -192,7 +192,7 @@ pub fn send_packet<T:Send>(p: *const packet<T>) -> send_packet<T> {
         }
     }
 
-    pub struct recv_packet<T> {
+    pub struct recv_packet<T:Send> {
         p: Option<*const packet<T>>,
     }
 
index 9d5f8576c633ee83a31c6bf78f33778135c4cf83..08ee955cabbacd65e29a8300f9901f6f29f60b6b 100644 (file)
@@ -21,7 +21,7 @@ fn default_method<T: std::fmt::Debug>(&self, x: &T) {
 struct Y(int);
 
 #[derive(Debug)]
-struct Z<T> {
+struct Z<T: X+std::fmt::Debug> {
     x: T
 }
 
index 59bca87bed0b61a8432cf09be88ff86ebaf2ea17..54773d71cbec0464575cabb24c2ea131181cadab 100644 (file)
@@ -41,7 +41,7 @@ fn new(inner: &Inner) -> Outer {
 }
 
 pub fn main() {
-    let inner = 5;
+    let inner: int = 5;
     let outer = Outer::new(&inner as &Inner);
     outer.inner.print();
 }
index 669a5cdfe304a174fc77cd973eb3cd68fefdb19d..6e88379f9a41b2676b33eb65002d535cb57376a5 100644 (file)
@@ -21,7 +21,7 @@ fn dummy(&self) { }
     impl X for int {}
 
     pub struct Z<'a>(Enum<&'a (X+'a)>);
-    fn foo() { let x = 42; let z = Z(Enum::A(&x as &X)); let _ = z; }
+    fn foo() { let x: int = 42; let z = Z(Enum::A(&x as &X)); let _ = z; }
 }
 
 mod b {
@@ -34,7 +34,7 @@ struct Y<'a>{
     }
 
     fn bar() {
-        let x = 42;
+        let x: int = 42;
         let _y = Y { x: Some(&x as &X) };
     }
 }
@@ -43,7 +43,7 @@ mod c {
     pub trait X { fn f(&self); }
     impl X for int { fn f(&self) {} }
     pub struct Z<'a>(Option<&'a (X+'a)>);
-    fn main() { let x = 42; let z = Z(Some(&x as &X)); let _ = z; }
+    fn main() { let x: int = 42; let z = Z(Some(&x as &X)); let _ = z; }
 }
 
 pub fn main() {}
diff --git a/src/test/run-pass/match-reassign.rs b/src/test/run-pass/match-reassign.rs
new file mode 100644 (file)
index 0000000..759296a
--- /dev/null
@@ -0,0 +1,30 @@
+// 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 #23698: The reassignment checker only cared
+// about the last assigment in a match arm body
+
+// Use an extra function to make sure no extra assignments
+// are introduced by macros in the match statement
+fn check_eq(x: i32, y: i32) {
+    assert_eq!(x, y);
+}
+
+#[allow(unused_assignments)]
+fn main() {
+    let mut x = Box::new(1);
+    match x {
+        y => {
+            x = Box::new(2);
+            let _tmp = 1; // This assignment used to throw off the reassignment checker
+            check_eq(*y, 1);
+        }
+    }
+}
index c8da4852ad35f5cdedbe9a67200a9eaac16869fd..de8d116255ba227a2ae18f36f8a9103871d2bca3 100644 (file)
@@ -33,6 +33,6 @@ fn foo(self) {}
 
 fn main() {
     let x: [int; 4] = [1,2,3,4];
-    let xptr = x.as_slice() as *const _;
+    let xptr = x.as_slice() as *const [int];
     xptr.foo();
 }
index f8a3ce7cda01708bb6e0ddf4faec337b4f974313..baf8c6e4c97913e459911e0940be8e47220833d3 100644 (file)
@@ -35,7 +35,7 @@ fn is<T:'static>(x: &Any) -> bool {
 }
 
 fn main() {
-    let x = box 22 as Box<Wrap>;
+    let x = box 22isize as Box<Wrap>;
     println!("x={}", x.get());
     let y = x.wrap();
 }
index efdd42c382c1538b54b1dda4aa7b643adcaab0a5..368842ed1b0304244841ae3d233670baf9351281 100644 (file)
@@ -42,7 +42,7 @@ fn do_it_imm(obj: &Foo, v: uint) {
 }
 
 pub fn main() {
-    let mut x = 22;
+    let mut x: uint = 22;
     let obj = &mut x as &mut Foo;
     do_it_mut(obj);
     do_it_imm(obj, 23);
index f5ccd87fd25df29b6c6ae928c6070565764aa10a..597075c550051bc8664e3b0e63853468757f8932 100644 (file)
 struct G<A>(PhantomData<A>);
 
 impl<'a, A: Add<i32, Output=i32>> Fn<(A,)> for G<A> {
-    type Output = i32;
-
     extern "rust-call" fn call(&self, (arg,): (A,)) -> i32 {
         arg.add(1)
     }
 }
 
+impl<'a, A: Add<i32, Output=i32>> FnMut<(A,)> for G<A> {
+    extern "rust-call" fn call_mut(&mut self, args: (A,)) -> i32 { self.call(args) }
+}
+
+impl<'a, A: Add<i32, Output=i32>> FnOnce<(A,)> for G<A> {
+    type Output = i32;
+    extern "rust-call" fn call_once(self, args: (A,)) -> i32 { self.call(args) }
+}
+
 fn main() {
     // ICE trigger
     (G(PhantomData))(1);
index 17990bb1bd1562827e9f9a223831ccb10aa1a3e5..eeb705a2e3c99b5db12af2de0530c1a98b1c1399 100644 (file)
@@ -20,24 +20,38 @@ struct S1 {
 }
 
 impl FnMut<(i32,)> for S1 {
-    type Output = i32;
     extern "rust-call" fn call_mut(&mut self, (z,): (i32,)) -> i32 {
         self.x * self.y * z
     }
 }
 
+impl FnOnce<(i32,)> for S1 {
+    type Output = i32;
+    extern "rust-call" fn call_once(mut self, args: (i32,)) -> i32 {
+        self.call_mut(args)
+    }
+}
+
 struct S2 {
     x: i32,
     y: i32,
 }
 
 impl Fn<(i32,)> for S2 {
-    type Output = i32;
     extern "rust-call" fn call(&self, (z,): (i32,)) -> i32 {
         self.x * self.y * z
     }
 }
 
+impl FnMut<(i32,)> for S2 {
+    extern "rust-call" fn call_mut(&mut self, args: (i32,)) -> i32 { self.call(args) }
+}
+
+impl FnOnce<(i32,)> for S2 {
+    type Output = i32;
+    extern "rust-call" fn call_once(self, args: (i32,)) -> i32 { self.call(args) }
+}
+
 struct S3 {
     x: i32,
     y: i32,
index ea78a75c0c751d3a6ea00571803f513f7d5050b0..110109018db59d672476ca3f9e9deea720b69b59 100644 (file)
@@ -20,12 +20,16 @@ struct S {
 }
 
 impl FnMut<()> for S {
-    type Output = i32;
     extern "rust-call" fn call_mut(&mut self, (): ()) -> i32 {
         self.x * self.y
     }
 }
 
+impl FnOnce<()> for S {
+    type Output = i32;
+    extern "rust-call" fn call_once(mut self, args: ()) -> i32 { self.call_mut(args) }
+}
+
 fn main() {
     let mut s = S {
         x: 3,
index 63fb18a8ba2c248c83c645a2d2fc80fc1b5092b9..c87c79ca24edaab83cd7ac4aba3063342ff95493 100644 (file)
@@ -83,7 +83,10 @@ fn short<'b>(&'b self) -> int {
 }
 
 impl<'t> MakerTrait for Box<Trait<'t>+'static> {
-    fn mk() -> Box<Trait<'t>+'static> { box() (4,5) as Box<Trait> }
+    fn mk() -> Box<Trait<'t>+'static> {
+        let tup: Box<(int, int)> = box() (4,5);
+        tup as Box<Trait>
+    }
 }
 
 enum List<'l> {
index b81d0f2407bf0c17f09191e782b06f8d6115f72a..4a05b487ae24e58a2a98ee2b2c54830a00b92c4c 100644 (file)
@@ -11,6 +11,7 @@
 // Be sure that when a SIGPIPE would have been received that the entire process
 // doesn't die in a ball of fire, but rather it's gracefully handled.
 
+// ignore-aarch64
 // pretty-expanded FIXME #23616
 
 use std::env;
index 152fb5dc961072a29f9b51dcfe680794fe1d5da6..920cd9e03ab6b4ee97fd876a94e5c60bbfa44d92 100644 (file)
@@ -13,6 +13,6 @@
 // pretty-expanded FIXME #23616
 
 pub fn main() {
-    let foo = 1;
+    let foo: int = 1;
     assert_eq!(&foo as *const int, &foo as *const int);
 }
index a6c6db1a1273e4aa4222b8fae06625d8c7dad909..5c0d0fe9a63d8ed74b4ff05042e1562a6debf52c 100644 (file)
@@ -19,7 +19,7 @@
 pub fn main() {
     let (tx, rx) = channel::<uint>();
 
-    let x: Box<_> = box 1;
+    let x: Box<int> = box 1;
     let x_in_parent = &(*x) as *const int as uint;
 
     let _t = Thread::spawn(move || {
index 11a58de45322a94e48b22a9a7d7dd6868f4ce482..28f683c485ae47f38ad8f0d128f1c96f357a7d70 100644 (file)
@@ -8,13 +8,13 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// aux-build:trait-safety-lib.rs
+// aux-build:trait_safety_lib.rs
 
 // Simple smoke test that unsafe traits can be compiled across crates.
 
 // pretty-expanded FIXME #23616
 
-extern crate "trait-safety-lib" as lib;
+extern crate trait_safety_lib as lib;
 
 use lib::Foo;
 
diff --git a/src/test/run-pass/trivial_casts.rs b/src/test/run-pass/trivial_casts.rs
new file mode 100644 (file)
index 0000000..3da1ba0
--- /dev/null
@@ -0,0 +1,71 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Test that all coercions can actually be done using casts (modulo the lints).
+
+#![allow(trivial_casts, trivial_numeric_casts)]
+
+trait Foo {
+    fn foo(&self) {}
+}
+
+pub struct Bar;
+
+impl Foo for Bar {}
+
+pub fn main() {
+    // Numeric
+    let _ = 42_i32 as i32;
+    let _ = 42_u8 as u8;
+
+    // & to * pointers
+    let x: &u32 = &42;
+    let _ = x as *const u32;
+
+    let x: &mut u32 = &mut 42;
+    let _ = x as *mut u32;
+
+    // unsize array
+    let x: &[u32; 3] = &[42, 43, 44];
+    let _ = x as &[u32];
+    let _ = x as *const [u32];
+
+    let x: &mut [u32; 3] = &mut [42, 43, 44];
+    let _ = x as &mut [u32];
+    let _ = x as *mut [u32];
+
+    let x: Box<[u32; 3]> = Box::new([42, 43, 44]);
+    let _ = x as Box<[u32]>;
+
+    // unsize trait
+    let x: &Bar = &Bar;
+    let _ = x as &Foo;
+    let _ = x as *const Foo;
+
+    let x: &mut Bar = &mut Bar;
+    let _ = x as &mut Foo;
+    let _ = x as *mut Foo;
+
+    let x: Box<Bar> = Box::new(Bar);
+    let _ = x as Box<Foo>;
+
+    // functions
+    fn baz(_x: i32) {}
+    let _ = &baz as &Fn(i32);
+    let x = |_x: i32| {};
+    let _ = &x as &Fn(i32);
+}
+
+// subtyping
+pub fn test_subtyping<'a, 'b: 'a>(a: &'a Bar, b: &'b Bar) {
+    let _ = a as &'a Bar;
+    let _ = b as &'a Bar;
+    let _ = b as &'b Bar;
+}
index f4c0992ae1a5645fdc71b1997f939546005e3e2c..53e78db68b19d485d7a4b81abc9fd4cfb0cd6c08 100644 (file)
 // pretty-expanded FIXME #23616
 
 struct TestStruct {
-    x: *const int
+    x: *const isize
 }
 
 unsafe impl Sync for TestStruct {}
 
-static CONSTEXPR: TestStruct = TestStruct{x: &413 as *const _};
+static CONSTEXPR: TestStruct = TestStruct{ x: &413 };
 
 
 pub fn main() {
     let x: Vec<_> = (0..5).collect();
-    let expected: &[uint] = &[0,1,2,3,4];
+    let expected: &[usize] = &[0,1,2,3,4];
     assert_eq!(x, expected);
 
     let x = (0..5).collect::<Vec<_>>();
@@ -33,8 +33,8 @@ pub fn main() {
     let y: _ = "hello";
     assert_eq!(y.len(), 5);
 
-    let ptr = &5;
+    let ptr: &usize = &5;
     let ptr2 = ptr as *const _;
 
-    assert_eq!(ptr as *const uint as uint, ptr2 as uint);
+    assert_eq!(ptr as *const usize as usize, ptr2 as usize);
 }
index 5ec280dabc98b471d376120b5279fcc40dae9359..9b71abf3653318c21fbc558cdb07822bba9845a5 100644 (file)
 struct S;
 
 impl Fn<(i32,)> for S {
-    type Output = i32;
     extern "rust-call" fn call(&self, (x,): (i32,)) -> i32 {
         x * x
     }
 }
 
+impl FnMut<(i32,)> for S {
+    extern "rust-call" fn call_mut(&mut self, args: (i32,)) -> i32 { self.call(args) }
+}
+
+impl FnOnce<(i32,)> for S {
+    type Output = i32;
+    extern "rust-call" fn call_once(self, args: (i32,)) -> i32 { self.call(args) }
+}
+
 fn call_it<F:Fn(i32)->i32>(f: &F, x: i32) -> i32 {
     f(x)
 }
index 79be7dae8d709f5986d52d3103ccd6685de70a04..6261058b86742a2f9d4edc91597ab03ef65e2638 100644 (file)
 struct S;
 
 impl FnMut<(i32,)> for S {
-    type Output = i32;
-
     extern "rust-call" fn call_mut(&mut self, (x,): (i32,)) -> i32 {
         x * x
     }
 }
 
+impl FnOnce<(i32,)> for S {
+    type Output = i32;
+
+    extern "rust-call" fn call_once(mut self, args: (i32,)) -> i32 { self.call_mut(args) }
+}
+
 fn call_it_mut<F:FnMut(i32)->i32>(f: &mut F, x: i32) -> i32 {
     f(x)
 }
index ece583e8d63979ee81d5f68d23957ae3d259a6fa..e02784f917a97e71ca134242bfd9013ac55f188c 100644 (file)
@@ -32,13 +32,20 @@ fn new(f: F) -> YCombinator<F,A,R> {
 }
 
 impl<A,R,F : Fn(&Fn(A) -> R, A) -> R> Fn<(A,)> for YCombinator<F,A,R> {
-    type Output = R;
-
     extern "rust-call" fn call(&self, (arg,): (A,)) -> R {
         (self.func)(self, arg)
     }
 }
 
+impl<A,R,F : Fn(&Fn(A) -> R, A) -> R> FnMut<(A,)> for YCombinator<F,A,R> {
+    extern "rust-call" fn call_mut(&mut self, args: (A,)) -> R { self.call(args) }
+}
+
+impl<A,R,F : Fn(&Fn(A) -> R, A) -> R> FnOnce<(A,)> for YCombinator<F,A,R> {
+    type Output = R;
+    extern "rust-call" fn call_once(self, args: (A,)) -> R { self.call(args) }
+}
+
 fn main() {
     let factorial = |recur: &Fn(u32) -> u32, arg: u32| -> u32 {
         if arg == 0 {1} else {arg * recur(arg-1)}
index b505caf6dd8f75a9f764e290ffb0cc4a0302acf0..38f15d6e4499b30c7f970eb83ebb482bbf025b45 100644 (file)
 struct S;
 
 impl FnMut<(i32,)> for S {
-    type Output = i32;
-
     extern "rust-call" fn call_mut(&mut self, (x,): (i32,)) -> i32 {
         x * x
     }
 }
 
+impl FnOnce<(i32,)> for S {
+    type Output = i32;
+
+    extern "rust-call" fn call_once(mut self, args: (i32,)) -> i32 { self.call_mut(args) }
+}
+
 fn call_it<F:FnMut(i32)->i32>(mut f: F, x: i32) -> i32 {
     f(x) + 3
 }
index 4cb7e40a4fbd14ad443ddcd51d29f363cfe3c010..ba12599747068ac7666d0655578f3181456dcc4d 100644 (file)
@@ -16,6 +16,6 @@ fn main() {
     // The subslice used to go out of bounds for zero-sized array items, check that this doesn't
     // happen anymore
     match x {
-        [_, y..] => assert_eq!(&x[1] as *const _, &y[0] as *const _)
+        [_, y..] => assert_eq!(&x[1] as *const (), &y[0] as *const ())
     }
 }