]> git.lizzy.rs Git - rust.git/commitdiff
auto merge of #15806 : treeman/rust/std-doc, r=alexcrichton
authorbors <bors@rust-lang.org>
Sun, 20 Jul 2014 17:46:32 +0000 (17:46 +0000)
committerbors <bors@rust-lang.org>
Sun, 20 Jul 2014 17:46:32 +0000 (17:46 +0000)
Used `HashMap` and `HashSet` as the base of most examples. Could change it up with different containers, but I don't think it's a big deal.

134 files changed:
mk/docs.mk
src/doc/guide-strings.md
src/doc/guide.md
src/doc/index.md
src/doc/tutorial.md
src/liballoc/rc.rs
src/libcollections/dlist.rs
src/libcollections/str.rs
src/libcore/cmp.rs
src/libcore/default.rs
src/libcore/str.rs
src/libgraphviz/lib.rs
src/libgraphviz/maybe_owned_vec.rs
src/libgreen/sched.rs
src/librustc/back/link.rs
src/librustc/back/lto.rs
src/librustc/diagnostics.rs
src/librustc/driver/driver.rs
src/librustc/lib.rs
src/librustc/metadata/encoder.rs
src/librustc/middle/check_match.rs
src/librustc/middle/const_eval.rs
src/librustc/middle/effect.rs
src/librustc/middle/entry.rs
src/librustc/middle/intrinsicck.rs
src/librustc/middle/kind.rs
src/librustc/middle/lang_items.rs
src/librustc/middle/pat_util.rs
src/librustc/middle/resolve.rs
src/librustc/middle/trans/_match.rs
src/librustc/middle/trans/adt.rs
src/librustc/middle/trans/base.rs
src/librustc/middle/trans/basic_block.rs
src/librustc/middle/trans/callee.rs
src/librustc/middle/trans/closure.rs
src/librustc/middle/trans/expr.rs
src/librustc/middle/trans/glue.rs
src/librustc/middle/trans/intrinsic.rs
src/librustc/middle/ty.rs
src/librustc/middle/typeck/astconv.rs
src/librustc/middle/typeck/check/vtable.rs
src/librustc/middle/typeck/check/writeback.rs
src/librustc/middle/typeck/coherence.rs
src/librustc/middle/typeck/collect.rs
src/librustc/middle/typeck/mod.rs
src/librustc/middle/typeck/rscope.rs
src/librustc_back/lib.rs
src/librustc_llvm/lib.rs
src/librustrt/local_data.rs
src/librustrt/rtio.rs
src/librustuv/file.rs
src/libserialize/json.rs
src/libstd/collections/hashmap.rs
src/libstd/rand/mod.rs
src/libstd/task.rs
src/libsync/comm/mod.rs
src/libsync/comm/sync.rs
src/libsyntax/ast_util.rs
src/libsyntax/diagnostics/macros.rs
src/libsyntax/ext/deriving/generic/ty.rs
src/libsyntax/ext/format.rs
src/libunicode/lib.rs
src/snapshots.txt
src/test/auxiliary/overloaded_autoderef_xc.rs
src/test/bench/shootout-k-nucleotide.rs
src/test/compile-fail/borrowck-borrow-from-temporary.rs
src/test/compile-fail/borrowck-borrow-mut-object-twice.rs
src/test/compile-fail/borrowck-borrow-overloaded-auto-deref-mut.rs
src/test/compile-fail/borrowck-borrow-overloaded-auto-deref.rs
src/test/compile-fail/borrowck-managed-pointer-deref-scope.rs
src/test/compile-fail/borrowck-object-lifetime.rs
src/test/compile-fail/borrowck-overloaded-index-2.rs
src/test/compile-fail/borrowck-vec-pattern-element-loan.rs
src/test/compile-fail/borrowck-vec-pattern-tail-element-loan.rs
src/test/compile-fail/cleanup-rvalue-scopes-cf.rs
src/test/compile-fail/crate-name-mismatch.rs [new file with mode: 0644]
src/test/compile-fail/drop-with-active-borrows-2.rs
src/test/compile-fail/ifmt-bad-arg.rs
src/test/compile-fail/infinite-autoderef.rs
src/test/compile-fail/issue-11681.rs
src/test/compile-fail/issue-3154.rs
src/test/compile-fail/issue-4972.rs
src/test/compile-fail/isuue-12470.rs
src/test/compile-fail/lifetime-elision-return-type-requires-explicit-lifetime.rs [new file with mode: 0644]
src/test/compile-fail/lifetime-inference-give-expl-lifetime-param.rs
src/test/compile-fail/match-arm-statics.rs [new file with mode: 0644]
src/test/compile-fail/multiple-main-2.rs
src/test/compile-fail/multiple-main-3.rs
src/test/compile-fail/regions-creating-enums.rs
src/test/compile-fail/regions-creating-enums4.rs
src/test/compile-fail/regions-fn-subtyping-return-static.rs
src/test/compile-fail/regions-fn-subtyping.rs
src/test/compile-fail/regions-infer-at-fn-not-param.rs
src/test/compile-fail/regions-infer-borrow-scope-too-big.rs
src/test/compile-fail/regions-infer-borrow-scope-within-loop.rs
src/test/compile-fail/regions-infer-not-param.rs
src/test/compile-fail/regions-lifetime-of-struct-or-enum-variant.rs
src/test/compile-fail/regions-ret-borrowed.rs
src/test/compile-fail/regions-ret.rs
src/test/compile-fail/regions-trait-variance.rs
src/test/compile-fail/static-mut-not-pat.rs
src/test/run-make/crate-name-priority/Makefile
src/test/run-make/extra-filename-with-temp-outputs/Makefile [new file with mode: 0644]
src/test/run-make/extra-filename-with-temp-outputs/foo.rs [new file with mode: 0644]
src/test/run-pass/borrowck-scope-of-deref-issue-4666.rs
src/test/run-pass/class-impl-very-parameterized-trait.rs
src/test/run-pass/cleanup-rvalue-for-scope.rs
src/test/run-pass/crate-name-attr-used.rs
src/test/run-pass/issue-2502.rs
src/test/run-pass/issue-2748-a.rs
src/test/run-pass/issue-4464.rs
src/test/run-pass/issue-5708.rs
src/test/run-pass/issue-7911.rs
src/test/run-pass/match-arm-statics.rs [new file with mode: 0644]
src/test/run-pass/nullable-pointer-iotareduction.rs
src/test/run-pass/operator-overloading.rs
src/test/run-pass/overloaded-autoderef-count.rs
src/test/run-pass/overloaded-autoderef-order.rs
src/test/run-pass/overloaded-autoderef-vtable.rs
src/test/run-pass/overloaded-deref-count.rs
src/test/run-pass/overloaded-index.rs
src/test/run-pass/regions-addr-of-interior-of-unique-box.rs
src/test/run-pass/regions-addr-of-ret.rs
src/test/run-pass/regions-copy-closure.rs
src/test/run-pass/regions-dependent-addr-of.rs
src/test/run-pass/regions-dependent-autofn.rs
src/test/run-pass/regions-escape-into-other-fn.rs
src/test/run-pass/regions-infer-borrow-scope-view.rs
src/test/run-pass/regions-infer-borrow-scope-within-loop-ok.rs
src/test/run-pass/regions-infer-borrow-scope.rs
src/test/run-pass/regions-nullary-variant.rs
src/test/run-pass/regions-params.rs
src/test/run-pass/regions-return-interior-of-option.rs
src/test/run-pass/regions-static-closure.rs

index 213565b09ac27d0633a81cbdb6fde4cc5cf61b5d..933a0bdc717cafb6fb2726b0876438deabb4cdc1 100644 (file)
@@ -30,7 +30,7 @@ DOCS := index intro tutorial guide guide-ffi guide-macros guide-lifetimes \
        guide-tasks guide-container guide-pointers guide-testing \
        guide-runtime complement-bugreport \
        complement-lang-faq complement-design-faq complement-project-faq rust \
-    rustdoc guide-unsafe
+    rustdoc guide-unsafe guide-strings
 
 PDF_DOCS := tutorial rust
 
index 6f301afc8498d45068ba7ee49836974c944eebe4..4fea8b8039e008ad5d6d9dfda701fef8cd2f0b8a 100644 (file)
@@ -1,7 +1,5 @@
 % The Strings Guide
 
-# Strings
-
 Strings are an important concept to master in any programming language. If you
 come from a managed language background, you may be surprised at the complexity
 of string handling in a systems programming language. Efficient access and
@@ -14,7 +12,7 @@ Additionally, strings are not null-terminated and can contain null bytes.
 
 Rust has two main types of strings: `&str` and `String`.
 
-## &str
+# &str
 
 The first kind is a `&str`. This is pronounced a 'string slice.' String literals
 are of the type `&str`:
@@ -38,7 +36,7 @@ Like vector slices, string slices are simply a pointer plus a length. This
 means that they're a 'view' into an already-allocated string, such as a
 `&'static str` or a `String`.
 
-## String
+# String
 
 A `String` is a heap-allocated string. This string is growable, and is also
 guaranteed to be UTF-8.
@@ -73,9 +71,9 @@ let x: &[u8] = &[b'a', b'b'];
 let stack_str: &str = str::from_utf8(x).unwrap();
 ```
 
-## Best Practices
+# Best Practices
 
-### `String` vs. `&str`
+## `String` vs. `&str`
 
 In general, you should prefer `String` when you need ownership, and `&str` when
 you just need to borrow a string. This is very similar to using `Vec<T>` vs. `&[T]`,
@@ -98,7 +96,7 @@ need, and it can make your lifetimes more complex. Furthermore, you can pass
 either kind of string into `foo` by using `.as_slice()` on any `String` you
 need to pass in, so the `&str` version is more flexible.
 
-### Comparisons
+## Comparisons
 
 To compare a String to a constant string, prefer `as_slice()`...
 
@@ -123,7 +121,7 @@ fn compare(string: String) {
 Converting a `String` to a `&str` is cheap, but converting the `&str` to a
 `String` involves an allocation.
 
-## Other Documentation
+# Other Documentation
 
 * [the `&str` API documentation](/std/str/index.html)
 * [the `String` API documentation](std/string/index.html)
index b05d0e8ea350e9fe07bdf40f096a250d7795e52a..0175817e66a7ea69835e74e4e50ede936aeac1ea 100644 (file)
@@ -583,7 +583,7 @@ arguments we pass to functions and macros, if you're passing more than one.
 When you just use the double curly braces, Rust will attempt to display the
 value in a meaningful way by checking out its type. If you want to specify the
 format in a more detailed manner, there are a [wide number of options
-available](/std/fmt/index.html). Fow now, we'll just stick to the default:
+available](/std/fmt/index.html). For now, we'll just stick to the default:
 integers aren't very complicated to print.
 
 So, we've cleared up all of the confusion around bindings, with one exception:
index eb8c59ac030ee17eeebbe407d1c11b2569cf816d..c54f4e00905de66048cea0a7c7eb55fd8acb7fa6 100644 (file)
@@ -13,6 +13,7 @@ li {list-style-type: none; }
 
 # Guides
 
+* [Strings](guide-strings.html)
 * [Pointers](guide-pointers.html)
 * [References and Lifetimes](guide-lifetimes.html)
 * [Containers and Iterators](guide-container.html)
index 4c90e564b584ec127883df86d0141c8b44effff3..2b85bc50de3ab34571478f9ca9166a7270797971 100644 (file)
@@ -716,8 +716,8 @@ When an enum has simple integer discriminators, you can apply the `as` cast
 operator to convert a variant to its discriminator value as an `int`:
 
 ~~~~
-# #[deriving(Show)] enum Direction { North }
-println!( "{} => {}", North, North as int );
+# enum Direction { North, East, South, West }
+println!( "North => {}", North as int );
 ~~~~
 
 It is possible to set the discriminator values to chosen constant values:
@@ -748,8 +748,15 @@ includes an identifier of the actual form that it holds, much like the
 
 This declaration defines a type `Shape` that can refer to such shapes, and two
 functions, `Circle` and `Rectangle`, which can be used to construct values of
-the type. To create a new Circle, write `Circle(Point { x: 0.0, y: 0.0 },
-10.0)`.
+the type.
+
+To create a new `Circle`, write:
+
+~~~~
+# struct Point { x: f64, y: f64 }
+# enum Shape { Circle(Point, f64), Rectangle(Point, Point) }
+let circle = Circle(Point { x: 0.0, y: 0.0 }, 10.0);
+~~~~
 
 All of these variant constructors may be used as patterns. The only way to
 access the contents of an enum instance is the destructuring of a match. For
@@ -757,6 +764,7 @@ example:
 
 ~~~~
 use std::f64;
+
 # struct Point {x: f64, y: f64}
 # enum Shape { Circle(Point, f64), Rectangle(Point, Point) }
 fn area(sh: Shape) -> f64 {
@@ -765,6 +773,9 @@ fn area(sh: Shape) -> f64 {
         Rectangle(Point { x, y }, Point { x: x2, y: y2 }) => (x2 - x) * (y2 - y)
     }
 }
+
+let rect = Rectangle(Point { x: 0.0, y: 0.0 }, Point { x: 2.0, y: 2.0 });
+println!("area: {}", area(rect));
 ~~~~
 
 Use a lone `_` to ignore an individual field. Ignore all fields of a variant
@@ -786,8 +797,9 @@ fn point_from_direction(dir: Direction) -> Point {
 Enum variants may also be structs. For example:
 
 ~~~~
-# #![feature(struct_variant)]
+#![feature(struct_variant)]
 use std::f64;
+
 # struct Point { x: f64, y: f64 }
 # fn square(x: f64) -> f64 { x * x }
 enum Shape {
@@ -802,7 +814,14 @@ fn area(sh: Shape) -> f64 {
         }
     }
 }
-# fn main() {}
+
+fn main() {
+    let rect = Rectangle {
+        top_left: Point { x: 0.0, y: 0.0 },
+        bottom_right: Point { x: 2.0, y: -2.0 }
+    };
+    println!("area: {}", area(rect));
+}
 ~~~~
 
 > *Note:* This feature of the compiler is currently gated behind the
@@ -986,6 +1005,10 @@ that are `Send`, but non-`Send` types can still *contain* types with custom
 destructors. Example of types which are not `Send` are [`Gc<T>`][gc] and
 [`Rc<T>`][rc], the shared-ownership types.
 
+> *Note:* See a [later chapter](#ownership-escape-hatches) for a discussion about
+> [`Gc<T>`][gc] and [`Rc<T>`][rc], and the [chapter about traits](#traits) for
+> a discussion about `Send`.
+
 [gc]: http://doc.rust-lang.org/std/gc/struct.Gc.html
 [rc]: http://doc.rust-lang.org/std/rc/struct.Rc.html
 
@@ -1645,6 +1668,13 @@ let string = "foobar";
 let view: &str = string.slice(0, 3);
 ~~~
 
+Square brackets denote indexing into a slice or fixed-size vector:
+
+~~~~
+let crayons: [&str, ..3] = ["BananaMania", "Beaver", "Bittersweet"];
+println!("Crayon 2 is '{}'", crayons[2]);
+~~~~
+
 Mutable slices also exist, just as there are mutable references. However, there
 are no mutable string slices. Strings are a multi-byte encoding (UTF-8) of
 Unicode code points, so they cannot be freely mutated without the ability to
@@ -1659,20 +1689,6 @@ view[0] = 5;
 let ys: &mut [int] = &mut [1i, 2i, 3i];
 ~~~
 
-Square brackets denote indexing into a slice or fixed-size vector:
-
-~~~~
-# enum Crayon { Almond, AntiqueBrass, Apricot,
-#               Aquamarine, Asparagus, AtomicTangerine,
-#               BananaMania, Beaver, Bittersweet };
-# fn draw_scene(c: Crayon) { }
-let crayons: [Crayon, ..3] = [BananaMania, Beaver, Bittersweet];
-match crayons[0] {
-    Bittersweet => draw_scene(crayons[0]),
-    _ => ()
-}
-~~~~
-
 A slice or fixed-size vector can be destructured using pattern matching:
 
 ~~~~
@@ -1738,6 +1754,8 @@ via dynamic checks and can fail at runtime.
 The `Rc` and `Gc` types are not sendable, so they cannot be used to share memory between tasks. Safe
 immutable and mutable shared memory is provided by the `sync::arc` module.
 
+> *Note:* See a [later chapter](#traits) for a discussion about `Send` and sendable types.
+
 # Closures
 
 Named functions, like those we've seen so far, may not refer to local
@@ -2609,7 +2627,7 @@ let nonsense = mycircle.radius() * mycircle.area();
 
 ## Deriving implementations for traits
 
-A small number of traits in `std` and `extra` can have implementations
+A small number of traits in can have implementations
 that can be automatically derived. These instances are specified by
 placing the `deriving` attribute on a data type declaration. For
 example, the following will mean that `Circle` has an implementation
@@ -2618,6 +2636,7 @@ of type `ABC` can be randomly generated and converted to a string:
 
 ~~~
 extern crate rand;
+use std::rand::{task_rng, Rng};
 
 #[deriving(PartialEq)]
 struct Circle { radius: f64 }
@@ -2628,6 +2647,13 @@ enum ABC { A, B, C }
 fn main() {
     // Use the Show trait to print "A, B, C."
     println!("{}, {}, {}", A, B, C);
+
+    let mut rng = task_rng();
+
+    // Use the Rand trait to generate a random variants.
+    for _ in range(0i, 10) {
+        println!("{}", rng.gen::<ABC>());
+    }
 }
 ~~~
 
@@ -3136,8 +3162,8 @@ In Rust terminology, we need a way to refer to other crates.
 For that, Rust offers you the `extern crate` declaration:
 
 ~~~
+// `num` ships with Rust.
 extern crate num;
-// `num` ships with Rust (much like `extra`; more details further down).
 
 fn main() {
     // The rational number '1/2':
index d97bce39c2de947693943229e618881f7bd5bfe7..8d4e788bc8035a0a5181fabd544ce95ce2a535d0 100644 (file)
@@ -148,6 +148,8 @@ fn main() {
 
 */
 
+#![stable]
+
 use core::mem::transmute;
 use core::cell::Cell;
 use core::clone::Clone;
@@ -171,6 +173,7 @@ struct RcBox<T> {
 
 /// Immutable reference counted pointer type
 #[unsafe_no_drop_flag]
+#[stable]
 pub struct Rc<T> {
     // FIXME #12808: strange names to try to avoid interfering with
     // field accesses of the contained type via Deref
@@ -179,6 +182,7 @@ pub struct Rc<T> {
     _noshare: marker::NoShare
 }
 
+#[stable]
 impl<T> Rc<T> {
     /// Construct a new reference-counted box
     pub fn new(value: T) -> Rc<T> {
@@ -203,6 +207,7 @@ pub fn new(value: T) -> Rc<T> {
 
 impl<T> Rc<T> {
     /// Downgrade the reference-counted pointer to a weak reference
+    #[experimental = "Weak pointers may not belong in this module."]
     pub fn downgrade(&self) -> Weak<T> {
         self.inc_weak();
         Weak {
@@ -238,6 +243,7 @@ pub fn make_unique<'a>(&'a mut self) -> &'a mut T {
     }
 }
 
+#[experimental = "Deref is experimental."]
 impl<T> Deref<T> for Rc<T> {
     /// Borrow the value contained in the reference-counted box
     #[inline(always)]
@@ -247,6 +253,7 @@ fn deref<'a>(&'a self) -> &'a T {
 }
 
 #[unsafe_destructor]
+#[experimental = "Drop is experimental."]
 impl<T> Drop for Rc<T> {
     fn drop(&mut self) {
         unsafe {
@@ -269,7 +276,7 @@ fn drop(&mut self) {
     }
 }
 
-#[unstable]
+#[unstable = "Clone is unstable."]
 impl<T> Clone for Rc<T> {
     #[inline]
     fn clone(&self) -> Rc<T> {
@@ -278,6 +285,7 @@ fn clone(&self) -> Rc<T> {
     }
 }
 
+#[stable]
 impl<T: Default> Default for Rc<T> {
     #[inline]
     fn default() -> Rc<T> {
@@ -285,6 +293,7 @@ fn default() -> Rc<T> {
     }
 }
 
+#[unstable = "PartialEq is unstable."]
 impl<T: PartialEq> PartialEq for Rc<T> {
     #[inline(always)]
     fn eq(&self, other: &Rc<T>) -> bool { **self == **other }
@@ -292,8 +301,10 @@ fn eq(&self, other: &Rc<T>) -> bool { **self == **other }
     fn ne(&self, other: &Rc<T>) -> bool { **self != **other }
 }
 
+#[unstable = "Eq is unstable."]
 impl<T: Eq> Eq for Rc<T> {}
 
+#[unstable = "PartialOrd is unstable."]
 impl<T: PartialOrd> PartialOrd for Rc<T> {
     #[inline(always)]
     fn partial_cmp(&self, other: &Rc<T>) -> Option<Ordering> {
@@ -313,11 +324,13 @@ fn gt(&self, other: &Rc<T>) -> bool { **self > **other }
     fn ge(&self, other: &Rc<T>) -> bool { **self >= **other }
 }
 
+#[unstable = "Ord is unstable."]
 impl<T: Ord> Ord for Rc<T> {
     #[inline]
     fn cmp(&self, other: &Rc<T>) -> Ordering { (**self).cmp(&**other) }
 }
 
+#[experimental = "Show is experimental."]
 impl<T: fmt::Show> fmt::Show for Rc<T> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         (**self).fmt(f)
@@ -326,6 +339,7 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
 
 /// Weak reference to a reference-counted box
 #[unsafe_no_drop_flag]
+#[experimental = "Weak pointers may not belong in this module."]
 pub struct Weak<T> {
     // FIXME #12808: strange names to try to avoid interfering with
     // field accesses of the contained type via Deref
@@ -334,6 +348,7 @@ pub struct Weak<T> {
     _noshare: marker::NoShare
 }
 
+#[experimental = "Weak pointers may not belong in this module."]
 impl<T> Weak<T> {
     /// Upgrade a weak reference to a strong reference
     pub fn upgrade(&self) -> Option<Rc<T>> {
@@ -347,6 +362,7 @@ pub fn upgrade(&self) -> Option<Rc<T>> {
 }
 
 #[unsafe_destructor]
+#[experimental = "Weak pointers may not belong in this module."]
 impl<T> Drop for Weak<T> {
     fn drop(&mut self) {
         unsafe {
@@ -364,6 +380,7 @@ fn drop(&mut self) {
 }
 
 #[unstable]
+#[experimental = "Weak pointers may not belong in this module."]
 impl<T> Clone for Weak<T> {
     #[inline]
     fn clone(&self) -> Weak<T> {
index 226dd5a2356c93415db75bc49d2aa0b7d6a7b22c..48ea1bd1c0150d72fcd641c600c88dfcac9f5ac5 100644 (file)
@@ -87,12 +87,14 @@ fn some(n: &mut T) -> Rawlink<T> {
     }
 
     /// Convert the `Rawlink` into an Option value
-    fn resolve_immut(&self) -> Option<&T> {
-        unsafe { self.p.to_option() }
+    fn resolve_immut<'a>(&self) -> Option<&'a T> {
+        unsafe {
+            mem::transmute(self.p.to_option())
+        }
     }
 
     /// Convert the `Rawlink` into an Option value
-    fn resolve(&mut self) -> Option<&mut T> {
+    fn resolve<'a>(&mut self) -> Option<&'a mut T> {
         if self.p.is_null() {
             None
         } else {
@@ -278,6 +280,23 @@ pub fn new() -> DList<T> {
     /// Move the last element to the front of the list.
     ///
     /// If the list is empty, do nothing.
+    ///
+    /// # Example
+    ///
+    /// ```rust
+    /// use std::collections::{DList, Deque};
+    ///
+    /// let mut dl = DList::new();
+    /// dl.push_back(1i);
+    /// dl.push_back(2);
+    /// dl.push_back(3);
+    ///
+    /// dl.rotate_forward();
+    ///
+    /// for e in dl.iter() {
+    ///     println!("{}", e); // prints 3, then 1, then 2
+    /// }
+    /// ```
     #[inline]
     pub fn rotate_forward(&mut self) {
         self.pop_back_node().map(|tail| {
@@ -288,6 +307,23 @@ pub fn rotate_forward(&mut self) {
     /// Move the first element to the back of the list.
     ///
     /// If the list is empty, do nothing.
+    ///
+    /// # Example
+    ///
+    /// ```rust
+    /// use std::collections::{DList, Deque};
+    ///
+    /// let mut dl = DList::new();
+    /// dl.push_back(1i);
+    /// dl.push_back(2);
+    /// dl.push_back(3);
+    ///
+    /// dl.rotate_backward();
+    ///
+    /// for e in dl.iter() {
+    ///     println!("{}", e); // prints 2, then 3, then 1
+    /// }
+    /// ```
     #[inline]
     pub fn rotate_backward(&mut self) {
         self.pop_front_node().map(|head| {
@@ -298,6 +334,25 @@ pub fn rotate_backward(&mut self) {
     /// Add all elements from `other` to the end of the list
     ///
     /// O(1)
+    ///
+    /// # Example
+    ///
+    /// ```rust
+    /// use std::collections::{DList, Deque};
+    ///
+    /// let mut a = DList::new();
+    /// let mut b = DList::new();
+    /// a.push_back(1i);
+    /// a.push_back(2);
+    /// b.push_back(3i);
+    /// b.push_back(4);
+    ///
+    /// a.append(b);
+    ///
+    /// for e in a.iter() {
+    ///     println!("{}", e); // prints 1, then 2, then 3, then 4
+    /// }
+    /// ```
     pub fn append(&mut self, mut other: DList<T>) {
         match self.list_tail.resolve() {
             None => *self = other,
@@ -320,6 +375,25 @@ pub fn append(&mut self, mut other: DList<T>) {
     /// Add all elements from `other` to the beginning of the list
     ///
     /// O(1)
+    ///
+    /// # Example
+    ///
+    /// ```rust
+    /// use std::collections::{DList, Deque};
+    ///
+    /// let mut a = DList::new();
+    /// let mut b = DList::new();
+    /// a.push_back(1i);
+    /// a.push_back(2);
+    /// b.push_back(3i);
+    /// b.push_back(4);
+    ///
+    /// a.prepend(b);
+    ///
+    /// for e in a.iter() {
+    ///     println!("{}", e); // prints 3, then 4, then 1, then 2
+    /// }
+    /// ```
     #[inline]
     pub fn prepend(&mut self, mut other: DList<T>) {
         mem::swap(self, &mut other);
@@ -330,6 +404,25 @@ pub fn prepend(&mut self, mut other: DList<T>) {
     /// or at the end.
     ///
     /// O(N)
+    ///
+    /// # Example
+    ///
+    /// ```rust
+    /// use std::collections::{DList, Deque};
+    ///
+    /// let mut a: DList<int> = DList::new();
+    /// a.push_back(2i);
+    /// a.push_back(4);
+    /// a.push_back(7);
+    /// a.push_back(8);
+    ///
+    /// // insert 11 before the first odd number in the list
+    /// a.insert_when(11, |&e, _| e % 2 == 1);
+    ///
+    /// for e in a.iter() {
+    ///     println!("{}", e); // prints 2, then 4, then 11, then 7, then 8
+    /// }
+    /// ```
     pub fn insert_when(&mut self, elt: T, f: |&T, &T| -> bool) {
         {
             let mut it = self.mut_iter();
index bd6a13ae2e3ed7c28c273d7c16f6c6d4df1bc030..1e29679f8a79ec61c363c6f5ef68e846927ec5e6 100644 (file)
@@ -808,6 +808,7 @@ fn append(mut self, rhs: &str) -> String {
 #[cfg(test)]
 mod tests {
     use std::iter::AdditiveIterator;
+    use std::iter::range;
     use std::default::Default;
     use std::char::Char;
     use std::clone::Clone;
@@ -1610,6 +1611,30 @@ fn test_rev_iterator() {
         assert_eq!(pos, v.len());
     }
 
+    #[test]
+    fn test_chars_decoding() {
+        let mut bytes = [0u8, ..4];
+        for c in range(0u32, 0x110000).filter_map(|c| ::core::char::from_u32(c)) {
+            let len = c.encode_utf8(bytes);
+            let s = ::core::str::from_utf8(bytes.slice_to(len)).unwrap();
+            if Some(c) != s.chars().next() {
+                fail!("character {:x}={} does not decode correctly", c as u32, c);
+            }
+        }
+    }
+
+    #[test]
+    fn test_chars_rev_decoding() {
+        let mut bytes = [0u8, ..4];
+        for c in range(0u32, 0x110000).filter_map(|c| ::core::char::from_u32(c)) {
+            let len = c.encode_utf8(bytes);
+            let s = ::core::str::from_utf8(bytes.slice_to(len)).unwrap();
+            if Some(c) != s.chars().rev().next() {
+                fail!("character {:x}={} does not decode correctly", c as u32, c);
+            }
+        }
+    }
+
     #[test]
     fn test_iterator_clone() {
         let s = "ศไทย中华Việt Nam";
@@ -2240,16 +2265,26 @@ fn test_into_maybe_owned() {
 #[cfg(test)]
 mod bench {
     use test::Bencher;
+    use test::black_box;
     use super::*;
+    use std::option::{None, Some};
     use std::iter::{Iterator, DoubleEndedIterator};
     use std::collections::Collection;
 
     #[bench]
     fn char_iterator(b: &mut Bencher) {
         let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb";
-        let len = s.char_len();
 
-        b.iter(|| assert_eq!(s.chars().count(), len));
+        b.iter(|| s.chars().count());
+    }
+
+    #[bench]
+    fn char_iterator_for(b: &mut Bencher) {
+        let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb";
+
+        b.iter(|| {
+            for ch in s.chars() { black_box(ch) }
+        });
     }
 
     #[bench]
@@ -2260,17 +2295,24 @@ fn char_iterator_ascii(b: &mut Bencher) {
         Mary had a little lamb, Little lamb
         Mary had a little lamb, Little lamb
         Mary had a little lamb, Little lamb";
-        let len = s.char_len();
 
-        b.iter(|| assert_eq!(s.chars().count(), len));
+        b.iter(|| s.chars().count());
     }
 
     #[bench]
     fn char_iterator_rev(b: &mut Bencher) {
         let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb";
-        let len = s.char_len();
 
-        b.iter(|| assert_eq!(s.chars().rev().count(), len));
+        b.iter(|| s.chars().rev().count());
+    }
+
+    #[bench]
+    fn char_iterator_rev_for(b: &mut Bencher) {
+        let s = "ศไทย中华Việt Nam; Mary had a little lamb, Little lamb";
+
+        b.iter(|| {
+            for ch in s.chars().rev() { black_box(ch) }
+        });
     }
 
     #[bench]
index f374d2e9a274338ac647206853624c4f4d9baf47..8db59bd370e76bcfd292139bca09518ac09a7336 100644 (file)
@@ -37,6 +37,8 @@
 //! assert!(SketchyNum {num: 25} != SketchyNum {num: 57});
 //! ```
 
+#![stable]
+
 use option::{Option, Some};
 
 /// Trait for values that can be compared for equality and inequality.
@@ -53,6 +55,7 @@
 /// Eventually, this will be implemented by default for types that implement
 /// `Eq`.
 #[lang="eq"]
+#[unstable = "Definition may change slightly after trait reform"]
 pub trait PartialEq {
     /// This method tests for `self` and `other` values to be equal, and is used by `==`.
     fn eq(&self, other: &Self) -> bool;
@@ -71,6 +74,7 @@ fn ne(&self, other: &Self) -> bool { !self.eq(other) }
 /// - reflexive: `a == a`;
 /// - symmetric: `a == b` implies `b == a`; and
 /// - transitive: `a == b` and `b == c` implies `a == c`.
+#[unstable = "Definition may change slightly after trait reform"]
 pub trait Eq: PartialEq {
     // FIXME #13101: this method is used solely by #[deriving] to
     // assert that every component of a type implements #[deriving]
@@ -86,6 +90,7 @@ fn assert_receiver_is_total_eq(&self) {}
 
 /// An ordering is, e.g, a result of a comparison between two values.
 #[deriving(Clone, PartialEq, Show)]
+#[stable]
 pub enum Ordering {
    /// An ordering where a compared value is less [than another].
    Less = -1i,
@@ -104,6 +109,7 @@ pub enum Ordering {
 ///   true; and
 /// - transitive, `a < b` and `b < c` implies `a < c`. The same must hold for
 ///   both `==` and `>`.
+#[unstable = "Definition may change slightly after trait reform"]
 pub trait Ord: Eq + PartialOrd {
     /// This method returns an ordering between `self` and `other` values.
     ///
@@ -118,8 +124,10 @@ pub trait Ord: Eq + PartialOrd {
     fn cmp(&self, other: &Self) -> Ordering;
 }
 
+#[unstable = "Trait is unstable."]
 impl Eq for Ordering {}
 
+#[unstable = "Trait is unstable."]
 impl Ord for Ordering {
     #[inline]
     fn cmp(&self, other: &Ordering) -> Ordering {
@@ -127,6 +135,7 @@ fn cmp(&self, other: &Ordering) -> Ordering {
     }
 }
 
+#[unstable = "Trait is unstable."]
 impl PartialOrd for Ordering {
     #[inline]
     fn partial_cmp(&self, other: &Ordering) -> Option<Ordering> {
@@ -140,6 +149,7 @@ fn partial_cmp(&self, other: &Ordering) -> Option<Ordering> {
 /// If the first ordering is different, the first ordering is all that must be returned.
 /// If the first ordering is equal, then second ordering is returned.
 #[inline]
+#[deprecated = "Just call .cmp() on an Ordering"]
 pub fn lexical_ordering(o1: Ordering, o2: Ordering) -> Ordering {
     match o1 {
         Equal => o2,
@@ -157,6 +167,7 @@ pub fn lexical_ordering(o1: Ordering, o2: Ordering) -> Ordering {
 /// `NaN < 0 == false` and `NaN >= 0 == false` (cf. IEEE 754-2008 section
 /// 5.11).
 #[lang="ord"]
+#[unstable = "Definition may change slightly after trait reform"]
 pub trait PartialOrd: PartialEq {
     /// This method returns an ordering between `self` and `other` values
     /// if one exists.
@@ -202,6 +213,7 @@ fn ge(&self, other: &Self) -> bool {
 /// of different types. The most common use case for this relation is
 /// container types; e.g. it is often desirable to be able to use `&str`
 /// values to look up entries in a container with `String` keys.
+#[experimental = "Better solutions may be discovered."]
 pub trait Equiv<T> {
     /// Implement this function to decide equivalent values.
     fn equiv(&self, other: &T) -> bool;
@@ -209,12 +221,14 @@ pub trait Equiv<T> {
 
 /// Compare and return the minimum of two values.
 #[inline]
+#[stable]
 pub fn min<T: Ord>(v1: T, v2: T) -> T {
     if v1 < v2 { v1 } else { v2 }
 }
 
 /// Compare and return the maximum of two values.
 #[inline]
+#[stable]
 pub fn max<T: Ord>(v1: T, v2: T) -> T {
     if v1 > v2 { v1 } else { v2 }
 }
@@ -227,6 +241,7 @@ mod impls {
 
     macro_rules! eq_impl(
         ($($t:ty)*) => ($(
+            #[unstable = "Trait is unstable."]
             impl PartialEq for $t {
                 #[inline]
                 fn eq(&self, other: &$t) -> bool { (*self) == (*other) }
@@ -236,6 +251,7 @@ fn ne(&self, other: &$t) -> bool { (*self) != (*other) }
         )*)
     )
 
+    #[unstable = "Trait is unstable."]
     impl PartialEq for () {
         #[inline]
         fn eq(&self, _other: &()) -> bool { true }
@@ -247,6 +263,7 @@ fn ne(&self, _other: &()) -> bool { false }
 
     macro_rules! totaleq_impl(
         ($($t:ty)*) => ($(
+            #[unstable = "Trait is unstable."]
             impl Eq for $t {}
         )*)
     )
@@ -255,6 +272,7 @@ impl Eq for $t {}
 
     macro_rules! ord_impl(
         ($($t:ty)*) => ($(
+            #[unstable = "Trait is unstable."]
             impl PartialOrd for $t {
                 #[inline]
                 fn partial_cmp(&self, other: &$t) -> Option<Ordering> {
@@ -277,6 +295,7 @@ fn gt(&self, other: &$t) -> bool { (*self) > (*other) }
         )*)
     )
 
+    #[unstable = "Trait is unstable."]
     impl PartialOrd for () {
         #[inline]
         fn partial_cmp(&self, _: &()) -> Option<Ordering> {
@@ -284,6 +303,7 @@ fn partial_cmp(&self, _: &()) -> Option<Ordering> {
         }
     }
 
+    #[unstable = "Trait is unstable."]
     impl PartialOrd for bool {
         #[inline]
         fn partial_cmp(&self, other: &bool) -> Option<Ordering> {
@@ -295,6 +315,7 @@ fn partial_cmp(&self, other: &bool) -> Option<Ordering> {
 
     macro_rules! totalord_impl(
         ($($t:ty)*) => ($(
+            #[unstable = "Trait is unstable."]
             impl Ord for $t {
                 #[inline]
                 fn cmp(&self, other: &$t) -> Ordering {
@@ -306,11 +327,13 @@ fn cmp(&self, other: &$t) -> Ordering {
         )*)
     )
 
+    #[unstable = "Trait is unstable."]
     impl Ord for () {
         #[inline]
         fn cmp(&self, _other: &()) -> Ordering { Equal }
     }
 
+    #[unstable = "Trait is unstable."]
     impl Ord for bool {
         #[inline]
         fn cmp(&self, other: &bool) -> Ordering {
@@ -321,12 +344,14 @@ fn cmp(&self, other: &bool) -> Ordering {
     totalord_impl!(char uint u8 u16 u32 u64 int i8 i16 i32 i64)
 
     // & pointers
+    #[unstable = "Trait is unstable."]
     impl<'a, T: PartialEq> PartialEq for &'a T {
         #[inline]
         fn eq(&self, other: & &'a T) -> bool { *(*self) == *(*other) }
         #[inline]
         fn ne(&self, other: & &'a T) -> bool { *(*self) != *(*other) }
     }
+    #[unstable = "Trait is unstable."]
     impl<'a, T: PartialOrd> PartialOrd for &'a T {
         #[inline]
         fn partial_cmp(&self, other: &&'a T) -> Option<Ordering> {
@@ -341,19 +366,23 @@ fn ge(&self, other: & &'a T) -> bool { *(*self) >= *(*other) }
         #[inline]
         fn gt(&self, other: & &'a T) -> bool { *(*self) > *(*other) }
     }
+    #[unstable = "Trait is unstable."]
     impl<'a, T: Ord> Ord for &'a T {
         #[inline]
         fn cmp(&self, other: & &'a T) -> Ordering { (**self).cmp(*other) }
     }
+    #[unstable = "Trait is unstable."]
     impl<'a, T: Eq> Eq for &'a T {}
 
     // &mut pointers
+    #[unstable = "Trait is unstable."]
     impl<'a, T: PartialEq> PartialEq for &'a mut T {
         #[inline]
         fn eq(&self, other: &&'a mut T) -> bool { **self == *(*other) }
         #[inline]
         fn ne(&self, other: &&'a mut T) -> bool { **self != *(*other) }
     }
+    #[unstable = "Trait is unstable."]
     impl<'a, T: PartialOrd> PartialOrd for &'a mut T {
         #[inline]
         fn partial_cmp(&self, other: &&'a mut T) -> Option<Ordering> {
@@ -368,9 +397,11 @@ fn ge(&self, other: &&'a mut T) -> bool { **self >= **other }
         #[inline]
         fn gt(&self, other: &&'a mut T) -> bool { **self > **other }
     }
+    #[unstable = "Trait is unstable."]
     impl<'a, T: Ord> Ord for &'a mut T {
         #[inline]
         fn cmp(&self, other: &&'a mut T) -> Ordering { (**self).cmp(*other) }
     }
+    #[unstable = "Trait is unstable."]
     impl<'a, T: Eq> Eq for &'a mut T {}
 }
index 363d8ecf002194e2ab516ea492dd7d7391a0b1ea..4de2384d23dc30b1f57ed2aea5b56ab98dc5d73b 100644 (file)
@@ -10,6 +10,8 @@
 
 //! The `Default` trait for types which may have meaningful default values
 
+#![stable]
+
 /// A trait that types which have a useful default value should implement.
 pub trait Default {
     /// Return the "default value" for a type.
index aa2050dacf1aa46da39ff1872e6b89c9f20eb661..c6aff9c8bdac8c58147e17131ea3a491080cca38 100644 (file)
@@ -97,47 +97,110 @@ fn only_ascii(&self) -> bool {
 Section: Iterators
 */
 
-/// External iterator for a string's characters.
-/// Use with the `std::iter` module.
+/// Iterator for the char (representing *Unicode Scalar Values*) of a string
+///
+/// Created with the method `.chars()`.
 #[deriving(Clone)]
 pub struct Chars<'a> {
-    /// The slice remaining to be iterated
-    string: &'a str,
+    iter: slice::Items<'a, u8>
+}
+
+// Return the initial codepoint accumulator for the first byte.
+// The first byte is special, only want bottom 5 bits for width 2, 4 bits
+// for width 3, and 3 bits for width 4
+macro_rules! utf8_first_byte(
+    ($byte:expr, $width:expr) => (($byte & (0x7F >> $width)) as u32)
+)
+
+// return the value of $ch updated with continuation byte $byte
+macro_rules! utf8_acc_cont_byte(
+    ($ch:expr, $byte:expr) => (($ch << 6) | ($byte & CONT_MASK) as u32)
+)
+
+macro_rules! utf8_is_cont_byte(
+    ($byte:expr) => (($byte & !CONT_MASK) == TAG_CONT_U8)
+)
+
+#[inline]
+fn unwrap_or_0(opt: Option<&u8>) -> u8 {
+    match opt {
+        Some(&byte) => byte,
+        None => 0,
+    }
 }
 
 impl<'a> Iterator<char> for Chars<'a> {
     #[inline]
     fn next(&mut self) -> Option<char> {
-        // Decode the next codepoint, then update
-        // the slice to be just the remaining part
-        if self.string.len() != 0 {
-            let CharRange {ch, next} = self.string.char_range_at(0);
-            unsafe {
-                self.string = raw::slice_unchecked(self.string, next, self.string.len());
+        // Decode UTF-8, using the valid UTF-8 invariant
+        let x = match self.iter.next() {
+            None => return None,
+            Some(&next_byte) if next_byte < 128 => return Some(next_byte as char),
+            Some(&next_byte) => next_byte,
+        };
+
+        // Multibyte case follows
+        // Decode from a byte combination out of: [[[x y] z] w]
+        // NOTE: Performance is sensitive to the exact formulation here
+        let init = utf8_first_byte!(x, 2);
+        let y = unwrap_or_0(self.iter.next());
+        let mut ch = utf8_acc_cont_byte!(init, y);
+        if x >= 0xE0 {
+            // [[x y z] w] case
+            // 5th bit in 0xE0 .. 0xEF is always clear, so `init` is still valid
+            let z = unwrap_or_0(self.iter.next());
+            let y_z = utf8_acc_cont_byte!((y & CONT_MASK) as u32, z);
+            ch = init << 12 | y_z;
+            if x >= 0xF0 {
+                // [x y z w] case
+                // use only the lower 3 bits of `init`
+                let w = unwrap_or_0(self.iter.next());
+                ch = (init & 7) << 18 | utf8_acc_cont_byte!(y_z, w);
             }
-            Some(ch)
-        } else {
-            None
+        }
+
+        // str invariant says `ch` is a valid Unicode Scalar Value
+        unsafe {
+            Some(mem::transmute(ch))
         }
     }
 
     #[inline]
     fn size_hint(&self) -> (uint, Option<uint>) {
-        (self.string.len().saturating_add(3)/4, Some(self.string.len()))
+        let (len, _) = self.iter.size_hint();
+        (len.saturating_add(3) / 4, Some(len))
     }
 }
 
 impl<'a> DoubleEndedIterator<char> for Chars<'a> {
     #[inline]
     fn next_back(&mut self) -> Option<char> {
-        if self.string.len() != 0 {
-            let CharRange {ch, next} = self.string.char_range_at_reverse(self.string.len());
-            unsafe {
-                self.string = raw::slice_unchecked(self.string, 0, next);
+        let w = match self.iter.next_back() {
+            None => return None,
+            Some(&back_byte) if back_byte < 128 => return Some(back_byte as char),
+            Some(&back_byte) => back_byte,
+        };
+
+        // Multibyte case follows
+        // Decode from a byte combination out of: [x [y [z w]]]
+        let mut ch;
+        let z = unwrap_or_0(self.iter.next_back());
+        ch = utf8_first_byte!(z, 2);
+        if utf8_is_cont_byte!(z) {
+            let y = unwrap_or_0(self.iter.next_back());
+            ch = utf8_first_byte!(y, 3);
+            if utf8_is_cont_byte!(y) {
+                let x = unwrap_or_0(self.iter.next_back());
+                ch = utf8_first_byte!(x, 4);
+                ch = utf8_acc_cont_byte!(ch, y);
             }
-            Some(ch)
-        } else {
-            None
+            ch = utf8_acc_cont_byte!(ch, z);
+        }
+        ch = utf8_acc_cont_byte!(ch, w);
+
+        // str invariant says `ch` is a valid Unicode Scalar Value
+        unsafe {
+            Some(mem::transmute(ch))
         }
     }
 }
@@ -146,18 +209,23 @@ fn next_back(&mut self) -> Option<char> {
 /// Use with the `std::iter` module.
 #[deriving(Clone)]
 pub struct CharOffsets<'a> {
-    /// The original string to be iterated
-    string: &'a str,
+    front_offset: uint,
     iter: Chars<'a>,
 }
 
 impl<'a> Iterator<(uint, char)> for CharOffsets<'a> {
     #[inline]
     fn next(&mut self) -> Option<(uint, char)> {
-        // Compute the byte offset by using the pointer offset between
-        // the original string slice and the iterator's remaining part
-        let offset = self.iter.string.as_ptr() as uint - self.string.as_ptr() as uint;
-        self.iter.next().map(|ch| (offset, ch))
+        let (pre_len, _) = self.iter.iter.size_hint();
+        match self.iter.next() {
+            None => None,
+            Some(ch) => {
+                let index = self.front_offset;
+                let (len, _) = self.iter.iter.size_hint();
+                self.front_offset += pre_len - len;
+                Some((index, ch))
+            }
+        }
     }
 
     #[inline]
@@ -169,11 +237,14 @@ fn size_hint(&self) -> (uint, Option<uint>) {
 impl<'a> DoubleEndedIterator<(uint, char)> for CharOffsets<'a> {
     #[inline]
     fn next_back(&mut self) -> Option<(uint, char)> {
-        self.iter.next_back().map(|ch| {
-            let offset = self.iter.string.len() +
-                    self.iter.string.as_ptr() as uint - self.string.as_ptr() as uint;
-            (offset, ch)
-        })
+        match self.iter.next_back() {
+            None => None,
+            Some(ch) => {
+                let (len, _) = self.iter.iter.size_hint();
+                let index = self.front_offset + len;
+                Some((index, ch))
+            }
+        }
     }
 }
 
@@ -672,9 +743,9 @@ macro_rules! next ( () => {
             // UTF8-4      = %xF0 %x90-BF 2( UTF8-tail ) / %xF1-F3 3( UTF8-tail ) /
             //               %xF4 %x80-8F 2( UTF8-tail )
             match w {
-                2 => if second & 192 != TAG_CONT_U8 {err!()},
+                2 => if second & !CONT_MASK != TAG_CONT_U8 {err!()},
                 3 => {
-                    match (first, second, next!() & 192) {
+                    match (first, second, next!() & !CONT_MASK) {
                         (0xE0        , 0xA0 .. 0xBF, TAG_CONT_U8) |
                         (0xE1 .. 0xEC, 0x80 .. 0xBF, TAG_CONT_U8) |
                         (0xED        , 0x80 .. 0x9F, TAG_CONT_U8) |
@@ -683,7 +754,7 @@ macro_rules! next ( () => {
                     }
                 }
                 4 => {
-                    match (first, second, next!() & 192, next!() & 192) {
+                    match (first, second, next!() & !CONT_MASK, next!() & !CONT_MASK) {
                         (0xF0        , 0x90 .. 0xBF, TAG_CONT_U8, TAG_CONT_U8) |
                         (0xF1 .. 0xF3, 0x80 .. 0xBF, TAG_CONT_U8, TAG_CONT_U8) |
                         (0xF4        , 0x80 .. 0x8F, TAG_CONT_U8, TAG_CONT_U8) => {}
@@ -880,19 +951,10 @@ pub struct CharRange {
     pub next: uint,
 }
 
-// Return the initial codepoint accumulator for the first byte.
-// The first byte is special, only want bottom 5 bits for width 2, 4 bits
-// for width 3, and 3 bits for width 4
-macro_rules! utf8_first_byte(
-    ($byte:expr, $width:expr) => (($byte & (0x7F >> $width)) as u32)
-)
-
-// return the value of $ch updated with continuation byte $byte
-macro_rules! utf8_acc_cont_byte(
-    ($ch:expr, $byte:expr) => (($ch << 6) | ($byte & 63u8) as u32)
-)
-
-static TAG_CONT_U8: u8 = 128u8;
+/// Mask of the value bits of a continuation byte
+static CONT_MASK: u8 = 0b0011_1111u8;
+/// Value of the tag bits (tag mask is !CONT_MASK) of a continuation byte
+static TAG_CONT_U8: u8 = 0b1000_0000u8;
 
 /// Unsafe operations
 pub mod raw {
@@ -1608,7 +1670,7 @@ fn contains_char(&self, needle: char) -> bool {
 
     #[inline]
     fn chars(&self) -> Chars<'a> {
-        Chars{string: *self}
+        Chars{iter: self.as_bytes().iter()}
     }
 
     #[inline]
@@ -1618,7 +1680,7 @@ fn bytes(&self) -> Bytes<'a> {
 
     #[inline]
     fn char_indices(&self) -> CharOffsets<'a> {
-        CharOffsets{string: *self, iter: self.chars()}
+        CharOffsets{front_offset: 0, iter: self.chars()}
     }
 
     #[inline]
@@ -1828,7 +1890,7 @@ fn char_range_at_reverse(&self, start: uint) -> CharRange {
         // Multibyte case is a fn to allow char_range_at_reverse to inline cleanly
         fn multibyte_char_range_at_reverse(s: &str, mut i: uint) -> CharRange {
             // while there is a previous byte == 10......
-            while i > 0 && s.as_bytes()[i] & 192u8 == TAG_CONT_U8 {
+            while i > 0 && s.as_bytes()[i] & !CONT_MASK == TAG_CONT_U8 {
                 i -= 1u;
             }
 
index 24698d09f56e53d782556aa343b0fd0f7e823d11..3c93a795071a6719831719aa4007036a7119d08e 100644 (file)
@@ -455,12 +455,12 @@ fn pre_escaped_content(self) -> str::MaybeOwned<'a> {
     }
 
     /// Puts `prefix` on a line above this label, with a blank line separator.
-    pub fn prefix_line(self, prefix: LabelText) -> LabelText {
+    pub fn prefix_line(self, prefix: LabelText) -> LabelText<'static> {
         prefix.suffix_line(self)
     }
 
     /// Puts `suffix` on a line below this label, with a blank line separator.
-    pub fn suffix_line(self, suffix: LabelText) -> LabelText {
+    pub fn suffix_line(self, suffix: LabelText) -> LabelText<'static> {
         let prefix = self.pre_escaped_content().into_string();
         let suffix = suffix.pre_escaped_content();
         EscStr(str::Owned(prefix.append(r"\n\n").append(suffix.as_slice())))
index ec60be195158ad67714689040f24a4a8e230c5c4..9e52af72138bba2fb839a25a8554b733956677d6 100644 (file)
@@ -109,7 +109,7 @@ fn as_slice<'a>(&'a self) -> &'a [T] {
 }
 
 impl<'a,T> FromIterator<T> for MaybeOwnedVector<'a,T> {
-    fn from_iter<I:Iterator<T>>(iterator: I) -> MaybeOwnedVector<T> {
+    fn from_iter<I:Iterator<T>>(iterator: I) -> MaybeOwnedVector<'a,T> {
         // If we are building from scratch, might as well build the
         // most flexible variant.
         Growable(FromIterator::from_iter(iterator))
index 7603b0a8013c75d25ad7d3a15ae86c2c5bb580d1..7151a78eacd43159380f5fd6fe4a99109e569d2e 100644 (file)
@@ -959,13 +959,13 @@ pub fn run(self, sched: &mut Scheduler) {
 type UnsafeTaskReceiver = raw::Closure;
 trait ClosureConverter {
     fn from_fn(|&mut Scheduler, Box<GreenTask>|) -> Self;
-    fn to_fn(self) -> |&mut Scheduler, Box<GreenTask>|;
+    fn to_fn(self) -> |&mut Scheduler, Box<GreenTask>|:'static ;
 }
 impl ClosureConverter for UnsafeTaskReceiver {
     fn from_fn(f: |&mut Scheduler, Box<GreenTask>|) -> UnsafeTaskReceiver {
         unsafe { mem::transmute(f) }
     }
-    fn to_fn(self) -> |&mut Scheduler, Box<GreenTask>| {
+    fn to_fn(self) -> |&mut Scheduler, Box<GreenTask>|:'static {
         unsafe { mem::transmute(self) }
     }
 }
index 88b42dba8e99d1adf18473c70afbc7eb1f83e973..cc73cdce6a8c3f8fc44f5f48e31aa3c923ce517f 100644 (file)
@@ -571,15 +571,27 @@ pub fn find_crate_name(sess: Option<&Session>,
     };
 
     // Look in attributes 100% of the time to make sure the attribute is marked
-    // as used. After doing this, however, favor crate names from the command
-    // line.
+    // as used. After doing this, however, we still prioritize a crate name from
+    // the command line over one found in the #[crate_name] attribute. If we
+    // find both we ensure that they're the same later on as well.
     let attr_crate_name = attrs.iter().find(|at| at.check_name("crate_name"))
                                .and_then(|at| at.value_str().map(|s| (at, s)));
 
     match sess {
         Some(sess) => {
             match sess.opts.crate_name {
-                Some(ref s) => return validate(s.clone(), None),
+                Some(ref s) => {
+                    match attr_crate_name {
+                        Some((attr, ref name)) if s.as_slice() != name.get() => {
+                            let msg = format!("--crate-name and #[crate_name] \
+                                               are required to match, but `{}` \
+                                               != `{}`", s, name);
+                            sess.span_err(attr.span, msg.as_slice());
+                        }
+                        _ => {},
+                    }
+                    return validate(s.clone(), None);
+                }
                 None => {}
             }
         }
@@ -1547,7 +1559,7 @@ fn add_upstream_rust_crates(cmd: &mut Command, sess: &Session,
                 add_dynamic_crate(cmd, sess, src.dylib.unwrap())
             }
             cstore::RequireStatic => {
-                add_static_crate(cmd, sess, tmpdir, cnum, src.rlib.unwrap())
+                add_static_crate(cmd, sess, tmpdir, src.rlib.unwrap())
             }
         }
 
@@ -1564,7 +1576,7 @@ fn unlib<'a>(config: &config::Config, stem: &'a [u8]) -> &'a [u8] {
 
     // Adds the static "rlib" versions of all crates to the command line.
     fn add_static_crate(cmd: &mut Command, sess: &Session, tmpdir: &Path,
-                        cnum: ast::CrateNum, cratepath: Path) {
+                        cratepath: Path) {
         // When performing LTO on an executable output, all of the
         // bytecode from the upstream libraries has already been
         // included in our object file output. We need to modify all of
@@ -1580,7 +1592,8 @@ fn add_static_crate(cmd: &mut Command, sess: &Session, tmpdir: &Path,
         // If we're not doing LTO, then our job is simply to just link
         // against the archive.
         if sess.lto() {
-            let name = sess.cstore.get_crate_data(cnum).name.clone();
+            let name = cratepath.filename_str().unwrap();
+            let name = name.slice(3, name.len() - 5); // chop off lib/.rlib
             time(sess.time_passes(),
                  format!("altering {}.rlib", name).as_slice(),
                  (), |()| {
index 6184ea4591f084ae5041f04c56372e6cd516d8f5..c51f1615d59806eff4f24011747e7f3f76fb7bfe 100644 (file)
@@ -54,17 +54,19 @@ pub fn run(sess: &session::Session, llmod: ModuleRef,
         };
 
         let archive = ArchiveRO::open(&path).expect("wanted an rlib");
-        debug!("reading {}", name);
+        let file = path.filename_str().unwrap();
+        let file = file.slice(3, file.len() - 5); // chop off lib/.rlib
+        debug!("reading {}", file);
         let bc = time(sess.time_passes(),
                       format!("read {}.bytecode.deflate", name).as_slice(),
                       (),
                       |_| {
                           archive.read(format!("{}.bytecode.deflate",
-                                               name).as_slice())
+                                               file).as_slice())
                       });
         let bc = bc.expect("missing compressed bytecode in archive!");
         let bc = time(sess.time_passes(),
-                      format!("inflate {}.bc", name).as_slice(),
+                      format!("inflate {}.bc", file).as_slice(),
                       (),
                       |_| {
                           match flate::inflate_bytes(bc) {
index 5f3bbf481056a4dc5662e616f39e7a4c58b55171..1b806e1c257dc6805ffe2fd3beeb63e421f8e904 100644 (file)
     E0091,
     E0092,
     E0093,
-    E0094
+    E0094,
+    E0095,
+    E0096,
+    E0097,
+    E0098,
+    E0099,
+    E0100,
+    E0101,
+    E0102,
+    E0103,
+    E0104,
+    E0105,
+    E0106,
+    E0107,
+    E0108,
+    E0109,
+    E0110,
+    E0111,
+    E0112,
+    E0113,
+    E0114,
+    E0115,
+    E0116,
+    E0117,
+    E0118,
+    E0119,
+    E0120,
+    E0121,
+    E0122,
+    E0123,
+    E0124,
+    E0125,
+    E0126,
+    E0127,
+    E0128,
+    E0129,
+    E0130,
+    E0131,
+    E0132,
+    E0133,
+    E0134,
+    E0135,
+    E0136,
+    E0137,
+    E0138,
+    E0139,
+    E0140,
+    E0141,
+    E0142,
+    E0143,
+    E0144,
+    E0145,
+    E0146,
+    E0147,
+    E0148,
+    E0149,
+    E0150,
+    E0151,
+    E0152,
+    E0153,
+    E0154,
+    E0155,
+    E0156,
+    E0157
 )
index 43aa3f9041fd97d146bbbad40a8a22fe1a6bd835..81ace4d015c8576101d566fb499694e4856eb5f7 100644 (file)
@@ -936,6 +936,7 @@ pub struct OutputFilenames {
     pub out_directory: Path,
     pub out_filestem: String,
     pub single_output_file: Option<Path>,
+    extra: String,
 }
 
 impl OutputFilenames {
@@ -948,7 +949,7 @@ pub fn path(&self, flavor: link::OutputType) -> Path {
     }
 
     pub fn temp_path(&self, flavor: link::OutputType) -> Path {
-        let base = self.out_directory.join(self.out_filestem.as_slice());
+        let base = self.out_directory.join(self.filestem());
         match flavor {
             link::OutputTypeBitcode => base.with_extension("bc"),
             link::OutputTypeAssembly => base.with_extension("s"),
@@ -959,8 +960,11 @@ pub fn temp_path(&self, flavor: link::OutputType) -> Path {
     }
 
     pub fn with_extension(&self, extension: &str) -> Path {
-        let stem = self.out_filestem.as_slice();
-        self.out_directory.join(stem).with_extension(extension)
+        self.out_directory.join(self.filestem()).with_extension(extension)
+    }
+
+    fn filestem(&self) -> String {
+        format!("{}{}", self.out_filestem, self.extra)
     }
 }
 
@@ -1000,6 +1004,7 @@ pub fn build_output_filenames(input: &Input,
                 out_directory: dirpath,
                 out_filestem: stem,
                 single_output_file: None,
+                extra: sess.opts.cg.extra_filename.clone(),
             }
         }
 
@@ -1018,6 +1023,7 @@ pub fn build_output_filenames(input: &Input,
                 out_directory: out_file.dir_path(),
                 out_filestem: out_file.filestem_str().unwrap().to_string(),
                 single_output_file: ofile,
+                extra: sess.opts.cg.extra_filename.clone(),
             }
         }
     }
index 92d1c176a1b92c8b28d8ef2faf7b2b56d6a6c811..2a7f7e8c54dd1f66bfb07e10df12e630a06b1bad 100644 (file)
@@ -68,42 +68,42 @@ pub mod back {
 }
 
 pub mod middle {
-    pub mod def;
-    pub mod trans;
-    pub mod ty;
-    pub mod ty_fold;
-    pub mod subst;
-    pub mod resolve;
-    pub mod resolve_lifetime;
-    pub mod typeck;
+    pub mod astencode;
+    pub mod borrowck;
+    pub mod cfg;
+    pub mod check_const;
     pub mod check_loop;
     pub mod check_match;
-    pub mod check_const;
     pub mod check_static;
-    pub mod borrowck;
+    pub mod const_eval;
     pub mod dataflow;
-    pub mod mem_categorization;
-    pub mod liveness;
-    pub mod kind;
+    pub mod dead;
+    pub mod def;
+    pub mod dependency_format;
+    pub mod effect;
+    pub mod entry;
+    pub mod expr_use_visitor;
     pub mod freevars;
-    pub mod pat_util;
-    pub mod region;
-    pub mod const_eval;
-    pub mod astencode;
+    pub mod graph;
+    pub mod intrinsicck;
+    pub mod kind;
     pub mod lang_items;
+    pub mod liveness;
+    pub mod mem_categorization;
+    pub mod pat_util;
     pub mod privacy;
-    pub mod entry;
-    pub mod effect;
     pub mod reachable;
-    pub mod graph;
-    pub mod cfg;
-    pub mod dead;
-    pub mod expr_use_visitor;
-    pub mod dependency_format;
-    pub mod weak_lang_items;
+    pub mod region;
+    pub mod resolve;
+    pub mod resolve_lifetime;
     pub mod save;
-    pub mod intrinsicck;
     pub mod stability;
+    pub mod subst;
+    pub mod trans;
+    pub mod ty;
+    pub mod ty_fold;
+    pub mod typeck;
+    pub mod weak_lang_items;
 }
 
 pub mod front {
index b86f5ee6cc2bc8fc6a9f146f302a82c0801bd95f..439455ff3d15ce3291c07acd9955b1fd852266bd 100644 (file)
@@ -314,8 +314,7 @@ fn encode_enum_variant_info(ecx: &EncodeContext,
                             ebml_w: &mut Encoder,
                             id: NodeId,
                             variants: &[P<Variant>],
-                            index: &mut Vec<entry<i64>>,
-                            generics: &ast::Generics) {
+                            index: &mut Vec<entry<i64>>) {
     debug!("encode_enum_variant_info(id={:?})", id);
 
     let mut disr_val = 0;
@@ -343,10 +342,6 @@ fn encode_enum_variant_info(ecx: &EncodeContext,
         encode_stability(ebml_w, stab);
 
         match variant.node.kind {
-            ast::TupleVariantKind(ref args)
-                    if args.len() > 0 && generics.ty_params.len() == 0 => {
-                encode_symbol(ecx, ebml_w, variant.node.id);
-            }
             ast::TupleVariantKind(_) => {},
             ast::StructVariantKind(_) => {
                 let fields = ty::lookup_struct_fields(ecx.tcx, def_id);
@@ -1019,7 +1014,7 @@ fn add_to_index(item: &Item, ebml_w: &Encoder,
         encode_stability(ebml_w, stab);
         ebml_w.end_tag();
       }
-      ItemEnum(ref enum_definition, ref generics) => {
+      ItemEnum(ref enum_definition, _) => {
         add_to_index(item, ebml_w, index);
 
         ebml_w.start_tag(tag_items_data_item);
@@ -1046,8 +1041,7 @@ fn add_to_index(item: &Item, ebml_w: &Encoder,
                                  ebml_w,
                                  item.id,
                                  (*enum_definition).variants.as_slice(),
-                                 index,
-                                 generics);
+                                 index);
       }
       ItemStruct(struct_def, _) => {
         let fields = ty::lookup_struct_fields(tcx, def_id);
index 066837afac94a008f1b56aadb3f8ddcc2ecdbb36..67208e33372867a67b1680dabdb315031ccc57b3 100644 (file)
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 use middle::const_eval::{compare_const_vals, const_bool, const_float, const_nil, const_val};
-use middle::const_eval::{eval_const_expr, lookup_const_by_id};
+use middle::const_eval::{const_expr_to_pat, eval_const_expr, lookup_const_by_id};
 use middle::def::*;
 use middle::pat_util::*;
 use middle::ty::*;
@@ -21,8 +21,9 @@
 use syntax::ast::*;
 use syntax::ast_util::{is_unguarded, walk_pat};
 use syntax::codemap::{Span, Spanned, DUMMY_SP};
-use syntax::owned_slice::OwnedSlice;
+use syntax::fold::{Folder, noop_fold_pat};
 use syntax::print::pprust::pat_to_string;
+use syntax::parse::token;
 use syntax::visit;
 use syntax::visit::{Visitor, FnKind};
 use util::ppaux::ty_to_string;
@@ -76,6 +77,12 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
     }
 }
 
+impl FromIterator<Vec<Gc<Pat>>> for Matrix {
+    fn from_iter<T: Iterator<Vec<Gc<Pat>>>>(mut iterator: T) -> Matrix {
+        Matrix(iterator.collect())
+    }
+}
+
 pub struct MatchCheckCtxt<'a> {
     pub tcx: &'a ty::ctxt
 }
@@ -120,10 +127,8 @@ fn visit_fn(&mut self, fk: &FnKind, fd: &FnDecl, b: &Block, s: Span, _: NodeId,
 }
 
 pub fn check_crate(tcx: &ty::ctxt, krate: &Crate) {
-    let mut cx = MatchCheckCtxt { tcx: tcx, };
-
+    let mut cx = MatchCheckCtxt { tcx: tcx };
     visit::walk_crate(&mut cx, krate, ());
-
     tcx.sess.abort_if_errors();
 }
 
@@ -155,48 +160,49 @@ fn check_expr(cx: &mut MatchCheckCtxt, ex: &Expr) {
                 // If the type *is* empty, it's vacuously exhaustive
                 return;
             }
-            let m: Matrix = Matrix(arms
+
+            let mut static_inliner = StaticInliner { tcx: cx.tcx };
+            let matrix: Matrix = arms
                 .iter()
                 .filter(|&arm| is_unguarded(arm))
                 .flat_map(|arm| arm.pats.iter())
-                .map(|pat| vec!(pat.clone()))
-                .collect());
-            check_exhaustive(cx, ex.span, &m);
+                .map(|pat| vec![static_inliner.fold_pat(*pat)])
+                .collect();
+            check_exhaustive(cx, ex.span, &matrix);
         },
         _ => ()
     }
 }
 
+fn is_expr_const_nan(tcx: &ty::ctxt, expr: &Expr) -> bool {
+    match eval_const_expr(tcx, expr) {
+        const_float(f) => f.is_nan(),
+        _ => false
+    }
+}
+
 // Check for unreachable patterns
 fn check_arms(cx: &MatchCheckCtxt, arms: &[Arm]) {
     let mut seen = Matrix(vec!());
+    let mut static_inliner = StaticInliner { tcx: cx.tcx };
     for arm in arms.iter() {
         for pat in arm.pats.iter() {
+            let inlined = static_inliner.fold_pat(*pat);
+
             // Check that we do not match against a static NaN (#6804)
-            let pat_matches_nan: |&Pat| -> bool = |p| {
-                let opt_def = cx.tcx.def_map.borrow().find_copy(&p.id);
-                match opt_def {
-                    Some(DefStatic(did, false)) => {
-                        let const_expr = lookup_const_by_id(cx.tcx, did).unwrap();
-                        match eval_const_expr(cx.tcx, &*const_expr) {
-                            const_float(f) if f.is_nan() => true,
-                            _ => false
-                        }
+            walk_pat(&*inlined, |p| {
+                match p.node {
+                    PatLit(expr) if is_expr_const_nan(cx.tcx, &*expr) => {
+                        span_warn!(cx.tcx.sess, pat.span, E0003,
+                            "unmatchable NaN in pattern, \
+                             use the is_nan method in a guard instead");
                     }
-                    _ => false
-                }
-            };
-
-            walk_pat(&**pat, |p| {
-                if pat_matches_nan(p) {
-                    span_warn!(cx.tcx.sess, p.span, E0003,
-                        "unmatchable NaN in pattern, use the is_nan method in a guard instead"
-                    );
+                    _ => ()
                 }
                 true
             });
 
-            let v = vec!(*pat);
+            let v = vec![inlined];
             match is_useful(cx, &seen, v.as_slice(), LeaveOutWitness) {
                 NotUseful => span_err!(cx.tcx.sess, pat.span, E0001, "unreachable pattern"),
                 Useful => (),
@@ -218,8 +224,8 @@ fn raw_pat(p: Gc<Pat>) -> Gc<Pat> {
     }
 }
 
-fn check_exhaustive(cx: &MatchCheckCtxt, sp: Span, m: &Matrix) {
-    match is_useful(cx, m, [wild()], ConstructWitness) {
+fn check_exhaustive(cx: &MatchCheckCtxt, sp: Span, matrix: &Matrix) {
+    match is_useful(cx, matrix, [wild()], ConstructWitness) {
         UsefulWithWitness(pats) => {
             let witness = match pats.as_slice() {
                 [witness] => witness,
@@ -251,16 +257,26 @@ fn const_val_to_expr(value: &const_val) -> Gc<Expr> {
     }
 }
 
-fn def_to_path(tcx: &ty::ctxt, id: DefId) -> Path {
-    ty::with_path(tcx, id, |mut path| Path {
-        global: false,
-        segments: path.last().map(|elem| PathSegment {
-            identifier: Ident::new(elem.name()),
-            lifetimes: vec!(),
-            types: OwnedSlice::empty()
-        }).move_iter().collect(),
-        span: DUMMY_SP,
-    })
+pub struct StaticInliner<'a> {
+    pub tcx: &'a ty::ctxt
+}
+
+impl<'a> Folder for StaticInliner<'a> {
+    fn fold_pat(&mut self, pat: Gc<Pat>) -> Gc<Pat> {
+        match pat.node {
+            PatIdent(..) | PatEnum(..) => {
+                let def = self.tcx.def_map.borrow().find_copy(&pat.id);
+                match def {
+                    Some(DefStatic(did, _)) => {
+                        let const_expr = lookup_const_by_id(self.tcx, did).unwrap();
+                        const_expr_to_pat(self.tcx, const_expr)
+                    },
+                    _ => noop_fold_pat(pat, self)
+                }
+            }
+            _ => noop_fold_pat(pat, self)
+        }
+    }
 }
 
 /// Constructs a partial witness for a pattern given a list of
@@ -283,9 +299,11 @@ fn construct_witness(cx: &MatchCheckCtxt, ctor: &Constructor,
 
         ty::ty_enum(cid, _) | ty::ty_struct(cid, _)  => {
             let (vid, is_structure) = match ctor {
-                &Variant(vid) => (vid,
-                    ty::enum_variant_with_id(cx.tcx, cid, vid).arg_names.is_some()),
-                _ => (cid, true)
+                &Variant(vid) =>
+                    (vid, ty::enum_variant_with_id(cx.tcx, cid, vid).arg_names.is_some()),
+                _ =>
+                    (cid, ty::lookup_struct_fields(cx.tcx, cid).iter()
+                        .any(|field| field.name != token::special_idents::unnamed_field.name))
             };
             if is_structure {
                 let fields = ty::lookup_struct_fields(cx.tcx, vid);
@@ -459,8 +477,7 @@ fn is_useful(cx: &MatchCheckCtxt, matrix @ &Matrix(ref rows): &Matrix,
             },
 
             Some(constructor) => {
-                let matrix = Matrix(rows.iter().filter_map(|r|
-                    default(cx, r.as_slice())).collect());
+                let matrix = rows.iter().filter_map(|r| default(cx, r.as_slice())).collect();
                 match is_useful(cx, &matrix, v.tail(), witness) {
                     UsefulWithWitness(pats) => {
                         let arity = constructor_arity(cx, &constructor, left_ty);
@@ -506,25 +523,23 @@ fn pat_constructors(cx: &MatchCheckCtxt, p: Gc<Pat>,
     match pat.node {
         PatIdent(..) =>
             match cx.tcx.def_map.borrow().find(&pat.id) {
-                Some(&DefStatic(did, false)) => {
-                    let const_expr = lookup_const_by_id(cx.tcx, did).unwrap();
-                    vec!(ConstantValue(eval_const_expr(cx.tcx, &*const_expr)))
-                },
+                Some(&DefStatic(..)) =>
+                    cx.tcx.sess.span_bug(pat.span, "static pattern should've been rewritten"),
                 Some(&DefStruct(_)) => vec!(Single),
                 Some(&DefVariant(_, id, _)) => vec!(Variant(id)),
                 _ => vec!()
             },
         PatEnum(..) =>
             match cx.tcx.def_map.borrow().find(&pat.id) {
-                Some(&DefStatic(did, false)) => {
-                    let const_expr = lookup_const_by_id(cx.tcx, did).unwrap();
-                    vec!(ConstantValue(eval_const_expr(cx.tcx, &*const_expr)))
-                },
+                Some(&DefStatic(..)) =>
+                    cx.tcx.sess.span_bug(pat.span, "static pattern should've been rewritten"),
                 Some(&DefVariant(_, id, _)) => vec!(Variant(id)),
                 _ => vec!(Single)
             },
         PatStruct(..) =>
             match cx.tcx.def_map.borrow().find(&pat.id) {
+                Some(&DefStatic(..)) =>
+                    cx.tcx.sess.span_bug(pat.span, "static pattern should've been rewritten"),
                 Some(&DefVariant(_, id, _)) => vec!(Variant(id)),
                 _ => vec!(Single)
             },
@@ -583,7 +598,7 @@ pub fn constructor_arity(cx: &MatchCheckCtxt, ctor: &Constructor, ty: ty::t) ->
 }
 
 fn range_covered_by_constructor(ctor: &Constructor,
-                                from: &const_val,to: &const_val) -> Option<bool> {
+                                from: &const_val, to: &const_val) -> Option<bool> {
     let (c_from, c_to) = match *ctor {
         ConstantValue(ref value)        => (value, value),
         ConstantRange(ref from, ref to) => (from, to),
@@ -621,44 +636,22 @@ pub fn specialize(cx: &MatchCheckCtxt, r: &[Gc<Pat>],
         &PatIdent(_, _, _) => {
             let opt_def = cx.tcx.def_map.borrow().find_copy(&pat_id);
             match opt_def {
+                Some(DefStatic(..)) =>
+                    cx.tcx.sess.span_bug(pat_span, "static pattern should've been rewritten"),
                 Some(DefVariant(_, id, _)) => if *constructor == Variant(id) {
                     Some(vec!())
                 } else {
                     None
                 },
-                Some(DefStatic(did, _)) => {
-                    let const_expr = lookup_const_by_id(cx.tcx, did).unwrap();
-                    let e_v = eval_const_expr(cx.tcx, &*const_expr);
-                    match range_covered_by_constructor(constructor, &e_v, &e_v) {
-                        Some(true) => Some(vec!()),
-                        Some(false) => None,
-                        None => {
-                            cx.tcx.sess.span_err(pat_span, "mismatched types between arms");
-                            None
-                        }
-                    }
-                }
-                _ => {
-                    Some(Vec::from_elem(arity, wild()))
-                }
+                _ => Some(Vec::from_elem(arity, wild()))
             }
         }
 
         &PatEnum(_, ref args) => {
             let def = cx.tcx.def_map.borrow().get_copy(&pat_id);
             match def {
-                DefStatic(did, _) => {
-                    let const_expr = lookup_const_by_id(cx.tcx, did).unwrap();
-                    let e_v = eval_const_expr(cx.tcx, &*const_expr);
-                    match range_covered_by_constructor(constructor, &e_v, &e_v) {
-                        Some(true) => Some(vec!()),
-                        Some(false) => None,
-                        None => {
-                            cx.tcx.sess.span_err(pat_span, "mismatched types between arms");
-                            None
-                        }
-                    }
-                }
+                DefStatic(..) =>
+                    cx.tcx.sess.span_bug(pat_span, "static pattern should've been rewritten"),
                 DefVariant(_, id, _) if *constructor != Variant(id) => None,
                 DefVariant(..) | DefFn(..) | DefStruct(..) => {
                     Some(match args {
@@ -674,6 +667,8 @@ pub fn specialize(cx: &MatchCheckCtxt, r: &[Gc<Pat>],
             // Is this a struct or an enum variant?
             let def = cx.tcx.def_map.borrow().get_copy(&pat_id);
             let class_id = match def {
+                DefStatic(..) =>
+                    cx.tcx.sess.span_bug(pat_span, "static pattern should've been rewritten"),
                 DefVariant(_, variant_id, _) => if *constructor == Variant(variant_id) {
                     Some(variant_id)
                 } else {
@@ -782,7 +777,8 @@ fn check_local(cx: &mut MatchCheckCtxt, loc: &Local) {
         LocalFor => "`for` loop"
     };
 
-    match is_refutable(cx, loc.pat) {
+    let mut static_inliner = StaticInliner { tcx: cx.tcx };
+    match is_refutable(cx, static_inliner.fold_pat(loc.pat)) {
         Some(pat) => {
             span_err!(cx.tcx.sess, loc.pat.span, E0005,
                 "refutable pattern in {} binding: `{}` not covered",
index 7567e73b01de9337515a664136e5c8738014ecf1..4d256549a64650cd44e6a1f87a888541a02ebc2f 100644 (file)
@@ -13,8 +13,8 @@
 
 use metadata::csearch;
 use middle::astencode;
-
 use middle::def;
+use middle::pat_util::def_to_path;
 use middle::ty;
 use middle::typeck::astconv;
 use util::nodemap::{DefIdMap};
@@ -26,7 +26,7 @@
 use syntax::{ast, ast_map, ast_util};
 
 use std::rc::Rc;
-use std::gc::Gc;
+use std::gc::{Gc, GC};
 
 //
 // This pass classifies expressions by their constant-ness.
@@ -303,6 +303,57 @@ pub enum const_val {
     const_nil
 }
 
+pub fn const_expr_to_pat(tcx: &ty::ctxt, expr: Gc<Expr>) -> Gc<Pat> {
+    let pat = match expr.node {
+        ExprTup(ref exprs) =>
+            PatTup(exprs.iter().map(|&expr| const_expr_to_pat(tcx, expr)).collect()),
+
+        ExprCall(callee, ref args) => {
+            let def = tcx.def_map.borrow().get_copy(&callee.id);
+            tcx.def_map.borrow_mut().find_or_insert(expr.id, def);
+            let path = match def {
+                def::DefStruct(def_id) => def_to_path(tcx, def_id),
+                def::DefVariant(_, variant_did, _) => def_to_path(tcx, variant_did),
+                _ => unreachable!()
+            };
+            let pats = args.iter().map(|&expr| const_expr_to_pat(tcx, expr)).collect();
+            PatEnum(path, Some(pats))
+        }
+
+        ExprStruct(ref path, ref fields, None) => {
+            let field_pats = fields.iter().map(|field| FieldPat {
+                ident: field.ident.node,
+                pat: const_expr_to_pat(tcx, field.expr)
+            }).collect();
+            PatStruct(path.clone(), field_pats, false)
+        }
+
+        ExprVec(ref exprs) => {
+            let pats = exprs.iter().map(|&expr| const_expr_to_pat(tcx, expr)).collect();
+            PatVec(pats, None, vec![])
+        }
+
+        ExprPath(ref path) => {
+            let opt_def = tcx.def_map.borrow().find_copy(&expr.id);
+            match opt_def {
+                Some(def::DefStruct(..)) =>
+                    PatStruct(path.clone(), vec![], false),
+                Some(def::DefVariant(..)) =>
+                    PatEnum(path.clone(), None),
+                _ => {
+                    match lookup_const(tcx, &*expr) {
+                        Some(actual) => return const_expr_to_pat(tcx, actual),
+                        _ => unreachable!()
+                    }
+                }
+            }
+        }
+
+        _ => PatLit(expr)
+    };
+    box (GC) Pat { id: expr.id, node: pat, span: expr.span }
+}
+
 pub fn eval_const_expr(tcx: &ty::ctxt, e: &Expr) -> const_val {
     match eval_const_expr_partial(tcx, e) {
         Ok(r) => r,
index fed2f91ce098601ccb5f6b5e3d7dfd141f3a7acc..e6160038b1d8c29662a7e57268ec423730713541 100644 (file)
@@ -49,10 +49,9 @@ fn require_unsafe(&mut self, span: Span, description: &str) {
         match self.unsafe_context {
             SafeContext => {
                 // Report an error.
-                self.tcx.sess.span_err(span,
-                                  format!("{} requires unsafe function or \
-                                           block",
-                                          description).as_slice())
+                span_err!(self.tcx.sess, span, E0133,
+                          "{} requires unsafe function or block",
+                          description);
             }
             UnsafeBlock(block_id) => {
                 // OK, but record this.
@@ -73,14 +72,14 @@ fn check_str_index(&mut self, e: &ast::Expr) {
         match ty::get(base_type).sty {
             ty::ty_uniq(ty) | ty::ty_rptr(_, ty::mt{ty, ..}) => match ty::get(ty).sty {
                 ty::ty_str => {
-                    self.tcx.sess.span_err(e.span,
-                        "modification of string types is not allowed");
+                    span_err!(self.tcx.sess, e.span, E0134,
+                              "modification of string types is not allowed");
                 }
                 _ => {}
             },
             ty::ty_str => {
-                self.tcx.sess.span_err(e.span,
-                    "modification of string types is not allowed");
+                span_err!(self.tcx.sess, e.span, E0135,
+                          "modification of string types is not allowed");
             }
             _ => {}
         }
index 9a5f226bb73ceaf5546fcaf9718945d3c430b563..3debdc158fe26c0d8c64f33cb454c1f0452284bd 100644 (file)
@@ -87,9 +87,8 @@ fn find_item(item: &Item, ctxt: &mut EntryContext) {
                             if ctxt.main_fn.is_none() {
                                 ctxt.main_fn = Some((item.id, item.span));
                             } else {
-                                ctxt.session.span_err(
-                                    item.span,
-                                    "multiple 'main' functions");
+                                span_err!(ctxt.session, item.span, E0136,
+                                          "multiple 'main' functions");
                             }
                         } else {
                             // This isn't main
@@ -102,9 +101,8 @@ fn find_item(item: &Item, ctxt: &mut EntryContext) {
                 if ctxt.attr_main_fn.is_none() {
                     ctxt.attr_main_fn = Some((item.id, item.span));
                 } else {
-                    ctxt.session.span_err(
-                        item.span,
-                        "multiple 'main' functions");
+                    span_err!(ctxt.session, item.span, E0137,
+                              "multiple functions with a #[main] attribute");
                 }
             }
 
@@ -112,9 +110,8 @@ fn find_item(item: &Item, ctxt: &mut EntryContext) {
                 if ctxt.start_fn.is_none() {
                     ctxt.start_fn = Some((item.id, item.span));
                 } else {
-                    ctxt.session.span_err(
-                        item.span,
-                        "multiple 'start' functions");
+                    span_err!(ctxt.session, item.span, E0138,
+                              "multiple 'start' functions");
                 }
             }
         }
index 93913f842711197bc6e032975920dfb15a3edd40..6669147b0dcacebf70cd721a5ebaf8faa8169dfe 100644 (file)
@@ -94,14 +94,12 @@ fn def_id_is_transmute(&self, def_id: DefId) -> bool {
 
     fn check_transmute(&self, span: Span, from: ty::t, to: ty::t) {
         if type_size_is_affected_by_type_parameters(self.tcx, from) {
-            self.tcx.sess.span_err(span,
-                                   "cannot transmute from a type that \
-                                    contains type parameters");
+            span_err!(self.tcx.sess, span, E0139,
+                      "cannot transmute from a type that contains type parameters");
         }
         if type_size_is_affected_by_type_parameters(self.tcx, to) {
-            self.tcx.sess.span_err(span,
-                                   "cannot transmute to a type that contains \
-                                    type parameters");
+            span_err!(self.tcx.sess, span, E0140,
+                      "cannot transmute to a type that contains type parameters");
         }
 
         let restriction = TransmuteRestriction {
index a45bb69a53ee1da04dfc46fba957807680dbf818..d2a5342c17ee86a8a83b9ae1d320a854b32dadbb 100644 (file)
@@ -92,22 +92,20 @@ fn check_struct_safe_for_destructor(cx: &mut Context,
         let struct_ty = ty::mk_struct(cx.tcx, struct_did,
                                       subst::Substs::empty());
         if !ty::type_is_sendable(cx.tcx, struct_ty) {
-            cx.tcx.sess.span_err(span,
-                                 "cannot implement a destructor on a \
-                                  structure that does not satisfy Send");
-            cx.tcx.sess.span_note(span,
-                                  "use \"#[unsafe_destructor]\" on the \
-                                   implementation to force the compiler to \
-                                   allow this");
+            span_err!(cx.tcx.sess, span, E0125,
+                      "cannot implement a destructor on a \
+                       structure that does not satisfy Send");
+            span_note!(cx.tcx.sess, span,
+                       "use \"#[unsafe_destructor]\" on the implementation \
+                        to force the compiler to allow this");
         }
     } else {
-        cx.tcx.sess.span_err(span,
-                             "cannot implement a destructor on a structure \
-                              with type parameters");
-        cx.tcx.sess.span_note(span,
-                              "use \"#[unsafe_destructor]\" on the \
-                               implementation to force the compiler to \
-                               allow this");
+        span_err!(cx.tcx.sess, span, E0141,
+                  "cannot implement a destructor on a structure \
+                   with type parameters");
+        span_note!(cx.tcx.sess, span,
+                   "use \"#[unsafe_destructor]\" on the implementation \
+                    to force the compiler to allow this");
     }
 }
 
@@ -124,14 +122,12 @@ fn check_impl_of_trait(cx: &mut Context, it: &Item, trait_ref: &TraitRef, self_t
     let self_ty: ty::t = ty::node_id_to_type(cx.tcx, it.id);
     debug!("checking impl with self type {}", ty::get(self_ty).sty);
     check_builtin_bounds(cx, self_ty, trait_def.bounds, |missing| {
-        cx.tcx.sess.span_err(self_type.span,
-            format!("the type `{}', which does not fulfill `{}`, cannot implement this \
-                    trait",
-                    ty_to_string(cx.tcx, self_ty),
-                    missing.user_string(cx.tcx)).as_slice());
-        cx.tcx.sess.span_note(self_type.span,
-            format!("types implementing this trait must fulfill `{}`",
-                    trait_def.bounds.user_string(cx.tcx)).as_slice());
+        span_err!(cx.tcx.sess, self_type.span, E0142,
+                  "the type `{}', which does not fulfill `{}`, cannot implement this trait",
+                  ty_to_string(cx.tcx, self_ty), missing.user_string(cx.tcx));
+        span_note!(cx.tcx.sess, self_type.span,
+                   "types implementing this trait must fulfill `{}`",
+                   trait_def.bounds.user_string(cx.tcx));
     });
 
     // If this is a destructor, check kinds.
@@ -191,10 +187,9 @@ fn check_for_block(cx: &Context, fv: &freevar_entry,
     }
 
     fn check_for_bare(cx: &Context, fv: &freevar_entry) {
-        cx.tcx.sess.span_err(
-            fv.span,
-            "can't capture dynamic environment in a fn item; \
-            use the || { ... } closure form instead");
+        span_err!(cx.tcx.sess, fv.span, E0143,
+                  "can't capture dynamic environment in a fn item; \
+                   use the || {} closure form instead", "{ ... }");
     } // same check is done in resolve.rs, but shouldn't be done
 
     let fty = ty::node_id_to_type(cx.tcx, id);
@@ -494,12 +489,11 @@ pub fn check_typaram_bounds(cx: &Context,
                          ty,
                          type_param_def.bounds.builtin_bounds,
                          |missing| {
-        cx.tcx.sess.span_err(
-            sp,
-            format!("instantiating a type parameter with an incompatible type \
-                     `{}`, which does not fulfill `{}`",
-                    ty_to_string(cx.tcx, ty),
-                    missing.user_string(cx.tcx)).as_slice());
+        span_err!(cx.tcx.sess, sp, E0144,
+                  "instantiating a type parameter with an incompatible type \
+                   `{}`, which does not fulfill `{}`",
+                   ty_to_string(cx.tcx, ty),
+                   missing.user_string(cx.tcx));
     });
 }
 
@@ -511,36 +505,32 @@ pub fn check_freevar_bounds(cx: &Context, sp: Span, ty: ty::t,
         // Emit a less mysterious error message in this case.
         match referenced_ty {
             Some(rty) => {
-                cx.tcx.sess.span_err(sp,
-                format!("cannot implicitly borrow variable of type `{}` in a \
-                         bounded stack closure (implicit reference does not \
-                         fulfill `{}`)",
-                        ty_to_string(cx.tcx, rty),
-                        missing.user_string(cx.tcx)).as_slice())
+                span_err!(cx.tcx.sess, sp, E0145,
+                    "cannot implicitly borrow variable of type `{}` in a \
+                     bounded stack closure (implicit reference does not fulfill `{}`)",
+                    ty_to_string(cx.tcx, rty), missing.user_string(cx.tcx));
             }
             None => {
-                cx.tcx.sess.span_err(sp,
-                format!("cannot capture variable of type `{}`, which does \
-                         not fulfill `{}`, in a bounded closure",
-                        ty_to_string(cx.tcx, ty),
-                        missing.user_string(cx.tcx)).as_slice())
+                span_err!(cx.tcx.sess, sp, E0146,
+                    "cannot capture variable of type `{}`, which does \
+                     not fulfill `{}`, in a bounded closure",
+                    ty_to_string(cx.tcx, ty), missing.user_string(cx.tcx));
             }
         }
-        cx.tcx.sess.span_note(
-            sp,
-            format!("this closure's environment must satisfy `{}`",
-                    bounds.user_string(cx.tcx)).as_slice());
+        span_note!(cx.tcx.sess, sp,
+            "this closure's environment must satisfy `{}`",
+            bounds.user_string(cx.tcx));
     });
 }
 
 pub fn check_trait_cast_bounds(cx: &Context, sp: Span, ty: ty::t,
                                bounds: ty::BuiltinBounds) {
     check_builtin_bounds(cx, ty, bounds, |missing| {
-        cx.tcx.sess.span_err(sp,
-            format!("cannot pack type `{}`, which does not fulfill \
-                     `{}`, as a trait bounded by {}",
-                    ty_to_string(cx.tcx, ty), missing.user_string(cx.tcx),
-                    bounds.user_string(cx.tcx)).as_slice());
+        span_err!(cx.tcx.sess, sp, E0147,
+            "cannot pack type `{}`, which does not fulfill `{}`, as a trait bounded by {}",
+            ty_to_string(cx.tcx, ty),
+            missing.user_string(cx.tcx),
+            bounds.user_string(cx.tcx));
     });
 }
 
@@ -549,26 +539,26 @@ fn check_copy(cx: &Context, ty: ty::t, sp: Span, reason: &str) {
            ty_to_string(cx.tcx, ty),
            ty::type_contents(cx.tcx, ty).to_string());
     if ty::type_moves_by_default(cx.tcx, ty) {
-        cx.tcx.sess.span_err(
-            sp,
-            format!("copying a value of non-copyable type `{}`",
-                    ty_to_string(cx.tcx, ty)).as_slice());
-        cx.tcx.sess.span_note(sp, format!("{}", reason).as_slice());
+        span_err!(cx.tcx.sess, sp, E0148,
+            "copying a value of non-copyable type `{}`",
+            ty_to_string(cx.tcx, ty));
+        span_note!(cx.tcx.sess, sp, "{}", reason.as_slice());
     }
 }
 
 pub fn check_static(tcx: &ty::ctxt, ty: ty::t, sp: Span) -> bool {
     if !ty::type_is_static(tcx, ty) {
         match ty::get(ty).sty {
-          ty::ty_param(..) => {
-            tcx.sess.span_err(sp,
-                format!("value may contain references; \
-                         add `'static` bound to `{}`",
-                        ty_to_string(tcx, ty)).as_slice());
-          }
-          _ => {
-            tcx.sess.span_err(sp, "value may contain references");
-          }
+            ty::ty_param(..) => {
+                span_err!(tcx.sess, sp, E0149,
+                    "value may contain references; \
+                     add `'static` bound to `{}`",
+                     ty_to_string(tcx, ty));
+            }
+            _ => {
+                span_err!(tcx.sess, sp, E0150,
+                    "value may contain references");
+            }
         }
         false
     } else {
@@ -685,11 +675,9 @@ fn is_ReScope(r: ty::Region) -> bool {
 // Ensure that `ty` has a statically known size (i.e., it has the `Sized` bound).
 fn check_sized(tcx: &ty::ctxt, ty: ty::t, name: String, sp: Span) {
     if !ty::type_is_sized(tcx, ty) {
-        tcx.sess.span_err(sp,
-                          format!("variable `{}` has dynamically sized type \
-                                   `{}`",
-                                  name,
-                                  ty_to_string(tcx, ty)).as_slice());
+        span_err!(tcx.sess, sp, E0151,
+            "variable `{}` has dynamically sized type `{}`",
+            name, ty_to_string(tcx, ty));
     }
 }
 
index 1a1d47b254770bd87293fea411963c95af53abc0..9abc9226c136456ade077a9f22b1e4fbb46d43c8 100644 (file)
@@ -27,6 +27,7 @@
 use syntax::ast;
 use syntax::ast_util::local_def;
 use syntax::attr::AttrMetaMethods;
+use syntax::codemap::{DUMMY_SP, Span};
 use syntax::parse::token::InternedString;
 use syntax::visit::Visitor;
 use syntax::visit;
@@ -122,7 +123,7 @@ fn visit_item(&mut self, item: &ast::Item, _: ()) {
 
                 match item_index {
                     Some(item_index) => {
-                        self.collect_item(item_index, local_def(item.id))
+                        self.collect_item(item_index, local_def(item.id), item.span)
                     }
                     None => {}
                 }
@@ -147,13 +148,13 @@ pub fn new(session: &'a Session) -> LanguageItemCollector<'a> {
         }
     }
 
-    pub fn collect_item(&mut self, item_index: uint, item_def_id: ast::DefId) {
+    pub fn collect_item(&mut self, item_index: uint,
+                        item_def_id: ast::DefId, span: Span) {
         // Check for duplicates.
         match self.items.items.get(item_index) {
             &Some(original_def_id) if original_def_id != item_def_id => {
-                self.session.err(format!("duplicate entry for `{}`",
-                                         LanguageItems::item_name(
-                                             item_index)).as_slice());
+                span_err!(self.session, span, E0152,
+                    "duplicate entry for `{}`", LanguageItems::item_name(item_index));
             }
             &Some(_) | &None => {
                 // OK.
@@ -173,7 +174,7 @@ pub fn collect_external_language_items(&mut self) {
         crate_store.iter_crate_data(|crate_number, _crate_metadata| {
             each_lang_item(crate_store, crate_number, |node_id, item_index| {
                 let def_id = ast::DefId { krate: crate_number, node: node_id };
-                self.collect_item(item_index, def_id);
+                self.collect_item(item_index, def_id, DUMMY_SP);
                 true
             });
         })
index 2d53d742ee44b15800ed580c6f375f65b1e87a24..faaffc7525786da0d0283ae6261a55b5829fe348 100644 (file)
 
 use middle::def::*;
 use middle::resolve;
+use middle::ty;
 
 use std::collections::HashMap;
 use std::gc::{Gc, GC};
 use syntax::ast::*;
 use syntax::ast_util::{walk_pat};
 use syntax::codemap::{Span, DUMMY_SP};
+use syntax::owned_slice::OwnedSlice;
 
 pub type PatIdMap = HashMap<Ident, NodeId>;
 
@@ -116,3 +118,15 @@ pub fn simple_identifier<'a>(pat: &'a Pat) -> Option<&'a Ident> {
 pub fn wild() -> Gc<Pat> {
     box (GC) Pat { id: 0, node: PatWild, span: DUMMY_SP }
 }
+
+pub fn def_to_path(tcx: &ty::ctxt, id: DefId) -> Path {
+    ty::with_path(tcx, id, |mut path| Path {
+        global: false,
+        segments: path.last().map(|elem| PathSegment {
+            identifier: Ident::new(elem.name()),
+            lifetimes: vec!(),
+            types: OwnedSlice::empty()
+        }).move_iter().collect(),
+        span: DUMMY_SP,
+    })
+}
index f1e6db1cab1731531413ee646e2d9998ef9cb177..a0adbf6e920ea935ab6a9a45655b72c6f4e23491 100644 (file)
@@ -4016,14 +4016,17 @@ fn resolve_struct(&mut self,
                                 this.record_def(path_id, (def, lp));
                             }
                             Some((DefStruct(_), _)) => {
-                                this.session.span_err(t.span,
-                                                      "super-struct is defined \
-                                                       in a different crate")
+                                span_err!(this.session, t.span, E0154,
+                                    "super-struct is defined in a different crate");
                             },
-                            Some(_) => this.session.span_err(t.span,
-                                                             "super-struct is not a struct type"),
-                            None => this.session.span_err(t.span,
-                                                          "super-struct could not be resolved"),
+                            Some(_) => {
+                                span_err!(this.session, t.span, E0155,
+                                    "super-struct is not a struct type");
+                            }
+                            None => {
+                                span_err!(this.session, t.span, E0156,
+                                    "super-struct could not be resolved");
+                            }
                         }
                     },
                     _ => this.session.span_bug(t.span, "path not mapped to a TyPath")
@@ -4297,17 +4300,13 @@ fn resolve_type(&mut self, ty: &Ty) {
                             if path.segments
                                    .iter()
                                    .any(|s| !s.lifetimes.is_empty()) {
-                                self.session.span_err(path.span,
-                                                      "lifetime parameters \
-                                                       are not allowed on \
-                                                       this type")
+                                span_err!(self.session, path.span, E0157,
+                                    "lifetime parameters are not allowed on this type");
                             } else if path.segments
                                           .iter()
                                           .any(|s| s.types.len() > 0) {
-                                self.session.span_err(path.span,
-                                                      "type parameters are \
-                                                       not allowed on this \
-                                                       type")
+                                span_err!(self.session, path.span, E0153,
+                                    "type parameters are not allowed on this type");
                             }
                         }
                         None => {
@@ -4398,7 +4397,7 @@ fn resolve_pattern(&mut self,
                     let ident = path1.node;
                     let renamed = mtwt::resolve(ident);
 
-                    match self.resolve_bare_identifier_pattern(ident) {
+                    match self.resolve_bare_identifier_pattern(ident, pattern.span) {
                         FoundStructOrEnumVariant(def, lp)
                                 if mode == RefutableMode => {
                             debug!("(resolving pattern) resolving `{}` to \
@@ -4562,7 +4561,7 @@ struct or enum variant",
         });
     }
 
-    fn resolve_bare_identifier_pattern(&mut self, name: Ident)
+    fn resolve_bare_identifier_pattern(&mut self, name: Ident, span: Span)
                                        -> BareIdentifierPatternResolution {
         let module = self.current_module.clone();
         match self.resolve_item_in_lexical_scope(module,
@@ -4589,6 +4588,11 @@ fn resolve_bare_identifier_pattern(&mut self, name: Ident)
                             def @ DefStatic(_, false) => {
                                 return FoundConst(def, LastMod(AllPublic));
                             }
+                            DefStatic(_, true) => {
+                                self.resolve_error(span,
+                                    "mutable static variables cannot be referenced in a pattern");
+                                return BareIdentifierPatternUnresolved;
+                            }
                             _ => {
                                 return BareIdentifierPatternUnresolved;
                             }
index 75224883cf37f1b312a89fc05a1a0e180573c78c..aeb171c068a85016a01d2ecc5f799f4a24f6aa9b 100644 (file)
 use middle::const_eval;
 use middle::def;
 use middle::check_match;
+use middle::check_match::StaticInliner;
 use middle::lang_items::StrEqFnLangItem;
 use middle::pat_util::*;
 use middle::resolve::DefMap;
 use syntax::ast;
 use syntax::ast::Ident;
 use syntax::codemap::Span;
+use syntax::fold::Folder;
 use syntax::parse::token::InternedString;
 
-// An option identifying a literal: either an expression or a DefId of a static expression.
-enum Lit {
-    ExprLit(Gc<ast::Expr>),
-    ConstLit(ast::DefId),              // the def ID of the constant
-}
-
 #[deriving(PartialEq)]
 pub enum VecLenOpt {
     vec_len_eq,
@@ -242,24 +238,15 @@ pub enum VecLenOpt {
 // An option identifying a branch (either a literal, an enum variant or a
 // range)
 enum Opt {
-    lit(Lit),
+    lit(Gc<ast::Expr>),
     var(ty::Disr, Rc<adt::Repr>, ast::DefId),
     range(Gc<ast::Expr>, Gc<ast::Expr>),
     vec_len(/* length */ uint, VecLenOpt, /*range of matches*/(uint, uint))
 }
 
-fn lit_to_expr(tcx: &ty::ctxt, a: &Lit) -> Gc<ast::Expr> {
-    match *a {
-        ExprLit(existing_a_expr) => existing_a_expr,
-        ConstLit(a_const) => const_eval::lookup_const_by_id(tcx, a_const).unwrap()
-    }
-}
-
 fn opt_eq(tcx: &ty::ctxt, a: &Opt, b: &Opt) -> bool {
     match (a, b) {
-        (&lit(a), &lit(b)) => {
-            let a_expr = lit_to_expr(tcx, &a);
-            let b_expr = lit_to_expr(tcx, &b);
+        (&lit(a_expr), &lit(b_expr)) => {
             match const_eval::compare_lit_exprs(tcx, &*a_expr, &*b_expr) {
                 Some(val1) => val1 == 0,
                 None => fail!("compare_list_exprs: type mismatch"),
@@ -286,20 +273,13 @@ pub enum opt_result<'a> {
     range_result(Result<'a>, Result<'a>),
 }
 
-fn trans_opt<'a>(bcx: &'a Block<'a>, o: &Opt) -> opt_result<'a> {
+fn trans_opt<'a>(mut bcx: &'a Block<'a>, o: &Opt) -> opt_result<'a> {
     let _icx = push_ctxt("match::trans_opt");
     let ccx = bcx.ccx();
-    let mut bcx = bcx;
     match *o {
-        lit(ExprLit(ref lit_expr)) => {
-            let lit_datum = unpack_datum!(bcx, expr::trans(bcx, &**lit_expr));
-            let lit_datum = lit_datum.assert_rvalue(bcx); // literals are rvalues
-            let lit_datum = unpack_datum!(bcx, lit_datum.to_appropriate_datum(bcx));
-            return single_result(Result::new(bcx, lit_datum.val));
-        }
-        lit(l @ ConstLit(ref def_id)) => {
-            let lit_ty = ty::node_id_to_type(bcx.tcx(), lit_to_expr(bcx.tcx(), &l).id);
-            let (llval, _) = consts::get_const_val(bcx.ccx(), *def_id);
+        lit(lit_expr) => {
+            let lit_ty = ty::node_id_to_type(bcx.tcx(), lit_expr.id);
+            let (llval, _) = consts::const_expr(ccx, &*lit_expr, true);
             let lit_datum = immediate_rvalue(llval, lit_ty);
             let lit_datum = unpack_datum!(bcx, lit_datum.to_appropriate_datum(bcx));
             return single_result(Result::new(bcx, lit_datum.val));
@@ -546,13 +526,12 @@ fn enter_opt<'a, 'b>(
     let _indenter = indenter();
 
     let ctor = match opt {
-        &lit(x) => {
-            check_match::ConstantValue(const_eval::eval_const_expr(
-                bcx.tcx(), &*lit_to_expr(bcx.tcx(), &x)))
-        }
-        &range(ref lo, ref hi) => check_match::ConstantRange(
-            const_eval::eval_const_expr(bcx.tcx(), &**lo),
-            const_eval::eval_const_expr(bcx.tcx(), &**hi)
+        &lit(expr) => check_match::ConstantValue(
+            const_eval::eval_const_expr(bcx.tcx(), &*expr)
+        ),
+        &range(lo, hi) => check_match::ConstantRange(
+            const_eval::eval_const_expr(bcx.tcx(), &*lo),
+            const_eval::eval_const_expr(bcx.tcx(), &*hi)
         ),
         &vec_len(len, _, _) => check_match::Slice(len),
         &var(_, _, def_id) => check_match::Variant(def_id)
@@ -649,7 +628,7 @@ fn add_veclen_to_set(set: &mut Vec<Opt> , i: uint,
         let cur = *br.pats.get(col);
         match cur.node {
             ast::PatLit(l) => {
-                add_to_set(ccx.tcx(), &mut found, lit(ExprLit(l)));
+                add_to_set(ccx.tcx(), &mut found, lit(l));
             }
             ast::PatIdent(..) => {
                 // This is either an enum variant or a variable binding.
@@ -659,10 +638,6 @@ fn add_veclen_to_set(set: &mut Vec<Opt> , i: uint,
                         add_to_set(ccx.tcx(), &mut found,
                                    variant_opt(bcx, cur.id));
                     }
-                    Some(def::DefStatic(const_did, false)) => {
-                        add_to_set(ccx.tcx(), &mut found,
-                                   lit(ConstLit(const_did)));
-                    }
                     _ => {}
                 }
             }
@@ -676,10 +651,6 @@ fn add_veclen_to_set(set: &mut Vec<Opt> , i: uint,
                         add_to_set(ccx.tcx(), &mut found,
                                    variant_opt(bcx, cur.id));
                     }
-                    Some(def::DefStatic(const_did, false)) => {
-                        add_to_set(ccx.tcx(), &mut found,
-                                   lit(ConstLit(const_did)));
-                    }
                     _ => {}
                 }
             }
@@ -1447,10 +1418,11 @@ fn trans_match_inner<'a>(scope_cx: &'a Block<'a>,
         bindings_map: create_bindings_map(bcx, *arm.pats.get(0))
     }).collect();
 
+    let mut static_inliner = StaticInliner { tcx: scope_cx.tcx() };
     let mut matches = Vec::new();
     for arm_data in arm_datas.iter() {
-        matches.extend(arm_data.arm.pats.iter().map(|p| Match {
-            pats: vec!(*p),
+        matches.extend(arm_data.arm.pats.iter().map(|&p| Match {
+            pats: vec![static_inliner.fold_pat(p)],
             data: arm_data,
             bound_ptrs: Vec::new(),
         }));
@@ -1754,8 +1726,6 @@ fn bind_irrefutable_pat<'a>(
                         }
                     }
                 }
-                Some(def::DefStatic(_, false)) => {
-                }
                 _ => {
                     // Nothing to do here.
                 }
index 1d0108fa3f7f29e2dce5cbbc42be861e4f023fb6..54c30e721548d4b93073bbe58db8f9691b1ef84d 100644 (file)
@@ -674,11 +674,10 @@ pub fn trans_case<'a>(bcx: &'a Block<'a>, r: &Repr, discr: Disr)
 }
 
 /**
- * Begin initializing a new value of the given case of the given
- * representation.  The fields, if any, should then be initialized via
- * `trans_field_ptr`.
+ * Set the discriminant for a new value of the given case of the given
+ * representation.
  */
-pub fn trans_start_init(bcx: &Block, r: &Repr, val: ValueRef, discr: Disr) {
+pub fn trans_set_discr(bcx: &Block, r: &Repr, val: ValueRef, discr: Disr) {
     match *r {
         CEnum(ity, min, max) => {
             assert_discr_in_range(ity, min, max, discr);
index 98342bfbcdc320643aa0d804544d3d7e6c46887a..7d7922ebfa90c56be16c22103456a4ac6b9f7c02 100644 (file)
@@ -80,7 +80,6 @@
 use std::cell::{Cell, RefCell};
 use std::rc::Rc;
 use std::{i8, i16, i32, i64};
-use std::gc::Gc;
 use syntax::abi::{X86, X86_64, Arm, Mips, Mipsel, Rust, RustCall};
 use syntax::abi::{RustIntrinsic, Abi};
 use syntax::ast_util::{local_def, is_local};
@@ -1704,6 +1703,59 @@ pub fn trans_enum_variant(ccx: &CrateContext,
         llfndecl);
 }
 
+pub fn trans_named_tuple_constructor<'a>(mut bcx: &'a Block<'a>,
+                                         ctor_ty: ty::t,
+                                         disr: ty::Disr,
+                                         args: callee::CallArgs,
+                                         dest: expr::Dest) -> Result<'a> {
+
+    let ccx = bcx.fcx.ccx;
+    let tcx = &ccx.tcx;
+
+    let result_ty = match ty::get(ctor_ty).sty {
+        ty::ty_bare_fn(ref bft) => bft.sig.output,
+        _ => ccx.sess().bug(
+            format!("trans_enum_variant_constructor: \
+                     unexpected ctor return type {}",
+                     ctor_ty.repr(tcx)).as_slice())
+    };
+
+    // Get location to store the result. If the user does not care about
+    // the result, just make a stack slot
+    let llresult = match dest {
+        expr::SaveIn(d) => d,
+        expr::Ignore => {
+            if !type_is_zero_size(ccx, result_ty) {
+                alloc_ty(bcx, result_ty, "constructor_result")
+            } else {
+                C_undef(type_of::type_of(ccx, result_ty))
+            }
+        }
+    };
+
+    if !type_is_zero_size(ccx, result_ty) {
+        let repr = adt::represent_type(ccx, result_ty);
+
+        match args {
+            callee::ArgExprs(exprs) => {
+                let fields = exprs.iter().map(|x| *x).enumerate().collect::<Vec<_>>();
+                bcx = expr::trans_adt(bcx, &*repr, disr, fields.as_slice(),
+                                      None, expr::SaveIn(llresult));
+            }
+            _ => ccx.sess().bug("expected expr as arguments for variant/struct tuple constructor")
+        }
+    }
+
+    // If the caller doesn't care about the result
+    // drop the temporary we made
+    let bcx = match dest {
+        expr::SaveIn(_) => bcx,
+        expr::Ignore => glue::drop_ty(bcx, llresult, result_ty)
+    };
+
+    Result::new(bcx, llresult)
+}
+
 pub fn trans_tuple_struct(ccx: &CrateContext,
                           _fields: &[ast::StructField],
                           ctor_id: ast::NodeId,
@@ -1746,7 +1798,6 @@ fn trans_enum_variant_or_tuple_like_struct(ccx: &CrateContext,
 
     if !type_is_zero_size(fcx.ccx, result_ty) {
         let repr = adt::represent_type(ccx, result_ty);
-        adt::trans_start_init(bcx, &*repr, fcx.llretptr.get().unwrap(), disr);
         for (i, arg_datum) in arg_datums.move_iter().enumerate() {
             let lldestptr = adt::trans_field_ptr(bcx,
                                                  &*repr,
@@ -1755,36 +1806,12 @@ fn trans_enum_variant_or_tuple_like_struct(ccx: &CrateContext,
                                                  i);
             arg_datum.store_to(bcx, lldestptr);
         }
+        adt::trans_set_discr(bcx, &*repr, fcx.llretptr.get().unwrap(), disr);
     }
 
     finish_fn(&fcx, bcx, result_ty);
 }
 
-fn trans_enum_def(ccx: &CrateContext, enum_definition: &ast::EnumDef,
-                  sp: Span, id: ast::NodeId, vi: &[Rc<ty::VariantInfo>],
-                  i: &mut uint) {
-    for variant in enum_definition.variants.iter() {
-        let disr_val = vi[*i].disr_val;
-        *i += 1;
-
-        match variant.node.kind {
-            ast::TupleVariantKind(ref args) if args.len() > 0 => {
-                let llfn = get_item_val(ccx, variant.node.id);
-                trans_enum_variant(ccx, id, &**variant, args.as_slice(),
-                                   disr_val, &param_substs::empty(), llfn);
-            }
-            ast::TupleVariantKind(_) => {
-                // Nothing to do.
-            }
-            ast::StructVariantKind(struct_def) => {
-                trans_struct_def(ccx, struct_def);
-            }
-        }
-    }
-
-    enum_variant_size_lint(ccx, enum_definition, sp, id);
-}
-
 fn enum_variant_size_lint(ccx: &CrateContext, enum_def: &ast::EnumDef, sp: Span, id: ast::NodeId) {
     let mut sizes = Vec::new(); // does no allocation if no pushes, thankfully
 
@@ -1877,12 +1904,8 @@ pub fn trans_item(ccx: &CrateContext, item: &ast::Item) {
       ast::ItemMod(ref m) => {
         trans_mod(ccx, m);
       }
-      ast::ItemEnum(ref enum_definition, ref generics) => {
-        if !generics.is_type_parameterized() {
-            let vi = ty::enum_variants(ccx.tcx(), local_def(item.id));
-            let mut i = 0;
-            trans_enum_def(ccx, enum_definition, item.span, item.id, vi.as_slice(), &mut i);
-        }
+      ast::ItemEnum(ref enum_definition, _) => {
+        enum_variant_size_lint(ccx, enum_definition, item.span, item.id);
       }
       ast::ItemStatic(_, m, ref expr) => {
           // Recurse on the expression to catch items in blocks
@@ -1909,11 +1932,6 @@ pub fn trans_item(ccx: &CrateContext, item: &ast::Item) {
       ast::ItemForeignMod(ref foreign_mod) => {
         foreign::trans_foreign_mod(ccx, foreign_mod);
       }
-      ast::ItemStruct(struct_def, ref generics) => {
-        if !generics.is_type_parameterized() {
-            trans_struct_def(ccx, struct_def);
-        }
-      }
       ast::ItemTrait(..) => {
         // Inside of this trait definition, we won't be actually translating any
         // functions, but the trait still needs to be walked. Otherwise default
@@ -1926,20 +1944,6 @@ pub fn trans_item(ccx: &CrateContext, item: &ast::Item) {
     }
 }
 
-pub fn trans_struct_def(ccx: &CrateContext, struct_def: Gc<ast::StructDef>) {
-    // If this is a tuple-like struct, translate the constructor.
-    match struct_def.ctor_id {
-        // We only need to translate a constructor if there are fields;
-        // otherwise this is a unit-like struct.
-        Some(ctor_id) if struct_def.fields.len() > 0 => {
-            let llfndecl = get_item_val(ccx, ctor_id);
-            trans_tuple_struct(ccx, struct_def.fields.as_slice(),
-                               ctor_id, &param_substs::empty(), llfndecl);
-        }
-        Some(_) | None => {}
-    }
-}
-
 // Translate a module. Doing this amounts to translating the items in the
 // module; there ends up being no artifact (aside from linkage names) of
 // separate modules in the compiled program.  That's because modules exist
index 13b8ed4df6b82a9b4b933a8ce2f5c6ce11803314..013350717171cefd2f74c1da3fbce71e9b274a32 100644 (file)
@@ -31,7 +31,7 @@ pub fn as_value(self) -> Value {
         }
     }
 
-    pub fn pred_iter(self) -> Preds {
+    pub fn pred_iter(self) -> Preds<'static> {
         self.as_value().user_iter()
             .filter(|user| user.is_a_terminator_inst())
             .map(|user| user.get_parent().unwrap())
index 8eab227ad16f7793da3e69836a979a58faf15fcf..e2ad8b4fd4680a6891587f6b76d42b3a23181707 100644 (file)
@@ -19,6 +19,7 @@
 use arena::TypedArena;
 use back::abi;
 use back::link;
+use driver::session;
 use llvm::{ValueRef, get_param};
 use llvm;
 use metadata::csearch;
@@ -54,6 +55,7 @@
 
 use std::gc::Gc;
 use syntax::ast;
+use syntax::ast_map;
 use synabi = syntax::abi;
 
 pub struct MethodData {
@@ -64,6 +66,10 @@ pub struct MethodData {
 pub enum CalleeData {
     Closure(Datum<Lvalue>),
 
+    // Constructor for enum variant/tuple-like-struct
+    // i.e. Some, Ok
+    NamedTupleConstructor(subst::Substs, ty::Disr),
+
     // Represents a (possibly monomorphized) top-level fn item or method
     // item. Note that this is just the fn-ptr and is not a Rust closure
     // value (which is a pair).
@@ -134,6 +140,23 @@ fn trans_def<'a>(bcx: &'a Block<'a>, def: def::Def, ref_expr: &ast::Expr)
         debug!("trans_def(def={}, ref_expr={})", def.repr(bcx.tcx()), ref_expr.repr(bcx.tcx()));
         let expr_ty = node_id_type(bcx, ref_expr.id);
         match def {
+            def::DefFn(did, _) if {
+                let def_id = if did.krate != ast::LOCAL_CRATE {
+                    inline::maybe_instantiate_inline(bcx.ccx(), did)
+                } else {
+                    did
+                };
+                match bcx.tcx().map.find(def_id.node) {
+                    Some(ast_map::NodeStructCtor(_)) => true,
+                    _ => false
+                }
+            } => {
+                let substs = node_id_substs(bcx, ExprId(ref_expr.id));
+                Callee {
+                    bcx: bcx,
+                    data: NamedTupleConstructor(substs, 0)
+                }
+            }
             def::DefFn(did, _) if match ty::get(expr_ty).sty {
                 ty::ty_bare_fn(ref f) => f.abi == synabi::RustIntrinsic,
                 _ => false
@@ -158,14 +181,23 @@ fn trans_def<'a>(bcx: &'a Block<'a>, def: def::Def, ref_expr: &ast::Expr)
                                                                 ref_expr.id))
             }
             def::DefVariant(tid, vid, _) => {
-                // nullary variants are not callable
-                assert!(ty::enum_variant_with_id(bcx.tcx(),
-                                                      tid,
-                                                      vid).args.len() > 0u);
-                fn_callee(bcx, trans_fn_ref(bcx, vid, ExprId(ref_expr.id)))
+                let vinfo = ty::enum_variant_with_id(bcx.tcx(), tid, vid);
+                let substs = node_id_substs(bcx, ExprId(ref_expr.id));
+
+                // Nullary variants are not callable
+                assert!(vinfo.args.len() > 0u);
+
+                Callee {
+                    bcx: bcx,
+                    data: NamedTupleConstructor(substs, vinfo.disr_val)
+                }
             }
-            def::DefStruct(def_id) => {
-                fn_callee(bcx, trans_fn_ref(bcx, def_id, ExprId(ref_expr.id)))
+            def::DefStruct(_) => {
+                let substs = node_id_substs(bcx, ExprId(ref_expr.id));
+                Callee {
+                    bcx: bcx,
+                    data: NamedTupleConstructor(substs, 0)
+                }
             }
             def::DefStatic(..) |
             def::DefArg(..) |
@@ -490,8 +522,27 @@ pub fn trans_fn_ref_with_vtables(
         }
     };
 
-    // We must monomorphise if the fn has type parameters or is a default method.
-    let must_monomorphise = !substs.types.is_empty() || is_default;
+    // We must monomorphise if the fn has type parameters, is a default method,
+    // or is a named tuple constructor.
+    let must_monomorphise = if !substs.types.is_empty() || is_default {
+        true
+    } else if def_id.krate == ast::LOCAL_CRATE {
+        let map_node = session::expect(
+            ccx.sess(),
+            tcx.map.find(def_id.node),
+            || "local item should be in ast map".to_string());
+
+        match map_node {
+            ast_map::NodeVariant(v) => match v.node.kind {
+                ast::TupleVariantKind(ref args) => args.len() > 0,
+                _ => false
+            },
+            ast_map::NodeStructCtor(_) => true,
+            _ => false
+        }
+    } else {
+        false
+    };
 
     // Create a monomorphic version of generic functions
     if must_monomorphise {
@@ -710,6 +761,14 @@ pub fn trans_call_inner<'a>(
                                                    arg_cleanup_scope, args,
                                                    dest.unwrap(), substs);
         }
+        NamedTupleConstructor(substs, disr) => {
+            assert!(dest.is_some());
+            fcx.pop_custom_cleanup_scope(arg_cleanup_scope);
+
+            let ctor_ty = callee_ty.subst(bcx.tcx(), &substs);
+            return base::trans_named_tuple_constructor(bcx, ctor_ty, disr,
+                                                       args, dest.unwrap());
+        }
     };
 
     // Intrinsics should not become actual functions.
index a3d8ab1733f97cbe39409ca1001eba86f01bbd15..ed6050b6543bc40c5235c4a624d6736e2600e1bb 100644 (file)
@@ -502,7 +502,6 @@ pub fn trans_unboxed_closure<'a>(
     let repr = adt::represent_type(bcx.ccx(), node_id_type(bcx, id));
 
     // Create the closure.
-    adt::trans_start_init(bcx, &*repr, dest_addr, 0);
     for freevar in freevars_ptr.iter() {
         let datum = expr::trans_local_var(bcx, freevar.def);
         let upvar_slot_dest = adt::trans_field_ptr(bcx,
@@ -512,6 +511,7 @@ pub fn trans_unboxed_closure<'a>(
                                                    0);
         bcx = datum.store_to(bcx, upvar_slot_dest);
     }
+    adt::trans_set_discr(bcx, &*repr, dest_addr, 0);
 
     bcx
 }
index e7bde00b3ded9d1ae2c5c771bc1a448ba3d6f456..68f577faefed0521a7295b3ea8d552153e7bf22c 100644 (file)
@@ -876,8 +876,8 @@ fn trans_def_dps_unadjusted<'a>(
                 // Nullary variant.
                 let ty = expr_ty(bcx, ref_expr);
                 let repr = adt::represent_type(bcx.ccx(), ty);
-                adt::trans_start_init(bcx, &*repr, lldest,
-                                      variant_info.disr_val);
+                adt::trans_set_discr(bcx, &*repr, lldest,
+                                     variant_info.disr_val);
                 return bcx;
             }
         }
@@ -886,7 +886,7 @@ fn trans_def_dps_unadjusted<'a>(
             match ty::get(ty).sty {
                 ty::ty_struct(did, _) if ty::has_dtor(bcx.tcx(), did) => {
                     let repr = adt::represent_type(bcx.ccx(), ty);
-                    adt::trans_start_init(bcx, &*repr, lldest, 0);
+                    adt::trans_set_discr(bcx, &*repr, lldest, 0);
                 }
                 _ => {}
             }
@@ -1098,7 +1098,7 @@ fn trans_rec_or_struct<'a>(
  * Note that `fields` may be empty; the base expression must always be
  * evaluated for side-effects.
  */
-struct StructBaseInfo {
+pub struct StructBaseInfo {
     /// The base expression; will be evaluated after all explicit fields.
     expr: Gc<ast::Expr>,
     /// The indices of fields to copy paired with their types.
@@ -1114,14 +1114,12 @@ struct StructBaseInfo {
  * - `optbase` contains information on the base struct (if any) from
  * which remaining fields are copied; see comments on `StructBaseInfo`.
  */
-fn trans_adt<'a>(
-             bcx: &'a Block<'a>,
-             repr: &adt::Repr,
-             discr: ty::Disr,
-             fields: &[(uint, Gc<ast::Expr>)],
-             optbase: Option<StructBaseInfo>,
-             dest: Dest)
-             -> &'a Block<'a> {
+pub fn trans_adt<'a>(bcx: &'a Block<'a>,
+                     repr: &adt::Repr,
+                     discr: ty::Disr,
+                     fields: &[(uint, Gc<ast::Expr>)],
+                     optbase: Option<StructBaseInfo>,
+                     dest: Dest) -> &'a Block<'a> {
     let _icx = push_ctxt("trans_adt");
     let fcx = bcx.fcx;
     let mut bcx = bcx;
@@ -1143,8 +1141,6 @@ fn trans_adt<'a>(
     // failure occur before the ADT as a whole is ready.
     let custom_cleanup_scope = fcx.push_custom_cleanup_scope();
 
-    adt::trans_start_init(bcx, repr, addr, discr);
-
     for &(i, ref e) in fields.iter() {
         let dest = adt::trans_field_ptr(bcx, repr, addr, discr, i);
         let e_ty = expr_ty_adjusted(bcx, &**e);
@@ -1166,6 +1162,8 @@ fn trans_adt<'a>(
         }
     }
 
+    adt::trans_set_discr(bcx, repr, addr, discr);
+
     fcx.pop_custom_cleanup_scope(custom_cleanup_scope);
 
     return bcx;
index aad7ba95a73a964b7bfda8d3b45ebbde959dfed9..7afba95a98b577a267c72bc0977fca1a13741437 100644 (file)
@@ -178,33 +178,12 @@ pub fn lazily_emit_visit_glue(ccx: &CrateContext, ti: &tydesc_info) -> ValueRef
 }
 
 // See [Note-arg-mode]
-pub fn call_visit_glue(bcx: &Block, v: ValueRef, tydesc: ValueRef,
-                       static_ti: Option<&tydesc_info>) {
-    let _icx = push_ctxt("call_tydesc_glue_full");
-    let ccx = bcx.ccx();
-    // NB: Don't short-circuit even if this block is unreachable because
-    // GC-based cleanup needs to the see that the roots are live.
-    if bcx.unreachable.get() && !ccx.sess().no_landing_pads() { return; }
-
-    let static_glue_fn = static_ti.map(|sti| lazily_emit_visit_glue(ccx, sti));
-
-    // When static type info is available, avoid casting to a generic pointer.
-    let llrawptr = if static_glue_fn.is_none() {
-        PointerCast(bcx, v, Type::i8p(ccx))
-    } else {
-        v
-    };
+pub fn call_visit_glue(bcx: &Block, v: ValueRef, tydesc: ValueRef) {
+    let _icx = push_ctxt("call_visit_glue");
 
-    let llfn = {
-        match static_glue_fn {
-            None => {
-                // Select out the glue function to call from the tydesc
-                let llfnptr = GEPi(bcx, tydesc, [0u, abi::tydesc_field_visit_glue]);
-                Load(bcx, llfnptr)
-            }
-            Some(sgf) => sgf
-        }
-    };
+    // Select the glue function to call from the tydesc
+    let llfn = Load(bcx, GEPi(bcx, tydesc, [0u, abi::tydesc_field_visit_glue]));
+    let llrawptr = PointerCast(bcx, v, Type::i8p(bcx.ccx()));
 
     Call(bcx, llfn, [llrawptr], []);
 }
index 2e3d7b291eab170ef15dbcc2c6bf48eef2612e45..bf8893904caba29899bfe76e2760bc6e375d68df 100644 (file)
@@ -296,7 +296,7 @@ pub fn trans_intrinsic_call<'a>(mut bcx: &'a Block<'a>, node: ast::NodeId,
             let td = *llargs.get(0);
             let visitor = *llargs.get(1);
             let td = PointerCast(bcx, td, ccx.tydesc_type().ptr_to());
-            glue::call_visit_glue(bcx, visitor, td, None);
+            glue::call_visit_glue(bcx, visitor, td);
             C_nil(ccx)
         }
         (_, "offset") => {
index 50563d42e44122bc9fdbb08ac6364139ee894499..9b55ee657fc00de0e585fc55a814c43dd5859827 100644 (file)
@@ -4872,3 +4872,55 @@ pub enum ExplicitSelfCategory {
     ByBoxExplicitSelfCategory,
 }
 
+/// Pushes all the lifetimes in the given type onto the given list. A
+/// "lifetime in a type" is a lifetime specified by a reference or a lifetime
+/// in a list of type substitutions. This does *not* traverse into nominal
+/// types, nor does it resolve fictitious types.
+pub fn accumulate_lifetimes_in_type(accumulator: &mut Vec<ty::Region>,
+                                    typ: t) {
+    walk_ty(typ, |typ| {
+        match get(typ).sty {
+            ty_rptr(region, _) => accumulator.push(region),
+            ty_enum(_, ref substs) |
+            ty_trait(box TyTrait {
+                substs: ref substs,
+                ..
+            }) |
+            ty_struct(_, ref substs) => {
+                match substs.regions {
+                    subst::ErasedRegions => {}
+                    subst::NonerasedRegions(ref regions) => {
+                        for region in regions.iter() {
+                            accumulator.push(*region)
+                        }
+                    }
+                }
+            }
+            ty_closure(ref closure_ty) => {
+                match closure_ty.store {
+                    RegionTraitStore(region, _) => accumulator.push(region),
+                    UniqTraitStore => {}
+                }
+            }
+            ty_nil |
+            ty_bot |
+            ty_bool |
+            ty_char |
+            ty_int(_) |
+            ty_uint(_) |
+            ty_float(_) |
+            ty_box(_) |
+            ty_uniq(_) |
+            ty_str |
+            ty_vec(_, _) |
+            ty_ptr(_) |
+            ty_bare_fn(_) |
+            ty_tup(_) |
+            ty_param(_) |
+            ty_infer(_) |
+            ty_unboxed_closure(_) |
+            ty_err => {}
+        }
+    })
+}
+
index 56fda065796778ea7b330c8f872c3984ad5a2330..e129492dbc2f8f5e3a67fe426c2aa5a32a9c4f99 100644 (file)
@@ -55,6 +55,7 @@
 use middle::subst::{FnSpace, TypeSpace, SelfSpace, Subst, Substs};
 use middle::ty;
 use middle::ty_fold::TypeFolder;
+use middle::typeck::rscope::{ExplicitRscope, ImpliedSingleRscope};
 use middle::typeck::rscope::RegionScope;
 use middle::typeck::{TypeAndSubsts, infer, lookup_def_tcx, rscope};
 use middle::typeck;
@@ -129,8 +130,8 @@ pub fn opt_ast_region_to_region<AC:AstConv,RS:RegionScope>(
             match rscope.anon_regions(default_span, 1) {
                 Err(()) => {
                     debug!("optional region in illegal location");
-                    this.tcx().sess.span_err(
-                        default_span, "missing lifetime specifier");
+                    span_err!(this.tcx().sess, default_span, E0106,
+                        "missing lifetime specifier");
                     ty::ReStatic
                 }
 
@@ -187,12 +188,9 @@ fn ast_path_substs<AC:AstConv,RS:RegionScope>(
             rscope.anon_regions(path.span, expected_num_region_params);
 
         if supplied_num_region_params != 0 || anon_regions.is_err() {
-            tcx.sess.span_err(
-                path.span,
-                format!("wrong number of lifetime parameters: \
-                        expected {} but found {}",
-                        expected_num_region_params,
-                        supplied_num_region_params).as_slice());
+            span_err!(tcx.sess, path.span, E0107,
+                "wrong number of lifetime parameters: expected {} but found {}",
+                expected_num_region_params, supplied_num_region_params);
         }
 
         match anon_regions {
@@ -235,10 +233,10 @@ fn ast_path_substs<AC:AstConv,RS:RegionScope>(
 
     if supplied_ty_param_count > required_ty_param_count
         && !this.tcx().sess.features.default_type_params.get() {
-        this.tcx().sess.span_err(path.span, "default type parameters are \
-                                             experimental and possibly buggy");
-        this.tcx().sess.span_note(path.span, "add #![feature(default_type_params)] \
-                                              to the crate attributes to enable");
+        span_err!(this.tcx().sess, path.span, E0108,
+            "default type parameters are experimental and possibly buggy");
+        span_note!(this.tcx().sess, path.span,
+            "add #![feature(default_type_params)] to the crate attributes to enable");
     }
 
     let tps = path.segments.iter().flat_map(|s| s.types.iter())
@@ -309,16 +307,14 @@ fn check_path_args(tcx: &ty::ctxt,
                    flags: uint) {
     if (flags & NO_TPS) != 0u {
         if !path.segments.iter().all(|s| s.types.is_empty()) {
-            tcx.sess.span_err(
-                path.span,
+            span_err!(tcx.sess, path.span, E0109,
                 "type parameters are not allowed on this type");
         }
     }
 
     if (flags & NO_REGIONS) != 0u {
         if !path.segments.last().unwrap().lifetimes.is_empty() {
-            tcx.sess.span_err(
-                path.span,
+            span_err!(tcx.sess, path.span, E0110,
                 "region parameters are not allowed on this type");
         }
     }
@@ -359,8 +355,8 @@ pub fn ast_ty_to_prim_ty(tcx: &ty::ctxt, ast_ty: &ast::Ty) -> Option<ty::t> {
                             Some(ty::mk_mach_float(ft))
                         }
                         ast::TyStr => {
-                            tcx.sess.span_err(ast_ty.span,
-                                              "bare `str` is not a type");
+                            span_err!(tcx.sess, ast_ty.span, E0037,
+                                      "bare `str` is not a type");
                             // return /something/ so they can at least get more errors
                             Some(ty::mk_uniq(tcx, ty::mk_str(tcx)))
                         }
@@ -408,10 +404,8 @@ pub fn ast_ty_to_builtin_ty<AC:AstConv,
                            .iter()
                            .flat_map(|s| s.types.iter())
                            .count() > 1 {
-                        this.tcx()
-                            .sess
-                            .span_err(path.span,
-                                      "`Box` has only one type parameter")
+                        span_err!(this.tcx().sess, path.span, E0047,
+                                  "`Box` has only one type parameter");
                     }
 
                     for inner_ast_type in path.segments
@@ -428,16 +422,12 @@ pub fn ast_ty_to_builtin_ty<AC:AstConv,
                                                |typ| {
                             match ty::get(typ).sty {
                                 ty::ty_str => {
-                                    this.tcx()
-                                        .sess
-                                        .span_err(path.span,
-                                                  "`Box<str>` is not a type");
+                                    span_err!(this.tcx().sess, path.span, E0111,
+                                              "`Box<str>` is not a type");
                                     ty::mk_err()
                                 }
                                 ty::ty_vec(_, None) => {
-                                    this.tcx()
-                                        .sess
-                                        .span_err(path.span,
+                                        span_err!(this.tcx().sess, path.span, E0112,
                                                   "`Box<[T]>` is not a type");
                                     ty::mk_err()
                                 }
@@ -445,9 +435,8 @@ pub fn ast_ty_to_builtin_ty<AC:AstConv,
                             }
                         }))
                     }
-                    this.tcx().sess.span_err(path.span,
-                                             "not enough type parameters \
-                                              supplied to `Box<T>`");
+                    span_err!(this.tcx().sess, path.span, E0113,
+                              "not enough type parameters supplied to `Box<T>`");
                     Some(ty::mk_err())
                 }
                 def::DefTy(did) | def::DefStruct(did)
@@ -456,10 +445,8 @@ pub fn ast_ty_to_builtin_ty<AC:AstConv,
                            .iter()
                            .flat_map(|s| s.types.iter())
                            .count() > 1 {
-                        this.tcx()
-                            .sess
-                            .span_err(path.span,
-                                      "`Gc` has only one type parameter")
+                        span_err!(this.tcx().sess, path.span, E0048,
+                                  "`Gc` has only one type parameter");
                     }
 
                     for inner_ast_type in path.segments
@@ -476,17 +463,13 @@ pub fn ast_ty_to_builtin_ty<AC:AstConv,
                                                |typ| {
                             match ty::get(typ).sty {
                                 ty::ty_str => {
-                                    this.tcx()
-                                        .sess
-                                        .span_err(path.span,
-                                                  "`Gc<str>` is not a type");
+                                    span_err!(this.tcx().sess, path.span, E0114,
+                                              "`Gc<str>` is not a type");
                                     ty::mk_err()
                                 }
                                 ty::ty_vec(_, None) => {
-                                    this.tcx()
-                                        .sess
-                                        .span_err(path.span,
-                                                  "`Gc<[T]>` is not a type");
+                                    span_err!(this.tcx().sess, path.span, E0115,
+                                              "`Gc<[T]>` is not a type");
                                     ty::mk_err()
                                 }
                                 _ => ty::mk_box(this.tcx(), typ),
@@ -949,31 +932,45 @@ fn ty_of_method_or_bare_fn<AC:AstConv>(
                                Option<ty::ExplicitSelfCategory>) {
     debug!("ty_of_method_or_bare_fn");
 
-    // new region names that appear inside of the fn decl are bound to
-    // that function type
+    // New region names that appear inside of the arguments of the function
+    // declaration are bound to that function type.
     let rb = rscope::BindingRscope::new(id);
 
+    // `implied_output_region` is the region that will be assumed for any
+    // region parameters in the return type. In accordance with the rules for
+    // lifetime elision, we can determine it in two ways. First (determined
+    // here), if self is by-reference, then the implied output region is the
+    // region of the self parameter.
     let mut explicit_self_category_result = None;
-    let self_ty = opt_self_info.and_then(|self_info| {
-        // Figure out and record the explicit self category.
-        let explicit_self_category =
-            determine_explicit_self_category(this, &rb, &self_info);
-        explicit_self_category_result = Some(explicit_self_category);
-        match explicit_self_category {
-            ty::StaticExplicitSelfCategory => None,
-            ty::ByValueExplicitSelfCategory => {
-                Some(self_info.untransformed_self_ty)
-            }
-            ty::ByReferenceExplicitSelfCategory(region, mutability) => {
-                Some(ty::mk_rptr(this.tcx(), region,
-                                 ty::mt {ty: self_info.untransformed_self_ty,
-                                         mutbl: mutability}))
-            }
-            ty::ByBoxExplicitSelfCategory => {
-                Some(ty::mk_uniq(this.tcx(), self_info.untransformed_self_ty))
+    let (self_ty, mut implied_output_region) = match opt_self_info {
+        None => (None, None),
+        Some(self_info) => {
+            // Figure out and record the explicit self category.
+            let explicit_self_category =
+                determine_explicit_self_category(this, &rb, &self_info);
+            explicit_self_category_result = Some(explicit_self_category);
+            match explicit_self_category {
+                ty::StaticExplicitSelfCategory => (None, None),
+                ty::ByValueExplicitSelfCategory => {
+                    (Some(self_info.untransformed_self_ty), None)
+                }
+                ty::ByReferenceExplicitSelfCategory(region, mutability) => {
+                    (Some(ty::mk_rptr(this.tcx(),
+                                      region,
+                                      ty::mt {
+                                        ty: self_info.untransformed_self_ty,
+                                        mutbl: mutability
+                                      })),
+                     Some(region))
+                }
+                ty::ByBoxExplicitSelfCategory => {
+                    (Some(ty::mk_uniq(this.tcx(),
+                                      self_info.untransformed_self_ty)),
+                     None)
+                }
             }
         }
-    });
+    };
 
     // HACK(eddyb) replace the fake self type in the AST with the actual type.
     let input_tys = if self_ty.is_some() {
@@ -982,12 +979,47 @@ fn ty_of_method_or_bare_fn<AC:AstConv>(
         decl.inputs.as_slice()
     };
     let input_tys = input_tys.iter().map(|a| ty_of_arg(this, &rb, a, None));
+    let self_and_input_tys: Vec<_> =
+        self_ty.move_iter().chain(input_tys).collect();
+
+    // Second, if there was exactly one lifetime (either a substitution or a
+    // reference) in the arguments, then any anonymous regions in the output
+    // have that lifetime.
+    if implied_output_region.is_none() {
+        let mut self_and_input_tys_iter = self_and_input_tys.iter();
+        if self_ty.is_some() {
+            // Skip the first argument if `self` is present.
+            drop(self_and_input_tys_iter.next())
+        }
 
-    let self_and_input_tys = self_ty.move_iter().chain(input_tys).collect();
+        let mut accumulator = Vec::new();
+        for input_type in self_and_input_tys_iter {
+            ty::accumulate_lifetimes_in_type(&mut accumulator, *input_type)
+        }
+        if accumulator.len() == 1 {
+            implied_output_region = Some(*accumulator.get(0));
+        }
+    }
 
     let output_ty = match decl.output.node {
         ast::TyInfer => this.ty_infer(decl.output.span),
-        _ => ast_ty_to_ty(this, &rb, &*decl.output)
+        _ => {
+            match implied_output_region {
+                Some(implied_output_region) => {
+                    let rb = ImpliedSingleRscope {
+                        region: implied_output_region,
+                    };
+                    ast_ty_to_ty(this, &rb, &*decl.output)
+                }
+                None => {
+                    // All regions must be explicitly specified in the output
+                    // if the lifetime elision rules do not apply. This saves
+                    // the user from potentially-confusing errors.
+                    let rb = ExplicitRscope;
+                    ast_ty_to_ty(this, &rb, &*decl.output)
+                }
+            }
+        }
     };
 
     (ty::BareFnTy {
index ea82a62d6c684f39b58c6683fe3ec2e740a743b1..c176054b3aed0e0d289cd3c8f767730e09d4e91e 100644 (file)
@@ -206,11 +206,10 @@ fn relate_trait_refs(vcx: &VtableContext,
                 !ty::trait_ref_contains_error(&r_exp_trait_ref)
             {
                 let tcx = vcx.tcx();
-                tcx.sess.span_err(span,
-                    format!("expected {}, but found {} ({})",
-                            ppaux::trait_ref_to_string(tcx, &r_exp_trait_ref),
-                            ppaux::trait_ref_to_string(tcx, &r_act_trait_ref),
-                            ty::type_err_to_str(tcx, err)).as_slice());
+                span_err!(tcx.sess, span, E0095, "expected {}, but found {} ({})",
+                          ppaux::trait_ref_to_string(tcx, &r_exp_trait_ref),
+                          ppaux::trait_ref_to_string(tcx, &r_act_trait_ref),
+                          ty::type_err_to_str(tcx, err));
             }
         }
     }
@@ -536,7 +535,8 @@ fn search_for_vtable(vcx: &VtableContext,
         1 => return Some(found.get(0).clone()),
         _ => {
             if !is_early {
-                vcx.tcx().sess.span_err(span, "multiple applicable methods in scope");
+                span_err!(vcx.tcx().sess, span, E0096,
+                          "multiple applicable methods in scope");
             }
             return Some(found.get(0).clone());
         }
@@ -631,9 +631,7 @@ fn mutability_allowed(a_mutbl: ast::Mutability,
             if !mutability_allowed(mt.mutbl, mutbl) => {
               match ty::get(ty).sty {
                   ty::ty_trait(..) => {
-                      fcx.tcx()
-                         .sess
-                         .span_err(ex.span, "types differ in mutability");
+                      span_err!(fcx.tcx().sess, ex.span, E0097, "types differ in mutability");
                   }
                   _ => {}
               }
@@ -709,11 +707,9 @@ fn mutability_allowed(a_mutbl: ast::Mutability,
           (&ty::ty_uniq(ty), _) => {
               match ty::get(ty).sty {
                   ty::ty_trait(..) => {
-                      fcx.ccx.tcx.sess.span_err(
-                          ex.span,
-                          format!("can only cast an boxed pointer \
-                                   to a boxed object, not a {}",
-                               ty::ty_sort_string(fcx.tcx(), src_ty)).as_slice());
+                      span_err!(fcx.ccx.tcx.sess, ex.span, E0098,
+                                "can only cast an boxed pointer to a boxed object, not a {}",
+                                ty::ty_sort_string(fcx.tcx(), src_ty));
                   }
                   _ => {}
               }
@@ -722,11 +718,9 @@ fn mutability_allowed(a_mutbl: ast::Mutability,
           (&ty::ty_rptr(_, ty::mt{ty, ..}), _) => {
               match ty::get(ty).sty {
                   ty::ty_trait(..) => {
-                      fcx.ccx.tcx.sess.span_err(
-                          ex.span,
-                          format!("can only cast an &-pointer \
-                                   to an &-object, not a {}",
-                                  ty::ty_sort_string(fcx.tcx(), src_ty)).as_slice());
+                      span_err!(fcx.ccx.tcx.sess, ex.span, E0099,
+                                "can only cast an &-pointer to an &-object, not a {}",
+                                ty::ty_sort_string(fcx.tcx(), src_ty));
                   }
                   _ => {}
               }
index d802e3d14433c3590a10e319b7d328e0ca95af56..c3e7d06f3f896dd28a458b41955237442946da0c 100644 (file)
@@ -261,9 +261,8 @@ fn visit_adjustments(&self, reason: ResolveReason, id: ast::NodeId) {
                             Some(&def::DefStruct(_)) => {
                             }
                             _ => {
-                                self.tcx().sess.span_err(
-                                    reason.span(self.tcx()),
-                                    "cannot coerce non-statically resolved bare fn")
+                                span_err!(self.tcx().sess, reason.span(self.tcx()), E0100,
+                                    "cannot coerce non-statically resolved bare fn");
                             }
                         }
 
@@ -431,47 +430,34 @@ fn report_error(&self, e: infer::fixup_err) {
         if !self.tcx.sess.has_errors() {
             match self.reason {
                 ResolvingExpr(span) => {
-                    self.tcx.sess.span_err(
-                        span,
-                        format!("cannot determine a type for \
-                                 this expression: {}",
-                                infer::fixup_err_to_string(e)).as_slice())
+                    span_err!(self.tcx.sess, span, E0101,
+                        "cannot determine a type for this expression: {}",
+                        infer::fixup_err_to_string(e));
                 }
 
                 ResolvingLocal(span) => {
-                    self.tcx.sess.span_err(
-                        span,
-                        format!("cannot determine a type for \
-                                 this local variable: {}",
-                                infer::fixup_err_to_string(e)).as_slice())
+                    span_err!(self.tcx.sess, span, E0102,
+                        "cannot determine a type for this local variable: {}",
+                        infer::fixup_err_to_string(e));
                 }
 
                 ResolvingPattern(span) => {
-                    self.tcx.sess.span_err(
-                        span,
-                        format!("cannot determine a type for \
-                                 this pattern binding: {}",
-                                infer::fixup_err_to_string(e)).as_slice())
+                    span_err!(self.tcx.sess, span, E0103,
+                        "cannot determine a type for this pattern binding: {}",
+                        infer::fixup_err_to_string(e));
                 }
 
                 ResolvingUpvar(upvar_id) => {
                     let span = self.reason.span(self.tcx);
-                    self.tcx.sess.span_err(
-                        span,
-                        format!("cannot resolve lifetime for \
-                                 captured variable `{}`: {}",
-                                ty::local_var_name_str(
-                                    self.tcx,
-                                    upvar_id.var_id).get().to_string(),
-                                infer::fixup_err_to_string(e)).as_slice());
+                    span_err!(self.tcx.sess, span, E0104,
+                        "cannot resolve lifetime for captured variable `{}`: {}",
+                        ty::local_var_name_str(self.tcx, upvar_id.var_id).get().to_string(),
+                        infer::fixup_err_to_string(e));
                 }
 
                 ResolvingImplRes(span) => {
-                    self.tcx
-                        .sess
-                        .span_err(span,
-                                  "cannot determine a type for impl \
-                                   supertrait");
+                    span_err!(self.tcx.sess, span, E0105,
+                        "cannot determine a type for impl supertrait");
                 }
 
                 ResolvingUnboxedClosure(_) => {
index 9e6d059650cc5b0aede25a72194cde54fcc340d2..fe140cf2c97c28e9fd1d3eee9d14a06828bfd182 100644 (file)
@@ -224,10 +224,10 @@ fn visit_item(&mut self, item: &Item, _: ()) {
                 if !self.cc.ast_type_is_defined_in_local_crate(&**ast_ty) {
                     // This is an error.
                     let session = &self.cc.crate_context.tcx.sess;
-                    session.span_err(item.span,
-                                     "cannot associate methods with a type outside the \
-                                     crate the type is defined in; define and implement \
-                                     a trait or new type instead");
+                    span_err!(session, item.span, E0116,
+                              "cannot associate methods with a type outside the \
+                               crate the type is defined in; define and implement \
+                               a trait or new type instead");
                 }
             }
             ItemImpl(_, Some(ref trait_ref), _, _) => {
@@ -244,9 +244,9 @@ fn visit_item(&mut self, item: &Item, _: ()) {
 
                     if trait_def_id.krate != LOCAL_CRATE {
                         let session = &self.cc.crate_context.tcx.sess;
-                        session.span_err(item.span,
-                                "cannot provide an extension implementation \
-                                where both trait and type are not defined in this crate");
+                        span_err!(session, item.span, E0117,
+                                  "cannot provide an extension implementation \
+                                   where both trait and type are not defined in this crate");
                     }
                 }
 
@@ -302,9 +302,9 @@ fn check_implementation(&self, item: &Item,
                                        self_type.ty) {
                 None => {
                     let session = &self.crate_context.tcx.sess;
-                    session.span_err(item.span,
-                                     "no base type found for inherent implementation; \
-                                      implement a trait or new type instead");
+                    span_err!(session, item.span, E0118,
+                              "no base type found for inherent implementation; \
+                               implement a trait or new type instead");
                 }
                 Some(_) => {
                     // Nothing to do.
@@ -441,22 +441,18 @@ fn check_implementation_coherence_of(&self, trait_def_id: DefId) {
 
                     if self.polytypes_unify(polytype_a.clone(), polytype_b) {
                         let session = &self.crate_context.tcx.sess;
-                        session.span_err(
-                            self.span_of_impl(impl_a),
-                            format!("conflicting implementations for trait `{}`",
-                                    ty::item_path_str(
-                                        self.crate_context.tcx,
-                                        trait_def_id)).as_slice());
+                        span_err!(session, self.span_of_impl(impl_a), E0119,
+                                  "conflicting implementations for trait `{}`",
+                                  ty::item_path_str(self.crate_context.tcx, trait_def_id));
                         if impl_b.krate == LOCAL_CRATE {
-                            session.span_note(self.span_of_impl(impl_b),
-                                              "note conflicting implementation here");
+                            span_note!(session, self.span_of_impl(impl_b),
+                                       "note conflicting implementation here");
                         } else {
                             let crate_store = &self.crate_context.tcx.sess.cstore;
                             let cdata = crate_store.get_crate_data(impl_b.krate);
-                            session.note(
-                                format!("conflicting implementation in crate \
-                                         `{}`",
-                                        cdata.name).as_slice());
+                            span_note!(session, self.span_of_impl(impl_a),
+                                       "conflicting implementation in crate `{}`",
+                                       cdata.name);
                         }
                     }
                 }
@@ -706,10 +702,8 @@ fn populate_destructor_table(&self) {
                         {
                             match tcx.map.find(impl_did.node) {
                                 Some(ast_map::NodeItem(item)) => {
-                                    tcx.sess.span_err((*item).span,
-                                                      "the Drop trait may \
-                                                       only be implemented \
-                                                       on structures");
+                                    span_err!(tcx.sess, item.span, E0120,
+                                        "the Drop trait may only be implemented on structures");
                                 }
                                 _ => {
                                     tcx.sess.bug("didn't find impl in ast \
index 5fd9b85d69aa044f960dffc965d0bb9e81ebc2e5..780faddb88639c8e384bc46882da01caa7dbdb09 100644 (file)
@@ -140,9 +140,8 @@ fn get_trait_def(&self, id: ast::DefId) -> Rc<ty::TraitDef> {
     }
 
     fn ty_infer(&self, span: Span) -> ty::t {
-        self.tcx.sess.span_err(span, "the type placeholder `_` is not \
-                                      allowed within types on item \
-                                      signatures.");
+        span_err!(self.tcx.sess, span, E0121,
+                  "the type placeholder `_` is not allowed within types on item signatures.");
         ty::mk_err()
     }
 }
@@ -439,10 +438,8 @@ pub fn ensure_no_ty_param_bounds(ccx: &CrateCtxt,
                                  thing: &'static str) {
     for ty_param in generics.ty_params.iter() {
         if ty_param.bounds.len() > 0 {
-            ccx.tcx.sess.span_err(
-                span,
-                format!("trait bounds are not allowed in {} definitions",
-                        thing).as_slice());
+            span_err!(ccx.tcx.sess, span, E0122,
+                      "trait bounds are not allowed in {} definitions", thing);
         }
     }
 }
@@ -453,8 +450,8 @@ fn ensure_generics_abi(ccx: &CrateCtxt,
                        generics: &ast::Generics) {
     if generics.ty_params.len() > 0 &&
        !(abi == abi::Rust || abi == abi::RustIntrinsic) {
-        ccx.tcx.sess.span_err(span,
-                              "foreign functions may not use type parameters");
+        span_err!(ccx.tcx.sess, span, E0123,
+                  "foreign functions may not use type parameters");
     }
 }
 
@@ -607,12 +604,10 @@ pub fn convert_struct(ccx: &CrateCtxt,
         if result.name != special_idents::unnamed_field.name {
             let dup = match seen_fields.find(&result.name) {
                 Some(prev_span) => {
-                    tcx.sess.span_err(
-                        f.span,
-                        format!("field `{}` is already declared",
-                                token::get_name(result.name)).as_slice());
-                    tcx.sess.span_note(*prev_span,
-                                       "previously declared here");
+                    span_err!(tcx.sess, f.span, E0124,
+                              "field `{}` is already declared",
+                              token::get_name(result.name));
+                    span_note!(tcx.sess, *prev_span, "previously declared here");
                     true
                 },
                 None => false,
@@ -641,9 +636,9 @@ pub fn convert_struct(ccx: &CrateCtxt,
                             Some(ast_map::NodeItem(i)) => match i.node {
                                 ast::ItemStruct(struct_def, _) => {
                                     if !struct_def.is_virtual {
-                                        tcx.sess.span_err(t.span,
-                                            "struct inheritance is only \
-                                             allowed from virtual structs");
+                                        span_err!(tcx.sess, t.span, E0126,
+                                                  "struct inheritance is only \
+                                                   allowed from virtual structs");
                                     }
                                 },
                                 _ => {},
@@ -862,8 +857,8 @@ fn ensure_supertraits(ccx: &CrateCtxt,
                 {
                     // This means a trait inherited from the same
                     // supertrait more than once.
-                    tcx.sess.span_err(sp, "duplicate supertrait in \
-                                           trait declaration");
+                    span_err!(tcx.sess, sp, E0127,
+                              "duplicate supertrait in trait declaration");
                     break;
                 } else {
                     ty_trait_refs.push(trait_ref);
@@ -1129,10 +1124,9 @@ fn get_or_create_type_parameter_def(ccx: &CrateCtxt,
             ty::walk_ty(ty, |t| {
                 match ty::get(t).sty {
                     ty::ty_param(p) => if p.idx > cur_idx {
-                        ccx.tcx.sess.span_err(
-                            path.span,
-                            "type parameters with a default cannot use \
-                             forward declared identifiers")
+                    span_err!(ccx.tcx.sess, path.span, E0128,
+                              "type parameters with a default cannot use \
+                               forward declared identifiers");
                     },
                     _ => {}
                 }
@@ -1239,12 +1233,11 @@ fn check_bounds_compatible(tcx: &ty::ctxt,
                                                  |trait_ref| {
                 let trait_def = ty::lookup_trait_def(tcx, trait_ref.def_id);
                 if trait_def.bounds.contains_elem(ty::BoundSized) {
-                    tcx.sess.span_err(span,
-                        format!("incompatible bounds on type parameter {}, \
-                                 bound {} does not allow unsized type",
-                        token::get_ident(ident),
-                        ppaux::trait_ref_to_string(tcx,
-                                                &*trait_ref)).as_slice());
+                    span_err!(tcx.sess, span, E0129,
+                              "incompatible bounds on type parameter {}, \
+                               bound {} does not allow unsized type",
+                              token::get_ident(ident),
+                              ppaux::trait_ref_to_string(tcx, &*trait_ref));
                 }
                 true
             });
@@ -1263,8 +1256,10 @@ pub fn ty_of_foreign_fn_decl(ccx: &CrateCtxt,
         match (*i).pat.node {
             ast::PatIdent(_, _, _) => (),
             ast::PatWild => (),
-            _ => ccx.tcx.sess.span_err((*i).pat.span,
-                    "patterns aren't allowed in foreign function declarations")
+            _ => {
+                span_err!(ccx.tcx.sess, (*i).pat.span, E0130,
+                          "patterns aren't allowed in foreign function declarations");
+            }
         }
     }
 
index aebdb5943826afe1a4724df70914a9d28df24448..4000807ec1b8e87cd7e6b2fc74c27203adfc17e5 100644 (file)
@@ -372,9 +372,8 @@ fn check_main_fn_ty(ccx: &CrateCtxt,
                     match it.node {
                         ast::ItemFn(_, _, _, ref ps, _)
                         if ps.is_parameterized() => {
-                            tcx.sess.span_err(
-                                main_span,
-                                "main function is not allowed to have type parameters");
+                            span_err!(ccx.tcx.sess, main_span, E0131,
+                                      "main function is not allowed to have type parameters");
                             return;
                         }
                         _ => ()
@@ -421,9 +420,8 @@ fn check_start_fn_ty(ccx: &CrateCtxt,
                     match it.node {
                         ast::ItemFn(_,_,_,ref ps,_)
                         if ps.is_parameterized() => {
-                            tcx.sess.span_err(
-                                start_span,
-                                "start function is not allowed to have type parameters");
+                            span_err!(tcx.sess, start_span, E0132,
+                                      "start function is not allowed to have type parameters");
                             return;
                         }
                         _ => ()
index 2abbd916d76276bee065f027c581ba9c8d4f88df..cdb691073cd3608c6ae4881f31c4748e19d7be32 100644 (file)
@@ -64,10 +64,24 @@ impl RegionScope for BindingRscope {
     fn anon_regions(&self,
                     _: Span,
                     count: uint)
-                    -> Result<Vec<ty::Region> , ()> {
+                    -> Result<Vec<ty::Region>, ()> {
         let idx = self.anon_bindings.get();
         self.anon_bindings.set(idx + count);
         Ok(Vec::from_fn(count, |i| ty::ReLateBound(self.binder_id,
                                                    ty::BrAnon(idx + i))))
     }
 }
+
+/// A scope in which we generate one specific region. This occurs after the
+/// `->` (i.e. in the return type) of function signatures.
+pub struct ImpliedSingleRscope {
+    pub region: ty::Region,
+}
+
+impl RegionScope for ImpliedSingleRscope {
+    fn anon_regions(&self, _: Span, count: uint)
+                    -> Result<Vec<ty::Region>,()> {
+        Ok(Vec::from_elem(count, self.region.clone()))
+    }
+}
+
index 8ec74f4d6efcc4076141306acd806ae915f0ef2a..5db6c72975587346501822b62cb04c847a37b942 100644 (file)
@@ -21,7 +21,6 @@
 //! one that doesn't; the one that doesn't might get decent parallel
 //! build speedups.
 
-#![crate_id = "rustc_back#0.11.0-pre"]
 #![crate_name = "rustc_back"]
 #![experimental]
 #![comment = "The Rust compiler minimal-dependency dumping-ground"]
@@ -33,7 +32,6 @@
       html_root_url = "http://doc.rust-lang.org/")]
 
 #![feature(globs, phase, macro_rules)]
-#![allow(unused_attribute)] // NOTE: remove after stage0
 
 #[phase(plugin, link)]
 extern crate log;
index 4ea4958e544ae0f1720697af779f01aa2f82557f..215ae444b6920f3181e2548e940c7b614b273cf1 100644 (file)
@@ -13,7 +13,6 @@
 #![allow(non_snake_case_functions)]
 #![allow(dead_code)]
 
-#![crate_id = "rustc_llvm#0.11.0"]
 #![crate_name = "rustc_llvm"]
 #![experimental]
 #![license = "MIT/ASL2"]
@@ -25,7 +24,6 @@
 
 #![feature(globs)]
 #![feature(link_args)]
-#![allow(unused_attribute)] // NOTE: remove after stage0
 
 extern crate libc;
 
index ace53478d0a034b5b2aa329318b1d2a0f31ef710..7434951d3ee9166db99cd67c3502b862dd1ab8f7 100644 (file)
@@ -94,7 +94,7 @@ impl<T: 'static> LocalData for T {}
 type TLSValue = Box<LocalData + Send>;
 
 // Gets the map from the runtime. Lazily initialises if not done so already.
-unsafe fn get_local_map() -> Option<&mut Map> {
+unsafe fn get_local_map<'a>() -> Option<&'a mut Map> {
     if !Local::exists(None::<Task>) { return None }
 
     let task: *mut Task = Local::unsafe_borrow();
index 343b911fb83f3d775e9312fa34b7ef3794d82fa0..81a033e4c987ea7345543dad69154043cce118eb 100644 (file)
@@ -134,7 +134,7 @@ fn drop(&mut self) {
 impl<'a> LocalIo<'a> {
     /// Returns the local I/O: either the local scheduler's I/O services or
     /// the native I/O services.
-    pub fn borrow() -> Option<LocalIo> {
+    pub fn borrow() -> Option<LocalIo<'a>> {
         // FIXME(#11053): bad
         //
         // This is currently very unsafely implemented. We don't actually
index 26ba601f73ec1cbddf6fa613a3e9c9ac7d0b8a3d..f42f42d2111601e28190a0c4de3ec4fa8df2d6fc 100644 (file)
@@ -469,7 +469,7 @@ mod test {
     use super::super::Loop;
     use super::super::local_loop;
 
-    fn l() -> &mut Loop { &mut local_loop().loop_ }
+    fn l() -> &'static mut Loop { &mut local_loop().loop_ }
 
     #[test]
     fn file_test_full_simple_sync() {
index e28c51d517ea3488775f09ca7dac7f98de5931f1..a56904c9ef4db700d0c2917d7f5b531082327488 100644 (file)
@@ -2795,6 +2795,7 @@ fn check_err<T: Decodable<Decoder, DecoderError>>(to_parse: &'static str,
         }
     }
     #[test]
+    #[ignore] // FIXME(#15763)
     fn test_decode_errors_struct() {
         check_err::<DecodeStruct>("[]", ExpectedError("Object".to_string(), "[]".to_string()));
         check_err::<DecodeStruct>("{\"x\": true, \"y\": true, \"z\": \"\", \"w\": []}",
index 9a53c941377e44be6bc29810d392bdc92711825e..14027bc1f544fd868dbd0fd3df90742d36dae616 100644 (file)
@@ -1514,54 +1514,44 @@ fn extend<T: Iterator<(K, V)>>(&mut self, mut iter: T) {
 ///     println!("{}", *book);
 /// }
 /// ```
+///
+/// The easiest way to use `HashSet` with a custom type is to derive
+/// `Eq` and `Hash`. We must also derive `PartialEq`, this will in the
+/// future be implied by `Eq`.
+///
+/// ```rust
+/// use std::collections::HashSet;
+///
+/// #[deriving(Hash, Eq, PartialEq, Show)]
+/// struct Viking<'a> {
+///     name: &'a str,
+///     power: uint,
+/// }
+///
+/// let mut vikings = HashSet::new();
+///
+/// vikings.insert(Viking { name: "Einar", power: 9u });
+/// vikings.insert(Viking { name: "Einar", power: 9u });
+/// vikings.insert(Viking { name: "Olaf", power: 4u });
+/// vikings.insert(Viking { name: "Harald", power: 8u });
+///
+/// // Use derived implementation to print the vikings.
+/// for x in vikings.iter() {
+///     println!("{}", x);
+/// }
+/// ```
 #[deriving(Clone)]
 pub struct HashSet<T, H = RandomSipHasher> {
     map: HashMap<T, (), H>
 }
 
-impl<T: Eq + Hash<S>, S, H: Hasher<S>> PartialEq for HashSet<T, H> {
-    fn eq(&self, other: &HashSet<T, H>) -> bool {
-        if self.len() != other.len() { return false; }
-
-        self.iter().all(|key| other.contains(key))
-    }
-}
-
-impl<T: Eq + Hash<S>, S, H: Hasher<S>> Eq for HashSet<T, H> {}
-
-impl<T: Eq + Hash<S>, S, H: Hasher<S>> Collection for HashSet<T, H> {
-    fn len(&self) -> uint { self.map.len() }
-}
-
-impl<T: Eq + Hash<S>, S, H: Hasher<S>> Mutable for HashSet<T, H> {
-    fn clear(&mut self) { self.map.clear() }
-}
-
-impl<T: Eq + Hash<S>, S, H: Hasher<S>> Set<T> for HashSet<T, H> {
-    fn contains(&self, value: &T) -> bool { self.map.contains_key(value) }
-
-    fn is_disjoint(&self, other: &HashSet<T, H>) -> bool {
-        self.iter().all(|v| !other.contains(v))
-    }
-
-    fn is_subset(&self, other: &HashSet<T, H>) -> bool {
-        self.iter().all(|v| other.contains(v))
-    }
-}
-
-impl<T: Eq + Hash<S>, S, H: Hasher<S>> MutableSet<T> for HashSet<T, H> {
-    fn insert(&mut self, value: T) -> bool { self.map.insert(value, ()) }
-
-    fn remove(&mut self, value: &T) -> bool { self.map.remove(value) }
-}
-
 impl<T: Hash + Eq> HashSet<T, RandomSipHasher> {
-    /// Create an empty HashSet
+    /// Create an empty HashSet.
     ///
     /// # Example
     ///
     /// ```rust
-    /// use std::collections::HashSet;
+    /// use std::collections::HashSet;
     /// let mut set: HashSet<int> = HashSet::new();
     /// ```
     #[inline]
@@ -1575,7 +1565,7 @@ pub fn new() -> HashSet<T, RandomSipHasher> {
     /// # Example
     ///
     /// ```rust
-    /// use std::collections::HashSet;
+    /// use std::collections::HashSet;
     /// let mut set: HashSet<int> = HashSet::with_capacity(10);
     /// ```
     #[inline]
@@ -1589,6 +1579,17 @@ impl<T: Eq + Hash<S>, S, H: Hasher<S>> HashSet<T, H> {
     /// keys.
     ///
     /// The hash set is also created with the default initial capacity.
+    ///
+    /// # Example
+    ///
+    /// ```rust
+    /// use std::collections::HashSet;
+    /// use std::hash::sip::SipHasher;
+    ///
+    /// let h = SipHasher::new();
+    /// let mut set = HashSet::with_hasher(h);
+    /// set.insert(2u);
+    /// ```
     #[inline]
     pub fn with_hasher(hasher: H) -> HashSet<T, H> {
         HashSet::with_capacity_and_hasher(INITIAL_CAPACITY, hasher)
@@ -1601,6 +1602,17 @@ pub fn with_hasher(hasher: H) -> HashSet<T, H> {
     /// is designed to allow `HashSet`s to be resistant to attacks that
     /// cause many collisions and very poor performance. Setting it
     /// manually using this function can expose a DoS attack vector.
+    ///
+    /// # Example
+    ///
+    /// ```rust
+    /// use std::collections::HashSet;
+    /// use std::hash::sip::SipHasher;
+    ///
+    /// let h = SipHasher::new();
+    /// let mut set = HashSet::with_capacity_and_hasher(10u, h);
+    /// set.insert(1i);
+    /// ```
     #[inline]
     pub fn with_capacity_and_hasher(capacity: uint, hasher: H) -> HashSet<T, H> {
         HashSet { map: HashMap::with_capacity_and_hasher(capacity, hasher) }
@@ -1611,7 +1623,7 @@ pub fn with_capacity_and_hasher(capacity: uint, hasher: H) -> HashSet<T, H> {
     /// # Example
     ///
     /// ```rust
-    /// use std::collections::HashSet;
+    /// use std::collections::HashSet;
     /// let mut set: HashSet<int> = HashSet::new();
     /// set.reserve(10);
     /// ```
@@ -1621,6 +1633,45 @@ pub fn reserve(&mut self, n: uint) {
 
     /// Returns true if the hash set contains a value equivalent to the
     /// given query value.
+    ///
+    /// # Example
+    ///
+    /// This is a slightly silly example where we define the number's
+    /// parity as the equivilance class. It is important that the
+    /// values hash the same, which is why we implement `Hash`.
+    ///
+    /// ```rust
+    /// use std::collections::HashSet;
+    /// use std::hash::Hash;
+    /// use std::hash::sip::SipState;
+    ///
+    /// #[deriving(Eq, PartialEq)]
+    /// struct EvenOrOdd {
+    ///     num: uint
+    /// };
+    ///
+    /// impl Hash for EvenOrOdd {
+    ///     fn hash(&self, state: &mut SipState) {
+    ///         let parity = self.num % 2;
+    ///         parity.hash(state);
+    ///     }
+    /// }
+    ///
+    /// impl Equiv<EvenOrOdd> for EvenOrOdd {
+    ///     fn equiv(&self, other: &EvenOrOdd) -> bool {
+    ///         self.num % 2 == other.num % 2
+    ///     }
+    /// }
+    ///
+    /// let mut set = HashSet::new();
+    /// set.insert(EvenOrOdd { num: 3u });
+    ///
+    /// assert!(set.contains_equiv(&EvenOrOdd { num: 3u }));
+    /// assert!(set.contains_equiv(&EvenOrOdd { num: 5u }));
+    /// assert!(!set.contains_equiv(&EvenOrOdd { num: 4u }));
+    /// assert!(!set.contains_equiv(&EvenOrOdd { num: 2u }));
+    ///
+    /// ```
     pub fn contains_equiv<Q: Hash<S> + Equiv<T>>(&self, value: &Q) -> bool {
       self.map.contains_key_equiv(value)
     }
@@ -1631,7 +1682,8 @@ pub fn contains_equiv<Q: Hash<S> + Equiv<T>>(&self, value: &Q) -> bool {
     /// # Example
     ///
     /// ```rust
-    /// # use std::collections::HashSet;
+    /// use std::collections::HashSet;
+    ///
     /// let mut set = HashSet::new();
     /// set.insert("a");
     /// set.insert("b");
@@ -1652,7 +1704,8 @@ pub fn iter<'a>(&'a self) -> SetItems<'a, T> {
     /// # Example
     ///
     /// ```rust
-    /// # use std::collections::HashSet;
+    /// use std::collections::HashSet;
+    ///
     /// let mut set = HashSet::new();
     /// set.insert("a".to_string());
     /// set.insert("b".to_string());
@@ -1674,7 +1727,8 @@ pub fn move_iter(self) -> SetMoveItems<T> {
     /// # Example
     ///
     /// ```rust
-    /// # use std::collections::HashSet;
+    /// use std::collections::HashSet;
+    ///
     /// let a: HashSet<int> = [1i, 2, 3].iter().map(|&x| x).collect();
     /// let b: HashSet<int> = [4i, 2, 3, 4].iter().map(|&x| x).collect();
     ///
@@ -1703,7 +1757,8 @@ pub fn difference<'a>(&'a self, other: &'a HashSet<T, H>) -> SetAlgebraItems<'a,
     /// # Example
     ///
     /// ```rust
-    /// # use std::collections::HashSet;
+    /// use std::collections::HashSet;
+    ///
     /// let a: HashSet<int> = [1i, 2, 3].iter().map(|&x| x).collect();
     /// let b: HashSet<int> = [4i, 2, 3, 4].iter().map(|&x| x).collect();
     ///
@@ -1728,7 +1783,8 @@ pub fn symmetric_difference<'a>(&'a self, other: &'a HashSet<T, H>)
     /// # Example
     ///
     /// ```rust
-    /// # use std::collections::HashSet;
+    /// use std::collections::HashSet;
+    ///
     /// let a: HashSet<int> = [1i, 2, 3].iter().map(|&x| x).collect();
     /// let b: HashSet<int> = [4i, 2, 3, 4].iter().map(|&x| x).collect();
     ///
@@ -1753,7 +1809,8 @@ pub fn intersection<'a>(&'a self, other: &'a HashSet<T, H>)
     /// # Example
     ///
     /// ```rust
-    /// # use std::collections::HashSet;
+    /// use std::collections::HashSet;
+    ///
     /// let a: HashSet<int> = [1i, 2, 3].iter().map(|&x| x).collect();
     /// let b: HashSet<int> = [4i, 2, 3, 4].iter().map(|&x| x).collect();
     ///
@@ -1771,6 +1828,43 @@ pub fn union<'a>(&'a self, other: &'a HashSet<T, H>)
     }
 }
 
+impl<T: Eq + Hash<S>, S, H: Hasher<S>> PartialEq for HashSet<T, H> {
+    fn eq(&self, other: &HashSet<T, H>) -> bool {
+        if self.len() != other.len() { return false; }
+
+        self.iter().all(|key| other.contains(key))
+    }
+}
+
+impl<T: Eq + Hash<S>, S, H: Hasher<S>> Eq for HashSet<T, H> {}
+
+impl<T: Eq + Hash<S>, S, H: Hasher<S>> Collection for HashSet<T, H> {
+    fn len(&self) -> uint { self.map.len() }
+}
+
+impl<T: Eq + Hash<S>, S, H: Hasher<S>> Mutable for HashSet<T, H> {
+    fn clear(&mut self) { self.map.clear() }
+}
+
+impl<T: Eq + Hash<S>, S, H: Hasher<S>> Set<T> for HashSet<T, H> {
+    fn contains(&self, value: &T) -> bool { self.map.contains_key(value) }
+
+    fn is_disjoint(&self, other: &HashSet<T, H>) -> bool {
+        self.iter().all(|v| !other.contains(v))
+    }
+
+    fn is_subset(&self, other: &HashSet<T, H>) -> bool {
+        self.iter().all(|v| other.contains(v))
+    }
+}
+
+impl<T: Eq + Hash<S>, S, H: Hasher<S>> MutableSet<T> for HashSet<T, H> {
+    fn insert(&mut self, value: T) -> bool { self.map.insert(value, ()) }
+
+    fn remove(&mut self, value: &T) -> bool { self.map.remove(value) }
+}
+
+
 impl<T: Eq + Hash<S> + fmt::Show, S, H: Hasher<S>> fmt::Show for HashSet<T, H> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         try!(write!(f, "{{"));
index 0ffaadef0a1303c876c52d3a4bcd8cc8f68b9659..a9b9a907a26421e2ce57c2e902811918597a7eae 100644 (file)
@@ -226,19 +226,24 @@ fn fill_bytes(&mut self, bytes: &mut [u8]) {
     }
 }
 
-/// Generate a random value using the task-local random number
-/// generator.
+/// Generates a random value using the task-local random number generator.
 ///
-/// # Example
+/// `random()` can generate various types of random things, and so may require
+/// type hinting to generate the specific type you want.
+///
+/// # Examples
 ///
 /// ```rust
-/// use std::rand::random;
+/// use std::rand;
+///
+/// let x = rand::random();
+/// println!("{}", 2u * x);
+///
+/// let y = rand::random::<f64>();
+/// println!("{}", y);
 ///
-/// if random() {
-///     let x = random();
-///     println!("{}", 2u * x);
-/// } else {
-///     println!("{}", random::<f64>());
+/// if rand::random() { // generates a boolean
+///     println!("Better lucky than good!");
 /// }
 /// ```
 #[inline]
index d7af92024eb5e6fe753f16e34885543086c4433a..4b8c15a0152a39f2316070c172c82a578267131e 100644 (file)
@@ -91,7 +91,7 @@
 //! # }
 //! ```
 
-#![experimental]
+#![stable]
 
 use any::Any;
 use comm::channel;
 use rt::task;
 use rt::task::Task;
 use str::{Str, SendStr, IntoMaybeOwned};
+use string::String;
 use sync::Future;
+use to_str::ToString;
 
 /// A means of spawning a task
 pub trait Spawner {
@@ -172,6 +174,7 @@ pub fn new() -> TaskBuilder<SiblingSpawner> {
 impl<S: Spawner> TaskBuilder<S> {
     /// Name the task-to-be. Currently the name is used for identification
     /// only in failure messages.
+    #[unstable = "IntoMaybeOwned will probably change."]
     pub fn named<T: IntoMaybeOwned<'static>>(mut self, name: T) -> TaskBuilder<S> {
         self.name = Some(name.into_maybe_owned());
         self
@@ -184,12 +187,14 @@ pub fn stack_size(mut self, size: uint) -> TaskBuilder<S> {
     }
 
     /// Redirect task-local stdout.
+    #[experimental = "May not want to make stdio overridable here."]
     pub fn stdout(mut self, stdout: Box<Writer + Send>) -> TaskBuilder<S> {
         self.stdout = Some(stdout);
         self
     }
 
     /// Redirect task-local stderr.
+    #[experimental = "May not want to make stdio overridable here."]
     pub fn stderr(mut self, stderr: Box<Writer + Send>) -> TaskBuilder<S> {
         self.stderr = Some(stderr);
         self
@@ -288,6 +293,7 @@ pub fn spawn(self, f: proc():Send) {
     /// future returns `result::Ok` containing the value returned by the
     /// function. If the child task fails then the future returns `result::Err`
     /// containing the argument to `fail!(...)` as an `Any` trait object.
+    #[experimental = "Futures are experimental."]
     pub fn try_future<T:Send>(self, f: proc():Send -> T)
                               -> Future<Result<T, Box<Any + Send>>> {
         // currently, the on_exit proc provided by librustrt only works for unit
@@ -308,6 +314,7 @@ pub fn try_future<T:Send>(self, f: proc():Send -> T)
 
     /// Execute a function in a newly-spawnedtask and block until the task
     /// completes or fails. Equivalent to `.try_future(f).unwrap()`.
+    #[unstable = "Error type may change."]
     pub fn try<T:Send>(self, f: proc():Send -> T) -> Result<T, Box<Any + Send>> {
         self.try_future(f).unwrap()
     }
@@ -329,6 +336,7 @@ pub fn spawn(f: proc(): Send) {
 /// value of the function or an error if the task failed.
 ///
 /// This is equivalent to `TaskBuilder::new().try`.
+#[unstable = "Error type may change."]
 pub fn try<T: Send>(f: proc(): Send -> T) -> Result<T, Box<Any + Send>> {
     TaskBuilder::new().try(f)
 }
@@ -337,6 +345,7 @@ pub fn try<T: Send>(f: proc(): Send -> T) -> Result<T, Box<Any + Send>> {
 /// task's result.
 ///
 /// This is equivalent to `TaskBuilder::new().try_future`.
+#[experimental = "Futures are experimental."]
 pub fn try_future<T:Send>(f: proc():Send -> T) -> Future<Result<T, Box<Any + Send>>> {
     TaskBuilder::new().try_future(f)
 }
@@ -345,6 +354,7 @@ pub fn try_future<T:Send>(f: proc():Send -> T) -> Future<Result<T, Box<Any + Sen
 /* Lifecycle functions */
 
 /// Read the name of the current task.
+#[deprecated = "Use `task::name()`."]
 pub fn with_task_name<U>(blk: |Option<&str>| -> U) -> U {
     use rt::task::Task;
 
@@ -355,7 +365,20 @@ pub fn with_task_name<U>(blk: |Option<&str>| -> U) -> U {
     }
 }
 
+/// Read the name of the current task.
+#[stable]
+pub fn name() -> Option<String> {
+    use rt::task::Task;
+
+    let task = Local::borrow(None::<Task>);
+    match task.name {
+        Some(ref name) => Some(name.as_slice().to_string()),
+        None => None
+    }
+}
+
 /// Yield control to the task scheduler.
+#[unstable = "Name will change."]
 pub fn deschedule() {
     use rt::local::Local;
 
@@ -366,6 +389,7 @@ pub fn deschedule() {
 
 /// True if the running task is currently failing (e.g. will return `true` inside a
 /// destructor that is run while unwinding the stack after a call to `fail!()`).
+#[unstable = "May move to a different module."]
 pub fn failing() -> bool {
     use rt::task::Task;
     Local::borrow(None::<Task>).unwinder.unwinding()
@@ -377,7 +401,6 @@ mod test {
     use boxed::BoxAny;
     use result;
     use result::{Ok, Err};
-    use str::StrAllocating;
     use string::String;
     use std::io::{ChanReader, ChanWriter};
     use prelude::*;
@@ -388,38 +411,30 @@ mod test {
 
     #[test]
     fn test_unnamed_task() {
-        spawn(proc() {
-            with_task_name(|name| {
-                assert!(name.is_none());
-            })
-        })
+        try(proc() {
+            assert!(name().is_none());
+        }).map_err(|_| ()).unwrap();
     }
 
     #[test]
     fn test_owned_named_task() {
-        TaskBuilder::new().named("ada lovelace".to_string()).spawn(proc() {
-            with_task_name(|name| {
-                assert!(name.unwrap() == "ada lovelace");
-            })
-        })
+        TaskBuilder::new().named("ada lovelace".to_string()).try(proc() {
+            assert!(name().unwrap() == "ada lovelace".to_string());
+        }).map_err(|_| ()).unwrap();
     }
 
     #[test]
     fn test_static_named_task() {
-        TaskBuilder::new().named("ada lovelace").spawn(proc() {
-            with_task_name(|name| {
-                assert!(name.unwrap() == "ada lovelace");
-            })
-        })
+        TaskBuilder::new().named("ada lovelace").try(proc() {
+            assert!(name().unwrap() == "ada lovelace".to_string());
+        }).map_err(|_| ()).unwrap();
     }
 
     #[test]
     fn test_send_named_task() {
-        TaskBuilder::new().named("ada lovelace".into_maybe_owned()).spawn(proc() {
-            with_task_name(|name| {
-                assert!(name.unwrap() == "ada lovelace");
-            })
-        })
+        TaskBuilder::new().named("ada lovelace".into_maybe_owned()).try(proc() {
+            assert!(name().unwrap() == "ada lovelace".to_string());
+        }).map_err(|_| ()).unwrap();
     }
 
     #[test]
index e9a303634fe37c0ac34dd26186862f7582407555..2aec39521255e33469a4b0486b51daef49fede52 100644 (file)
@@ -2098,4 +2098,23 @@ fn recv(rx: Receiver<Box<int>>, i: int) {
         });
         assert_eq!(rx.recv(), 1);
     } #[ignore(reason = "flaky on libnative")])
+
+    test!(fn issue_15761() {
+        fn repro() {
+            let (tx1, rx1) = sync_channel::<()>(3);
+            let (tx2, rx2) = sync_channel::<()>(3);
+
+            spawn(proc() {
+                rx1.recv();
+                tx2.try_send(()).unwrap();
+            });
+
+            tx1.try_send(()).unwrap();
+            rx2.recv();
+        }
+
+        for _ in range(0u, 100) {
+            repro()
+        }
+    })
 }
index cc3c2197c13f03368adf77a6e75647e5463c07a1..1d5a7d6ed9f58718e3cc96dd8d74c892f7a61d15 100644 (file)
@@ -218,9 +218,15 @@ pub fn try_send(&self, t: T) -> Result<(), super::TrySendError<T>> {
             }
         } else {
             // If the buffer has some space and the capacity isn't 0, then we
-            // just enqueue the data for later retrieval.
+            // just enqueue the data for later retrieval, ensuring to wake up
+            // any blocked receiver if there is one.
             assert!(state.buf.size() < state.buf.cap());
             state.buf.enqueue(t);
+            match mem::replace(&mut state.blocker, NoneBlocked) {
+                BlockedReceiver(task) => wakeup(task, guard),
+                NoneBlocked => {}
+                BlockedSender(..) => unreachable!(),
+            }
             Ok(())
         }
     }
index 2b98a3bdd28efa482573c116c320661127a564f1..3b4f6a6e0f85f34b5a1d67555d504d00e277a3e6 100644 (file)
@@ -766,30 +766,6 @@ pub trait PostExpansionMethod {
     fn pe_vis(&self) -> ast::Visibility;
 }
 
-
-/// can't use the standard cfg(stage0) tricks here, because the error occurs in
-/// parsing, before cfg gets a chance to save the day. (yes, interleaved parsing
-/// / expansion / configuring would solve this problem...)
-
-// NOTE: remove after next snapshot
-/// to be more specific: after a snapshot, swap out the "PRE" stuff, and
-// swap in the "POST" stuff.
-
-/// PRE
-macro_rules! mf_method_body{
-    ($slf:ident, $field_pat:pat, $result:ident) => {
-        match $slf.node {
-            $field_pat => $result,
-                MethMac(_) => {
-                    fail!("expected an AST without macro invocations");
-                }
-        }
-    }
-}
-
-/// POST
-/*
-#[cfg(not(stage0))]
 macro_rules! mf_method{
     ($meth_name:ident, $field_ty:ty, $field_pat:pat, $result:ident) => {
         fn $meth_name<'a>(&'a self) -> $field_ty {
@@ -801,52 +777,21 @@ fn $meth_name<'a>(&'a self) -> $field_ty {
             }
         }
     }
-}*/
-
-
-// PRE
-impl PostExpansionMethod for Method {
-    fn pe_ident(&self) -> ast::Ident {
-        mf_method_body!(self, MethDecl(ident,_,_,_,_,_,_,_),ident)
-    }
-    fn pe_generics<'a>(&'a self) -> &'a ast::Generics {
-        mf_method_body!(self, MethDecl(_,ref generics,_,_,_,_,_,_),generics)
-    }
-    fn pe_abi(&self) -> Abi {
-        mf_method_body!(self, MethDecl(_,_,abi,_,_,_,_,_),abi)
-    }
-    fn pe_explicit_self<'a>(&'a self) -> &'a ast::ExplicitSelf {
-        mf_method_body!(self, MethDecl(_,_,_,ref explicit_self,_,_,_,_),explicit_self)
-    }
-    fn pe_fn_style(&self) -> ast::FnStyle{
-        mf_method_body!(self, MethDecl(_,_,_,_,fn_style,_,_,_),fn_style)
-    }
-    fn pe_fn_decl(&self) -> P<ast::FnDecl> {
-        mf_method_body!(self, MethDecl(_,_,_,_,_,decl,_,_),decl)
-    }
-    fn pe_body(&self) -> P<ast::Block> {
-        mf_method_body!(self, MethDecl(_,_,_,_,_,_,body,_),body)
-    }
-    fn pe_vis(&self) -> ast::Visibility {
-        mf_method_body!(self, MethDecl(_,_,_,_,_,_,_,vis),vis)
-    }
 }
 
-// POST
-/*
-#[cfg(not(stage0))]
+
 impl PostExpansionMethod for Method {
-    mf_method!(pe_ident,ast::Ident,MethDecl(ident,_,_,_,_,_,_),ident)
+    mf_method!(pe_ident,ast::Ident,MethDecl(ident,_,_,_,_,_,_,_),ident)
     mf_method!(pe_generics,&'a ast::Generics,
-               MethDecl(_,ref generics,_,_,_,_,_),generics)
+               MethDecl(_,ref generics,_,_,_,_,_,_),generics)
+    mf_method!(pe_abi,Abi,MethDecl(_,_,abi,_,_,_,_,_),abi)
     mf_method!(pe_explicit_self,&'a ast::ExplicitSelf,
-               MethDecl(_,_,ref explicit_self,_,_,_,_),explicit_self)
-    mf_method!(pe_fn_style,ast::FnStyle,MethDecl(_,_,_,fn_style,_,_,_),fn_style)
-    mf_method!(pe_fn_decl,P<ast::FnDecl>,MethDecl(_,_,_,_,decl,_,_),decl)
-    mf_method!(pe_body,P<ast::Block>,MethDecl(_,_,_,_,_,body,_),body)
-    mf_method!(pe_vis,ast::Visibility,MethDecl(_,_,_,_,_,_,vis),vis)
+               MethDecl(_,_,_,ref explicit_self,_,_,_,_),explicit_self)
+    mf_method!(pe_fn_style,ast::FnStyle,MethDecl(_,_,_,_,fn_style,_,_,_),fn_style)
+    mf_method!(pe_fn_decl,P<ast::FnDecl>,MethDecl(_,_,_,_,_,decl,_,_),decl)
+    mf_method!(pe_body,P<ast::Block>,MethDecl(_,_,_,_,_,_,body,_),body)
+    mf_method!(pe_vis,ast::Visibility,MethDecl(_,_,_,_,_,_,_,vis),vis)
 }
-*/
 
 #[cfg(test)]
 mod test {
index b4af7205c42068fae0ea49c8ec5f5427887bf85b..c344168b62a2841b679fbd6a6a23390a9a81de28 100644 (file)
 
 #![macro_escape]
 
-// NOTE: remove after next snapshot
-#[cfg(stage0)]
-#[macro_export]
-macro_rules! __register_diagnostic(
-    ($code:tt, $description:tt) => ();
-    ($code:tt) => ()
-)
-
 #[macro_export]
 macro_rules! register_diagnostic(
     ($code:tt, $description:tt) => (__register_diagnostic!($code, $description));
     ($code:tt) => (__register_diagnostic!($code))
 )
 
-// NOTE: remove after next snapshot
-#[cfg(stage0)]
-#[macro_export]
-macro_rules! __build_diagnostic_array(
-    ($name:ident) => {
-        pub static $name: [(&'static str, &'static str), ..0] = [];
-    }
-)
-
-// NOTE: remove after next snapshot
-#[cfg(stage0)]
-#[macro_export]
-macro_rules! __diagnostic_used(
-    ($code:ident) => {
-        ()
-    }
-)
-
 #[macro_export]
 macro_rules! span_err(
-    ($session:expr, $span:expr, $code:ident, $($arg:expr),*) => ({
+    ($session:expr, $span:expr, $code:ident, $($message:tt)*) => ({
         __diagnostic_used!($code);
-        ($session).span_err_with_code($span, format!($($arg),*).as_slice(), stringify!($code))
+        $session.span_err_with_code($span, format!($($message)*).as_slice(), stringify!($code))
     })
 )
 
 #[macro_export]
 macro_rules! span_warn(
-    ($session:expr, $span:expr, $code:ident, $($arg:expr),*) => ({
+    ($session:expr, $span:expr, $code:ident, $($message:tt)*) => ({
         __diagnostic_used!($code);
-        ($session).span_warn_with_code($span, format!($($arg),*).as_slice(), stringify!($code))
+        $session.span_warn_with_code($span, format!($($message)*).as_slice(), stringify!($code))
     })
 )
 
 #[macro_export]
 macro_rules! span_note(
-    ($session:expr, $span:expr, $($arg:expr),*) => ({
-        ($session).span_note($span, format!($($arg),*).as_slice())
+    ($session:expr, $span:expr, $($message:tt)*) => ({
+        ($session).span_note($span, format!($($message)*).as_slice())
     })
 )
 
index 06eb92e1b271b1c1e333f7639be97b84a124aa02..5d8b56606986b08c62e359f722dcf8a0fc0f8a3f 100644 (file)
@@ -24,6 +24,7 @@
 use std::gc::Gc;
 
 /// The types of pointers
+#[deriving(Clone)]
 pub enum PtrTy<'a> {
     /// &'lifetime mut
     Borrowed(Option<&'a str>, ast::Mutability),
@@ -31,6 +32,7 @@ pub enum PtrTy<'a> {
 
 /// A path, e.g. `::std::option::Option::<int>` (global). Has support
 /// for type parameters and a lifetime.
+#[deriving(Clone)]
 pub struct Path<'a> {
     pub path: Vec<&'a str> ,
     pub lifetime: Option<&'a str>,
@@ -81,6 +83,7 @@ pub fn to_path(&self,
 }
 
 /// A type. Supports pointers (except for *), Self, and literals
+#[deriving(Clone)]
 pub enum Ty<'a> {
     Self,
     /// &/Box/ Ty
@@ -107,7 +110,7 @@ pub fn borrowed_self<'r>() -> Ty<'r> {
     borrowed(box Self)
 }
 
-pub fn nil_ty() -> Ty<'static> {
+pub fn nil_ty<'r>() -> Ty<'r> {
     Tuple(Vec::new())
 }
 
@@ -205,13 +208,14 @@ fn mk_generics(lifetimes: Vec<ast::Lifetime>, ty_params: Vec<ast::TyParam> ) ->
 }
 
 /// Lifetimes and bounds on type parameters
+#[deriving(Clone)]
 pub struct LifetimeBounds<'a> {
     pub lifetimes: Vec<&'a str>,
     pub bounds: Vec<(&'a str, Option<ast::TyParamBound>, Vec<Path<'a>>)>,
 }
 
 impl<'a> LifetimeBounds<'a> {
-    pub fn empty() -> LifetimeBounds<'static> {
+    pub fn empty() -> LifetimeBounds<'a> {
         LifetimeBounds {
             lifetimes: Vec::new(), bounds: Vec::new()
         }
index 786fd953f8901ca9ccfe5d7799f73882fe9bda81..4b245f2c9fd48ffc981a211d772292ee234957ec 100644 (file)
@@ -215,12 +215,21 @@ fn check_positional_ok(&mut self) -> bool {
         }
     }
 
+    fn describe_num_args(&self) -> String {
+        match self.args.len() {
+            0 => "no arguments given".to_string(),
+            1 => "there is 1 argument".to_string(),
+            x => format!("there are {} arguments", x),
+        }
+    }
+
     fn verify_arg_type(&mut self, arg: Position, ty: ArgumentType) {
         match arg {
             Exact(arg) => {
                 if self.args.len() <= arg {
-                    let msg = format!("invalid reference to argument `{}` (there \
-                                    are {} arguments)", arg, self.args.len());
+                    let msg = format!("invalid reference to argument `{}` ({:s})",
+                                      arg, self.describe_num_args());
+
                     self.ecx.span_err(self.fmtsp, msg.as_slice());
                     return;
                 }
index 13e54ed3c977bf1a2062e49ddfc1dbd1d7730886..c923799e812ff099416876650dfa5ab3ae73505e 100644 (file)
@@ -29,7 +29,6 @@
        html_root_url = "http://doc.rust-lang.org/",
        html_playground_url = "http://play.rust-lang.org/")]
 #![no_std]
-#![allow(unused_attribute)] // NOTE: remove after stage0
 
 extern crate core;
 
index c0c7015e31a77840815841aca47aae8238e70bce..623f8f8bcc00d3097c4f4f02bba9cad9a6ba489c 100644 (file)
@@ -1,3 +1,11 @@
+S 2014-07-17 9fc8394
+  freebsd-x86_64 5a4b645e2b42ae06224cc679d4a43b3d89be1482
+  linux-i386 a5e1bb723020ac35173d49600e76b0935e257a6a
+  linux-x86_64 1a2407df17442d93d1c34c916269a345658045d7
+  macos-i386 6648fa88e41ad7c0991a085366e36d56005873ca
+  macos-x86_64 71b2d1dfd0abe1052908dc091e098ed22cf272c6
+  winnt-i386 c26f0a713c5fadf99cce935f60dce0ea403fb411
+
 S 2014-07-09 8ddd286
   freebsd-x86_64 de0c39057f409b69e5ddb888ba3e20b90d63f5db
   linux-i386 28bef31f2a017e1998256d0c2b2e0a0c9221451b
index dbb978a0b4ed907e262ff73ae027ae1d750fcf1b..26d61e166f26be51fd694185de0fd69c3e51aa83 100644 (file)
@@ -15,17 +15,17 @@ struct DerefWithHelper<H, T> {
 }
 
 trait Helper<T> {
-    fn helper_borrow<'a>(&'a self) -> &'a T;
+    fn helper_borrow(&self) -> &T;
 }
 
 impl<T> Helper<T> for Option<T> {
-    fn helper_borrow<'a>(&'a self) -> &'a T {
+    fn helper_borrow(&self) -> &T {
         self.as_ref().unwrap()
     }
 }
 
 impl<T, H: Helper<T>> Deref<T> for DerefWithHelper<H, T> {
-    fn deref<'a>(&'a self) -> &'a T {
+    fn deref(&self) -> &T {
         self.helper.helper_borrow()
     }
 }
index fe0744e5e7c379eb4b896ff71475c87a96616bbd..b31b524cf9b45d8a4aa9de2b2e25fcff9c543684 100644 (file)
@@ -156,7 +156,7 @@ fn lookup<C:TableCallback>(&mut self, key: Code, c: C) {
         }
     }
 
-    fn iter<'a>(&'a self) -> Items<'a> {
+    fn iter(&self) -> Items {
         Items { cur: None, items: self.items.iter() }
     }
 }
index a2f5e28de3bdf2bb2f314654c7fd8b1ecc0ebb6f..784bd1e8ae45d15d95e97e3b30d1b1135f959afa 100644 (file)
@@ -13,7 +13,7 @@
 
 struct Foo(int);
 
-fn foo() -> &int {
+fn foo<'a>() -> &'a int {
     let &Foo(ref x) = &Foo(3); //~ ERROR borrowed value does not live long enough
     x
 }
index 34b9c31fdd82fb8aeb101ce0f87347e68cb0d689..7175194355b0aa3b47cc273a1e3a39c831b8205a 100644 (file)
@@ -12,7 +12,7 @@
 // other `&mut` pointers.
 
 trait Foo {
-    fn f1<'a>(&'a mut self) -> &'a ();
+    fn f1(&mut self) -> &();
     fn f2(&mut self);
 }
 
index 1e04a3568c350fbe38cdef388e64b7942f3e7741..05bc0d1e13b2dea51e0ead40ea1595d8cbe5cbb8 100644 (file)
@@ -18,13 +18,13 @@ struct Own<T> {
 }
 
 impl<T> Deref<T> for Own<T> {
-    fn deref<'a>(&'a self) -> &'a T {
+    fn deref(&self) -> &T {
         unsafe { &*self.value }
     }
 }
 
 impl<T> DerefMut<T> for Own<T> {
-    fn deref_mut<'a>(&'a mut self) -> &'a mut T {
+    fn deref_mut(&mut self) -> &mut T {
         unsafe { &mut *self.value }
     }
 }
@@ -44,11 +44,11 @@ fn set(&mut self, x: int, y: int) {
         self.y = y;
     }
 
-    fn x_ref<'a>(&'a self) -> &'a int {
+    fn x_ref(&self) -> &int {
         &self.x
     }
 
-    fn y_mut<'a>(&'a mut self) -> &'a mut int {
+    fn y_mut(&mut self) -> &mut int {
         &mut self.y
     }
 }
@@ -65,19 +65,19 @@ fn deref_mut_field2(mut x: Own<Point>) {
     let _i = &mut x.y;
 }
 
-fn deref_extend_field<'a>(x: &'a Own<Point>) -> &'a int {
+fn deref_extend_field(x: &Own<Point>) -> &int {
     &x.y
 }
 
-fn deref_extend_mut_field1<'a>(x: &'a Own<Point>) -> &'a mut int {
+fn deref_extend_mut_field1(x: &Own<Point>) -> &mut int {
     &mut x.y //~ ERROR cannot borrow
 }
 
-fn deref_extend_mut_field2<'a>(x: &'a mut Own<Point>) -> &'a mut int {
+fn deref_extend_mut_field2(x: &mut Own<Point>) -> &mut int {
     &mut x.y
 }
 
-fn deref_extend_mut_field3<'a>(x: &'a mut Own<Point>) {
+fn deref_extend_mut_field3(x: &mut Own<Point>) {
     // Hmm, this is unfortunate, because with box it would work,
     // but it's presently the expected outcome. See `deref_extend_mut_field4`
     // for the workaround.
@@ -124,15 +124,15 @@ fn deref_mut_method2(mut x: Own<Point>) {
     x.set(0, 0);
 }
 
-fn deref_extend_method<'a>(x: &'a Own<Point>) -> &'a int {
+fn deref_extend_method(x: &Own<Point>) -> &int {
     x.x_ref()
 }
 
-fn deref_extend_mut_method1<'a>(x: &'a Own<Point>) -> &'a mut int {
+fn deref_extend_mut_method1(x: &Own<Point>) -> &mut int {
     x.y_mut() //~ ERROR cannot borrow
 }
 
-fn deref_extend_mut_method2<'a>(x: &'a mut Own<Point>) -> &'a mut int {
+fn deref_extend_mut_method2(x: &mut Own<Point>) -> &mut int {
     x.y_mut()
 }
 
index 30aed76a4ebdb04dadf032fc071f08d635a7189b..5aaefd01739908d2ebb15c271bf52e7a8255a0d6 100644 (file)
@@ -18,7 +18,7 @@ struct Rc<T> {
 }
 
 impl<T> Deref<T> for Rc<T> {
-    fn deref<'a>(&'a self) -> &'a T {
+    fn deref(&self) -> &T {
         unsafe { &*self.value }
     }
 }
@@ -38,11 +38,11 @@ fn set(&mut self, x: int, y: int) {
         self.y = y;
     }
 
-    fn x_ref<'a>(&'a self) -> &'a int {
+    fn x_ref(&self) -> &int {
         &self.x
     }
 
-    fn y_mut<'a>(&'a mut self) -> &'a mut int {
+    fn y_mut(&mut self) -> &mut int {
         &mut self.y
     }
 }
@@ -59,15 +59,15 @@ fn deref_mut_field2(mut x: Rc<Point>) {
     let _i = &mut x.y; //~ ERROR cannot borrow
 }
 
-fn deref_extend_field<'a>(x: &'a Rc<Point>) -> &'a int {
+fn deref_extend_field(x: &Rc<Point>) -> &int {
     &x.y
 }
 
-fn deref_extend_mut_field1<'a>(x: &'a Rc<Point>) -> &'a mut int {
+fn deref_extend_mut_field1(x: &Rc<Point>) -> &mut int {
     &mut x.y //~ ERROR cannot borrow
 }
 
-fn deref_extend_mut_field2<'a>(x: &'a mut Rc<Point>) -> &'a mut int {
+fn deref_extend_mut_field2(x: &mut Rc<Point>) -> &mut int {
     &mut x.y //~ ERROR cannot borrow
 }
 
@@ -95,15 +95,15 @@ fn deref_mut_method2(mut x: Rc<Point>) {
     x.set(0, 0); //~ ERROR cannot borrow
 }
 
-fn deref_extend_method<'a>(x: &'a Rc<Point>) -> &'a int {
+fn deref_extend_method(x: &Rc<Point>) -> &int {
     x.x_ref()
 }
 
-fn deref_extend_mut_method1<'a>(x: &'a Rc<Point>) -> &'a mut int {
+fn deref_extend_mut_method1(x: &Rc<Point>) -> &mut int {
     x.y_mut() //~ ERROR cannot borrow
 }
 
-fn deref_extend_mut_method2<'a>(x: &'a mut Rc<Point>) -> &'a mut int {
+fn deref_extend_mut_method2(x: &mut Rc<Point>) -> &mut int {
     x.y_mut() //~ ERROR cannot borrow
 }
 
index 30430e00ef3422d35d5dd4af0b6dac9c88c7e04d..9e6bafa1eba7c35853e7b11134feab953fb46856 100644 (file)
@@ -15,7 +15,7 @@
 
 use std::gc::{GC, Gc};
 
-fn foo<'a>(x: &'a Gc<int>) -> &'a int {
+fn foo(x: &Gc<int>) -> &int {
     match x {
         &ref y => {
             &**y // Do not expect an error here
index 9466a78588c4555255f7f98d9e23e640108fae43..c55a5a30538d8caa2d7f26fecd591c5996f4625b 100644 (file)
 
 
 trait Foo {
-    fn borrowed<'a>(&'a self) -> &'a ();
+    fn borrowed(&self) -> &();
 }
 
-fn borrowed_receiver<'a>(x: &'a Foo) -> &'a () {
+fn borrowed_receiver(x: &Foo) -> &() {
     x.borrowed()
 }
 
-fn owned_receiver(x: Box<Foo>) -> &() {
+fn owned_receiver(x: Box<Foo>) -> &'static () {
     x.borrowed() //~ ERROR `*x` does not live long enough
 }
 
index 1e3144a931fbf68e181fa0103d2ce4d6e0860085..6d2eae8bc1e12e3cbdcfafa311238514901b9968 100644 (file)
@@ -13,7 +13,7 @@ struct MyVec<T> {
 }
 
 impl<T> Index<uint, T> for MyVec<T> {
-    fn index<'a>(&'a self, &i: &uint) -> &'a T {
+    fn index(&self, &i: &uint) -> &T {
         self.data.get(i)
     }
 }
index 3da284175541d730aeaf130ea1e376705f1b1d67..53ebaa38fddba7f4ddf796758ef814980ff7c8b7 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-fn a() -> &[int] {
+fn a<'a>() -> &'a [int] {
     let vec = vec!(1, 2, 3, 4);
     let vec: &[int] = vec.as_slice(); //~ ERROR does not live long enough
     let tail = match vec {
@@ -18,7 +18,7 @@ fn a() -> &[int] {
     tail
 }
 
-fn b() -> &[int] {
+fn b<'a>() -> &'a [int] {
     let vec = vec!(1, 2, 3, 4);
     let vec: &[int] = vec.as_slice(); //~ ERROR does not live long enough
     let init = match vec {
@@ -28,7 +28,7 @@ fn b() -> &[int] {
     init
 }
 
-fn c() -> &[int] {
+fn c<'a>() -> &'a [int] {
     let vec = vec!(1, 2, 3, 4);
     let vec: &[int] = vec.as_slice(); //~ ERROR does not live long enough
     let slice = match vec {
index 26dc853859c9256ef286c6e6396a8670fb068b80..57a276bec81bc4f8a78f908e269de05bf0ae7416 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-fn a() -> &int {
+fn a<'a>() -> &'a int {
     let vec = vec!(1, 2, 3, 4);
     let vec: &[int] = vec.as_slice(); //~ ERROR `vec` does not live long enough
     let tail = match vec {
index 01c6256173f03c5411436d8b2b273145c6247e12..b79f4507d4673876825707ae5ea2cc06e24eb993 100644 (file)
@@ -24,12 +24,12 @@ fn AddFlags(bits: u64) -> AddFlags {
     AddFlags { bits: bits }
 }
 
-fn arg<'a>(x: &'a AddFlags) -> &'a AddFlags {
+fn arg(x: &AddFlags) -> &AddFlags {
     x
 }
 
 impl AddFlags {
-    fn get<'a>(&'a self) -> &'a AddFlags {
+    fn get(&self) -> &AddFlags {
         self
     }
 }
diff --git a/src/test/compile-fail/crate-name-mismatch.rs b/src/test/compile-fail/crate-name-mismatch.rs
new file mode 100644 (file)
index 0000000..589c0be
--- /dev/null
@@ -0,0 +1,16 @@
+// 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.
+
+// compile-flags: --crate-name foo
+
+#![crate_name = "bar"]
+//~^ ERROR: --crate-name and #[crate_name] are required to match, but `foo` != `bar`
+
+fn main() {}
index 2700ceff68a072b675eff2a005a345c5be569d45..1cbd6292e9907713d4eaecbc7bad812fc56ee76e 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-fn read_lines_borrowed() -> Vec<&str> {
+fn read_lines_borrowed<'a>() -> Vec<&'a str> {
     let raw_lines: Vec<String> = vec!("foo  ".to_string(), "  bar".to_string());
     raw_lines.iter().map(|l| l.as_slice().trim()).collect()
     //~^ ERROR `raw_lines` does not live long enough
index 84735ec78ce7ed1da161d8e845c034ac011a76c8..6829b1e2721a77252f739e458fd94f24a4ffa659 100644 (file)
@@ -29,6 +29,21 @@ fn main() {
     format!("{foo}", foo=1, foo=2);    //~ ERROR: duplicate argument
     format!("", foo=1, 2);             //~ ERROR: positional arguments cannot follow
 
+    // bad number of arguments, see #15780
+
+    format!("{0}");
+    //~^ ERROR invalid reference to argument `0` (no arguments given)
+
+    format!("{0} {1}", 1);
+    //~^ ERROR invalid reference to argument `1` (there is 1 argument)
+
+    format!("{0} {1} {2}", 1, 2);
+    //~^ ERROR invalid reference to argument `2` (there are 2 arguments)
+
+    format!("{0} {1}");
+    //~^ ERROR invalid reference to argument `0` (no arguments given)
+    //~^^ ERROR invalid reference to argument `1` (no arguments given)
+
     // bad syntax of the format string
 
     format!("{"); //~ ERROR: expected `}` but string was terminated
index b41797d0042fa6536c6bc856dfc5e26b9edf8c87..e4c6fa7d47f4a1d5f3e3ebf55bf2cca616d90710 100644 (file)
@@ -15,7 +15,7 @@
 struct Foo;
 
 impl Deref<Foo> for Foo {
-    fn deref<'a>(&'a self) -> &'a Foo {
+    fn deref(&self) -> &Foo {
         self
     }
 }
index dad503e88e1b9c1753c9ebf2352d4b7ba8fd3270..71f1d5dcc9af4af1007fbf40ff0c8fdd57574a38 100644 (file)
@@ -18,7 +18,7 @@ impl Drop for Test {
     fn drop (&mut self) {}
 }
 
-fn createTest() -> &Test {
+fn createTest<'a>() -> &'a Test {
   let testValue = &Test; //~ ERROR borrowed value does not live long enough
   return testValue;
 }
index dcb705856d997b6ad2916298621c21a226b772a2..141bf2b42791b632a71393bb3f496000da660899 100644 (file)
@@ -12,7 +12,7 @@ struct thing<'a, Q> {
     x: &'a Q
 }
 
-fn thing<Q>(x: &Q) -> thing<Q> {
+fn thing<'a,Q>(x: &Q) -> thing<'a,Q> {
     thing{ x: x } //~ ERROR cannot infer
 }
 
index edd6932aec6f0d3900614ad11699aced0a25fb3f..d684d1b376b8f5ebbf5f1f8c930bb5d0c2a34445 100644 (file)
@@ -15,7 +15,7 @@ pub enum TraitWrapper {
     A(Box<MyTrait>),
 }
 
-fn get_tw_map<'lt>(tw: &'lt TraitWrapper) -> &'lt MyTrait {
+fn get_tw_map(tw: &TraitWrapper) -> &MyTrait {
     match *tw {
         A(box ref map) => map, //~ ERROR cannot be dereferenced
     }
index d4073a5e98479230fd6a471426359c067c992c7d..bf13b7ebbdbbe0ad45d32926687c2db286d1db32 100644 (file)
@@ -31,7 +31,7 @@ fn make_a<'a>(p: &'a X) -> A<'a> {
     A { p: p }
 }
 
-fn make_make_a() -> A {
+fn make_make_a<'a>() -> A<'a> {
     let b: Box<B> = box B {i:1};
     let bb: &B = &*b;    //~ ERROR does not live long enough
     make_a(bb)
diff --git a/src/test/compile-fail/lifetime-elision-return-type-requires-explicit-lifetime.rs b/src/test/compile-fail/lifetime-elision-return-type-requires-explicit-lifetime.rs
new file mode 100644 (file)
index 0000000..aef3f7a
--- /dev/null
@@ -0,0 +1,32 @@
+// 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.
+
+// Lifetime annotation needed because we have no arguments.
+fn f() -> &int {    //~ ERROR missing lifetime specifier
+    fail!()
+}
+
+// Lifetime annotation needed because we have two by-reference parameters.
+fn g(_: &int, _: &int) -> &int {    //~ ERROR missing lifetime specifier
+    fail!()
+}
+
+struct Foo<'a> {
+    x: &'a int,
+}
+
+// Lifetime annotation needed because we have two lifetimes: one as a parameter
+// and one on the reference.
+fn h(_: &Foo) -> &int { //~ ERROR missing lifetime specifier
+    fail!()
+}
+
+fn main() {}
+
index 3328a5d23e62ec1923b89f71cd187d0acdba03ee..ef5a45fcf70ae820a74659349a26012f983d0786 100644 (file)
@@ -11,7 +11,7 @@
 // ignore-tidy-linelength
 
 struct Foo<'x> { bar: int }
-fn foo1(x: &Foo) -> &int {
+fn foo1<'a>(x: &Foo) -> &'a int {
 //~^ NOTE: consider using an explicit lifetime parameter as shown: fn foo1<'a>(x: &'a Foo) -> &'a int
     &x.bar //~ ERROR: cannot infer
 }
@@ -21,34 +21,28 @@ fn foo2<'a, 'b>(x: &'a Foo) -> &'b int {
     &x.bar //~ ERROR: cannot infer
 }
 
-fn foo3(x: &Foo) -> (&int, &int) {
+fn foo3<'a>(x: &Foo) -> (&'a int, &'a int) {
 //~^ NOTE: consider using an explicit lifetime parameter as shown: fn foo3<'a>(x: &'a Foo) -> (&'a int, &'a int)
     (&x.bar, &x.bar) //~ ERROR: cannot infer
     //~^ ERROR: cannot infer
 }
 
-fn foo4<'a, 'b>(x: &'a Foo) -> (&'b int, &'a int, &int) {
+fn foo4<'a, 'b>(x: &'a Foo) -> (&'b int, &'a int, &'b int) {
 //~^ NOTE: consider using an explicit lifetime parameter as shown: fn foo4<'a>(x: &'a Foo) -> (&'a int, &'a int, &'a int)
     (&x.bar, &x.bar, &x.bar) //~ ERROR: cannot infer
     //~^ ERROR: cannot infer
 }
 
-fn foo5(x: &int) -> &int {
-//~^ NOTE: consider using an explicit lifetime parameter as shown: fn foo5<'a>(x: &'a int) -> &'a int
-    x //~ ERROR: mismatched types
-    //~^ ERROR: cannot infer
-}
-
 struct Bar<'x, 'y, 'z> { bar: &'y int, baz: int }
-fn bar1(x: &Bar) -> (&int, &int, &int) {
-//~^ NOTE: consider using an explicit lifetime parameter as shown: fn bar1<'a, 'b, 'c, 'd>(x: &'d Bar<'b, 'a, 'c>) -> (&'a int, &'d int, &'d int)
+fn bar1<'a>(x: &Bar) -> (&'a int, &'a int, &'a int) {
+//~^ NOTE: consider using an explicit lifetime parameter as shown: fn bar1<'b, 'c, 'a>(x: &'a Bar<'b, 'a, 'c>) -> (&'a int, &'a int, &'a int)
     (x.bar, &x.baz, &x.baz) //~ ERROR: mismatched types
     //~^ ERROR: cannot infer
     //~^^ ERROR: cannot infer
 }
 
-fn bar2<'a, 'b, 'c>(x: &Bar<'a, 'b, 'c>) -> (&int, &int, &int) {
-//~^ NOTE: consider using an explicit lifetime parameter as shown: fn bar2<'d, 'a, 'b, 'c>(x: &'d Bar<'a, 'b, 'c>) -> (&'b int, &'d int, &'d int)
+fn bar2<'a, 'b, 'c>(x: &Bar<'a, 'b, 'c>) -> (&'a int, &'a int, &'a int) {
+//~^ NOTE: consider using an explicit lifetime parameter as shown: fn bar2<'a, 'c>(x: &'a Bar<'a, 'a, 'c>) -> (&'a int, &'a int, &'a int)
     (x.bar, &x.baz, &x.baz) //~ ERROR: mismatched types
     //~^ ERROR: cannot infer
     //~^^ ERROR: cannot infer
@@ -56,13 +50,9 @@ fn bar2<'a, 'b, 'c>(x: &Bar<'a, 'b, 'c>) -> (&int, &int, &int) {
 
 struct Cat<'x, T> { cat: &'x int, t: T }
 struct Dog<'y> { dog: &'y int }
-fn cat<'x>(x: Cat<'x, Dog>) -> &int {
-//~^ NOTE: consider using an explicit lifetime parameter as shown: fn cat<'a, 'x>(x: Cat<'x, Dog<'a>>) -> &'a int
-    x.t.dog //~ ERROR: mismatched types
-}
 
-fn cat2<'x, 'y>(x: Cat<'x, Dog<'y>>) -> &int {
-//~^ NOTE: consider using an explicit lifetime parameter as shown: fn cat2<'x, 'y>(x: Cat<'x, Dog<'y>>) -> &'y int
+fn cat2<'x, 'y>(x: Cat<'x, Dog<'y>>) -> &'x int {
+//~^ NOTE: consider using an explicit lifetime parameter as shown: fn cat2<'x>(x: Cat<'x, Dog<'x>>) -> &'x int
     x.t.dog //~ ERROR: mismatched types
 }
 
@@ -70,16 +60,11 @@ struct Baz<'x> {
     bar: &'x int
 }
 
-impl<'x> Baz<'x> {
-    fn baz1(&self) -> &int {
-    //~^ NOTE: consider using an explicit lifetime parameter as shown: fn baz1(&self) -> &'x int
-        self.bar //~ ERROR: mismatched types
-    }
-}
 
 impl<'a> Baz<'a> {
-    fn baz2(&self, x: &int) -> (&int, &int) {
-    //~^ NOTE: consider using an explicit lifetime parameter as shown: fn baz2<'b>(&self, x: &'b int) -> (&'a int, &'b int)
+    fn baz2<'b>(&self, x: &int) -> (&'b int, &'b int) {
+        // The lifetime that gets assigned to `x` seems somewhat random.
+        // I have disabled this test for the time being. --pcwalton
         (self.bar, x) //~ ERROR: cannot infer
         //~^ ERROR: mismatched types
         //~^^ ERROR: mismatched types
diff --git a/src/test/compile-fail/match-arm-statics.rs b/src/test/compile-fail/match-arm-statics.rs
new file mode 100644 (file)
index 0000000..69cb626
--- /dev/null
@@ -0,0 +1,108 @@
+// 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 NewBool(bool);
+
+enum Direction {
+    North,
+    East,
+    South,
+    West
+}
+
+static TRUE_TRUE: (bool, bool) = (true, true);
+
+fn nonexhaustive_1() {
+    match (true, false) {
+    //~^ ERROR non-exhaustive patterns: `(true, false)` not covered
+        TRUE_TRUE => (),
+        (false, false) => (),
+        (false, true) => ()
+    }
+}
+
+fn unreachable_1() {
+    match (true, false) {
+        TRUE_TRUE => (),
+        (false, false) => (),
+        (false, true) => (),
+        (true, false) => (),
+        (true, true) => ()
+        //~^ ERROR unreachable pattern
+    }
+}
+
+static NONE: Option<Direction> = None;
+static EAST: Direction = East;
+
+fn nonexhaustive_2() {
+    match Some(Some(North)) {
+    //~^ ERROR non-exhaustive patterns: `Some(Some(West))` not covered
+        Some(NONE) => (),
+        Some(Some(North)) => (),
+        Some(Some(EAST)) => (),
+        Some(Some(South)) => (),
+        None => ()
+    }
+}
+
+fn unreachable_2() {
+    match Some(Some(North)) {
+        Some(NONE) => (),
+        Some(Some(North)) => (),
+        Some(Some(EAST)) => (),
+        Some(Some(South)) => (),
+        Some(Some(West)) => (),
+        Some(Some(East)) => (),
+        //~^ ERROR unreachable pattern
+        None => ()
+    }
+}
+
+static NEW_FALSE: NewBool = NewBool(false);
+struct Foo {
+    bar: Option<Direction>,
+    baz: NewBool
+}
+
+static STATIC_FOO: Foo = Foo { bar: None, baz: NEW_FALSE };
+
+fn nonexhaustive_3() {
+    match (Foo { bar: Some(North), baz: NewBool(true) }) {
+    //~^ ERROR non-exhaustive patterns: `Foo { bar: Some(North), baz: NewBool(true) }`
+        Foo { bar: None, baz: NewBool(true) } => (),
+        Foo { bar: _, baz: NEW_FALSE } => (),
+        Foo { bar: Some(West), baz: NewBool(true) } => (),
+        Foo { bar: Some(South), .. } => (),
+        Foo { bar: Some(EAST), .. } => ()
+    }
+}
+
+fn unreachable_3() {
+    match (Foo { bar: Some(EAST), baz: NewBool(true) }) {
+        Foo { bar: None, baz: NewBool(true) } => (),
+        Foo { bar: _, baz: NEW_FALSE } => (),
+        Foo { bar: Some(West), baz: NewBool(true) } => (),
+        Foo { bar: Some(South), .. } => (),
+        Foo { bar: Some(EAST), .. } => (),
+        Foo { bar: Some(North), baz: NewBool(true) } => (),
+        Foo { bar: Some(EAST), baz: NewBool(false) } => ()
+        //~^ ERROR unreachable pattern
+    }
+}
+
+fn main() {
+    nonexhaustive_1();
+    nonexhaustive_2();
+    nonexhaustive_3();
+    unreachable_1();
+    unreachable_2();
+    unreachable_3();
+}
index 723aefb91cb9cd3506b30ca99ed00729faf41214..e3dbc67b7a9ef7fee3a591ed967642797ab1a08e 100644 (file)
@@ -13,5 +13,5 @@ fn bar() {
 }
 
 #[main]
-fn foo() { //~ ERROR multiple 'main' functions
+fn foo() { //~ ERROR multiple functions with a #[main] attribute
 }
index 36da3e6e84a22dcc10e37a7492757d6c9d9a3837..58cc148568ee6dfeb75acf4bc425d29be57bcb85 100644 (file)
@@ -14,6 +14,6 @@ fn main1() {
 
 mod foo {
     #[main]
-    fn main2() { //~ ERROR multiple 'main' functions
+    fn main2() { //~ ERROR multiple functions with a #[main] attribute
     }
 }
index 4fd3cd2704437fc38f04a5ae7ac2374666870993..ed3ce1fd0f077dea7131ee9a3c05aea15b5fc5ed 100644 (file)
@@ -27,7 +27,7 @@ fn compute(x: &ast) -> uint {
     }
 }
 
-fn map_nums(x: &ast, f: |uint| -> uint) -> &ast {
+fn map_nums<'a,'b>(x: &ast, f: |uint| -> uint) -> &'a ast<'b> {
     match *x {
       num(x) => {
         return &num(f(x)); //~ ERROR borrowed value does not live long enough
index 0cd5a97596045439c9be46acc8488bc1eb788da6..082ba0f0cf10395c7ca4522619be3a64f8f3264f 100644 (file)
@@ -13,7 +13,7 @@ enum ast<'a> {
     add(&'a ast<'a>, &'a ast<'a>)
 }
 
-fn mk_add_bad2<'a>(x: &'a ast<'a>, y: &'a ast<'a>, z: &ast) -> ast {
+fn mk_add_bad2<'a,'b>(x: &'a ast<'a>, y: &'a ast<'a>, z: &ast) -> ast<'b> {
     add(x, y) //~ ERROR cannot infer
 }
 
index c03040fe0f21189f9a7d7bab314081531c82cffd..2d20634cdc41de8a9bcdfe0d8fa336f227cf68c6 100644 (file)
@@ -40,7 +40,7 @@ fn bar<'a,'b>(x: &'a S) -> &'b S {
 }
 
 // Meets F, but not G.
-fn baz<'a>(x: &'a S) -> &'a S {
+fn baz(x: &S) -> &S {
     fail!()
 }
 
index 0cbd37a3b9a5ea9531fdb48ac096fa3fffb364a5..30b33e82a4b79b32dd71aed7c7b87ca6d0f6b2eb 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-fn of<T>() -> |T| { fail!(); }
+fn of<'a,T>() -> |T|:'a { fail!(); }
 fn subtype<T>(x: |T|) { fail!(); }
 
 fn test_fn<'x,'y,'z,T>(_x: &'x T, _y: &'y T, _z: &'z T) {
index 4c883656d61a5d4e8b7b70e39c25632360c325b8..e5444aadc1ca64d650992cf50ca746a7e337a714 100644 (file)
@@ -20,7 +20,7 @@ struct not_parameterized2 {
     g: ||: 'static
 }
 
-fn take1(p: parameterized1) -> parameterized1 { p }
+fn take1<'a>(p: parameterized1) -> parameterized1<'a> { p }
 //~^ ERROR mismatched types
 //~^^ ERROR cannot infer
 
index 028988dbd4fa5f93bb9ada80657577833fd423e9..b00ceec028782d917e65b872baa1ae5b9bae42cc 100644 (file)
@@ -21,7 +21,7 @@ fn x_coord<'r>(p: &'r point) -> &'r int {
     return &p.x;
 }
 
-fn foo(p: Gc<point>) -> &int {
+fn foo<'a>(p: Gc<point>) -> &'a int {
     let xc = x_coord(&*p); //~ ERROR `*p` does not live long enough
     assert_eq!(*xc, 3);
     return xc;
index bb021d4135a160cd320847414c7ca3f23c57503f..ce6a51e8fb5e75dcd4ad6f7e6bf2ea9c2008082b 100644 (file)
@@ -12,7 +12,7 @@
 
 use std::gc::Gc;
 
-fn borrow<'r, T>(x: &'r T) -> &'r T {x}
+fn borrow<T>(x: &T) -> &T {x}
 
 fn foo(cond: || -> bool, make_box: || -> Gc<int>) {
     let mut y: &int;
index 86f98d5cc3515b4de3cd7ebf8b04b2c13ee62865..cadf66c3286869fdc72776e5f97682a1769323cd 100644 (file)
@@ -22,12 +22,12 @@ struct indirect2<'a> {
     g: |direct<'a>|: 'static
 }
 
-fn take_direct(p: direct) -> direct { p } //~ ERROR mismatched types
+fn take_direct<'a,'b>(p: direct<'a>) -> direct<'b> { p } //~ ERROR mismatched types
 //~^ ERROR cannot infer
 
 fn take_indirect1(p: indirect1) -> indirect1 { p }
 
-fn take_indirect2(p: indirect2) -> indirect2 { p } //~ ERROR mismatched types
+fn take_indirect2<'a,'b>(p: indirect2<'a>) -> indirect2<'b> { p } //~ ERROR mismatched types
 //~^ ERROR cannot infer
 
 fn main() {}
index c266952f08f0871f17a5e989029645ff9aeb1059..27e2f5582f5a449eb4b5a939bb2f9e042a275f18 100644 (file)
@@ -18,12 +18,12 @@ enum MyEnum {
     Variant1
 }
 
-fn structLifetime() -> &Test {
+fn structLifetime<'a>() -> &'a Test {
   let testValue = &Test; //~ ERROR borrowed value does not live long enough
   testValue
 }
 
-fn variantLifetime() -> &MyEnum {
+fn variantLifetime<'a>() -> &'a MyEnum {
   let testValue = &Variant1; //~ ERROR borrowed value does not live long enough
   testValue
 }
index c20764e0728d129747811b652869bbadc6654d7d..f9983bcf80172207e26449ebd4245f163516bd8b 100644 (file)
@@ -19,7 +19,7 @@ fn with<R>(f: |x: &int| -> R) -> R {
     f(&3)
 }
 
-fn return_it() -> &int {
+fn return_it<'a>() -> &'a int {
     with(|o| o) //~ ERROR mismatched types
         //~^ ERROR lifetime of return value does not outlive the function call
         //~^^ ERROR cannot infer
index eccffb4051e23a928a8a8909c8c5879f52ee930f..4986771c79397375745cf2a1dc2f5a0230354cd4 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-fn f<'a>(_x : &'a int) -> &'a int {
+fn f(_x: &int) -> &int {
     return &3; //~ ERROR borrowed value does not live long enough
 }
 
index 24dcfb87ad884e24d4985ba8ff6e576f21007080..53cfd4e0324977221a374f23236cc177c18b79c3 100644 (file)
@@ -34,11 +34,11 @@ struct A<'r> {
     p: &'r X
 }
 
-fn make_a<'r>(p:&'r X) -> A<'r> {
+fn make_a(p:&X) -> A {
     A{p:p}
 }
 
-fn make_make_a() -> A {
+fn make_make_a<'a>() -> A<'a> {
     let b: Box<B> = box B {
         i: 1,
     };
index c410e85655258e161857a9b248d5e5779360e1f4..b3e93daccab8df2288d703eb41692c208b1f6b38 100644 (file)
@@ -20,7 +20,34 @@ fn main() {
     // instead of spitting out a custom error about some identifier collisions
     // (we should allow shadowing)
     match 4i {
-        a => {}
-        _ => {} //~ ERROR: unreachable pattern
+        a => {} //~ ERROR mutable static variables cannot be referenced in a pattern
+        _ => {}
+    }
+}
+
+struct NewBool(bool);
+enum Direction {
+    North,
+    East,
+    South,
+    West
+}
+static NEW_FALSE: NewBool = NewBool(false);
+struct Foo {
+    bar: Option<Direction>,
+    baz: NewBool
+}
+
+static mut STATIC_MUT_FOO: Foo = Foo { bar: Some(West), baz: NEW_FALSE };
+
+fn mutable_statics() {
+    match (Foo { bar: Some(North), baz: NewBool(true) }) {
+        Foo { bar: None, baz: NewBool(true) } => (),
+        STATIC_MUT_FOO => (),
+        //~^ ERROR mutable static variables cannot be referenced in a pattern
+        Foo { bar: Some(South), .. } => (),
+        Foo { bar: Some(EAST), .. } => (),
+        Foo { bar: Some(North), baz: NewBool(true) } => (),
+        Foo { bar: Some(EAST), baz: NewBool(false) } => ()
     }
 }
index 250602710f57d7c7b8cdd46018c62fd28d8d169b..2fe518324336171c97d0c4bfb37e314979fafd39 100644 (file)
@@ -7,7 +7,5 @@ all:
        rm $(TMPDIR)/$(call BIN,bar)
        $(RUSTC) foo1.rs
        rm $(TMPDIR)/$(call BIN,foo)
-       $(RUSTC) foo1.rs --crate-name bar
-       rm $(TMPDIR)/$(call BIN,bar)
-       $(RUSTC) foo1.rs --crate-name bar -o $(TMPDIR)/bar1
+       $(RUSTC) foo1.rs -o $(TMPDIR)/bar1
        rm $(TMPDIR)/$(call BIN,bar1)
diff --git a/src/test/run-make/extra-filename-with-temp-outputs/Makefile b/src/test/run-make/extra-filename-with-temp-outputs/Makefile
new file mode 100644 (file)
index 0000000..28c22a1
--- /dev/null
@@ -0,0 +1,6 @@
+-include ../tools.mk
+
+all:
+       $(RUSTC) -C extra-filename=bar foo.rs -C save-temps
+       rm $(TMPDIR)/foobar.o
+       rm $(TMPDIR)/$(call BIN,foobar)
diff --git a/src/test/run-make/extra-filename-with-temp-outputs/foo.rs b/src/test/run-make/extra-filename-with-temp-outputs/foo.rs
new file mode 100644 (file)
index 0000000..8ae3d07
--- /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.
+
+fn main() {}
index 420ee843766bb3ed3aa831b9831e9cd2a9da9af1..02c7dc38db00fe9198b8b6ce2d62396177044f8c 100644 (file)
@@ -17,7 +17,7 @@ struct Box {
 }
 
 impl Box {
-    fn get<'a>(&'a self) -> &'a uint {
+    fn get(&self) -> &uint {
         &self.x
     }
     fn set(&mut self, x: uint) {
index 924625faa1010a87338d6f025674716ae56bcee9..dd3a7b86bea830b98840f99fb232beba55c673fd 100644 (file)
@@ -60,7 +60,7 @@ fn clear(&mut self) {}
 impl<T> Map<int, T> for cat<T> {
     fn contains_key(&self, k: &int) -> bool { *k <= self.meows }
 
-    fn find<'a>(&'a self, k: &int) -> Option<&'a T> {
+    fn find(&self, k: &int) -> Option<&T> {
         if *k <= self.meows {
             Some(&self.name)
         } else {
@@ -75,7 +75,7 @@ fn insert(&mut self, k: int, _: T) -> bool {
         true
     }
 
-    fn find_mut<'a>(&'a mut self, _k: &int) -> Option<&'a mut T> { fail!() }
+    fn find_mut(&mut self, _k: &int) -> Option<&mut T> { fail!() }
 
     fn remove(&mut self, k: &int) -> bool {
         if self.find(k).is_some() {
@@ -91,7 +91,7 @@ fn swap(&mut self, _k: int, _v: T) -> Option<T> { fail!() }
 }
 
 impl<T> cat<T> {
-    pub fn get<'a>(&'a self, k: &int) -> &'a T {
+    pub fn get(&self, k: &int) -> &T {
         match self.find(k) {
           Some(v) => { v }
           None    => { fail!("epic fail"); }
index e352fc0be981e48e6fca066bc31125bab97fe538..932a5a044ad3e2bfda211090ac662ec64734ab7b 100644 (file)
@@ -42,7 +42,7 @@ fn check_flags(exp: u64) {
 }
 
 impl AddFlags {
-    fn check_flags<'a>(&'a self, exp: u64) -> &'a AddFlags {
+    fn check_flags(&self, exp: u64) -> &AddFlags {
         check_flags(exp);
         self
     }
index abc565d31758f29ef7b61aa855e6dfe7e3b5f6ec..95c7d331264e128b04e5dc45af7556173ab5f160 100644 (file)
@@ -10,6 +10,6 @@
 
 // compile-flags:--crate-name crate-name-attr-used -F unused-attribute
 
-#![crate_name = "test"]
+#![crate_name = "crate-name-attr-used"]
 
 fn main() {}
index 91912e00e180918d01af98e1c1692022b2e8e86d..a62e329f106f542914543a8062475755ead843d7 100644 (file)
@@ -19,7 +19,7 @@ pub fn buf(&self) -> &'a Vec<u8> {
     }
 }
 
-fn font<'r>(fontbuf: &'r Vec<u8> ) -> font<'r> {
+fn font(fontbuf: &Vec<u8> ) -> font {
     font {
         fontbuf: fontbuf
     }
index 455d22fe7f0f5bff9032eb00ac676951faf334cd..23e26ca5665c5a5a3e658baa1f153c85a1198915 100644 (file)
@@ -12,7 +12,7 @@ struct CMap<'a> {
     buf: &'a [u8],
 }
 
-fn CMap<'r>(buf: &'r [u8]) -> CMap<'r> {
+fn CMap(buf: &[u8]) -> CMap {
     CMap {
         buf: buf
     }
index 529f8ecc6ebe12920d0905c98ac6ca50375fc2c5..822fda8a18ec825c3f93ca39d6379fe5d99e0305 100644 (file)
@@ -8,6 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-fn broken<'r>(v: &'r [u8], i: uint, j: uint) -> &'r [u8] { v.slice(i, j) }
+fn broken(v: &[u8], i: uint, j: uint) -> &[u8] { v.slice(i, j) }
 
 pub fn main() {}
index 39c8562e4589b3a709fea93cbac06745b076d016..2bb320e55623514f0532e0438508488c809de445 100644 (file)
@@ -33,7 +33,7 @@ struct Outer<'a> {
 }
 
 impl<'a> Outer<'a> {
-    fn new<'r>(inner: &'r Inner) -> Outer<'r> {
+    fn new(inner: &Inner) -> Outer {
         Outer {
             inner: inner
         }
index 75494c47dcef10746663b0ab18f249578f0b2ed0..d8bb61477a0c8750904cc845edae4c1e08cf0542 100644 (file)
@@ -23,17 +23,17 @@ struct Foo { bar: Bar }
 impl FooBar for Bar {}
 
 trait Test {
-    fn get_immut<'r>(&'r self) -> &'r FooBar;
-    fn get_mut<'r>(&'r mut self) -> &'r mut FooBar;
+    fn get_immut(&self) -> &FooBar;
+    fn get_mut(&mut self) -> &mut FooBar;
 }
 
 macro_rules! generate_test(($type_:path, $slf:ident, $field:expr) => (
     impl Test for $type_ {
-        fn get_immut<'r>(&'r $slf) -> &'r FooBar {
+        fn get_immut(&$slf) -> &FooBar {
             &$field as &FooBar
         }
 
-        fn get_mut<'r>(&'r mut $slf) -> &'r mut FooBar {
+        fn get_mut(&mut $slf) -> &mut FooBar {
             &mut $field as &mut FooBar
         }
     }
diff --git a/src/test/run-pass/match-arm-statics.rs b/src/test/run-pass/match-arm-statics.rs
new file mode 100644 (file)
index 0000000..a8f6d9c
--- /dev/null
@@ -0,0 +1,156 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![feature(struct_variant)]
+
+struct NewBool(bool);
+
+enum Direction {
+    North,
+    East,
+    South,
+    West
+}
+struct Foo {
+    bar: Option<Direction>,
+    baz: NewBool
+}
+enum EnumWithStructVariants {
+    Variant1(bool),
+    Variant2 {
+        dir: Direction
+    }
+}
+
+static TRUE_TRUE: (bool, bool) = (true, true);
+static NONE: Option<Direction> = None;
+static EAST: Direction = East;
+static NEW_FALSE: NewBool = NewBool(false);
+static STATIC_FOO: Foo = Foo { bar: Some(South), baz: NEW_FALSE };
+static VARIANT2_NORTH: EnumWithStructVariants = Variant2 { dir: North };
+
+pub mod glfw {
+    pub struct InputState(uint);
+
+    pub static RELEASE  : InputState = InputState(0);
+    pub static PRESS    : InputState = InputState(1);
+    pub static REPEAT   : InputState = InputState(2);
+}
+
+fn issue_6533() {
+    use glfw;
+
+    fn action_to_str(state: glfw::InputState) -> &'static str {
+        use glfw::{RELEASE, PRESS, REPEAT};
+        match state {
+            RELEASE => { "Released" }
+            PRESS   => { "Pressed"  }
+            REPEAT  => { "Repeated" }
+            _       => { "Unknown"  }
+        }
+    }
+
+    assert_eq!(action_to_str(glfw::RELEASE), "Released");
+    assert_eq!(action_to_str(glfw::PRESS), "Pressed");
+    assert_eq!(action_to_str(glfw::REPEAT), "Repeated");
+}
+
+fn issue_13626() {
+    static VAL: [u8, ..1] = [0];
+    match [1] {
+        VAL => unreachable!(),
+        _ => ()
+    }
+}
+
+fn issue_14576() {
+    type Foo = (i32, i32);
+    static ON: Foo = (1, 1);
+    static OFF: Foo = (0, 0);
+
+    match (1, 1) {
+        OFF => unreachable!(),
+        ON => (),
+        _ => unreachable!()
+    }
+
+    enum C { D = 3, E = 4 }
+    static F : C = D;
+
+    assert_eq!(match D { F => 1i, _ => 2, }, 1);
+}
+
+fn issue_13731() {
+    enum A { A(()) }
+    static B: A = A(());
+
+    match A(()) {
+        B => ()
+    }
+}
+
+fn issue_15393() {
+    #![allow(dead_code)]
+    struct Flags {
+        bits: uint
+    }
+
+    static FOO: Flags = Flags { bits: 0x01 };
+    static BAR: Flags = Flags { bits: 0x02 };
+    match (Flags { bits: 0x02 }) {
+        FOO => unreachable!(),
+        BAR => (),
+        _ => unreachable!()
+    }
+}
+
+fn main() {
+    assert_eq!(match (true, false) {
+        TRUE_TRUE => 1i,
+        (false, false) => 2,
+        (false, true) => 3,
+        (true, false) => 4
+    }, 4);
+
+    assert_eq!(match Some(Some(North)) {
+        Some(NONE) => 1i,
+        Some(Some(North)) => 2,
+        Some(Some(EAST)) => 3,
+        Some(Some(South)) => 4,
+        Some(Some(West)) => 5,
+        None => 6
+    }, 2);
+
+    assert_eq!(match (Foo { bar: Some(West), baz: NewBool(true) }) {
+        Foo { bar: None, baz: NewBool(true) } => 1i,
+        Foo { bar: NONE, baz: NEW_FALSE } => 2,
+        STATIC_FOO => 3,
+        Foo { bar: _, baz: NEW_FALSE } => 4,
+        Foo { bar: Some(West), baz: NewBool(true) } => 5,
+        Foo { bar: Some(South), baz: NewBool(true) } => 6,
+        Foo { bar: Some(EAST), .. } => 7,
+        Foo { bar: Some(North), baz: NewBool(true) } => 8
+    }, 5);
+
+    assert_eq!(match (Variant2 { dir: North }) {
+        Variant1(true) => 1i,
+        Variant1(false) => 2,
+        Variant2 { dir: West } => 3,
+        VARIANT2_NORTH => 4,
+        Variant2 { dir: South } => 5,
+        Variant2 { dir: East } => 6
+    }, 4);
+
+    issue_6533();
+    issue_13626();
+    issue_13731();
+    issue_14576();
+    issue_15393();
+}
index 8b26ece176d4d58bc1e3f00df438f1be09c16cea..10c07e6435400476f7d42ba56ad4f0f769823331 100644 (file)
@@ -29,7 +29,7 @@ fn is_none(&self) -> bool {
             Nothing(..) => true
         }
     }
-    fn get_ref<'r>(&'r self) -> (int, &'r T) {
+    fn get_ref(&self) -> (int, &T) {
         match *self {
             Nothing(..) => fail!("E::get_ref(Nothing::<{}>)",  stringify!(T)),
             Thing(x, ref y) => (x, y)
index a36d8132b260a86cd50fed157f02e2184122c1d5..a896d2b06f7bddbf3de1e66e130252892db001d8 100644 (file)
@@ -43,7 +43,7 @@ fn not(&self) -> Point {
 }
 
 impl ops::Index<bool,int> for Point {
-    fn index<'a>(&'a self, x: &bool) -> &'a int {
+    fn index(&self, x: &bool) -> &int {
         if *x {
             &self.x
         } else {
index 6fdbd17c21b38f98ab0fc61a590142aa18514610..24146c4a6ea6a46ab1845d45ed7a9e43275f5e47 100644 (file)
@@ -33,14 +33,14 @@ fn counts(&self) -> (uint, uint) {
 }
 
 impl<T> Deref<T> for DerefCounter<T> {
-    fn deref<'a>(&'a self) -> &'a T {
+    fn deref(&self) -> &T {
         self.count_imm.set(self.count_imm.get() + 1);
         &self.value
     }
 }
 
 impl<T> DerefMut<T> for DerefCounter<T> {
-    fn deref_mut<'a>(&'a mut self) -> &'a mut T {
+    fn deref_mut(&mut self) -> &mut T {
         self.count_mut += 1;
         &mut self.value
     }
index 188c62751bcd979b6f99922b62e5211f75d2c358..0a9ac734c26fdd96a5f6d06e61503ed9459def91 100644 (file)
@@ -22,7 +22,7 @@ fn get_x(self) -> X {
 }
 
 impl<X, Y> Deref<Y> for DerefWrapper<X, Y> {
-    fn deref<'a>(&'a self) -> &'a Y {
+    fn deref(&self) -> &Y {
         &self.y
     }
 }
@@ -43,7 +43,7 @@ pub fn new(x: X, y: Y) -> DerefWrapperHideX<X, Y> {
     }
 
     impl<X, Y> Deref<Y> for DerefWrapperHideX<X, Y> {
-        fn deref<'a>(&'a self) -> &'a Y {
+        fn deref(&self) -> &Y {
             &self.y
         }
     }
index 15b5cca9cf83ea681c2899b0b9067e2a3b2723b1..f71afb96507432390009310b9d237e4505dc609d 100644 (file)
@@ -15,17 +15,17 @@ struct DerefWithHelper<H, T> {
 }
 
 trait Helper<T> {
-    fn helper_borrow<'a>(&'a self) -> &'a T;
+    fn helper_borrow(&self) -> &T;
 }
 
 impl<T> Helper<T> for Option<T> {
-    fn helper_borrow<'a>(&'a self) -> &'a T {
+    fn helper_borrow(&self) -> &T {
         self.as_ref().unwrap()
     }
 }
 
 impl<T, H: Helper<T>> Deref<T> for DerefWithHelper<H, T> {
-    fn deref<'a>(&'a self) -> &'a T {
+    fn deref(&self) -> &T {
         self.helper.helper_borrow()
     }
 }
index 283c76adf0dafcc2a90d17ba8114c6c16af9270e..0b5406b8f67d5a7c645c2228567debaaa43dc25d 100644 (file)
@@ -33,14 +33,14 @@ fn counts(&self) -> (uint, uint) {
 }
 
 impl<T> Deref<T> for DerefCounter<T> {
-    fn deref<'a>(&'a self) -> &'a T {
+    fn deref(&self) -> &T {
         self.count_imm.set(self.count_imm.get() + 1);
         &self.value
     }
 }
 
 impl<T> DerefMut<T> for DerefCounter<T> {
-    fn deref_mut<'a>(&'a mut self) -> &'a mut T {
+    fn deref_mut(&mut self) -> &mut T {
         self.count_mut += 1;
         &mut self.value
     }
index 9d7c068cccd937e092988b3d0be7808ea9272248..1187e066950704a9765cb9106bb4f5313ec75f32 100644 (file)
@@ -14,7 +14,7 @@ struct Foo {
 }
 
 impl Index<int,int> for Foo {
-    fn index<'a>(&'a self, z: &int) -> &'a int {
+    fn index(&self, z: &int) -> &int {
         if *z == 0 {
             &self.x
         } else {
@@ -24,7 +24,7 @@ fn index<'a>(&'a self, z: &int) -> &'a int {
 }
 
 impl IndexMut<int,int> for Foo {
-    fn index_mut<'a>(&'a mut self, z: &int) -> &'a mut int {
+    fn index_mut(&mut self, z: &int) -> &mut int {
         if *z == 0 {
             &mut self.x
         } else {
index 47ae5c13d28cb65dce53f6ee8d3afacd4c7fc836..bb2885a21778525045bc9cae919fa85a8d2013f0 100644 (file)
@@ -18,7 +18,7 @@ struct Character {
     pos: Box<Point>,
 }
 
-fn get_x<'r>(x: &'r Character) -> &'r int {
+fn get_x(x: &Character) -> &int {
     // interesting case because the scope of this
     // borrow of the unique pointer is in fact
     // larger than the fn itself
index 357d829627da0f898964653ba2f6276ee6327eee..a046ba456a6b06e9eb306a764986fca97bfb0ec3 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-fn f<'a>(x : &'a int) -> &'a int {
+fn f(x: &int) -> &int {
     return &*x;
 }
 
index 65cecb2d5008bbfdb976ccdfd7d807a7835d2654..b4523ce41ce751af93ba7c58690fa58ea2727666 100644 (file)
@@ -12,7 +12,7 @@ struct closure_box<'a> {
     cl: ||: 'a,
 }
 
-fn box_it<'r>(x: ||: 'r) -> closure_box<'r> {
+fn box_it(x: ||) -> closure_box {
     closure_box {cl: x}
 }
 
index 400ab462f761f127a4e0a4f5343976c8e8895dfb..252c0b5578ac65bfd3e8348a7f2bde749c8cbad2 100644 (file)
@@ -29,54 +29,54 @@ struct C {
     f: int
 }
 
-fn get_v1<'v>(a: &'v A) -> &'v int {
+fn get_v1(a: &A) -> &int {
     // Region inferencer must deduce that &v < L2 < L1
     let foo = &a.value; // L1
     &foo.v1             // L2
 }
 
-fn get_v2<'v>(a: &'v A, i: uint) -> &'v int {
+fn get_v2(a: &A, i: uint) -> &int {
     let foo = &a.value;
     &foo.v2[i]
 }
 
-fn get_v3<'v>(a: &'v A, i: uint) -> &'v int {
+fn get_v3(a: &A, i: uint) -> &int {
     let foo = &a.value;
     foo.v3.get(i)
 }
 
-fn get_v4<'v>(a: &'v A, _i: uint) -> &'v int {
+fn get_v4(a: &A, _i: uint) -> &int {
     let foo = &a.value;
     &foo.v4.f
 }
 
-fn get_v5<'v>(a: &'v A, _i: uint) -> &'v int {
+fn get_v5(a: &A, _i: uint) -> &int {
     let foo = &a.value;
     &foo.v5.f
 }
 
-fn get_v6_a<'v>(a: &'v A, _i: uint) -> &'v int {
+fn get_v6_a(a: &A, _i: uint) -> &int {
     match a.value.v6 {
         Some(ref v) => &v.f,
         None => fail!()
     }
 }
 
-fn get_v6_b<'v>(a: &'v A, _i: uint) -> &'v int {
+fn get_v6_b(a: &A, _i: uint) -> &int {
     match *a {
         A { value: B { v6: Some(ref v), .. } } => &v.f,
         _ => fail!()
     }
 }
 
-fn get_v6_c<'v>(a: &'v A, _i: uint) -> &'v int {
+fn get_v6_c(a: &A, _i: uint) -> &int {
     match a {
         &A { value: B { v6: Some(ref v), .. } } => &v.f,
         _ => fail!()
     }
 }
 
-fn get_v5_ref<'v>(a: &'v A, _i: uint) -> &'v int {
+fn get_v5_ref(a: &A, _i: uint) -> &int {
     match &a.value {
         &B {v5: box C {f: ref v}, ..} => v
     }
index e9cd7fb49731fc7838cef65621006f4a7a84a253..311fd1bcdf2e06cb72392b50a06ab7fe61db7bad 100644 (file)
@@ -11,9 +11,9 @@
 // Test lifetimes are linked properly when we autoslice a vector.
 // Issue #3148.
 
-fn subslice<'r>(v: ||: 'r) -> ||: 'r { v }
+fn subslice(v: ||) -> || { v }
 
-fn both<'r>(v: ||: 'r) -> ||: 'r {
+fn both(v: ||) -> || {
     subslice(subslice(v))
 }
 
index 5e2893c49809e45e901752866063ea2a83ca7c44..46e1aaa3a241b180a6b51204ecddc554535567fa 100644 (file)
@@ -12,7 +12,7 @@
 
 use std::gc::GC;
 
-fn foo<'r>(x: &'r uint) -> &'r uint { x }
+fn foo(x: &uint) -> &uint { x }
 fn bar(x: &uint) -> uint { *x }
 
 pub fn main() {
index 13200d619d02e0ba9dbe63ca017f782280895ad1..c4e0e3bb4fc11ec674f441f019be179243394b1e 100644 (file)
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 
-fn view<'r, T>(x: &'r [T]) -> &'r [T] {x}
+fn view<T>(x: &[T]) -> &[T] {x}
 
 pub fn main() {
     let v = vec!(1i, 2, 3);
index 0b42f71fccb051e41fb69a318b6dbdeb45fcf599..4d4417189c9081f805566c8235cf64e47bb07c13 100644 (file)
@@ -10,7 +10,7 @@
 
 use std::gc::GC;
 
-fn borrow<'r, T>(x: &'r T) -> &'r T {x}
+fn borrow<T>(x: &T) -> &T {x}
 
 pub fn main() {
     let x = box(GC) 3i;
index abbbb51580fb7f0ccf2f3dfd63c463720f91b7ac..65e753ddee12d384f21b4293a11f02b460a3ab03 100644 (file)
@@ -14,7 +14,7 @@
 
 struct Point {x: int, y: int}
 
-fn x_coord<'r>(p: &'r Point) -> &'r int {
+fn x_coord(p: &Point) -> &int {
     return &p.x;
 }
 
index 784424ad54c8aa1ec1652d7242e8c167fd495ee1..845ef4017447c58ab0e083efdbf7c476ad2d621d 100644 (file)
@@ -12,7 +12,7 @@ enum roption<'a> {
     a, b(&'a uint)
 }
 
-fn mk<'r>(cond: bool, ptr: &'r uint) -> roption<'r> {
+fn mk(cond: bool, ptr: &uint) -> roption {
     if cond {a} else {b(ptr)}
 }
 
index b83d7af9a11d35b0433000a5736e5d77cf5ef123..c0e821b8d3854424fe960f2f7eba8bec0a2ed8a8 100644 (file)
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 
-fn region_identity<'r>(x: &'r uint) -> &'r uint { x }
+fn region_identity(x: &uint) -> &uint { x }
 
 fn apply<T>(t: T, f: |T| -> T) -> T { f(t) }
 
index d1530c4c7b91a13e82d7444c3b5637f1e0ee1b47..f6971a8b4ad30e189cc61b720ae589e78ba30a86 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-fn get<'r, T>(opt: &'r Option<T>) -> &'r T {
+fn get<T>(opt: &Option<T>) -> &T {
     match *opt {
       Some(ref v) => v,
       None => fail!("none")
index d91c11dde10e2da6e24f2eaa2c5f35e2203b07d4..f1d2adcaf94d876478fe142df78353b6e4388427 100644 (file)
@@ -12,7 +12,7 @@ struct closure_box<'a> {
     cl: ||: 'a,
 }
 
-fn box_it<'r>(x: ||: 'r) -> closure_box<'r> {
+fn box_it(x: ||) -> closure_box {
     closure_box {cl: x}
 }