]> git.lizzy.rs Git - rust.git/commitdiff
Rollup merge of #39697 - notriddle:rustdoc_tooltip, r=GuillaumeGomez
authorGuillaume Gomez <guillaume1.gomez@gmail.com>
Sun, 12 Feb 2017 18:16:30 +0000 (19:16 +0100)
committerGitHub <noreply@github.com>
Sun, 12 Feb 2017 18:16:30 +0000 (19:16 +0100)
Add the item type to the tooltip

See:
https://users.rust-lang.org/t/seeking-opinions-from-colorblind-rustaceans-coloring-in-rustdoc-code-blocks

64 files changed:
.mailmap
RELEASES.md
src/Cargo.lock
src/bootstrap/config.rs
src/bootstrap/config.toml.example
src/doc/book/nightly-rust.md
src/liballoc/boxed.rs
src/liballoc/boxed_test.rs
src/libcollections/btree/set.rs
src/libcollections/vec.rs
src/libcore/fmt/mod.rs
src/libcore/iter/iterator.rs
src/libcore/macros.rs
src/libcore/ops.rs
src/libcore/slice.rs
src/libcore/str/pattern.rs
src/librustc/ty/inhabitedness/mod.rs
src/librustc/ty/sty.rs
src/librustc_const_eval/_match.rs
src/librustc_data_structures/flock.rs
src/librustc_driver/driver.rs
src/librustc_llvm/ffi.rs
src/librustc_metadata/index.rs
src/librustc_mir/build/matches/simplify.rs
src/librustc_trans/Cargo.toml
src/librustc_trans/back/link.rs
src/librustc_trans/back/linker.rs
src/librustc_trans/back/write.rs
src/librustc_trans/base.rs
src/librustc_trans/debuginfo/metadata.rs
src/librustc_trans/debuginfo/mod.rs
src/librustc_trans/lib.rs
src/librustc_trans/mir/mod.rs
src/librustc_typeck/check/op.rs
src/librustdoc/html/render.rs
src/libstd/collections/hash/set.rs
src/libstd/collections/mod.rs
src/libstd/lib.rs
src/libstd/panicking.rs
src/libsyntax/parse/parser.rs
src/libtest/lib.rs
src/rustllvm/RustWrapper.cpp
src/test/codegen/mainsubprogram.rs [new file with mode: 0644]
src/test/codegen/mainsubprogramstart.rs [new file with mode: 0644]
src/test/compile-fail/binary-op-on-double-ref.rs
src/test/compile-fail/feature-gate-const-indexing.rs [new file with mode: 0644]
src/test/compile-fail/inhabitedness-infinite-loop.rs [new file with mode: 0644]
src/test/compile-fail/issue-39388.rs [new file with mode: 0644]
src/test/compile-fail/issue-39616.rs [new file with mode: 0644]
src/test/debuginfo/macro-stepping.inc [new file with mode: 0644]
src/test/debuginfo/macro-stepping.rs
src/test/parse-fail/issue-39018.stderr [deleted file]
src/test/run-pass/catch-unwind-bang.rs [new file with mode: 0644]
src/test/run-pass/dst-field-align.rs
src/test/run-pass/mir_adt_construction.rs
src/test/run-pass/u128.rs
src/test/rustdoc/attributes.rs [new file with mode: 0644]
src/test/ui/macros/assert_eq_trailing_comma.rs [new file with mode: 0644]
src/test/ui/macros/assert_eq_trailing_comma.stderr [new file with mode: 0644]
src/test/ui/macros/assert_ne_trailing_comma.rs [new file with mode: 0644]
src/test/ui/macros/assert_ne_trailing_comma.stderr [new file with mode: 0644]
src/test/ui/span/issue-39018.stderr
src/tools/build-manifest/src/main.rs
src/tools/tidy/src/features.rs

index 1ae0aae2d01baeb9664f244ececb7a3815145716..4b4f343d15a9d3c2c93ad89183e7c4954a43634b 100644 (file)
--- a/.mailmap
+++ b/.mailmap
@@ -132,9 +132,8 @@ Lindsey Kuper <lindsey@composition.al> <lkuper@mozilla.com>
 Luke Metz <luke.metz@students.olin.edu>
 Luqman Aden <me@luqman.ca> <laden@csclub.uwaterloo.ca>
 Luqman Aden <me@luqman.ca> <laden@mozilla.com>
-Makoto Nakashima <makoto.nksm+github@gmail.com> <makoto.nksm@gmail.com>
-Makoto Nakashima <makoto.nksm+github@gmail.com> gifnksm <makoto.nksm+github@gmail.com>
-Makoto Nakashima <makoto.nksm+github@gmail.com> NAKASHIMA, Makoto <makoto.nksm+github@gmail.com>
+NAKASHIMA, Makoto <makoto.nksm+github@gmail.com> <makoto.nksm@gmail.com>
+NAKASHIMA, Makoto <makoto.nksm+github@gmail.com> <makoto.nksm+github@gmail.com>
 Marcell Pardavi <marcell.pardavi@gmail.com>
 Margaret Meyerhofer <mmeyerho@andrew.cmu.edu> <mmeyerho@andrew>
 Mark Sinclair <mark.edward.x@gmail.com>
@@ -150,7 +149,6 @@ Michael Woerister <michaelwoerister@posteo> <michaelwoerister@gmail>
 Mickaël Raybaud-Roig <raybaudroigm@gmail.com> m-r-r <raybaudroigm@gmail.com>
 Ms2ger <ms2ger@gmail.com> <Ms2ger@gmail.com>
 Mukilan Thiagarajan <mukilanthiagarajan@gmail.com>
-NAKASHIMA, Makoto <makoto.nksm+github@gmail.com>
 Nathan Wilson <wilnathan@gmail.com>
 Nathaniel Herman <nherman@post.harvard.edu> Nathaniel Herman <nherman@college.harvard.edu>
 Neil Pankey <npankey@gmail.com> <neil@wire.im>
index 2df1a83db81ffb3a5fa806a3ffd44863e582ae3b..1de44ef7e6d0546dd024f5a7e0eaf1e6bc232528 100644 (file)
@@ -1,9 +1,11 @@
-Version 1.15.1 (2017-02-08)
+Version 1.15.1 (2017-02-09)
 ===========================
 
 * [Fix IntoIter::as_mut_slice's signature][39466]
+* [Compile compiler builtins with `-fPIC` on 32-bit platforms][39523]
 
 [39466]: https://github.com/rust-lang/rust/pull/39466
+[39523]: https://github.com/rust-lang/rust/pull/39523
 
 
 Version 1.15.0 (2017-02-02)
index 09aefd45e94c88964ce6bdcd1515c6f9dc5b2460..219ed5d6bc281ba86d120e3c415b705bf5cc7639 100644 (file)
@@ -551,6 +551,7 @@ dependencies = [
  "rustc_incremental 0.0.0",
  "rustc_llvm 0.0.0",
  "rustc_platform_intrinsics 0.0.0",
+ "serialize 0.0.0",
  "syntax 0.0.0",
  "syntax_pos 0.0.0",
 ]
index 604c0397d5242972a118b26b4e0bd2ced74bf9d8..47f505ad37e744c6b440d1f41b7b004482b7bda0 100644 (file)
@@ -150,6 +150,7 @@ struct Build {
     python: Option<String>,
     full_bootstrap: Option<bool>,
     extended: Option<bool>,
+    verbose: Option<usize>,
     sanitizers: Option<bool>,
 }
 
@@ -296,6 +297,7 @@ pub fn parse(build: &str, file: Option<PathBuf>) -> Config {
         set(&mut config.vendor, build.vendor);
         set(&mut config.full_bootstrap, build.full_bootstrap);
         set(&mut config.extended, build.extended);
+        set(&mut config.verbose, build.verbose);
         set(&mut config.sanitizers, build.sanitizers);
 
         if let Some(ref install) = toml.install {
index 025fe990f91dab67e27e338e8bd9f08faa754ffb..5f4303a728c5c2c46b3d63afe6b54fcc32b21299 100644 (file)
 # disabled by default.
 #extended = false
 
+# Verbosity level: 0 == not verbose, 1 == verbose, 2 == very verbose
+#verbose = 0
+
 # Build the sanitizer runtimes
 #sanitizers = false
 
index 25570cb5503c94f6f3c8ccebaee24baaaa3a86a6..f55bb0784202a7079204e6374f762d998954e8dc 100644 (file)
@@ -6,10 +6,13 @@ process, see ‘[Stability as a deliverable][stability]’.
 
 [stability]: http://blog.rust-lang.org/2014/10/30/Stability.html
 
-To install nightly Rust, you can use `rustup.sh`:
+To install nightly Rust, you can use [rustup.rs][rustup]:
+
+[rustup]: https://rustup.rs
 
 ```bash
-$ curl -s https://static.rust-lang.org/rustup.sh | sh -s -- --channel=nightly
+$ curl https://sh.rustup.rs -sSf | sh
+$ rustup install nightly
 ```
 
 If you're concerned about the [potential insecurity][insecurity] of using `curl
@@ -17,31 +20,28 @@ If you're concerned about the [potential insecurity][insecurity] of using `curl
 use a two-step version of the installation and examine our installation script:
 
 ```bash
-$ curl -f -L https://static.rust-lang.org/rustup.sh -O
-$ sh rustup.sh --channel=nightly
+$ curl https://sh.rustup.rs -sSf -o rustup.sh
+$ sh rustup.sh
+$ rustup install nightly
 ```
 
 [insecurity]: http://curlpipesh.tumblr.com
 
-If you're on Windows, please download either the [32-bit installer][win32] or
-the [64-bit installer][win64] and run it.
+If you're on Windows, please download the [rustup installer][installer]
+and run it.
 
-[win32]: https://static.rust-lang.org/dist/rust-nightly-i686-pc-windows-gnu.msi
-[win64]: https://static.rust-lang.org/dist/rust-nightly-x86_64-pc-windows-gnu.msi
+[installer]: https://win.rustup.rs
 
 ## Uninstalling
 
 If you decide you don't want Rust anymore, we'll be a bit sad, but that's okay.
 Not every programming language is great for everyone. Just run the uninstall
-script:
+command:
 
 ```bash
-$ sudo /usr/local/lib/rustlib/uninstall.sh
+$ rustup self uninstall
 ```
 
-If you used the Windows installer, re-run the `.msi` and it will give you
-an uninstall option.
-
 Some people, and somewhat rightfully so, get very upset when we tell you to
 `curl | sh`. Basically, when you do this, you are trusting that the good
 people who maintain Rust aren't going to hack your computer and do bad things.
index 82d361fb0e853064ffa317b66e582f36f87b6660..ac9439974a491c9d634c9ff461355b8b4218c6e7 100644 (file)
@@ -419,6 +419,23 @@ fn from(t: T) -> Self {
     }
 }
 
+#[stable(feature = "box_from_slice", since = "1.17.0")]
+impl<'a, T: Copy> From<&'a [T]> for Box<[T]> {
+    fn from(slice: &'a [T]) -> Box<[T]> {
+        let mut boxed = unsafe { RawVec::with_capacity(slice.len()).into_box() };
+        boxed.copy_from_slice(slice);
+        boxed
+    }
+}
+
+#[stable(feature = "box_from_slice", since = "1.17.0")]
+impl<'a> From<&'a str> for Box<str> {
+    fn from(s: &'a str) -> Box<str> {
+        let boxed: Box<[u8]> = Box::from(s.as_bytes());
+        unsafe { mem::transmute(boxed) }
+    }
+}
+
 impl Box<Any> {
     #[inline]
     #[stable(feature = "rust1", since = "1.0.0")]
index 8d68ce3c1f6e2ebfa406c81a15cb50c478df4139..837f8dfaca13a52ecddab5f7dd9b6114a8a75ae5 100644 (file)
@@ -14,6 +14,8 @@
 use core::ops::Deref;
 use core::result::Result::{Err, Ok};
 use core::clone::Clone;
+use core::f64;
+use core::i64;
 
 use std::boxed::Box;
 
@@ -117,3 +119,24 @@ fn set(&mut self, value: u32) {
         assert_eq!(19, y.get());
     }
 }
+
+#[test]
+fn f64_slice() {
+    let slice: &[f64] = &[-1.0, 0.0, 1.0, f64::INFINITY];
+    let boxed: Box<[f64]> = Box::from(slice);
+    assert_eq!(&*boxed, slice)
+}
+
+#[test]
+fn i64_slice() {
+    let slice: &[i64] = &[i64::MIN, -2, -1, 0, 1, 2, i64::MAX];
+    let boxed: Box<[i64]> = Box::from(slice);
+    assert_eq!(&*boxed, slice)
+}
+
+#[test]
+fn str_slice() {
+    let s = "Hello, world!";
+    let boxed: Box<str> = Box::from(s);
+    assert_eq!(&*boxed, s)
+}
index bfffa0b8efa1cb074168f78c6217055e5371caed..e3c990c80decfc9ce7a075a0d4305a2b241454f6 100644 (file)
@@ -289,7 +289,9 @@ pub fn range<K: ?Sized, R>(&self, range: R) -> Range<T>
 }
 
 impl<T: Ord> BTreeSet<T> {
-    /// Visits the values representing the difference, in ascending order.
+    /// Visits the values representing the difference,
+    /// i.e. the values that are in `self` but not in `other`,
+    /// in ascending order.
     ///
     /// # Examples
     ///
@@ -315,7 +317,9 @@ pub fn difference<'a>(&'a self, other: &'a BTreeSet<T>) -> Difference<'a, T> {
         }
     }
 
-    /// Visits the values representing the symmetric difference, in ascending order.
+    /// Visits the values representing the symmetric difference,
+    /// i.e. the values that are in `self` or in `other` but not in both,
+    /// in ascending order.
     ///
     /// # Examples
     ///
@@ -343,7 +347,9 @@ pub fn symmetric_difference<'a>(&'a self,
         }
     }
 
-    /// Visits the values representing the intersection, in ascending order.
+    /// Visits the values representing the intersection,
+    /// i.e. the values that are both in `self` and `other`,
+    /// in ascending order.
     ///
     /// # Examples
     ///
@@ -369,7 +375,9 @@ pub fn intersection<'a>(&'a self, other: &'a BTreeSet<T>) -> Intersection<'a, T>
         }
     }
 
-    /// Visits the values representing the union, in ascending order.
+    /// Visits the values representing the union,
+    /// i.e. all the values in `self` or `other`, without duplicates,
+    /// in ascending order.
     ///
     /// # Examples
     ///
@@ -480,7 +488,7 @@ pub fn get<Q: ?Sized>(&self, value: &Q) -> Option<&T>
         Recover::get(&self.map, value)
     }
 
-    /// Returns `true` if the set has no elements in common with `other`.
+    /// Returns `true` if `self` has no elements in common with `other`.
     /// This is equivalent to checking for an empty intersection.
     ///
     /// # Examples
@@ -502,7 +510,8 @@ pub fn is_disjoint(&self, other: &BTreeSet<T>) -> bool {
         self.intersection(other).next().is_none()
     }
 
-    /// Returns `true` if the set is a subset of another.
+    /// Returns `true` if the set is a subset of another,
+    /// i.e. `other` contains at least all the values in `self`.
     ///
     /// # Examples
     ///
@@ -544,7 +553,8 @@ pub fn is_subset(&self, other: &BTreeSet<T>) -> bool {
         true
     }
 
-    /// Returns `true` if the set is a superset of another.
+    /// Returns `true` if the set is a superset of another,
+    /// i.e. `self` contains at least all the values in `other`.
     ///
     /// # Examples
     ///
index dc0f33d9bc3e00d82e0ca9a5d92d835050bc218a..3873b3535a07b5bacc8d61e3091ea2faf5ff4bef 100644 (file)
@@ -437,7 +437,9 @@ pub fn capacity(&self) -> usize {
 
     /// Reserves capacity for at least `additional` more elements to be inserted
     /// in the given `Vec<T>`. The collection may reserve more space to avoid
-    /// frequent reallocations.
+    /// frequent reallocations. After calling `reserve`, capacity will be
+    /// greater than or equal to `self.len() + additional`. Does nothing if
+    /// capacity is already sufficient.
     ///
     /// # Panics
     ///
@@ -456,8 +458,9 @@ pub fn reserve(&mut self, additional: usize) {
     }
 
     /// Reserves the minimum capacity for exactly `additional` more elements to
-    /// be inserted in the given `Vec<T>`. Does nothing if the capacity is already
-    /// sufficient.
+    /// be inserted in the given `Vec<T>`. After calling `reserve_exact`,
+    /// capacity will be greater than or equal to `self.len() + additional`.
+    /// Does nothing if the capacity is already sufficient.
     ///
     /// Note that the allocator may give the collection more space than it
     /// requests. Therefore capacity can not be relied upon to be precisely
index eb086c201812a3f0c9e3671c2abed863615aff66..6c48c29ecd1512fa3e013310b1c220a9e732d1a1 100644 (file)
@@ -434,7 +434,7 @@ fn fmt(&self, fmt: &mut Formatter) -> Result {
 pub trait Debug {
     /// Formats the value using the given formatter.
     #[stable(feature = "rust1", since = "1.0.0")]
-    fn fmt(&self, &mut Formatter) -> Result;
+    fn fmt(&self, f: &mut Formatter) -> Result;
 }
 
 /// Format trait for an empty format, `{}`.
@@ -477,7 +477,7 @@ pub trait Debug {
 pub trait Display {
     /// Formats the value using the given formatter.
     #[stable(feature = "rust1", since = "1.0.0")]
-    fn fmt(&self, &mut Formatter) -> Result;
+    fn fmt(&self, f: &mut Formatter) -> Result;
 }
 
 /// Format trait for the `o` character.
@@ -524,7 +524,7 @@ pub trait Display {
 pub trait Octal {
     /// Formats the value using the given formatter.
     #[stable(feature = "rust1", since = "1.0.0")]
-    fn fmt(&self, &mut Formatter) -> Result;
+    fn fmt(&self, f: &mut Formatter) -> Result;
 }
 
 /// Format trait for the `b` character.
@@ -571,7 +571,7 @@ pub trait Octal {
 pub trait Binary {
     /// Formats the value using the given formatter.
     #[stable(feature = "rust1", since = "1.0.0")]
-    fn fmt(&self, &mut Formatter) -> Result;
+    fn fmt(&self, f: &mut Formatter) -> Result;
 }
 
 /// Format trait for the `x` character.
@@ -619,7 +619,7 @@ pub trait Binary {
 pub trait LowerHex {
     /// Formats the value using the given formatter.
     #[stable(feature = "rust1", since = "1.0.0")]
-    fn fmt(&self, &mut Formatter) -> Result;
+    fn fmt(&self, f: &mut Formatter) -> Result;
 }
 
 /// Format trait for the `X` character.
@@ -667,7 +667,7 @@ pub trait LowerHex {
 pub trait UpperHex {
     /// Formats the value using the given formatter.
     #[stable(feature = "rust1", since = "1.0.0")]
-    fn fmt(&self, &mut Formatter) -> Result;
+    fn fmt(&self, f: &mut Formatter) -> Result;
 }
 
 /// Format trait for the `p` character.
@@ -712,7 +712,7 @@ pub trait UpperHex {
 pub trait Pointer {
     /// Formats the value using the given formatter.
     #[stable(feature = "rust1", since = "1.0.0")]
-    fn fmt(&self, &mut Formatter) -> Result;
+    fn fmt(&self, f: &mut Formatter) -> Result;
 }
 
 /// Format trait for the `e` character.
@@ -755,7 +755,7 @@ pub trait Pointer {
 pub trait LowerExp {
     /// Formats the value using the given formatter.
     #[stable(feature = "rust1", since = "1.0.0")]
-    fn fmt(&self, &mut Formatter) -> Result;
+    fn fmt(&self, f: &mut Formatter) -> Result;
 }
 
 /// Format trait for the `E` character.
@@ -798,7 +798,7 @@ pub trait LowerExp {
 pub trait UpperExp {
     /// Formats the value using the given formatter.
     #[stable(feature = "rust1", since = "1.0.0")]
-    fn fmt(&self, &mut Formatter) -> Result;
+    fn fmt(&self, f: &mut Formatter) -> Result;
 }
 
 /// The `write` function takes an output stream, a precompiled format string,
index 3b406873d4b191b63fc2d5a71cc416fd884d4606..d41767cce18fe9ef2710217bc3e9650484fa9eb9 100644 (file)
@@ -209,11 +209,14 @@ fn last(self) -> Option<Self::Item> where Self: Sized {
 
     /// Returns the `n`th element of the iterator.
     ///
-    /// Note that all preceding elements will be consumed (i.e. discarded).
-    ///
     /// Like most indexing operations, the count starts from zero, so `nth(0)`
     /// returns the first value, `nth(1)` the second, and so on.
     ///
+    /// Note that all preceding elements, as well as the returned element, will be
+    /// consumed from the iterator. That means that the preceding elements will be
+    /// discarded, and also that calling `nth(0)` multiple times on the same iterator
+    /// will return different elements.
+    ///
     /// `nth()` will return [`None`] if `n` is greater than or equal to the length of the
     /// iterator.
     ///
index bc5392f6b88491466e6c44799d535ca46dcef228..66a923f8e588ae33fe11784d12096ab9c0d45010 100644 (file)
@@ -103,7 +103,7 @@ macro_rules! assert {
 #[macro_export]
 #[stable(feature = "rust1", since = "1.0.0")]
 macro_rules! assert_eq {
-    ($left:expr , $right:expr) => ({
+    ($left:expr, $right:expr) => ({
         match (&$left, &$right) {
             (left_val, right_val) => {
                 if !(*left_val == *right_val) {
@@ -113,13 +113,13 @@ macro_rules! assert_eq {
             }
         }
     });
-    ($left:expr , $right:expr, $($arg:tt)*) => ({
+    ($left:expr, $right:expr, $($arg:tt)+) => ({
         match (&($left), &($right)) {
             (left_val, right_val) => {
                 if !(*left_val == *right_val) {
                     panic!("assertion failed: `(left == right)` \
                            (left: `{:?}`, right: `{:?}`): {}", left_val, right_val,
-                           format_args!($($arg)*))
+                           format_args!($($arg)+))
                 }
             }
         }
@@ -146,7 +146,7 @@ macro_rules! assert_eq {
 #[macro_export]
 #[stable(feature = "assert_ne", since = "1.12.0")]
 macro_rules! assert_ne {
-    ($left:expr , $right:expr) => ({
+    ($left:expr, $right:expr) => ({
         match (&$left, &$right) {
             (left_val, right_val) => {
                 if *left_val == *right_val {
@@ -156,13 +156,13 @@ macro_rules! assert_ne {
             }
         }
     });
-    ($left:expr , $right:expr, $($arg:tt)*) => ({
+    ($left:expr, $right:expr, $($arg:tt)+) => ({
         match (&($left), &($right)) {
             (left_val, right_val) => {
                 if *left_val == *right_val {
                     panic!("assertion failed: `(left != right)` \
                            (left: `{:?}`, right: `{:?}`): {}", left_val, right_val,
-                           format_args!($($arg)*))
+                           format_args!($($arg)+))
                 }
             }
         }
index 566fb89365a51ae3f42cca5dc13a24eca0f616c1..59bcb340ec99a07accf078d53eb04d628ee5a275 100644 (file)
@@ -1324,7 +1324,7 @@ macro_rules! shr_impl_all {
 pub trait AddAssign<Rhs=Self> {
     /// The method for the `+=` operator
     #[stable(feature = "op_assign_traits", since = "1.8.0")]
-    fn add_assign(&mut self, Rhs);
+    fn add_assign(&mut self, rhs: Rhs);
 }
 
 macro_rules! add_assign_impl {
@@ -1380,7 +1380,7 @@ fn add_assign(&mut self, other: $t) { *self += other }
 pub trait SubAssign<Rhs=Self> {
     /// The method for the `-=` operator
     #[stable(feature = "op_assign_traits", since = "1.8.0")]
-    fn sub_assign(&mut self, Rhs);
+    fn sub_assign(&mut self, rhs: Rhs);
 }
 
 macro_rules! sub_assign_impl {
@@ -1425,7 +1425,7 @@ fn sub_assign(&mut self, other: $t) { *self -= other }
 pub trait MulAssign<Rhs=Self> {
     /// The method for the `*=` operator
     #[stable(feature = "op_assign_traits", since = "1.8.0")]
-    fn mul_assign(&mut self, Rhs);
+    fn mul_assign(&mut self, rhs: Rhs);
 }
 
 macro_rules! mul_assign_impl {
@@ -1470,7 +1470,7 @@ fn mul_assign(&mut self, other: $t) { *self *= other }
 pub trait DivAssign<Rhs=Self> {
     /// The method for the `/=` operator
     #[stable(feature = "op_assign_traits", since = "1.8.0")]
-    fn div_assign(&mut self, Rhs);
+    fn div_assign(&mut self, rhs: Rhs);
 }
 
 macro_rules! div_assign_impl {
@@ -1514,7 +1514,7 @@ fn div_assign(&mut self, other: $t) { *self /= other }
 pub trait RemAssign<Rhs=Self> {
     /// The method for the `%=` operator
     #[stable(feature = "op_assign_traits", since = "1.8.0")]
-    fn rem_assign(&mut self, Rhs);
+    fn rem_assign(&mut self, rhs: Rhs);
 }
 
 macro_rules! rem_assign_impl {
@@ -1600,7 +1600,7 @@ fn rem_assign(&mut self, other: $t) { *self %= other }
 pub trait BitAndAssign<Rhs=Self> {
     /// The method for the `&=` operator
     #[stable(feature = "op_assign_traits", since = "1.8.0")]
-    fn bitand_assign(&mut self, Rhs);
+    fn bitand_assign(&mut self, rhs: Rhs);
 }
 
 macro_rules! bitand_assign_impl {
@@ -1644,7 +1644,7 @@ fn bitand_assign(&mut self, other: $t) { *self &= other }
 pub trait BitOrAssign<Rhs=Self> {
     /// The method for the `|=` operator
     #[stable(feature = "op_assign_traits", since = "1.8.0")]
-    fn bitor_assign(&mut self, Rhs);
+    fn bitor_assign(&mut self, rhs: Rhs);
 }
 
 macro_rules! bitor_assign_impl {
@@ -1688,7 +1688,7 @@ fn bitor_assign(&mut self, other: $t) { *self |= other }
 pub trait BitXorAssign<Rhs=Self> {
     /// The method for the `^=` operator
     #[stable(feature = "op_assign_traits", since = "1.8.0")]
-    fn bitxor_assign(&mut self, Rhs);
+    fn bitxor_assign(&mut self, rhs: Rhs);
 }
 
 macro_rules! bitxor_assign_impl {
@@ -1732,7 +1732,7 @@ fn bitxor_assign(&mut self, other: $t) { *self ^= other }
 pub trait ShlAssign<Rhs> {
     /// The method for the `<<=` operator
     #[stable(feature = "op_assign_traits", since = "1.8.0")]
-    fn shl_assign(&mut self, Rhs);
+    fn shl_assign(&mut self, rhs: Rhs);
 }
 
 macro_rules! shl_assign_impl {
@@ -1797,7 +1797,7 @@ macro_rules! shl_assign_impl_all {
 pub trait ShrAssign<Rhs=Self> {
     /// The method for the `>>=` operator
     #[stable(feature = "op_assign_traits", since = "1.8.0")]
-    fn shr_assign(&mut self, Rhs);
+    fn shr_assign(&mut self, rhs: Rhs);
 }
 
 macro_rules! shr_assign_impl {
index 1a482b75731c102fc36b1e92d772822f2e8a07fd..3e0b84255735382e34795423d04f952a741b2d4c 100644 (file)
@@ -2290,9 +2290,10 @@ impl<A> SlicePartialOrd<A> for [A]
     }
 }
 
-impl SlicePartialOrd<u8> for [u8] {
-    #[inline]
-    fn partial_compare(&self, other: &[u8]) -> Option<Ordering> {
+impl<A> SlicePartialOrd<A> for [A]
+    where A: Ord
+{
+    default fn partial_compare(&self, other: &[A]) -> Option<Ordering> {
         Some(SliceOrd::compare(self, other))
     }
 }
index 7dced2ba7514c2ac492167f882adcede4e7970bb..8493afe98bc5742b285c99bcd029af2b430ad42e 100644 (file)
@@ -240,7 +240,7 @@ pub trait DoubleEndedSearcher<'a>: ReverseSearcher<'a> {}
 
 #[doc(hidden)]
 trait CharEq {
-    fn matches(&mut self, char) -> bool;
+    fn matches(&mut self, c: char) -> bool;
     fn only_ascii(&self) -> bool;
 }
 
@@ -1178,8 +1178,8 @@ fn reverse_maximal_suffix(arr: &[u8], known_period: usize,
 trait TwoWayStrategy {
     type Output;
     fn use_early_reject() -> bool;
-    fn rejecting(usize, usize) -> Self::Output;
-    fn matching(usize, usize) -> Self::Output;
+    fn rejecting(a: usize, b: usize) -> Self::Output;
+    fn matching(a: usize, b: usize) -> Self::Output;
 }
 
 /// Skip to match intervals as quickly as possible
index 18a3f1a218d854e00d9e2f4204152234b08ba18f..24ca476e5ff7994a36311f123cec3cace45b164a 100644 (file)
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use util::nodemap::FxHashSet;
+use util::nodemap::{FxHashMap, FxHashSet};
 use ty::context::TyCtxt;
 use ty::{AdtDef, VariantDef, FieldDef, TyS};
 use ty::{DefId, Substs};
@@ -66,19 +66,13 @@ impl<'a, 'gcx, 'tcx> AdtDef {
     /// Calculate the forest of DefIds from which this adt is visibly uninhabited.
     pub fn uninhabited_from(
                 &self,
-                visited: &mut FxHashSet<(DefId, &'tcx Substs<'tcx>)>,
+                visited: &mut FxHashMap<DefId, FxHashSet<&'tcx Substs<'tcx>>>,
                 tcx: TyCtxt<'a, 'gcx, 'tcx>,
                 substs: &'tcx Substs<'tcx>) -> DefIdForest
     {
-        if !visited.insert((self.did, substs)) {
-            return DefIdForest::empty();
-        }
-
-        let ret = DefIdForest::intersection(tcx, self.variants.iter().map(|v| {
+        DefIdForest::intersection(tcx, self.variants.iter().map(|v| {
             v.uninhabited_from(visited, tcx, substs, self.adt_kind())
-        }));
-        visited.remove(&(self.did, substs));
-        ret
+        }))
     }
 }
 
@@ -86,7 +80,7 @@ impl<'a, 'gcx, 'tcx> VariantDef {
     /// Calculate the forest of DefIds from which this variant is visibly uninhabited.
     pub fn uninhabited_from(
                 &self,
-                visited: &mut FxHashSet<(DefId, &'tcx Substs<'tcx>)>,
+                visited: &mut FxHashMap<DefId, FxHashSet<&'tcx Substs<'tcx>>>,
                 tcx: TyCtxt<'a, 'gcx, 'tcx>,
                 substs: &'tcx Substs<'tcx>,
                 adt_kind: AdtKind) -> DefIdForest
@@ -115,12 +109,14 @@ impl<'a, 'gcx, 'tcx> FieldDef {
     /// Calculate the forest of DefIds from which this field is visibly uninhabited.
     pub fn uninhabited_from(
                 &self,
-                visited: &mut FxHashSet<(DefId, &'tcx Substs<'tcx>)>,
+                visited: &mut FxHashMap<DefId, FxHashSet<&'tcx Substs<'tcx>>>,
                 tcx: TyCtxt<'a, 'gcx, 'tcx>,
                 substs: &'tcx Substs<'tcx>,
                 is_enum: bool) -> DefIdForest
     {
-        let mut data_uninhabitedness = move || self.ty(tcx, substs).uninhabited_from(visited, tcx);
+        let mut data_uninhabitedness = move || {
+            self.ty(tcx, substs).uninhabited_from(visited, tcx)
+        };
         // FIXME(canndrew): Currently enum fields are (incorrectly) stored with
         // Visibility::Invisible so we need to override self.vis if we're
         // dealing with an enum.
@@ -144,7 +140,7 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> {
     /// Calculate the forest of DefIds from which this type is visibly uninhabited.
     pub fn uninhabited_from(
                 &self,
-                visited: &mut FxHashSet<(DefId, &'tcx Substs<'tcx>)>,
+                visited: &mut FxHashMap<DefId, FxHashSet<&'tcx Substs<'tcx>>>,
                 tcx: TyCtxt<'a, 'gcx, 'tcx>) -> DefIdForest
     {
         match tcx.lift_to_global(&self) {
@@ -169,12 +165,37 @@ pub fn uninhabited_from(
 
     fn uninhabited_from_inner(
                 &self,
-                visited: &mut FxHashSet<(DefId, &'tcx Substs<'tcx>)>,
+                visited: &mut FxHashMap<DefId, FxHashSet<&'tcx Substs<'tcx>>>,
                 tcx: TyCtxt<'a, 'gcx, 'tcx>) -> DefIdForest
     {
         match self.sty {
             TyAdt(def, substs) => {
-                def.uninhabited_from(visited, tcx, substs)
+                {
+                    let mut substs_set = visited.entry(def.did).or_insert(FxHashSet::default());
+                    if !substs_set.insert(substs) {
+                        // We are already calculating the inhabitedness of this type.
+                        // The type must contain a reference to itself. Break the
+                        // infinite loop.
+                        return DefIdForest::empty();
+                    }
+                    if substs_set.len() >= tcx.sess.recursion_limit.get() / 4 {
+                        // We have gone very deep, reinstantiating this ADT inside
+                        // itself with different type arguments. We are probably
+                        // hitting an infinite loop. For example, it's possible to write:
+                        //                a type Foo<T>
+                        //      which contains a Foo<(T, T)>
+                        //      which contains a Foo<((T, T), (T, T))>
+                        //      which contains a Foo<(((T, T), (T, T)), ((T, T), (T, T)))>
+                        //      etc.
+                        let error = format!("reached recursion limit while checking
+                                             inhabitedness of `{}`", self);
+                        tcx.sess.fatal(&error);
+                    }
+                }
+                let ret = def.uninhabited_from(visited, tcx, substs);
+                let mut substs_set = visited.get_mut(&def.did).unwrap();
+                substs_set.remove(substs);
+                ret
             },
 
             TyNever => DefIdForest::full(tcx),
index 4ce1d7a9013621cce9c4deb186da33c39eaa1021..862bc15c0526001775f1088c92cb540be4ed225a 100644 (file)
@@ -24,7 +24,7 @@
 use syntax::abi;
 use syntax::ast::{self, Name};
 use syntax::symbol::{keywords, InternedString};
-use util::nodemap::FxHashSet;
+use util::nodemap::FxHashMap;
 
 use serialize;
 
@@ -1018,7 +1018,7 @@ pub fn is_defaulted_unit(&self) -> bool {
     /// This code should only compile in modules where the uninhabitedness of Foo is
     /// visible.
     pub fn is_uninhabited_from(&self, module: DefId, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> bool {
-        let mut visited = FxHashSet::default();
+        let mut visited = FxHashMap::default();
         let forest = self.uninhabited_from(&mut visited, tcx);
 
         // To check whether this type is uninhabited at all (not just from the
index 7a64ff7114a7eaba36871218c566db2e58c54c2e..78c4027aa4319297a1ab45100580d6e863b70c57 100644 (file)
@@ -17,7 +17,7 @@
 
 use rustc_const_math::ConstInt;
 
-use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::indexed_vec::Idx;
 
 use pattern::{FieldPattern, Pattern, PatternKind};
@@ -404,7 +404,7 @@ fn all_constructors<'a, 'tcx: 'a>(cx: &mut MatchCheckCtxt<'a, 'tcx>,
         }
         ty::TyAdt(def, substs) if def.is_enum() && def.variants.len() != 1 => {
             def.variants.iter().filter_map(|v| {
-                let mut visited = FxHashSet::default();
+                let mut visited = FxHashMap::default();
                 let forest = v.uninhabited_from(&mut visited,
                                                 cx.tcx, substs,
                                                 AdtKind::Enum);
index 33d71ba86264388ed9e329b41620448d1aa06a8a..26417e3ba7cd1ef825662510bf3638cba933093c 100644 (file)
@@ -27,7 +27,7 @@ mod imp {
     use std::io;
     use libc;
 
-    #[cfg(target_os = "linux")]
+    #[cfg(any(target_os = "linux", target_os = "android"))]
     mod os {
         use libc;
 
index 33bf4d5276adf23e7f9aa8b0d3204bc8483660a0..4fe3730bbe24985c88a6e0dd61d51a634750e0e2 100644 (file)
@@ -1000,6 +1000,7 @@ macro_rules! try_with_f {
 }
 
 /// Run the translation phase to LLVM, after which the AST and analysis can
+/// be discarded.
 pub fn phase_4_translate_to_llvm<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                            analysis: ty::CrateAnalysis,
                                            incremental_hashes_map: &IncrementalHashesMap)
index 949e949f673a2b39dd084162d20d8c4606bb3d56..8a958cf1ac105b6493d19fc56ecb7741960189f0 100644 (file)
@@ -468,6 +468,7 @@ pub enum DIBuilder_opaque {}
             const FlagStaticMember        = (1 << 12),
             const FlagLValueReference     = (1 << 13),
             const FlagRValueReference     = (1 << 14),
+            const FlagMainSubprogram      = (1 << 21),
         }
     }
 }
@@ -1333,8 +1334,7 @@ pub fn LLVMRustInlineAsm(Ty: TypeRef,
 
     pub fn LLVMRustDIBuilderCreateCompileUnit(Builder: DIBuilderRef,
                                               Lang: c_uint,
-                                              File: *const c_char,
-                                              Dir: *const c_char,
+                                              File: DIFile,
                                               Producer: *const c_char,
                                               isOptimized: bool,
                                               Flags: *const c_char,
index 5b52b268849d3d6c2c080806531c62cdf6ed5d8b..db9fc870fa86a6a19f51071f255d51fde492e3f7 100644 (file)
@@ -96,9 +96,17 @@ pub fn iter_enumerated<'a>(&self,
 }
 
 #[repr(packed)]
-#[derive(Copy, Clone)]
+#[derive(Copy)]
 struct Unaligned<T>(T);
 
+// The derived Clone impl is unsafe for this packed struct since it needs to pass a reference to
+// the field to `T::clone`, but this reference may not be properly aligned.
+impl<T: Copy> Clone for Unaligned<T> {
+    fn clone(&self) -> Self {
+        *self
+    }
+}
+
 impl<T> Unaligned<T> {
     fn get(self) -> T { self.0 }
 }
index e94d35195c21336cc162a8f777ca2e7a303eecb5..efddee2c933f40baf3bb7d80c1d19f4293232ebc 100644 (file)
@@ -26,7 +26,7 @@
 use build::matches::{Binding, MatchPair, Candidate};
 use hair::*;
 use rustc::mir::*;
-use rustc_data_structures::fx::FxHashSet;
+use rustc_data_structures::fx::FxHashMap;
 
 use std::mem;
 
@@ -102,7 +102,7 @@ fn simplify_match_pair<'pat>(&mut self,
                 if self.hir.tcx().sess.features.borrow().never_type {
                     let irrefutable = adt_def.variants.iter().enumerate().all(|(i, v)| {
                         i == variant_index || {
-                            let mut visited = FxHashSet::default();
+                            let mut visited = FxHashMap::default();
                             let node_set = v.uninhabited_from(&mut visited,
                                                               self.hir.tcx(),
                                                               substs,
index fa48a63b6b8f5865350fd879a18523de28c22fc4..b5c67ad998b69e4ea448eebe5cca0e99078b42f8 100644 (file)
@@ -22,5 +22,6 @@ rustc_errors = { path = "../librustc_errors" }
 rustc_incremental = { path = "../librustc_incremental" }
 rustc_llvm = { path = "../librustc_llvm" }
 rustc_platform_intrinsics = { path = "../librustc_platform_intrinsics" }
+serialize = { path = "../libserialize" }
 syntax = { path = "../libsyntax" }
 syntax_pos = { path = "../libsyntax_pos" }
index 1cbfa26b705ac8190d6ba15e49477116d767c337..1da9fcb0e95e437cd4dd614b149ebae102a790b9 100644 (file)
 use syntax::symbol::Symbol;
 use syntax_pos::Span;
 
+/// The LLVM module name containing crate-metadata. This includes a `.` on
+/// purpose, so it cannot clash with the name of a user-defined module.
+pub const METADATA_MODULE_NAME: &'static str = "crate.metadata";
+/// The name of the crate-metadata object file the compiler generates. Must
+/// match up with `METADATA_MODULE_NAME`.
+pub const METADATA_OBJ_NAME: &'static str = "crate.metadata.o";
+
 // RLIB LLVM-BYTECODE OBJECT LAYOUT
 // Version 1
 // Bytes    Data
@@ -213,7 +220,7 @@ pub fn link_binary(sess: &Session,
                 remove(sess, &obj);
             }
         }
-        remove(sess, &outputs.with_extension("metadata.o"));
+        remove(sess, &outputs.with_extension(METADATA_OBJ_NAME));
     }
 
     out_filenames
@@ -715,9 +722,13 @@ fn link_natively(sess: &Session,
         cmd.arg(root.join(obj));
     }
 
-    if sess.target.target.options.is_like_emscripten &&
-       sess.panic_strategy() == PanicStrategy::Abort {
-        cmd.args(&["-s", "DISABLE_EXCEPTION_CATCHING=1"]);
+    if sess.target.target.options.is_like_emscripten {
+        cmd.arg("-s");
+        cmd.arg(if sess.panic_strategy() == PanicStrategy::Abort {
+            "DISABLE_EXCEPTION_CATCHING=1"
+        } else {
+            "DISABLE_EXCEPTION_CATCHING=0"
+        });
     }
 
     {
@@ -823,7 +834,8 @@ fn link_args(cmd: &mut Linker,
 
     // If we're building a dynamic library then some platforms need to make sure
     // that all symbols are exported correctly from the dynamic library.
-    if crate_type != config::CrateTypeExecutable {
+    if crate_type != config::CrateTypeExecutable ||
+       sess.target.target.options.is_like_emscripten {
         cmd.export_symbols(tmpdir, crate_type);
     }
 
@@ -832,7 +844,7 @@ fn link_args(cmd: &mut Linker,
     // object file, so we link that in here.
     if crate_type == config::CrateTypeDylib ||
        crate_type == config::CrateTypeProcMacro {
-        cmd.add_object(&outputs.with_extension("metadata.o"));
+        cmd.add_object(&outputs.with_extension(METADATA_OBJ_NAME));
     }
 
     // Try to strip as much out of the generated object by removing unused
index 7f352f1da517d215215c740b0d82286a05f0724d..830d1d0d3a5586fddba895d70551857381dd17eb 100644 (file)
@@ -23,8 +23,8 @@
 use middle::dependency_format::Linkage;
 use rustc::hir::def_id::{LOCAL_CRATE, CrateNum};
 use session::Session;
-use session::config::CrateType;
-use session::config;
+use session::config::{self, CrateType, OptLevel, DebugInfoLevel};
+use serialize::{json, Encoder};
 
 /// For all the linkers we support, and information they might
 /// need out of the shared crate context before we get rid of it.
@@ -51,6 +51,12 @@ pub fn to_linker(&'a self,
                 sess: sess,
                 info: self
             }) as Box<Linker>
+        } else if sess.target.target.options.is_like_emscripten {
+            Box::new(EmLinker {
+                cmd: cmd,
+                sess: sess,
+                info: self
+            }) as Box<Linker>
         } else {
             Box::new(GnuLinker {
                 cmd: cmd,
@@ -488,6 +494,154 @@ fn subsystem(&mut self, subsystem: &str) {
     }
 }
 
+pub struct EmLinker<'a> {
+    cmd: &'a mut Command,
+    sess: &'a Session,
+    info: &'a LinkerInfo
+}
+
+impl<'a> Linker for EmLinker<'a> {
+    fn include_path(&mut self, path: &Path) {
+        self.cmd.arg("-L").arg(path);
+    }
+
+    fn link_staticlib(&mut self, lib: &str) {
+        self.cmd.arg("-l").arg(lib);
+    }
+
+    fn output_filename(&mut self, path: &Path) {
+        self.cmd.arg("-o").arg(path);
+    }
+
+    fn add_object(&mut self, path: &Path) {
+        self.cmd.arg(path);
+    }
+
+    fn link_dylib(&mut self, lib: &str) {
+        // Emscripten always links statically
+        self.link_staticlib(lib);
+    }
+
+    fn link_whole_staticlib(&mut self, lib: &str, _search_path: &[PathBuf]) {
+        // not supported?
+        self.link_staticlib(lib);
+    }
+
+    fn link_whole_rlib(&mut self, lib: &Path) {
+        // not supported?
+        self.link_rlib(lib);
+    }
+
+    fn link_rust_dylib(&mut self, lib: &str, _path: &Path) {
+        self.link_dylib(lib);
+    }
+
+    fn link_rlib(&mut self, lib: &Path) {
+        self.add_object(lib);
+    }
+
+    fn position_independent_executable(&mut self) {
+        // noop
+    }
+
+    fn args(&mut self, args: &[String]) {
+        self.cmd.args(args);
+    }
+
+    fn framework_path(&mut self, _path: &Path) {
+        bug!("frameworks are not supported on Emscripten")
+    }
+
+    fn link_framework(&mut self, _framework: &str) {
+        bug!("frameworks are not supported on Emscripten")
+    }
+
+    fn gc_sections(&mut self, _keep_metadata: bool) {
+        // noop
+    }
+
+    fn optimize(&mut self) {
+        // Emscripten performs own optimizations
+        self.cmd.arg(match self.sess.opts.optimize {
+            OptLevel::No => "-O0",
+            OptLevel::Less => "-O1",
+            OptLevel::Default => "-O2",
+            OptLevel::Aggressive => "-O3",
+            OptLevel::Size => "-Os",
+            OptLevel::SizeMin => "-Oz"
+        });
+        // Unusable until https://github.com/rust-lang/rust/issues/38454 is resolved
+        self.cmd.args(&["--memory-init-file", "0"]);
+    }
+
+    fn debuginfo(&mut self) {
+        // Preserve names or generate source maps depending on debug info
+        self.cmd.arg(match self.sess.opts.debuginfo {
+            DebugInfoLevel::NoDebugInfo => "-g0",
+            DebugInfoLevel::LimitedDebugInfo => "-g3",
+            DebugInfoLevel::FullDebugInfo => "-g4"
+        });
+    }
+
+    fn no_default_libraries(&mut self) {
+        self.cmd.args(&["-s", "DEFAULT_LIBRARY_FUNCS_TO_INCLUDE=[]"]);
+    }
+
+    fn build_dylib(&mut self, _out_filename: &Path) {
+        bug!("building dynamic library is unsupported on Emscripten")
+    }
+
+    fn whole_archives(&mut self) {
+        // noop
+    }
+
+    fn no_whole_archives(&mut self) {
+        // noop
+    }
+
+    fn hint_static(&mut self) {
+        // noop
+    }
+
+    fn hint_dynamic(&mut self) {
+        // noop
+    }
+
+    fn export_symbols(&mut self, _tmpdir: &Path, crate_type: CrateType) {
+        let symbols = &self.info.exports[&crate_type];
+
+        debug!("EXPORTED SYMBOLS:");
+
+        self.cmd.arg("-s");
+
+        let mut arg = OsString::from("EXPORTED_FUNCTIONS=");
+        let mut encoded = String::new();
+
+        {
+            let mut encoder = json::Encoder::new(&mut encoded);
+            let res = encoder.emit_seq(symbols.len(), |encoder| {
+                for (i, sym) in symbols.iter().enumerate() {
+                    encoder.emit_seq_elt(i, |encoder| {
+                        encoder.emit_str(&("_".to_string() + sym))
+                    })?;
+                }
+                Ok(())
+            });
+            if let Err(e) = res {
+                self.sess.fatal(&format!("failed to encode exported symbols: {}", e));
+            }
+        }
+        debug!("{}", encoded);
+        arg.push(encoded);
+
+        self.cmd.arg(arg);
+    }
+
+    fn subsystem(&mut self, _subsystem: &str) {
+        // noop
+    }
+}
+
 fn exported_symbols(scx: &SharedCrateContext,
                     exported_symbols: &ExportedSymbols,
                     crate_type: CrateType)
index 5c4a5a9a4423d3abdf4bd9a96b90cb1884d5417f..b717254ef0d25aa6c35ccd27ff90aab06d2b928a 100644 (file)
@@ -886,12 +886,12 @@ pub fn run_passes(sess: &Session,
     // Clean up unwanted temporary files.
 
     // We create the following files by default:
-    //  - crate.#module-name#.bc
-    //  - crate.#module-name#.o
-    //  - crate.metadata.bc
-    //  - crate.metadata.o
-    //  - crate.o (linked from crate.##.o)
-    //  - crate.bc (copied from crate.##.bc)
+    //  - #crate#.#module-name#.bc
+    //  - #crate#.#module-name#.o
+    //  - #crate#.crate.metadata.bc
+    //  - #crate#.crate.metadata.o
+    //  - #crate#.o (linked from crate.##.o)
+    //  - #crate#.bc (copied from crate.##.bc)
     // We may create additional files if requested by the user (through
     // `-C save-temps` or `--emit=` flags).
 
@@ -939,9 +939,9 @@ pub fn run_passes(sess: &Session,
     }
 
     // We leave the following files around by default:
-    //  - crate.o
-    //  - crate.metadata.o
-    //  - crate.bc
+    //  - #crate#.o
+    //  - #crate#.crate.metadata.o
+    //  - #crate#.bc
     // These are used in linking steps and will be cleaned up afterward.
 
     // FIXME: time_llvm_passes support - does this use a global context or
index 5312cc60b09167b82e3dbc607b9e3043816756bb..ce02c9725d1043bb53b810bbc4a0ac8a9656e698 100644 (file)
@@ -1151,7 +1151,7 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
     });
 
     let metadata_module = ModuleTranslation {
-        name: "metadata".to_string(),
+        name: link::METADATA_MODULE_NAME.to_string(),
         symbol_name_hash: 0, // we always rebuild metadata, at least for now
         source: ModuleSource::Translated(ModuleLlvm {
             llcx: shared_ccx.metadata_llcx(),
index 7578cc74dbf34bf990436ef8a412daaf56c8e99f..c453d9bbd051f5e4c4c1beee7d7c5f2da51b136e 100644 (file)
@@ -791,12 +791,15 @@ pub fn compile_unit_metadata(scc: &SharedCrateContext,
     let producer = CString::new(producer).unwrap();
     let flags = "\0";
     let split_name = "\0";
-    return unsafe {
-        llvm::LLVMRustDIBuilderCreateCompileUnit(
+
+    unsafe {
+        let file_metadata = llvm::LLVMRustDIBuilderCreateFile(
+            debug_context.builder, compile_unit_name, work_dir.as_ptr());
+
+        return llvm::LLVMRustDIBuilderCreateCompileUnit(
             debug_context.builder,
             DW_LANG_RUST,
-            compile_unit_name,
-            work_dir.as_ptr(),
+            file_metadata,
             producer.as_ptr(),
             sess.opts.optimize != config::OptLevel::No,
             flags.as_ptr() as *const _,
index 729eae15ad696ae85693f1f7c43d47d3cffa7064..e9b592ec8fd79814ef6f5061b6aa08d3771749f8 100644 (file)
@@ -257,6 +257,16 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
     let function_name = CString::new(name).unwrap();
     let linkage_name = CString::new(linkage_name).unwrap();
 
+    let mut flags = DIFlags::FlagPrototyped;
+    match *cx.sess().entry_fn.borrow() {
+        Some((id, _)) => {
+            if local_id == Some(id) {
+                flags = flags | DIFlags::FlagMainSubprogram;
+            }
+        }
+        None => {}
+    };
+
     let fn_metadata = unsafe {
         llvm::LLVMRustDIBuilderCreateFunction(
             DIB(cx),
@@ -269,7 +279,7 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
             is_local_to_unit,
             true,
             scope_line as c_uint,
-            DIFlags::FlagPrototyped,
+            flags,
             cx.sess().opts.optimize != config::OptLevel::No,
             llfn,
             template_parameters,
index 21c92cb4a4ad2329b5f06f558012a9db69fa1a05..1530fcda3d3ea19c5415d17983fd47220de6928a 100644 (file)
@@ -59,6 +59,7 @@
 #[macro_use] extern crate syntax;
 extern crate syntax_pos;
 extern crate rustc_errors as errors;
+extern crate serialize;
 
 pub use rustc::session;
 pub use rustc::middle;
index e017c8f2532e4a98591f8d74c6248a0461e6361f..0cfc2c8d16352b16b48f31228778c4604165eb05 100644 (file)
@@ -138,13 +138,20 @@ pub fn debug_loc(&mut self, source_info: mir::SourceInfo) -> (DIScope, Span) {
             while span.expn_id != NO_EXPANSION && span.expn_id != COMMAND_LINE_EXPN {
                 if let Some(callsite_span) = cm.with_expn_info(span.expn_id,
                                                     |ei| ei.map(|ei| ei.call_site.clone())) {
+                    // When the current function itself is a result of macro expansion,
+                    // we stop at the function body level because no line stepping can occurr
+                    // at the level above that.
+                    if self.mir.span.expn_id != NO_EXPANSION &&
+                       span.expn_id == self.mir.span.expn_id {
+                        break;
+                    }
                     span = callsite_span;
                 } else {
                     break;
                 }
             }
             let scope = self.scope_metadata_for_loc(source_info.scope, span.lo);
-            // Use span of the outermost call site, while keeping the original lexical scope
+            // Use span of the outermost expansion site, while keeping the original lexical scope.
             (scope, span)
         }
     }
index 0dcdab07e6fc8a259727e571ae5f37f87a30f11c..f492ab12e3f991f5fac03104fd9195800c295b20 100644 (file)
@@ -212,11 +212,10 @@ fn check_overloaded_binop(&self,
                                 self.lookup_op_method(expr, ty_mut.ty, vec![rhs_ty_var],
                                     Symbol::intern(name), trait_def_id,
                                     lhs_expr).is_ok() {
-                                err.span_note(
-                                    lhs_expr.span,
+                                err.note(
                                     &format!(
-                                        "this is a reference of type that `{}` can be applied to, \
-                                        you need to dereference this variable once for this \
+                                        "this is a reference to a type that `{}` can be applied \
+                                        to; you need to dereference this variable once for this \
                                         operation to work",
                                     op.node.as_str()));
                             }
@@ -244,11 +243,11 @@ fn check_overloaded_binop(&self,
                                                          rhs_expr, rhs_ty_var, &mut err) {
                                 // This has nothing here because it means we did string
                                 // concatenation (e.g. "Hello " + "World!"). This means
-                                // we don't want the span in the else clause to be emmitted
+                                // we don't want the note in the else clause to be emitted
                             } else {
-                                span_note!(&mut err, lhs_expr.span,
-                                            "an implementation of `{}` might be missing for `{}`",
-                                            missing_trait, lhs_ty);
+                                err.note(
+                                    &format!("an implementation of `{}` might be missing for `{}`",
+                                             missing_trait, lhs_ty));
                             }
                         }
                         err.emit();
@@ -271,16 +270,14 @@ fn check_str_addition(&self,
                           rhs_expr: &'gcx hir::Expr,
                           rhs_ty_var: Ty<'tcx>,
                           mut err: &mut errors::DiagnosticBuilder) -> bool {
-        // If this function returns false it means we use it to make sure we print
-        // out the an "implementation of span_note!" above where this function is
-        // called and if true we don't.
+        // If this function returns true it means a note was printed, so we don't need
+        // to print the normal "implementation of `std::ops::Add` might be missing" note
         let mut is_string_addition = false;
         let rhs_ty = self.check_expr_coercable_to_type(rhs_expr, rhs_ty_var);
         if let TyRef(_, l_ty) = lhs_ty.sty {
             if let TyRef(_, r_ty) = rhs_ty.sty {
                 if l_ty.ty.sty == TyStr && r_ty.ty.sty == TyStr {
-                    span_note!(&mut err, lhs_expr.span,
-                            "`+` can't be used to concatenate two `&str` strings");
+                    err.note("`+` can't be used to concatenate two `&str` strings");
                     let codemap = self.tcx.sess.codemap();
                     let suggestion =
                         match (codemap.span_to_snippet(lhs_expr.span),
index 29b0c00d11b42e52f6221ae6546d7ea6bf5ed619..75fe8cabe12cc991ac9de0f2142b54c46bc52aa5 100644 (file)
@@ -1937,7 +1937,9 @@ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
 
 fn item_constant(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
                  c: &clean::Constant) -> fmt::Result {
-    write!(w, "<pre class='rust const'>{vis}const \
+    write!(w, "<pre class='rust const'>")?;
+    render_attributes(w, it)?;
+    write!(w, "{vis}const \
                {name}: {typ}{init}</pre>",
            vis = VisSpace(&it.visibility),
            name = it.name.as_ref().unwrap(),
@@ -1948,7 +1950,9 @@ fn item_constant(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
 
 fn item_static(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
                s: &clean::Static) -> fmt::Result {
-    write!(w, "<pre class='rust static'>{vis}static {mutability}\
+    write!(w, "<pre class='rust static'>")?;
+    render_attributes(w, it)?;
+    write!(w, "{vis}static {mutability}\
                {name}: {typ}{init}</pre>",
            vis = VisSpace(&it.visibility),
            mutability = MutableSpace(s.mutability),
@@ -1972,7 +1976,9 @@ fn item_function(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
                          AbiSpace(f.abi),
                          it.name.as_ref().unwrap(),
                          f.generics).len();
-    write!(w, "<pre class='rust fn'>{vis}{constness}{unsafety}{abi}fn \
+    write!(w, "<pre class='rust fn'>")?;
+    render_attributes(w, it)?;
+    write!(w, "{vis}{constness}{unsafety}{abi}fn \
                {name}{generics}{decl}{where_clause}</pre>",
            vis = VisSpace(&it.visibility),
            constness = ConstnessSpace(vis_constness),
@@ -2007,7 +2013,9 @@ fn item_trait(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
     }
 
     // Output the trait definition
-    write!(w, "<pre class='rust trait'>{}{}trait {}{}{}{} ",
+    write!(w, "<pre class='rust trait'>")?;
+    render_attributes(w, it)?;
+    write!(w, "{}{}trait {}{}{}{} ",
            VisSpace(&it.visibility),
            UnsafetySpace(t.unsafety),
            it.name.as_ref().unwrap(),
@@ -3002,7 +3010,9 @@ fn render_default_items(w: &mut fmt::Formatter,
 fn item_typedef(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
                 t: &clean::Typedef) -> fmt::Result {
     let indent = format!("type {}{:#} ", it.name.as_ref().unwrap(), t.generics).len();
-    write!(w, "<pre class='rust typedef'>type {}{}{where_clause} = {type_};</pre>",
+    write!(w, "<pre class='rust typedef'>")?;
+    render_attributes(w, it)?;
+    write!(w, "type {}{}{where_clause} = {type_};</pre>",
            it.name.as_ref().unwrap(),
            t.generics,
            where_clause = WhereClause(&t.generics, indent),
index a3f7e13bbf9131615f369a5ee328947e1cdfc8b2..d438aa8b3ac9cf53b2c9278f839eaa14d221296c 100644 (file)
@@ -291,7 +291,8 @@ pub fn iter(&self) -> Iter<T> {
         Iter { iter: self.map.keys() }
     }
 
-    /// Visit the values representing the difference.
+    /// Visit the values representing the difference,
+    /// i.e. the values that are in `self` but not in `other`.
     ///
     /// # Examples
     ///
@@ -321,7 +322,8 @@ pub fn difference<'a>(&'a self, other: &'a HashSet<T, S>) -> Difference<'a, T, S
         }
     }
 
-    /// Visit the values representing the symmetric difference.
+    /// Visit the values representing the symmetric difference,
+    /// i.e. the values that are in `self` or in `other` but not in both.
     ///
     /// # Examples
     ///
@@ -348,7 +350,8 @@ pub fn symmetric_difference<'a>(&'a self,
         SymmetricDifference { iter: self.difference(other).chain(other.difference(self)) }
     }
 
-    /// Visit the values representing the intersection.
+    /// Visit the values representing the intersection,
+    /// i.e. the values that are both in `self` and `other`.
     ///
     /// # Examples
     ///
@@ -373,7 +376,8 @@ pub fn intersection<'a>(&'a self, other: &'a HashSet<T, S>) -> Intersection<'a,
         }
     }
 
-    /// Visit the values representing the union.
+    /// Visit the values representing the union,
+    /// i.e. all the values in `self` or `other`, without duplicates.
     ///
     /// # Examples
     ///
@@ -489,7 +493,7 @@ pub fn get<Q: ?Sized>(&self, value: &Q) -> Option<&T>
         Recover::get(&self.map, value)
     }
 
-    /// Returns `true` if the set has no elements in common with `other`.
+    /// Returns `true` if `self` has no elements in common with `other`.
     /// This is equivalent to checking for an empty intersection.
     ///
     /// # Examples
@@ -511,7 +515,8 @@ pub fn is_disjoint(&self, other: &HashSet<T, S>) -> bool {
         self.iter().all(|v| !other.contains(v))
     }
 
-    /// Returns `true` if the set is a subset of another.
+    /// Returns `true` if the set is a subset of another,
+    /// i.e. `other` contains at least all the values in `self`.
     ///
     /// # Examples
     ///
@@ -532,7 +537,8 @@ pub fn is_subset(&self, other: &HashSet<T, S>) -> bool {
         self.iter().all(|v| other.contains(v))
     }
 
-    /// Returns `true` if the set is a superset of another.
+    /// Returns `true` if the set is a superset of another,
+    /// i.e. `self` contains at least all the values in `other`.
     ///
     /// # Examples
     ///
index b9e92a01b2f8e72a72102d3ec756bd3731a9110b..8884d0688b8b7661ff406680edd53ce14dab3d22 100644 (file)
@@ -68,7 +68,7 @@
 //! * You want to find the largest or smallest key that is smaller or larger
 //!   than something.
 //! * You want to be able to get all of the entries in order on-demand.
-//! * You want a sorted map.
+//! * You want a map sorted by its keys.
 //!
 //! ### Use the `Set` variant of any of these `Map`s when:
 //! * You just want to remember which keys you've seen.
index 3a552c060a9b9066d0031e1007213b15561184e4..070690773b6c4792a05dc525ce790c9d1cdc72ce 100644 (file)
 #![feature(unboxed_closures)]
 #![feature(unicode)]
 #![feature(unique)]
+#![feature(untagged_unions)]
 #![feature(unwind_attributes)]
 #![feature(vec_push_all)]
 #![feature(zero_one)]
index d76e8816ca45f3932b37baf92a35fcdf8fca5028..3fba49345e63d1e5ee34cf8f63cc483f44492353 100644 (file)
@@ -389,28 +389,23 @@ pub fn update_panic_count(amt: isize) -> usize {
 
 /// Invoke a closure, capturing the cause of an unwinding panic if one occurs.
 pub unsafe fn try<R, F: FnOnce() -> R>(f: F) -> Result<R, Box<Any + Send>> {
-    struct Data<F, R> {
+    #[allow(unions_with_drop_fields)]
+    union Data<F, R> {
         f: F,
         r: R,
     }
 
     // We do some sketchy operations with ownership here for the sake of
-    // performance. The `Data` structure is never actually fully valid, but
-    // instead it always contains at least one uninitialized field. We can only
-    // pass pointers down to `__rust_maybe_catch_panic` (can't pass objects by
-    // value), so we do all the ownership tracking here manully.
+    // performance. We can only  pass pointers down to
+    // `__rust_maybe_catch_panic` (can't pass objects by value), so we do all
+    // the ownership tracking here manually using a union.
     //
-    // Note that this is all invalid if any of these functions unwind, but the
-    // whole point of this function is to prevent that! As a result we go
-    // through a transition where:
+    // We go through a transition where:
     //
-    // * First, only the closure we're going to call is initialized. The return
-    //   value is uninitialized.
+    // * First, we set the data to be the closure that we're going to call.
     // * When we make the function call, the `do_call` function below, we take
-    //   ownership of the function pointer, replacing it with uninitialized
-    //   data. At this point the `Data` structure is entirely uninitialized, but
-    //   it won't drop due to an unwind because it's owned on the other side of
-    //   the catch panic.
+    //   ownership of the function pointer. At this point the `Data` union is
+    //   entirely uninitialized.
     // * If the closure successfully returns, we write the return value into the
     //   data's return slot. Note that `ptr::write` is used as it's overwriting
     //   uninitialized data.
@@ -418,11 +413,10 @@ struct Data<F, R> {
     //   in one of two states:
     //
     //      1. The closure didn't panic, in which case the return value was
-    //         filled in. We have to be careful to `forget` the closure,
-    //         however, as ownership was passed to the `do_call` function.
+    //         filled in. We move it out of `data` and return it.
     //      2. The closure panicked, in which case the return value wasn't
-    //         filled in. In this case the entire `data` structure is invalid,
-    //         so we forget the entire thing.
+    //         filled in. In this case the entire `data` union is invalid, so
+    //         there is no need to drop anything.
     //
     // Once we stack all that together we should have the "most efficient'
     // method of calling a catch panic whilst juggling ownership.
@@ -430,7 +424,6 @@ struct Data<F, R> {
     let mut any_vtable = 0;
     let mut data = Data {
         f: f,
-        r: mem::uninitialized(),
     };
 
     let r = __rust_maybe_catch_panic(do_call::<F, R>,
@@ -439,12 +432,9 @@ struct Data<F, R> {
                                      &mut any_vtable);
 
     return if r == 0 {
-        let Data { f, r } = data;
-        mem::forget(f);
         debug_assert!(update_panic_count(0) == 0);
-        Ok(r)
+        Ok(data.r)
     } else {
-        mem::forget(data);
         update_panic_count(-1);
         debug_assert!(update_panic_count(0) == 0);
         Err(mem::transmute(raw::TraitObject {
index 45d8354d317dc5949959ebbdef94b67cfb157f6b..b051928ff9d3c69abad69a90b18bdb231ab01984 100644 (file)
@@ -802,6 +802,10 @@ fn parse_seq_to_before_tokens<T, F, Fe>(&mut self,
         let mut first: bool = true;
         let mut v = vec![];
         while !kets.contains(&&self.token) {
+            match self.token {
+                token::CloseDelim(..) | token::Eof => break,
+                _ => {}
+            };
             match sep.sep {
                 Some(ref t) => {
                     if first {
@@ -2608,9 +2612,12 @@ fn parse_kleene_op<'a>(parser: &mut Parser<'a>) ->
             return Ok((None, kleene_op));
         }
 
-        let separator = self.bump_and_get();
+        let separator = match self.token {
+            token::CloseDelim(..) => None,
+            _ => Some(self.bump_and_get()),
+        };
         match parse_kleene_op(self)? {
-            Some(zerok) => Ok((Some(separator), zerok)),
+            Some(zerok) => Ok((separator, zerok)),
             None => return Err(self.fatal("expected `*` or `+`"))
         }
     }
@@ -2647,7 +2654,7 @@ pub fn parse_token_tree(&mut self) -> PResult<'a, TokenTree> {
                     tts: tts,
                 })))
             },
-            token::CloseDelim(_) | token::Eof => unreachable!(),
+            token::CloseDelim(..) | token::Eof => Ok(TokenTree::Token(self.span, token::Eof)),
             token::Dollar | token::SubstNt(..) if self.quote_depth > 0 => self.parse_unquoted(),
             _ => Ok(TokenTree::Token(self.span, self.bump_and_get())),
         }
index cfbc284de4dce59f6216add8b3c174dcb6dfe655..112bf61cf97222aec886f9b20fee335e46365818 100644 (file)
@@ -445,6 +445,8 @@ pub fn parse_opts(args: &[String]) -> Option<OptRes> {
     let test_threads = match matches.opt_str("test-threads") {
         Some(n_str) =>
             match n_str.parse::<usize>() {
+                Ok(0) =>
+                    return Some(Err(format!("argument for --test-threads must not be 0"))),
                 Ok(n) => Some(n),
                 Err(e) =>
                     return Some(Err(format!("argument for --test-threads must be a number > 0 \
index f3b52b71b99c12655dfcdbc9fa86294e7af5551e..40432735911893a94ef09e3db2615fa8720b7a1d 100644 (file)
@@ -352,6 +352,7 @@ enum class LLVMRustDIFlags : uint32_t {
   FlagStaticMember = (1 << 12),
   FlagLValueReference = (1 << 13),
   FlagRValueReference = (1 << 14),
+  FlagMainSubprogram      = (1 << 21),
   // Do not add values that are not supported by the minimum LLVM
   // version we support!
 };
@@ -438,6 +439,11 @@ static unsigned fromRust(LLVMRustDIFlags Flags) {
   if (isSet(Flags & LLVMRustDIFlags::FlagRValueReference)) {
     Result |= DINode::DIFlags::FlagRValueReference;
   }
+#if LLVM_RUSTLLVM || LLVM_VERSION_GE(4, 0)
+  if (isSet(Flags & LLVMRustDIFlags::FlagMainSubprogram)) {
+    Result |= DINode::DIFlags::FlagMainSubprogram;
+  }
+#endif
 
   return Result;
 }
@@ -468,11 +474,19 @@ extern "C" void LLVMRustDIBuilderFinalize(LLVMRustDIBuilderRef Builder) {
 }
 
 extern "C" LLVMRustMetadataRef LLVMRustDIBuilderCreateCompileUnit(
-    LLVMRustDIBuilderRef Builder, unsigned Lang, const char *File,
-    const char *Dir, const char *Producer, bool isOptimized, const char *Flags,
+    LLVMRustDIBuilderRef Builder, unsigned Lang, LLVMRustMetadataRef FileRef,
+    const char *Producer, bool isOptimized, const char *Flags,
     unsigned RuntimeVer, const char *SplitName) {
-  return wrap(Builder->createCompileUnit(Lang, File, Dir, Producer, isOptimized,
+  auto *File = unwrapDI<DIFile>(FileRef);
+
+#if LLVM_VERSION_GE(4, 0)
+  return wrap(Builder->createCompileUnit(Lang, File, Producer, isOptimized,
                                          Flags, RuntimeVer, SplitName));
+#else
+  return wrap(Builder->createCompileUnit(Lang, File->getFilename(),
+      File->getDirectory(), Producer, isOptimized,
+      Flags, RuntimeVer, SplitName));
+#endif
 }
 
 extern "C" LLVMRustMetadataRef
diff --git a/src/test/codegen/mainsubprogram.rs b/src/test/codegen/mainsubprogram.rs
new file mode 100644 (file)
index 0000000..657f4b6
--- /dev/null
@@ -0,0 +1,26 @@
+// Copyright 2016 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.
+
+// The minimum LLVM version is set to 3.8, but really this test
+// depends on a patch that is was committed to upstream LLVM before
+// 4.0; and also backported to the Rust LLVM fork.
+
+// ignore-tidy-linelength
+// ignore-windows
+// ignore-macos
+// min-llvm-version 3.8
+
+// compile-flags: -g -C no-prepopulate-passes
+
+// CHECK-LABEL: @main
+// CHECK: {{.*}}DISubprogram{{.*}}name: "main",{{.*}}DIFlagMainSubprogram{{.*}}
+
+pub fn main() {
+}
diff --git a/src/test/codegen/mainsubprogramstart.rs b/src/test/codegen/mainsubprogramstart.rs
new file mode 100644 (file)
index 0000000..cd34a16
--- /dev/null
@@ -0,0 +1,30 @@
+// Copyright 2016 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.
+
+// The minimum LLVM version is set to 3.8, but really this test
+// depends on a patch that is was committed to upstream LLVM before
+// 4.0; and also backported to the Rust LLVM fork.
+
+// ignore-tidy-linelength
+// ignore-windows
+// ignore-macos
+// min-llvm-version 3.8
+
+// compile-flags: -g -C no-prepopulate-passes
+
+#![feature(start)]
+
+// CHECK-LABEL: @main
+// CHECK: {{.*}}DISubprogram{{.*}}name: "start",{{.*}}DIFlagMainSubprogram{{.*}}
+
+#[start]
+fn start(_: isize, _: *const *const u8) -> isize {
+    return 0;
+}
index a49cfaa17606dfcad53844dd0f3351440a9dd77f..23ca026f541dd0ceeef51add2857946239caba8d 100644 (file)
@@ -13,7 +13,7 @@ fn main() {
     let vr = v.iter().filter(|x| {
         x % 2 == 0
         //~^ ERROR binary operation `%` cannot be applied to type `&&{integer}`
-        //~| NOTE this is a reference of type that `%` can be applied to
+        //~| NOTE this is a reference to a type that `%` can be applied to
         //~| NOTE an implementation of `std::ops::Rem` might be missing for `&&{integer}`
     });
     println!("{:?}", vr);
diff --git a/src/test/compile-fail/feature-gate-const-indexing.rs b/src/test/compile-fail/feature-gate-const-indexing.rs
new file mode 100644 (file)
index 0000000..0d61878
--- /dev/null
@@ -0,0 +1,17 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+
+fn main() {
+    const ARR: [i32; 6] = [42, 43, 44, 45, 46, 47];
+    const IDX: usize = 3;
+    const VAL: i32 = ARR[IDX];
+    const BLUB: [i32; (ARR[0] - 41) as usize] = [5]; //~ ERROR constant evaluation error
+}
diff --git a/src/test/compile-fail/inhabitedness-infinite-loop.rs b/src/test/compile-fail/inhabitedness-infinite-loop.rs
new file mode 100644 (file)
index 0000000..91b85d7
--- /dev/null
@@ -0,0 +1,25 @@
+// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// error-pattern:reached recursion limit
+
+#![feature(never_type)]
+
+struct Foo<'a, T: 'a> {
+    ph: std::marker::PhantomData<T>,
+    foo: &'a Foo<'a, (T, T)>,
+}
+
+fn wub(f: Foo<!>) {
+    match f {}
+}
+
+fn main() {}
+
diff --git a/src/test/compile-fail/issue-39388.rs b/src/test/compile-fail/issue-39388.rs
new file mode 100644 (file)
index 0000000..6994d21
--- /dev/null
@@ -0,0 +1,17 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+macro_rules! assign {
+    (($($a:tt)*) = ($($b:tt))*) => { //~ ERROR expected `*` or `+`
+        $($a)* = $($b)*
+    }
+}
+
+fn main() {}
diff --git a/src/test/compile-fail/issue-39616.rs b/src/test/compile-fail/issue-39616.rs
new file mode 100644 (file)
index 0000000..d601249
--- /dev/null
@@ -0,0 +1,15 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+fn foo(a: [0; 1]) {} //~ ERROR expected type, found `0`
+//~| ERROR expected one of `->`, `where`, or `{`, found `]`
+// FIXME(jseyfried): avoid emitting the second error (preexisting)
+
+fn main() {}
diff --git a/src/test/debuginfo/macro-stepping.inc b/src/test/debuginfo/macro-stepping.inc
new file mode 100644 (file)
index 0000000..6aaf7ed
--- /dev/null
@@ -0,0 +1,17 @@
+// Copyright 2013-2017 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 included() {
+    foo!(); // #inc-loc1
+
+    foo2!(); // #inc-loc2
+
+    zzz(); // #inc-loc3
+}
index 37355ed377b796318ad0958b9a3fdbab4f458bc4..ca2c1e0c8f0298982c42397e077254d3988c9b0b 100644 (file)
 // gdb-command:frame
 // gdb-check:[...]#loc6[...]
 
+// gdb-command:continue
+// gdb-command:step
+// gdb-command:frame
+// gdb-check:[...]#inc-loc1[...]
+// gdb-command:next
+// gdb-command:frame
+// gdb-check:[...]#inc-loc2[...]
+// gdb-command:next
+// gdb-command:frame
+// gdb-check:[...]#inc-loc3[...]
+
 // === LLDB TESTS ==================================================================================
 
 // lldb-command:set set stop-line-count-before 0
 // lldb-command:frame select
 // lldb-check:[...]#loc5[...]
 
+// lldb-command:continue
+// lldb-command:step
+// lldb-command:frame select
+// lldb-check:[...]#inc-loc1[...]
+// lldb-command:next
+// lldb-command:frame select
+// lldb-check:[...]#inc-loc2[...]
+// lldb-command:next
+// lldb-command:frame select
+// lldb-check:[...]#inc-loc3[...]
+
 macro_rules! foo {
     () => {
         let a = 1;
@@ -99,6 +121,10 @@ fn main() {
              "world");
 
     zzz(); // #loc6
+
+    included(); // #break
 }
 
 fn zzz() {()}
+
+include!("macro-stepping.inc");
diff --git a/src/test/parse-fail/issue-39018.stderr b/src/test/parse-fail/issue-39018.stderr
deleted file mode 100644 (file)
index ee1a32c..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-error[E0369]: binary operation `+` cannot be applied to type `&'static str`
- --> src/test/ui/span/issue-39018.rs:2:13
-  |
-2 |     let x = "Hello " + "World!";
-  |             ^^^^^^^^
-  |
-note: `+` can't be used to concatenate two `&str` strings
- --> src/test/ui/span/issue-39018.rs:2:13
-  |
-2 |     let x = "Hello " + "World!";
-  |             ^^^^^^^^
-help: to_owned() can be used to create an owned `String` from a string reference. This allows concatenation since the `String` is owned.
-  |     let x = "Hello ".to_owned() + "World!";
-
-error[E0369]: binary operation `+` cannot be applied to type `World`
- --> src/test/ui/span/issue-39018.rs:7:13
-  |
-7 |     let y = World::Hello + World::Goodbye;
-  |             ^^^^^^^^^^^^
-  |
-note: an implementation of `std::ops::Add` might be missing for `World`
- --> src/test/ui/span/issue-39018.rs:7:13
-  |
-7 |     let y = World::Hello + World::Goodbye;
-  |             ^^^^^^^^^^^^
-
-error: aborting due to 2 previous errors
-
diff --git a/src/test/run-pass/catch-unwind-bang.rs b/src/test/run-pass/catch-unwind-bang.rs
new file mode 100644 (file)
index 0000000..df54ec9
--- /dev/null
@@ -0,0 +1,17 @@
+// Copyright 2017 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 worker() -> ! {
+    panic!()
+}
+
+fn main() {
+    std::panic::catch_unwind(worker).unwrap_err();
+}
index cf2acfe986c2155b4276613b65882ece9bf5770d..c36833f2fb6271862f25fade4e7988edd6779265 100644 (file)
@@ -25,12 +25,6 @@ struct Baz<T: ?Sized> {
     a: T
 }
 
-#[repr(packed)]
-struct Packed<T: ?Sized> {
-    a: u8,
-    b: T
-}
-
 struct HasDrop<T: ?Sized> {
     ptr: Box<usize>,
     data: T
@@ -55,12 +49,6 @@ fn main() {
     // The pointers should be the same
     assert_eq!(ptr1, ptr2);
 
-    // Test that packed structs are handled correctly
-    let p : Packed<usize> = Packed { a: 0, b: 13 };
-    assert_eq!(p.b.get(), 13);
-    let p : &Packed<Bar> = &p;
-    assert_eq!(p.b.get(), 13);
-
     // Test that nested DSTs work properly
     let f : Foo<Foo<usize>> = Foo { a: 0, b: Foo { a: 1, b: 17 }};
     assert_eq!(f.b.b.get(), 17);
index 6b47721ab4b32779e372d8daa773e16aa5c5b237..eb96d94efec930d3edaf3149d43b38a94a488d20 100644 (file)
@@ -8,6 +8,8 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use std::fmt;
+
 #[repr(C)]
 enum CEnum {
     Hello = 30,
@@ -15,16 +17,15 @@ enum CEnum {
 }
 
 fn test1(c: CEnum) -> i32 {
-  let c2 = CEnum::Hello;
-  match (c, c2) {
-    (CEnum::Hello, CEnum::Hello) => 42,
-    (CEnum::World, CEnum::Hello) => 0,
-    _ => 1
-  }
+    let c2 = CEnum::Hello;
+    match (c, c2) {
+        (CEnum::Hello, CEnum::Hello) => 42,
+        (CEnum::World, CEnum::Hello) => 0,
+        _ => 1
+    }
 }
 
 #[repr(packed)]
-#[derive(PartialEq, Debug)]
 struct Pakd {
     a: u64,
     b: u32,
@@ -33,6 +34,36 @@ struct Pakd {
     e: ()
 }
 
+// It is unsafe to use #[derive(Debug)] on a packed struct because the code generated by the derive
+// macro takes references to the fields instead of accessing them directly.
+impl fmt::Debug for Pakd {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        // It's important that we load the fields into locals by-value here. This will do safe
+        // unaligned loads into the locals, then pass references to the properly-aligned locals to
+        // the formatting code.
+        let Pakd { a, b, c, d, e } = *self;
+        f.debug_struct("Pakd")
+            .field("a", &a)
+            .field("b", &b)
+            .field("c", &c)
+            .field("d", &d)
+            .field("e", &e)
+            .finish()
+    }
+}
+
+// It is unsafe to use #[derive(PartialEq)] on a packed struct because the code generated by the
+// derive macro takes references to the fields instead of accessing them directly.
+impl PartialEq for Pakd {
+    fn eq(&self, other: &Pakd) -> bool {
+        self.a == other.a &&
+            self.b == other.b &&
+            self.c == other.c &&
+            self.d == other.d &&
+            self.e == other.e
+    }
+}
+
 impl Drop for Pakd {
     fn drop(&mut self) {}
 }
@@ -59,12 +90,12 @@ fn test5(x: fn(u32) -> Option<u32>) -> (Option<u32>, Option<u32>) {
 }
 
 fn main() {
-  assert_eq!(test1(CEnum::Hello), 42);
-  assert_eq!(test1(CEnum::World), 0);
-  assert_eq!(test2(), Pakd { a: 42, b: 42, c: 42, d: 42, e: () });
-  assert_eq!(test3(), TupleLike(42, 42));
-  let t4 = test4(TupleLike);
-  assert_eq!(t4.0, t4.1);
-  let t5 = test5(Some);
-  assert_eq!(t5.0, t5.1);
+    assert_eq!(test1(CEnum::Hello), 42);
+    assert_eq!(test1(CEnum::World), 0);
+    assert_eq!(test2(), Pakd { a: 42, b: 42, c: 42, d: 42, e: () });
+    assert_eq!(test3(), TupleLike(42, 42));
+    let t4 = test4(TupleLike);
+    assert_eq!(t4.0, t4.1);
+    let t5 = test5(Some);
+    assert_eq!(t5.0, t5.1);
 }
index 139d42e3a3524b39bb7b3cac5e4c91c77014cc5d..ac3dfcdfde155cd79aca32d0c6b71e937303d93c 100644 (file)
@@ -8,9 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// ignore-stage0
-// ignore-stage1
-
 // ignore-emscripten
 
 #![feature(i128_type, test)]
diff --git a/src/test/rustdoc/attributes.rs b/src/test/rustdoc/attributes.rs
new file mode 100644 (file)
index 0000000..22e5090
--- /dev/null
@@ -0,0 +1,27 @@
+// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![crate_name = "foo"]
+
+// @has foo/fn.f.html '//*[@class="docblock attributes"]' '#[no_mangle]'
+#[no_mangle]
+pub extern "C" fn f() {}
+
+// @has foo/fn.g.html '//*[@class="docblock attributes"]' '#[export_name = "bar"]'
+#[export_name = "bar"]
+pub extern "C" fn g() {}
+
+// @has foo/enum.Foo.html '//*[@class="docblock attributes"]' '#[repr(i64)]'
+// @has foo/enum.Foo.html '//*[@class="docblock attributes"]' '#[must_use]'
+#[repr(i64)]
+#[must_use]
+pub enum Foo {
+    Bar,
+}
diff --git a/src/test/ui/macros/assert_eq_trailing_comma.rs b/src/test/ui/macros/assert_eq_trailing_comma.rs
new file mode 100644 (file)
index 0000000..d98baf6
--- /dev/null
@@ -0,0 +1,13 @@
+// Copyright 2017 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() {
+    assert_eq!(1, 1,);
+}
diff --git a/src/test/ui/macros/assert_eq_trailing_comma.stderr b/src/test/ui/macros/assert_eq_trailing_comma.stderr
new file mode 100644 (file)
index 0000000..ca590db
--- /dev/null
@@ -0,0 +1,6 @@
+error: unexpected end of macro invocation
+  --> $DIR/assert_eq_trailing_comma.rs:12:20
+   |
+12 |     assert_eq!(1, 1,);
+   |                    ^
+
diff --git a/src/test/ui/macros/assert_ne_trailing_comma.rs b/src/test/ui/macros/assert_ne_trailing_comma.rs
new file mode 100644 (file)
index 0000000..4d3c29d
--- /dev/null
@@ -0,0 +1,13 @@
+// Copyright 2017 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() {
+    assert_ne!(1, 2,);
+}
diff --git a/src/test/ui/macros/assert_ne_trailing_comma.stderr b/src/test/ui/macros/assert_ne_trailing_comma.stderr
new file mode 100644 (file)
index 0000000..ffabcae
--- /dev/null
@@ -0,0 +1,6 @@
+error: unexpected end of macro invocation
+  --> $DIR/assert_ne_trailing_comma.rs:12:20
+   |
+12 |     assert_ne!(1, 2,);
+   |                    ^
+
index a8cc74056ca2cfd5aaf0207f74ca021c68d482b5..9d6d4570c6ba6f2a8830f1178f79fdd838c84db0 100644 (file)
@@ -4,11 +4,7 @@ error[E0369]: binary operation `+` cannot be applied to type `&'static str`
 12 |     let x = "Hello " + "World!";
    |             ^^^^^^^^
    |
-note: `+` can't be used to concatenate two `&str` strings
-  --> $DIR/issue-39018.rs:12:13
-   |
-12 |     let x = "Hello " + "World!";
-   |             ^^^^^^^^
+   = note: `+` can't be used to concatenate two `&str` strings
 help: to_owned() can be used to create an owned `String` from a string reference. String concatenation appends the string on the right to the string on the left and may require reallocation. This requires ownership of the string on the left.
    |     let x = "Hello ".to_owned() + "World!";
 
@@ -18,11 +14,7 @@ error[E0369]: binary operation `+` cannot be applied to type `World`
 17 |     let y = World::Hello + World::Goodbye;
    |             ^^^^^^^^^^^^
    |
-note: an implementation of `std::ops::Add` might be missing for `World`
-  --> $DIR/issue-39018.rs:17:13
-   |
-17 |     let y = World::Hello + World::Goodbye;
-   |             ^^^^^^^^^^^^
+   = note: an implementation of `std::ops::Add` might be missing for `World`
 
 error: aborting due to 2 previous errors
 
index 2a24edd4e3f330633b05a87d2ac32091c3a340ff..991cd02d215dcdfd782c6216e2c88a61bc28edc5 100644 (file)
@@ -179,8 +179,8 @@ fn build(&mut self) {
         // and wrap it up in a `Value::Table`.
         let mut manifest = BTreeMap::new();
         manifest.insert("manifest-version".to_string(),
-                        toml::encode(&manifest_version));
-        manifest.insert("date".to_string(), toml::encode(&date));
+                        toml::Value::String(manifest_version));
+        manifest.insert("date".to_string(), toml::Value::String(date));
         manifest.insert("pkg".to_string(), toml::encode(&pkg));
         let manifest = toml::Value::Table(manifest).to_string();
 
@@ -362,7 +362,8 @@ fn version(&self, component: &str, target: &str) -> String {
     fn hash(&self, path: &Path) -> String {
         let sha = t!(Command::new("shasum")
                         .arg("-a").arg("256")
-                        .arg(path)
+                        .arg(path.file_name().unwrap())
+                        .current_dir(path.parent().unwrap())
                         .output());
         assert!(sha.status.success());
 
index 2c3e57c8332623272afb278193914f98f4e905d7..707d5da50bf73e961fa33ecf1614e2212d1c9277 100644 (file)
@@ -167,7 +167,7 @@ pub fn check(path: &Path, bad: &mut bool) {
     // FIXME get this whitelist empty.
     let whitelist = vec![
         "abi_ptx", "simd", "static_recursion",
-        "cfg_target_has_atomic", "staged_api", "const_indexing",
+        "cfg_target_has_atomic", "staged_api",
         "unboxed_closures", "stmt_expr_attributes",
         "cfg_target_thread_local", "unwind_attributes",
         "inclusive_range_syntax"