]> git.lizzy.rs Git - rust.git/commitdiff
Auto merge of #23522 - steveklabnik:gh22518, r=Manishearth
authorbors <bors@rust-lang.org>
Fri, 20 Mar 2015 11:29:12 +0000 (11:29 +0000)
committerbors <bors@rust-lang.org>
Fri, 20 Mar 2015 11:29:12 +0000 (11:29 +0000)
When investigating #22518, this chapter is really the only part that has `rand`, and the rest still works without it. We should have some examples like this, but for now, it's more important to be right than perfect.

40 files changed:
Makefile.in
man/rustc.1
src/compiletest/compiletest.rs
src/compiletest/header.rs
src/doc/trpl/ffi.md
src/doc/trpl/pointers.md
src/doc/trpl/unsafe.md
src/libcore/num/mod.rs
src/librustc/middle/astencode.rs
src/librustc_back/tempdir.rs
src/librustdoc/html/render.rs
src/librustdoc/lib.rs
src/libserialize/lib.rs
src/libstd/fs/mod.rs
src/libstd/fs/tempdir.rs
src/libstd/io/error.rs
src/libstd/io/mod.rs
src/libstd/net/mod.rs
src/libstd/net/parser.rs
src/libstd/net/tcp.rs
src/libstd/num/f32.rs
src/libstd/num/f64.rs
src/libstd/num/mod.rs
src/libstd/process.rs
src/libstd/rt/mod.rs
src/libstd/rt/util.rs
src/libstd/sys/unix/mod.rs
src/libstd/sys/windows/mod.rs
src/libsyntax/ext/quote.rs
src/libsyntax/print/pprust.rs
src/libtest/lib.rs
src/libunicode/char.rs
src/test/auxiliary/crate_with_invalid_spans.rs [new file with mode: 0644]
src/test/auxiliary/crate_with_invalid_spans_macros.rs [new file with mode: 0644]
src/test/run-fail/test-tasks-invalid-value.rs
src/test/run-make/rustdoc-src-links/Makefile [new file with mode: 0644]
src/test/run-make/rustdoc-src-links/foo.rs [new file with mode: 0644]
src/test/run-make/rustdoc-src-links/qux/mod.rs [new file with mode: 0644]
src/test/run-pass/import-crate-with-invalid-spans.rs [new file with mode: 0644]
src/test/run-pass/tcp-connect-timeouts.rs

index a760155bbd91aeeee3a961599f7a7cf86c4b331a..e7ad2aec7be0af4be5390c40443f5f7c5262fcfa 100644 (file)
 #     make check-stage1-rpass TESTNAME=my-shiny-new-test
 #
 #     // Having trouble figuring out which test is failing? Turn off parallel tests
-#     make check-stage1-std RUST_TEST_TASKS=1
-#
-# This is hardly all there is to know of The Rust Build System's
-# mysteries. The tale continues on the wiki[1].
-#
-# [1]: https://github.com/rust-lang/rust/wiki/Note-testsuite
+#     make check-stage1-std RUST_TEST_THREADS=1
 #
 # If you really feel like getting your hands dirty, then:
 #
index f37e66001909305143f627359a9f392adbbfeb6d..33ef3f9ee4acba4e3078a5a3afb8ac6ccf3849d5 100644 (file)
@@ -242,6 +242,28 @@ full debug info with variable and type information.
 \fBopt\-level\fR=\fIVAL\fR
 Optimize with possible levels 0\[en]3
 
+.SH ENVIRONMENT VARIABLES
+
+Some of these affect the output of the compiler, while others affect programs
+which link to the standard library.
+
+.TP
+\fBRUST_TEST_THREADS\fR
+The test framework Rust provides executes tests in parallel. This variable sets
+the maximum number of threads used for this purpose.
+
+.TP
+\fBRUST_TEST_NOCAPTURE\fR
+A synonym for the --nocapture flag.
+
+.TP
+\fBRUST_MIN_STACK\fR
+Sets the minimum stack size for new threads.
+
+.TP
+\fBRUST_BACKTRACE\fR
+If set, produces a backtrace in the output of a program which panics.
+
 .SH "EXAMPLES"
 To build an executable from a source file with a main function:
     $ rustc \-o hello hello.rs
index 7fbe772b7f5bdd1171971509be08063c3adc86ee..01c4e99b77c70a25daa503a95ac2f1d45a093f0d 100644 (file)
@@ -224,7 +224,7 @@ pub fn run_tests(config: &Config) {
         // android debug-info test uses remote debugger
         // so, we test 1 task at once.
         // also trying to isolate problems with adb_run_wrapper.sh ilooping
-        env::set_var("RUST_TEST_TASKS","1");
+        env::set_var("RUST_TEST_THREADS","1");
     }
 
     match config.mode {
@@ -232,7 +232,7 @@ pub fn run_tests(config: &Config) {
             // Some older versions of LLDB seem to have problems with multiple
             // instances running in parallel, so only run one test task at a
             // time.
-            env::set_var("RUST_TEST_TASKS", "1");
+            env::set_var("RUST_TEST_THREADS", "1");
         }
         _ => { /* proceed */ }
     }
index 21cebc61b3a9d3d4dcc821e15de197b896bdd769..6899fa13974e9e4282bafd0fda4021ec4223765e 100644 (file)
@@ -131,7 +131,7 @@ pub fn load_props(testfile: &Path) -> TestProps {
         true
     });
 
-    for key in vec!["RUST_TEST_NOCAPTURE", "RUST_TEST_TASKS"] {
+    for key in vec!["RUST_TEST_NOCAPTURE", "RUST_TEST_THREADS"] {
         match env::var(key) {
             Ok(val) =>
                 if exec_env.iter().find(|&&(ref x, _)| *x == key.to_string()).is_none() {
index 20b0ffc1b286200c751e294ad684787f3c6ad49e..018f35337f3c0b376f86c23b571e93f6ebc2603a 100644 (file)
@@ -170,6 +170,8 @@ Foreign libraries often hand off ownership of resources to the calling code.
 When this occurs, we must use Rust's destructors to provide safety and guarantee
 the release of these resources (especially in the case of panic).
 
+For more about destructors, see the [Drop trait](../std/ops/trait.Drop.html).
+
 # Callbacks from C code to Rust functions
 
 Some external libraries require the usage of callbacks to report back their
index 930a40c5050db4c001f0d306d4aa8e671000fa3d..39106aaf85751c3efeb31b2ce6ebf8357a302879 100644 (file)
@@ -561,38 +561,40 @@ fn main() {
 In this case, Rust knows that `x` is being *borrowed* by the `add_one()`
 function, and since it's only reading the value, allows it.
 
-We can borrow `x` multiple times, as long as it's not simultaneous:
+We can borrow `x` as read-only multiple times, even simultaneously:
 
 ```{rust}
-fn add_one(x: &i32) -> i32 {
-    *x + 1
+fn add(x: &i32, y: &i32) -> i32 {
+    *x + *y
 }
 
 fn main() {
     let x = Box::new(5);
 
-    println!("{}", add_one(&*x));
-    println!("{}", add_one(&*x));
-    println!("{}", add_one(&*x));
+    println!("{}", add(&x, &x));
+    println!("{}", add(&x, &x));
 }
 ```
 
-Or as long as it's not a mutable borrow. This will error:
+We can mutably borrow `x` multiple times, but only if x itself is mutable, and
+it may not be *simultaneously* borrowed: 
 
 ```{rust,ignore}
-fn add_one(x: &mut i32) -> i32 {
-    *x + 1
+fn increment(x: &mut i32) {
+    *x += 1;
 }
 
 fn main() {
-    let x = Box::new(5);
+    // If variable x is not "mut", this will not compile
+    let mut x = Box::new(5);
 
-    println!("{}", add_one(&*x)); // error: cannot borrow immutable dereference
-                                  // of `&`-pointer as mutable
+    increment(&mut x);
+    increment(&mut x);
+    println!("{}", x);
 }
 ```
 
-Notice we changed the signature of `add_one()` to request a mutable reference.
+Notice the signature of `increment()` requests a mutable reference.
 
 ## Best practices
 
index 4e14085599b603d3b640d672748c8f41eebce10f..11f0b8e1ddbf96df73378f4169fae121551fea85 100644 (file)
@@ -93,10 +93,6 @@ offered by the Rust language and libraries. For example, they
 - are plain-old-data, that is, they don't move ownership, again unlike
   `Box`, hence the Rust compiler cannot protect against bugs like
   use-after-free;
-- are considered sendable (if their contents is considered sendable),
-  so the compiler offers no assistance with ensuring their use is
-  thread-safe; for example, one can concurrently access a `*mut i32`
-  from two threads without synchronization.
 - lack any form of lifetimes, unlike `&`, and so the compiler cannot
   reason about dangling pointers; and
 - have no guarantees about aliasing or mutability other than mutation
index 156bc2708fb5f338e46a29e2feca4e9c23dcece7..17ef0ecb1c0da6feb4905230334690661eadd29d 100644 (file)
@@ -345,6 +345,16 @@ fn to_le(self) -> Self {
 
     /// Saturating integer addition. Computes `self + other`, saturating at
     /// the numeric bounds instead of overflowing.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::num::Int;
+    ///
+    /// assert_eq!(5u16.saturating_add(65534), 65535);
+    /// assert_eq!((-5i16).saturating_add(-32767), -32768);
+    /// assert_eq!(100u32.saturating_add(4294967294), 4294967295);
+    /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     fn saturating_add(self, other: Self) -> Self {
@@ -357,6 +367,16 @@ fn saturating_add(self, other: Self) -> Self {
 
     /// Saturating integer subtraction. Computes `self - other`, saturating at
     /// the numeric bounds instead of overflowing.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// use std::num::Int;
+    ///
+    /// assert_eq!(5u16.saturating_sub(65534), 0);
+    /// assert_eq!(5i16.saturating_sub(-32767), 32767);
+    /// assert_eq!(100u32.saturating_sub(4294967294), 0);
+    /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     fn saturating_sub(self, other: Self) -> Self {
index f7210728bb480099731fad7eb7c999007705179f..8b2a94025f337441a3fa44b86d7e9d4dd549b228 100644 (file)
@@ -235,12 +235,27 @@ pub fn tr_intern_def_id(&self, did: ast::DefId) -> ast::DefId {
     pub fn tr_span(&self, span: Span) -> Span {
         let imported_filemaps = &self.cdata.codemap_import_info[..];
 
+        let span = if span.lo > span.hi {
+            // Currently macro expansion sometimes produces invalid Span values
+            // where lo > hi. In order not to crash the compiler when trying to
+            // translate these values, let's transform them into something we
+            // can handle (and which will produce useful debug locations at
+            // least some of the time).
+            // This workaround is only necessary as long as macro expansion is
+            // not fixed. FIXME(#23480)
+            codemap::mk_sp(span.lo, span.lo)
+        } else {
+            span
+        };
+
         let filemap_index = {
             // Optimize for the case that most spans within a translated item
             // originate from the same filemap.
             let last_filemap_index = self.last_filemap_index.get();
 
             if span.lo >= imported_filemaps[last_filemap_index].original_start_pos &&
+               span.lo <= imported_filemaps[last_filemap_index].original_end_pos &&
+               span.hi >= imported_filemaps[last_filemap_index].original_start_pos &&
                span.hi <= imported_filemaps[last_filemap_index].original_end_pos {
                 last_filemap_index
             } else {
index 4d8619a81216f940c6d14633703836187503fd71..0e87ba278db21f520286843306901c2494beac2f 100644 (file)
@@ -61,12 +61,12 @@ pub fn new_in<P: AsPath + ?Sized>(tmpdir: &P, prefix: &str)
             let path = tmpdir.join(&leaf);
             match fs::create_dir(&path) {
                 Ok(_) => return Ok(TempDir { path: Some(path) }),
-                Err(ref e) if e.kind() == ErrorKind::PathAlreadyExists => {}
+                Err(ref e) if e.kind() == ErrorKind::AlreadyExists => {}
                 Err(e) => return Err(e)
             }
         }
 
-        Err(Error::new(ErrorKind::PathAlreadyExists,
+        Err(Error::new(ErrorKind::AlreadyExists,
                        "too many temporary directories already exist",
                        None))
     }
index f97470dbaed758d885165bed8c20e67c334d0c98..81daac7b90f0d018fb86ed71288a9f088ce8fffe 100644 (file)
@@ -692,16 +692,23 @@ fn shortty(item: &clean::Item) -> ItemType {
 
 /// Takes a path to a source file and cleans the path to it. This canonicalizes
 /// things like ".." to components which preserve the "top down" hierarchy of a
-/// static HTML tree.
+/// static HTML tree. Each component in the cleaned path will be passed as an
+/// argument to `f`. The very last component of the path (ie the file name) will
+/// be passed to `f` if `keep_filename` is true, and ignored otherwise.
 // FIXME (#9639): The closure should deal with &[u8] instead of &str
 // FIXME (#9639): This is too conservative, rejecting non-UTF-8 paths
-fn clean_srcpath<F>(src_root: &Path, p: &Path, mut f: F) where
+fn clean_srcpath<F>(src_root: &Path, p: &Path, keep_filename: bool, mut f: F) where
     F: FnMut(&str),
 {
     // make it relative, if possible
     let p = p.relative_from(src_root).unwrap_or(p);
 
-    for c in p.iter().map(|x| x.to_str().unwrap()) {
+    let mut iter = p.iter().map(|x| x.to_str().unwrap()).peekable();
+    while let Some(c) = iter.next() {
+        if !keep_filename && iter.peek().is_none() {
+            break;
+        }
+
         if ".." == c {
             f("up");
         } else {
@@ -803,7 +810,7 @@ fn emit_source(&mut self, filename: &str) -> io::Result<()> {
         // Create the intermediate directories
         let mut cur = self.dst.clone();
         let mut root_path = String::from_str("../../");
-        clean_srcpath(&self.cx.src_root, &p, |component| {
+        clean_srcpath(&self.cx.src_root, &p, false, |component| {
             cur.push(component);
             mkdir(&cur).unwrap();
             root_path.push_str("../");
@@ -1368,7 +1375,7 @@ fn href(&self, cx: &Context) -> Option<String> {
         if ast_util::is_local(self.item.def_id) {
             let mut path = Vec::new();
             clean_srcpath(&cx.src_root, Path::new(&self.item.source.filename),
-                          |component| {
+                          true, |component| {
                 path.push(component.to_string());
             });
             let href = if self.item.source.loline == self.item.source.hiline {
index bd4177861dd42f9d53ee6b3d5861fa8a0bc41ae0..0650b4d515860902ab9409444b96822042a5611c 100644 (file)
@@ -35,7 +35,6 @@
 #![feature(test)]
 #![feature(unicode)]
 #![feature(str_words)]
-#![feature(io)]
 #![feature(file_path)]
 #![feature(path_ext)]
 #![feature(path_relative_from)]
index 31c270dca6bba1fa612d6c18da71362b4cc33916..90cb88046e53d008416577d3934a927888b6dbe9 100644 (file)
@@ -31,7 +31,6 @@
 #![feature(collections)]
 #![feature(core)]
 #![feature(int_uint)]
-#![feature(io)]
 #![feature(old_path)]
 #![feature(rustc_private)]
 #![feature(staged_api)]
index ba89b3a0ea63f8b0e365a07ea6275d0beb258839..c56852cb18a0577b93ca8895a34c44a1d0c44965 100644 (file)
@@ -73,6 +73,11 @@ pub struct File {
 /// will yield instances of `io::Result<DirEntry>`. Through a `DirEntry`
 /// information like the entry's path and possibly other metadata can be
 /// learned.
+///
+/// # Failure
+///
+/// This `io::Result` will be an `Err` if there's some sort of intermittent
+/// IO error during iteration.
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct ReadDir(fs_imp::ReadDir);
 
@@ -493,7 +498,7 @@ pub fn copy<P: AsPath, Q: AsPath>(from: P, to: Q) -> io::Result<u64> {
     let from = from.as_path();
     let to = to.as_path();
     if !from.is_file() {
-        return Err(Error::new(ErrorKind::MismatchedFileTypeForOperation,
+        return Err(Error::new(ErrorKind::InvalidInput,
                               "the source path is not an existing file",
                               None))
     }
@@ -1134,7 +1139,7 @@ fn mkdir_path_already_exists_error() {
         let dir = &tmpdir.join("mkdir_error_twice");
         check!(fs::create_dir(dir));
         let e = fs::create_dir(dir).err().unwrap();
-        assert_eq!(e.kind(), ErrorKind::PathAlreadyExists);
+        assert_eq!(e.kind(), ErrorKind::AlreadyExists);
     }
 
     #[test]
index c1da77a6668f51b513ab79d7428a87aa1bcebd3d..8f32d7a586459241324a3a249a6ede228c4bce55 100644 (file)
@@ -68,12 +68,12 @@ pub fn new_in<P: AsPath + ?Sized>(tmpdir: &P, prefix: &str)
             let path = tmpdir.join(&leaf);
             match fs::create_dir(&path) {
                 Ok(_) => return Ok(TempDir { path: Some(path) }),
-                Err(ref e) if e.kind() == ErrorKind::PathAlreadyExists => {}
+                Err(ref e) if e.kind() == ErrorKind::AlreadyExists => {}
                 Err(e) => return Err(e)
             }
         }
 
-        Err(Error::new(ErrorKind::PathAlreadyExists,
+        Err(Error::new(ErrorKind::AlreadyExists,
                        "too many temporary directories already exist",
                        None))
     }
index 530c672810723a26ae7c59cfd1c6535a3e6a9105..f445ace081e4ffc9f2b66b4e2317d07f76076bdb 100644 (file)
@@ -51,41 +51,53 @@ struct Custom {
 }
 
 /// A list specifying general categories of I/O error.
+///
+/// This list is intended to grow over time and it is not recommended to
+/// exhaustively match against it.
 #[derive(Copy, PartialEq, Eq, Clone, Debug)]
-#[unstable(feature = "io",
-           reason = "the interaction between OS error codes and how they map to \
-                     these names (as well as the names themselves) has not \
-                     been thoroughly thought out")]
+#[stable(feature = "rust1", since = "1.0.0")]
 pub enum ErrorKind {
-    /// The file was not found.
-    FileNotFound,
-    /// The file permissions disallowed access to this file.
+    /// An entity was not found, often a file.
+    #[stable(feature = "rust1", since = "1.0.0")]
+    NotFound,
+    /// The operation lacked the necessary privileges to complete.
+    #[stable(feature = "rust1", since = "1.0.0")]
     PermissionDenied,
     /// The connection was refused by the remote server.
+    #[stable(feature = "rust1", since = "1.0.0")]
     ConnectionRefused,
     /// The connection was reset by the remote server.
+    #[stable(feature = "rust1", since = "1.0.0")]
     ConnectionReset,
     /// The connection was aborted (terminated) by the remote server.
+    #[stable(feature = "rust1", since = "1.0.0")]
     ConnectionAborted,
     /// The network operation failed because it was not connected yet.
+    #[stable(feature = "rust1", since = "1.0.0")]
     NotConnected,
+    /// A socket address could not be bound because the address is already in
+    /// use elsewhere.
+    #[stable(feature = "rust1", since = "1.0.0")]
+    AddrInUse,
+    /// A nonexistent interface was requested or the requested address was not
+    /// local.
+    #[stable(feature = "rust1", since = "1.0.0")]
+    AddrNotAvailable,
     /// The operation failed because a pipe was closed.
+    #[stable(feature = "rust1", since = "1.0.0")]
     BrokenPipe,
-    /// A file already existed with that name.
-    PathAlreadyExists,
-    /// No file exists at that location.
-    PathDoesntExist,
-    /// The path did not specify the type of file that this operation required.
-    /// For example, attempting to copy a directory with the `fs::copy()`
-    /// operation will fail with this error.
-    MismatchedFileTypeForOperation,
-    /// The operation temporarily failed (for example, because a signal was
-    /// received), and retrying may succeed.
-    ResourceUnavailable,
-    /// A parameter was incorrect in a way that caused an I/O error not part of
-    /// this list.
+    /// An entity already exists, often a file.
+    #[stable(feature = "rust1", since = "1.0.0")]
+    AlreadyExists,
+    /// The operation needs to block to complete, but the blocking operation was
+    /// requested to not occur.
+    #[stable(feature = "rust1", since = "1.0.0")]
+    WouldBlock,
+    /// A parameter was incorrect.
+    #[stable(feature = "rust1", since = "1.0.0")]
     InvalidInput,
     /// The I/O operation's timeout expired, causing it to be canceled.
+    #[stable(feature = "rust1", since = "1.0.0")]
     TimedOut,
     /// An error returned when an operation could not be completed because a
     /// call to `write` returned `Ok(0)`.
@@ -93,11 +105,23 @@ pub enum ErrorKind {
     /// This typically means that an operation could only succeed if it wrote a
     /// particular number of bytes but only a smaller number of bytes could be
     /// written.
+    #[stable(feature = "rust1", since = "1.0.0")]
     WriteZero,
-    /// This operation was interrupted
+    /// This operation was interrupted.
+    ///
+    /// Interrupted operations can typically be retried.
+    #[stable(feature = "rust1", since = "1.0.0")]
     Interrupted,
     /// Any I/O error not part of this list.
+    #[stable(feature = "rust1", since = "1.0.0")]
     Other,
+
+    /// Any I/O error not part of this list.
+    #[unstable(feature = "std_misc",
+               reason = "better expressed through extensible enums that this \
+                         enum cannot be exhaustively matched against")]
+    #[doc(hidden)]
+    __Nonexhaustive,
 }
 
 impl Error {
@@ -134,6 +158,19 @@ pub fn from_os_error(code: i32) -> Error {
         Error { repr: Repr::Os(code) }
     }
 
+    /// Returns the OS error that this error represents (if any).
+    ///
+    /// If this `Error` was constructed via `last_os_error` then this function
+    /// will return `Some`, otherwise it will return `None`.
+    #[unstable(feature = "io", reason = "function was just added and the return \
+                                         type may become an abstract OS error")]
+    pub fn raw_os_error(&self) -> Option<i32> {
+        match self.repr {
+            Repr::Os(i) => Some(i),
+            Repr::Custom(..) => None,
+        }
+    }
+
     /// Return the corresponding `ErrorKind` for this error.
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn kind(&self) -> ErrorKind {
index 8691c84a4622f348b675545aa060740f23d40f06..237435d6dfbfa4c9b8a224c515edc74d122dc20a 100644 (file)
@@ -584,7 +584,8 @@ fn read_until(&mut self, byte: u8, buf: &mut Vec<u8>) -> Result<usize> {
         read_until(self, byte, buf)
     }
 
-    /// Read all bytes until a newline byte (the 0xA byte) is reached.
+    /// Read all bytes until a newline byte (the 0xA byte) is reached, and
+    /// append them to the provided buffer.
     ///
     /// This function will continue to read (and buffer) bytes from the
     /// underlying stream until the newline delimiter (the 0xA byte) or EOF is
index 36f36af73e1480c10bc435e1455e8f8d48c41122..543fdd16f41e307d3b185f7e8f39232ad494e6b0 100644 (file)
@@ -25,6 +25,7 @@
 pub use self::addr::{SocketAddr, SocketAddrV4, SocketAddrV6, ToSocketAddrs};
 pub use self::tcp::{TcpStream, TcpListener};
 pub use self::udp::UdpSocket;
+pub use self::parser::AddrParseError;
 
 mod ip;
 mod addr;
index 9843a1527180e356b7f996e69e4aba307e8fd99b..e7509834c7b7866a83b2f52f564c40816c76781a 100644 (file)
@@ -296,35 +296,40 @@ fn read_socket_addr(&mut self) -> Option<SocketAddr> {
     }
 }
 
+#[stable(feature = "rust1", since = "1.0.0")]
 impl FromStr for Ipv4Addr {
-    type Err = ParseError;
-    fn from_str(s: &str) -> Result<Ipv4Addr, ParseError> {
+    type Err = AddrParseError;
+    fn from_str(s: &str) -> Result<Ipv4Addr, AddrParseError> {
         match Parser::new(s).read_till_eof(|p| p.read_ipv4_addr()) {
             Some(s) => Ok(s),
-            None => Err(ParseError)
+            None => Err(AddrParseError(()))
         }
     }
 }
 
+#[stable(feature = "rust1", since = "1.0.0")]
 impl FromStr for Ipv6Addr {
-    type Err = ParseError;
-    fn from_str(s: &str) -> Result<Ipv6Addr, ParseError> {
+    type Err = AddrParseError;
+    fn from_str(s: &str) -> Result<Ipv6Addr, AddrParseError> {
         match Parser::new(s).read_till_eof(|p| p.read_ipv6_addr()) {
             Some(s) => Ok(s),
-            None => Err(ParseError)
+            None => Err(AddrParseError(()))
         }
     }
 }
 
+#[stable(feature = "rust1", since = "1.0.0")]
 impl FromStr for SocketAddr {
-    type Err = ParseError;
-    fn from_str(s: &str) -> Result<SocketAddr, ParseError> {
+    type Err = AddrParseError;
+    fn from_str(s: &str) -> Result<SocketAddr, AddrParseError> {
         match Parser::new(s).read_till_eof(|p| p.read_socket_addr()) {
             Some(s) => Ok(s),
-            None => Err(ParseError),
+            None => Err(AddrParseError(())),
         }
     }
 }
 
-#[derive(Debug, Clone, PartialEq, Copy)]
-pub struct ParseError;
+/// An error returned when parsing an IP address or a socket address.
+#[stable(feature = "rust1", since = "1.0.0")]
+#[derive(Debug, Clone, PartialEq)]
+pub struct AddrParseError(());
index 501ba2dc2c178b63ffe7b98597c769043ee112f5..f263d7d72d35d364d5d5d04af0a6c2d78dc83c15 100644 (file)
@@ -273,8 +273,7 @@ fn bind_error() {
         match TcpListener::bind("1.1.1.1:9999") {
             Ok(..) => panic!(),
             Err(e) =>
-                // EADDRNOTAVAIL is mapped to ConnectionRefused
-                assert_eq!(e.kind(), ErrorKind::ConnectionRefused),
+                assert_eq!(e.kind(), ErrorKind::AddrNotAvailable),
         }
     }
 
@@ -282,8 +281,11 @@ fn bind_error() {
     fn connect_error() {
         match TcpStream::connect("0.0.0.0:1") {
             Ok(..) => panic!(),
-            Err(e) => assert!((e.kind() == ErrorKind::ConnectionRefused)
-                              || (e.kind() == ErrorKind::InvalidInput)),
+            Err(e) => assert!(e.kind() == ErrorKind::ConnectionRefused ||
+                              e.kind() == ErrorKind::InvalidInput ||
+                              e.kind() == ErrorKind::AddrInUse ||
+                              e.kind() == ErrorKind::AddrNotAvailable,
+                              "bad error: {} {:?}", e, e.kind()),
         }
     }
 
@@ -535,7 +537,8 @@ fn double_bind() {
                 Ok(..) => panic!(),
                 Err(e) => {
                     assert!(e.kind() == ErrorKind::ConnectionRefused ||
-                            e.kind() == ErrorKind::Other,
+                            e.kind() == ErrorKind::Other ||
+                            e.kind() == ErrorKind::AddrInUse,
                             "unknown error: {} {:?}", e, e.kind());
                 }
             }
index 11e2b8dca1b8082d73c6835326497b4d96185acb..b5513dfd0354d542538360bb947fb510020596d3 100644 (file)
@@ -191,8 +191,8 @@ fn to_radians(self) -> f32 { num::Float::to_radians(self) }
     /// Constructs a floating point number by multiplying `x` by 2 raised to the
     /// power of `exp`
     #[inline]
-    fn ldexp(x: f32, exp: int) -> f32 {
-        unsafe { cmath::ldexpf(x, exp as c_int) }
+    fn ldexp(self, exp: isize) -> f32 {
+        unsafe { cmath::ldexpf(self, exp as c_int) }
     }
 
     /// Breaks the number into a normalized fraction and a base-2 exponent,
@@ -2207,8 +2207,8 @@ fn test_ldexp() {
         let f1: f32 = FromStrRadix::from_str_radix("1p-123", 16).unwrap();
         let f2: f32 = FromStrRadix::from_str_radix("1p-111", 16).unwrap();
         let f3: f32 = FromStrRadix::from_str_radix("1.Cp-12", 16).unwrap();
-        assert_eq!(Float::ldexp(1f32, -123), f1);
-        assert_eq!(Float::ldexp(1f32, -111), f2);
+        assert_eq!(1f32.ldexp(-123), f1);
+        assert_eq!(1f32.ldexp(-111), f2);
         assert_eq!(Float::ldexp(1.75f32, -12), f3);
 
         assert_eq!(Float::ldexp(0f32, -123), 0f32);
index 650f642220fc0c270257226d1912068c9d80738b..61bddc3d18f66310c7210bdd5c7747b9001f0517 100644 (file)
@@ -200,8 +200,8 @@ fn to_degrees(self) -> f64 { num::Float::to_degrees(self) }
     fn to_radians(self) -> f64 { num::Float::to_radians(self) }
 
     #[inline]
-    fn ldexp(x: f64, exp: int) -> f64 {
-        unsafe { cmath::ldexp(x, exp as c_int) }
+    fn ldexp(self, exp: isize) -> f64 {
+        unsafe { cmath::ldexp(self, exp as c_int) }
     }
 
     /// Breaks the number into a normalized fraction and a base-2 exponent,
@@ -2214,8 +2214,8 @@ fn test_ldexp() {
         let f1: f64 = FromStrRadix::from_str_radix("1p-123", 16).unwrap();
         let f2: f64 = FromStrRadix::from_str_radix("1p-111", 16).unwrap();
         let f3: f64 = FromStrRadix::from_str_radix("1.Cp-12", 16).unwrap();
-        assert_eq!(Float::ldexp(1f64, -123), f1);
-        assert_eq!(Float::ldexp(1f64, -111), f2);
+        assert_eq!(1f64.ldexp(-123), f1);
+        assert_eq!(1f64.ldexp(-111), f2);
         assert_eq!(Float::ldexp(1.75f64, -12), f3);
 
         assert_eq!(Float::ldexp(0f64, -123), 0f64);
index 37f1f69177621781729c03e49f0c6d2bcb7fdf6d..082dad613b5561891bd11be67406f354e198fa9b 100644 (file)
@@ -699,7 +699,7 @@ pub trait Float
     /// ```
     #[unstable(feature = "std_misc",
                reason = "pending integer conventions")]
-    fn ldexp(x: Self, exp: isize) -> Self;
+    fn ldexp(self, exp: isize) -> Self;
     /// Breaks the number into a normalized fraction and a base-2 exponent,
     /// satisfying:
     ///
index df8a5d27c7fa0be9767784af1d481af23997beeb..cda37b19c48680b4815e579acb839be6faa891ff 100644 (file)
@@ -668,7 +668,7 @@ fn test_process_status() {
     #[test]
     fn test_process_output_fail_to_start() {
         match Command::new("/no-binary-by-this-name-should-exist").output() {
-            Err(e) => assert_eq!(e.kind(), ErrorKind::FileNotFound),
+            Err(e) => assert_eq!(e.kind(), ErrorKind::NotFound),
             Ok(..) => panic!()
         }
     }
index 90cc189b9a0f0a3f8c4e93eb4945f9e740263dbb..5e8abfd0a3f8988a9f4a128e0bc233dd90b6aec8 100644 (file)
@@ -30,7 +30,7 @@
 use usize;
 
 // Reexport some of our utilities which are expected by other crates.
-pub use self::util::{default_sched_threads, min_stack, running_on_valgrind};
+pub use self::util::{min_stack, running_on_valgrind};
 pub use self::unwind::{begin_unwind, begin_unwind_fmt};
 
 // Reexport some functionality from liballoc.
index e72fd7b33202dab64a063d2acb39ac67462e25b6..f1c43a07e6e3895ef35cc52369876cc8f0cc7350 100644 (file)
@@ -58,29 +58,6 @@ pub fn min_stack() -> uint {
     return amt;
 }
 
-/// Get's the number of scheduler threads requested by the environment
-/// either `RUST_THREADS` or `num_cpus`.
-#[allow(deprecated)]
-pub fn default_sched_threads() -> uint {
-    use os;
-    match env::var("RUST_THREADS") {
-        Ok(nstr) => {
-            let opt_n: Option<uint> = nstr.parse().ok();
-            match opt_n {
-                Some(n) if n > 0 => n,
-                _ => panic!("`RUST_THREADS` is `{}`, should be a positive integer", nstr)
-            }
-        }
-        Err(..) => {
-            if limit_thread_creation_due_to_osx_and_valgrind() {
-                1
-            } else {
-                os::num_cpus()
-            }
-        }
-    }
-}
-
 // Indicates whether we should perform expensive sanity checks, including rtassert!
 //
 // FIXME: Once the runtime matures remove the `true` below to turn off rtassert,
index a8cee74828d3496c433f07bcf73b202a32f9d03c..5555eec4f391876ad7227ba501540bec7dd198df 100644 (file)
@@ -139,22 +139,19 @@ pub fn decode_error_kind(errno: i32) -> ErrorKind {
         libc::EPIPE => ErrorKind::BrokenPipe,
         libc::ENOTCONN => ErrorKind::NotConnected,
         libc::ECONNABORTED => ErrorKind::ConnectionAborted,
-        libc::EADDRNOTAVAIL => ErrorKind::ConnectionRefused,
-        libc::EADDRINUSE => ErrorKind::ConnectionRefused,
-        libc::ENOENT => ErrorKind::FileNotFound,
-        libc::EISDIR => ErrorKind::InvalidInput,
+        libc::EADDRNOTAVAIL => ErrorKind::AddrNotAvailable,
+        libc::EADDRINUSE => ErrorKind::AddrInUse,
+        libc::ENOENT => ErrorKind::NotFound,
         libc::EINTR => ErrorKind::Interrupted,
         libc::EINVAL => ErrorKind::InvalidInput,
-        libc::ENOTTY => ErrorKind::MismatchedFileTypeForOperation,
         libc::ETIMEDOUT => ErrorKind::TimedOut,
-        libc::ECANCELED => ErrorKind::TimedOut,
-        libc::consts::os::posix88::EEXIST => ErrorKind::PathAlreadyExists,
+        libc::consts::os::posix88::EEXIST => ErrorKind::AlreadyExists,
 
         // These two constants can have the same value on some systems,
         // but different values on others, so we can't use a match
         // clause
         x if x == libc::EAGAIN || x == libc::EWOULDBLOCK =>
-            ErrorKind::ResourceUnavailable,
+            ErrorKind::WouldBlock,
 
         _ => ErrorKind::Other,
     }
index d02fe79fcdb1f9ea18f93f22ce599f32f38d1009..eeaf4ced07239e16fe0b5b3b83b08bb45a45fe99 100644 (file)
@@ -149,25 +149,21 @@ pub fn decode_error_detailed(errno: i32) -> IoError {
 pub fn decode_error_kind(errno: i32) -> ErrorKind {
     match errno as libc::c_int {
         libc::ERROR_ACCESS_DENIED => ErrorKind::PermissionDenied,
-        libc::ERROR_ALREADY_EXISTS => ErrorKind::PathAlreadyExists,
+        libc::ERROR_ALREADY_EXISTS => ErrorKind::AlreadyExists,
         libc::ERROR_BROKEN_PIPE => ErrorKind::BrokenPipe,
-        libc::ERROR_FILE_NOT_FOUND => ErrorKind::FileNotFound,
-        libc::ERROR_INVALID_FUNCTION => ErrorKind::InvalidInput,
-        libc::ERROR_INVALID_HANDLE => ErrorKind::MismatchedFileTypeForOperation,
-        libc::ERROR_INVALID_NAME => ErrorKind::InvalidInput,
-        libc::ERROR_NOTHING_TO_TERMINATE => ErrorKind::InvalidInput,
+        libc::ERROR_FILE_NOT_FOUND => ErrorKind::NotFound,
         libc::ERROR_NO_DATA => ErrorKind::BrokenPipe,
         libc::ERROR_OPERATION_ABORTED => ErrorKind::TimedOut,
 
         libc::WSAEACCES => ErrorKind::PermissionDenied,
-        libc::WSAEADDRINUSE => ErrorKind::ConnectionRefused,
-        libc::WSAEADDRNOTAVAIL => ErrorKind::ConnectionRefused,
+        libc::WSAEADDRINUSE => ErrorKind::AddrInUse,
+        libc::WSAEADDRNOTAVAIL => ErrorKind::AddrNotAvailable,
         libc::WSAECONNABORTED => ErrorKind::ConnectionAborted,
         libc::WSAECONNREFUSED => ErrorKind::ConnectionRefused,
         libc::WSAECONNRESET => ErrorKind::ConnectionReset,
         libc::WSAEINVAL => ErrorKind::InvalidInput,
         libc::WSAENOTCONN => ErrorKind::NotConnected,
-        libc::WSAEWOULDBLOCK => ErrorKind::ResourceUnavailable,
+        libc::WSAEWOULDBLOCK => ErrorKind::WouldBlock,
 
         _ => ErrorKind::Other,
     }
index c38556b0782196e3bb51f0d59d985bbb8793aeea..c11ffe66e6c392305450dd13706994e6ba3ed812 100644 (file)
@@ -176,6 +176,8 @@ fn to_source_with_hygiene(&self) -> String {
     impl_to_source! { ast::Arg, arg_to_string }
     impl_to_source! { Generics, generics_to_string }
     impl_to_source! { P<ast::Item>, item_to_string }
+    impl_to_source! { P<ast::ImplItem>, impl_item_to_string }
+    impl_to_source! { P<ast::TraitItem>, trait_item_to_string }
     impl_to_source! { P<ast::Stmt>, stmt_to_string }
     impl_to_source! { P<ast::Expr>, expr_to_string }
     impl_to_source! { P<ast::Pat>, pat_to_string }
@@ -308,6 +310,8 @@ fn to_tokens(&self, cx: &ExtCtxt) -> Vec<TokenTree> {
 
     impl_to_tokens! { ast::Ident }
     impl_to_tokens! { P<ast::Item> }
+    impl_to_tokens! { P<ast::ImplItem> }
+    impl_to_tokens! { P<ast::TraitItem> }
     impl_to_tokens! { P<ast::Pat> }
     impl_to_tokens! { ast::Arm }
     impl_to_tokens_lifetime! { &'a [P<ast::Item>] }
index b58c121c5fd54730df170197ef956b41145b95cc..239fea57d94d2ae795f47dc5ba21543818e8aa8d 100644 (file)
@@ -355,6 +355,14 @@ pub fn item_to_string(i: &ast::Item) -> String {
     $to_string(|s| s.print_item(i))
 }
 
+pub fn impl_item_to_string(i: &ast::ImplItem) -> String {
+    $to_string(|s| s.print_impl_item(i))
+}
+
+pub fn trait_item_to_string(i: &ast::TraitItem) -> String {
+    $to_string(|s| s.print_trait_item(i))
+}
+
 pub fn generics_to_string(generics: &ast::Generics) -> String {
     $to_string(|s| s.print_generics(generics))
 }
index 02ddeea46bfc8ad14fcf5f20a0308fa93b5447cc..51decbab8587d1e516279ff98e05dccd3dd6ce91 100644 (file)
@@ -44,6 +44,7 @@
 #![feature(std_misc)]
 #![feature(libc)]
 #![feature(set_stdio)]
+#![feature(os)]
 
 extern crate getopts;
 extern crate serialize;
@@ -338,7 +339,7 @@ fn usage(binary: &str) {
 only those tests that match are run.
 
 By default, all tests are run in parallel. This can be altered with the
-RUST_TEST_TASKS environment variable when running tests (set it to 1).
+RUST_TEST_THRADS environment variable when running tests (set it to 1).
 
 All tests have their standard output and standard error captured by default.
 This can be overridden with the --nocapture flag or the RUST_TEST_NOCAPTURE=1
@@ -841,18 +842,22 @@ fn run_tests<F>(opts: &TestOpts,
     Ok(())
 }
 
+#[allow(deprecated)]
 fn get_concurrency() -> uint {
-    use std::rt;
-    match env::var("RUST_TEST_TASKS") {
+    match env::var("RUST_TEST_THREADS") {
         Ok(s) => {
             let opt_n: Option<uint> = s.parse().ok();
             match opt_n {
                 Some(n) if n > 0 => n,
-                _ => panic!("RUST_TEST_TASKS is `{}`, should be a positive integer.", s)
+                _ => panic!("RUST_TEST_THREADS is `{}`, should be a positive integer.", s)
             }
         }
         Err(..) => {
-            rt::default_sched_threads()
+            if std::rt::util::limit_thread_creation_due_to_osx_and_valgrind() {
+                1
+            } else {
+                std::os::num_cpus()
+            }
         }
     }
 }
index e24ade58a5224e36f33d440f00d19038b6ad1020..5e1070c6dc503d1bc1019eab14dff4a90a16288b 100644 (file)
@@ -462,7 +462,8 @@ fn width(self, is_cjk: bool) -> Option<usize> { charwidth::width(self, is_cjk) }
 }
 
 /// An iterator over the lowercase mapping of a given character, returned from
-/// the `lowercase` method on characters.
+/// the [`to_lowercase` method](../primitive.char.html#method.to_lowercase) on
+/// characters.
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct ToLowercase(Option<char>);
 
@@ -473,7 +474,8 @@ fn next(&mut self) -> Option<char> { self.0.take() }
 }
 
 /// An iterator over the uppercase mapping of a given character, returned from
-/// the `uppercase` method on characters.
+/// the [`to_uppercase` method](../primitive.char.html#method.to_uppercase) on
+/// characters.
 #[stable(feature = "rust1", since = "1.0.0")]
 pub struct ToUppercase(Option<char>);
 
diff --git a/src/test/auxiliary/crate_with_invalid_spans.rs b/src/test/auxiliary/crate_with_invalid_spans.rs
new file mode 100644 (file)
index 0000000..b37533d
--- /dev/null
@@ -0,0 +1,30 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![crate_type = "rlib"]
+// no-prefer-dynamic
+
+// compile-flags: -g
+
+#[macro_use]
+mod crate_with_invalid_spans_macros;
+
+pub fn exported_generic<T>(x: T, y: u32) -> (T, u32) {
+    // Using the add1 macro will produce an invalid span, because the `y` passed
+    // to the macro will have a span from this file, but the rest of the code
+    // generated from the macro will have spans from the macro-defining file.
+    // The AST node for the (1 + y) expression generated by the macro will then
+    // take it's `lo` span bound from the `1` literal in the macro-defining file
+    // and it's `hi` bound from `y` in this file, which should be lower than the
+    // `lo` and even lower than the lower bound of the FileMap it is supposedly
+    // contained in because the FileMap for this file was allocated earlier than
+    // the FileMap of the macro-defining file.
+    return (x, add1!(y));
+}
diff --git a/src/test/auxiliary/crate_with_invalid_spans_macros.rs b/src/test/auxiliary/crate_with_invalid_spans_macros.rs
new file mode 100644 (file)
index 0000000..112315a
--- /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.
+
+macro_rules! add1 {
+    ($e:expr) => ({
+        let a = 1 + $e;
+        let b = $e + 1;
+        a + b - 1
+    })
+}
index 8c9cd2d63cb4758f4c29f40e3e2435294872a126..94ed641c79c9372cabcf34a107356b5e2bc780cc 100644 (file)
@@ -8,12 +8,12 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// This checks that RUST_TEST_TASKS not being 1, 2, ... is detected
+// This checks that RUST_TEST_THREADS not being 1, 2, ... is detected
 // properly.
 
 // error-pattern:should be a positive integer
 // compile-flags: --test
-// exec-env:RUST_TEST_TASKS=foo
+// exec-env:RUST_TEST_THREADS=foo
 // ignore-pretty: does not work well with `--test`
 
 #[test]
diff --git a/src/test/run-make/rustdoc-src-links/Makefile b/src/test/run-make/rustdoc-src-links/Makefile
new file mode 100644 (file)
index 0000000..419603e
--- /dev/null
@@ -0,0 +1,5 @@
+-include ../tools.mk
+all:
+       $(HOST_RPATH_ENV) $(RUSTDOC) -w html -o $(TMPDIR)/doc foo.rs
+       $(HTMLDOCCK) $(TMPDIR)/doc foo.rs
+       $(HTMLDOCCK) $(TMPDIR)/doc qux/mod.rs
diff --git a/src/test/run-make/rustdoc-src-links/foo.rs b/src/test/run-make/rustdoc-src-links/foo.rs
new file mode 100644 (file)
index 0000000..9a964f1
--- /dev/null
@@ -0,0 +1,43 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![crate_name = "foo"]
+
+//! Dox
+// @has src/foo/foo.rs.html
+// @has foo/index.html '//a/@href' '../src/foo/foo.rs.html'
+
+pub mod qux;
+
+// @has foo/bar/index.html '//a/@href' '../../src/foo/foo.rs.html'
+pub mod bar {
+
+    /// Dox
+    // @has foo/bar/baz/index.html '//a/@href' '../../../src/foo/foo.rs.html'
+    pub mod baz {
+        /// Dox
+        // @has foo/bar/baz/fn.baz.html '//a/@href' '../../../src/foo/foo.rs.html'
+        pub fn baz() { }
+    }
+
+    /// Dox
+    // @has foo/bar/trait.Foobar.html '//a/@href' '../../src/foo/foo.rs.html'
+    pub trait Foobar { fn dummy(&self) { } }
+
+    // @has foo/bar/struct.Foo.html '//a/@href' '../../src/foo/foo.rs.html'
+    pub struct Foo { x: i32, y: u32 }
+
+    // @has foo/bar/fn.prawns.html '//a/@href' '../../src/foo/foo.rs.html'
+    pub fn prawns((a, b): (i32, u32), Foo { x, y }: Foo) { }
+}
+
+/// Dox
+// @has foo/fn.modfn.html '//a/@href' '../src/foo/foo.rs.html'
+pub fn modfn() { }
diff --git a/src/test/run-make/rustdoc-src-links/qux/mod.rs b/src/test/run-make/rustdoc-src-links/qux/mod.rs
new file mode 100644 (file)
index 0000000..9b1563d
--- /dev/null
@@ -0,0 +1,39 @@
+// 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.
+
+//! Dox
+// @has src/foo/qux/mod.rs.html
+// @has foo/qux/index.html '//a/@href' '../../src/foo/qux/mod.rs.html'
+
+// @has foo/qux/bar/index.html '//a/@href' '../../../src/foo/qux/mod.rs.html'
+pub mod bar {
+
+    /// Dox
+    // @has foo/qux/bar/baz/index.html '//a/@href' '../../../../src/foo/qux/mod.rs.html'
+    pub mod baz {
+        /// Dox
+        // @has foo/qux/bar/baz/fn.baz.html '//a/@href' '../../../../src/foo/qux/mod.rs.html'
+        pub fn baz() { }
+    }
+
+    /// Dox
+    // @has foo/qux/bar/trait.Foobar.html '//a/@href' '../../../src/foo/qux/mod.rs.html'
+    pub trait Foobar { fn dummy(&self) { } }
+
+    // @has foo/qux/bar/struct.Foo.html '//a/@href' '../../../src/foo/qux/mod.rs.html'
+    pub struct Foo { x: i32, y: u32 }
+
+    // @has foo/qux/bar/fn.prawns.html '//a/@href' '../../../src/foo/qux/mod.rs.html'
+    pub fn prawns((a, b): (i32, u32), Foo { x, y }: Foo) { }
+}
+
+/// Dox
+// @has foo/qux/fn.modfn.html '//a/@href' '../../src/foo/qux/mod.rs.html'
+pub fn modfn() { }
diff --git a/src/test/run-pass/import-crate-with-invalid-spans.rs b/src/test/run-pass/import-crate-with-invalid-spans.rs
new file mode 100644 (file)
index 0000000..a949f25
--- /dev/null
@@ -0,0 +1,20 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// aux-build:crate_with_invalid_spans.rs
+
+extern crate crate_with_invalid_spans;
+
+fn main() {
+    // The AST of `exported_generic` stored in crate_with_invalid_spans's
+    // metadata should contain an invalid span where span.lo > span.hi.
+    // Let's make sure the compiler doesn't crash when encountering this.
+    let _ = crate_with_invalid_spans::exported_generic(32u32, 7u32);
+}
index d1a3edcfbc52931cb341ed9bf6c2dc0fae0429ec..5462a996f73d974d071a4ca31b6845cc68228dc1 100644 (file)
@@ -10,7 +10,7 @@
 
 // ignore-pretty
 // compile-flags:--test
-// exec-env:RUST_TEST_TASKS=1
+// exec-env:RUST_TEST_THREADS=1
 
 // Tests for the connect_timeout() function on a TcpStream. This runs with only
 // one test task to ensure that errors are timeouts, not file descriptor