Auto merge of #34720 - Manishearth:rollup, r=Manishearth

Rollup of 9 pull requests

- Successful merges: #34097, #34456, #34610, #34612, #34659, #34688, #34691, #34699, #34700
- Failed merges:
This commit is contained in:
bors 2016-07-08 05:24:43 -07:00 committed by GitHub
commit e7751e436b
8 changed files with 84 additions and 90 deletions

View File

@ -41,8 +41,9 @@ they get set in the [`[features]` section][features] of your `Cargo.toml`:
# no features by default # no features by default
default = [] default = []
# The “secure-password” feature depends on the bcrypt package. # Add feature "foo" here, then you can use it.
secure-password = ["bcrypt"] # Our "foo" feature depends on nothing else.
foo = []
``` ```
When you do this, Cargo passes along a flag to `rustc`: When you do this, Cargo passes along a flag to `rustc`:

View File

@ -11,7 +11,7 @@ an Internet connection to run the commands in this section, as well be
downloading Rust from the Internet. downloading Rust from the Internet.
Well be showing off a number of commands using a terminal, and those lines all Well be showing off a number of commands using a terminal, and those lines all
start with `$`. We don't need to type in the `$`s, they are there to indicate start with `$`. You don't need to type in the `$`s, they are there to indicate
the start of each command. Well see many tutorials and examples around the web the start of each command. Well see many tutorials and examples around the web
that follow this convention: `$` for commands run as our regular user, and `#` that follow this convention: `$` for commands run as our regular user, and `#`
for commands we should be running as an administrator. for commands we should be running as an administrator.
@ -159,9 +159,11 @@ You should see the version number, commit hash, and commit date.
If you do, Rust has been installed successfully! Congrats! If you do, Rust has been installed successfully! Congrats!
If you don't and you're on Windows, check that Rust is in your %PATH% system If you don't and you're on Windows, check that Rust is in your %PATH% system
variable. If it isn't, run the installer again, select "Change" on the "Change, variable: `$ echo %PATH%`. If it isn't, run the installer again, select "Change"
repair, or remove installation" page and ensure "Add to PATH" is installed on on the "Change, repair, or remove installation" page and ensure "Add to PATH" is
the local hard drive. installed on the local hard drive. If you need to configure your path manually,
you can find the Rust executables in a directory like
`"C:\Program Files\Rust stable GNU 1.x\bin"`.
Rust does not do its own linking, and so youll need to have a linker Rust does not do its own linking, and so youll need to have a linker
installed. Doing so will depend on your specific system, consult its installed. Doing so will depend on your specific system, consult its
@ -339,7 +341,8 @@ On Windows, you'd enter:
```bash ```bash
$ dir $ dir
main.exe main.rs main.exe
main.rs
``` ```
This shows we have two files: the source code, with an `.rs` extension, and the This shows we have two files: the source code, with an `.rs` extension, and the
@ -347,7 +350,7 @@ executable (`main.exe` on Windows, `main` everywhere else). All that's left to
do from here is run the `main` or `main.exe` file, like this: do from here is run the `main` or `main.exe` file, like this:
```bash ```bash
$ ./main # or main.exe on Windows $ ./main # or .\main.exe on Windows
``` ```
If *main.rs* were your "Hello, world!" program, this would print `Hello, If *main.rs* were your "Hello, world!" program, this would print `Hello,

View File

@ -10,7 +10,8 @@
#![allow(deprecated)] #![allow(deprecated)]
//! Thread-local reference-counted boxes (the `Rc<T>` type). //! Unsynchronized reference-counted boxes (the `Rc<T>` type) which are usable
//! only within a single thread.
//! //!
//! The `Rc<T>` type provides shared ownership of an immutable value. //! The `Rc<T>` type provides shared ownership of an immutable value.
//! Destruction is deterministic, and will occur as soon as the last owner is //! Destruction is deterministic, and will occur as soon as the last owner is

View File

@ -371,13 +371,16 @@ pub trait Extend<A> {
/// Basic usage: /// Basic usage:
/// ///
/// ``` /// ```
/// let numbers = vec![1, 2, 3]; /// let numbers = vec![1, 2, 3, 4, 5, 6];
/// ///
/// let mut iter = numbers.iter(); /// let mut iter = numbers.iter();
/// ///
/// assert_eq!(Some(&1), iter.next()); /// assert_eq!(Some(&1), iter.next());
/// assert_eq!(Some(&3), iter.next_back()); /// assert_eq!(Some(&6), iter.next_back());
/// assert_eq!(Some(&2), iter.next_back()); /// assert_eq!(Some(&5), iter.next_back());
/// assert_eq!(Some(&2), iter.next());
/// assert_eq!(Some(&3), iter.next());
/// assert_eq!(Some(&4), iter.next());
/// assert_eq!(None, iter.next()); /// assert_eq!(None, iter.next());
/// assert_eq!(None, iter.next_back()); /// assert_eq!(None, iter.next_back());
/// ``` /// ```
@ -395,13 +398,16 @@ pub trait DoubleEndedIterator: Iterator {
/// Basic usage: /// Basic usage:
/// ///
/// ``` /// ```
/// let numbers = vec![1, 2, 3]; /// let numbers = vec![1, 2, 3, 4, 5, 6];
/// ///
/// let mut iter = numbers.iter(); /// let mut iter = numbers.iter();
/// ///
/// assert_eq!(Some(&1), iter.next()); /// assert_eq!(Some(&1), iter.next());
/// assert_eq!(Some(&3), iter.next_back()); /// assert_eq!(Some(&6), iter.next_back());
/// assert_eq!(Some(&2), iter.next_back()); /// assert_eq!(Some(&5), iter.next_back());
/// assert_eq!(Some(&2), iter.next());
/// assert_eq!(Some(&3), iter.next());
/// assert_eq!(Some(&4), iter.next());
/// assert_eq!(None, iter.next()); /// assert_eq!(None, iter.next());
/// assert_eq!(None, iter.next_back()); /// assert_eq!(None, iter.next_back());
/// ``` /// ```

View File

@ -214,6 +214,30 @@ impl Error {
} }
/// Creates a new instance of an `Error` from a particular OS error code. /// Creates a new instance of an `Error` from a particular OS error code.
///
/// # Examples
///
/// On Linux:
///
/// ```
/// # if cfg!(target_os = "linux") {
/// use std::io;
///
/// let error = io::Error::from_raw_os_error(98);
/// assert_eq!(error.kind(), io::ErrorKind::AddrInUse);
/// # }
/// ```
///
/// On Windows:
///
/// ```
/// # if cfg!(windows) {
/// use std::io;
///
/// let error = io::Error::from_raw_os_error(10048);
/// assert_eq!(error.kind(), io::ErrorKind::AddrInUse);
/// # }
/// ```
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
pub fn from_raw_os_error(code: i32) -> Error { pub fn from_raw_os_error(code: i32) -> Error {
Error { repr: Repr::Os(code) } Error { repr: Repr::Os(code) }

View File

@ -1529,8 +1529,7 @@ impl Path {
/// The final component of the path, if it is a normal file. /// The final component of the path, if it is a normal file.
/// ///
/// If the path terminates in `.`, `..`, or consists solely of a root of /// If the path terminates in `..`, `file_name` will return `None`.
/// prefix, `file_name` will return `None`.
/// ///
/// # Examples /// # Examples
/// ///
@ -1543,6 +1542,17 @@ impl Path {
/// ///
/// assert_eq!(Some(os_str), path.file_name()); /// assert_eq!(Some(os_str), path.file_name());
/// ``` /// ```
///
/// # Other examples
///
/// ```
/// use std::path::Path;
/// use std::ffi::OsStr;
///
/// assert_eq!(Some(OsStr::new("foo.txt")), Path::new("foo.txt/.").file_name());
/// assert_eq!(Some(OsStr::new("foo.txt")), Path::new("foo.txt/.//").file_name());
/// assert_eq!(None, Path::new("foo.txt/..").file_name());
/// ```
#[stable(feature = "rust1", since = "1.0.0")] #[stable(feature = "rust1", since = "1.0.0")]
pub fn file_name(&self) -> Option<&OsStr> { pub fn file_name(&self) -> Option<&OsStr> {
self.components().next_back().and_then(|p| { self.components().next_back().and_then(|p| {

View File

@ -152,9 +152,19 @@ pub fn lookup_host(host: &str) -> io::Result<LookupHost> {
init(); init();
let c_host = CString::new(host)?; let c_host = CString::new(host)?;
let hints = c::addrinfo {
ai_flags: 0,
ai_family: 0,
ai_socktype: c::SOCK_STREAM,
ai_protocol: 0,
ai_addrlen: 0,
ai_addr: ptr::null_mut(),
ai_canonname: ptr::null_mut(),
ai_next: ptr::null_mut()
};
let mut res = ptr::null_mut(); let mut res = ptr::null_mut();
unsafe { unsafe {
cvt_gai(c::getaddrinfo(c_host.as_ptr(), ptr::null(), ptr::null(), cvt_gai(c::getaddrinfo(c_host.as_ptr(), ptr::null(), &hints,
&mut res))?; &mut res))?;
Ok(LookupHost { original: res, cur: res }) Ok(LookupHost { original: res, cur: res })
} }

View File

@ -495,64 +495,6 @@ impl<'a> Parser<'a> {
} }
} }
/// Check for erroneous `ident { }`; if matches, signal error and
/// recover (without consuming any expected input token). Returns
/// true if and only if input was consumed for recovery.
pub fn check_for_erroneous_unit_struct_expecting(&mut self,
expected: &[token::Token])
-> bool {
if self.token == token::OpenDelim(token::Brace)
&& expected.iter().all(|t| *t != token::OpenDelim(token::Brace))
&& self.look_ahead(1, |t| *t == token::CloseDelim(token::Brace)) {
// matched; signal non-fatal error and recover.
let span = self.span;
self.span_err(span, "unit-like struct construction is written with no trailing `{ }`");
self.eat(&token::OpenDelim(token::Brace));
self.eat(&token::CloseDelim(token::Brace));
true
} else {
false
}
}
/// Commit to parsing a complete expression `e` expected to be
/// followed by some token from the set edible + inedible. Recover
/// from anticipated input errors, discarding erroneous characters.
pub fn commit_expr(&mut self, e: &Expr, edible: &[token::Token],
inedible: &[token::Token]) -> PResult<'a, ()> {
debug!("commit_expr {:?}", e);
if let ExprKind::Path(..) = e.node {
// might be unit-struct construction; check for recoverableinput error.
let expected = edible.iter()
.cloned()
.chain(inedible.iter().cloned())
.collect::<Vec<_>>();
self.check_for_erroneous_unit_struct_expecting(&expected[..]);
}
self.expect_one_of(edible, inedible)
}
pub fn commit_expr_expecting(&mut self, e: &Expr, edible: token::Token) -> PResult<'a, ()> {
self.commit_expr(e, &[edible], &[])
}
/// Commit to parsing a complete statement `s`, which expects to be
/// followed by some token from the set edible + inedible. Check
/// for recoverable input errors, discarding erroneous characters.
pub fn commit_stmt(&mut self, edible: &[token::Token],
inedible: &[token::Token]) -> PResult<'a, ()> {
if self.last_token
.as_ref()
.map_or(false, |t| t.is_ident() || t.is_path()) {
let expected = edible.iter()
.cloned()
.chain(inedible.iter().cloned())
.collect::<Vec<_>>();
self.check_for_erroneous_unit_struct_expecting(&expected);
}
self.expect_one_of(edible, inedible)
}
/// returns the span of expr, if it was not interpolated or the span of the interpolated token /// returns the span of expr, if it was not interpolated or the span of the interpolated token
fn interpolated_or_expr_span(&self, fn interpolated_or_expr_span(&self,
expr: PResult<'a, P<Expr>>) expr: PResult<'a, P<Expr>>)
@ -1247,7 +1189,7 @@ impl<'a> Parser<'a> {
let default = if self.check(&token::Eq) { let default = if self.check(&token::Eq) {
self.bump(); self.bump();
let expr = self.parse_expr()?; let expr = self.parse_expr()?;
self.commit_expr_expecting(&expr, token::Semi)?; self.expect(&token::Semi)?;
Some(expr) Some(expr)
} else { } else {
self.expect(&token::Semi)?; self.expect(&token::Semi)?;
@ -2195,8 +2137,7 @@ impl<'a> Parser<'a> {
let mut trailing_comma = false; let mut trailing_comma = false;
while self.token != token::CloseDelim(token::Paren) { while self.token != token::CloseDelim(token::Paren) {
es.push(self.parse_expr()?); es.push(self.parse_expr()?);
self.commit_expr(&es.last().unwrap(), &[], self.expect_one_of(&[], &[token::Comma, token::CloseDelim(token::Paren)])?;
&[token::Comma, token::CloseDelim(token::Paren)])?;
if self.check(&token::Comma) { if self.check(&token::Comma) {
trailing_comma = true; trailing_comma = true;
@ -2407,9 +2348,8 @@ impl<'a> Parser<'a> {
} }
} }
match self.commit_expr(&fields.last().unwrap().expr, match self.expect_one_of(&[token::Comma],
&[token::Comma], &[token::CloseDelim(token::Brace)]) {
&[token::CloseDelim(token::Brace)]) {
Ok(()) => {} Ok(()) => {}
Err(mut e) => { Err(mut e) => {
e.emit(); e.emit();
@ -2662,7 +2602,7 @@ impl<'a> Parser<'a> {
self.bump(); self.bump();
let ix = self.parse_expr()?; let ix = self.parse_expr()?;
hi = self.span.hi; hi = self.span.hi;
self.commit_expr_expecting(&ix, token::CloseDelim(token::Bracket))?; self.expect(&token::CloseDelim(token::Bracket))?;
let index = self.mk_index(e, ix); let index = self.mk_index(e, ix);
e = self.mk_expr(lo, hi, index, ThinVec::new()) e = self.mk_expr(lo, hi, index, ThinVec::new())
} }
@ -3329,8 +3269,7 @@ impl<'a> Parser<'a> {
let lo = self.last_span.lo; let lo = self.last_span.lo;
let discriminant = self.parse_expr_res(Restrictions::RESTRICTION_NO_STRUCT_LITERAL, let discriminant = self.parse_expr_res(Restrictions::RESTRICTION_NO_STRUCT_LITERAL,
None)?; None)?;
if let Err(mut e) = self.commit_expr_expecting(&discriminant, if let Err(mut e) = self.expect(&token::OpenDelim(token::Brace)) {
token::OpenDelim(token::Brace)) {
if self.token == token::Token::Semi { if self.token == token::Token::Semi {
e.span_note(match_span, "did you mean to remove this `match` keyword?"); e.span_note(match_span, "did you mean to remove this `match` keyword?");
} }
@ -3376,7 +3315,7 @@ impl<'a> Parser<'a> {
&& self.token != token::CloseDelim(token::Brace); && self.token != token::CloseDelim(token::Brace);
if require_comma { if require_comma {
self.commit_expr(&expr, &[token::Comma], &[token::CloseDelim(token::Brace)])?; self.expect_one_of(&[token::Comma], &[token::CloseDelim(token::Brace)])?;
} else { } else {
self.eat(&token::Comma); self.eat(&token::Comma);
} }
@ -4118,7 +4057,7 @@ impl<'a> Parser<'a> {
_ => { // all other kinds of statements: _ => { // all other kinds of statements:
let mut hi = span.hi; let mut hi = span.hi;
if classify::stmt_ends_with_semi(&node) { if classify::stmt_ends_with_semi(&node) {
self.commit_stmt(&[token::Semi], &[])?; self.expect(&token::Semi)?;
hi = self.last_span.hi; hi = self.last_span.hi;
} }
@ -4196,7 +4135,7 @@ impl<'a> Parser<'a> {
if classify::expr_requires_semi_to_be_stmt(&e) { if classify::expr_requires_semi_to_be_stmt(&e) {
// Just check for errors and recover; do not eat semicolon yet. // Just check for errors and recover; do not eat semicolon yet.
if let Err(mut e) = if let Err(mut e) =
self.commit_stmt(&[], &[token::Semi, token::CloseDelim(token::Brace)]) self.expect_one_of(&[], &[token::Semi, token::CloseDelim(token::Brace)])
{ {
e.emit(); e.emit();
self.recover_stmt(); self.recover_stmt();
@ -4863,7 +4802,7 @@ impl<'a> Parser<'a> {
let typ = self.parse_ty_sum()?; let typ = self.parse_ty_sum()?;
self.expect(&token::Eq)?; self.expect(&token::Eq)?;
let expr = self.parse_expr()?; let expr = self.parse_expr()?;
self.commit_expr_expecting(&expr, token::Semi)?; self.expect(&token::Semi)?;
(name, ast::ImplItemKind::Const(typ, expr)) (name, ast::ImplItemKind::Const(typ, expr))
} else { } else {
let (name, inner_attrs, node) = self.parse_impl_method(&vis)?; let (name, inner_attrs, node) = self.parse_impl_method(&vis)?;
@ -5287,7 +5226,7 @@ impl<'a> Parser<'a> {
let ty = self.parse_ty_sum()?; let ty = self.parse_ty_sum()?;
self.expect(&token::Eq)?; self.expect(&token::Eq)?;
let e = self.parse_expr()?; let e = self.parse_expr()?;
self.commit_expr_expecting(&e, token::Semi)?; self.expect(&token::Semi)?;
let item = match m { let item = match m {
Some(m) => ItemKind::Static(ty, m, e), Some(m) => ItemKind::Static(ty, m, e),
None => ItemKind::Const(ty, e), None => ItemKind::Const(ty, e),