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

This commit is contained in:
bors 2015-03-19 03:19:08 +00:00
commit 0084f92302
25 changed files with 532 additions and 114 deletions

View File

@ -19,7 +19,6 @@
#![feature(unboxed_closures)]
#![feature(std_misc)]
#![feature(test)]
#![feature(core)]
#![feature(path_ext)]
#![deny(warnings)]

View File

@ -2068,7 +2068,7 @@ type int8_t = i8;
item](#language-items) for more details.
- `test` - indicates that this function is a test function, to only be compiled
in case of `--test`.
- `should_fail` - indicates that this test function should panic, inverting the success condition.
- `should_panic` - indicates that this test function should panic, inverting the success condition.
- `cold` - The function is unlikely to be executed, so optimize it (and calls
to it) differently.

View File

@ -562,6 +562,11 @@ place in the hierarchy instead. There's one more special form of `use`: you can
people like to think of `self` as `.` and `super` as `..`, from many shells'
display for the current directory and the parent directory.
Outside of `use`, paths are relative: `foo::bar()` refers to a function inside
of `foo` relative to where we are. If that's prefixed with `::`, as in
`::foo::bar()`, it refers to a different `foo`, an absolute path from your
crate root.
Also, note that we `pub use`d before we declared our `mod`s. Rust requires that
`use` declarations go first.

View File

@ -179,7 +179,7 @@ Because this function will cause a crash, it will never return, and so it has
the type '`!`', which is read "diverges." A diverging function can be used
as any type:
```should_fail
```should_panic
# fn diverges() -> ! {
# panic!("This function never returns!");
# }

View File

@ -129,11 +129,11 @@ $ echo $?
This is useful if you want to integrate `cargo test` into other tooling.
We can invert our test's failure with another attribute: `should_fail`:
We can invert our test's failure with another attribute: `should_panic`:
```rust
#[test]
#[should_fail]
#[should_panic]
fn it_works() {
assert!(false);
}
@ -163,13 +163,13 @@ equality:
```rust
#[test]
#[should_fail]
#[should_panic]
fn it_works() {
assert_eq!("Hello", "world");
}
```
Does this test pass or fail? Because of the `should_fail` attribute, it
Does this test pass or fail? Because of the `should_panic` attribute, it
passes:
```bash
@ -189,15 +189,15 @@ running 0 tests
test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured
```
`should_fail` tests can be fragile, as it's hard to guarantee that the test
`should_panic` tests can be fragile, as it's hard to guarantee that the test
didn't fail for an unexpected reason. To help with this, an optional `expected`
parameter can be added to the `should_fail` attribute. The test harness will
parameter can be added to the `should_panic` attribute. The test harness will
make sure that the failure message contains the provided text. A safer version
of the example above would be:
```
#[test]
#[should_fail(expected = "assertion failed")]
#[should_panic(expected = "assertion failed")]
fn it_works() {
assert_eq!("Hello", "world");
}

View File

@ -16,7 +16,7 @@
//! This macro is implemented in the compiler to emit calls to this module in
//! order to format arguments at runtime into strings and streams.
//!
//! ## Usage
//! # Usage
//!
//! The `format!` macro is intended to be familiar to those coming from C's
//! printf/fprintf functions or Python's `str.format` function. In its current
@ -41,7 +41,7 @@
//! will then parse the format string and determine if the list of arguments
//! provided is suitable to pass to this format string.
//!
//! ### Positional parameters
//! ## Positional parameters
//!
//! Each formatting argument is allowed to specify which value argument it's
//! referencing, and if omitted it is assumed to be "the next argument". For
@ -54,7 +54,7 @@
//! iterator over the argument. Each time a "next argument" specifier is seen,
//! the iterator advances. This leads to behavior like this:
//!
//! ```rust
//! ```
//! format!("{1} {} {0} {}", 1, 2); // => "2 1 1 2"
//! ```
//!
@ -68,7 +68,7 @@
//! compile-time error. You may refer to the same argument more than once in the
//! format string, although it must always be referred to with the same type.
//!
//! ### Named parameters
//! ## Named parameters
//!
//! Rust itself does not have a Python-like equivalent of named parameters to a
//! function, but the `format!` macro is a syntax extension which allows it to
@ -91,7 +91,7 @@
//! arguments which have names. Like with positional parameters, it is illegal
//! to provide named parameters that are unused by the format string.
//!
//! ### Argument types
//! ## Argument types
//!
//! Each argument's type is dictated by the format string. It is a requirement
//! that every argument is only ever referred to by one type. For example, this
@ -105,18 +105,25 @@
//! hexadecimal as well as an
//! octal.
//!
//! There are various parameters which do require a particular type, however.
//! Namely if the syntax `{:.*}` is used, then the number of characters to print
//! precedes the actual object being formatted, and the number of characters
//! must have the type `usize`. Although a `usize` can be printed with `{}`, it is
//! illegal to reference an argument as such. For example this is another
//! There are various parameters which do require a particular type, however. Namely, the `{:.*}`
//! syntax, which sets the number of numbers after the decimal in floating-point types:
//!
//! ```
//! let formatted_number = format!("{:.*}", 2, 1.234567);
//!
//! assert_eq!("1.23", formatted_number)
//! ```
//!
//! If this syntax is used, then the number of characters to print precedes the actual object being
//! formatted, and the number of characters must have the type `usize`. Although a `usize` can be
//! printed with `{}`, it is illegal to reference an argument as such. For example this is another
//! invalid format string:
//!
//! ```text
//! {:.*} {0}
//! ```
//!
//! ### Formatting traits
//! ## Formatting traits
//!
//! When requesting that an argument be formatted with a particular type, you
//! are actually requesting that an argument ascribes to a particular trait.
@ -142,7 +149,7 @@
//! When implementing a format trait for your own type, you will have to
//! implement a method of the signature:
//!
//! ```rust
//! ```
//! # use std::fmt;
//! # struct Foo; // our custom type
//! # impl fmt::Display for Foo {
@ -166,7 +173,7 @@
//! An example of implementing the formatting traits would look
//! like:
//!
//! ```rust
//! ```
//! use std::fmt;
//! use std::f64;
//! use std::num::Float;
@ -211,7 +218,7 @@
//! }
//! ```
//!
//! #### fmt::Display vs fmt::Debug
//! ### fmt::Display vs fmt::Debug
//!
//! These two formatting traits have distinct purposes:
//!
@ -231,7 +238,7 @@
//! assert_eq!(format!("{} {:?}", "foo\n", "bar\n"), "foo\n \"bar\\n\"");
//! ```
//!
//! ### Related macros
//! ## Related macros
//!
//! There are a number of related macros in the `format!` family. The ones that
//! are currently implemented are:
@ -245,7 +252,7 @@
//! format_args! // described below.
//! ```
//!
//! #### `write!`
//! ### `write!`
//!
//! This and `writeln` are two macros which are used to emit the format string
//! to a specified stream. This is used to prevent intermediate allocations of
@ -253,24 +260,25 @@
//! function is actually invoking the `write` function defined in this module.
//! Example usage is:
//!
//! ```rust
//! ```
//! # #![allow(unused_must_use)]
//! let mut w = Vec::new();
//! write!(&mut w, "Hello {}!", "world");
//! ```
//!
//! #### `print!`
//! ### `print!`
//!
//! This and `println` emit their output to stdout. Similarly to the `write!`
//! macro, the goal of these macros is to avoid intermediate allocations when
//! printing output. Example usage is:
//!
//! ```rust
//! ```
//! print!("Hello {}!", "world");
//! println!("I have a newline {}", "character at the end");
//! ```
//!
//! #### `format_args!`
//! ### `format_args!`
//!
//! This is a curious macro which is used to safely pass around
//! an opaque object describing the format string. This object
//! does not require any heap allocations to create, and it only
@ -303,7 +311,7 @@
//! it would internally pass around this structure until it has been determined
//! where output should go to.
//!
//! ## Syntax
//! # Syntax
//!
//! The syntax for the formatting language used is drawn from other languages,
//! so it should not be too alien. Arguments are formatted with python-like
@ -326,14 +334,14 @@
//! parameter := integer '$'
//! ```
//!
//! ## Formatting Parameters
//! # Formatting Parameters
//!
//! Each argument being formatted can be transformed by a number of formatting
//! parameters (corresponding to `format_spec` in the syntax above). These
//! parameters affect the string representation of what's being formatted. This
//! syntax draws heavily from Python's, so it may seem a bit familiar.
//!
//! ### Fill/Alignment
//! ## Fill/Alignment
//!
//! The fill character is provided normally in conjunction with the `width`
//! parameter. This indicates that if the value being formatted is smaller than
@ -345,7 +353,7 @@
//! * `^` - the argument is center-aligned in `width` columns
//! * `>` - the argument is right-aligned in `width` columns
//!
//! ### Sign/#/0
//! ## Sign/#/0
//!
//! These can all be interpreted as flags for a particular formatter.
//!
@ -368,7 +376,7 @@
//! same format would yield `-0000001` for the integer `-1`. Notice that
//! the negative version has one fewer zero than the positive version.
//!
//! ### Width
//! ## Width
//!
//! This is a parameter for the "minimum width" that the format should take up.
//! If the value's string does not fill up this many characters, then the
@ -384,7 +392,7 @@
//! parameters by using the `2$` syntax indicating that the second argument is a
//! `usize` specifying the width.
//!
//! ### Precision
//! ## Precision
//!
//! For non-numeric types, this can be considered a "maximum width". If the
//! resulting string is longer than this width, then it is truncated down to
@ -395,7 +403,7 @@
//! For floating-point types, this indicates how many digits after the decimal
//! point should be printed.
//!
//! ## Escaping
//! # Escaping
//!
//! The literal characters `{` and `}` may be included in a string by preceding
//! them with the same character. For example, the `{` character is escaped with

View File

@ -360,7 +360,7 @@ fn test_mut_rev_iter_wrap() {
assert_eq!(d.pop_front(), Some(1));
d.push_back(4);
assert_eq!(d.iter_mut().rev().cloned().collect::<Vec<_>>(),
assert_eq!(d.iter_mut().rev().map(|x| *x).collect::<Vec<_>>(),
vec![4, 3, 2]);
}

View File

@ -168,6 +168,7 @@ impl<T:Copy> Cell<T> {
/// let c = Cell::new(5);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn new(value: T) -> Cell<T> {
Cell {
value: UnsafeCell::new(value),
@ -237,6 +238,7 @@ unsafe impl<T> Send for Cell<T> where T: Send {}
#[stable(feature = "rust1", since = "1.0.0")]
impl<T:Copy> Clone for Cell<T> {
#[inline]
fn clone(&self) -> Cell<T> {
Cell::new(self.get())
}
@ -245,6 +247,7 @@ impl<T:Copy> Clone for Cell<T> {
#[stable(feature = "rust1", since = "1.0.0")]
impl<T:Default + Copy> Default for Cell<T> {
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
fn default() -> Cell<T> {
Cell::new(Default::default())
}
@ -252,6 +255,7 @@ impl<T:Default + Copy> Default for Cell<T> {
#[stable(feature = "rust1", since = "1.0.0")]
impl<T:PartialEq + Copy> PartialEq for Cell<T> {
#[inline]
fn eq(&self, other: &Cell<T>) -> bool {
self.get() == other.get()
}
@ -295,6 +299,7 @@ impl<T> RefCell<T> {
/// let c = RefCell::new(5);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn new(value: T) -> RefCell<T> {
RefCell {
value: UnsafeCell::new(value),
@ -314,6 +319,7 @@ impl<T> RefCell<T> {
/// let five = c.into_inner();
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn into_inner(self) -> T {
// Since this function takes `self` (the `RefCell`) by value, the
// compiler statically verifies that it is not currently borrowed.
@ -327,6 +333,7 @@ impl<T> RefCell<T> {
/// The returned value can be dispatched on to determine if a call to
/// `borrow` or `borrow_mut` would succeed.
#[unstable(feature = "std_misc")]
#[inline]
pub fn borrow_state(&self) -> BorrowState {
match self.borrow.get() {
WRITING => BorrowState::Writing,
@ -344,6 +351,7 @@ impl<T> RefCell<T> {
#[unstable(feature = "core", reason = "may be renamed or removed")]
#[deprecated(since = "1.0.0",
reason = "dispatch on `cell.borrow_state()` instead")]
#[inline]
pub fn try_borrow<'a>(&'a self) -> Option<Ref<'a, T>> {
match BorrowRef::new(&self.borrow) {
Some(b) => Some(Ref { _value: unsafe { &*self.value.get() }, _borrow: b }),
@ -387,6 +395,7 @@ impl<T> RefCell<T> {
/// assert!(result.is_err());
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn borrow<'a>(&'a self) -> Ref<'a, T> {
match BorrowRef::new(&self.borrow) {
Some(b) => Ref {
@ -406,6 +415,7 @@ impl<T> RefCell<T> {
#[unstable(feature = "core", reason = "may be renamed or removed")]
#[deprecated(since = "1.0.0",
reason = "dispatch on `cell.borrow_state()` instead")]
#[inline]
pub fn try_borrow_mut<'a>(&'a self) -> Option<RefMut<'a, T>> {
match BorrowRefMut::new(&self.borrow) {
Some(b) => Some(RefMut { _value: unsafe { &mut *self.value.get() }, _borrow: b }),
@ -448,6 +458,7 @@ impl<T> RefCell<T> {
/// assert!(result.is_err());
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn borrow_mut<'a>(&'a self) -> RefMut<'a, T> {
match BorrowRefMut::new(&self.borrow) {
Some(b) => RefMut {
@ -475,6 +486,7 @@ unsafe impl<T> Send for RefCell<T> where T: Send {}
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: Clone> Clone for RefCell<T> {
#[inline]
fn clone(&self) -> RefCell<T> {
RefCell::new(self.borrow().clone())
}
@ -483,6 +495,7 @@ impl<T: Clone> Clone for RefCell<T> {
#[stable(feature = "rust1", since = "1.0.0")]
impl<T:Default> Default for RefCell<T> {
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
fn default() -> RefCell<T> {
RefCell::new(Default::default())
}
@ -490,6 +503,7 @@ impl<T:Default> Default for RefCell<T> {
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: PartialEq> PartialEq for RefCell<T> {
#[inline]
fn eq(&self, other: &RefCell<T>) -> bool {
*self.borrow() == *other.borrow()
}
@ -500,6 +514,7 @@ struct BorrowRef<'b> {
}
impl<'b> BorrowRef<'b> {
#[inline]
fn new(borrow: &'b Cell<BorrowFlag>) -> Option<BorrowRef<'b>> {
match borrow.get() {
WRITING => None,
@ -513,6 +528,7 @@ impl<'b> BorrowRef<'b> {
#[unsafe_destructor]
impl<'b> Drop for BorrowRef<'b> {
#[inline]
fn drop(&mut self) {
let borrow = self._borrow.get();
debug_assert!(borrow != WRITING && borrow != UNUSED);
@ -521,6 +537,7 @@ impl<'b> Drop for BorrowRef<'b> {
}
impl<'b> Clone for BorrowRef<'b> {
#[inline]
fn clone(&self) -> BorrowRef<'b> {
// Since this Ref exists, we know the borrow flag
// is not set to WRITING.
@ -561,6 +578,7 @@ impl<'b, T> Deref for Ref<'b, T> {
/// use of `r.borrow().clone()` to clone the contents of a `RefCell`.
#[unstable(feature = "core",
reason = "likely to be moved to a method, pending language changes")]
#[inline]
pub fn clone_ref<'b, T:Clone>(orig: &Ref<'b, T>) -> Ref<'b, T> {
Ref {
_value: orig._value,
@ -574,6 +592,7 @@ struct BorrowRefMut<'b> {
#[unsafe_destructor]
impl<'b> Drop for BorrowRefMut<'b> {
#[inline]
fn drop(&mut self) {
let borrow = self._borrow.get();
debug_assert!(borrow == WRITING);
@ -582,6 +601,7 @@ impl<'b> Drop for BorrowRefMut<'b> {
}
impl<'b> BorrowRefMut<'b> {
#[inline]
fn new(borrow: &'b Cell<BorrowFlag>) -> Option<BorrowRefMut<'b>> {
match borrow.get() {
UNUSED => {
@ -674,6 +694,7 @@ impl<T> UnsafeCell<T> {
/// let uc = UnsafeCell::new(5);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[inline]
pub fn new(value: T) -> UnsafeCell<T> {
UnsafeCell { value: value }
}

View File

@ -65,7 +65,7 @@ use default::Default;
use marker;
use mem;
use num::{ToPrimitive, Int};
use ops::{Add, Deref, FnMut, RangeFrom};
use ops::{Add, FnMut, RangeFrom};
use option::Option;
use option::Option::{Some, None};
use marker::Sized;
@ -976,12 +976,11 @@ pub trait IteratorExt: Iterator + Sized {
(ts, us)
}
/// Creates an iterator that clones the elements it yields. Useful for converting an
/// Iterator<&T> to an Iterator<T>.
#[unstable(feature = "core", reason = "recent addition")]
fn cloned(self) -> Cloned<Self> where
Self::Item: Deref,
<Self::Item as Deref>::Target: Clone,
/// Creates an iterator that clones the elements it yields. Useful for
/// converting an Iterator<&T> to an Iterator<T>.
#[stable(feature = "rust1", since = "1.0.0")]
fn cloned<'a, T: 'a>(self) -> Cloned<Self>
where Self: Iterator<Item=&'a T>, T: Clone
{
Cloned { it: self }
}
@ -1279,14 +1278,12 @@ pub struct Cloned<I> {
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<I> Iterator for Cloned<I> where
I: Iterator,
I::Item: Deref,
<I::Item as Deref>::Target: Clone
impl<'a, I, T: 'a> Iterator for Cloned<I>
where I: Iterator<Item=&'a T>, T: Clone
{
type Item = <I::Item as Deref>::Target;
type Item = T;
fn next(&mut self) -> Option<<Self as Iterator>::Item> {
fn next(&mut self) -> Option<T> {
self.it.next().cloned()
}
@ -1296,28 +1293,22 @@ impl<I> Iterator for Cloned<I> where
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<I> DoubleEndedIterator for Cloned<I> where
I: DoubleEndedIterator,
I::Item: Deref,
<I::Item as Deref>::Target: Clone
impl<'a, I, T: 'a> DoubleEndedIterator for Cloned<I>
where I: DoubleEndedIterator<Item=&'a T>, T: Clone
{
fn next_back(&mut self) -> Option<<Self as Iterator>::Item> {
fn next_back(&mut self) -> Option<T> {
self.it.next_back().cloned()
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<I> ExactSizeIterator for Cloned<I> where
I: ExactSizeIterator,
I::Item: Deref,
<I::Item as Deref>::Target: Clone
impl<'a, I, T: 'a> ExactSizeIterator for Cloned<I>
where I: ExactSizeIterator<Item=&'a T>, T: Clone
{}
#[unstable(feature = "core", reason = "trait is experimental")]
impl<I> RandomAccessIterator for Cloned<I> where
I: RandomAccessIterator,
I::Item: Deref,
<I::Item as Deref>::Target: Clone
impl<'a, I, T: 'a> RandomAccessIterator for Cloned<I>
where I: RandomAccessIterator<Item=&'a T>, T: Clone
{
#[inline]
fn indexable(&self) -> usize {
@ -1325,7 +1316,7 @@ impl<I> RandomAccessIterator for Cloned<I> where
}
#[inline]
fn idx(&mut self, index: usize) -> Option<<Self as Iterator>::Item> {
fn idx(&mut self, index: usize) -> Option<T> {
self.it.idx(index).cloned()
}
}

View File

@ -330,7 +330,7 @@ impl<T, E> Result<T, E> {
/// Convert from `Result<T, E>` to `Option<E>`
///
/// Converts `self` into an `Option<E>`, consuming `self`,
/// and discarding the value, if any.
/// and discarding the success value, if any.
///
/// # Examples
///

View File

@ -131,6 +131,7 @@ pub use funcs::bsd43::*;
#[cfg(unix)] pub use funcs::posix88::net::*;
#[cfg(unix)] pub use funcs::posix01::stat_::*;
#[cfg(unix)] pub use funcs::posix01::unistd::*;
#[cfg(unix)] pub use funcs::posix01::resource::*;
#[cfg(windows)] pub use funcs::extra::kernel32::*;
@ -223,6 +224,7 @@ pub mod types {
pub type pthread_t = c_ulong;
#[cfg(target_os = "nacl")]
pub type pthread_t = *mut c_void;
pub type rlim_t = u64;
#[repr(C)]
#[derive(Copy)] pub struct glob_t {
@ -252,7 +254,42 @@ pub mod types {
#[derive(Copy)] pub enum timezone {}
pub type sighandler_t = size_t;
#[repr(C)]
#[derive(Copy)]
pub struct rlimit {
pub rlim_cur: rlim_t,
pub rlim_max: rlim_t,
}
}
pub mod bsd43 {
use types::os::common::posix01::timeval;
use types::os::arch::c95::c_long;
// This is also specified in POSIX 2001, but only has two fields. All implementors
// implement BSD 4.3 version.
#[repr(C)]
#[derive(Copy)]
pub struct rusage {
pub ru_utime: timeval,
pub ru_stime: timeval,
pub ru_maxrss: c_long,
pub ru_ixrss: c_long,
pub ru_idrss: c_long,
pub ru_isrss: c_long,
pub ru_minflt: c_long,
pub ru_majflt: c_long,
pub ru_nswap: c_long,
pub ru_inblock: c_long,
pub ru_oublock: c_long,
pub ru_msgsnd: c_long,
pub ru_msgrcv: c_long,
pub ru_nsignals: c_long,
pub ru_nvcsw: c_long,
pub ru_nivcsw: c_long
}
}
pub mod bsd44 {
use types::common::c95::{c_void};
use types::os::arch::c95::{c_char, c_int, c_uint};
@ -734,6 +771,7 @@ pub mod types {
use types::os::arch::c99::{uintptr_t};
pub type pthread_t = uintptr_t;
pub type rlim_t = i64;
#[repr(C)]
#[derive(Copy)] pub struct glob_t {
@ -767,7 +805,40 @@ pub mod types {
#[derive(Copy)] pub enum timezone {}
pub type sighandler_t = size_t;
#[repr(C)]
#[derive(Copy)]
pub struct rlimit {
pub rlim_cur: rlim_t,
pub rlim_max: rlim_t,
}
}
pub mod bsd43 {
use types::os::common::posix01::timeval;
use types::os::arch::c95::c_long;
#[repr(C)]
#[derive(Copy)]
pub struct rusage {
pub ru_utime: timeval,
pub ru_stime: timeval,
pub ru_maxrss: c_long,
pub ru_ixrss: c_long,
pub ru_idrss: c_long,
pub ru_isrss: c_long,
pub ru_minflt: c_long,
pub ru_majflt: c_long,
pub ru_nswap: c_long,
pub ru_inblock: c_long,
pub ru_oublock: c_long,
pub ru_msgsnd: c_long,
pub ru_msgrcv: c_long,
pub ru_nsignals: c_long,
pub ru_nvcsw: c_long,
pub ru_nivcsw: c_long
}
}
pub mod bsd44 {
use types::common::c95::{c_void};
use types::os::arch::c95::{c_char, c_int, c_uint};
@ -962,6 +1033,7 @@ pub mod types {
use types::os::arch::c99::{uintptr_t};
pub type pthread_t = uintptr_t;
pub type rlim_t = i64;
#[repr(C)]
#[derive(Copy)] pub struct glob_t {
@ -995,7 +1067,40 @@ pub mod types {
#[derive(Copy)] pub enum timezone {}
pub type sighandler_t = size_t;
#[repr(C)]
#[derive(Copy)]
pub struct rlimit {
pub rlim_cur: rlim_t,
pub rlim_max: rlim_t,
}
}
pub mod bsd43 {
use types::os::common::posix01::timeval;
use types::os::arch::c95::c_long;
#[repr(C)]
#[derive(Copy)]
pub struct rusage {
pub ru_utime: timeval,
pub ru_stime: timeval,
pub ru_maxrss: c_long,
pub ru_ixrss: c_long,
pub ru_idrss: c_long,
pub ru_isrss: c_long,
pub ru_minflt: c_long,
pub ru_majflt: c_long,
pub ru_nswap: c_long,
pub ru_inblock: c_long,
pub ru_oublock: c_long,
pub ru_msgsnd: c_long,
pub ru_msgrcv: c_long,
pub ru_nsignals: c_long,
pub ru_nvcsw: c_long,
pub ru_nivcsw: c_long
}
}
pub mod bsd44 {
use types::common::c95::{c_void};
use types::os::arch::c95::{c_char, c_int, c_uint};
@ -1189,6 +1294,7 @@ pub mod types {
use types::os::arch::c99::{uintptr_t};
pub type pthread_t = uintptr_t;
pub type rlim_t = u64;
#[cfg(target_os = "bitrig")]
#[repr(C)]
@ -1241,7 +1347,40 @@ pub mod types {
#[derive(Copy)] pub enum timezone {}
pub type sighandler_t = size_t;
#[repr(C)]
#[derive(Copy)]
pub struct rlimit {
pub rlim_cur: rlim_t,
pub rlim_max: rlim_t,
}
}
pub mod bsd43 {
use types::os::common::posix01::timeval;
use types::os::arch::c95::c_long;
#[repr(C)]
#[derive(Copy)]
pub struct rusage {
pub ru_utime: timeval,
pub ru_stime: timeval,
pub ru_maxrss: c_long,
pub ru_ixrss: c_long,
pub ru_idrss: c_long,
pub ru_isrss: c_long,
pub ru_minflt: c_long,
pub ru_majflt: c_long,
pub ru_nswap: c_long,
pub ru_inblock: c_long,
pub ru_oublock: c_long,
pub ru_msgsnd: c_long,
pub ru_msgrcv: c_long,
pub ru_nsignals: c_long,
pub ru_nvcsw: c_long,
pub ru_nivcsw: c_long
}
}
pub mod bsd44 {
use types::common::c95::{c_void};
use types::os::arch::c95::{c_char, c_int, c_uint};
@ -1840,6 +1979,7 @@ pub mod types {
use types::os::arch::c99::{uintptr_t};
pub type pthread_t = uintptr_t;
pub type rlim_t = u64;
#[repr(C)]
#[derive(Copy)] pub struct glob_t {
@ -1873,6 +2013,38 @@ pub mod types {
#[derive(Copy)] pub enum timezone {}
pub type sighandler_t = size_t;
#[repr(C)]
#[derive(Copy)]
pub struct rlimit {
pub rlim_cur: rlim_t,
pub rlim_max: rlim_t,
}
}
pub mod bsd43 {
use types::os::common::posix01::timeval;
use types::os::arch::c95::c_long;
#[repr(C)]
#[derive(Copy)]
pub struct rusage {
pub ru_utime: timeval,
pub ru_stime: timeval,
pub ru_maxrss: c_long,
pub ru_ixrss: c_long,
pub ru_idrss: c_long,
pub ru_isrss: c_long,
pub ru_minflt: c_long,
pub ru_majflt: c_long,
pub ru_nswap: c_long,
pub ru_inblock: c_long,
pub ru_oublock: c_long,
pub ru_msgsnd: c_long,
pub ru_msgrcv: c_long,
pub ru_nsignals: c_long,
pub ru_nvcsw: c_long,
pub ru_nivcsw: c_long
}
}
pub mod bsd44 {
@ -3024,6 +3196,7 @@ pub mod consts {
#[cfg(not(target_os = "nacl"))]
pub mod posix01 {
use types::os::arch::c95::{c_int, size_t};
use types::os::common::posix01::rlim_t;
pub const F_DUPFD : c_int = 0;
pub const F_GETFD : c_int = 1;
@ -3102,10 +3275,36 @@ pub mod consts {
pub const CLOCK_REALTIME: c_int = 0;
pub const CLOCK_MONOTONIC: c_int = 1;
pub const RLIMIT_CPU: c_int = 0;
pub const RLIMIT_FSIZE: c_int = 1;
pub const RLIMIT_DATA: c_int = 2;
pub const RLIMIT_STACK: c_int = 3;
pub const RLIMIT_CORE: c_int = 4;
pub const RLIMIT_RSS: c_int = 5;
pub const RLIMIT_NOFILE: c_int = 7;
pub const RLIMIT_AS: c_int = 9;
pub const RLIMIT_NPROC: c_int = 6;
pub const RLIMIT_MEMLOCK: c_int = 8;
pub const RLIMIT_LOCKS: c_int = 10;
pub const RLIMIT_SIGPENDING: c_int = 11;
pub const RLIMIT_MSGQUEUE: c_int = 12;
pub const RLIMIT_NICE: c_int = 13;
pub const RLIMIT_RTPRIO: c_int = 14;
pub const RLIMIT_RTTIME: c_int = 15;
pub const RLIMIT_NLIMITS: c_int = 16;
pub const RLIM_INFINITY: rlim_t = 0xffff_ffff_ffff_ffff;
pub const RLIM_SAVED_MAX: rlim_t = RLIM_INFINITY;
pub const RLIM_SAVED_CUR: rlim_t = RLIM_INFINITY;
pub const RUSAGE_SELF: c_int = 0;
pub const RUSAGE_CHILDREN: c_int = -1;
pub const RUSAGE_THREAD: c_int = 1;
}
#[cfg(target_os = "nacl")]
pub mod posix01 {
use types::os::arch::c95::{c_int, size_t};
use types::os::common::posix01::rlim_t;
pub const F_DUPFD : c_int = 0;
pub const F_GETFD : c_int = 1;
@ -3170,6 +3369,32 @@ pub mod consts {
pub const CLOCK_REALTIME: c_int = 0;
pub const CLOCK_MONOTONIC: c_int = 1;
pub const RLIMIT_CPU: c_int = 0;
pub const RLIMIT_FSIZE: c_int = 1;
pub const RLIMIT_DATA: c_int = 2;
pub const RLIMIT_STACK: c_int = 3;
pub const RLIMIT_CORE: c_int = 4;
pub const RLIMIT_RSS: c_int = 5;
pub const RLIMIT_NOFILE: c_int = 7;
pub const RLIMIT_AS: c_int = 9;
pub const RLIMIT_NPROC: c_int = 6;
pub const RLIMIT_MEMLOCK: c_int = 8;
pub const RLIMIT_LOCKS: c_int = 10;
pub const RLIMIT_SIGPENDING: c_int = 11;
pub const RLIMIT_MSGQUEUE: c_int = 12;
pub const RLIMIT_NICE: c_int = 13;
pub const RLIMIT_RTPRIO: c_int = 14;
pub const RLIMIT_RTTIME: c_int = 15;
pub const RLIMIT_NLIMITS: c_int = 16;
pub const RLIM_INFINITY: rlim_t = 0xffff_ffff_ffff_ffff;
pub const RLIM_SAVED_MAX: rlim_t = RLIM_INFINITY;
pub const RLIM_SAVED_CUR: rlim_t = RLIM_INFINITY;
pub const RUSAGE_SELF: c_int = 0;
pub const RUSAGE_CHILDREN: c_int = -1;
pub const RUSAGE_THREAD: c_int = 1;
}
pub mod posix08 {
}
@ -3632,6 +3857,7 @@ pub mod consts {
}
pub mod posix01 {
use types::os::arch::c95::{c_int, size_t};
use types::os::common::posix01::rlim_t;
pub const F_DUPFD : c_int = 0;
pub const F_GETFD : c_int = 1;
@ -3707,6 +3933,29 @@ pub mod consts {
pub const CLOCK_REALTIME: c_int = 0;
pub const CLOCK_MONOTONIC: c_int = 4;
pub const RLIMIT_CPU: c_int = 0;
pub const RLIMIT_FSIZE: c_int = 1;
pub const RLIMIT_DATA: c_int = 2;
pub const RLIMIT_STACK: c_int = 3;
pub const RLIMIT_CORE: c_int = 4;
pub const RLIMIT_RSS: c_int = 5;
pub const RLIMIT_MEMLOCK: c_int = 6;
pub const RLIMIT_NPROC: c_int = 7;
pub const RLIMIT_NOFILE: c_int = 8;
pub const RLIMIT_SBSIZE: c_int = 9;
pub const RLIMIT_VMEM: c_int = 10;
pub const RLIMIT_AS: c_int = RLIMIT_VMEM;
pub const RLIMIT_NPTS: c_int = 11;
pub const RLIMIT_SWAP: c_int = 12;
pub const RLIMIT_KQUEUES: c_int = 13;
pub const RLIM_NLIMITS: rlim_t = 14;
pub const RLIM_INFINITY: rlim_t = 0x7fff_ffff_ffff_ffff;
pub const RUSAGE_SELF: c_int = 0;
pub const RUSAGE_CHILDREN: c_int = -1;
pub const RUSAGE_THREAD: c_int = 1;
}
pub mod posix08 {
}
@ -4032,6 +4281,7 @@ pub mod consts {
}
pub mod posix01 {
use types::os::arch::c95::{c_int, size_t};
use types::os::common::posix01::rlim_t;
pub const F_DUPFD : c_int = 0;
pub const F_GETFD : c_int = 1;
@ -4101,6 +4351,25 @@ pub mod consts {
pub const CLOCK_REALTIME : c_int = 0;
pub const CLOCK_MONOTONIC : c_int = 3;
pub const RLIMIT_CPU: c_int = 0;
pub const RLIMIT_FSIZE: c_int = 1;
pub const RLIMIT_DATA: c_int = 2;
pub const RLIMIT_STACK: c_int = 3;
pub const RLIMIT_CORE: c_int = 4;
pub const RLIMIT_RSS: c_int = 5;
pub const RLIMIT_MEMLOCK: c_int = 6;
pub const RLIMIT_NPROC: c_int = 7;
pub const RLIMIT_NOFILE: c_int = 8;
pub const RLIM_NLIMITS: c_int = 9;
pub const RLIM_INFINITY: rlim_t = 0x7fff_ffff_ffff_ffff;
pub const RLIM_SAVED_MAX: rlim_t = RLIM_INFINITY;
pub const RLIM_SAVED_CUR: rlim_t = RLIM_INFINITY;
pub const RUSAGE_SELF: c_int = 0;
pub const RUSAGE_CHILDREN: c_int = -1;
pub const RUSAGE_THREAD: c_int = 1;
}
pub mod posix08 {
}
@ -4428,6 +4697,7 @@ pub mod consts {
}
pub mod posix01 {
use types::os::arch::c95::{c_int, size_t};
use types::os::common::posix01::rlim_t;
pub const F_DUPFD : c_int = 0;
pub const F_GETFD : c_int = 1;
@ -4488,6 +4758,24 @@ pub mod consts {
pub const PTHREAD_CREATE_JOINABLE: c_int = 1;
pub const PTHREAD_CREATE_DETACHED: c_int = 2;
pub const PTHREAD_STACK_MIN: size_t = 8192;
pub const RLIMIT_CPU: c_int = 0;
pub const RLIMIT_FSIZE: c_int = 1;
pub const RLIMIT_DATA: c_int = 2;
pub const RLIMIT_STACK: c_int = 3;
pub const RLIMIT_CORE: c_int = 4;
pub const RLIMIT_AS: c_int = 5;
pub const RLIMIT_MEMLOCK: c_int = 6;
pub const RLIMIT_NPROC: c_int = 7;
pub const RLIMIT_NOFILE: c_int = 8;
pub const RLIM_NLIMITS: c_int = 9;
pub const _RLIMIT_POSIX_FLAG: c_int = 0x1000;
pub const RLIM_INFINITY: rlim_t = 0xffff_ffff_ffff_ffff;
pub const RUSAGE_SELF: c_int = 0;
pub const RUSAGE_CHILDREN: c_int = -1;
pub const RUSAGE_THREAD: c_int = 1;
}
pub mod posix08 {
}
@ -5348,6 +5636,18 @@ pub mod funcs {
-> c_int;
}
}
pub mod resource {
use types::os::arch::c95::c_int;
use types::os::common::posix01::rlimit;
use types::os::common::bsd43::rusage;
extern {
pub fn getrlimit(resource: c_int, rlim: *mut rlimit) -> c_int;
pub fn setrlimit(resource: c_int, rlim: *const rlimit) -> c_int;
pub fn getrusage(resource: c_int, usage: *mut rusage) -> c_int;
}
}
}
#[cfg(target_os = "windows")]

View File

@ -146,7 +146,7 @@ impl Stdin {
/// accessing the underlying data.
#[stable(feature = "rust1", since = "1.0.0")]
pub fn lock(&self) -> StdinLock {
StdinLock { inner: self.inner.lock().unwrap() }
StdinLock { inner: self.inner.lock().unwrap_or_else(|e| e.into_inner()) }
}
/// Locks this handle and reads a line of input into the specified buffer.
@ -249,7 +249,7 @@ impl Stdout {
/// returned guard also implements the `Write` trait for writing data.
#[stable(feature = "rust1", since = "1.0.0")]
pub fn lock(&self) -> StdoutLock {
StdoutLock { inner: self.inner.lock().unwrap() }
StdoutLock { inner: self.inner.lock().unwrap_or_else(|e| e.into_inner()) }
}
}
@ -319,7 +319,7 @@ impl Stderr {
/// returned guard also implements the `Write` trait for writing data.
#[stable(feature = "rust1", since = "1.0.0")]
pub fn lock(&self) -> StderrLock {
StderrLock { inner: self.inner.lock().unwrap() }
StderrLock { inner: self.inner.lock().unwrap_or_else(|e| e.into_inner()) }
}
}
@ -402,3 +402,29 @@ pub fn _print(args: fmt::Arguments) {
panic!("failed printing to stdout: {}", e);
}
}
#[cfg(test)]
mod test {
use thread;
use super::*;
#[test]
fn panic_doesnt_poison() {
thread::spawn(|| {
let _a = stdin();
let _a = _a.lock();
let _a = stdout();
let _a = _a.lock();
let _a = stderr();
let _a = _a.lock();
panic!();
}).join().unwrap_err();
let _a = stdin();
let _a = _a.lock();
let _a = stdout();
let _a = _a.lock();
let _a = stderr();
let _a = _a.lock();
}
}

View File

@ -404,4 +404,18 @@ pub mod builtin {
/// ```
#[macro_export]
macro_rules! cfg { ($cfg:tt) => ({ /* compiler built-in */ }) }
/// Parse the current given file as an expression.
///
/// This is generally a bad idea, because it's going to behave unhygenically.
///
/// # Examples
///
/// ```ignore
/// fn foo() {
/// include!("/path/to/a/file")
/// }
/// ```
#[macro_export]
macro_rules! include { ($cfg:tt) => ({ /* compiler built-in */ }) }
}

View File

@ -306,12 +306,11 @@ pub fn args() -> Args {
// In general it looks like:
// res = Vec::new()
// let args = [[NSProcessInfo processInfo] arguments]
// for i in range(0, [args count])
// for i in (0..[args count])
// res.push([args objectAtIndex:i])
// res
#[cfg(target_os = "ios")]
pub fn args() -> Args {
use iter::range;
use mem;
#[link(name = "objc")]
@ -341,7 +340,7 @@ pub fn args() -> Args {
let args = objc_msgSend(info, arguments_sel);
let cnt: int = mem::transmute(objc_msgSend(args, count_sel));
for i in range(0, cnt) {
for i in (0..cnt) {
let tmp = objc_msgSend(args, object_at_sel, i);
let utf_c_str: *const libc::c_char =
mem::transmute(objc_msgSend(tmp, utf8_sel));

View File

@ -130,12 +130,13 @@ pub mod guard {
#[cfg(any(target_os = "openbsd", target_os = "bitrig"))]
pub unsafe fn current() -> usize {
#[repr(C)]
pub struct stack_t {
struct stack_t {
ss_sp: *mut libc::c_void,
ss_size: libc::size_t,
ss_flags: libc::c_int,
}
extern {
fn pthread_main_np() -> libc::c_uint;
fn pthread_stackseg_np(thread: pthread_t,
sinfo: *mut stack_t) -> libc::c_uint;
}
@ -339,9 +340,6 @@ fn min_stack_size(_: *const libc::pthread_attr_t) -> libc::size_t {
}
extern {
#[cfg(any(target_os = "bitrig", target_os = "openbsd"))]
fn pthread_main_np() -> libc::c_uint;
fn pthread_self() -> libc::pthread_t;
fn pthread_create(native: *mut libc::pthread_t,
attr: *const libc::pthread_attr_t,

View File

@ -215,8 +215,8 @@ pub struct Lifetime {
pub name: Name
}
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
/// A lifetime definition, eg `'a: 'b+'c+'d`
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
pub struct LifetimeDef {
pub lifetime: Lifetime,
pub bounds: Vec<Lifetime>
@ -590,6 +590,7 @@ pub enum Pat_ {
/// A PatIdent may either be a new bound variable,
/// or a nullary enum (in which case the third field
/// is None).
///
/// In the nullary enum case, the parser can't determine
/// which it is. The resolver determines this, and
/// records this pattern's NodeId in an auxiliary
@ -786,18 +787,22 @@ pub enum Expr_ {
/// An array (`[a, b, c, d]`)
ExprVec(Vec<P<Expr>>),
/// A function call
///
/// The first field resolves to the function itself,
/// and the second field is the list of arguments
ExprCall(P<Expr>, Vec<P<Expr>>),
/// A method call (`x.foo::<Bar, Baz>(a, b, c, d)`)
/// The `SpannedIdent` is the identifier for the method name
///
/// The `SpannedIdent` is the identifier for the method name.
/// The vector of `Ty`s are the ascripted type parameters for the method
/// (within the angle brackets)
/// (within the angle brackets).
///
/// The first element of the vector of `Expr`s is the expression that evaluates
/// to the object on which the method is being called on (the receiver),
/// and the remaining elements are the rest of the arguments.
///
/// Thus, `x.foo::<Bar, Baz>(a, b, c, d)` is represented as
/// `ExprMethodCall(foo, [Bar, Baz], [x, a, b, c, d])`
/// `ExprMethodCall(foo, [Bar, Baz], [x, a, b, c, d])`.
ExprMethodCall(SpannedIdent, Vec<P<Ty>>, Vec<P<Expr>>),
/// A tuple (`(a, b, c ,d)`)
ExprTup(Vec<P<Expr>>),
@ -810,32 +815,41 @@ pub enum Expr_ {
/// A cast (`foo as f64`)
ExprCast(P<Expr>, P<Ty>),
/// An `if` block, with an optional else block
///
/// `if expr { block } else { expr }`
ExprIf(P<Expr>, P<Block>, Option<P<Expr>>),
/// An `if let` expression with an optional else block
///
/// `if let pat = expr { block } else { expr }`
/// This is desugared to a `match` expression
///
/// This is desugared to a `match` expression.
ExprIfLet(P<Pat>, P<Expr>, P<Block>, Option<P<Expr>>),
// FIXME #6993: change to Option<Name> ... or not, if these are hygienic.
/// A while loop, with an optional label
///
/// `'label: while expr { block }`
ExprWhile(P<Expr>, P<Block>, Option<Ident>),
// FIXME #6993: change to Option<Name> ... or not, if these are hygienic.
/// A while-let loop, with an optional label
///
/// `'label: while let pat = expr { block }`
/// This is desugared to a combination of `loop` and `match` expressions
///
/// This is desugared to a combination of `loop` and `match` expressions.
ExprWhileLet(P<Pat>, P<Expr>, P<Block>, Option<Ident>),
// FIXME #6993: change to Option<Name> ... or not, if these are hygienic.
/// A for loop, with an optional label
///
/// `'label: for pat in expr { block }`
/// This is desugared to a combination of `loop` and `match` expressions
///
/// This is desugared to a combination of `loop` and `match` expressions.
ExprForLoop(P<Pat>, P<Expr>, P<Block>, Option<Ident>),
/// Conditionless loop (can be exited with break, continue, or return)
///
/// `'label: loop { block }`
// FIXME #6993: change to Option<Name> ... or not, if these are hygienic.
ExprLoop(P<Block>, Option<Ident>),
/// A `match` block, with a source that indicates whether or not it is
/// the result of a desugaring, and if so, which kind
/// the result of a desugaring, and if so, which kind.
ExprMatch(P<Expr>, Vec<Arm>, MatchSource),
/// A closure (for example, `move |a, b, c| {a + b + c}`)
ExprClosure(CaptureClause, P<FnDecl>, P<Block>),
@ -845,12 +859,14 @@ pub enum Expr_ {
/// An assignment (`a = foo()`)
ExprAssign(P<Expr>, P<Expr>),
/// An assignment with an operator
/// For example, `a += 1`
///
/// For example, `a += 1`.
ExprAssignOp(BinOp, P<Expr>, P<Expr>),
/// Access of a named struct field (`obj.foo`)
ExprField(P<Expr>, SpannedIdent),
/// Access of an unnamed field of a struct or tuple-struct
/// For example, `foo.0`
///
/// For example, `foo.0`.
ExprTupField(P<Expr>, Spanned<usize>),
/// An indexing operation (`foo[2]`)
ExprIndex(P<Expr>, P<Expr>),
@ -858,7 +874,9 @@ pub enum Expr_ {
ExprRange(Option<P<Expr>>, Option<P<Expr>>),
/// Variable reference, possibly containing `::` and/or type
/// parameters, e.g. foo::bar::<baz>. Optionally "qualified",
/// parameters, e.g. foo::bar::<baz>.
///
/// Optionally "qualified",
/// e.g. `<Vec<T> as SomeTrait>::SomeType`.
ExprPath(Option<QSelf>, Path),
@ -878,13 +896,15 @@ pub enum Expr_ {
ExprMac(Mac),
/// A struct literal expression.
///
/// For example, `Foo {x: 1, y: 2}`, or
/// `Foo {x: 1, .. base}`, where `base` is the `Option<Expr>`
/// `Foo {x: 1, .. base}`, where `base` is the `Option<Expr>`.
ExprStruct(Path, Vec<Field>, Option<P<Expr>>),
/// A vector literal constructed from one repeated element.
///
/// For example, `[1u8; 5]`. The first expression is the element
/// to be repeated; the second is the number of times to repeat it
/// to be repeated; the second is the number of times to repeat it.
ExprRepeat(P<Expr>, P<Expr>),
/// No-op: used solely so we can pretty-print faithfully
@ -1092,6 +1112,7 @@ pub type Mac = Spanned<Mac_>;
/// Represents a macro invocation. The Path indicates which macro
/// is being invoked, and the vector of token-trees contains the source
/// of the macro invocation.
///
/// There's only one flavor, now, so this could presumably be simplified.
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
pub enum Mac_ {
@ -1105,6 +1126,7 @@ pub enum StrStyle {
/// A regular string, like `"foo"`
CookedStr,
/// A raw string, like `r##"foo"##`
///
/// The uint is the number of `#` symbols used
RawStr(usize)
}
@ -1155,7 +1177,7 @@ pub enum Lit_ {
LitByte(u8),
/// A character literal (`'a'`)
LitChar(char),
/// An integer liteal (`1u8`)
/// An integer literal (`1u8`)
LitInt(u64, LitIntType),
/// A float literal (`1f64` or `1E10f64`)
LitFloat(InternedString, FloatTy),
@ -1459,7 +1481,7 @@ impl Arg {
}
}
/// represents the header (not the body) of a function declaration
/// Represents the header (not the body) of a function declaration
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
pub struct FnDecl {
pub inputs: Vec<Arg>,
@ -1505,7 +1527,9 @@ pub enum FunctionRetTy {
/// Functions with return type `!`that always
/// raise an error or exit (i.e. never return to the caller)
NoReturn(Span),
/// Return type is not specified. Functions default to `()` and
/// Return type is not specified.
///
/// Functions default to `()` and
/// closures default to inference. Span points to where return
/// type would be inserted.
DefaultReturn(Span),
@ -1645,6 +1669,7 @@ pub struct Attribute_ {
}
/// TraitRef's appear in impls.
///
/// resolve maps each TraitRef's ref_id to its defining trait; that's all
/// that the ref_id is for. The impl_id maps to the "self type" of this impl.
/// If this impl is an ItemImpl, the impl_id is redundant (it could be the
@ -1745,6 +1770,7 @@ pub struct Item {
#[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug)]
pub enum Item_ {
/// An`extern crate` item, with optional original crate name,
///
/// e.g. `extern crate foo` or `extern crate "foo-bar" as foo`
ItemExternCrate(Option<(InternedString, StrStyle)>),
/// A `use` or `pub use` item
@ -1773,6 +1799,7 @@ pub enum Item_ {
Vec<P<TraitItem>>),
// Default trait implementations
///
// `impl Trait for .. {}`
ItemDefaultImpl(Unsafety, TraitRef),
/// An implementation, eg `impl<A> Trait for Foo { .. }`

View File

@ -404,7 +404,7 @@ pub fn char_lit(lit: &str) -> (char, isize) {
.map(|x| (x, len as isize))
}
let unicode_escape = || -> Option<(char, isize)>
let unicode_escape = || -> Option<(char, isize)> {
if lit.as_bytes()[2] == b'{' {
let idx = lit.find('}').expect(msg2);
let subslice = &lit[3..idx];
@ -413,7 +413,8 @@ pub fn char_lit(lit: &str) -> (char, isize) {
.map(|x| (x, subslice.chars().count() as isize + 4))
} else {
esc(6, lit)
};
}
};
// Unicode escapes
return match lit.as_bytes()[1] as char {

View File

@ -2099,10 +2099,7 @@ impl<'a> Parser<'a> {
}
},
token::OpenDelim(token::Brace) => {
self.bump();
let blk = self.parse_block_tail(lo, DefaultBlock);
return self.mk_expr(blk.span.lo, blk.span.hi,
ExprBlock(blk));
return self.parse_block_expr(lo, DefaultBlock);
},
token::BinOp(token::Or) | token::OrOr => {
return self.parse_lambda_expr(CaptureByRef);
@ -2998,19 +2995,30 @@ impl<'a> Parser<'a> {
{
let lo = self.span.lo;
let decl = self.parse_fn_block_decl();
let body = self.parse_expr();
let fakeblock = P(ast::Block {
id: ast::DUMMY_NODE_ID,
stmts: vec![],
span: body.span,
expr: Some(body),
rules: DefaultBlock,
});
let body = match decl.output {
DefaultReturn(_) => {
// If no explicit return type is given, parse any
// expr and wrap it up in a dummy block:
let body_expr = self.parse_expr();
P(ast::Block {
id: ast::DUMMY_NODE_ID,
stmts: vec![],
span: body_expr.span,
expr: Some(body_expr),
rules: DefaultBlock,
})
}
_ => {
// If an explicit return type is given, require a
// block to appear (RFC 968).
self.parse_block()
}
};
self.mk_expr(
lo,
fakeblock.span.hi,
ExprClosure(capture_clause, decl, fakeblock))
body.span.hi,
ExprClosure(capture_clause, decl, body))
}
pub fn parse_else_expr(&mut self) -> P<Expr> {

View File

@ -1777,7 +1777,12 @@ impl<'a> State<'a> {
try!(self.print_fn_block_args(&**decl));
try!(space(&mut self.s));
if !body.stmts.is_empty() || !body.expr.is_some() {
let default_return = match decl.output {
ast::DefaultReturn(..) => true,
_ => false
};
if !default_return || !body.stmts.is_empty() || body.expr.is_none() {
try!(self.print_block_unclosed(&**body));
} else {
// we extract the block, so as not to create another set of boxes

View File

@ -26,7 +26,7 @@ fn main() {
//~| found `Box<core::ops::Fn(isize, isize)>`
//~| expected ()
//~| found box
let _: () = (box || -> isize unimplemented!()) as Box<FnMut() -> isize>;
let _: () = (box || -> isize { unimplemented!() }) as Box<FnMut() -> isize>;
//~^ ERROR mismatched types
//~| expected `()`
//~| found `Box<core::ops::FnMut() -> isize>`

View File

@ -13,6 +13,6 @@ use std::vec::Vec;
fn main() {
let a: Vec<isize> = Vec::new();
a.iter().all(|_| -> bool {
//~^ ERROR mismatched types
//~^ ERROR not all control paths return a value
});
}

View File

@ -0,0 +1,16 @@
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// Test that we cannot parse a closure with an explicit return type
// unless it uses braces.
fn main() {
let x = || -> i32 22; //~ ERROR expected `{`, found `22`
}

View File

@ -10,5 +10,5 @@
pub fn main() {
fn as_buf<T, F>(s: String, f: F) -> T where F: FnOnce(String) -> T { f(s) }
as_buf("foo".to_string(), |foo: String| -> () println!("{}", foo) );
as_buf("foo".to_string(), |foo: String| -> () { println!("{}", foo) });
}

View File

@ -14,6 +14,6 @@
pub fn main() {
let bar: Box<_> = box 3;
let h = || -> int *bar;
let h = || -> int { *bar };
assert_eq!(h(), 3);
}

View File

@ -14,7 +14,7 @@ use std::marker::PhantomData;
fn main() {
struct Symbol<'a, F: Fn(Vec<&'a str>) -> &'a str> { function: F, marker: PhantomData<&'a ()> }
let f = |x: Vec<&str>| -> &str "foobar";
let f = |x: Vec<&str>| -> &str { "foobar" };
let sym = Symbol { function: f, marker: PhantomData };
(sym.function)(vec![]);
}