From 302de36c8f647bd394d75f1ab28255f00c8d703a Mon Sep 17 00:00:00 2001 From: Steve Klabnik <steve@steveklabnik.com> Date: Tue, 13 Oct 2015 13:49:53 -0400 Subject: [PATCH 1/5] Properly link up iterator documentation Due to the way iterators work, the std::iter module is chock full of structs that you, humble Rust programmer, will never actually use. However, they have URLs, and therefore get linked to, because they are real structs that do exist. So, rather than just have a tiny sentence about each one of them, this patch adds links back to the functions and methods on Iterator which actually create the structs, where helpful documentation already exists. --- src/libcore/iter.rs | 157 ++++++++++++++++++++++++++++++++++++++------ 1 file changed, 137 insertions(+), 20 deletions(-) diff --git a/src/libcore/iter.rs b/src/libcore/iter.rs index 2f12579d67411..d54817f5201e1 100644 --- a/src/libcore/iter.rs +++ b/src/libcore/iter.rs @@ -1618,7 +1618,13 @@ impl<B, I: ExactSizeIterator, F> ExactSizeIterator for Map<I, F> where impl<A, B> ExactSizeIterator for Zip<A, B> where A: ExactSizeIterator, B: ExactSizeIterator {} -/// An double-ended iterator with the direction inverted +/// An double-ended iterator with the direction inverted. +/// +/// This `struct` is created by the [`rev()`] method on [`Iterator`]. See its +/// documentation for more. +/// +/// [`rev()`]: trait.Iterator.html#method.rev +/// [`Iterator`]: trait.Iterator.html #[derive(Clone)] #[must_use = "iterator adaptors are lazy and do nothing unless consumed"] #[stable(feature = "rust1", since = "1.0.0")] @@ -1642,7 +1648,13 @@ impl<I> DoubleEndedIterator for Rev<I> where I: DoubleEndedIterator { fn next_back(&mut self) -> Option<<I as Iterator>::Item> { self.iter.next() } } -/// An iterator that clones the elements of an underlying iterator +/// An iterator that clones the elements of an underlying iterator. +/// +/// This `struct` is created by the [`cloned()`] method on [`Iterator`]. See its +/// documentation for more. +/// +/// [`cloned()`]: trait.Iterator.html#method.cloned +/// [`Iterator`]: trait.Iterator.html #[stable(feature = "iter_cloned", since = "1.1.0")] #[must_use = "iterator adaptors are lazy and do nothing unless consumed"] #[derive(Clone)] @@ -1679,7 +1691,13 @@ impl<'a, I, T: 'a> ExactSizeIterator for Cloned<I> where I: ExactSizeIterator<Item=&'a T>, T: Clone {} -/// An iterator that repeats endlessly +/// An iterator that repeats endlessly. +/// +/// This `struct` is created by the [`cycle()`] method on [`Iterator`]. See its +/// documentation for more. +/// +/// [`cycle()`]: trait.Iterator.html#method.cycle +/// [`Iterator`]: trait.Iterator.html #[derive(Clone)] #[must_use = "iterator adaptors are lazy and do nothing unless consumed"] #[stable(feature = "rust1", since = "1.0.0")] @@ -1711,7 +1729,13 @@ impl<I> Iterator for Cycle<I> where I: Clone + Iterator { } } -/// An iterator that strings two iterators together +/// An iterator that strings two iterators together. +/// +/// This `struct` is created by the [`chain()`] method on [`Iterator`]. See its +/// documentation for more. +/// +/// [`chain()`]: trait.Iterator.html#method.chain +/// [`Iterator`]: trait.Iterator.html #[derive(Clone)] #[must_use = "iterator adaptors are lazy and do nothing unless consumed"] #[stable(feature = "rust1", since = "1.0.0")] @@ -1849,7 +1873,13 @@ impl<A, B> DoubleEndedIterator for Chain<A, B> where } } -/// An iterator that iterates two other iterators simultaneously +/// An iterator that iterates two other iterators simultaneously. +/// +/// This `struct` is created by the [`zip()`] method on [`Iterator`]. See its +/// documentation for more. +/// +/// [`zip()`]: trait.Iterator.html#method.zip +/// [`Iterator`]: trait.Iterator.html #[derive(Clone)] #[must_use = "iterator adaptors are lazy and do nothing unless consumed"] #[stable(feature = "rust1", since = "1.0.0")] @@ -1915,7 +1945,13 @@ impl<A, B> DoubleEndedIterator for Zip<A, B> where } } -/// An iterator that maps the values of `iter` with `f` +/// An iterator that maps the values of `iter` with `f`. +/// +/// This `struct` is created by the [`map()`] method on [`Iterator`]. See its +/// documentation for more. +/// +/// [`map()`]: trait.Iterator.html#method.map +/// [`Iterator`]: trait.Iterator.html #[must_use = "iterator adaptors are lazy and do nothing unless consumed"] #[stable(feature = "rust1", since = "1.0.0")] #[derive(Clone)] @@ -1949,7 +1985,13 @@ impl<B, I: DoubleEndedIterator, F> DoubleEndedIterator for Map<I, F> where } } -/// An iterator that filters the elements of `iter` with `predicate` +/// An iterator that filters the elements of `iter` with `predicate`. +/// +/// This `struct` is created by the [`filter()`] method on [`Iterator`]. See its +/// documentation for more. +/// +/// [`filter()`]: trait.Iterator.html#method.filter +/// [`Iterator`]: trait.Iterator.html #[must_use = "iterator adaptors are lazy and do nothing unless consumed"] #[stable(feature = "rust1", since = "1.0.0")] #[derive(Clone)] @@ -1994,7 +2036,13 @@ impl<I: DoubleEndedIterator, P> DoubleEndedIterator for Filter<I, P> } } -/// An iterator that uses `f` to both filter and map elements from `iter` +/// An iterator that uses `f` to both filter and map elements from `iter`. +/// +/// This `struct` is created by the [`filter_map()`] method on [`Iterator`]. See its +/// documentation for more. +/// +/// [`filter_map()`]: trait.Iterator.html#method.filter_map +/// [`Iterator`]: trait.Iterator.html #[must_use = "iterator adaptors are lazy and do nothing unless consumed"] #[stable(feature = "rust1", since = "1.0.0")] #[derive(Clone)] @@ -2041,7 +2089,13 @@ impl<B, I: DoubleEndedIterator, F> DoubleEndedIterator for FilterMap<I, F> } } -/// An iterator that yields the current count and the element during iteration +/// An iterator that yields the current count and the element during iteration. +/// +/// This `struct` is created by the [`enumerate()`] method on [`Iterator`]. See its +/// documentation for more. +/// +/// [`enumerate()`]: trait.Iterator.html#method.enumerate +/// [`Iterator`]: trait.Iterator.html #[derive(Clone)] #[must_use = "iterator adaptors are lazy and do nothing unless consumed"] #[stable(feature = "rust1", since = "1.0.0")] @@ -2108,7 +2162,14 @@ impl<I> DoubleEndedIterator for Enumerate<I> where } } -/// An iterator with a `peek()` that returns an optional reference to the next element. +/// An iterator with a `peek()` that returns an optional reference to the next +/// element. +/// +/// This `struct` is created by the [`peekable()`] method on [`Iterator`]. See its +/// documentation for more. +/// +/// [`peekable()`]: trait.Iterator.html#method.peekable +/// [`Iterator`]: trait.Iterator.html #[derive(Clone)] #[must_use = "iterator adaptors are lazy and do nothing unless consumed"] #[stable(feature = "rust1", since = "1.0.0")] @@ -2190,7 +2251,13 @@ impl<I: Iterator> Peekable<I> { } } -/// An iterator that rejects elements while `predicate` is true +/// An iterator that rejects elements while `predicate` is true. +/// +/// This `struct` is created by the [`skip_while()`] method on [`Iterator`]. See its +/// documentation for more. +/// +/// [`skip_while()`]: trait.Iterator.html#method.skip_while +/// [`Iterator`]: trait.Iterator.html #[must_use = "iterator adaptors are lazy and do nothing unless consumed"] #[stable(feature = "rust1", since = "1.0.0")] #[derive(Clone)] @@ -2224,7 +2291,13 @@ impl<I: Iterator, P> Iterator for SkipWhile<I, P> } } -/// An iterator that only accepts elements while `predicate` is true +/// An iterator that only accepts elements while `predicate` is true. +/// +/// This `struct` is created by the [`take_while()`] method on [`Iterator`]. See its +/// documentation for more. +/// +/// [`take_while()`]: trait.Iterator.html#method.take_while +/// [`Iterator`]: trait.Iterator.html #[must_use = "iterator adaptors are lazy and do nothing unless consumed"] #[stable(feature = "rust1", since = "1.0.0")] #[derive(Clone)] @@ -2264,6 +2337,12 @@ impl<I: Iterator, P> Iterator for TakeWhile<I, P> } /// An iterator that skips over `n` elements of `iter`. +/// +/// This `struct` is created by the [`skip()`] method on [`Iterator`]. See its +/// documentation for more. +/// +/// [`skip()`]: trait.Iterator.html#method.skip +/// [`Iterator`]: trait.Iterator.html #[derive(Clone)] #[must_use = "iterator adaptors are lazy and do nothing unless consumed"] #[stable(feature = "rust1", since = "1.0.0")] @@ -2338,6 +2417,12 @@ impl<I> Iterator for Skip<I> where I: Iterator { impl<I> ExactSizeIterator for Skip<I> where I: ExactSizeIterator {} /// An iterator that only iterates over the first `n` iterations of `iter`. +/// +/// This `struct` is created by the [`take()`] method on [`Iterator`]. See its +/// documentation for more. +/// +/// [`take()`]: trait.Iterator.html#method.take +/// [`Iterator`]: trait.Iterator.html #[derive(Clone)] #[must_use = "iterator adaptors are lazy and do nothing unless consumed"] #[stable(feature = "rust1", since = "1.0.0")] @@ -2393,7 +2478,13 @@ impl<I> Iterator for Take<I> where I: Iterator{ impl<I> ExactSizeIterator for Take<I> where I: ExactSizeIterator {} -/// An iterator to maintain state while iterating another iterator +/// An iterator to maintain state while iterating another iterator. +/// +/// This `struct` is created by the [`scan()`] method on [`Iterator`]. See its +/// documentation for more. +/// +/// [`scan()`]: trait.Iterator.html#method.scan +/// [`Iterator`]: trait.Iterator.html #[must_use = "iterator adaptors are lazy and do nothing unless consumed"] #[stable(feature = "rust1", since = "1.0.0")] #[derive(Clone)] @@ -2422,9 +2513,14 @@ impl<B, I, St, F> Iterator for Scan<I, St, F> where } } -/// An iterator that maps each element to an iterator, -/// and yields the elements of the produced iterators +/// An iterator that maps each element to an iterator, and yields the elements +/// of the produced iterators. /// +/// This `struct` is created by the [`flat_map()`] method on [`Iterator`]. See its +/// documentation for more. +/// +/// [`flat_map()`]: trait.Iterator.html#method.flat_map +/// [`Iterator`]: trait.Iterator.html #[must_use = "iterator adaptors are lazy and do nothing unless consumed"] #[stable(feature = "rust1", since = "1.0.0")] #[derive(Clone)] @@ -2493,8 +2589,11 @@ impl<I: DoubleEndedIterator, U, F> DoubleEndedIterator for FlatMap<I, U, F> wher /// An iterator that yields `None` forever after the underlying iterator /// yields `None` once. /// -/// These can be created through -/// [`iter.fuse()`](trait.Iterator.html#method.fuse). +/// This `struct` is created by the [`fuse()`] method on [`Iterator`]. See its +/// documentation for more. +/// +/// [`fuse()`]: trait.Iterator.html#method.fuse +/// [`Iterator`]: trait.Iterator.html #[derive(Clone)] #[must_use = "iterator adaptors are lazy and do nothing unless consumed"] #[stable(feature = "rust1", since = "1.0.0")] @@ -2574,8 +2673,14 @@ impl<I> DoubleEndedIterator for Fuse<I> where I: DoubleEndedIterator { #[stable(feature = "rust1", since = "1.0.0")] impl<I> ExactSizeIterator for Fuse<I> where I: ExactSizeIterator {} -/// An iterator that calls a function with a reference to each -/// element before yielding it. +/// An iterator that calls a function with a reference to each element before +/// yielding it. +/// +/// This `struct` is created by the [`inspect()`] method on [`Iterator`]. See its +/// documentation for more. +/// +/// [`inspect()`]: trait.Iterator.html#method.inspect +/// [`Iterator`]: trait.Iterator.html #[must_use = "iterator adaptors are lazy and do nothing unless consumed"] #[stable(feature = "rust1", since = "1.0.0")] #[derive(Clone)] @@ -3009,7 +3114,11 @@ impl<A: Step + One> Iterator for ops::RangeFrom<A> where } } -/// An iterator that repeats an element endlessly +/// An iterator that repeats an element endlessly. +/// +/// This `struct` is created by the [`repeat()`] function. See its documentation for more. +/// +/// [`repeat()`]: fn.repeat.html #[derive(Clone)] #[stable(feature = "rust1", since = "1.0.0")] pub struct Repeat<A> { @@ -3040,6 +3149,10 @@ pub fn repeat<T: Clone>(elt: T) -> Repeat<T> { } /// An iterator that yields nothing. +/// +/// This `struct` is created by the [`empty()`] function. See its documentation for more. +/// +/// [`empty()`]: fn.empty.html #[stable(feature = "iter_empty", since = "1.2.0")] pub struct Empty<T>(marker::PhantomData<T>); @@ -3095,6 +3208,10 @@ pub fn empty<T>() -> Empty<T> { } /// An iterator that yields an element exactly once. +/// +/// This `struct` is created by the [`once()`] function. See its documentation for more. +/// +/// [`once()`]: fn.once.html #[derive(Clone)] #[stable(feature = "iter_once", since = "1.2.0")] pub struct Once<T> { From c3058a25d8794e9e47cc1d1e05c1428512949d57 Mon Sep 17 00:00:00 2001 From: Kevin Yap <me@kevinyap.ca> Date: Sat, 17 Oct 2015 12:34:25 -0700 Subject: [PATCH 2/5] Fix minor issues with std::io docs --- src/libstd/io/mod.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/libstd/io/mod.rs b/src/libstd/io/mod.rs index 166909f20b7e1..ebe50a6e2b8a2 100644 --- a/src/libstd/io/mod.rs +++ b/src/libstd/io/mod.rs @@ -20,11 +20,11 @@ //! //! # Read and Write //! -//! Because they are traits, they're implemented by a number of other types, -//! and you can implement them for your types too. As such, you'll see a -//! few different types of I/O throughout the documentation in this module: -//! `File`s, `TcpStream`s, and sometimes even `Vec<T>`s. For example, `Read` -//! adds a `read()` method, which we can use on `File`s: +//! Because they are traits, `Read` and `Write` are implemented by a number +//! of other types, and you can implement them for your types too. As such, +//! you'll see a few different types of I/O throughout the documentation in +//! this module: `File`s, `TcpStream`s, and sometimes even `Vec<T>`s. For +//! example, `Read` adds a `read()` method, which we can use on `File`s: //! //! ``` //! use std::io; @@ -111,7 +111,7 @@ //! # } //! ``` //! -//! `BufWriter` doesn't add any new ways of writing, it just buffers every call +//! `BufWriter` doesn't add any new ways of writing; it just buffers every call //! to [`write()`][write]: //! //! ``` @@ -165,7 +165,7 @@ //! # } //! ``` //! -//! Of course, using `io::stdout()` directly is less comon than something like +//! Of course, using `io::stdout()` directly is less common than something like //! `println!`. //! //! ## Iterator types From 1e68c91666ab0f88461c62559f0e2aaf1d431b5a Mon Sep 17 00:00:00 2001 From: Stefan O'Rear <stefanor@cox.net> Date: Sat, 17 Oct 2015 17:39:31 -0700 Subject: [PATCH 3/5] Document that Ordering::Relaxed is Monotonic --- src/libcore/sync/atomic.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/libcore/sync/atomic.rs b/src/libcore/sync/atomic.rs index 0f72dcc1281a4..7225b4f6e0d2a 100644 --- a/src/libcore/sync/atomic.rs +++ b/src/libcore/sync/atomic.rs @@ -153,7 +153,8 @@ unsafe impl<T> Sync for AtomicPtr<T> {} #[stable(feature = "rust1", since = "1.0.0")] #[derive(Copy, Clone)] pub enum Ordering { - /// No ordering constraints, only atomic operations. + /// No ordering constraints, only atomic operations. Corresponds to LLVM's + /// `Monotonic` ordering. #[stable(feature = "rust1", since = "1.0.0")] Relaxed, /// When coupled with a store, all previous writes become visible From 19041cde499b6d4b69b394f4d74f96f7ed0a154c Mon Sep 17 00:00:00 2001 From: William Throwe <wtt6@cornell.edu> Date: Sun, 18 Oct 2015 15:24:08 -0400 Subject: [PATCH 4/5] Add a regression test for #29122 (fixed in #29134) --- src/test/run-make/linker-output-non-utf8/Makefile | 12 ++++++++++++ src/test/run-make/linker-output-non-utf8/exec.rs | 6 ++++++ src/test/run-make/linker-output-non-utf8/library.rs | 9 +++++++++ 3 files changed, 27 insertions(+) create mode 100644 src/test/run-make/linker-output-non-utf8/Makefile create mode 100644 src/test/run-make/linker-output-non-utf8/exec.rs create mode 100644 src/test/run-make/linker-output-non-utf8/library.rs diff --git a/src/test/run-make/linker-output-non-utf8/Makefile b/src/test/run-make/linker-output-non-utf8/Makefile new file mode 100644 index 0000000000000..b26940cb1b483 --- /dev/null +++ b/src/test/run-make/linker-output-non-utf8/Makefile @@ -0,0 +1,12 @@ +-include ../tools.mk + +# Make sure we don't ICE if the linker prints a non-UTF-8 error message. + +# The zzz it to allow humans to tab complete or glob this thing. +bad_dir := $(TMPDIR)/zzz$$'\xff' + +all: + $(RUSTC) library.rs + mkdir $(bad_dir) + mv $(call DYLIB,library) $(bad_dir) + LIBRARY_PATH=$(bad_dir) $(RUSTC) exec.rs 2>&1 | grep this_symbol_not_defined diff --git a/src/test/run-make/linker-output-non-utf8/exec.rs b/src/test/run-make/linker-output-non-utf8/exec.rs new file mode 100644 index 0000000000000..6864018d64e97 --- /dev/null +++ b/src/test/run-make/linker-output-non-utf8/exec.rs @@ -0,0 +1,6 @@ +#[link(name="library")] +extern "C" { + fn foo(); +} + +fn main() { unsafe { foo(); } } diff --git a/src/test/run-make/linker-output-non-utf8/library.rs b/src/test/run-make/linker-output-non-utf8/library.rs new file mode 100644 index 0000000000000..1a5138c3c20d6 --- /dev/null +++ b/src/test/run-make/linker-output-non-utf8/library.rs @@ -0,0 +1,9 @@ +#![crate_type = "dylib"] + +extern "C" { + fn this_symbol_not_defined(); +} + +pub extern "C" fn foo() { + unsafe { this_symbol_not_defined(); } +} From e2ecf279b6795d0a86a964fdc7a31c1f3981456f Mon Sep 17 00:00:00 2001 From: "Irving A.J. Rivas Z." <axel.rivas@gmail.com> Date: Mon, 19 Oct 2015 10:02:46 -0400 Subject: [PATCH 5/5] Made the example capable of consistent deadlocking To augment the didactic effect, made placed the thread::sleep_ms call in the last example, so that there will be time for the other locks to happen; without this, I was unable to observe the deadlock in over 1,000 runs when there was no left-handed philosopher. --- src/doc/trpl/dining-philosophers.md | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/doc/trpl/dining-philosophers.md b/src/doc/trpl/dining-philosophers.md index 28702d95b60a7..e81ae4648ad43 100644 --- a/src/doc/trpl/dining-philosophers.md +++ b/src/doc/trpl/dining-philosophers.md @@ -512,6 +512,7 @@ impl Philosopher { fn eat(&self, table: &Table) { let _left = table.forks[self.left].lock().unwrap(); + thread::sleep_ms(150); let _right = table.forks[self.right].lock().unwrap(); println!("{} is eating.", self.name); @@ -597,6 +598,7 @@ We now need to construct those `left` and `right` values, so we add them to ```rust,ignore fn eat(&self, table: &Table) { let _left = table.forks[self.left].lock().unwrap(); + thread::sleep_ms(150); let _right = table.forks[self.right].lock().unwrap(); println!("{} is eating.", self.name); @@ -607,11 +609,14 @@ fn eat(&self, table: &Table) { } ``` -We have two new lines. We’ve also added an argument, `table`. We access the +We have three new lines. We’ve added an argument, `table`. We access the `Table`’s list of forks, and then use `self.left` and `self.right` to access the fork at that particular index. That gives us access to the `Mutex` at that index, and we call `lock()` on it. If the mutex is currently being accessed by -someone else, we’ll block until it becomes available. +someone else, we’ll block until it becomes available. We have also a call to +`thread::sleep_ms` between the moment first fork is picked and the moment the +second forked is picked, as the process of picking up the fork is not +immediate. The call to `lock()` might fail, and if it does, we want to crash. In this case, the error that could happen is that the mutex is [‘poisoned’][poison], @@ -660,7 +665,9 @@ We need to pass in our `left` and `right` values to the constructors for our you look at the pattern, it’s all consistent until the very end. Monsieur Foucault should have `4, 0` as arguments, but instead, has `0, 4`. This is what prevents deadlock, actually: one of our philosophers is left handed! This is -one way to solve the problem, and in my opinion, it’s the simplest. +one way to solve the problem, and in my opinion, it’s the simplest. If you +change the order of the parameters, you will be able to observe the deadlock +taking place. ```rust,ignore let handles: Vec<_> = philosophers.into_iter().map(|p| {