This PR allows the quote macros to unquote trait items, impl items, where clauses, and paths.
CTEST_DISABLE_debuginfo-gdb = "gdb on darwin needs root"
endif
+ifeq ($(findstring android, $(CFG_TARGET)), android)
+CTEST_DISABLE_debuginfo-gdb =
+CTEST_DISABLE_debuginfo-lldb = "lldb tests are disabled on android"
+endif
+
# CTEST_DISABLE_NONSELFHOST_$(TEST_GROUP), if set, will cause that
# test group to be disabled *unless* the target is able to build a
# compiler (i.e. when the target triple is in the set of of host
* Sending signals
* Accessing/modifying the file system
* Unsigned integer overflow (well-defined as wrapping)
-* Signed integer overflow (well-defined as two's complement representation
+* Signed integer overflow (well-defined as two’s complement representation
wrapping)
#### Diverging functions
: Exclusive or.
Calls the `bitxor` method of the `std::ops::BitXor` trait.
* `<<`
- : Logical left shift.
+ : Left shift.
Calls the `shl` method of the `std::ops::Shl` trait.
* `>>`
- : Logical right shift.
+ : Right shift.
Calls the `shr` method of the `std::ops::Shr` trait.
#### Lazy boolean operators
* [More Strings](more-strings.md)
* [Patterns](patterns.md)
* [Method Syntax](method-syntax.md)
+ * [Associated Types](associated-types.md)
* [Closures](closures.md)
* [Iterators](iterators.md)
* [Generics](generics.md)
--- /dev/null
+% Associated Types
+
+Associated types are a powerful part of Rust's type system. They're related to
+the idea of a 'type family', in other words, grouping multiple types together. That
+description is a bit abstract, so let's dive right into an example. If you want
+to write a `Graph` trait, you have two types to be generic over: the node type
+and the edge type. So you might write a trait, `Graph<N, E>`, that looks like
+this:
+
+```rust
+trait Graph<N, E> {
+ fn has_edge(&self, &N, &N) -> bool;
+ fn edges(&self, &N) -> Vec<E>;
+ // etc
+}
+```
+
+While this sort of works, it ends up being awkward. For example, any function
+that wants to take a `Graph` as a parameter now _also_ needs to be generic over
+the `N`ode and `E`dge types too:
+
+```rust,ignore
+fn distance<N, E, G: Graph<N, E>>(graph: &G, start: &N, end: &N) -> u32 { ... }
+```
+
+Our distance calculation works regardless of our `Edge` type, so the `E` stuff in
+this signature is just a distraction.
+
+What we really want to say is that a certain `E`dge and `N`ode type come together
+to form each kind of `Graph`. We can do that with associated types:
+
+```rust
+trait Graph {
+ type N;
+ type E;
+
+ fn has_edge(&self, &Self::N, &Self::N) -> bool;
+ fn edges(&self, &Self::N) -> Vec<Self::E>;
+ // etc
+}
+```
+
+Now, our clients can be abstract over a given `Graph`:
+
+```rust,ignore
+fn distance<G: Graph>(graph: &G, start: &G::N, end: &G::N) -> uint { ... }
+```
+
+No need to deal with the `E`dge type here!
+
+Let's go over all this in more detail.
+
+## Defining associated types
+
+Let's build that `Graph` trait. Here's the definition:
+
+```rust
+trait Graph {
+ type N;
+ type E;
+
+ fn has_edge(&self, &Self::N, &Self::N) -> bool;
+ fn edges(&self, &Self::N) -> Vec<Self::E>;
+}
+```
+
+Simple enough. Associated types use the `type` keyword, and go inside the body
+of the trait, with the functions.
+
+These `type` declarations can have all the same thing as functions do. For example,
+if we wanted our `N` type to implement `Display`, so we can print the nodes out,
+we could do this:
+
+```rust
+use std::fmt;
+
+trait Graph {
+ type N: fmt::Display;
+ type E;
+
+ fn has_edge(&self, &Self::N, &Self::N) -> bool;
+ fn edges(&self, &Self::N) -> Vec<Self::E>;
+}
+```
+
+## Implementing associated types
+
+Just like any trait, traits that use associated types use the `impl` keyword to
+provide implementations. Here's a simple implementation of Graph:
+
+```rust
+# trait Graph {
+# type N;
+# type E;
+# fn has_edge(&self, &Self::N, &Self::N) -> bool;
+# fn edges(&self, &Self::N) -> Vec<Self::E>;
+# }
+struct Node;
+
+struct Edge;
+
+struct MyGraph;
+
+impl Graph for MyGraph {
+ type N = Node;
+ type E = Edge;
+
+ fn has_edge(&self, n1: &Node, n2: &Node) -> bool {
+ true
+ }
+
+ fn edges(&self, n: &Node) -> Vec<Edge> {
+ Vec::new()
+ }
+}
+```
+
+This silly implementation always returns `true` and an empty `Vec<Edge>`, but it
+gives you an idea of how to implement this kind of thing. We first need three
+`struct`s, one for the graph, one for the node, and one for the edge. If it made
+more sense to use a different type, that would work as well, we're just going to
+use `struct`s for all three here.
+
+Next is the `impl` line, which is just like implementing any other trait.
+
+From here, we use `=` to define our associated types. The name the trait uses
+goes on the left of the `=`, and the concrete type we're `impl`ementing this
+for goes on the right. Finally, we use the concrete types in our function
+declarations.
+
+## Trait objects with associated types
+
+There’s one more bit of syntax we should talk about: trait objects. If you
+try to create a trait object from an associated type, like this:
+
+```rust,ignore
+# trait Graph {
+# type N;
+# type E;
+# fn has_edge(&self, &Self::N, &Self::N) -> bool;
+# fn edges(&self, &Self::N) -> Vec<Self::E>;
+# }
+# struct Node;
+# struct Edge;
+# struct MyGraph;
+# impl Graph for MyGraph {
+# type N = Node;
+# type E = Edge;
+# fn has_edge(&self, n1: &Node, n2: &Node) -> bool {
+# true
+# }
+# fn edges(&self, n: &Node) -> Vec<Edge> {
+# Vec::new()
+# }
+# }
+let graph = MyGraph;
+let obj = Box::new(graph) as Box<Graph>;
+```
+
+You’ll get two errors:
+
+```text
+error: the value of the associated type `E` (from the trait `main::Graph`) must
+be specified [E0191]
+let obj = Box::new(graph) as Box<Graph>;
+ ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+24:44 error: the value of the associated type `N` (from the trait
+`main::Graph`) must be specified [E0191]
+let obj = Box::new(graph) as Box<Graph>;
+ ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+```
+
+We can’t create a trait object like this, becuase we don’t know the associated
+types. Instead, we can write this:
+
+```rust
+# trait Graph {
+# type N;
+# type E;
+# fn has_edge(&self, &Self::N, &Self::N) -> bool;
+# fn edges(&self, &Self::N) -> Vec<Self::E>;
+# }
+# struct Node;
+# struct Edge;
+# struct MyGraph;
+# impl Graph for MyGraph {
+# type N = Node;
+# type E = Edge;
+# fn has_edge(&self, n1: &Node, n2: &Node) -> bool {
+# true
+# }
+# fn edges(&self, n: &Node) -> Vec<Edge> {
+# Vec::new()
+# }
+# }
+let graph = MyGraph;
+let obj = Box::new(graph) as Box<Graph<N=Node, E=Edge>>;
+```
+
+The `N=Node` syntax allows us to provide a concrete type, `Node`, for the `N`
+type parameter. Same with `E=Edge`. If we didn’t proide this constraint, we
+couldn’t be sure which `impl` to match this trait object to.
### Examples
-Here are some examples of functions with elided lifetimes, and the version of
-what the elided lifetimes are expand to:
+Here are some examples of functions with elided lifetimes. We've paired each
+example of an elided lifetime with its expanded form.
```{rust,ignore}
fn print(s: &str); // elided
// Define a wrapper around the handle returned by the foreign code.
// Unique<T> has the same semantics as Box<T>
-pub struct Unique<T> {
+//
+// NB: For simplicity and correctness, we require that T has kind Send
+// (owned boxes relax this restriction).
+pub struct Unique<T: Send> {
// It contains a single raw, mutable pointer to the object in question.
ptr: *mut T
}
// Implement methods for creating and using the values in the box.
-// NB: For simplicity and correctness, we require that T has kind Send
-// (owned boxes relax this restriction).
impl<T: Send> Unique<T> {
pub fn new(value: T) -> Unique<T> {
unsafe {
// Unique<T>, making the struct manage the raw pointer: when the
// struct goes out of scope, it will automatically free the raw pointer.
//
-// NB: This is an unsafe destructor, because rustc will not normally
-// allow destructors to be associated with parameterized types, due to
-// bad interaction with managed boxes. (With the Send restriction,
-// we don't have this problem.) Note that the `#[unsafe_destructor]`
-// feature gate is required to use unsafe destructors.
+// NB: This is an unsafe destructor; rustc will not normally allow
+// destructors to be associated with parameterized types (due to
+// historically failing to check them soundly). Note that the
+// `#[unsafe_destructor]` feature gate is currently required to use
+// unsafe destructors.
#[unsafe_destructor]
impl<T: Send> Drop for Unique<T> {
fn drop(&mut self) {
put_const(S_IWUSR, int);
put_const(S_IRUSR, int);
+ put_const(S_IRWXG, int);
+ put_const(S_IXGRP, int);
+ put_const(S_IWGRP, int);
+ put_const(S_IRGRP, int);
+
+ put_const(S_IRWXO, int);
+ put_const(S_IXOTH, int);
+ put_const(S_IWOTH, int);
+ put_const(S_IROTH, int);
+
#ifdef F_OK
put_const(F_OK, int);
#endif
#[unsafe_destructor]
#[stable(feature = "rust1", since = "1.0.0")]
-impl<T: Sync + Send> Drop for Arc<T> {
+impl<T> Drop for Arc<T> {
/// Drops the `Arc<T>`.
///
/// This will decrement the strong reference count. If the strong reference
#[unstable(feature = "alloc",
reason = "Weak pointers may not belong in this module.")]
-impl<T: Sync + Send> Weak<T> {
+impl<T> Weak<T> {
/// Upgrades a weak reference to a strong reference.
///
/// Upgrades the `Weak<T>` reference to an `Arc<T>`, if possible.
#[unsafe_destructor]
#[stable(feature = "rust1", since = "1.0.0")]
-impl<T: Sync + Send> Drop for Weak<T> {
+impl<T> Drop for Weak<T> {
/// Drops the `Weak<T>`.
///
/// This will decrement the weak reference count.
// Destroy the next chunk.
let next = self.next;
let size = calculate_size::<T>(self.capacity);
- deallocate(self as *mut TypedArenaChunk<T> as *mut u8, size,
+ let self_ptr: *mut TypedArenaChunk<T> = self;
+ deallocate(self_ptr as *mut u8, size,
mem::min_align_of::<TypedArenaChunk<T>>());
if !next.is_null() {
let capacity = (*next).capacity;
pub fn is_empty(&self) -> bool { self.len() == 0 }
/// Clears the binary heap, returning an iterator over the removed elements.
+ ///
+ /// The elements are removed in arbitrary order.
#[inline]
#[unstable(feature = "collections",
reason = "matches collection reform specification, waiting for dust to settle")]
html_playground_url = "http://play.rust-lang.org/")]
#![doc(test(no_crate_inject))]
+#![allow(trivial_casts)]
+#![allow(trivial_numeric_casts)]
#![feature(alloc)]
#![feature(box_syntax)]
#![feature(box_patterns)]
//! The `slice` module contains useful code to help work with slice values.
//! Slices are a view into a block of memory represented as a pointer and a length.
//!
-//! ```rust
-//! # #![feature(core)]
+//! ```
//! // slicing a Vec
-//! let vec = vec!(1, 2, 3);
-//! let int_slice = vec.as_slice();
+//! let vec = vec![1, 2, 3];
+//! let int_slice = &vec[..];
//! // coercing an array to a slice
//! let str_slice: &[&str] = &["one", "two", "three"];
//! ```
//!
//! Slices are either mutable or shared. The shared slice type is `&[T]`,
-//! while the mutable slice type is `&mut[T]`. For example, you can mutate the
-//! block of memory that a mutable slice points to:
+//! while the mutable slice type is `&mut [T]`, where `T` represents the element
+//! type. For example, you can mutate the block of memory that a mutable slice
+//! points to:
//!
-//! ```rust
-//! let x: &mut[i32] = &mut [1, 2, 3];
+//! ```
+//! let x = &mut [1, 2, 3];
//! x[1] = 7;
-//! assert_eq!(x[0], 1);
-//! assert_eq!(x[1], 7);
-//! assert_eq!(x[2], 3);
+//! assert_eq!(x, &[1, 7, 3]);
//! ```
//!
//! Here are some of the things this module contains:
//! There are several structs that are useful for slices, such as `Iter`, which
//! represents iteration over a slice.
//!
-//! ## Traits
-//!
-//! A number of traits add methods that allow you to accomplish tasks
-//! with slices, the most important being `SliceExt`. Other traits
-//! apply only to slices of elements satisfying certain bounds (like
-//! `Ord`).
-//!
-//! An example is the `slice` method which enables slicing syntax `[a..b]` that
-//! returns an immutable "view" into a `Vec` or another slice from the index
-//! interval `[a, b)`:
-//!
-//! ```rust
-//! fn main() {
-//! let numbers = [0, 1, 2];
-//! let last_numbers = &numbers[1..3];
-//! // last_numbers is now &[1, 2]
-//! }
-//! ```
-//!
-//! ## Implementations of other traits
+//! ## Trait Implementations
//!
//! There are several implementations of common traits for slices. Some examples
//! include:
//!
//! * `Clone`
-//! * `Eq`, `Ord` - for immutable slices whose element type are `Eq` or `Ord`.
+//! * `Eq`, `Ord` - for slices whose element type are `Eq` or `Ord`.
//! * `Hash` - for slices whose element type is `Hash`
//!
//! ## Iteration
//!
-//! The method `iter()` returns an iteration value for a slice. The iterator
-//! yields references to the slice's elements, so if the element
-//! type of the slice is `isize`, the element type of the iterator is `&isize`.
+//! The slices implement `IntoIterator`. The iterators of yield references
+//! to the slice elements.
//!
-//! ```rust
-//! let numbers = [0, 1, 2];
-//! for &x in numbers.iter() {
-//! println!("{} is a number!", x);
+//! ```
+//! let numbers = &[0, 1, 2];
+//! for n in numbers {
+//! println!("{} is a number!", n);
//! }
//! ```
//!
-//! * `.iter_mut()` returns an iterator that allows modifying each value.
-//! * Further iterators exist that split, chunk or permute the slice.
+//! The mutable slice yields mutable references to the elements:
+//!
+//! ```
+//! let mut scores = [7, 8, 9];
+//! for score in &mut scores[..] {
+//! *score += 1;
+//! }
+//! ```
+//!
+//! This iterator yields mutable references to the slice's elements, so while the element
+//! type of the slice is `i32`, the element type of the iterator is `&mut i32`.
+//!
+//! * `.iter()` and `.iter_mut()` are the explicit methods to return the default
+//! iterators.
+//! * Further methods that return iterators are `.split()`, `.splitn()`,
+//! `.chunks()`, `.windows()` and more.
#![doc(primitive = "slice")]
#![stable(feature = "rust1", since = "1.0.0")]
//! are owned elsewhere.
//!
//! Basic operations are implemented directly by the compiler, but more advanced
-//! operations are defined on the [`StrExt`](trait.StrExt.html) trait.
+//! operations are defined as methods on the `str` type.
//!
//! # Examples
//!
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn push(&mut self, value: T) {
+ #[cold]
+ #[inline(never)]
+ fn resize<T>(vec: &mut Vec<T>) {
+ let old_size = vec.cap * mem::size_of::<T>();
+ let size = max(old_size, 2 * mem::size_of::<T>()) * 2;
+ if old_size > size { panic!("capacity overflow") }
+ unsafe {
+ let ptr = alloc_or_realloc(*vec.ptr, old_size, size);
+ if ptr.is_null() { ::alloc::oom() }
+ vec.ptr = Unique::new(ptr);
+ }
+ vec.cap = max(vec.cap, 2) * 2;
+ }
+
if mem::size_of::<T>() == 0 {
// zero-size types consume no memory, so we can't rely on the
// address space running out
unsafe { mem::forget(value); }
return
}
+
if self.len == self.cap {
- let old_size = self.cap * mem::size_of::<T>();
- let size = max(old_size, 2 * mem::size_of::<T>()) * 2;
- if old_size > size { panic!("capacity overflow") }
- unsafe {
- let ptr = alloc_or_realloc(*self.ptr, old_size, size);
- if ptr.is_null() { ::alloc::oom() }
- self.ptr = Unique::new(ptr);
- }
- self.cap = max(self.cap, 2) * 2;
+ resize(self);
}
unsafe {
// Avoid bounds checks by using unsafe pointers.
let p = self.as_mut_ptr();
- let mut r = 1;
- let mut w = 1;
+ let mut r: usize = 1;
+ let mut w: usize = 1;
while r < ln {
let p_r = p.offset(r as isize);
}
impl<'a, 'b, 'c> FnMut<(&'c i32,)> for Counter<'a, 'b> {
- type Output = bool;
-
extern "rust-call" fn call_mut(&mut self, (&x,): (&'c i32,)) -> bool {
assert_eq!(x, self.expected[*self.i]);
*self.i += 1;
}
}
+impl<'a, 'b, 'c> FnOnce<(&'c i32,)> for Counter<'a, 'b> {
+ type Output = bool;
+
+ extern "rust-call" fn call_once(mut self, args: (&'c i32,)) -> bool {
+ self.call_mut(args)
+ }
+}
+
fn check<F>(a: &[i32], b: &[i32], expected: &[i32], f: F) where
// FIXME Replace Counter with `Box<FnMut(_) -> _>`
F: FnOnce(&BTreeSet<i32>, &BTreeSet<i32>, Counter) -> bool,
// Any trait
///////////////////////////////////////////////////////////////////////////////
-/// The `Any` trait is implemented by all `'static` types, and can be used for
-/// dynamic typing
+/// A type to emulate dynamic typing. See the [module-level documentation][mod] for more details.
///
-/// Every type with no non-`'static` references implements `Any`, so `Any` can
-/// be used as a trait object to emulate the effects dynamic typing.
+/// Every type with no non-`'static` references implements `Any`.
+///
+/// [mod]: ../index.html
#[stable(feature = "rust1", since = "1.0.0")]
pub trait Any: 'static {
/// Get the `TypeId` of `self`
/// ```
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
- pub fn get(&self) -> *mut T { &self.value as *const T as *mut T }
+ pub fn get(&self) -> *mut T {
+ // FIXME(#23542) Replace with type ascription.
+ #![allow(trivial_casts)]
+ &self.value as *const T as *mut T
+ }
/// Unwraps the value
///
#[stable(feature = "rust1", since = "1.0.0")]
pub trait Clone : Sized {
/// Returns a copy of the value.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// let hello = "Hello"; // &str implements Clone
+ ///
+ /// assert_eq!("Hello", hello.clone());
+ /// ```
#[stable(feature = "rust1", since = "1.0.0")]
fn clone(&self) -> Self;
#[stable(feature = "rust1", since = "1.0.0")]
impl<T> Pointer for *mut T {
fn fmt(&self, f: &mut Formatter) -> Result {
+ // FIXME(#23542) Replace with type ascription.
+ #![allow(trivial_casts)]
Pointer::fmt(&(*self as *const T), f)
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T> Pointer for &'a T {
fn fmt(&self, f: &mut Formatter) -> Result {
+ // FIXME(#23542) Replace with type ascription.
+ #![allow(trivial_casts)]
Pointer::fmt(&(*self as *const T), f)
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, T> Pointer for &'a mut T {
fn fmt(&self, f: &mut Formatter) -> Result {
+ // FIXME(#23542) Replace with type ascription.
+ #![allow(trivial_casts)]
Pointer::fmt(&(&**self as *const T), f)
}
}
// FIXME: #6220 Implement floating point formatting
#![allow(unsigned_negation)]
+#![allow(trivial_numeric_casts)]
use fmt;
use iter::IteratorExt;
}
fn hash_slice<H: Hasher>(data: &[$ty], state: &mut H) {
+ // FIXME(#23542) Replace with type ascription.
+ #![allow(trivial_casts)]
let newlen = data.len() * ::$ty::BYTES as usize;
let ptr = data.as_ptr() as *const u8;
state.write(unsafe { slice::from_raw_parts(ptr, newlen) })
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
pub unsafe fn transmute_copy<T, U>(src: &T) -> U {
+ // FIXME(#23542) Replace with type ascription.
+ #![allow(trivial_casts)]
ptr::read(src as *const T as *const U)
}
#![stable(feature = "rust1", since = "1.0.0")]
#![doc(primitive = "i16")]
+#![allow(trivial_numeric_casts)]
int_module! { i16, 16 }
#![stable(feature = "rust1", since = "1.0.0")]
#![doc(primitive = "i32")]
+#![allow(trivial_numeric_casts)]
int_module! { i32, 32 }
#![stable(feature = "rust1", since = "1.0.0")]
#![doc(primitive = "i64")]
+#![allow(trivial_numeric_casts)]
int_module! { i64, 64 }
#![stable(feature = "rust1", since = "1.0.0")]
#![doc(primitive = "i8")]
+#![allow(trivial_numeric_casts)]
int_module! { i8, 8 }
// except according to those terms.
#![doc(hidden)]
+#![allow(trivial_numeric_casts)]
macro_rules! int_module { ($T:ty, $bits:expr) => (
#![stable(feature = "rust1", since = "1.0.0")]
#![doc(primitive = "isize")]
+#![allow(trivial_numeric_casts)]
#[cfg(target_pointer_width = "32")]
int_module! { isize, 32 }
#![stable(feature = "rust1", since = "1.0.0")]
#![allow(missing_docs)]
+#![allow(trivial_numeric_casts)]
use self::wrapping::{OverflowingOps, WrappingOps};
#![stable(feature = "rust1", since = "1.0.0")]
#![doc(primitive = "u16")]
+#![allow(trivial_numeric_casts)]
uint_module! { u16, i16, 16 }
#![stable(feature = "rust1", since = "1.0.0")]
#![doc(primitive = "u32")]
+#![allow(trivial_numeric_casts)]
uint_module! { u32, i32, 32 }
#![stable(feature = "rust1", since = "1.0.0")]
#![doc(primitive = "u64")]
+#![allow(trivial_numeric_casts)]
uint_module! { u64, i64, 64 }
#![stable(feature = "rust1", since = "1.0.0")]
#![doc(primitive = "u8")]
+#![allow(trivial_numeric_casts)]
uint_module! { u8, i8, 8 }
// except according to those terms.
#![doc(hidden)]
+#![allow(trivial_numeric_casts)]
macro_rules! uint_module { ($T:ty, $T_SIGNED:ty, $bits:expr) => (
#![stable(feature = "rust1", since = "1.0.0")]
#![doc(primitive = "usize")]
+#![allow(trivial_numeric_casts)]
uint_module! { usize, isize, ::isize::BITS }
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Range<Idx> {
/// The lower bound of the range (inclusive).
+ #[stable(feature = "rust1", since = "1.0.0")]
pub start: Idx,
/// The upper bound of the range (exclusive).
+ #[stable(feature = "rust1", since = "1.0.0")]
pub end: Idx,
}
#[stable(feature = "rust1", since = "1.0.0")]
pub struct RangeFrom<Idx> {
/// The lower bound of the range (inclusive).
+ #[stable(feature = "rust1", since = "1.0.0")]
pub start: Idx,
}
-
-
#[stable(feature = "rust1", since = "1.0.0")]
impl<Idx: fmt::Debug> fmt::Debug for RangeFrom<Idx> {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
#[stable(feature = "rust1", since = "1.0.0")]
pub struct RangeTo<Idx> {
/// The upper bound of the range (exclusive).
+ #[stable(feature = "rust1", since = "1.0.0")]
pub end: Idx,
}
}
}
-
/// The `Deref` trait is used to specify the functionality of dereferencing
/// operations like `*v`.
///
#[lang="fn"]
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_paren_sugar]
+#[cfg(stage0)]
pub trait Fn<Args> {
/// The returned type after the call operator is used.
type Output;
extern "rust-call" fn call(&self, args: Args) -> Self::Output;
}
+/// A version of the call operator that takes an immutable receiver.
+#[lang="fn"]
+#[stable(feature = "rust1", since = "1.0.0")]
+#[rustc_paren_sugar]
+#[cfg(not(stage0))]
+pub trait Fn<Args> : FnMut<Args> {
+ /// This is called when the call operator is used.
+ extern "rust-call" fn call(&self, args: Args) -> Self::Output;
+}
+
/// A version of the call operator that takes a mutable receiver.
#[lang="fn_mut"]
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_paren_sugar]
+#[cfg(stage0)]
pub trait FnMut<Args> {
/// The returned type after the call operator is used.
type Output;
extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output;
}
+/// A version of the call operator that takes a mutable receiver.
+#[lang="fn_mut"]
+#[stable(feature = "rust1", since = "1.0.0")]
+#[rustc_paren_sugar]
+#[cfg(not(stage0))]
+pub trait FnMut<Args> : FnOnce<Args> {
+ /// This is called when the call operator is used.
+ extern "rust-call" fn call_mut(&mut self, args: Args) -> Self::Output;
+}
+
/// A version of the call operator that takes a by-value receiver.
#[lang="fn_once"]
#[stable(feature = "rust1", since = "1.0.0")]
extern "rust-call" fn call_once(self, args: Args) -> Self::Output;
}
+#[cfg(stage0)]
impl<F: ?Sized, A> FnMut<A> for F
where F : Fn<A>
{
}
}
+#[cfg(stage0)]
impl<F,A> FnOnce<A> for F
where F : FnMut<A>
{
/// Create a new `Unique`.
#[unstable(feature = "unique")]
pub unsafe fn new(ptr: *mut T) -> Unique<T> {
- Unique { pointer: NonZero::new(ptr as *const T), _marker: PhantomData }
+ Unique { pointer: NonZero::new(ptr), _marker: PhantomData }
}
/// Dereference the content.
use iter::{Map, Iterator, IteratorExt, DoubleEndedIterator};
use marker::Sized;
use mem;
+#[allow(deprecated)]
use num::Int;
-use ops::{Fn, FnMut};
+use ops::{Fn, FnMut, FnOnce};
use option::Option::{self, None, Some};
use raw::{Repr, Slice};
use result::Result::{self, Ok, Err};
/// assert!(<bool as FromStr>::from_str("not even a boolean").is_err());
/// ```
///
- /// Note, in many cases, the StrExt::parse() which is based on
- /// this FromStr::from_str() is more proper.
+ /// Note, in many cases, the `.parse()` method on `str` is more proper.
///
/// ```
/// assert_eq!("true".parse(), Ok(true));
reason = "use std::ffi::c_str_to_bytes + str::from_utf8")]
pub unsafe fn from_c_str(s: *const i8) -> &'static str {
let s = s as *const u8;
- let mut len = 0;
+ let mut len: usize = 0;
while *s.offset(len as isize) != 0 {
len += 1;
}
/// External iterator for a string's bytes.
/// Use with the `std::iter` module.
///
-/// Created with `StrExt::bytes`
+/// Created with `str::bytes`
#[stable(feature = "rust1", since = "1.0.0")]
#[derive(Clone)]
pub struct Bytes<'a>(Map<slice::Iter<'a, u8>, BytesDeref>);
#[derive(Copy, Clone)]
struct BytesDeref;
+#[cfg(stage0)]
impl<'a> Fn<(&'a u8,)> for BytesDeref {
type Output = u8;
}
}
+#[cfg(not(stage0))]
+impl<'a> Fn<(&'a u8,)> for BytesDeref {
+ #[inline]
+ extern "rust-call" fn call(&self, (ptr,): (&'a u8,)) -> u8 {
+ *ptr
+ }
+}
+
+#[cfg(not(stage0))]
+impl<'a> FnMut<(&'a u8,)> for BytesDeref {
+ #[inline]
+ extern "rust-call" fn call_mut(&mut self, (ptr,): (&'a u8,)) -> u8 {
+ Fn::call(&*self, (ptr,))
+ }
+}
+
+#[cfg(not(stage0))]
+impl<'a> FnOnce<(&'a u8,)> for BytesDeref {
+ type Output = u8;
+
+ #[inline]
+ extern "rust-call" fn call_once(self, (ptr,): (&'a u8,)) -> u8 {
+ Fn::call(&self, (ptr,))
+ }
+}
+
/// An iterator over the substrings of a string, separated by `sep`.
struct CharSplits<'a, P: Pattern<'a>> {
/// The slice remaining to be iterated
fn as_slice(&self) -> &str { Str::as_slice(*self) }
}
-/// Return type of `StrExt::split`
+/// Return type of `str::split`
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Split<'a, P: Pattern<'a>>(CharSplits<'a, P>);
delegate_iter!{pattern &'a str : Split<'a, P>}
-/// Return type of `StrExt::split_terminator`
+/// Return type of `str::split_terminator`
#[stable(feature = "rust1", since = "1.0.0")]
pub struct SplitTerminator<'a, P: Pattern<'a>>(CharSplits<'a, P>);
delegate_iter!{pattern &'a str : SplitTerminator<'a, P>}
-/// Return type of `StrExt::splitn`
+/// Return type of `str::splitn`
#[stable(feature = "rust1", since = "1.0.0")]
pub struct SplitN<'a, P: Pattern<'a>>(CharSplitsN<'a, P>);
delegate_iter!{pattern forward &'a str : SplitN<'a, P>}
-/// Return type of `StrExt::rsplit`
+/// Return type of `str::rsplit`
#[stable(feature = "rust1", since = "1.0.0")]
pub struct RSplit<'a, P: Pattern<'a>>(RCharSplits<'a, P>);
delegate_iter!{pattern reverse &'a str : RSplit<'a, P>}
-/// Return type of `StrExt::rsplitn`
+/// Return type of `str::rsplitn`
#[stable(feature = "rust1", since = "1.0.0")]
pub struct RSplitN<'a, P: Pattern<'a>>(RCharSplitsN<'a, P>);
delegate_iter!{pattern reverse &'a str : RSplitN<'a, P>}
trait Foo { fn dummy(&self) { } }
impl Foo for int {}
- let a = box 100 as Box<Foo>;
+ let a = box 100isize as Box<Foo>;
unsafe {
let x: ::core::raw::TraitObject = transmute(a);
assert!(*(x.data as *const int) == 100);
assert_eq!(q.as_ref().unwrap(), &2);
// Lifetime inference
- let u = 2;
+ let u = 2isize;
{
- let p: *const int = &u as *const _;
+ let p = &u as *const int;
assert_eq!(p.as_ref().unwrap(), &2);
}
}
assert!(q.as_mut().unwrap() == &mut 2);
// Lifetime inference
- let mut u = 2;
+ let mut u = 2isize;
{
- let p: *mut int = &mut u as *mut _;
+ let p = &mut u as *mut int;
assert!(p.as_mut().unwrap() == &mut 2);
}
}
#[test]
fn test_unsized_unique() {
- let xs: &mut [_] = &mut [1, 2, 3];
- let ptr = unsafe { Unique::new(xs as *mut [_]) };
+ let xs: &mut [i32] = &mut [1, 2, 3];
+ let ptr = unsafe { Unique::new(xs as *mut [i32]) };
let ys = unsafe { &mut **ptr };
- let zs: &mut [_] = &mut [1, 2, 3];
+ let zs: &mut [i32] = &mut [1, 2, 3];
assert!(ys == zs);
}
}
pub mod posix88 {
use types::os::arch::c95::c_int;
+ use types::os::arch::posix88::mode_t;
pub const O_RDONLY : c_int = 0;
pub const O_WRONLY : c_int = 1;
pub const S_IXUSR : c_int = 64;
pub const S_IWUSR : c_int = 128;
pub const S_IRUSR : c_int = 256;
+ pub const S_IRWXG : mode_t = 56;
+ pub const S_IXGRP : mode_t = 8;
+ pub const S_IWGRP : mode_t = 16;
+ pub const S_IRGRP : mode_t = 32;
+ pub const S_IRWXO : mode_t = 7;
+ pub const S_IXOTH : mode_t = 1;
+ pub const S_IWOTH : mode_t = 2;
+ pub const S_IROTH : mode_t = 4;
pub const F_OK : c_int = 0;
pub const R_OK : c_int = 4;
pub const W_OK : c_int = 2;
pub const S_IXUSR : mode_t = 64;
pub const S_IWUSR : mode_t = 128;
pub const S_IRUSR : mode_t = 256;
+ pub const S_IRWXG : mode_t = 56;
+ pub const S_IXGRP : mode_t = 8;
+ pub const S_IWGRP : mode_t = 16;
+ pub const S_IRGRP : mode_t = 32;
+ pub const S_IRWXO : mode_t = 7;
+ pub const S_IXOTH : mode_t = 1;
+ pub const S_IWOTH : mode_t = 2;
+ pub const S_IROTH : mode_t = 4;
pub const F_OK : c_int = 0;
pub const R_OK : c_int = 4;
pub const W_OK : c_int = 2;
pub const S_IXUSR : mode_t = 64;
pub const S_IWUSR : mode_t = 128;
pub const S_IRUSR : mode_t = 256;
+ pub const S_IRWXG : mode_t = 56;
+ pub const S_IXGRP : mode_t = 8;
+ pub const S_IWGRP : mode_t = 16;
+ pub const S_IRGRP : mode_t = 32;
+ pub const S_IRWXO : mode_t = 7;
+ pub const S_IXOTH : mode_t = 1;
+ pub const S_IWOTH : mode_t = 2;
+ pub const S_IROTH : mode_t = 4;
pub const F_OK : c_int = 0;
pub const R_OK : c_int = 4;
pub const W_OK : c_int = 2;
pub const S_IXUSR : mode_t = 64;
pub const S_IWUSR : mode_t = 128;
pub const S_IRUSR : mode_t = 256;
+ pub const S_IRWXG : mode_t = 56;
+ pub const S_IXGRP : mode_t = 8;
+ pub const S_IWGRP : mode_t = 16;
+ pub const S_IRGRP : mode_t = 32;
+ pub const S_IRWXO : mode_t = 7;
+ pub const S_IXOTH : mode_t = 1;
+ pub const S_IWOTH : mode_t = 2;
+ pub const S_IROTH : mode_t = 4;
pub const F_OK : c_int = 0;
pub const R_OK : c_int = 4;
pub const W_OK : c_int = 2;
pub const S_IXUSR : mode_t = 64;
pub const S_IWUSR : mode_t = 128;
pub const S_IRUSR : mode_t = 256;
+ pub const S_IRWXG : mode_t = 56;
+ pub const S_IXGRP : mode_t = 8;
+ pub const S_IWGRP : mode_t = 16;
+ pub const S_IRGRP : mode_t = 32;
+ pub const S_IRWXO : mode_t = 7;
+ pub const S_IXOTH : mode_t = 1;
+ pub const S_IWOTH : mode_t = 2;
+ pub const S_IROTH : mode_t = 4;
pub const F_OK : c_int = 0;
pub const R_OK : c_int = 4;
pub const W_OK : c_int = 2;
pub const S_IXUSR : mode_t = 64;
pub const S_IWUSR : mode_t = 128;
pub const S_IRUSR : mode_t = 256;
+ pub const S_IRWXG : mode_t = 56;
+ pub const S_IXGRP : mode_t = 8;
+ pub const S_IWGRP : mode_t = 16;
+ pub const S_IRGRP : mode_t = 32;
+ pub const S_IRWXO : mode_t = 7;
+ pub const S_IXOTH : mode_t = 1;
+ pub const S_IWOTH : mode_t = 2;
+ pub const S_IROTH : mode_t = 4;
pub const F_OK : c_int = 0;
pub const R_OK : c_int = 4;
pub const W_OK : c_int = 2;
// Completely remove the local logger from TLS in case anyone attempts to
// frob the slot while we're doing the logging. This will destroy any logger
// set during logging.
- let mut logger = LOCAL_LOGGER.with(|s| {
+ let mut logger: Box<Logger + Send> = LOCAL_LOGGER.with(|s| {
s.borrow_mut().take()
}).unwrap_or_else(|| {
- box DefaultLogger { handle: io::stderr() } as Box<Logger + Send>
+ box DefaultLogger { handle: io::stderr() }
});
logger.log(&LogRecord {
level: LogLevel(level),
DIRECTIVES = boxed::into_raw(box directives);
// Schedule the cleanup for the globals for when the runtime exits.
- rt::at_exit(move || {
+ let _ = rt::at_exit(move || {
let _g = LOCK.lock();
assert!(!DIRECTIVES.is_null());
let _directives = Box::from_raw(DIRECTIVES);
//! Generating numbers between two others.
+#![allow(trivial_numeric_casts)]
+
// this is surprisingly complicated to be both generic & correct
use core::prelude::{PartialOrd};
#[inline]
fn next_u64(&mut self) -> u64 {
+ #![allow(trivial_numeric_casts)]
if self.cnt == 0 {
// make some more numbers
self.isaac64();
let i = (val >> 28) as uint;
let (shift, mask) = SHIFT_MASK_TABLE[i];
Ok(Res {
- val: ((val >> shift) & mask) as uint,
- next: start + (((32 - shift) >> 3) as uint)
+ val: ((val >> shift) & mask) as usize,
+ next: start + ((32 - shift) >> 3),
})
}
}
0 => doc_as_u8(r_doc) as u64,
1 => doc_as_u16(r_doc) as u64,
2 => doc_as_u32(r_doc) as u64,
- 3 => doc_as_u64(r_doc) as u64,
+ 3 => doc_as_u64(r_doc),
_ => unreachable!(),
}
} else {
#![feature(into_cow)]
#![cfg_attr(test, feature(test))]
+#![allow(trivial_casts)]
+#![allow(trivial_numeric_casts)]
+
extern crate arena;
extern crate flate;
extern crate fmt_macros;
"detects transmutes of fat pointers"
}
+declare_lint! {
+ pub TRIVIAL_CASTS,
+ Warn,
+ "detects trivial casts which could be removed"
+}
+
+declare_lint! {
+ pub TRIVIAL_NUMERIC_CASTS,
+ Warn,
+ "detects trivial casts of numeric types which could be removed"
+}
/// Does nothing as a lint pass, but registers some `Lint`s
/// which are used by other parts of the compiler.
#[derive(Copy)]
STABLE_FEATURES,
UNKNOWN_CRATE_TYPES,
VARIANT_SIZE_DIFFERENCES,
- FAT_PTR_TRANSMUTES
+ FAT_PTR_TRANSMUTES,
+ TRIVIAL_CASTS,
+ TRIVIAL_NUMERIC_CASTS
)
}
}
}
pub fn validate_crate_name(sess: Option<&Session>, s: &str, sp: Option<Span>) {
- let err = |s: &str| {
+ let say = |s: &str, warn: bool| {
match (sp, sess) {
(_, None) => panic!("{}", s),
+ (Some(sp), Some(sess)) if warn => sess.span_warn(sp, s),
(Some(sp), Some(sess)) => sess.span_err(sp, s),
+ (None, Some(sess)) if warn => sess.warn(s),
(None, Some(sess)) => sess.err(s),
}
};
if s.len() == 0 {
- err("crate name must not be empty");
- } else if s.char_at(0) == '-' {
- err(&format!("crate name cannot start with a hyphen: {}", s));
+ say("crate name must not be empty", false);
+ } else if s.contains("-") {
+ say(&format!("crate names soon cannot contain hyphens: {}", s), true);
}
for c in s.chars() {
if c.is_alphanumeric() { continue }
if c == '_' || c == '-' { continue }
- err(&format!("invalid character `{}` in crate name: `{}`", c, s));
+ say(&format!("invalid character `{}` in crate name: `{}`", c, s), false);
}
match sess {
Some(sess) => sess.abort_if_errors(),
}
}
- // Traverses an AST, reading all the information about use'd crates and extern
- // libraries necessary for later resolving, typechecking, linking, etc.
+ // Traverses an AST, reading all the information about use'd crates and
+ // extern libraries necessary for later resolving, typechecking, linking,
+ // etc.
pub fn read_crates(&mut self, krate: &ast::Crate) {
self.process_crate(krate);
visit::walk_crate(self, krate);
debug!("resolving extern crate stmt. ident: {} path_opt: {:?}",
ident, path_opt);
let name = match *path_opt {
- Some((ref path_str, _)) => {
- let name = path_str.to_string();
- validate_crate_name(Some(self.sess), &name[..],
+ Some(name) => {
+ validate_crate_name(Some(self.sess), name.as_str(),
Some(i.span));
- name
+ name.as_str().to_string()
}
None => ident.to_string(),
};
-> Option<ast::CrateNum> {
let mut ret = None;
self.sess.cstore.iter_crate_data(|cnum, data| {
- if data.name != name { return }
+ // For now we do a "fuzzy match" on crate names by considering
+ // hyphens equal to underscores. This is purely meant to be a
+ // transitionary feature while we deprecate the quote syntax of
+ // `extern crate` statements.
+ if data.name != name.replace("-", "_") {
+ return
+ }
match hash {
Some(hash) if *hash == data.hash() => { ret = Some(cnum); return }
}
};
- let message_root_str = match trace.origin {
- infer::Misc(_) => "mismatched types",
- infer::MethodCompatCheck(_) => "method not compatible with trait",
- infer::ExprAssignable(_) => "mismatched types",
- infer::RelateTraitRefs(_) => "mismatched traits",
- infer::RelateSelfType(_) => "mismatched types",
- infer::RelateOutputImplTypes(_) => "mismatched types",
- infer::MatchExpressionArm(_, _) => "match arms have incompatible types",
- infer::IfExpression(_) => "if and else have incompatible types",
- infer::IfExpressionWithNoElse(_) => "if may be missing an else clause",
- infer::RangeExpression(_) => "start and end of range have incompatible types",
- infer::EquatePredicate(_) => "equality predicate not satisfied",
- };
-
span_err!(self.tcx.sess, trace.origin.span(), E0308,
"{}: {} ({})",
- message_root_str,
+ trace.origin,
expected_found_str,
ty::type_err_to_str(self.tcx, terr));
infer::Subtype(ref trace) => {
let desc = match trace.origin {
infer::Misc(_) => {
- format!("types are compatible")
+ "types are compatible"
}
infer::MethodCompatCheck(_) => {
- format!("method type is compatible with trait")
+ "method type is compatible with trait"
}
infer::ExprAssignable(_) => {
- format!("expression is assignable")
+ "expression is assignable"
}
infer::RelateTraitRefs(_) => {
- format!("traits are compatible")
+ "traits are compatible"
}
infer::RelateSelfType(_) => {
- format!("self type matches impl self type")
+ "self type matches impl self type"
}
infer::RelateOutputImplTypes(_) => {
- format!("trait type parameters matches those \
- specified on the impl")
+ "trait type parameters matches those \
+ specified on the impl"
}
infer::MatchExpressionArm(_, _) => {
- format!("match arms have compatible types")
+ "match arms have compatible types"
}
infer::IfExpression(_) => {
- format!("if and else have compatible types")
+ "if and else have compatible types"
}
infer::IfExpressionWithNoElse(_) => {
- format!("if may be missing an else clause")
+ "if may be missing an else clause"
}
infer::RangeExpression(_) => {
- format!("start and end of range have compatible types")
+ "start and end of range have compatible types"
}
infer::EquatePredicate(_) => {
- format!("equality where clause is satisfied")
+ "equality where clause is satisfied"
}
};
infer::RelateRegionParamBound(span) => {
self.tcx.sess.span_note(
span,
- &format!("...so that the declared lifetime parameter bounds \
- are satisfied"));
+ "...so that the declared lifetime parameter bounds \
+ are satisfied");
}
infer::SafeDestructor(span) => {
self.tcx.sess.span_note(
use super::{CombinedSnapshot, cres, InferCtxt, HigherRankedType, SkolemizationMap};
use super::combine::{Combine, Combineable};
+use middle::subst;
use middle::ty::{self, Binder};
use middle::ty_fold::{self, TypeFoldable};
use syntax::codemap::Span;
}
}
+/// Constructs and returns a substitution that, for a given type
+/// scheme parameterized by `generics`, will replace every generic
+/// parmeter in the type with a skolemized type/region (which one can
+/// think of as a "fresh constant", except at the type/region level of
+/// reasoning).
+///
+/// Since we currently represent bound/free type parameters in the
+/// same way, this only has an effect on regions.
+///
+/// (Note that unlike a substitution from `ty::construct_free_substs`,
+/// this inserts skolemized regions rather than free regions; this
+/// allows one to use `fn leak_check` to catch attmepts to unify the
+/// skolemized regions with e.g. the `'static` lifetime)
+pub fn construct_skolemized_substs<'a,'tcx>(infcx: &InferCtxt<'a,'tcx>,
+ generics: &ty::Generics<'tcx>,
+ snapshot: &CombinedSnapshot)
+ -> (subst::Substs<'tcx>, SkolemizationMap)
+{
+ let mut map = FnvHashMap();
+
+ // map T => T
+ let mut types = subst::VecPerParamSpace::empty();
+ push_types_from_defs(infcx.tcx, &mut types, generics.types.as_slice());
+
+ // map early- or late-bound 'a => fresh 'a
+ let mut regions = subst::VecPerParamSpace::empty();
+ push_region_params(infcx, &mut map, &mut regions, generics.regions.as_slice(), snapshot);
+
+ let substs = subst::Substs { types: types,
+ regions: subst::NonerasedRegions(regions) };
+ return (substs, map);
+
+ fn push_region_params<'a,'tcx>(infcx: &InferCtxt<'a,'tcx>,
+ map: &mut SkolemizationMap,
+ regions: &mut subst::VecPerParamSpace<ty::Region>,
+ region_params: &[ty::RegionParameterDef],
+ snapshot: &CombinedSnapshot)
+ {
+ for r in region_params {
+ let br = r.to_bound_region();
+ let skol_var = infcx.region_vars.new_skolemized(br, &snapshot.region_vars_snapshot);
+ let sanity_check = map.insert(br, skol_var);
+ assert!(sanity_check.is_none());
+ regions.push(r.space, skol_var);
+ }
+ }
+
+ fn push_types_from_defs<'tcx>(tcx: &ty::ctxt<'tcx>,
+ types: &mut subst::VecPerParamSpace<ty::Ty<'tcx>>,
+ defs: &[ty::TypeParameterDef<'tcx>]) {
+ for def in defs {
+ let ty = ty::mk_param_from_def(tcx, def);
+ types.push(def.space, ty);
+ }
+ }
+}
+
pub fn skolemize_late_bound_regions<'a,'tcx,T>(infcx: &InferCtxt<'a,'tcx>,
binder: &ty::Binder<T>,
snapshot: &CombinedSnapshot)
use middle::ty::{self, Ty};
use middle::ty_fold::{TypeFolder, TypeFoldable};
use std::cell::{RefCell};
+use std::fmt;
use std::rc::Rc;
use syntax::ast;
use syntax::codemap;
EquatePredicate(Span),
}
+impl TypeOrigin {
+ fn as_str(&self) -> &'static str {
+ match self {
+ &TypeOrigin::Misc(_) |
+ &TypeOrigin::RelateSelfType(_) |
+ &TypeOrigin::RelateOutputImplTypes(_) |
+ &TypeOrigin::ExprAssignable(_) => "mismatched types",
+ &TypeOrigin::RelateTraitRefs(_) => "mismatched traits",
+ &TypeOrigin::MethodCompatCheck(_) => "method not compatible with trait",
+ &TypeOrigin::MatchExpressionArm(_, _) => "match arms have incompatible types",
+ &TypeOrigin::IfExpression(_) => "if and else have incompatible types",
+ &TypeOrigin::IfExpressionWithNoElse(_) => "if may be missing an else clause",
+ &TypeOrigin::RangeExpression(_) => "start and end of range have incompatible types",
+ &TypeOrigin::EquatePredicate(_) => "equality predicate not satisfied",
+ }
+ }
+}
+
+impl fmt::Display for TypeOrigin {
+ fn fmt(&self, f: &mut fmt::Formatter) -> Result<(),fmt::Error> {
+ fmt::Display::fmt(self.as_str(), f)
+ }
+}
+
/// See `error_reporting.rs` for more details
#[derive(Clone, Debug)]
pub enum ValuePairs<'tcx> {
})
}
+ pub fn construct_skolemized_subst(&self,
+ generics: &ty::Generics<'tcx>,
+ snapshot: &CombinedSnapshot)
+ -> (subst::Substs<'tcx>, SkolemizationMap) {
+ /*! See `higher_ranked::construct_skolemized_subst` */
+
+ higher_ranked::construct_skolemized_substs(self, generics, snapshot)
+ }
+
pub fn skolemize_late_bound_regions<T>(&self,
value: &ty::Binder<T>,
snapshot: &CombinedSnapshot)
obligation.repr(tcx),
fn_sig.repr(tcx));
+ // the `Output` associated type is declared on `FnOnce`
+ let fn_once_def_id = tcx.lang_items.fn_once_trait().unwrap();
+
// Note: we unwrap the binder here but re-create it below (1)
let ty::Binder((trait_ref, ret_type)) =
util::closure_trait_ref_and_return_type(tcx,
- obligation.predicate.trait_ref.def_id,
+ fn_once_def_id,
obligation.predicate.trait_ref.self_ty(),
fn_sig,
flag);
match self.closure_typer.closure_kind(closure_def_id) {
Some(closure_kind) => {
debug!("assemble_unboxed_candidates: closure_kind = {:?}", closure_kind);
- if closure_kind == kind {
+ if closure_kind.extends(kind) {
candidates.vec.push(ClosureCandidate(closure_def_id, substs.clone()));
}
}
candidates: &mut SelectionCandidateSet<'tcx>)
-> Result<(),SelectionError<'tcx>>
{
- // We provide a `Fn` impl for fn pointers. There is no need to provide
- // the other traits (e.g. `FnMut`) since those are provided by blanket
- // impls.
- if Some(obligation.predicate.def_id()) != self.tcx().lang_items.fn_trait() {
+ // We provide impl of all fn traits for fn pointers.
+ if self.tcx().lang_items.fn_trait_kind(obligation.predicate.def_id()).is_none() {
return Ok(());
}
impl<'tcx> Hash for TyS<'tcx> {
fn hash<H: Hasher>(&self, s: &mut H) {
- (self as *const _).hash(s)
+ (self as *const TyS).hash(s)
}
}
pub fn to_early_bound_region(&self) -> ty::Region {
ty::ReEarlyBound(self.def_id.node, self.space, self.index, self.name)
}
+ pub fn to_bound_region(&self) -> ty::BoundRegion {
+ ty::BoundRegion::BrNamed(self.def_id, self.name)
+ }
}
/// Information about the formal type/lifetime parameters associated
pub substs: Substs<'tcx>,
}
-#[derive(Clone, Copy, PartialEq, Eq, Debug, RustcEncodable, RustcDecodable)]
+#[derive(Clone, Copy, PartialOrd, Ord, PartialEq, Eq, Debug, RustcEncodable, RustcDecodable)]
pub enum ClosureKind {
+ // Warning: Ordering is significant here! The ordering is chosen
+ // because the trait Fn is a subtrait of FnMut and so in turn, and
+ // hence we order it so that Fn < FnMut < FnOnce.
FnClosureKind,
FnMutClosureKind,
FnOnceClosureKind,
Err(err) => cx.sess.fatal(&err[..]),
}
}
+
+ /// True if this a type that impls this closure kind
+ /// must also implement `other`.
+ pub fn extends(self, other: ty::ClosureKind) -> bool {
+ match (self, other) {
+ (FnClosureKind, FnClosureKind) => true,
+ (FnClosureKind, FnMutClosureKind) => true,
+ (FnClosureKind, FnOnceClosureKind) => true,
+ (FnMutClosureKind, FnMutClosureKind) => true,
+ (FnMutClosureKind, FnOnceClosureKind) => true,
+ (FnOnceClosureKind, FnOnceClosureKind) => true,
+ _ => false,
+ }
+ }
}
pub trait ClosureTyper<'tcx> {
};
debug!("Interned type: {:?} Pointer: {:?}",
- ty, ty as *const _);
+ ty, ty as *const TyS);
interner.insert(InternedTy { ty: ty }, ty);
RvalueDpsExpr
}
- ast::ExprCast(..) => {
- match tcx.node_types.borrow().get(&expr.id) {
- Some(&ty) => {
- if type_is_trait(ty) {
- RvalueDpsExpr
- } else {
- RvalueDatumExpr
- }
- }
- None => {
- // Technically, it should not happen that the expr is not
- // present within the table. However, it DOES happen
- // during type check, because the final types from the
- // expressions are not yet recorded in the tcx. At that
- // time, though, we are only interested in knowing lvalue
- // vs rvalue. It would be better to base this decision on
- // the AST type in cast node---but (at the time of this
- // writing) it's not easy to distinguish casts to traits
- // from other casts based on the AST. This should be
- // easier in the future, when casts to traits
- // would like @Foo, Box<Foo>, or &Foo.
- RvalueDatumExpr
- }
- }
- }
-
ast::ExprBreak(..) |
ast::ExprAgain(..) |
ast::ExprRet(..) |
ast::ExprUnary(..) |
ast::ExprBox(None, _) |
ast::ExprAddrOf(..) |
- ast::ExprBinary(..) => {
+ ast::ExprBinary(..) |
+ ast::ExprCast(..) => {
RvalueDatumExpr
}
}
}
-declare_lint! {
- UNUSED_TYPECASTS,
- Allow,
- "detects unnecessary type casts that can be removed"
-}
-
-#[derive(Copy)]
-pub struct UnusedCasts;
-
-impl LintPass for UnusedCasts {
- fn get_lints(&self) -> LintArray {
- lint_array!(UNUSED_TYPECASTS)
- }
-
- fn check_expr(&mut self, cx: &Context, e: &ast::Expr) {
- if let ast::ExprCast(ref expr, ref ty) = e.node {
- let t_t = ty::expr_ty(cx.tcx, e);
- if ty::expr_ty(cx.tcx, &**expr) == t_t {
- cx.span_lint(UNUSED_TYPECASTS, ty.span, "unnecessary type cast");
- }
- }
- }
-}
-
declare_lint! {
UNSIGNED_NEGATION,
Warn,
fn check_fn(&mut self, cx: &Context, fn_kind: visit::FnKind, _: &ast::FnDecl,
blk: &ast::Block, sp: Span, id: ast::NodeId) {
+ // FIXME(#23542) Replace with type ascription.
+ #![allow(trivial_casts)]
+
type F = for<'tcx> fn(&ty::ctxt<'tcx>,
ast::NodeId, ast::NodeId, ast::Ident, ast::NodeId) -> bool;
pub use rustc::util as util;
use session::Session;
-use lint::{LintPassObject, LintId};
+use lint::LintId;
mod builtin;
macro_rules! add_builtin {
($sess:ident, $($name:ident),*,) => (
{$(
- store.register_pass($sess, false, box builtin::$name as LintPassObject);
+ store.register_pass($sess, false, box builtin::$name);
)*}
)
}
macro_rules! add_builtin_with_new {
($sess:ident, $($name:ident),*,) => (
{$(
- store.register_pass($sess, false, box builtin::$name::new() as LintPassObject);
+ store.register_pass($sess, false, box builtin::$name::new());
)*}
)
}
add_builtin!(sess,
HardwiredLints,
WhileTrue,
- UnusedCasts,
ImproperCTypes,
BoxPointers,
UnusedAttributes,
UNUSED_UNSAFE, PATH_STATEMENTS);
// We have one lint pass defined specially
- store.register_pass(sess, false, box lint::GatherNodeLevels as LintPassObject);
+ store.register_pass(sess, false, box lint::GatherNodeLevels);
// Insert temporary renamings for a one-time deprecation
store.register_renamed("raw_pointer_deriving", "raw_pointer_derive");
#![allow(non_camel_case_types)]
#![allow(non_snake_case)]
#![allow(dead_code)]
+#![allow(trivial_casts)]
+#![allow(trivial_numeric_casts)]
#![crate_name = "rustc_llvm"]
#![unstable(feature = "rustc_private")]
#![feature(convert)]
#![feature(path_relative_from)]
+#![allow(trivial_casts)]
+#![allow(trivial_numeric_casts)]
+
extern crate arena;
extern crate flate;
extern crate getopts;
let name = get_ident(item.ident);
let name = &name;
let location = match *s {
- Some((ref s, _)) => s.to_string(),
+ Some(s) => s.to_string(),
None => name.to_string(),
};
let alias_span = self.span.span_for_last_ident(item.span);
fn mutate(&mut self, _: ast::NodeId, _: Span, cmt: mc::cmt, _: euv::MutateMode) {
match cmt.cat {
mc::cat_upvar(mc::Upvar { id: ty::UpvarId { var_id: vid, .. }, .. }) |
- mc::cat_local(vid) => self.reassigned = self.node == vid,
+ mc::cat_local(vid) => self.reassigned |= self.node == vid,
mc::cat_interior(ref base_cmt, mc::InteriorField(field)) => {
match base_cmt.cat {
mc::cat_upvar(mc::Upvar { id: ty::UpvarId { var_id: vid, .. }, .. }) |
mc::cat_local(vid) => {
- self.reassigned = self.node == vid && Some(field) == self.field
+ self.reassigned |= self.node == vid && Some(field) == self.field
},
_ => {}
}
/// but for the bare function type given.
pub fn trans_fn_pointer_shim<'a, 'tcx>(
ccx: &'a CrateContext<'a, 'tcx>,
+ closure_kind: ty::ClosureKind,
bare_fn_ty: Ty<'tcx>)
-> ValueRef
{
let _icx = push_ctxt("trans_fn_pointer_shim");
let tcx = ccx.tcx();
+ // Normalize the type for better caching.
let bare_fn_ty = common::erase_regions(tcx, &bare_fn_ty);
- match ccx.fn_pointer_shims().borrow().get(&bare_fn_ty) {
+
+ // If this is an impl of `Fn` or `FnMut` trait, the receiver is `&self`.
+ let is_by_ref = match closure_kind {
+ ty::FnClosureKind | ty::FnMutClosureKind => true,
+ ty::FnOnceClosureKind => false,
+ };
+ let bare_fn_ty_maybe_ref = if is_by_ref {
+ ty::mk_imm_rptr(tcx, tcx.mk_region(ty::ReStatic), bare_fn_ty)
+ } else {
+ bare_fn_ty
+ };
+
+ // Check if we already trans'd this shim.
+ match ccx.fn_pointer_shims().borrow().get(&bare_fn_ty_maybe_ref) {
Some(&llval) => { return llval; }
None => { }
}
debug!("trans_fn_pointer_shim(bare_fn_ty={})",
bare_fn_ty.repr(tcx));
- // This is an impl of `Fn` trait, so receiver is `&self`.
- let bare_fn_ty_ref = ty::mk_imm_rptr(tcx, tcx.mk_region(ty::ReStatic), bare_fn_ty);
-
// Construct the "tuply" version of `bare_fn_ty`. It takes two arguments: `self`,
// which is the fn pointer, and `args`, which is the arguments tuple.
let (opt_def_id, sig) =
unsafety: ast::Unsafety::Normal,
abi: synabi::RustCall,
sig: ty::Binder(ty::FnSig {
- inputs: vec![bare_fn_ty_ref,
+ inputs: vec![bare_fn_ty_maybe_ref,
tuple_input_ty],
output: sig.output,
variadic: false
let mut bcx = init_function(&fcx, false, sig.output);
// the first argument (`self`) will be ptr to the the fn pointer
- let llfnpointer =
- Load(bcx, get_param(fcx.llfn, fcx.arg_pos(0) as u32));
+ let llfnpointer = if is_by_ref {
+ Load(bcx, get_param(fcx.llfn, fcx.arg_pos(0) as u32))
+ } else {
+ get_param(fcx.llfn, fcx.arg_pos(0) as u32)
+ };
// the remaining arguments will be the untupled values
let llargs: Vec<_> =
finish_fn(&fcx, bcx, sig.output, DebugLoc::None);
- ccx.fn_pointer_shims().borrow_mut().insert(bare_fn_ty, llfn);
+ ccx.fn_pointer_shims().borrow_mut().insert(bare_fn_ty_maybe_ref, llfn);
llfn
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use back::link::mangle_internal_name_by_path_and_seq;
-use llvm::ValueRef;
+use arena::TypedArena;
+use back::link::{self, mangle_internal_name_by_path_and_seq};
+use llvm::{ValueRef, get_param};
use middle::mem_categorization::Typer;
use trans::adt;
use trans::base::*;
use trans::build::*;
-use trans::cleanup::{CleanupMethods, ScopeId};
+use trans::callee::{self, ArgVals, Callee, TraitItem, MethodData};
+use trans::cleanup::{CleanupMethods, CustomScope, ScopeId};
use trans::common::*;
-use trans::datum::{Datum, rvalue_scratch_datum};
-use trans::datum::{Rvalue, ByValue};
-use trans::debuginfo;
+use trans::datum::{self, Datum, rvalue_scratch_datum, Rvalue, ByValue};
+use trans::debuginfo::{self, DebugLoc};
use trans::expr;
use trans::monomorphize::{self, MonoId};
use trans::type_of::*;
use middle::ty::{self, ClosureTyper};
use middle::subst::{Substs};
use session::config::FullDebugInfo;
+use util::ppaux::Repr;
+use syntax::abi::RustCall;
use syntax::ast;
use syntax::ast_util;
// Create the closure.
for (i, freevar) in freevars.iter().enumerate() {
let datum = expr::trans_local_var(bcx, freevar.def);
- let upvar_slot_dest = adt::trans_field_ptr(bcx,
- &*repr,
- dest_addr,
- 0,
- i);
+ let upvar_slot_dest = adt::trans_field_ptr(bcx, &*repr, dest_addr, 0, i);
let upvar_id = ty::UpvarId { var_id: freevar.def.local_node_id(),
closure_expr_id: id };
match tcx.upvar_capture(upvar_id).unwrap() {
Some(bcx)
}
+
+pub fn trans_closure_method<'a, 'tcx>(ccx: &'a CrateContext<'a, 'tcx>,
+ closure_def_id: ast::DefId,
+ substs: Substs<'tcx>,
+ node: ExprOrMethodCall,
+ param_substs: &'tcx Substs<'tcx>,
+ trait_closure_kind: ty::ClosureKind)
+ -> ValueRef
+{
+ // The substitutions should have no type parameters remaining
+ // after passing through fulfill_obligation
+ let llfn = callee::trans_fn_ref_with_substs(ccx,
+ closure_def_id,
+ node,
+ param_substs,
+ substs.clone()).val;
+
+ // If the closure is a Fn closure, but a FnOnce is needed (etc),
+ // then adapt the self type
+ let closure_kind = ccx.tcx().closure_kind(closure_def_id);
+ trans_closure_adapter_shim(ccx,
+ closure_def_id,
+ substs,
+ closure_kind,
+ trait_closure_kind,
+ llfn)
+}
+
+fn trans_closure_adapter_shim<'a, 'tcx>(
+ ccx: &'a CrateContext<'a, 'tcx>,
+ closure_def_id: ast::DefId,
+ substs: Substs<'tcx>,
+ llfn_closure_kind: ty::ClosureKind,
+ trait_closure_kind: ty::ClosureKind,
+ llfn: ValueRef)
+ -> ValueRef
+{
+ let _icx = push_ctxt("trans_closure_adapter_shim");
+ let tcx = ccx.tcx();
+
+ debug!("trans_closure_adapter_shim(llfn_closure_kind={:?}, \
+ trait_closure_kind={:?}, \
+ llfn={})",
+ llfn_closure_kind,
+ trait_closure_kind,
+ ccx.tn().val_to_string(llfn));
+
+ match (llfn_closure_kind, trait_closure_kind) {
+ (ty::FnClosureKind, ty::FnClosureKind) |
+ (ty::FnMutClosureKind, ty::FnMutClosureKind) |
+ (ty::FnOnceClosureKind, ty::FnOnceClosureKind) => {
+ // No adapter needed.
+ llfn
+ }
+ (ty::FnClosureKind, ty::FnMutClosureKind) => {
+ // The closure fn `llfn` is a `fn(&self, ...)`. We want a
+ // `fn(&mut self, ...)`. In fact, at trans time, these are
+ // basically the same thing, so we can just return llfn.
+ llfn
+ }
+ (ty::FnClosureKind, ty::FnOnceClosureKind) |
+ (ty::FnMutClosureKind, ty::FnOnceClosureKind) => {
+ // The closure fn `llfn` is a `fn(&self, ...)` or `fn(&mut
+ // self, ...)`. We want a `fn(self, ...)`. We can produce
+ // this by doing something like:
+ //
+ // fn call_once(self, ...) { call_mut(&self, ...) }
+ // fn call_once(mut self, ...) { call_mut(&mut self, ...) }
+ //
+ // These are both the same at trans time.
+ trans_fn_once_adapter_shim(ccx, closure_def_id, substs, llfn)
+ }
+ _ => {
+ tcx.sess.bug(&format!("trans_closure_adapter_shim: cannot convert {:?} to {:?}",
+ llfn_closure_kind,
+ trait_closure_kind));
+ }
+ }
+}
+
+fn trans_fn_once_adapter_shim<'a, 'tcx>(
+ ccx: &'a CrateContext<'a, 'tcx>,
+ closure_def_id: ast::DefId,
+ substs: Substs<'tcx>,
+ llreffn: ValueRef)
+ -> ValueRef
+{
+ debug!("trans_fn_once_adapter_shim(closure_def_id={}, substs={}, llreffn={})",
+ closure_def_id.repr(ccx.tcx()),
+ substs.repr(ccx.tcx()),
+ ccx.tn().val_to_string(llreffn));
+
+ let tcx = ccx.tcx();
+ let typer = NormalizingClosureTyper::new(tcx);
+
+ // Find a version of the closure type. Substitute static for the
+ // region since it doesn't really matter.
+ let substs = tcx.mk_substs(substs);
+ let closure_ty = ty::mk_closure(tcx, closure_def_id, substs);
+ let ref_closure_ty = ty::mk_imm_rptr(tcx, tcx.mk_region(ty::ReStatic), closure_ty);
+
+ // Make a version with the type of by-ref closure.
+ let ty::ClosureTy { unsafety, abi, mut sig } = typer.closure_type(closure_def_id, substs);
+ sig.0.inputs.insert(0, ref_closure_ty); // sig has no self type as of yet
+ let llref_bare_fn_ty = tcx.mk_bare_fn(ty::BareFnTy { unsafety: unsafety,
+ abi: abi,
+ sig: sig.clone() });
+ let llref_fn_ty = ty::mk_bare_fn(tcx, None, llref_bare_fn_ty);
+ debug!("trans_fn_once_adapter_shim: llref_fn_ty={}",
+ llref_fn_ty.repr(tcx));
+
+ // Make a version of the closure type with the same arguments, but
+ // with argument #0 being by value.
+ assert_eq!(abi, RustCall);
+ sig.0.inputs[0] = closure_ty;
+ let llonce_bare_fn_ty = tcx.mk_bare_fn(ty::BareFnTy { unsafety: unsafety,
+ abi: abi,
+ sig: sig });
+ let llonce_fn_ty = ty::mk_bare_fn(tcx, None, llonce_bare_fn_ty);
+
+ // Create the by-value helper.
+ let function_name = link::mangle_internal_name_by_type_and_seq(ccx, llonce_fn_ty, "once_shim");
+ let lloncefn = decl_internal_rust_fn(ccx, llonce_fn_ty, &function_name);
+
+ let sig = ty::erase_late_bound_regions(tcx, &llonce_bare_fn_ty.sig);
+ let (block_arena, fcx): (TypedArena<_>, FunctionContext);
+ block_arena = TypedArena::new();
+ fcx = new_fn_ctxt(ccx,
+ lloncefn,
+ ast::DUMMY_NODE_ID,
+ false,
+ sig.output,
+ substs,
+ None,
+ &block_arena);
+ let mut bcx = init_function(&fcx, false, sig.output);
+
+ // the first argument (`self`) will be the (by value) closure env.
+ let self_scope = fcx.push_custom_cleanup_scope();
+ let self_scope_id = CustomScope(self_scope);
+ let rvalue_mode = datum::appropriate_rvalue_mode(ccx, closure_ty);
+ let llself = get_param(lloncefn, fcx.arg_pos(0) as u32);
+ let env_datum = Datum::new(llself, closure_ty, Rvalue::new(rvalue_mode));
+ let env_datum = unpack_datum!(bcx,
+ env_datum.to_lvalue_datum_in_scope(bcx, "self",
+ self_scope_id));
+
+ debug!("trans_fn_once_adapter_shim: env_datum={}",
+ bcx.val_to_string(env_datum.val));
+
+ // the remaining arguments will be packed up in a tuple.
+ let input_tys = match sig.inputs[1].sty {
+ ty::ty_tup(ref tys) => &**tys,
+ _ => bcx.sess().bug(&format!("trans_fn_once_adapter_shim: not rust-call! \
+ closure_def_id={}",
+ closure_def_id.repr(tcx)))
+ };
+ let llargs: Vec<_> =
+ input_tys.iter()
+ .enumerate()
+ .map(|(i, _)| get_param(lloncefn, fcx.arg_pos(i+1) as u32))
+ .collect();
+
+ let dest =
+ fcx.llretslotptr.get().map(
+ |_| expr::SaveIn(fcx.get_ret_slot(bcx, sig.output, "ret_slot")));
+
+ let callee_data = TraitItem(MethodData { llfn: llreffn,
+ llself: env_datum.val });
+
+ bcx = callee::trans_call_inner(bcx,
+ DebugLoc::None,
+ llref_fn_ty,
+ |bcx, _| Callee { bcx: bcx, data: callee_data },
+ ArgVals(&llargs),
+ dest).bcx;
+
+ fcx.pop_custom_cleanup_scope(self_scope);
+
+ finish_fn(&fcx, bcx, sig.output, DebugLoc::None);
+
+ lloncefn
+}
})
}
- /// Ensures that `self` will get cleaned up, if it is not an lvalue already.
- pub fn clean<'blk>(self,
- bcx: Block<'blk, 'tcx>,
- name: &'static str,
- expr_id: ast::NodeId)
- -> Block<'blk, 'tcx> {
- self.to_lvalue_datum(bcx, name, expr_id).bcx
- }
-
pub fn to_lvalue_datum<'blk>(self,
bcx: Block<'blk, 'tcx>,
name: &str,
trans_overloaded_op(bcx, expr, MethodCall::expr(expr.id), base,
vec![(idx_datum, idx.id)], Some(dest), true).bcx
}
- ast::ExprCast(ref val, _) => {
- // DPS output mode means this is a trait cast:
- if ty::type_is_trait(node_id_type(bcx, expr.id)) {
- let trait_ref =
- bcx.tcx().object_cast_map.borrow()
- .get(&expr.id)
- .cloned()
- .unwrap();
- let trait_ref = bcx.monomorphize(&trait_ref);
- let datum = unpack_datum!(bcx, trans(bcx, &**val));
- meth::trans_trait_cast(bcx, datum, expr.id,
- trait_ref, dest)
- } else {
- bcx.tcx().sess.span_bug(expr.span,
- "expr_cast of non-trait");
- }
+ ast::ExprCast(..) => {
+ // Trait casts used to come this way, now they should be coercions.
+ bcx.tcx().sess.span_bug(expr.span, "DPS expr_cast (residual trait cast?)")
}
ast::ExprAssignOp(op, ref dst, ref src) => {
trans_assign_op(bcx, expr, op, &**dst, &**src)
ast::BiAdd => {
if is_float {
FAdd(bcx, lhs, rhs, binop_debug_loc)
+ } else if is_simd {
+ Add(bcx, lhs, rhs, binop_debug_loc)
} else {
let (newbcx, res) = with_overflow_check(
bcx, OverflowOp::Add, info, lhs_t, lhs, rhs, binop_debug_loc);
ast::BiSub => {
if is_float {
FSub(bcx, lhs, rhs, binop_debug_loc)
+ } else if is_simd {
+ Sub(bcx, lhs, rhs, binop_debug_loc)
} else {
let (newbcx, res) = with_overflow_check(
bcx, OverflowOp::Sub, info, lhs_t, lhs, rhs, binop_debug_loc);
ast::BiMul => {
if is_float {
FMul(bcx, lhs, rhs, binop_debug_loc)
+ } else if is_simd {
+ Mul(bcx, lhs, rhs, binop_debug_loc)
} else {
let (newbcx, res) = with_overflow_check(
bcx, OverflowOp::Mul, info, lhs_t, lhs, rhs, binop_debug_loc);
let mut bcx = bcx;
let ccx = bcx.ccx();
- let t_in = expr_ty(bcx, expr);
+ let t_in = expr_ty_adjusted(bcx, expr);
let t_out = node_id_type(bcx, id);
let k_in = cast_type_kind(bcx.tcx(), t_in);
let k_out = cast_type_kind(bcx.tcx(), t_out);
// by-value as appropriate given its type:
let mut datum = unpack_datum!(bcx, trans(bcx, expr));
- if cast_is_noop(datum.ty, t_out) {
+ let datum_ty = monomorphize_type(bcx, datum.ty);
+ if cast_is_noop(datum_ty, t_out) {
datum.ty = t_out;
return DatumBlock::new(bcx, datum);
}
use middle::subst::VecPerParamSpace;
use middle::subst;
use middle::traits;
+use middle::ty::ClosureTyper;
use trans::base::*;
use trans::build::*;
use trans::callee::*;
use trans::callee;
use trans::cleanup;
+use trans::closure;
use trans::common::*;
use trans::consts;
use trans::datum::*;
use trans::debuginfo::DebugLoc;
-use trans::expr::{SaveIn, Ignore};
+use trans::expr::SaveIn;
use trans::expr;
use trans::glue;
use trans::machine;
traits::VtableClosure(closure_def_id, substs) => {
// The substitutions should have no type parameters remaining
// after passing through fulfill_obligation
- let llfn = trans_fn_ref_with_substs(bcx.ccx(),
- closure_def_id,
- MethodCallKey(method_call),
- bcx.fcx.param_substs,
- substs).val;
-
+ let trait_closure_kind = bcx.tcx().lang_items.fn_trait_kind(trait_id).unwrap();
+ let llfn = closure::trans_closure_method(bcx.ccx(),
+ closure_def_id,
+ substs,
+ MethodCallKey(method_call),
+ bcx.fcx.param_substs,
+ trait_closure_kind);
Callee {
bcx: bcx,
data: Fn(llfn),
}
}
traits::VtableFnPointer(fn_ty) => {
- let llfn = trans_fn_pointer_shim(bcx.ccx(), fn_ty);
+ let trait_closure_kind = bcx.tcx().lang_items.fn_trait_kind(trait_id).unwrap();
+ let llfn = trans_fn_pointer_shim(bcx.ccx(), trait_closure_kind, fn_ty);
Callee { bcx: bcx, data: Fn(llfn) }
}
traits::VtableObject(ref data) => {
assert!(!fcx.needs_ret_allocas);
- let sig =
- ty::erase_late_bound_regions(bcx.tcx(), &fty.sig);
-
let dest =
fcx.llretslotptr.get().map(
|_| expr::SaveIn(fcx.get_ret_slot(bcx, sig.output, "ret_slot")));
emit_vtable_methods(ccx, id, substs, param_substs).into_iter()
}
traits::VtableClosure(closure_def_id, substs) => {
- let llfn = trans_fn_ref_with_substs(
- ccx,
- closure_def_id,
- ExprId(0),
- param_substs,
- substs).val;
-
+ let trait_closure_kind = tcx.lang_items.fn_trait_kind(trait_ref.def_id()).unwrap();
+ let llfn = closure::trans_closure_method(ccx,
+ closure_def_id,
+ substs,
+ ExprId(0),
+ param_substs,
+ trait_closure_kind);
vec![llfn].into_iter()
}
traits::VtableFnPointer(bare_fn_ty) => {
- vec![trans_fn_pointer_shim(ccx, bare_fn_ty)].into_iter()
+ let trait_closure_kind = tcx.lang_items.fn_trait_kind(trait_ref.def_id()).unwrap();
+ vec![trans_fn_pointer_shim(ccx, trait_closure_kind, bare_fn_ty)].into_iter()
}
traits::VtableObject(ref data) => {
// this would imply that the Self type being erased is
.collect()
}
-/// Generates the code to convert from a pointer (`Box<T>`, `&T`, etc) into an object
-/// (`Box<Trait>`, `&Trait`, etc). This means creating a pair where the first word is the vtable
-/// and the second word is the pointer.
-pub fn trans_trait_cast<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
- datum: Datum<'tcx, Expr>,
- id: ast::NodeId,
- trait_ref: ty::PolyTraitRef<'tcx>,
- dest: expr::Dest)
- -> Block<'blk, 'tcx> {
- let mut bcx = bcx;
- let _icx = push_ctxt("meth::trans_trait_cast");
-
- let lldest = match dest {
- Ignore => {
- return datum.clean(bcx, "trait_trait_cast", id);
- }
- SaveIn(dest) => dest
- };
-
- debug!("trans_trait_cast: trait_ref={}",
- trait_ref.repr(bcx.tcx()));
-
- let llty = type_of(bcx.ccx(), datum.ty);
-
- // Store the pointer into the first half of pair.
- let llboxdest = GEPi(bcx, lldest, &[0, abi::FAT_PTR_ADDR]);
- let llboxdest = PointerCast(bcx, llboxdest, llty.ptr_to());
- bcx = datum.store_to(bcx, llboxdest);
-
- // Store the vtable into the second half of pair.
- let vtable = get_vtable(bcx.ccx(), trait_ref, bcx.fcx.param_substs);
- let llvtabledest = GEPi(bcx, lldest, &[0, abi::FAT_PTR_EXTRA]);
- let llvtabledest = PointerCast(bcx, llvtabledest, val_ty(vtable).ptr_to());
- Store(bcx, vtable, llvtabledest);
-
- bcx
-}
-
/// Replace the self type (&Self or Box<Self>) with an opaque pointer.
pub fn opaque_method_ty<'tcx>(tcx: &ty::ctxt<'tcx>, method_ty: &ty::BareFnTy<'tcx>)
-> &'tcx ty::BareFnTy<'tcx> {
use middle::privacy::{AllPublic, LastMod};
use middle::subst::{FnSpace, TypeSpace, SelfSpace, Subst, Substs};
use middle::traits;
-use middle::ty::{self, RegionEscape, ToPolyTraitRef, Ty};
+use middle::ty::{self, RegionEscape, Ty};
use rscope::{self, UnelidableRscope, RegionScope, ElidableRscope,
ObjectLifetimeDefaultRscope, ShiftedRscope, BindingRscope};
use util::common::{ErrorReported, FN_OUTPUT_NAME};
poly_projections: &mut Vec<ty::PolyProjectionPredicate<'tcx>>)
-> ty::PolyTraitRef<'tcx>
{
- let mut projections = Vec::new();
-
- // The trait reference introduces a binding level here, so
- // we need to shift the `rscope`. It'd be nice if we could
- // do away with this rscope stuff and work this knowledge
- // into resolve_lifetimes, as we do with non-omitted
- // lifetimes. Oh well, not there yet.
- let shifted_rscope = ShiftedRscope::new(rscope);
-
- let trait_ref = instantiate_trait_ref(this, &shifted_rscope,
- &ast_trait_ref.trait_ref,
- None, self_ty, Some(&mut projections));
-
- for projection in projections {
- poly_projections.push(ty::Binder(projection));
- }
-
- ty::Binder(trait_ref)
+ let trait_ref = &ast_trait_ref.trait_ref;
+ let trait_def_id = trait_def_id(this, trait_ref);
+ ast_path_to_poly_trait_ref(this,
+ rscope,
+ trait_ref.path.span,
+ PathParamMode::Explicit,
+ trait_def_id,
+ self_ty,
+ trait_ref.path.segments.last().unwrap(),
+ poly_projections)
}
/// Instantiates the path for the given trait reference, assuming that it's
///
/// If the `projections` argument is `None`, then assoc type bindings like `Foo<T=X>`
/// are disallowed. Otherwise, they are pushed onto the vector given.
-pub fn instantiate_trait_ref<'tcx>(
+pub fn instantiate_mono_trait_ref<'tcx>(
this: &AstConv<'tcx>,
rscope: &RegionScope,
trait_ref: &ast::TraitRef,
- impl_id: Option<ast::NodeId>,
- self_ty: Option<Ty<'tcx>>,
- projections: Option<&mut Vec<ty::ProjectionPredicate<'tcx>>>)
+ self_ty: Option<Ty<'tcx>>)
-> Rc<ty::TraitRef<'tcx>>
{
+ let trait_def_id = trait_def_id(this, trait_ref);
+ ast_path_to_mono_trait_ref(this,
+ rscope,
+ trait_ref.path.span,
+ PathParamMode::Explicit,
+ trait_def_id,
+ self_ty,
+ trait_ref.path.segments.last().unwrap())
+}
+
+fn trait_def_id<'tcx>(this: &AstConv<'tcx>, trait_ref: &ast::TraitRef) -> ast::DefId {
let path = &trait_ref.path;
match ::lookup_full_def(this.tcx(), path.span, trait_ref.ref_id) {
- def::DefTrait(trait_def_id) => {
- let trait_ref = ast_path_to_trait_ref(this,
- rscope,
- path.span,
- PathParamMode::Explicit,
- trait_def_id,
- self_ty,
- path.segments.last().unwrap(),
- projections);
- if let Some(id) = impl_id {
- this.tcx().impl_trait_refs.borrow_mut().insert(id, trait_ref.clone());
- }
- trait_ref
- }
+ def::DefTrait(trait_def_id) => trait_def_id,
_ => {
span_fatal!(this.tcx().sess, path.span, E0245, "`{}` is not a trait",
path.user_string(this.tcx()));
mut projections: &mut Vec<ty::PolyProjectionPredicate<'tcx>>)
-> ty::PolyTraitRef<'tcx>
{
- // we are introducing a binder here, so shift the
- // anonymous regions depth to account for that
- let shifted_rscope = ShiftedRscope::new(rscope);
-
- let mut tmp = Vec::new();
- let trait_ref = ty::Binder(ast_path_to_trait_ref(this,
- &shifted_rscope,
- span,
- param_mode,
- trait_def_id,
- None,
- trait_segment,
- Some(&mut tmp)));
- projections.extend(tmp.into_iter().map(ty::Binder));
- trait_ref
+ ast_path_to_poly_trait_ref(this,
+ rscope,
+ span,
+ param_mode,
+ trait_def_id,
+ None,
+ trait_segment,
+ projections)
}
-fn ast_path_to_trait_ref<'a,'tcx>(
+fn ast_path_to_poly_trait_ref<'a,'tcx>(
this: &AstConv<'tcx>,
rscope: &RegionScope,
span: Span,
trait_def_id: ast::DefId,
self_ty: Option<Ty<'tcx>>,
trait_segment: &ast::PathSegment,
- mut projections: Option<&mut Vec<ty::ProjectionPredicate<'tcx>>>)
- -> Rc<ty::TraitRef<'tcx>>
+ poly_projections: &mut Vec<ty::PolyProjectionPredicate<'tcx>>)
+ -> ty::PolyTraitRef<'tcx>
+{
+ // The trait reference introduces a binding level here, so
+ // we need to shift the `rscope`. It'd be nice if we could
+ // do away with this rscope stuff and work this knowledge
+ // into resolve_lifetimes, as we do with non-omitted
+ // lifetimes. Oh well, not there yet.
+ let shifted_rscope = &ShiftedRscope::new(rscope);
+
+ let (substs, assoc_bindings) =
+ create_substs_for_ast_trait_ref(this,
+ shifted_rscope,
+ span,
+ param_mode,
+ trait_def_id,
+ self_ty,
+ trait_segment);
+ let poly_trait_ref = ty::Binder(Rc::new(ty::TraitRef::new(trait_def_id, substs)));
+
+ {
+ let converted_bindings =
+ assoc_bindings
+ .iter()
+ .filter_map(|binding| {
+ // specify type to assert that error was already reported in Err case:
+ let predicate: Result<_, ErrorReported> =
+ ast_type_binding_to_poly_projection_predicate(this,
+ poly_trait_ref.clone(),
+ self_ty,
+ binding);
+ predicate.ok() // ok to ignore Err() because ErrorReported (see above)
+ });
+ poly_projections.extend(converted_bindings);
+ }
+
+ poly_trait_ref
+}
+
+fn ast_path_to_mono_trait_ref<'a,'tcx>(this: &AstConv<'tcx>,
+ rscope: &RegionScope,
+ span: Span,
+ param_mode: PathParamMode,
+ trait_def_id: ast::DefId,
+ self_ty: Option<Ty<'tcx>>,
+ trait_segment: &ast::PathSegment)
+ -> Rc<ty::TraitRef<'tcx>>
{
- debug!("ast_path_to_trait_ref {:?}", trait_segment);
+ let (substs, assoc_bindings) =
+ create_substs_for_ast_trait_ref(this,
+ rscope,
+ span,
+ param_mode,
+ trait_def_id,
+ self_ty,
+ trait_segment);
+ prohibit_projections(this.tcx(), &assoc_bindings);
+ Rc::new(ty::TraitRef::new(trait_def_id, substs))
+}
+
+fn create_substs_for_ast_trait_ref<'a,'tcx>(this: &AstConv<'tcx>,
+ rscope: &RegionScope,
+ span: Span,
+ param_mode: PathParamMode,
+ trait_def_id: ast::DefId,
+ self_ty: Option<Ty<'tcx>>,
+ trait_segment: &ast::PathSegment)
+ -> (&'tcx Substs<'tcx>, Vec<ConvertedBinding<'tcx>>)
+{
+ debug!("create_substs_for_ast_trait_ref(trait_segment={:?})",
+ trait_segment);
+
let trait_def = match this.get_trait_def(span, trait_def_id) {
Ok(trait_def) => trait_def,
Err(ErrorReported) => {
self_ty,
types,
regions);
- let substs = this.tcx().mk_substs(substs);
- let trait_ref = Rc::new(ty::TraitRef::new(trait_def_id, substs));
-
- match projections {
- None => {
- prohibit_projections(this.tcx(), &assoc_bindings);
- }
- Some(ref mut v) => {
- for binding in &assoc_bindings {
- match ast_type_binding_to_projection_predicate(this, trait_ref.clone(),
- self_ty, binding) {
- Ok(pp) => { v.push(pp); }
- Err(ErrorReported) => { }
- }
- }
- }
- }
-
- trait_ref
+ (this.tcx().mk_substs(substs), assoc_bindings)
}
-fn ast_type_binding_to_projection_predicate<'tcx>(
+fn ast_type_binding_to_poly_projection_predicate<'tcx>(
this: &AstConv<'tcx>,
- mut trait_ref: Rc<ty::TraitRef<'tcx>>,
+ mut trait_ref: ty::PolyTraitRef<'tcx>,
self_ty: Option<Ty<'tcx>>,
binding: &ConvertedBinding<'tcx>)
- -> Result<ty::ProjectionPredicate<'tcx>, ErrorReported>
+ -> Result<ty::PolyProjectionPredicate<'tcx>, ErrorReported>
{
let tcx = this.tcx();
// We want to produce `<B as SuperTrait<int>>::T == foo`.
// Simple case: X is defined in the current trait.
- if this.trait_defines_associated_type_named(trait_ref.def_id, binding.item_name) {
- return Ok(ty::ProjectionPredicate {
- projection_ty: ty::ProjectionTy {
- trait_ref: trait_ref,
+ if this.trait_defines_associated_type_named(trait_ref.def_id(), binding.item_name) {
+ return Ok(ty::Binder(ty::ProjectionPredicate { // <-------------------+
+ projection_ty: ty::ProjectionTy { // |
+ trait_ref: trait_ref.skip_binder().clone(), // Binder moved here --+
item_name: binding.item_name,
},
ty: binding.ty,
- });
+ }));
}
// Otherwise, we have to walk through the supertraits to find
let dummy_self_ty = ty::mk_infer(tcx, ty::FreshTy(0));
if self_ty.is_none() { // if converting for an object type
- let mut dummy_substs = trait_ref.substs.clone();
- assert!(dummy_substs.self_ty().is_none());
- dummy_substs.types.push(SelfSpace, dummy_self_ty);
- trait_ref = Rc::new(ty::TraitRef::new(trait_ref.def_id,
- tcx.mk_substs(dummy_substs)));
+ let mut dummy_substs = trait_ref.skip_binder().substs.clone(); // binder moved here -+
+ assert!(dummy_substs.self_ty().is_none()); // |
+ dummy_substs.types.push(SelfSpace, dummy_self_ty); // |
+ trait_ref = ty::Binder(Rc::new(ty::TraitRef::new(trait_ref.def_id(), // <------------+
+ tcx.mk_substs(dummy_substs))));
}
- try!(this.ensure_super_predicates(binding.span, trait_ref.def_id));
+ try!(this.ensure_super_predicates(binding.span, trait_ref.def_id()));
let mut candidates: Vec<ty::PolyTraitRef> =
- traits::supertraits(tcx, trait_ref.to_poly_trait_ref())
+ traits::supertraits(tcx, trait_ref.clone())
.filter(|r| this.trait_defines_associated_type_named(r.def_id(), binding.item_name))
.collect();
}
};
- if ty::binds_late_bound_regions(tcx, &candidate) {
- span_err!(tcx.sess, binding.span, E0219,
- "associated type `{}` defined in higher-ranked supertrait `{}`",
- token::get_name(binding.item_name),
- candidate.user_string(tcx));
- return Err(ErrorReported);
- }
-
- Ok(ty::ProjectionPredicate {
- projection_ty: ty::ProjectionTy {
- trait_ref: candidate.0,
+ Ok(ty::Binder(ty::ProjectionPredicate { // <-------------------------+
+ projection_ty: ty::ProjectionTy { // |
+ trait_ref: candidate.skip_binder().clone(), // binder is moved up here --+
item_name: binding.item_name,
},
ty: binding.ty,
- })
+ }))
}
fn ast_path_to_ty<'tcx>(
debug!("qpath_to_ty: self_type={}", self_ty.repr(tcx));
- let trait_ref = ast_path_to_trait_ref(this,
- rscope,
- span,
- param_mode,
- trait_def_id,
- Some(self_ty),
- trait_segment,
- None);
+ let trait_ref =
+ ast_path_to_mono_trait_ref(this,
+ rscope,
+ span,
+ param_mode,
+ trait_def_id,
+ Some(self_ty),
+ trait_segment);
debug!("qpath_to_ty: trait_ref={}", trait_ref.repr(tcx));
use middle::region;
use middle::subst;
use middle::ty::{self, ToPolyTraitRef, Ty};
+use std::cmp;
use syntax::abi;
use syntax::ast;
use syntax::ast_util;
ty::ty_trait(ref object_type) => {
let proj_bounds = object_type.projection_bounds_with_self_ty(fcx.tcx(),
fcx.tcx().types.err);
- let expectations =
- proj_bounds.iter()
- .filter_map(|pb| deduce_expectations_from_projection(fcx, pb))
- .next();
-
- match expectations {
- Some((sig, kind)) => (Some(sig), Some(kind)),
- None => (None, None)
- }
+ let sig = proj_bounds.iter()
+ .filter_map(|pb| deduce_sig_from_projection(fcx, pb))
+ .next();
+ let kind = fcx.tcx().lang_items.fn_trait_kind(object_type.principal_def_id());
+ (sig, kind)
}
ty::ty_infer(ty::TyVar(vid)) => {
deduce_expectations_from_obligations(fcx, vid)
let fulfillment_cx = fcx.inh.fulfillment_cx.borrow();
// Here `expected_ty` is known to be a type inference variable.
- let expected_sig_and_kind =
+ let expected_sig =
fulfillment_cx
.pending_obligations()
.iter()
ty::Predicate::Projection(ref proj_predicate) => {
let trait_ref = proj_predicate.to_poly_trait_ref();
self_type_matches_expected_vid(fcx, trait_ref, expected_vid)
- .and_then(|_| deduce_expectations_from_projection(fcx, proj_predicate))
+ .and_then(|_| deduce_sig_from_projection(fcx, proj_predicate))
}
_ => {
None
})
.next();
- match expected_sig_and_kind {
- Some((sig, kind)) => { return (Some(sig), Some(kind)); }
- None => { }
- }
-
// Even if we can't infer the full signature, we may be able to
// infer the kind. This can occur if there is a trait-reference
- // like `F : Fn<A>`.
+ // like `F : Fn<A>`. Note that due to subtyping we could encounter
+ // many viable options, so pick the most restrictive.
let expected_kind =
fulfillment_cx
.pending_obligations()
.and_then(|trait_ref| self_type_matches_expected_vid(fcx, trait_ref, expected_vid))
.and_then(|trait_ref| fcx.tcx().lang_items.fn_trait_kind(trait_ref.def_id()))
})
- .next();
+ .fold(None, pick_most_restrictive_closure_kind);
+
+ (expected_sig, expected_kind)
+}
- (None, expected_kind)
+fn pick_most_restrictive_closure_kind(best: Option<ty::ClosureKind>,
+ cur: ty::ClosureKind)
+ -> Option<ty::ClosureKind>
+{
+ match best {
+ None => Some(cur),
+ Some(best) => Some(cmp::min(best, cur))
+ }
}
/// Given a projection like "<F as Fn(X)>::Result == Y", we can deduce
/// everything we need to know about a closure.
-fn deduce_expectations_from_projection<'a,'tcx>(
+fn deduce_sig_from_projection<'a,'tcx>(
fcx: &FnCtxt<'a,'tcx>,
projection: &ty::PolyProjectionPredicate<'tcx>)
- -> Option<(ty::FnSig<'tcx>, ty::ClosureKind)>
+ -> Option<ty::FnSig<'tcx>>
{
let tcx = fcx.tcx();
- debug!("deduce_expectations_from_projection({})",
+ debug!("deduce_sig_from_projection({})",
projection.repr(tcx));
let trait_ref = projection.to_poly_trait_ref();
- let kind = match tcx.lang_items.fn_trait_kind(trait_ref.def_id()) {
- Some(k) => k,
- None => { return None; }
- };
-
- debug!("found object type {:?}", kind);
+ if tcx.lang_items.fn_trait_kind(trait_ref.def_id()).is_none() {
+ return None;
+ }
let arg_param_ty = *trait_ref.substs().types.get(subst::TypeSpace, 0);
let arg_param_ty = fcx.infcx().resolve_type_vars_if_possible(&arg_param_ty);
- debug!("arg_param_ty {}", arg_param_ty.repr(tcx));
+ debug!("deduce_sig_from_projection: arg_param_ty {}", arg_param_ty.repr(tcx));
let input_tys = match arg_param_ty.sty {
ty::ty_tup(ref tys) => { (*tys).clone() }
_ => { return None; }
};
- debug!("input_tys {}", input_tys.repr(tcx));
+ debug!("deduce_sig_from_projection: input_tys {}", input_tys.repr(tcx));
let ret_param_ty = projection.0.ty;
let ret_param_ty = fcx.infcx().resolve_type_vars_if_possible(&ret_param_ty);
- debug!("ret_param_ty {}", ret_param_ty.repr(tcx));
+ debug!("deduce_sig_from_projection: ret_param_ty {}", ret_param_ty.repr(tcx));
let fn_sig = ty::FnSig {
inputs: input_tys,
output: ty::FnConverging(ret_param_ty),
variadic: false
};
- debug!("fn_sig {}", fn_sig.repr(tcx));
+ debug!("deduce_sig_from_projection: fn_sig {}", fn_sig.repr(tcx));
- return Some((fn_sig, kind));
+ Some(fn_sig)
}
fn self_type_matches_expected_vid<'a,'tcx>(
match (&a.sty, &b.sty) {
(&ty::ty_rptr(_, ty::mt{ty: t_a, mutbl: mutbl_a}), &ty::ty_rptr(_, mt_b)) => {
- self.unpack_actual_value(t_a, |a| {
- match self.unsize_ty(t_a, a, mt_b.ty) {
- Some((ty, kind)) => {
- if !can_coerce_mutbls(mutbl_a, mt_b.mutbl) {
- return Err(ty::terr_mutability);
- }
-
- let coercion = Coercion(self.trace.clone());
- let r_borrow = self.fcx.infcx().next_region_var(coercion);
- let ty = ty::mk_rptr(self.tcx(),
- self.tcx().mk_region(r_borrow),
- ty::mt{ty: ty, mutbl: mt_b.mutbl});
- try!(self.fcx.infcx().try(|_| self.subtype(ty, b)));
- debug!("Success, coerced with AutoDerefRef(1, \
- AutoPtr(AutoUnsize({:?})))", kind);
- Ok(Some(AdjustDerefRef(AutoDerefRef {
- autoderefs: 1,
- autoref: Some(ty::AutoPtr(r_borrow, mt_b.mutbl,
- Some(box AutoUnsize(kind))))
- })))
+ match self.unsize_ty(t_a, mt_b.ty) {
+ Some((ty, kind)) => {
+ if !can_coerce_mutbls(mutbl_a, mt_b.mutbl) {
+ return Err(ty::terr_mutability);
}
- _ => Err(ty::terr_mismatch)
+
+ let coercion = Coercion(self.trace.clone());
+ let r_borrow = self.fcx.infcx().next_region_var(coercion);
+ let ty = ty::mk_rptr(self.tcx(),
+ self.tcx().mk_region(r_borrow),
+ ty::mt{ty: ty, mutbl: mt_b.mutbl});
+ try!(self.fcx.infcx().try(|_| self.subtype(ty, b)));
+ debug!("Success, coerced with AutoDerefRef(1, \
+ AutoPtr(AutoUnsize({:?})))", kind);
+ Ok(Some(AdjustDerefRef(AutoDerefRef {
+ autoderefs: 1,
+ autoref: Some(ty::AutoPtr(r_borrow, mt_b.mutbl,
+ Some(box AutoUnsize(kind))))
+ })))
}
- })
+ _ => Err(ty::terr_mismatch)
+ }
}
(&ty::ty_rptr(_, ty::mt{ty: t_a, mutbl: mutbl_a}), &ty::ty_ptr(mt_b)) => {
- self.unpack_actual_value(t_a, |a| {
- match self.unsize_ty(t_a, a, mt_b.ty) {
- Some((ty, kind)) => {
- if !can_coerce_mutbls(mutbl_a, mt_b.mutbl) {
- return Err(ty::terr_mutability);
- }
-
- let ty = ty::mk_ptr(self.tcx(),
- ty::mt{ty: ty, mutbl: mt_b.mutbl});
- try!(self.fcx.infcx().try(|_| self.subtype(ty, b)));
- debug!("Success, coerced with AutoDerefRef(1, \
- AutoPtr(AutoUnsize({:?})))", kind);
- Ok(Some(AdjustDerefRef(AutoDerefRef {
- autoderefs: 1,
- autoref: Some(ty::AutoUnsafe(mt_b.mutbl,
- Some(box AutoUnsize(kind))))
- })))
+ match self.unsize_ty(t_a, mt_b.ty) {
+ Some((ty, kind)) => {
+ if !can_coerce_mutbls(mutbl_a, mt_b.mutbl) {
+ return Err(ty::terr_mutability);
}
- _ => Err(ty::terr_mismatch)
+
+ let ty = ty::mk_ptr(self.tcx(),
+ ty::mt{ty: ty, mutbl: mt_b.mutbl});
+ try!(self.fcx.infcx().try(|_| self.subtype(ty, b)));
+ debug!("Success, coerced with AutoDerefRef(1, \
+ AutoPtr(AutoUnsize({:?})))", kind);
+ Ok(Some(AdjustDerefRef(AutoDerefRef {
+ autoderefs: 1,
+ autoref: Some(ty::AutoUnsafe(mt_b.mutbl,
+ Some(box AutoUnsize(kind))))
+ })))
}
- })
+ _ => Err(ty::terr_mismatch)
+ }
}
(&ty::ty_uniq(t_a), &ty::ty_uniq(t_b)) => {
- self.unpack_actual_value(t_a, |a| {
- match self.unsize_ty(t_a, a, t_b) {
- Some((ty, kind)) => {
- let ty = ty::mk_uniq(self.tcx(), ty);
- try!(self.fcx.infcx().try(|_| self.subtype(ty, b)));
- debug!("Success, coerced with AutoDerefRef(1, \
- AutoUnsizeUniq({:?}))", kind);
- Ok(Some(AdjustDerefRef(AutoDerefRef {
- autoderefs: 1,
- autoref: Some(ty::AutoUnsizeUniq(kind))
- })))
- }
- _ => Err(ty::terr_mismatch)
+ match self.unsize_ty(t_a, t_b) {
+ Some((ty, kind)) => {
+ let ty = ty::mk_uniq(self.tcx(), ty);
+ try!(self.fcx.infcx().try(|_| self.subtype(ty, b)));
+ debug!("Success, coerced with AutoDerefRef(1, \
+ AutoUnsizeUniq({:?}))", kind);
+ Ok(Some(AdjustDerefRef(AutoDerefRef {
+ autoderefs: 1,
+ autoref: Some(ty::AutoUnsizeUniq(kind))
+ })))
}
- })
+ _ => Err(ty::terr_mismatch)
+ }
}
_ => Err(ty::terr_mismatch)
}
// E.g., `[T, ..n]` -> `([T], UnsizeLength(n))`
fn unsize_ty(&self,
ty_a: Ty<'tcx>,
- a: Ty<'tcx>,
ty_b: Ty<'tcx>)
- -> Option<(Ty<'tcx>, ty::UnsizeKind<'tcx>)> {
- debug!("unsize_ty(a={:?}, ty_b={})", a, ty_b.repr(self.tcx()));
-
+ -> Option<(Ty<'tcx>, ty::UnsizeKind<'tcx>)>
+ {
let tcx = self.tcx();
- self.unpack_actual_value(ty_b, |b|
- match (&a.sty, &b.sty) {
- (&ty::ty_vec(t_a, Some(len)), &ty::ty_vec(_, None)) => {
- let ty = ty::mk_vec(tcx, t_a, None);
- Some((ty, ty::UnsizeLength(len)))
- }
- (&ty::ty_trait(ref data_a), &ty::ty_trait(ref data_b)) => {
- // Upcasts permit two things:
- //
- // 1. Dropping builtin bounds, e.g. `Foo+Send` to `Foo`
- // 2. Tightening the region bound, e.g. `Foo+'a` to `Foo+'b` if `'a : 'b`
- //
- // Note that neither of these changes requires any
- // change at runtime. Eventually this will be
- // generalized.
- //
- // We always upcast when we can because of reason
- // #2 (region bounds).
- if data_a.bounds.builtin_bounds.is_superset(&data_b.bounds.builtin_bounds) {
- // construct a type `a1` which is a version of
- // `a` using the upcast bounds from `b`
- let bounds_a1 = ty::ExistentialBounds {
- // From type b
- region_bound: data_b.bounds.region_bound,
- builtin_bounds: data_b.bounds.builtin_bounds,
-
- // From type a
- projection_bounds: data_a.bounds.projection_bounds.clone(),
- };
- let ty_a1 = ty::mk_trait(tcx, data_a.principal.clone(), bounds_a1);
-
- // relate `a1` to `b`
- let result = self.fcx.infcx().try(|_| {
- // it's ok to upcast from Foo+'a to Foo+'b so long as 'a : 'b
- try!(self.outlives(data_a.bounds.region_bound,
- data_b.bounds.region_bound));
- self.subtype(ty_a1, ty_b)
- });
-
- // if that was successful, we have a coercion
- match result {
- Ok(_) => Some((ty_b, ty::UnsizeUpcast(ty_b))),
- Err(_) => None,
- }
- } else {
- None
+ self.unpack_actual_value(ty_a, |a| {
+ self.unpack_actual_value(ty_b, |b| {
+ debug!("unsize_ty(a={}, b={})", a.repr(self.tcx()), b.repr(self.tcx()));
+ match (&a.sty, &b.sty) {
+ (&ty::ty_vec(t_a, Some(len)), &ty::ty_vec(_, None)) => {
+ let ty = ty::mk_vec(tcx, t_a, None);
+ Some((ty, ty::UnsizeLength(len)))
}
- }
- (_, &ty::ty_trait(ref data)) => {
- Some((ty_b, ty::UnsizeVtable(ty::TyTrait { principal: data.principal.clone(),
- bounds: data.bounds.clone() },
- ty_a)))
- }
- (&ty::ty_struct(did_a, substs_a), &ty::ty_struct(did_b, substs_b))
- if did_a == did_b => {
- debug!("unsizing a struct");
- // Try unsizing each type param in turn to see if we end up with ty_b.
- let ty_substs_a = substs_a.types.get_slice(subst::TypeSpace);
- let ty_substs_b = substs_b.types.get_slice(subst::TypeSpace);
- assert!(ty_substs_a.len() == ty_substs_b.len());
-
- let mut result = None;
- let tps = ty_substs_a.iter().zip(ty_substs_b.iter()).enumerate();
- for (i, (tp_a, tp_b)) in tps {
- if self.fcx.infcx().try(|_| self.subtype(*tp_a, *tp_b)).is_ok() {
- continue;
+ (&ty::ty_trait(ref data_a), &ty::ty_trait(ref data_b)) => {
+ // Upcasts permit two things:
+ //
+ // 1. Dropping builtin bounds, e.g. `Foo+Send` to `Foo`
+ // 2. Tightening the region bound, e.g. `Foo+'a` to `Foo+'b` if `'a : 'b`
+ //
+ // Note that neither of these changes requires any
+ // change at runtime. Eventually this will be
+ // generalized.
+ //
+ // We always upcast when we can because of reason
+ // #2 (region bounds).
+ if data_a.bounds.builtin_bounds.is_superset(&data_b.bounds.builtin_bounds) {
+ // construct a type `a1` which is a version of
+ // `a` using the upcast bounds from `b`
+ let bounds_a1 = ty::ExistentialBounds {
+ // From type b
+ region_bound: data_b.bounds.region_bound,
+ builtin_bounds: data_b.bounds.builtin_bounds,
+
+ // From type a
+ projection_bounds: data_a.bounds.projection_bounds.clone(),
+ };
+ let ty_a1 = ty::mk_trait(tcx, data_a.principal.clone(), bounds_a1);
+
+ // relate `a1` to `b`
+ let result = self.fcx.infcx().try(|_| {
+ // it's ok to upcast from Foo+'a to Foo+'b so long as 'a : 'b
+ try!(self.outlives(data_a.bounds.region_bound,
+ data_b.bounds.region_bound));
+ self.subtype(ty_a1, ty_b)
+ });
+
+ // if that was successful, we have a coercion
+ match result {
+ Ok(_) => Some((ty_b, ty::UnsizeUpcast(ty_b))),
+ Err(_) => None,
+ }
+ } else {
+ None
}
- match
- self.unpack_actual_value(
- *tp_a,
- |tp| self.unsize_ty(*tp_a, tp, *tp_b))
- {
- Some((new_tp, k)) => {
- // Check that the whole types match.
- let mut new_substs = substs_a.clone();
- new_substs.types.get_mut_slice(subst::TypeSpace)[i] = new_tp;
- let ty = ty::mk_struct(tcx, did_a, tcx.mk_substs(new_substs));
- if self.fcx.infcx().try(|_| self.subtype(ty, ty_b)).is_err() {
- debug!("Unsized type parameter '{}', but still \
- could not match types {} and {}",
- ppaux::ty_to_string(tcx, *tp_a),
- ppaux::ty_to_string(tcx, ty),
- ppaux::ty_to_string(tcx, ty_b));
- // We can only unsize a single type parameter, so
- // if we unsize one and it doesn't give us the
- // type we want, then we won't succeed later.
+ }
+ (_, &ty::ty_trait(ref data)) => {
+ Some((ty_b, ty::UnsizeVtable(ty::TyTrait {
+ principal: data.principal.clone(),
+ bounds: data.bounds.clone()
+ },
+ ty_a)))
+ }
+ (&ty::ty_struct(did_a, substs_a), &ty::ty_struct(did_b, substs_b))
+ if did_a == did_b => {
+ debug!("unsizing a struct");
+ // Try unsizing each type param in turn to see if we end up with ty_b.
+ let ty_substs_a = substs_a.types.get_slice(subst::TypeSpace);
+ let ty_substs_b = substs_b.types.get_slice(subst::TypeSpace);
+ assert!(ty_substs_a.len() == ty_substs_b.len());
+
+ let mut result = None;
+ let tps = ty_substs_a.iter().zip(ty_substs_b.iter()).enumerate();
+ for (i, (tp_a, tp_b)) in tps {
+ if self.fcx.infcx().try(|_| self.subtype(*tp_a, *tp_b)).is_ok() {
+ continue;
+ }
+ match self.unsize_ty(*tp_a, *tp_b) {
+ Some((new_tp, k)) => {
+ // Check that the whole types match.
+ let mut new_substs = substs_a.clone();
+ new_substs.types.get_mut_slice(subst::TypeSpace)[i] = new_tp;
+ let ty = ty::mk_struct(tcx, did_a, tcx.mk_substs(new_substs));
+ if self.fcx.infcx().try(|_| self.subtype(ty, ty_b)).is_err() {
+ debug!("Unsized type parameter '{}', but still \
+ could not match types {} and {}",
+ ppaux::ty_to_string(tcx, *tp_a),
+ ppaux::ty_to_string(tcx, ty),
+ ppaux::ty_to_string(tcx, ty_b));
+ // We can only unsize a single type parameter, so
+ // if we unsize one and it doesn't give us the
+ // type we want, then we won't succeed later.
+ break;
+ }
+
+ result = Some((ty, ty::UnsizeStruct(box k, i)));
break;
}
-
- result = Some((ty, ty::UnsizeStruct(box k, i)));
- break;
+ None => {}
}
- None => {}
}
+ result
}
- result
+ _ => None
}
- _ => None
- }
- )
+ })
+ })
}
fn coerce_from_fn_pointer(&self,
}
}
-// Checks that the type `actual` can be coerced to `expected`.
-pub fn coerce<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, sp: Span,
- expected: Ty<'tcx>, expr: &ast::Expr) {
+// Checks that the type of `expr` can be coerced to `expected`.
+pub fn coerce<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
+ sp: Span,
+ expected: Ty<'tcx>,
+ expr: &ast::Expr) {
let expr_ty = fcx.expr_ty(expr);
debug!("demand::coerce(expected = {}, expr_ty = {})",
expected.repr(fcx.ccx.tcx),
use middle::infer;
use middle::region;
-use middle::subst;
+use middle::subst::{self, Subst};
use middle::ty::{self, Ty};
use util::ppaux::{Repr, UserString};
use syntax::ast;
-use syntax::codemap::Span;
+use syntax::codemap::{self, Span};
+
+/// check_drop_impl confirms that the Drop implementation identfied by
+/// `drop_impl_did` is not any more specialized than the type it is
+/// attached to (Issue #8142).
+///
+/// This means:
+///
+/// 1. The self type must be nominal (this is already checked during
+/// coherence),
+///
+/// 2. The generic region/type parameters of the impl's self-type must
+/// all be parameters of the Drop impl itself (i.e. no
+/// specialization like `impl Drop for Foo<i32>`), and,
+///
+/// 3. Any bounds on the generic parameters must be reflected in the
+/// struct/enum definition for the nominal type itself (i.e.
+/// cannot do `struct S<T>; impl<T:Clone> Drop for S<T> { ... }`).
+///
+pub fn check_drop_impl(tcx: &ty::ctxt, drop_impl_did: ast::DefId) -> Result<(), ()> {
+ let ty::TypeScheme { generics: ref dtor_generics,
+ ty: ref dtor_self_type } = ty::lookup_item_type(tcx, drop_impl_did);
+ let dtor_predicates = ty::lookup_predicates(tcx, drop_impl_did);
+ match dtor_self_type.sty {
+ ty::ty_enum(self_type_did, self_to_impl_substs) |
+ ty::ty_struct(self_type_did, self_to_impl_substs) |
+ ty::ty_closure(self_type_did, self_to_impl_substs) => {
+ try!(ensure_drop_params_and_item_params_correspond(tcx,
+ drop_impl_did,
+ dtor_generics,
+ dtor_self_type,
+ self_type_did));
+
+ ensure_drop_predicates_are_implied_by_item_defn(tcx,
+ drop_impl_did,
+ &dtor_predicates,
+ self_type_did,
+ self_to_impl_substs)
+ }
+ _ => {
+ // Destructors only work on nominal types. This was
+ // already checked by coherence, so we can panic here.
+ let span = tcx.map.def_id_span(drop_impl_did, codemap::DUMMY_SP);
+ tcx.sess.span_bug(
+ span, &format!("should have been rejected by coherence check: {}",
+ dtor_self_type.repr(tcx)));
+ }
+ }
+}
+
+fn ensure_drop_params_and_item_params_correspond<'tcx>(
+ tcx: &ty::ctxt<'tcx>,
+ drop_impl_did: ast::DefId,
+ drop_impl_generics: &ty::Generics<'tcx>,
+ drop_impl_ty: &ty::Ty<'tcx>,
+ self_type_did: ast::DefId) -> Result<(), ()>
+{
+ // New strategy based on review suggestion from nikomatsakis.
+ //
+ // (In the text and code below, "named" denotes "struct/enum", and
+ // "generic params" denotes "type and region params")
+ //
+ // 1. Create fresh skolemized type/region "constants" for each of
+ // the named type's generic params. Instantiate the named type
+ // with the fresh constants, yielding `named_skolem`.
+ //
+ // 2. Create unification variables for each of the Drop impl's
+ // generic params. Instantiate the impl's Self's type with the
+ // unification-vars, yielding `drop_unifier`.
+ //
+ // 3. Attempt to unify Self_unif with Type_skolem. If unification
+ // succeeds, continue (i.e. with the predicate checks).
+
+ let ty::TypeScheme { generics: ref named_type_generics,
+ ty: named_type } =
+ ty::lookup_item_type(tcx, self_type_did);
+
+ let infcx = infer::new_infer_ctxt(tcx);
+ infcx.try(|snapshot| {
+ let (named_type_to_skolem, skol_map) =
+ infcx.construct_skolemized_subst(named_type_generics, snapshot);
+ let named_type_skolem = named_type.subst(tcx, &named_type_to_skolem);
+
+ let drop_impl_span = tcx.map.def_id_span(drop_impl_did, codemap::DUMMY_SP);
+ let drop_to_unifier =
+ infcx.fresh_substs_for_generics(drop_impl_span, drop_impl_generics);
+ let drop_unifier = drop_impl_ty.subst(tcx, &drop_to_unifier);
+
+ if let Ok(()) = infer::mk_eqty(&infcx, true, infer::TypeOrigin::Misc(drop_impl_span),
+ named_type_skolem, drop_unifier) {
+ // Even if we did manage to equate the types, the process
+ // may have just gathered unsolvable region constraints
+ // like `R == 'static` (represented as a pair of subregion
+ // constraints) for some skolemization constant R.
+ //
+ // However, the leak_check method allows us to confirm
+ // that no skolemized regions escaped (i.e. were related
+ // to other regions in the constraint graph).
+ if let Ok(()) = infcx.leak_check(&skol_map, snapshot) {
+ return Ok(())
+ }
+ }
+
+ span_err!(tcx.sess, drop_impl_span, E0366,
+ "Implementations of Drop cannot be specialized");
+ let item_span = tcx.map.span(self_type_did.node);
+ tcx.sess.span_note(item_span,
+ "Use same sequence of generic type and region \
+ parameters that is on the struct/enum definition");
+ return Err(());
+ })
+}
+
+/// Confirms that every predicate imposed by dtor_predicates is
+/// implied by assuming the predicates attached to self_type_did.
+fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>(
+ tcx: &ty::ctxt<'tcx>,
+ drop_impl_did: ast::DefId,
+ dtor_predicates: &ty::GenericPredicates<'tcx>,
+ self_type_did: ast::DefId,
+ self_to_impl_substs: &subst::Substs<'tcx>) -> Result<(), ()> {
+
+ // Here is an example, analogous to that from
+ // `compare_impl_method`.
+ //
+ // Consider a struct type:
+ //
+ // struct Type<'c, 'b:'c, 'a> {
+ // x: &'a Contents // (contents are irrelevant;
+ // y: &'c Cell<&'b Contents>, // only the bounds matter for our purposes.)
+ // }
+ //
+ // and a Drop impl:
+ //
+ // impl<'z, 'y:'z, 'x:'y> Drop for P<'z, 'y, 'x> {
+ // fn drop(&mut self) { self.y.set(self.x); } // (only legal if 'x: 'y)
+ // }
+ //
+ // We start out with self_to_impl_substs, that maps the generic
+ // parameters of Type to that of the Drop impl.
+ //
+ // self_to_impl_substs = {'c => 'z, 'b => 'y, 'a => 'x}
+ //
+ // Applying this to the predicates (i.e. assumptions) provided by the item
+ // definition yields the instantiated assumptions:
+ //
+ // ['y : 'z]
+ //
+ // We then check all of the predicates of the Drop impl:
+ //
+ // ['y:'z, 'x:'y]
+ //
+ // and ensure each is in the list of instantiated
+ // assumptions. Here, `'y:'z` is present, but `'x:'y` is
+ // absent. So we report an error that the Drop impl injected a
+ // predicate that is not present on the struct definition.
+
+ assert_eq!(self_type_did.krate, ast::LOCAL_CRATE);
+
+ let drop_impl_span = tcx.map.def_id_span(drop_impl_did, codemap::DUMMY_SP);
+
+ // We can assume the predicates attached to struct/enum definition
+ // hold.
+ let generic_assumptions = ty::lookup_predicates(tcx, self_type_did);
+
+ let assumptions_in_impl_context = generic_assumptions.instantiate(tcx, &self_to_impl_substs);
+ assert!(assumptions_in_impl_context.predicates.is_empty_in(subst::SelfSpace));
+ assert!(assumptions_in_impl_context.predicates.is_empty_in(subst::FnSpace));
+ let assumptions_in_impl_context =
+ assumptions_in_impl_context.predicates.get_slice(subst::TypeSpace);
+
+ // An earlier version of this code attempted to do this checking
+ // via the traits::fulfill machinery. However, it ran into trouble
+ // since the fulfill machinery merely turns outlives-predicates
+ // 'a:'b and T:'b into region inference constraints. It is simpler
+ // just to look for all the predicates directly.
+
+ assert!(dtor_predicates.predicates.is_empty_in(subst::SelfSpace));
+ assert!(dtor_predicates.predicates.is_empty_in(subst::FnSpace));
+ let predicates = dtor_predicates.predicates.get_slice(subst::TypeSpace);
+ for predicate in predicates {
+ // (We do not need to worry about deep analysis of type
+ // expressions etc because the Drop impls are already forced
+ // to take on a structure that is roughly a alpha-renaming of
+ // the generic parameters of the item definition.)
+
+ // This path now just checks *all* predicates via the direct
+ // lookup, rather than using fulfill machinery.
+ //
+ // However, it may be more efficient in the future to batch
+ // the analysis together via the fulfill , rather than the
+ // repeated `contains` calls.
+
+ if !assumptions_in_impl_context.contains(&predicate) {
+ let item_span = tcx.map.span(self_type_did.node);
+ let req = predicate.user_string(tcx);
+ span_err!(tcx.sess, drop_impl_span, E0367,
+ "The requirement `{}` is added only by the Drop impl.", req);
+ tcx.sess.span_note(item_span,
+ "The same requirement must be part of \
+ the struct/enum definition");
+ }
+ }
+
+ if tcx.sess.has_errors() {
+ return Err(());
+ }
+ Ok(())
+}
+/// check_safety_of_destructor_if_necessary confirms that the type
+/// expression `typ` conforms to the "Drop Check Rule" from the Sound
+/// Generic Drop (RFC 769).
+///
+/// ----
+///
+/// The Drop Check Rule is the following:
+///
+/// Let `v` be some value (either temporary or named) and 'a be some
+/// lifetime (scope). If the type of `v` owns data of type `D`, where
+///
+/// (1.) `D` has a lifetime- or type-parametric Drop implementation, and
+/// (2.) the structure of `D` can reach a reference of type `&'a _`, and
+/// (3.) either:
+///
+/// (A.) the Drop impl for `D` instantiates `D` at 'a directly,
+/// i.e. `D<'a>`, or,
+///
+/// (B.) the Drop impl for `D` has some type parameter with a
+/// trait bound `T` where `T` is a trait that has at least
+/// one method,
+///
+/// then 'a must strictly outlive the scope of v.
+///
+/// ----
+///
+/// This function is meant to by applied to the type for every
+/// expression in the program.
pub fn check_safety_of_destructor_if_necessary<'a, 'tcx>(rcx: &mut Rcx<'a, 'tcx>,
typ: ty::Ty<'tcx>,
span: Span,
};
// this closure doesn't implement the right kind of `Fn` trait
- if closure_kind != kind {
+ if !closure_kind.extends(kind) {
continue;
}
// def-id of the closure, so that once we decide, we can easily go
// back and process them.
deferred_call_resolutions: RefCell<DefIdMap<Vec<DeferredCallResolutionHandler<'tcx>>>>,
+
+ deferred_cast_checks: RefCell<Vec<CastCheck<'tcx>>>,
}
trait DeferredCallResolution<'tcx> {
type DeferredCallResolutionHandler<'tcx> = Box<DeferredCallResolution<'tcx>+'tcx>;
+/// Reifies a cast check to be checked once we have full type information for
+/// a function context.
+struct CastCheck<'tcx> {
+ expr: ast::Expr,
+ expr_ty: Ty<'tcx>,
+ cast_ty: Ty<'tcx>,
+ span: Span,
+}
+
/// When type-checking an expression, we propagate downward
/// whatever type hint we are able in the form of an `Expectation`.
#[derive(Copy)]
fn_sig_map: RefCell::new(NodeMap()),
fulfillment_cx: RefCell::new(traits::FulfillmentContext::new()),
deferred_call_resolutions: RefCell::new(DefIdMap()),
+ deferred_cast_checks: RefCell::new(Vec::new()),
}
}
visit::walk_crate(&mut visit, krate);
ccx.tcx.sess.abort_if_errors();
+
+ for drop_method_did in ccx.tcx.destructors.borrow().iter() {
+ if drop_method_did.krate == ast::LOCAL_CRATE {
+ let drop_impl_did = ccx.tcx.map.get_parent_did(drop_method_did.node);
+ match dropck::check_drop_impl(ccx.tcx, drop_impl_did) {
+ Ok(()) => {}
+ Err(()) => {
+ assert!(ccx.tcx.sess.has_errors());
+ }
+ }
+ }
+ }
+
+ ccx.tcx.sess.abort_if_errors();
}
fn check_bare_fn<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
vtable::select_all_fcx_obligations_and_apply_defaults(&fcx);
upvar::closure_analyze_fn(&fcx, fn_id, decl, body);
vtable::select_all_fcx_obligations_or_error(&fcx);
+ fcx.check_casts();
regionck::regionck_fn(&fcx, fn_id, fn_span, decl, body);
writeback::resolve_type_vars_in_fn(&fcx, decl, body);
}
}
-fn check_cast_inner<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
- span: Span,
- t_1: Ty<'tcx>,
- t_e: Ty<'tcx>,
- e: &ast::Expr) {
+fn check_cast<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, cast: &CastCheck<'tcx>) {
fn cast_through_integer_err<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
span: Span,
t_1: Ty<'tcx>,
}, t_e, None);
}
+ let span = cast.span;
+ let e = &cast.expr;
+ let t_e = structurally_resolved_type(fcx, span, cast.expr_ty);
+ let t_1 = structurally_resolved_type(fcx, span, cast.cast_ty);
+
+ // Check for trivial casts.
+ if !ty::type_has_ty_infer(t_1) {
+ if let Ok(()) = coercion::mk_assignty(fcx, e, t_e, t_1) {
+ if ty::type_is_numeric(t_1) && ty::type_is_numeric(t_e) {
+ fcx.tcx().sess.add_lint(lint::builtin::TRIVIAL_NUMERIC_CASTS,
+ e.id,
+ span,
+ format!("trivial numeric cast: `{}` as `{}`",
+ fcx.infcx().ty_to_string(t_e),
+ fcx.infcx().ty_to_string(t_1)));
+ } else {
+ fcx.tcx().sess.add_lint(lint::builtin::TRIVIAL_CASTS,
+ e.id,
+ span,
+ format!("trivial cast: `{}` as `{}`",
+ fcx.infcx().ty_to_string(t_e),
+ fcx.infcx().ty_to_string(t_1)));
+ }
+ return;
+ }
+ }
+
let t_e_is_bare_fn_item = ty::type_is_bare_fn_item(t_e);
let t_e_is_scalar = ty::type_is_scalar(t_e);
let t_e_is_integral = ty::type_is_integral(t_e);
let t_1_is_trivial = t_1_is_scalar && !t_1_is_char && !t_1_is_bare_fn;
if t_e_is_bare_fn_item && t_1_is_bare_fn {
- demand::coerce(fcx, e.span, t_1, &*e);
+ demand::coerce(fcx, e.span, t_1, &e);
} else if t_1_is_char {
let t_e = fcx.infcx().shallow_resolve(t_e);
if t_e.sty != ty::ty_uint(ast::TyU8) {
fcx.type_error_message(span, |actual| {
- format!("only `u8` can be cast as \
- `char`, not `{}`", actual)
+ format!("only `u8` can be cast as `char`, not `{}`", actual)
}, t_e, None);
}
} else if t_1.sty == ty::ty_bool {
span_err!(fcx.tcx().sess, span, E0054,
- "cannot cast as `bool`, compare with zero instead");
+ "cannot cast as `bool`, compare with zero instead");
} else if t_1_is_float && (t_e_is_scalar || t_e_is_c_enum) && !(
t_e_is_integral || t_e_is_float || t_e.sty == ty::ty_bool) {
// Casts to float must go through an integer or boolean
/* this case is allowed */
}
_ => {
- demand::coerce(fcx, e.span, t_1, &*e);
+ demand::coerce(fcx, e.span, t_1, &e);
}
}
} else if !(t_e_is_scalar && t_1_is_trivial) {
}
}
-fn check_cast<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
- cast_expr: &ast::Expr,
- e: &'tcx ast::Expr,
- t: &ast::Ty) {
- let id = cast_expr.id;
- let span = cast_expr.span;
-
- // Find the type of `e`. Supply hints based on the type we are casting to,
- // if appropriate.
- let t_1 = fcx.to_ty(t);
- let t_1 = structurally_resolved_type(fcx, span, t_1);
-
- check_expr_with_expectation(fcx, e, ExpectCastableToType(t_1));
-
- let t_e = fcx.expr_ty(e);
-
- debug!("t_1={}", fcx.infcx().ty_to_string(t_1));
- debug!("t_e={}", fcx.infcx().ty_to_string(t_e));
-
- if ty::type_is_error(t_e) {
- fcx.write_error(id);
- return
- }
-
- if !fcx.type_is_known_to_be_sized(t_1, cast_expr.span) {
- report_cast_to_unsized_type(fcx, span, t.span, e.span, t_1, t_e, id);
- return
- }
-
- if ty::type_is_trait(t_1) {
- // This will be looked up later on.
- vtable::check_object_cast(fcx, cast_expr, e, t_1);
- fcx.write_ty(id, t_1);
- return
- }
-
- let t_1 = structurally_resolved_type(fcx, span, t_1);
- let t_e = structurally_resolved_type(fcx, span, t_e);
-
- check_cast_inner(fcx, span, t_1, t_e, e);
- fcx.write_ty(id, t_1);
-}
-
impl<'a, 'tcx> AstConv<'tcx> for FnCtxt<'a, 'tcx> {
fn tcx(&self) -> &ty::ctxt<'tcx> { self.ccx.tcx }
}
pub fn tag(&self) -> String {
- format!("{:?}", self as *const FnCtxt)
+ let self_ptr: *const FnCtxt = self;
+ format!("{:?}", self_ptr)
}
pub fn local_ty(&self, span: Span, nid: ast::NodeId) -> Ty<'tcx> {
self.inh.node_types.borrow_mut().insert(node_id, ty);
}
- pub fn write_object_cast(&self,
- key: ast::NodeId,
- trait_ref: ty::PolyTraitRef<'tcx>) {
- debug!("write_object_cast key={} trait_ref={}",
- key, trait_ref.repr(self.tcx()));
- self.inh.object_cast_map.borrow_mut().insert(key, trait_ref);
- }
-
pub fn write_substs(&self, node_id: ast::NodeId, substs: ty::ItemSubsts<'tcx>) {
if !substs.substs.is_noop() {
debug!("write_substs({}, {}) in fcx {}",
o_field.map(|f| ty::lookup_field_type(self.tcx(), class_id, f.id, substs))
.map(|t| self.normalize_associated_types_in(span, &t))
}
+
+ fn check_casts(&self) {
+ let mut deferred_cast_checks = self.inh.deferred_cast_checks.borrow_mut();
+ for check in deferred_cast_checks.iter() {
+ check_cast(self, check);
+ }
+
+ deferred_cast_checks.clear();
+ }
}
impl<'a, 'tcx> RegionScope for FnCtxt<'a, 'tcx> {
if let ast::TyFixedLengthVec(_, ref count_expr) = t.node {
check_expr_with_hint(fcx, &**count_expr, tcx.types.uint);
}
- check_cast(fcx, expr, &**e, &**t);
+
+ // Find the type of `e`. Supply hints based on the type we are casting to,
+ // if appropriate.
+ let t_1 = fcx.to_ty(t);
+ let t_1 = structurally_resolved_type(fcx, expr.span, t_1);
+ check_expr_with_expectation(fcx, e, ExpectCastableToType(t_1));
+ let t_e = fcx.expr_ty(e);
+
+ // Eagerly check for some obvious errors.
+ if ty::type_is_error(t_e) {
+ fcx.write_error(id);
+ } else if !fcx.type_is_known_to_be_sized(t_1, expr.span) {
+ report_cast_to_unsized_type(fcx, expr.span, t.span, e.span, t_1, t_e, id);
+ } else {
+ // Write a type for the whole expression, assuming everything is going
+ // to work out Ok.
+ fcx.write_ty(id, t_1);
+
+ // Defer other checks until we're done type checking.
+ let mut deferred_cast_checks = fcx.inh.deferred_cast_checks.borrow_mut();
+ deferred_cast_checks.push(CastCheck {
+ expr: (**e).clone(),
+ expr_ty: t_e,
+ cast_ty: t_1,
+ span: expr.span,
+ });
+ }
}
ast::ExprVec(ref args) => {
let uty = expected.to_option(fcx).and_then(|uty| {
check_expr_with_hint(fcx, e, declty);
demand::coerce(fcx, e.span, declty, e);
vtable::select_all_fcx_obligations_or_error(fcx);
+ fcx.check_casts();
regionck::regionck_expr(fcx, e);
writeback::resolve_type_vars_in_expr(fcx, e);
}
ty: attr::IntType,
disr: ty::Disr) -> bool {
fn uint_in_range(ccx: &CrateCtxt, ty: ast::UintTy, disr: ty::Disr) -> bool {
+ #![allow(trivial_numeric_casts)]
+
match ty {
ast::TyU8 => disr as u8 as Disr == disr,
ast::TyU16 => disr as u16 as Disr == disr,
id: ast::NodeId,
hint: attr::ReprAttr)
-> Vec<Rc<ty::VariantInfo<'tcx>>> {
+ #![allow(trivial_numeric_casts)]
use std::num::Int;
let rty = ty::node_id_to_type(ccx.tcx, id);
// except according to those terms.
use check::{FnCtxt};
-use check::demand;
use middle::traits::{self, ObjectSafetyViolation, MethodViolationCode};
use middle::traits::{Obligation, ObligationCause};
use middle::traits::report_fulfillment_errors;
use util::nodemap::FnvHashSet;
use util::ppaux::{Repr, UserString};
-pub fn check_object_cast<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
- cast_expr: &ast::Expr,
- source_expr: &ast::Expr,
- target_object_ty: Ty<'tcx>)
-{
- let tcx = fcx.tcx();
- debug!("check_object_cast(cast_expr={}, target_object_ty={})",
- cast_expr.repr(tcx),
- target_object_ty.repr(tcx));
-
- // Look up vtables for the type we're casting to,
- // passing in the source and target type. The source
- // must be a pointer type suitable to the object sigil,
- // e.g.: `&x as &Trait` or `box x as Box<Trait>`
-
- // First, construct a fresh type that we can feed into `<expr>`
- // within `<expr> as <type>` to inform type inference (e.g. to
- // tell it that we are expecting a `Box<_>` or an `&_`).
- let fresh_ty = fcx.infcx().next_ty_var();
- let (object_trait_ty, source_expected_ty) = match target_object_ty.sty {
- ty::ty_uniq(object_trait_ty) => {
- (object_trait_ty, ty::mk_uniq(fcx.tcx(), fresh_ty))
- }
- ty::ty_rptr(target_region, ty::mt { ty: object_trait_ty,
- mutbl: target_mutbl }) => {
- (object_trait_ty,
- ty::mk_rptr(fcx.tcx(),
- target_region, ty::mt { ty: fresh_ty,
- mutbl: target_mutbl }))
- }
- _ => {
- fcx.tcx().sess.span_bug(source_expr.span, "expected object type");
- }
- };
-
- let source_ty = fcx.expr_ty(source_expr);
- debug!("check_object_cast pre unify source_ty={}", source_ty.repr(tcx));
-
- // This ensures that the source_ty <: source_expected_ty, which
- // will ensure e.g. that &'a T <: &'b T when doing `&'a T as &'b Trait`
- //
- // FIXME (pnkfelix): do we need to use suptype_with_fn in order to
- // override the error message emitted when the types do not work
- // out in the manner desired?
- demand::suptype(fcx, source_expr.span, source_expected_ty, source_ty);
-
- debug!("check_object_cast postunify source_ty={}", source_ty.repr(tcx));
-
- let object_trait = object_trait(&object_trait_ty);
-
- // Ensure that if Ptr<T> is cast to Ptr<Trait>, then T : Trait.
- push_cast_obligation(fcx, cast_expr, object_trait, fresh_ty);
- check_object_safety(tcx, object_trait, source_expr.span);
-
- fn object_trait<'a, 'tcx>(t: &'a Ty<'tcx>) -> &'a ty::TyTrait<'tcx> {
- match t.sty {
- ty::ty_trait(ref ty_trait) => &**ty_trait,
- _ => panic!("expected ty_trait")
- }
- }
-
- fn push_cast_obligation<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
- cast_expr: &ast::Expr,
- object_trait: &ty::TyTrait<'tcx>,
- referent_ty: Ty<'tcx>) {
- let object_trait_ref =
- register_object_cast_obligations(fcx,
- cast_expr.span,
- object_trait,
- referent_ty);
-
- // Finally record the object_trait_ref for use during trans
- // (it would prob be better not to do this, but it's just kind
- // of a pain to have to reconstruct it).
- fcx.write_object_cast(cast_expr.id, object_trait_ref);
- }
-}
// Check that a trait is 'object-safe'. This should be checked whenever a trait object
// is created (by casting or coercion, etc.). A trait is object-safe if all its
&enum_definition.variants);
},
ast::ItemDefaultImpl(_, ref ast_trait_ref) => {
- let trait_ref = astconv::instantiate_trait_ref(&ccx.icx(&()),
- &ExplicitRscope,
- ast_trait_ref,
- Some(it.id),
- None,
- None);
+ let trait_ref =
+ astconv::instantiate_mono_trait_ref(&ccx.icx(&()),
+ &ExplicitRscope,
+ ast_trait_ref,
+ None);
ty::record_trait_has_default_impl(tcx, trait_ref.def_id);
+
+ tcx.impl_trait_refs.borrow_mut().insert(it.id, trait_ref);
}
ast::ItemImpl(_, _,
ref generics,
}
}
- if let Some(ref trait_ref) = *opt_trait_ref {
- astconv::instantiate_trait_ref(&ccx.icx(&ty_predicates),
- &ExplicitRscope,
- trait_ref,
- Some(it.id),
- Some(selfty),
- None);
+ if let Some(ref ast_trait_ref) = *opt_trait_ref {
+ let trait_ref =
+ astconv::instantiate_mono_trait_ref(&ccx.icx(&ty_predicates),
+ &ExplicitRscope,
+ ast_trait_ref,
+ Some(selfty));
+
+ tcx.impl_trait_refs.borrow_mut().insert(it.id, trait_ref);
}
enforce_impl_ty_params_are_constrained(tcx,
E0319, // trait impls for defaulted traits allowed just for structs/enums
E0320, // recursive overflow during dropck
E0321, // extended coherence rules for defaulted traits violated
- E0322 // cannot implement Sized explicitly
+ E0322, // cannot implement Sized explicitly
+ E0366, // dropck forbid specialization to concrete type or region
+ E0367 // dropck forbid specialization to predicate not in struct/enum
}
__build_diagnostic_array! { DIAGNOSTICS }
};
(*((*renderer).opaque as *mut hoedown_html_renderer_state)).opaque
= &mut opaque as *mut _ as *mut libc::c_void;
- (*renderer).blockcode = Some(block as blockcodefn);
- (*renderer).header = Some(header as headerfn);
+ (*renderer).blockcode = Some(block);
+ (*renderer).header = Some(header);
let document = hoedown_document_new(renderer, HOEDOWN_EXTENSIONS, 16);
hoedown_document_render(document, ob, s.as_ptr(),
unsafe {
let ob = hoedown_buffer_new(DEF_OUNIT);
let renderer = hoedown_html_renderer_new(0, 0);
- (*renderer).blockcode = Some(block as blockcodefn);
- (*renderer).header = Some(header as headerfn);
+ (*renderer).blockcode = Some(block);
+ (*renderer).header = Some(header);
(*((*renderer).opaque as *mut hoedown_html_renderer_state)).opaque
= tests as *mut _ as *mut libc::c_void;
unsafe {
let ob = hoedown_buffer_new(DEF_OUNIT);
let mut plain_renderer: hoedown_renderer = ::std::mem::zeroed();
- let renderer = &mut plain_renderer as *mut hoedown_renderer;
+ let renderer: *mut hoedown_renderer = &mut plain_renderer;
(*renderer).opaque = ob as *mut libc::c_void;
- (*renderer).link = Some(link as linkfn);
- (*renderer).normal_text = Some(normal_text as normaltextfn);
+ (*renderer).link = Some(link);
+ (*renderer).normal_text = Some(normal_text);
let document = hoedown_document_new(renderer, HOEDOWN_EXTENSIONS, 16);
hoedown_document_render(document, ob, md.as_ptr(),
ast::ItemExternCrate(ref p) => {
let path = match *p {
None => None,
- Some((ref x, _)) => Some(x.to_string()),
+ Some(x) => Some(x.to_string()),
};
om.extern_crates.push(ExternCrate {
name: name,
macro_rules! to_json_impl_i64 {
($($t:ty), +) => (
$(impl ToJson for $t {
- fn to_json(&self) -> Json { Json::I64(*self as i64) }
+ fn to_json(&self) -> Json {
+ #![allow(trivial_numeric_casts)]
+ Json::I64(*self as i64)
+ }
})+
)
}
macro_rules! to_json_impl_u64 {
($($t:ty), +) => (
$(impl ToJson for $t {
- fn to_json(&self) -> Json { Json::U64(*self as u64) }
+ fn to_json(&self) -> Json {
+ #![allow(trivial_numeric_casts)]
+ Json::U64(*self as u64)
+ }
})+
)
}
///
/// This function will return an error if `path` does not already exist.
/// Other errors may also be returned according to `OpenOptions::open`.
+ ///
+ /// # Examples
+ ///
+ /// ```no_run
+ /// use std::fs::File;
+ ///
+ /// # fn foo() -> std::io::Result<()> {
+ /// let mut f = try!(File::open("foo.txt"));
+ /// # Ok(())
+ /// # }
+ /// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn open<P: AsRef<Path>>(path: P) -> io::Result<File> {
OpenOptions::new().read(true).open(path)
/// and will truncate it if it does.
///
/// See the `OpenOptions::open` function for more details.
+ ///
+ /// # Examples
+ ///
+ /// ```no_run
+ /// use std::fs::File;
+ ///
+ /// # fn foo() -> std::io::Result<()> {
+ /// let mut f = try!(File::create("foo.txt"));
+ /// # Ok(())
+ /// # }
+ /// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn create<P: AsRef<Path>>(path: P) -> io::Result<File> {
OpenOptions::new().write(true).create(true).truncate(true).open(path)
///
/// This function will attempt to ensure that all in-core data reaches the
/// filesystem before returning.
+ ///
+ /// # Examples
+ ///
+ /// ```no_run
+ /// use std::fs::File;
+ /// use std::io::prelude::*;
+ ///
+ /// # fn foo() -> std::io::Result<()> {
+ /// let mut f = try!(File::create("foo.txt"));
+ /// try!(f.write_all(b"Hello, world!"));
+ ///
+ /// try!(f.sync_all());
+ /// # Ok(())
+ /// # }
+ /// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn sync_all(&self) -> io::Result<()> {
self.inner.fsync()
///
/// Note that some platforms may simply implement this in terms of
/// `sync_all`.
+ ///
+ /// # Examples
+ ///
+ /// ```no_run
+ /// use std::fs::File;
+ /// use std::io::prelude::*;
+ ///
+ /// # fn foo() -> std::io::Result<()> {
+ /// let mut f = try!(File::create("foo.txt"));
+ /// try!(f.write_all(b"Hello, world!"));
+ ///
+ /// try!(f.sync_data());
+ /// # Ok(())
+ /// # }
+ /// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn sync_data(&self) -> io::Result<()> {
self.inner.datasync()
/// be shrunk. If it is greater than the current file's size, then the file
/// will be extended to `size` and have all of the intermediate data filled
/// in with 0s.
+ ///
+ /// # Examples
+ ///
+ /// ```no_run
+ /// use std::fs::File;
+ ///
+ /// # fn foo() -> std::io::Result<()> {
+ /// let mut f = try!(File::open("foo.txt"));
+ /// try!(f.set_len(0));
+ /// # Ok(())
+ /// # }
+ /// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn set_len(&self, size: u64) -> io::Result<()> {
self.inner.truncate(size)
}
/// Queries metadata about the underlying file.
+ ///
+ /// # Examples
+ ///
+ /// ```no_run
+ /// use std::fs::File;
+ ///
+ /// # fn foo() -> std::io::Result<()> {
+ /// let mut f = try!(File::open("foo.txt"));
+ /// let metadata = try!(f.metadata());
+ /// # Ok(())
+ /// # }
+ /// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn metadata(&self) -> io::Result<Metadata> {
self.inner.file_attr().map(Metadata)
///
/// The buffer will be written out when the writer is dropped.
#[stable(feature = "rust1", since = "1.0.0")]
-pub struct BufWriter<W> {
+pub struct BufWriter<W: Write> {
inner: Option<W>,
buf: Vec<u8>,
}
}
#[stable(feature = "rust1", since = "1.0.0")]
-impl<W> fmt::Debug for BufWriter<W> where W: fmt::Debug {
+impl<W: Write> fmt::Debug for BufWriter<W> where W: fmt::Debug {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
write!(fmt, "BufWriter {{ writer: {:?}, buffer: {}/{} }}",
self.inner.as_ref().unwrap(), self.buf.len(), self.buf.capacity())
///
/// The buffer will be written out when the writer is dropped.
#[stable(feature = "rust1", since = "1.0.0")]
-pub struct LineWriter<W> {
+pub struct LineWriter<W: Write> {
inner: BufWriter<W>,
}
}
#[stable(feature = "rust1", since = "1.0.0")]
-impl<W> fmt::Debug for LineWriter<W> where W: fmt::Debug {
+impl<W: Write> fmt::Debug for LineWriter<W> where W: fmt::Debug {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
write!(fmt, "LineWriter {{ writer: {:?}, buffer: {}/{} }}",
self.inner.inner, self.inner.buf.len(),
}
}
-struct InternalBufWriter<W>(BufWriter<W>);
+struct InternalBufWriter<W: Write>(BufWriter<W>);
-impl<W> InternalBufWriter<W> {
+impl<W: Read + Write> InternalBufWriter<W> {
fn get_mut(&mut self) -> &mut BufWriter<W> {
let InternalBufWriter(ref mut w) = *self;
return w;
}
}
-impl<W: Read> Read for InternalBufWriter<W> {
+impl<W: Read + Write> Read for InternalBufWriter<W> {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
self.get_mut().inner.as_mut().unwrap().read(buf)
}
///
/// The output buffer will be written out when this stream is dropped.
#[stable(feature = "rust1", since = "1.0.0")]
-pub struct BufStream<S> {
+pub struct BufStream<S: Write> {
inner: BufReader<InternalBufWriter<S>>
}
}
#[stable(feature = "rust1", since = "1.0.0")]
-impl<S> fmt::Debug for BufStream<S> where S: fmt::Debug {
+impl<S: Write> fmt::Debug for BufStream<S> where S: fmt::Debug {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
let reader = &self.inner;
let writer = &self.inner.inner.0;
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, R: Read + ?Sized> Read for &'a mut R {
+ #[inline]
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
(**self).read(buf)
}
+
+ #[inline]
fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
(**self).read_to_end(buf)
}
+
+ #[inline]
fn read_to_string(&mut self, buf: &mut String) -> io::Result<usize> {
(**self).read_to_string(buf)
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, W: Write + ?Sized> Write for &'a mut W {
+ #[inline]
fn write(&mut self, buf: &[u8]) -> io::Result<usize> { (**self).write(buf) }
+
+ #[inline]
fn flush(&mut self) -> io::Result<()> { (**self).flush() }
+
+ #[inline]
fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
(**self).write_all(buf)
}
+
+ #[inline]
fn write_fmt(&mut self, fmt: fmt::Arguments) -> io::Result<()> {
(**self).write_fmt(fmt)
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, S: Seek + ?Sized> Seek for &'a mut S {
+ #[inline]
fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> { (**self).seek(pos) }
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a, B: BufRead + ?Sized> BufRead for &'a mut B {
+ #[inline]
fn fill_buf(&mut self) -> io::Result<&[u8]> { (**self).fill_buf() }
+
+ #[inline]
fn consume(&mut self, amt: usize) { (**self).consume(amt) }
+
+ #[inline]
fn read_until(&mut self, byte: u8, buf: &mut Vec<u8>) -> io::Result<usize> {
(**self).read_until(byte, buf)
}
+
+ #[inline]
fn read_line(&mut self, buf: &mut String) -> io::Result<usize> {
(**self).read_line(buf)
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<R: Read + ?Sized> Read for Box<R> {
+ #[inline]
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
(**self).read(buf)
}
+
+ #[inline]
fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
(**self).read_to_end(buf)
}
+
+ #[inline]
fn read_to_string(&mut self, buf: &mut String) -> io::Result<usize> {
(**self).read_to_string(buf)
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<W: Write + ?Sized> Write for Box<W> {
+ #[inline]
fn write(&mut self, buf: &[u8]) -> io::Result<usize> { (**self).write(buf) }
+
+ #[inline]
fn flush(&mut self) -> io::Result<()> { (**self).flush() }
+
+ #[inline]
fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
(**self).write_all(buf)
}
+
+ #[inline]
fn write_fmt(&mut self, fmt: fmt::Arguments) -> io::Result<()> {
(**self).write_fmt(fmt)
}
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<S: Seek + ?Sized> Seek for Box<S> {
+ #[inline]
fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> { (**self).seek(pos) }
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<B: BufRead + ?Sized> BufRead for Box<B> {
+ #[inline]
fn fill_buf(&mut self) -> io::Result<&[u8]> { (**self).fill_buf() }
+
+ #[inline]
fn consume(&mut self, amt: usize) { (**self).consume(amt) }
+
+ #[inline]
fn read_until(&mut self, byte: u8, buf: &mut Vec<u8>) -> io::Result<usize> {
(**self).read_until(byte, buf)
}
+
+ #[inline]
fn read_line(&mut self, buf: &mut String) -> io::Result<usize> {
(**self).read_line(buf)
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a> Read for &'a [u8] {
+ #[inline]
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
let amt = cmp::min(buf.len(), self.len());
let (a, b) = self.split_at(amt);
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a> BufRead for &'a [u8] {
+ #[inline]
fn fill_buf(&mut self) -> io::Result<&[u8]> { Ok(*self) }
+
+ #[inline]
fn consume(&mut self, amt: usize) { *self = &self[amt..]; }
}
#[stable(feature = "rust1", since = "1.0.0")]
impl<'a> Write for &'a mut [u8] {
+ #[inline]
fn write(&mut self, data: &[u8]) -> io::Result<usize> {
let amt = cmp::min(data.len(), self.len());
let (a, b) = mem::replace(self, &mut []).split_at_mut(amt);
Ok(amt)
}
+ #[inline]
fn write_all(&mut self, data: &[u8]) -> io::Result<()> {
if try!(self.write(data)) == data.len() {
Ok(())
}
}
+ #[inline]
fn flush(&mut self) -> io::Result<()> { Ok(()) }
}
#[stable(feature = "rust1", since = "1.0.0")]
impl Write for Vec<u8> {
+ #[inline]
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
self.push_all(buf);
Ok(buf.len())
}
+ #[inline]
fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
self.push_all(buf);
Ok(())
}
+ #[inline]
fn flush(&mut self) -> io::Result<()> { Ok(()) }
}
+
+#[cfg(test)]
+mod tests {
+ use io::prelude::*;
+ use vec::Vec;
+ use test;
+
+ #[bench]
+ fn bench_read_slice(b: &mut test::Bencher) {
+ let buf = [5; 1024];
+ let mut dst = [0; 128];
+
+ b.iter(|| {
+ let mut rd = &buf[..];
+ for _ in (0 .. 8) {
+ let _ = rd.read(&mut dst);
+ test::black_box(&dst);
+ }
+ })
+ }
+
+ #[bench]
+ fn bench_write_slice(b: &mut test::Bencher) {
+ let mut buf = [0; 1024];
+ let src = [5; 128];
+
+ b.iter(|| {
+ let mut wr = &mut buf[..];
+ for _ in (0 .. 8) {
+ let _ = wr.write_all(&src);
+ test::black_box(&wr);
+ }
+ })
+ }
+
+ #[bench]
+ fn bench_read_vec(b: &mut test::Bencher) {
+ let buf = vec![5; 1024];
+ let mut dst = [0; 128];
+
+ b.iter(|| {
+ let mut rd = &buf[..];
+ for _ in (0 .. 8) {
+ let _ = rd.read(&mut dst);
+ test::black_box(&dst);
+ }
+ })
+ }
+
+ #[bench]
+ fn bench_write_vec(b: &mut test::Bencher) {
+ let mut buf = Vec::with_capacity(1024);
+ let src = [5; 128];
+
+ b.iter(|| {
+ let mut wr = &mut buf[..];
+ for _ in (0 .. 8) {
+ let _ = wr.write_all(&src);
+ test::black_box(&wr);
+ }
+ })
+ }
+}
pub fn get(&'static self) -> Option<Arc<T>> {
let _g = self.lock.lock();
unsafe {
- let mut ptr = *self.ptr.get();
+ let ptr = *self.ptr.get();
if ptr.is_null() {
- ptr = boxed::into_raw(self.init());
- *self.ptr.get() = ptr;
+ Some(self.init())
} else if ptr as usize == 1 {
- return None
+ None
+ } else {
+ Some((*ptr).clone())
}
- Some((*ptr).clone())
}
}
- fn init(&'static self) -> Box<Arc<T>> {
- rt::at_exit(move || unsafe {
+ unsafe fn init(&'static self) -> Arc<T> {
+ // If we successfully register an at exit handler, then we cache the
+ // `Arc` allocation in our own internal box (it will get deallocated by
+ // the at exit handler). Otherwise we just return the freshly allocated
+ // `Arc`.
+ let registered = rt::at_exit(move || {
let g = self.lock.lock();
let ptr = *self.ptr.get();
*self.ptr.get() = 1 as *mut _;
drop(g);
drop(Box::from_raw(ptr))
});
- Box::new((self.init)())
+ let ret = (self.init)();
+ if registered.is_ok() {
+ *self.ptr.get() = boxed::into_raw(Box::new(ret.clone()));
+ }
+ return ret
}
}
use unicode::str as core_str;
use error as std_error;
use fmt;
-use iter::Iterator;
+use iter::{self, Iterator, IteratorExt, Extend};
use marker::Sized;
use ops::{Drop, FnOnce};
use option::Option::{self, Some, None};
use result::Result::{Ok, Err};
use result;
-use slice;
use string::String;
use str;
use vec::Vec;
const DEFAULT_BUF_SIZE: usize = 64 * 1024;
// Acquires a slice of the vector `v` from its length to its capacity
-// (uninitialized data), reads into it, and then updates the length.
+// (after initializing the data), reads into it, and then updates the length.
//
// This function is leveraged to efficiently read some bytes into a destination
// vector without extra copying and taking advantage of the space that's already
// in `v`.
-//
-// The buffer we're passing down, however, is pointing at uninitialized data
-// (the end of a `Vec`), and many operations will be *much* faster if we don't
-// have to zero it out. In order to prevent LLVM from generating an `undef`
-// value when reads happen from this uninitialized memory, we force LLVM to
-// think it's initialized by sending it through a black box. This should prevent
-// actual undefined behavior after optimizations.
fn with_end_to_cap<F>(v: &mut Vec<u8>, f: F) -> Result<usize>
where F: FnOnce(&mut [u8]) -> Result<usize>
{
- unsafe {
- let n = try!(f({
- let base = v.as_mut_ptr().offset(v.len() as isize);
- black_box(slice::from_raw_parts_mut(base,
- v.capacity() - v.len()))
- }));
-
- // If the closure (typically a `read` implementation) reported that it
- // read a larger number of bytes than the vector actually has, we need
- // to be sure to clamp the vector to at most its capacity.
- let new_len = cmp::min(v.capacity(), v.len() + n);
- v.set_len(new_len);
- return Ok(n);
- }
-
- // Semi-hack used to prevent LLVM from retaining any assumptions about
- // `dummy` over this function call
- unsafe fn black_box<T>(mut dummy: T) -> T {
- asm!("" :: "r"(&mut dummy) : "memory");
- dummy
+ let len = v.len();
+ let new_area = v.capacity() - len;
+ v.extend(iter::repeat(0).take(new_area));
+ match f(&mut v[len..]) {
+ Ok(n) => {
+ v.truncate(len + n);
+ Ok(n)
+ }
+ Err(e) => {
+ v.truncate(len);
+ Err(e)
+ }
}
}
/// A `Write` adaptor which will write data to multiple locations.
///
-/// For more information, see `WriteExt::broadcast`.
-#[unstable(feature = "io", reason = "awaiting stability of WriteExt::broadcast")]
+/// For more information, see `Write::broadcast`.
+#[unstable(feature = "io", reason = "awaiting stability of Write::broadcast")]
pub struct Broadcast<T, U> {
first: T,
second: U,
}
-#[unstable(feature = "io", reason = "awaiting stability of WriteExt::broadcast")]
+#[unstable(feature = "io", reason = "awaiting stability of Write::broadcast")]
impl<T: Write, U: Write> Write for Broadcast<T, U> {
fn write(&mut self, data: &[u8]) -> Result<usize> {
let n = try!(self.first.write(data));
/// Adaptor to chain together two instances of `Read`.
///
-/// For more information, see `ReadExt::chain`.
+/// For more information, see `Read::chain`.
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Chain<T, U> {
first: T,
/// Reader adaptor which limits the bytes read from an underlying reader.
///
-/// For more information, see `ReadExt::take`.
+/// For more information, see `Read::take`.
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Take<T> {
inner: T,
/// An adaptor which will emit all read data to a specified writer as well.
///
-/// For more information see `ReadExt::tee`
-#[unstable(feature = "io", reason = "awaiting stability of ReadExt::tee")]
+/// For more information see `Read::tee`
+#[unstable(feature = "io", reason = "awaiting stability of Read::tee")]
pub struct Tee<R, W> {
reader: R,
writer: W,
}
-#[unstable(feature = "io", reason = "awaiting stability of ReadExt::tee")]
+#[unstable(feature = "io", reason = "awaiting stability of Read::tee")]
impl<R: Read, W: Write> Read for Tee<R, W> {
fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
let n = try!(self.reader.read(buf));
/// A bridge from implementations of `Read` to an `Iterator` of `u8`.
///
-/// See `ReadExt::bytes` for more information.
+/// See `Read::bytes` for more information.
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Bytes<R> {
inner: R,
/// A bridge from implementations of `Read` to an `Iterator` of `char`.
///
-/// See `ReadExt::chars` for more information.
-#[unstable(feature = "io", reason = "awaiting stability of ReadExt::chars")]
+/// See `Read::chars` for more information.
+#[unstable(feature = "io", reason = "awaiting stability of Read::chars")]
pub struct Chars<R> {
inner: R,
}
/// An enumeration of possible errors that can be generated from the `Chars`
/// adapter.
#[derive(PartialEq, Clone, Debug)]
-#[unstable(feature = "io", reason = "awaiting stability of ReadExt::chars")]
+#[unstable(feature = "io", reason = "awaiting stability of Read::chars")]
pub enum CharsError {
/// Variant representing that the underlying stream was read successfully
/// but it did not contain valid utf8 data.
Other(Error),
}
-#[unstable(feature = "io", reason = "awaiting stability of ReadExt::chars")]
+#[unstable(feature = "io", reason = "awaiting stability of Read::chars")]
impl<R: Read> Iterator for Chars<R> {
type Item = result::Result<char, CharsError>;
}
}
-#[unstable(feature = "io", reason = "awaiting stability of ReadExt::chars")]
+#[unstable(feature = "io", reason = "awaiting stability of Read::chars")]
impl std_error::Error for CharsError {
fn description(&self) -> &str {
match *self {
}
}
-#[unstable(feature = "io", reason = "awaiting stability of ReadExt::chars")]
+#[unstable(feature = "io", reason = "awaiting stability of Read::chars")]
impl fmt::Display for CharsError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
//! ```
//!
//! This module contains reexports of many core I/O traits such as `Read`,
-//! `Write`, `ReadExt`, and `WriteExt`. Structures and functions are not
+//! `Write` and `BufRead`. Structures and functions are not
//! contained in this module.
#![stable(feature = "rust1", since = "1.0.0")]
#![feature(no_std)]
#![no_std]
+#![allow(trivial_casts)]
+#![allow(trivial_numeric_casts)]
#![deny(missing_docs)]
#[cfg(test)] extern crate test;
use io;
use libc::{self, socklen_t, sa_family_t};
use mem;
-use net::{lookup_host, ntoh, hton, Ipv4Addr, Ipv6Addr};
+use net::{lookup_host, ntoh, hton, IpAddr, Ipv4Addr, Ipv6Addr};
use option;
use sys_common::{FromInner, AsInner, IntoInner};
use vec;
pub struct SocketAddrV6 { inner: libc::sockaddr_in6 }
impl SocketAddr {
+ /// Gets the IP address associated with this socket address.
+ #[unstable(feature = "ip_addr", reason = "recent addition")]
+ pub fn ip(&self) -> IpAddr {
+ match *self {
+ SocketAddr::V4(ref a) => IpAddr::V4(*a.ip()),
+ SocketAddr::V6(ref a) => IpAddr::V6(*a.ip()),
+ }
+ }
+
/// Gets the port number associated with this socket address
#[stable(feature = "rust1", since = "1.0.0")]
pub fn port(&self) -> u16 {
}
}
+#[stable(feature = "rust1", since = "1.0.0")]
+impl ToSocketAddrs for (IpAddr, u16) {
+ type Iter = option::IntoIter<SocketAddr>;
+ fn to_socket_addrs(&self) -> io::Result<option::IntoIter<SocketAddr>> {
+ let (ip, port) = *self;
+ match ip {
+ IpAddr::V4(ref a) => (*a, port).to_socket_addrs(),
+ IpAddr::V6(ref a) => (*a, port).to_socket_addrs(),
+ }
+ }
+}
+
#[stable(feature = "rust1", since = "1.0.0")]
impl ToSocketAddrs for (Ipv4Addr, u16) {
type Iter = option::IntoIter<SocketAddr>;
use sys_common::{AsInner, FromInner};
use net::{hton, ntoh};
+/// An IP address, either a IPv4 or IPv6 address.
+#[unstable(feature = "ip_addr", reason = "recent addition")]
+#[derive(Copy, Clone, Eq, PartialEq, Debug, Hash, PartialOrd, Ord)]
+pub enum IpAddr {
+ /// Representation of an IPv4 address.
+ V4(Ipv4Addr),
+ /// Representation of an IPv6 address.
+ V6(Ipv6Addr),
+}
+
/// Representation of an IPv4 address.
#[derive(Copy)]
#[stable(feature = "rust1", since = "1.0.0")]
}
+#[stable(feature = "rust1", since = "1.0.0")]
+impl fmt::Display for IpAddr {
+ fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
+ match *self {
+ IpAddr::V4(ref a) => a.fmt(fmt),
+ IpAddr::V6(ref a) => a.fmt(fmt),
+ }
+ }
+}
+
#[stable(feature = "rust1", since = "1.0.0")]
impl fmt::Display for Ipv4Addr {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
use num::Int;
use sys_common::net2 as net_imp;
-pub use self::ip::{Ipv4Addr, Ipv6Addr, Ipv6MulticastScope};
+pub use self::ip::{IpAddr, Ipv4Addr, Ipv6Addr, Ipv6MulticastScope};
pub use self::addr::{SocketAddr, SocketAddrV4, SocketAddrV6, ToSocketAddrs};
pub use self::tcp::{TcpStream, TcpListener};
pub use self::udp::UdpSocket;
}
/// An iterator over `SocketAddr` values returned from a host lookup operation.
-#[stable(feature = "rust1", since = "1.0.0")]
+#[unstable(feature = "lookup_host", reason = "unsure about the returned \
+ iterator and returning socket \
+ addresses")]
pub struct LookupHost(net_imp::LookupHost);
-#[stable(feature = "rust1", since = "1.0.0")]
+#[unstable(feature = "lookup_host", reason = "unsure about the returned \
+ iterator and returning socket \
+ addresses")]
impl Iterator for LookupHost {
type Item = io::Result<SocketAddr>;
fn next(&mut self) -> Option<io::Result<SocketAddr>> { self.0.next() }
/// # Examples
///
/// ```no_run
-/// # #![feature(net)]
+/// # #![feature(lookup_host)]
/// use std::net;
///
/// # fn foo() -> std::io::Result<()> {
/// # Ok(())
/// # }
/// ```
-#[stable(feature = "rust1", since = "1.0.0")]
+#[unstable(feature = "lookup_host", reason = "unsure about the returned \
+ iterator and returning socket \
+ addresses")]
pub fn lookup_host(host: &str) -> io::Result<LookupHost> {
net_imp::lookup_host(host).map(LookupHost)
}
use prelude::v1::*;
use io::{self, Error, ErrorKind};
-use net::{ToSocketAddrs, SocketAddr};
+use net::{ToSocketAddrs, SocketAddr, IpAddr};
use sys_common::net2 as net_imp;
use sys_common::AsInner;
}
/// Joins a multicast IP address (becomes a member of it)
- pub fn join_multicast(&self, multi: &SocketAddr) -> io::Result<()> {
+ pub fn join_multicast(&self, multi: &IpAddr) -> io::Result<()> {
self.0.join_multicast(multi)
}
/// Leaves a multicast IP address (drops membership from it)
- pub fn leave_multicast(&self, multi: &SocketAddr) -> io::Result<()> {
+ pub fn leave_multicast(&self, multi: &IpAddr) -> io::Result<()> {
self.0.leave_multicast(multi)
}
/// writer.write_str("hello, world").unwrap();
/// writer.flush().unwrap();
/// ```
-pub struct BufferedWriter<W> {
+pub struct BufferedWriter<W: Writer> {
inner: Option<W>,
buf: Vec<u8>,
pos: uint
}
#[stable(feature = "rust1", since = "1.0.0")]
-impl<W> fmt::Debug for BufferedWriter<W> where W: fmt::Debug {
+impl<W: Writer> fmt::Debug for BufferedWriter<W> where W: fmt::Debug {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
write!(fmt, "BufferedWriter {{ writer: {:?}, buffer: {}/{} }}",
self.inner.as_ref().unwrap(), self.pos, self.buf.len())
/// `'\n'`) is detected.
///
/// This writer will be flushed when it is dropped.
-pub struct LineBufferedWriter<W> {
+pub struct LineBufferedWriter<W: Writer> {
inner: BufferedWriter<W>,
}
#[stable(feature = "rust1", since = "1.0.0")]
-impl<W> fmt::Debug for LineBufferedWriter<W> where W: fmt::Debug {
+impl<W: Writer> fmt::Debug for LineBufferedWriter<W> where W: fmt::Debug {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
write!(fmt, "LineBufferedWriter {{ writer: {:?}, buffer: {}/{} }}",
self.inner.inner, self.inner.pos, self.inner.buf.len())
fn flush(&mut self) -> IoResult<()> { self.inner.flush() }
}
-struct InternalBufferedWriter<W>(BufferedWriter<W>);
+struct InternalBufferedWriter<W: Writer>(BufferedWriter<W>);
-impl<W> InternalBufferedWriter<W> {
+impl<W: Writer> InternalBufferedWriter<W> {
fn get_mut<'a>(&'a mut self) -> &'a mut BufferedWriter<W> {
let InternalBufferedWriter(ref mut w) = *self;
return w;
}
}
-impl<W: Reader> Reader for InternalBufferedWriter<W> {
+impl<W: Reader + Writer> Reader for InternalBufferedWriter<W> {
fn read(&mut self, buf: &mut [u8]) -> IoResult<uint> {
self.get_mut().inner.as_mut().unwrap().read(buf)
}
/// Err(e) => println!("error reading: {}", e)
/// }
/// ```
-pub struct BufferedStream<S> {
+pub struct BufferedStream<S: Writer> {
inner: BufferedReader<InternalBufferedWriter<S>>
}
#[stable(feature = "rust1", since = "1.0.0")]
-impl<S> fmt::Debug for BufferedStream<S> where S: fmt::Debug {
+impl<S: Writer> fmt::Debug for BufferedStream<S> where S: fmt::Debug {
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
let reader = &self.inner;
let writer = &self.inner.inner.0;
STDIN = boxed::into_raw(box stdin);
// Make sure to free it at exit
- rt::at_exit(|| {
+ let _ = rt::at_exit(|| {
Box::from_raw(STDIN);
STDIN = ptr::null_mut();
});
// })
// })
fn with_task_stdout<F>(f: F) where F: FnOnce(&mut Writer) -> IoResult<()> {
- let mut my_stdout = LOCAL_STDOUT.with(|slot| {
+ let mut my_stdout: Box<Writer + Send> = LOCAL_STDOUT.with(|slot| {
slot.borrow_mut().take()
}).unwrap_or_else(|| {
- box stdout() as Box<Writer + Send>
+ box stdout()
});
let result = f(&mut *my_stdout);
let mut var = Some(my_stdout);
cmd
}
+ #[cfg(not(target_arch = "aarch64"))]
#[test]
fn test_keep_current_working_dir() {
use os;
//!
//! Documentation can be found on the `rt::at_exit` function.
+// FIXME: switch this to use atexit. Currently this
+// segfaults (the queue's memory is mysteriously gone), so
+// instead the cleanup is tied to the `std::rt` entry point.
+
use boxed;
use boxed::Box;
use vec::Vec;
static LOCK: Mutex = MUTEX_INIT;
static mut QUEUE: *mut Queue = 0 as *mut Queue;
-unsafe fn init() {
+// The maximum number of times the cleanup routines will be run. While running
+// the at_exit closures new ones may be registered, and this count is the number
+// of times the new closures will be allowed to register successfully. After
+// this number of iterations all new registrations will return `false`.
+const ITERS: usize = 10;
+
+unsafe fn init() -> bool {
if QUEUE.is_null() {
let state: Box<Queue> = box Vec::new();
QUEUE = boxed::into_raw(state);
- } else {
+ } else if QUEUE as usize == 1 {
// can't re-init after a cleanup
- rtassert!(QUEUE as uint != 1);
+ return false
}
- // FIXME: switch this to use atexit as below. Currently this
- // segfaults (the queue's memory is mysteriously gone), so
- // instead the cleanup is tied to the `std::rt` entry point.
- //
- // ::libc::atexit(cleanup);
+ return true
}
pub fn cleanup() {
- unsafe {
- LOCK.lock();
- let queue = QUEUE;
- QUEUE = 1 as *mut _;
- LOCK.unlock();
+ for i in 0..ITERS {
+ unsafe {
+ LOCK.lock();
+ let queue = QUEUE;
+ QUEUE = if i == ITERS - 1 {1} else {0} as *mut _;
+ LOCK.unlock();
- // make sure we're not recursively cleaning up
- rtassert!(queue as uint != 1);
+ // make sure we're not recursively cleaning up
+ rtassert!(queue as usize != 1);
- // If we never called init, not need to cleanup!
- if queue as uint != 0 {
- let queue: Box<Queue> = Box::from_raw(queue);
- for to_run in *queue {
- to_run.invoke(());
+ // If we never called init, not need to cleanup!
+ if queue as usize != 0 {
+ let queue: Box<Queue> = Box::from_raw(queue);
+ for to_run in *queue {
+ to_run.invoke(());
+ }
}
}
}
}
-pub fn push(f: Thunk<'static>) {
+pub fn push(f: Thunk<'static>) -> bool {
+ let mut ret = true;
unsafe {
LOCK.lock();
- init();
- (*QUEUE).push(f);
+ if init() {
+ (*QUEUE).push(f);
+ } else {
+ ret = false;
+ }
LOCK.unlock();
}
+ return ret
}
//! time being.
#![unstable(feature = "std_misc")]
-
-// FIXME: this should not be here.
#![allow(missing_docs)]
-#![allow(dead_code)]
-
-use marker::Send;
-use ops::FnOnce;
+use prelude::v1::*;
use sys;
use thunk::Thunk;
use usize;
use thread::Thread;
let something_around_the_top_of_the_stack = 1;
- let addr = &something_around_the_top_of_the_stack as *const int;
+ let addr = &something_around_the_top_of_the_stack as *const _ as *const int;
let my_stack_top = addr as uint;
// FIXME #11359 we just assume that this thread has a stack of a
/// Enqueues a procedure to run when the main thread exits.
///
-/// It is forbidden for procedures to register more `at_exit` handlers when they
-/// are running, and doing so will lead to a process abort.
+/// Currently these closures are only run once the main *Rust* thread exits.
+/// Once the `at_exit` handlers begin running, more may be enqueued, but not
+/// infinitely so. Eventually a handler registration will be forced to fail.
///
-/// Note that other threads may still be running when `at_exit` routines start
-/// running.
-pub fn at_exit<F: FnOnce() + Send + 'static>(f: F) {
- at_exit_imp::push(Thunk::new(f));
+/// Returns `Ok` if the handler was successfully registered, meaning that the
+/// closure will be run once the main thread exits. Returns `Err` to indicate
+/// that the closure could not be registered, meaning that it is not scheduled
+/// to be rune.
+pub fn at_exit<F: FnOnce() + Send + 'static>(f: F) -> Result<(), ()> {
+ if at_exit_imp::push(Thunk::new(f)) {Ok(())} else {Err(())}
}
/// One-time runtime cleanup.
/// The receiving-half of Rust's channel type. This half can only be owned by
/// one task
#[stable(feature = "rust1", since = "1.0.0")]
-pub struct Receiver<T> {
+pub struct Receiver<T:Send> {
inner: UnsafeCell<Flavor<T>>,
}
/// whenever `next` is called, waiting for a new message, and `None` will be
/// returned when the corresponding channel has hung up.
#[stable(feature = "rust1", since = "1.0.0")]
-pub struct Iter<'a, T:'a> {
+pub struct Iter<'a, T:Send+'a> {
rx: &'a Receiver<T>
}
/// The sending-half of Rust's asynchronous channel type. This half can only be
/// owned by one task, but it can be cloned to send to other tasks.
#[stable(feature = "rust1", since = "1.0.0")]
-pub struct Sender<T> {
+pub struct Sender<T:Send> {
inner: UnsafeCell<Flavor<T>>,
}
/// The sending-half of Rust's synchronous channel type. This half can only be
/// owned by one task, but it can be cloned to send to other tasks.
#[stable(feature = "rust1", since = "1.0.0")]
-pub struct SyncSender<T> {
+pub struct SyncSender<T: Send> {
inner: Arc<UnsafeCell<sync::Packet<T>>>,
}
Disconnected(T),
}
-enum Flavor<T> {
+enum Flavor<T:Send> {
Oneshot(Arc<UnsafeCell<oneshot::Packet<T>>>),
Stream(Arc<UnsafeCell<stream::Packet<T>>>),
Shared(Arc<UnsafeCell<shared::Packet<T>>>),
}
#[doc(hidden)]
-trait UnsafeFlavor<T> {
+trait UnsafeFlavor<T:Send> {
fn inner_unsafe<'a>(&'a self) -> &'a UnsafeCell<Flavor<T>>;
unsafe fn inner_mut<'a>(&'a self) -> &'a mut Flavor<T> {
&mut *self.inner_unsafe().get()
&*self.inner_unsafe().get()
}
}
-impl<T> UnsafeFlavor<T> for Sender<T> {
+impl<T:Send> UnsafeFlavor<T> for Sender<T> {
fn inner_unsafe<'a>(&'a self) -> &'a UnsafeCell<Flavor<T>> {
&self.inner
}
}
-impl<T> UnsafeFlavor<T> for Receiver<T> {
+impl<T:Send> UnsafeFlavor<T> for Receiver<T> {
fn inner_unsafe<'a>(&'a self) -> &'a UnsafeCell<Flavor<T>> {
&self.inner
}
/// The multi-producer single-consumer structure. This is not cloneable, but it
/// may be safely shared so long as it is guaranteed that there is only one
/// popper at a time (many pushers are allowed).
-pub struct Queue<T> {
+pub struct Queue<T: Send> {
head: AtomicPtr<Node<T>>,
tail: UnsafeCell<*mut Node<T>>,
}
// moves *from* a pointer, ownership of the token is transferred to
// whoever changed the state.
-pub struct Packet<T> {
+pub struct Packet<T:Send> {
// Internal state of the chan/port pair (stores the blocked task as well)
state: AtomicUsize,
// One-shot data slot location
upgrade: MyUpgrade<T>,
}
-pub enum Failure<T> {
+pub enum Failure<T:Send> {
Empty,
Disconnected,
Upgraded(Receiver<T>),
UpWoke(SignalToken),
}
-pub enum SelectionResult<T> {
+pub enum SelectionResult<T:Send> {
SelCanceled,
SelUpgraded(SignalToken, Receiver<T>),
SelSuccess,
}
-enum MyUpgrade<T> {
+enum MyUpgrade<T:Send> {
NothingSent,
SendUsed,
GoUp(Receiver<T>),
/// A handle to a receiver which is currently a member of a `Select` set of
/// receivers. This handle is used to keep the receiver in the set as well as
/// interact with the underlying receiver.
-pub struct Handle<'rx, T:'rx> {
+pub struct Handle<'rx, T:Send+'rx> {
/// The ID of this handle, used to compare against the return value of
/// `Select::wait()`
id: usize,
#[cfg(not(test))]
const MAX_STEALS: isize = 1 << 20;
-pub struct Packet<T> {
+pub struct Packet<T: Send> {
queue: mpsc::Queue<T>,
cnt: AtomicIsize, // How many items are on this channel
steals: isize, // How many times has a port received without blocking?
/// but it can be safely shared in an Arc if it is guaranteed that there
/// is only one popper and one pusher touching the queue at any one point in
/// time.
-pub struct Queue<T> {
+pub struct Queue<T: Send> {
// consumer fields
tail: UnsafeCell<*mut Node<T>>, // where to pop from
tail_prev: AtomicPtr<Node<T>>, // where to pop from
#[cfg(not(test))]
const MAX_STEALS: isize = 1 << 20;
-pub struct Packet<T> {
+pub struct Packet<T:Send> {
queue: spsc::Queue<Message<T>>, // internal queue for all message
cnt: AtomicIsize, // How many items are on this channel
port_dropped: AtomicBool, // flag if the channel has been destroyed.
}
-pub enum Failure<T> {
+pub enum Failure<T:Send> {
Empty,
Disconnected,
Upgraded(Receiver<T>),
UpWoke(SignalToken),
}
-pub enum SelectionResult<T> {
+pub enum SelectionResult<T:Send> {
SelSuccess,
SelCanceled,
SelUpgraded(SignalToken, Receiver<T>),
// Any message could contain an "upgrade request" to a new shared port, so the
// internal queue it's a queue of T, but rather Message<T>
-enum Message<T> {
+enum Message<T:Send> {
Data(T),
GoUp(Receiver<T>),
}
use sync::mpsc::select::StartResult::{self, Installed, Abort};
use sync::{Mutex, MutexGuard};
-pub struct Packet<T> {
+pub struct Packet<T: Send> {
/// Only field outside of the mutex. Just done for kicks, but mainly because
/// the other shared channel already had the code implemented
channels: AtomicUsize,
/// *guard += 1;
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
-pub struct Mutex<T> {
+pub struct Mutex<T: Send> {
// Note that this static mutex is in a *box*, not inlined into the struct
// itself. Once a native mutex has been used once, its address can never
// change (it can't be moved). This mutex type can be safely moved at any
use sync::{Arc, Mutex, StaticMutex, MUTEX_INIT, Condvar};
use thread;
- struct Packet<T>(Arc<(Mutex<T>, Condvar)>);
+ struct Packet<T: Send>(Arc<(Mutex<T>, Condvar)>);
unsafe impl<T: Send> Send for Packet<T> {}
unsafe impl<T> Sync for Packet<T> {}
///
/// The fields of this helper are all public, but they should not be used, this
/// is for static initialization.
-pub struct Helper<M> {
+pub struct Helper<M:Send> {
/// Internal lock which protects the remaining fields
pub lock: StaticMutex,
pub cond: StaticCondvar,
self.cond.notify_one()
});
- rt::at_exit(move || { self.shutdown() });
+ let _ = rt::at_exit(move || { self.shutdown() });
*self.initialized.get() = true;
} else if *self.chan.get() as uint == 1 {
panic!("cannot continue usage after shutdown");
use io::{self, Error, ErrorKind};
use libc::{self, c_int, c_char, c_void, socklen_t};
use mem;
-use net::{SocketAddr, Shutdown};
+use net::{SocketAddr, Shutdown, IpAddr};
use sys::c;
use sys::net::{cvt, cvt_r, cvt_gai, Socket, init, wrlen_t};
use sys_common::{AsInner, FromInner, IntoInner};
libc::IP_MULTICAST_LOOP, on as c_int)
}
- pub fn join_multicast(&self, multi: &SocketAddr) -> io::Result<()> {
+ pub fn join_multicast(&self, multi: &IpAddr) -> io::Result<()> {
match *multi {
- SocketAddr::V4(..) => {
+ IpAddr::V4(..) => {
self.set_membership(multi, libc::IP_ADD_MEMBERSHIP)
}
- SocketAddr::V6(..) => {
+ IpAddr::V6(..) => {
self.set_membership(multi, libc::IPV6_ADD_MEMBERSHIP)
}
}
}
- pub fn leave_multicast(&self, multi: &SocketAddr) -> io::Result<()> {
+ pub fn leave_multicast(&self, multi: &IpAddr) -> io::Result<()> {
match *multi {
- SocketAddr::V4(..) => {
+ IpAddr::V4(..) => {
self.set_membership(multi, libc::IP_DROP_MEMBERSHIP)
}
- SocketAddr::V6(..) => {
+ IpAddr::V6(..) => {
self.set_membership(multi, libc::IPV6_DROP_MEMBERSHIP)
}
}
}
- fn set_membership(&self, addr: &SocketAddr, opt: c_int) -> io::Result<()> {
+ fn set_membership(&self, addr: &IpAddr, opt: c_int) -> io::Result<()> {
match *addr {
- SocketAddr::V4(ref addr) => {
+ IpAddr::V4(ref addr) => {
let mreq = libc::ip_mreq {
- imr_multiaddr: *addr.ip().as_inner(),
+ imr_multiaddr: *addr.as_inner(),
// interface == INADDR_ANY
imr_interface: libc::in_addr { s_addr: 0x0 },
};
setsockopt(&self.inner, libc::IPPROTO_IP, opt, mreq)
}
- SocketAddr::V6(ref addr) => {
+ IpAddr::V6(ref addr) => {
let mreq = libc::ip6_mreq {
- ipv6mr_multiaddr: *addr.ip().as_inner(),
+ ipv6mr_multiaddr: *addr.as_inner(),
ipv6mr_interface: 0,
};
setsockopt(&self.inner, libc::IPPROTO_IPV6, opt, mreq)
if err != 0 { return Err(io::Error::last_os_error()); }
if sz == 0 { return Err(io::Error::last_os_error()); }
v.set_len(sz as uint - 1); // chop off trailing NUL
- Ok(PathBuf::new::<OsString>(OsStringExt::from_vec(v)))
+ Ok(PathBuf::from(OsString::from_vec(v)))
}
}
Err(io::Error::last_os_error())
} else {
let vec = CStr::from_ptr(v).to_bytes().to_vec();
- Ok(PathBuf::new::<OsString>(OsStringExt::from_vec(vec)))
+ Ok(PathBuf::from(OsString::from_vec(vec)))
}
}
}
let utf_c_str: *const libc::c_char =
mem::transmute(objc_msgSend(tmp, utf8_sel));
let bytes = CStr::from_ptr(utf_c_str).to_bytes();
- res.push(OsString::from_str(str::from_utf8(bytes).unwrap()))
+ res.push(OsString::from(str::from_utf8(bytes).unwrap()))
}
}
&mut data);
assert_eq!(ret, 0);
- rt::at_exit(|| { c::WSACleanup(); })
+ let _ = rt::at_exit(|| { c::WSACleanup(); });
});
}
if *self.cur == 0 { return None }
let p = &*self.cur;
let mut len = 0;
- while *(p as *const _).offset(len) != 0 {
+ while *(p as *const u16).offset(len) != 0 {
len += 1;
}
let p = p as *const u16;
if !DTORS.is_null() { return }
let dtors = box Vec::<(Key, Dtor)>::new();
- DTORS = boxed::into_raw(dtors);
- rt::at_exit(move|| {
+ let res = rt::at_exit(move|| {
DTOR_LOCK.lock();
let dtors = DTORS;
DTORS = 1 as *mut _;
assert!(DTORS as uint == 1); // can't re-init after destructing
DTOR_LOCK.unlock();
});
+ if res.is_ok() {
+ DTORS = boxed::into_raw(dtors);
+ } else {
+ DTORS = 1 as *mut _;
+ }
}
unsafe fn register_dtor(key: Key, dtor: Dtor) {
}
};
+ #[allow(trivial_casts)]
#[cfg(any(not(any(target_os = "macos", target_os = "linux")), target_arch = "aarch64"))]
const _INIT: ::std::thread::__local::__impl::KeyInner<$t> = {
::std::thread::__local::__impl::KeyInner {
/// permission.
#[must_use = "thread will be immediately joined if `JoinGuard` is not used"]
#[stable(feature = "rust1", since = "1.0.0")]
-pub struct JoinGuard<'a, T: 'a> {
+pub struct JoinGuard<'a, T: Send + 'a> {
inner: JoinInner<T>,
_marker: PhantomData<&'a T>,
}
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)>),
+ /// e.g. `extern crate foo` or `extern crate foo_bar as foo`
+ ItemExternCrate(Option<Name>),
/// A `use` or `pub use` item
ItemUse(P<ViewPath>),
impl ExpnId {
pub fn from_llvm_cookie(cookie: c_uint) -> ExpnId {
- ExpnId(cookie as u32)
+ ExpnId(cookie)
}
pub fn to_llvm_cookie(self) -> i32 {
match bytes_per_diff {
1 => for diff in diff_iter { try! { (diff.0 as u8).encode(s) } },
2 => for diff in diff_iter { try! { (diff.0 as u16).encode(s) } },
- 4 => for diff in diff_iter { try! { (diff.0 as u32).encode(s) } },
+ 4 => for diff in diff_iter { try! { diff.0.encode(s) } },
_ => unreachable!()
}
}
let lo = self.lookup_char_pos(sp.lo);
let hi = self.lookup_char_pos(sp.hi);
let mut lines = Vec::new();
- for i in lo.line - 1..hi.line as usize {
+ for i in lo.line - 1..hi.line {
lines.push(i);
};
FileLines {file: lo.file, lines: lines}
box MacEager {
$fld: Some(v),
..Default::default()
- } as Box<MacResult>
+ }
}
)*
}
/// Use this as a return value after hitting any errors and
/// calling `span_err`.
pub fn any(sp: Span) -> Box<MacResult+'static> {
- box DummyResult { expr_only: false, span: sp } as Box<MacResult+'static>
+ box DummyResult { expr_only: false, span: sp }
}
/// Create a default MacResult that can only be an expression.
/// if an error is encountered internally, the user will receive
/// an error that they also used it in the wrong place.
pub fn expr(sp: Span) -> Box<MacResult+'static> {
- box DummyResult { expr_only: true, span: sp } as Box<MacResult+'static>
+ box DummyResult { expr_only: true, span: sp }
}
/// A plain dummy expression.
RefCell::new(f)
}
+/// This method helps to extract all the type parameters referenced from a
+/// type. For a type parameter `<T>`, it looks for either a `TyPath` that
+/// is not global and starts with `T`, or a `TyQPath`.
+fn find_type_parameters(ty: &ast::Ty, ty_param_names: &[ast::Name]) -> Vec<P<ast::Ty>> {
+ use visit;
+
+ struct Visitor<'a> {
+ ty_param_names: &'a [ast::Name],
+ types: Vec<P<ast::Ty>>,
+ }
+
+ impl<'a> visit::Visitor<'a> for Visitor<'a> {
+ fn visit_ty(&mut self, ty: &'a ast::Ty) {
+ match ty.node {
+ ast::TyPath(_, ref path) if !path.global => {
+ match path.segments.first() {
+ Some(segment) => {
+ if self.ty_param_names.contains(&segment.identifier.name) {
+ self.types.push(P(ty.clone()));
+ }
+ }
+ None => {}
+ }
+ }
+ _ => {}
+ }
+
+ visit::walk_ty(self, ty)
+ }
+ }
+
+ let mut visitor = Visitor {
+ ty_param_names: ty_param_names,
+ types: Vec::new(),
+ };
+
+ visit::Visitor::visit_ty(&mut visitor, ty);
+
+ visitor.types
+}
impl<'a> TraitDef<'a> {
pub fn expand<F>(&self,
}))
}
- /// Given that we are deriving a trait `Tr` for a type `T<'a, ...,
- /// 'z, A, ..., Z>`, creates an impl like:
+ /// Given that we are deriving a trait `DerivedTrait` for a type like:
///
/// ```ignore
- /// impl<'a, ..., 'z, A:Tr B1 B2, ..., Z: Tr B1 B2> Tr for T<A, ..., Z> { ... }
+ /// struct Struct<'a, ..., 'z, A, B: DeclaredTrait, C, ..., Z> where C: WhereTrait {
+ /// a: A,
+ /// b: B::Item,
+ /// b1: <B as DeclaredTrait>::Item,
+ /// c1: <C as WhereTrait>::Item,
+ /// c2: Option<<C as WhereTrait>::Item>,
+ /// ...
+ /// }
+ /// ```
+ ///
+ /// create an impl like:
+ ///
+ /// ```ignore
+ /// impl<'a, ..., 'z, A, B: DeclaredTrait, C, ... Z> where
+ /// C: WhereTrait,
+ /// A: DerivedTrait + B1 + ... + BN,
+ /// B: DerivedTrait + B1 + ... + BN,
+ /// C: DerivedTrait + B1 + ... + BN,
+ /// B::Item: DerivedTrait + B1 + ... + BN,
+ /// <C as WhereTrait>::Item: DerivedTrait + B1 + ... + BN,
+ /// ...
+ /// {
+ /// ...
+ /// }
/// ```
///
- /// where B1, B2, ... are the bounds given by `bounds_paths`.'
+ /// where B1, ..., BN are the bounds given by `bounds_paths`.'. Z is a phantom type, and
+ /// therefore does not get bound by the derived trait.
fn create_derived_impl(&self,
cx: &mut ExtCtxt,
type_ident: Ident,
generics: &Generics,
+ field_tys: Vec<P<ast::Ty>>,
methods: Vec<P<ast::ImplItem>>) -> P<ast::Item> {
let trait_path = self.path.to_path(cx, self.span, type_ident, generics);
}
}));
+ if !ty_params.is_empty() {
+ let ty_param_names: Vec<ast::Name> = ty_params.iter()
+ .map(|ty_param| ty_param.ident.name)
+ .collect();
+
+ for field_ty in field_tys.into_iter() {
+ let tys = find_type_parameters(&*field_ty, &ty_param_names);
+
+ for ty in tys.into_iter() {
+ let mut bounds: Vec<_> = self.additional_bounds.iter().map(|p| {
+ cx.typarambound(p.to_path(cx, self.span, type_ident, generics))
+ }).collect();
+
+ // require the current trait
+ bounds.push(cx.typarambound(trait_path.clone()));
+
+ let predicate = ast::WhereBoundPredicate {
+ span: self.span,
+ bound_lifetimes: vec![],
+ bounded_ty: ty,
+ bounds: OwnedSlice::from_vec(bounds),
+ };
+
+ let predicate = ast::WherePredicate::BoundPredicate(predicate);
+ where_clause.predicates.push(predicate);
+ }
+ }
+ }
+
let trait_generics = Generics {
lifetimes: lifetimes,
ty_params: OwnedSlice::from_vec(ty_params),
struct_def: &StructDef,
type_ident: Ident,
generics: &Generics) -> P<ast::Item> {
+ let field_tys: Vec<P<ast::Ty>> = struct_def.fields.iter()
+ .map(|field| field.node.ty.clone())
+ .collect();
+
let methods = self.methods.iter().map(|method_def| {
let (explicit_self, self_args, nonself_args, tys) =
method_def.split_self_nonself_args(
body)
}).collect();
- self.create_derived_impl(cx, type_ident, generics, methods)
+ self.create_derived_impl(cx, type_ident, generics, field_tys, methods)
}
fn expand_enum_def(&self,
enum_def: &EnumDef,
type_ident: Ident,
generics: &Generics) -> P<ast::Item> {
+ let mut field_tys = Vec::new();
+
+ for variant in enum_def.variants.iter() {
+ match variant.node.kind {
+ ast::VariantKind::TupleVariantKind(ref args) => {
+ field_tys.extend(args.iter()
+ .map(|arg| arg.ty.clone()));
+ }
+ ast::VariantKind::StructVariantKind(ref args) => {
+ field_tys.extend(args.fields.iter()
+ .map(|field| field.node.ty.clone()));
+ }
+ }
+ }
+
let methods = self.methods.iter().map(|method_def| {
let (explicit_self, self_args, nonself_args, tys) =
method_def.split_self_nonself_args(cx, self,
body)
}).collect();
- self.create_derived_impl(cx, type_ident, generics, methods)
+ self.create_derived_impl(cx, type_ident, generics, field_tys, methods)
}
}
(unsigned, $t:ty, $tag:expr) => (
impl ToSource for $t {
fn to_source(&self) -> String {
+ #![allow(trivial_numeric_casts)]
let lit = ast::LitInt(*self as u64, ast::UnsignedIntLit($tag));
pprust::lit_to_string(&dummy_spanned(lit))
}
// Weird, but useful for X-macros.
return box ParserAnyMacro {
parser: RefCell::new(p),
- } as Box<MacResult+'cx>
+ }
}
Failure(sp, ref msg) => if sp.lo >= best_fail_spot.lo {
best_fail_spot = sp;
self.err_span_char(self.last_pos, self.pos,
"illegal character in numeric character escape", c);
0
- }) as u32;
+ });
self.bump();
}
self.fatal_span_char(self.last_pos, self.pos,
"illegal character in unicode escape", c);
}
- }) as u32;
+ });
self.bump();
count += 1;
}
let vitem_s = item_to_string(&*vitem);
assert_eq!(&vitem_s[..], ex_s);
- let ex_s = "extern crate \"foo\" as bar;";
+ let ex_s = "extern crate foo as bar;";
let vitem = string_to_item(ex_s.to_string()).unwrap();
let vitem_s = item_to_string(&*vitem);
assert_eq!(&vitem_s[..], ex_s);
pub enum ObsoleteSyntax {
ClosureKind,
EmptyIndex,
+ ExternCrateString,
}
pub trait ParserObsoleteMethods {
"write `[..]` instead",
false, // warning for now
),
+ ObsoleteSyntax::ExternCrateString => (
+ "\"crate-name\"",
+ "use an identifier not in quotes instead",
+ false, // warning for now
+ ),
};
self.report(sp, kind, kind_str, desc, error);
} else {
// Avoid token copies with `replace`.
let buffer_start = self.buffer_start as usize;
- let next_index = (buffer_start + 1) & 3 as usize;
+ let next_index = (buffer_start + 1) & 3;
self.buffer_start = next_index as isize;
let placeholder = TokenAndSpan {
attrs: Vec<Attribute>)
-> P<Item> {
- let span = self.span;
let (maybe_path, ident) = match self.token {
token::Ident(..) => {
- let the_ident = self.parse_ident();
- let path = if self.eat_keyword_noexpect(keywords::As) {
- // skip the ident if there is one
- if self.token.is_ident() { self.bump(); }
-
- self.span_err(span, "expected `;`, found `as`");
- self.fileline_help(span,
- &format!("perhaps you meant to enclose the crate name `{}` in \
- a string?",
- the_ident.as_str()));
- None
+ let crate_name = self.parse_ident();
+ if self.eat_keyword(keywords::As) {
+ (Some(crate_name.name), self.parse_ident())
} else {
- None
- };
- self.expect(&token::Semi);
- (path, the_ident)
+ (None, crate_name)
+ }
},
- token::Literal(token::Str_(..), suf) | token::Literal(token::StrRaw(..), suf) => {
+ token::Literal(token::Str_(..), suf) |
+ token::Literal(token::StrRaw(..), suf) => {
let sp = self.span;
self.expect_no_suffix(sp, "extern crate name", suf);
// forgo the internal suffix check of `parse_str` to
// avoid repeats (this unwrap will always succeed due
// to the restriction of the `match`)
- let (s, style, _) = self.parse_optional_str().unwrap();
+ let (s, _, _) = self.parse_optional_str().unwrap();
self.expect_keyword(keywords::As);
let the_ident = self.parse_ident();
- self.expect(&token::Semi);
- (Some((s, style)), the_ident)
+ self.obsolete(sp, ObsoleteSyntax::ExternCrateString);
+ let s = token::intern(&s);
+ (Some(s), the_ident)
},
_ => {
let span = self.span;
token_str));
}
};
+ self.expect(&token::Semi);
let last_span = self.last_span;
self.mk_item(lo,
ast::ItemExternCrate(ref optional_path) => {
try!(self.head(&visibility_qualified(item.vis,
"extern crate")));
- if let Some((ref p, style)) = *optional_path {
- try!(self.print_string(p, style));
+ if let Some(p) = *optional_path {
+ let val = token::get_name(p);
+ if val.contains("-") {
+ try!(self.print_string(&val, ast::CookedStr));
+ } else {
+ try!(self.print_name(p));
+ }
try!(space(&mut self.s));
try!(word(&mut self.s, "as"));
try!(space(&mut self.s));
ast::LitBinary(ref v) => {
let mut escaped: String = String::new();
for &ch in &**v {
- escaped.extend(ascii::escape_default(ch as u8)
+ escaped.extend(ascii::escape_default(ch)
.map(|c| c as char));
}
word(&mut self.s, &format!("b\"{}\"", escaped))
// The name to use in `extern crate "name" as std;`
let actual_crate_name = match self.alt_std_name {
- Some(ref s) => token::intern_and_get_ident(&s[..]),
- None => token::intern_and_get_ident("std"),
+ Some(ref s) => token::intern(&s),
+ None => token::intern("std"),
};
krate.module.items.insert(0, P(ast::Item {
attrs: vec!(
attr::mk_attr_outer(attr::mk_attr_id(), attr::mk_word_item(
InternedString::new("macro_use")))),
- node: ast::ItemExternCrate(Some((actual_crate_name, ast::CookedStr))),
+ node: ast::ItemExternCrate(Some(actual_crate_name)),
vis: ast::Inherited,
span: DUMMY_SP
}));
/// opened.
pub fn stdout() -> Option<Box<Terminal<WriterWrapper> + Send>> {
TerminfoTerminal::new(WriterWrapper {
- wrapped: box std::io::stdout() as Box<Write + Send>,
+ wrapped: box std::io::stdout(),
})
}
/// opened.
pub fn stdout() -> Option<Box<Terminal<WriterWrapper> + Send>> {
let ti = TerminfoTerminal::new(WriterWrapper {
- wrapped: box std::io::stdout() as Box<Write + Send>,
+ wrapped: box std::io::stdout(),
});
match ti {
Some(t) => Some(t),
None => {
WinConsole::new(WriterWrapper {
- wrapped: box std::io::stdout() as Box<Write + Send>,
+ wrapped: box std::io::stdout(),
})
}
}
/// opened.
pub fn stderr() -> Option<Box<Terminal<WriterWrapper> + Send>> {
TerminfoTerminal::new(WriterWrapper {
- wrapped: box std::io::stderr() as Box<Write + Send>,
+ wrapped: box std::io::stderr(),
})
}
/// opened.
pub fn stderr() -> Option<Box<Terminal<WriterWrapper> + Send>> {
let ti = TerminfoTerminal::new(WriterWrapper {
- wrapped: box std::io::stderr() as Box<Write + Send>,
+ wrapped: box std::io::stderr(),
});
match ti {
Some(t) => Some(t),
None => {
WinConsole::new(WriterWrapper {
- wrapped: box std::io::stderr() as Box<Write + Send>,
+ wrapped: box std::io::stderr(),
})
}
}
out: out,
ti: msys_terminfo(),
num_colors: 8,
- } as Box<Terminal<T>+Send>)
+ })
},
_ => {
debug!("error finding terminfo entry: {:?}", err);
return Some(box TerminfoTerminal {out: out,
ti: inf,
- num_colors: nc} as Box<Terminal<T>+Send>);
+ num_colors: nc});
}
fn dim_if_necessary(&self, color: color::Color) -> color::Color {
let magic = try!(read_le_u16(file));
if magic != 0x011A {
return Err(format!("invalid magic number: expected {:x}, found {:x}",
- 0x011A as usize, magic as usize));
+ 0x011A_usize, magic as usize));
}
let names_bytes = try!(read_le_u16(file)) as int;
}
Some(box WinConsole { buf: out,
def_foreground: fg, def_background: bg,
- foreground: fg, background: bg } as Box<Terminal<T>+Send>)
+ foreground: fg, background: bg })
}
}
let MetricMap(ref mm) = *self;
let v : Vec<String> = mm.iter()
.map(|(k,v)| format!("{}: {} (+/- {})", *k,
- v.value as f64, v.noise as f64))
+ v.value, v.noise))
.collect();
v.connect(", ")
}
/// Create a Subcommand object based on its name.
pub fn parse_name(name: &str) -> Option<Box<Subcommand>> {
- for parser in [
- help::parse_cmd as fn(&str) -> Option<Box<Subcommand>>,
- build::parse_cmd as fn(&str) -> Option<Box<Subcommand>>,
- serve::parse_cmd as fn(&str) -> Option<Box<Subcommand>>,
- test::parse_cmd as fn(&str) -> Option<Box<Subcommand>>].iter() {
+ let cmds: [fn(&str) -> Option<Box<Subcommand>>; 4] = [help::parse_cmd,
+ build::parse_cmd,
+ serve::parse_cmd,
+ test::parse_cmd];
+ for parser in cmds.iter() {
let parsed = (*parser)(name);
if parsed.is_some() { return parsed }
}
+++ /dev/null
-// Copyright 2012 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="lib"]
-
-pub trait Remote {
- fn foo(&self) { }
-}
-
-pub trait Remote1<T> {
- fn foo(&self, t: T) { }
-}
-
-pub trait Remote2<T, U> {
- fn foo(&self, t: T, u: U) { }
-}
-
-pub struct Pair<T,U>(T,U);
+++ /dev/null
-// 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.
-
-pub trait TheTrait<T> : ::std::marker::PhantomFn<T> {
- fn the_fn(&self);
-}
--- /dev/null
+// Copyright 2012 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="lib"]
+
+pub trait Remote {
+ fn foo(&self) { }
+}
+
+pub trait Remote1<T> {
+ fn foo(&self, t: T) { }
+}
+
+pub trait Remote2<T, U> {
+ fn foo(&self, t: T, u: U) { }
+}
+
+pub struct Pair<T,U>(T,U);
--- /dev/null
+// 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.
+
+pub trait TheTrait<T> : ::std::marker::PhantomFn<T> {
+ fn the_fn(&self);
+}
}
pub fn foo() {
- let a = &1 as &inner::Trait;
+ let a = &1i as &inner::Trait;
a.f();
}
+++ /dev/null
-// 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.
-
-enum Foo {
- Bar(int)
-}
-
-pub mod test {
- enum Foo {
- Bar(int)
- }
-}
+++ /dev/null
-// 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.
-
-pub mod bar {
- pub fn foo() {}
-}
+++ /dev/null
-// 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.
-
-pub fn baz() {}
+++ /dev/null
-// 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.
-
-extern {
- fn bar();
-}
+++ /dev/null
-// 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.
-
-pub use foo::FOO2;
-
-pub const FOO: uint = 3;
-const BAR: uint = 3;
-
-mod foo {
- pub const FOO2: uint = 3;
-}
+++ /dev/null
-// 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.
-
-pub mod A {
- pub struct Foo;
- impl Foo {
- fn foo(&self) { }
- }
-}
use std::marker;
-struct arc_destruct<T> {
+struct arc_destruct<T: Sync> {
_data: int,
_marker: marker::PhantomData<T>
}
--- /dev/null
+// 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.
+
+enum Foo {
+ Bar(int)
+}
+
+pub mod test {
+ enum Foo {
+ Bar(int)
+ }
+}
--- /dev/null
+// 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.
+
+pub mod bar {
+ pub fn foo() {}
+}
--- /dev/null
+// 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.
+
+pub fn baz() {}
--- /dev/null
+// 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.
+
+extern {
+ fn bar();
+}
--- /dev/null
+// 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.
+
+pub use foo::FOO2;
+
+pub const FOO: uint = 3;
+const BAR: uint = 3;
+
+mod foo {
+ pub const FOO2: uint = 3;
+}
--- /dev/null
+// 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.
+
+pub mod A {
+ pub struct Foo;
+ impl Foo {
+ fn foo(&self) { }
+ }
+}
+++ /dev/null
-// 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.
-
-pub fn foo() {}
--- /dev/null
+// 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.
+
+pub fn foo() {}
+++ /dev/null
-// 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.
-
-pub struct A(());
-pub struct B(int);
-pub struct C(pub int, int);
-pub struct D(pub int);
--- /dev/null
+// 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.
+
+pub struct A(());
+pub struct B(int);
+pub struct C(pub int, int);
+pub struct D(pub int);
+++ /dev/null
-// 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.
-
-// Check that method bounds declared on traits/impls in a cross-crate
-// scenario work. This is the library portion of the test.
-
-pub enum MaybeOwned<'a> {
- Owned(int),
- Borrowed(&'a int)
-}
-
-pub struct Inv<'a> { // invariant w/r/t 'a
- x: &'a mut &'a int
-}
-
-// I encountered a bug at some point with encoding the IntoMaybeOwned
-// trait, so I'll use that as the template for this test.
-pub trait IntoMaybeOwned<'a> {
- fn into_maybe_owned(self) -> MaybeOwned<'a>;
-
- // Note: without this `into_inv` method, the trait is
- // contravariant w/r/t `'a`, since if you look strictly at the
- // interface, it only returns `'a`. This complicates the
- // downstream test since it wants invariance to force an error.
- // Hence we add this method.
- fn into_inv(self) -> Inv<'a>;
-
- fn bigger_region<'b:'a>(self, b: Inv<'b>);
-}
-
-impl<'a> IntoMaybeOwned<'a> for Inv<'a> {
- fn into_maybe_owned(self) -> MaybeOwned<'a> { panic!() }
- fn into_inv(self) -> Inv<'a> { panic!() }
- fn bigger_region<'b:'a>(self, b: Inv<'b>) { panic!() }
-}
--- /dev/null
+// 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.
+
+// Check that method bounds declared on traits/impls in a cross-crate
+// scenario work. This is the library portion of the test.
+
+pub enum MaybeOwned<'a> {
+ Owned(int),
+ Borrowed(&'a int)
+}
+
+pub struct Inv<'a> { // invariant w/r/t 'a
+ x: &'a mut &'a int
+}
+
+// I encountered a bug at some point with encoding the IntoMaybeOwned
+// trait, so I'll use that as the template for this test.
+pub trait IntoMaybeOwned<'a> {
+ fn into_maybe_owned(self) -> MaybeOwned<'a>;
+
+ // Note: without this `into_inv` method, the trait is
+ // contravariant w/r/t `'a`, since if you look strictly at the
+ // interface, it only returns `'a`. This complicates the
+ // downstream test since it wants invariance to force an error.
+ // Hence we add this method.
+ fn into_inv(self) -> Inv<'a>;
+
+ fn bigger_region<'b:'a>(self, b: Inv<'b>);
+}
+
+impl<'a> IntoMaybeOwned<'a> for Inv<'a> {
+ fn into_maybe_owned(self) -> MaybeOwned<'a> { panic!() }
+ fn into_inv(self) -> Inv<'a> { panic!() }
+ fn bigger_region<'b:'a>(self, b: Inv<'b>) { panic!() }
+}
+++ /dev/null
-// 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.
-
-struct A {
- a: int,
- pub b: int,
-}
-
-pub struct B {
- pub a: int,
- b: int,
-}
--- /dev/null
+// 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.
+
+struct A {
+ a: int,
+ pub b: int,
+}
+
+pub struct B {
+ pub a: int,
+ b: int,
+}
#![crate_name="struct_variant_xc_aux"]
#![crate_type = "lib"]
+#[derive(Copy)]
pub enum Enum {
Variant(u8),
StructVariant { arg: u8 }
+++ /dev/null
-// 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.
-
-// Simple smoke test that unsafe traits can be compiled etc.
-
-pub unsafe trait Foo {
- fn foo(&self) -> int;
-}
-
-unsafe impl Foo for int {
- fn foo(&self) -> int { *self }
-}
--- /dev/null
+// 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.
+
+// Simple smoke test that unsafe traits can be compiled etc.
+
+pub unsafe trait Foo {
+ fn foo(&self) -> int;
+}
+
+unsafe impl Foo for int {
+ fn foo(&self) -> int { *self }
+}
+++ /dev/null
-// 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.
-
-#![feature(optin_builtin_traits, core)]
-#![crate_type = "rlib"]
-
-use std::marker::MarkerTrait;
-
-pub trait DefaultedTrait : MarkerTrait { }
-impl DefaultedTrait for .. { }
-
-pub struct Something<T> { t: T }
--- /dev/null
+// 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.
+
+#![feature(optin_builtin_traits, core)]
+#![crate_type = "rlib"]
+
+use std::marker::MarkerTrait;
+
+pub trait DefaultedTrait : MarkerTrait { }
+impl DefaultedTrait for .. { }
+
+pub struct Something<T> { t: T }
+++ /dev/null
-// Copyright 2012 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.
-
-mod super_sekrit {
- pub enum sooper_sekrit {
- quux, baz
- }
-}
--- /dev/null
+// Copyright 2012 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.
+
+mod super_sekrit {
+ pub enum sooper_sekrit {
+ quux, baz
+ }
+}
// except according to those terms.
extern crate "" as foo; //~ ERROR: crate name must not be empty
+//~^ WARNING: obsolete syntax
fn main() {}
// except according to those terms.
extern crate "#a" as bar; //~ ERROR: invalid character `#` in crate name: `#a`
+//~^ WARNING: obsolete syntax
fn main() {}
}
impl Fn<(isize,)> for SFn {
- type Output = isize;
-
extern "rust-call" fn call(&self, (z,): (isize,)) -> isize {
self.x * self.y * z
}
}
+impl FnMut<(isize,)> for SFn {
+ extern "rust-call" fn call_mut(&mut self, args: (isize,)) -> isize { self.call(args) }
+}
+
+impl FnOnce<(isize,)> for SFn {
+ type Output = isize;
+ extern "rust-call" fn call_once(self, args: (isize,)) -> isize { self.call(args) }
+}
+
struct SFnMut {
x: isize,
y: isize,
}
impl FnMut<(isize,)> for SFnMut {
- type Output = isize;
-
extern "rust-call" fn call_mut(&mut self, (z,): (isize,)) -> isize {
self.x * self.y * z
}
}
+impl FnOnce<(isize,)> for SFnMut {
+ type Output = isize;
+ extern "rust-call" fn call_once(mut self, args: (isize,)) -> isize { self.call_mut(args) }
+}
+
struct SFnOnce {
x: String,
}
fn main() {
let x: Option<&[u8]> = Some("foo").map(std::mem::transmute);
- //~^ ERROR: is not implemented for the type
+ //~^ ERROR E0277
+ //~| ERROR E0277
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// aux-build:coherence-lib.rs
+// aux-build:coherence_lib.rs
-extern crate "coherence-lib" as lib;
+extern crate coherence_lib as lib;
use lib::Remote1;
impl<T> Remote1<T> for isize { }
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// aux-build:coherence-lib.rs
+// aux-build:coherence_lib.rs
-extern crate "coherence-lib" as lib;
+extern crate coherence_lib as lib;
use lib::Remote1;
pub struct BigInt;
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// aux-build:coherence-lib.rs
+// aux-build:coherence_lib.rs
// Test that it's not ok for U to appear uncovered
-extern crate "coherence-lib" as lib;
+extern crate coherence_lib as lib;
use lib::{Remote,Pair};
pub struct Cover<T>(T);
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// aux-build:coherence-lib.rs
+// aux-build:coherence_lib.rs
-extern crate "coherence-lib" as lib;
+extern crate coherence_lib as lib;
use lib::Remote;
impl<T> Remote for T { }
// except according to those terms.
// ignore-tidy-linelength
-// aux-build:coherence-orphan-lib.rs
+// aux-build:coherence_orphan_lib.rs
#![feature(optin_builtin_traits)]
-extern crate "coherence-orphan-lib" as lib;
+extern crate coherence_orphan_lib as lib;
use lib::TheTrait;
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// aux-build:coherence-lib.rs
+// aux-build:coherence_lib.rs
-extern crate "coherence-lib" as lib;
+extern crate coherence_lib as lib;
use lib::Remote;
struct Foo;
// Test that the same coverage rules apply even if the local type appears in the
// list of type parameters, not the self type.
-// aux-build:coherence-lib.rs
+// aux-build:coherence_lib.rs
-extern crate "coherence-lib" as lib;
+extern crate coherence_lib as lib;
use lib::{Remote1, Pair};
pub struct Local<T>(T);
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// aux-build:coherence-lib.rs
+// aux-build:coherence_lib.rs
-extern crate "coherence-lib" as lib;
+extern crate coherence_lib as lib;
use lib::{Remote, Pair};
struct Local<T>(T);
--- /dev/null
+// 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.
+
+trait Foo {
+ type X;
+ fn method(&self) {}
+}
+
+#[derive(Clone)]
+struct Bar<T: Foo> {
+ x: T::X,
+}
+
+struct NotClone;
+
+impl Foo for NotClone {
+ type X = i8;
+}
+
+fn main() {
+ Bar::<NotClone> { x: 1 }.clone(); //~ ERROR
+}
extern crate core;
extern crate rand;
-extern crate "serialize" as rustc_serialize;
+extern crate serialize as rustc_serialize;
#[derive(Rand)] //~ ERROR this trait cannot be derived
//~^ WARNING `#[derive(Rand)]` is deprecated
let _x: extern "C" fn() = f; // OK
is_fn(f);
//~^ ERROR the trait `core::ops::Fn<()>` is not implemented for the type `extern "C" fn()
- //~| ERROR the trait `core::ops::Fn<()>` is not implemented for the type `extern "C" fn()
+ //~| ERROR the trait `core::ops::FnOnce<()>` is not implemented for the type `extern "C" fn()
}
struct Foo;
impl Fn<()> for Foo {
//~^ ERROR angle-bracket notation is not stable when used with the `Fn` family of traits
- type Output = ();
-
- extern "rust-call" fn call(&self, args: ()) -> () {}
+ extern "rust-call" fn call(self, args: ()) -> () {}
}
struct Foo1;
-impl Fn() for Foo1 {
+impl FnOnce() for Foo1 {
//~^ ERROR associated type bindings are not allowed here
-
- extern "rust-call" fn call(&self, args: ()) -> () {}
+ extern "rust-call" fn call_once(self, args: ()) -> () {}
}
struct Bar;
impl FnMut<()> for Bar {
//~^ ERROR angle-bracket notation is not stable when used with the `Fn` family of traits
- type Output = ();
-
extern "rust-call" fn call_mut(&self, args: ()) -> () {}
}
struct Baz;
impl FnOnce<()> for Baz {
//~^ ERROR angle-bracket notation is not stable when used with the `Fn` family of traits
- type Output = ();
-
extern "rust-call" fn call_once(&self, args: ()) -> () {}
}
needs_fn(1);
//~^ ERROR `core::ops::Fn<(isize,)>`
- //~| ERROR `core::ops::Fn<(isize,)>`
+ //~| ERROR `core::ops::FnOnce<(isize,)>`
}
}
fn main() {
- apply(&3, takes_mut); //~ ERROR (values differ in mutability)
apply(&3, takes_imm);
+ apply(&3, takes_mut);
+ //~^ ERROR (values differ in mutability)
+ //~| ERROR (values differ in mutability)
apply(&mut 3, takes_mut);
- apply(&mut 3, takes_imm); //~ ERROR (values differ in mutability)
+ apply(&mut 3, takes_imm);
+ //~^ ERROR (values differ in mutability)
+ //~| ERROR (values differ in mutability)
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// aux-build:issue-11680.rs
+// aux-build:issue_11680.rs
-extern crate "issue-11680" as other;
+extern crate issue_11680 as other;
fn main() {
let _b = other::Foo::Bar(1);
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// aux-build:issue-12612-1.rs
+// aux-build:issue_12612_1.rs
-extern crate "issue-12612-1" as foo;
+extern crate issue_12612_1 as foo;
use foo::bar;
//~| expected u8
//~| found array of 1 elements
- let local = [0];
+ let local: [u8; 1] = [0];
let _v = &local as *mut u8;
//~^ ERROR mismatched types
//~| expected `*mut u8`
- //~| found `&[_; 1]`
+ //~| found `&[u8; 1]`
//~| expected u8,
//~| found array of 1 elements
}
x: T
}
-impl<T: fmt::Debug> ops::Fn<(),> for Debuger<T> {
+impl<T: fmt::Debug> ops::FnOnce<(),> for Debuger<T> {
type Output = ();
-
- fn call(&self, _args: ()) {
-//~^ ERROR `call` has an incompatible type for trait: expected "rust-call" fn, found "Rust" fn
+ fn call_once(self, _args: ()) {
+//~^ ERROR `call_once` has an incompatible type for trait: expected "rust-call" fn, found "Rust" fn
println!("{:?}", self.x);
}
}
}
static foo: *const Y::X = Y::foo(Y::x as *const Y::X);
-//~^ ERROR cannot refer to other statics by value
-//~| ERROR the trait `core::marker::Sync` is not implemented for the type
+//~^ ERROR the trait `core::marker::Sync` is not implemented for the type
//~| ERROR function calls in statics are limited to struct and enum constructors
fn main() {}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// aux-build:issue-16725.rs
+// aux-build:issue_16725.rs
-extern crate "issue-16725" as foo;
+extern crate issue_16725 as foo;
fn main() {
unsafe { foo::bar(); }
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// aux-build:issue-17718-const-privacy.rs
+// aux-build:issue_17718_const_privacy.rs
-extern crate "issue-17718-const-privacy" as other;
+extern crate issue_17718_const_privacy as other;
use a::B; //~ ERROR: const `B` is private
use other::{
struct Foo;
impl<'a, T> Fn<(&'a T,)> for Foo {
+ extern "rust-call" fn call(&self, (_,): (T,)) {}
+ //~^ ERROR: has an incompatible type for trait: expected &-ptr
+}
+
+impl<'a, T> FnMut<(&'a T,)> for Foo {
+ extern "rust-call" fn call_mut(&mut self, (_,): (T,)) {}
+ //~^ ERROR: has an incompatible type for trait: expected &-ptr
+}
+
+impl<'a, T> FnOnce<(&'a T,)> for Foo {
type Output = ();
- extern "rust-call" fn call(&self, (_,): (T,)) {}
+ extern "rust-call" fn call_once(self, (_,): (T,)) {}
//~^ ERROR: has an incompatible type for trait: expected &-ptr
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// aux-build:issue-21202.rs
+// aux-build:issue_21202.rs
-extern crate "issue-21202" as crate1;
+extern crate issue_21202 as crate1;
use crate1::A;
+++ /dev/null
-// 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.
-
-trait Foo { fn foo(&self) {} }
-impl Foo for u8 {}
-
-fn main() {
- // FIXME (#22405): Replace `Box::new` with `box` here when/if possible.
- let r: Box<Foo> = Box::new(5);
- let _m: Box<Foo> = r as Box<Foo>;
- //~^ ERROR `core::marker::Sized` is not implemented for the type `Foo`
-}
let a = &t as &Gettable<T>;
//~^ ERROR the trait `core::marker::Send` is not implemented
//~^^ ERROR the trait `core::marker::Copy` is not implemented
+ //~^^^ ERROR the parameter type `T` may not live long enough
}
fn g<T>(val: T) {
}
pub fn foo() {
- let a = &1 as &inner::Trait;
+ let a: &inner::Trait = &1_isize;
a.f();
}
+++ /dev/null
-// Copyright 2013 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.
-
-#![forbid(unused_typecasts)]
-
-fn foo_i32(_: i32) {}
-
-fn foo_u64(a: u64) {
- let b: i32 = a as i32;
- foo_i32(b as i32); //~ ERROR: unnecessary type cast
-}
-
-fn main() {
- let x: u64 = 1;
- let y: u64 = x as u64; //~ ERROR: unnecessary type cast
- foo_u64(y as u64); //~ ERROR: unnecessary type cast
-}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// aux-build:lint-unused-extern-crate.rs
+// aux-build:lint_unused_extern_crate.rs
#![deny(unused_extern_crates)]
#![allow(unused_variables)]
extern crate libc; //~ ERROR: unused extern crate
-extern crate "collections" as collecs; // no error, it is used
+extern crate collections as collecs; // no error, it is used
extern crate rand; // no error, the use marks it as used
// even if imported objects aren't used
-extern crate "lint-unused-extern-crate" as other; // no error, the use * marks it as used
+extern crate lint_unused_extern_crate as other; // no error, the use * marks it as used
#[allow(unused_imports)]
use rand::isaac::IsaacRng;
#![deny(unused_variables)]
#![deny(unused_assignments)]
-#![allow(dead_code, non_camel_case_types)]
+#![allow(dead_code, non_camel_case_types, trivial_numeric_casts)]
fn f1(x: isize) {
//~^ ERROR unused variable: `x`
#![feature(rustc_attrs)]
#![allow(dead_code)]
+#![allow(trivial_casts)]
trait Bar {
fn bar(self);
}
impl FnMut<(isize,)> for S {
- type Output = isize;
-
extern "rust-call" fn call_mut(&mut self, (z,): (isize,)) -> isize {
self.x * self.y * z
}
}
+impl FnOnce<(isize,)> for S {
+ type Output = isize;
+ extern "rust-call" fn call_once(mut self, (z,): (isize,)) -> isize {
+ self.call_mut((z,))
+ }
+}
+
fn main() {
let mut s = S {
x: 3,
}
impl FnMut<isize> for S {
- type Output = isize;
extern "rust-call" fn call_mut(&mut self, z: isize) -> isize {
self.x + self.y + z
}
}
+impl FnOnce<isize> for S {
+ type Output = isize;
+ extern "rust-call" fn call_once(mut self, z: isize) -> isize { self.call_mut(z) }
+}
+
fn main() {
let mut s = S {
x: 1,
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// aux-build:privacy-tuple-struct.rs
+// aux-build:privacy_tuple_struct.rs
-extern crate "privacy-tuple-struct" as other;
+extern crate privacy_tuple_struct as other;
mod a {
pub struct A(());
let c = other::C(2, 3); //~ ERROR: cannot invoke tuple struct constructor
let d = other::D(4);
- let other::A(()) = a; //~ ERROR: field #1 of struct `privacy-tuple-struct::A` is private
+ let other::A(()) = a; //~ ERROR: field #1 of struct `privacy_tuple_struct::A` is private
let other::A(_) = a;
match a { other::A(()) => {} }
- //~^ ERROR: field #1 of struct `privacy-tuple-struct::A` is private
+ //~^ ERROR: field #1 of struct `privacy_tuple_struct::A` is private
match a { other::A(_) => {} }
let other::B(_) = b;
- let other::B(_b) = b; //~ ERROR: field #1 of struct `privacy-tuple-struct::B` is private
+ let other::B(_b) = b; //~ ERROR: field #1 of struct `privacy_tuple_struct::B` is private
match b { other::B(_) => {} }
match b { other::B(_b) => {} }
- //~^ ERROR: field #1 of struct `privacy-tuple-struct::B` is private
+ //~^ ERROR: field #1 of struct `privacy_tuple_struct::B` is private
match b { other::B(1) => {} other::B(_) => {} }
- //~^ ERROR: field #1 of struct `privacy-tuple-struct::B` is private
+ //~^ ERROR: field #1 of struct `privacy_tuple_struct::B` is private
let other::C(_, _) = c;
let other::C(_a, _) = c;
- let other::C(_, _b) = c; //~ ERROR: field #2 of struct `privacy-tuple-struct::C` is private
- let other::C(_a, _b) = c; //~ ERROR: field #2 of struct `privacy-tuple-struct::C` is private
+ let other::C(_, _b) = c; //~ ERROR: field #2 of struct `privacy_tuple_struct::C` is private
+ let other::C(_a, _b) = c; //~ ERROR: field #2 of struct `privacy_tuple_struct::C` is private
match c { other::C(_, _) => {} }
match c { other::C(_a, _) => {} }
match c { other::C(_, _b) => {} }
- //~^ ERROR: field #2 of struct `privacy-tuple-struct::C` is private
+ //~^ ERROR: field #2 of struct `privacy_tuple_struct::C` is private
match c { other::C(_a, _b) => {} }
- //~^ ERROR: field #2 of struct `privacy-tuple-struct::C` is private
+ //~^ ERROR: field #2 of struct `privacy_tuple_struct::C` is private
let other::D(_) = d;
let other::D(_d) = d;
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// aux-build:regions-bounded-method-type-parameters-cross-crate-lib.rs
+// aux-build:regions_bounded_method_type_parameters_cross_crate_lib.rs
// Check explicit region bounds on methods in the cross crate case.
-extern crate "regions-bounded-method-type-parameters-cross-crate-lib" as lib;
+extern crate regions_bounded_method_type_parameters_cross_crate_lib as lib;
use lib::Inv;
use lib::MaybeOwned;
fn f<'a, T, U>(v: Box<A<T>+'static>) -> Box<X+'static> {
box B(&*v) as Box<X> //~ ERROR the parameter type `T` may not live long enough
+ //~^ ERROR the parameter type `T` may not live long enough
}
fn main() {}
fn make_object1<A:SomeTrait>(v: A) -> Box<SomeTrait+'static> {
box v as Box<SomeTrait+'static>
//~^ ERROR the parameter type `A` may not live long enough
+ //~^^ ERROR the parameter type `A` may not live long enough
}
fn make_object2<'a,A:SomeTrait+'a>(v: A) -> Box<SomeTrait+'a> {
fn make_object3<'a,'b,A:SomeTrait+'a>(v: A) -> Box<SomeTrait+'b> {
box v as Box<SomeTrait+'b>
//~^ ERROR the parameter type `A` may not live long enough
+ //~^^ ERROR the parameter type `A` may not live long enough
}
fn main() { }
--- /dev/null
+// 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.
+
+// Issue 8142: Test that Drop impls cannot be specialized beyond the
+// predicates attached to the struct/enum definition itself.
+
+#![feature(unsafe_destructor)]
+
+trait Bound { fn foo(&self) { } }
+struct K<'l1,'l2> { x: &'l1 i8, y: &'l2 u8 }
+struct L<'l1,'l2> { x: &'l1 i8, y: &'l2 u8 }
+struct M<'m> { x: &'m i8 }
+struct N<'n> { x: &'n i8 }
+struct O<To> { x: *const To }
+struct P<Tp> { x: *const Tp }
+struct Q<Tq> { x: *const Tq }
+struct R<Tr> { x: *const Tr }
+struct S<Ts:Bound> { x: *const Ts }
+struct T<'t,Ts:'t> { x: &'t Ts }
+struct U;
+struct V<Tva, Tvb> { x: *const Tva, y: *const Tvb }
+struct W<'l1, 'l2> { x: &'l1 i8, y: &'l2 u8 }
+
+#[unsafe_destructor]
+impl<'al,'adds_bnd:'al> Drop for K<'al,'adds_bnd> { // REJECT
+ //~^ ERROR The requirement `'adds_bnd : 'al` is added only by the Drop impl.
+ fn drop(&mut self) { } }
+
+#[unsafe_destructor]
+impl<'al,'adds_bnd> Drop for L<'al,'adds_bnd> where 'adds_bnd:'al { // REJECT
+ //~^ ERROR The requirement `'adds_bnd : 'al` is added only by the Drop impl.
+ fn drop(&mut self) { } }
+
+#[unsafe_destructor]
+impl<'ml> Drop for M<'ml> { fn drop(&mut self) { } } // ACCEPT
+
+#[unsafe_destructor]
+impl Drop for N<'static> { fn drop(&mut self) { } } // REJECT
+//~^ ERROR Implementations of Drop cannot be specialized
+
+#[unsafe_destructor]
+impl<Cok_nobound> Drop for O<Cok_nobound> { fn drop(&mut self) { } } // ACCEPT
+
+#[unsafe_destructor]
+impl Drop for P<i8> { fn drop(&mut self) { } } // REJECT
+//~^ ERROR Implementations of Drop cannot be specialized
+
+#[unsafe_destructor]
+impl<Adds_bnd:Bound> Drop for Q<Adds_bnd> { fn drop(&mut self) { } } // REJECT
+//~^ ERROR The requirement `Adds_bnd : Bound` is added only by the Drop impl.
+
+#[unsafe_destructor]
+impl<'rbnd,Adds_rbnd:'rbnd> Drop for R<Adds_rbnd> { fn drop(&mut self) { } } // REJECT
+//~^ ERROR The requirement `Adds_rbnd : 'rbnd` is added only by the Drop impl.
+
+#[unsafe_destructor]
+impl<Bs:Bound> Drop for S<Bs> { fn drop(&mut self) { } } // ACCEPT
+
+#[unsafe_destructor]
+impl<'t,Bt:'t> Drop for T<'t,Bt> { fn drop(&mut self) { } } // ACCEPT
+
+impl Drop for U { fn drop(&mut self) { } } // ACCEPT
+
+#[unsafe_destructor]
+impl<One> Drop for V<One,One> { fn drop(&mut self) { } } // REJECT
+//~^ERROR Implementations of Drop cannot be specialized
+
+#[unsafe_destructor]
+impl<'lw> Drop for W<'lw,'lw> { fn drop(&mut self) { } } // REJECT
+//~^ERROR Implementations of Drop cannot be specialized
+
+pub fn main() { }
// aux-build:pub_static_array.rs
-extern crate "pub_static_array" as array;
+extern crate pub_static_array as array;
use array::ARRAY;
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// aux-build:struct-field-privacy.rs
+// aux-build:struct_field_privacy.rs
-extern crate "struct-field-privacy" as xc;
+extern crate struct_field_privacy as xc;
struct A {
a: isize,
c.a;
c.b; //~ ERROR: field `b` of struct `inner::B` is private
- d.a; //~ ERROR: field `a` of struct `struct-field-privacy::A` is private
+ d.a; //~ ERROR: field `a` of struct `struct_field_privacy::A` is private
d.b;
e.a;
- e.b; //~ ERROR: field `b` of struct `struct-field-privacy::B` is private
+ e.b; //~ ERROR: field `b` of struct `struct_field_privacy::B` is private
}
fn main() {}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// aux-build:struct-field-privacy.rs
+// aux-build:struct_field_privacy.rs
-extern crate "struct-field-privacy" as xc;
+extern crate struct_field_privacy as xc;
use xc::B;
fn main () {
// external crate struct
let k = B {
- aa: 20, //~ ERROR structure `struct-field-privacy::B` has no field named `aa`
+ aa: 20, //~ ERROR structure `struct_field_privacy::B` has no field named `aa`
//~^ HELP did you mean `a`?
- bb: 20, //~ ERROR structure `struct-field-privacy::B` has no field named `bb`
+ bb: 20, //~ ERROR structure `struct_field_privacy::B` has no field named `bb`
};
// local crate struct
let l = A {
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// aux-build:trait-safety-lib.rs
+// aux-build:trait_safety_lib.rs
// Check that unsafe traits require unsafe impls and that inherent
// impls cannot be unsafe.
-extern crate "trait-safety-lib" as lib;
+extern crate trait_safety_lib as lib;
struct Bar;
impl lib::Foo for Bar { //~ ERROR requires an `unsafe impl` declaration
--- /dev/null
+// 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.
+
+// Test the trivial_casts and trivial_numeric_casts lints. For each error we also
+// check that the cast can be done using just coercion.
+
+#![deny(trivial_casts, trivial_numeric_casts)]
+
+trait Foo {
+ fn foo(&self) {}
+}
+
+pub struct Bar;
+
+impl Foo for Bar {}
+
+pub fn main() {
+ // Numeric
+ let _ = 42_i32 as i32; //~ ERROR trivial numeric cast: `i32` as `i32`
+ let _: i32 = 42_i32;
+
+ let _ = 42_u8 as u8; //~ ERROR trivial numeric cast: `u8` as `u8`
+ let _: u8 = 42_u8;
+
+ // & to * pointers
+ let x: &u32 = &42;
+ let _ = x as *const u32; //~ERROR trivial cast: `&u32` as `*const u32`
+ let _: *const u32 = x;
+
+ let x: &mut u32 = &mut 42;
+ let _ = x as *mut u32; //~ERROR trivial cast: `&mut u32` as `*mut u32`
+ let _: *mut u32 = x;
+
+ // unsize array
+ let x: &[u32; 3] = &[42, 43, 44];
+ let _ = x as &[u32]; //~ERROR trivial cast: `&[u32; 3]` as `&[u32]`
+ let _ = x as *const [u32]; //~ERROR trivial cast: `&[u32; 3]` as `*const [u32]`
+ let _: &[u32] = x;
+ let _: *const [u32] = x;
+
+ let x: &mut [u32; 3] = &mut [42, 43, 44];
+ let _ = x as &mut [u32]; //~ERROR trivial cast: `&mut [u32; 3]` as `&mut [u32]`
+ let _ = x as *mut [u32]; //~ERROR trivial cast: `&mut [u32; 3]` as `*mut [u32]`
+ let _: &mut [u32] = x;
+ let _: *mut [u32] = x;
+
+ let x: Box<[u32; 3]> = Box::new([42, 43, 44]);
+ let _ = x as Box<[u32]>; //~ERROR trivial cast: `Box<[u32; 3]>` as `Box<[u32]>`
+ let x: Box<[u32; 3]> = Box::new([42, 43, 44]);
+ let _: Box<[u32]> = x;
+
+ // unsize trait
+ let x: &Bar = &Bar;
+ let _ = x as &Foo; //~ERROR trivial cast: `&Bar` as `&Foo`
+ let _ = x as *const Foo; //~ERROR trivial cast: `&Bar` as `*const Foo`
+ let _: &Foo = x;
+ let _: *const Foo = x;
+
+ let x: &mut Bar = &mut Bar;
+ let _ = x as &mut Foo; //~ERROR trivial cast: `&mut Bar` as `&mut Foo`
+ let _ = x as *mut Foo; //~ERROR trivial cast: `&mut Bar` as `*mut Foo`
+ let _: &mut Foo = x;
+ let _: *mut Foo = x;
+
+ let x: Box<Bar> = Box::new(Bar);
+ let _ = x as Box<Foo>; //~ERROR trivial cast: `Box<Bar>` as `Box<Foo>`
+ let x: Box<Bar> = Box::new(Bar);
+ let _: Box<Foo> = x;
+
+ // functions
+ fn baz(_x: i32) {}
+ let _ = &baz as &Fn(i32); //~ERROR trivial cast: `&fn(i32) {main::baz}` as `&core::ops::Fn(i32)`
+ let _: &Fn(i32) = &baz;
+ let x = |_x: i32| {};
+ let _ = &x as &Fn(i32); //~ERROR trivial cast
+ let _: &Fn(i32) = &x;
+}
+
+// subtyping
+pub fn test_subtyping<'a, 'b: 'a>(a: &'a Bar, b: &'b Bar) {
+ let _ = a as &'a Bar; //~ERROR trivial cast
+ let _: &'a Bar = a;
+ let _ = b as &'a Bar; //~ERROR trivial cast
+ let _: &'a Bar = b;
+ let _ = b as &'b Bar; //~ERROR trivial cast
+ let _: &'b Bar = b;
+}
}
fn main() {
- let x = 5;
+ let x: i32 = 5;
let y = x as MyAdd<i32>;
//~^ ERROR as `MyAdd<i32>`
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// aux-build:typeck-default-trait-impl-cross-crate-coherence-lib.rs
+// aux-build:typeck_default_trait_impl_cross_crate_coherence_lib.rs
// Test that we do not consider associated types to be sendable without
// some applicable trait bound (and we don't ICE).
#![feature(optin_builtin_traits)]
-extern crate "typeck-default-trait-impl-cross-crate-coherence-lib" as lib;
+extern crate typeck_default_trait_impl_cross_crate_coherence_lib as lib;
use lib::DefaultedTrait;
struct S;
impl FnMut<(isize,)> for S {
- type Output = isize;
-
extern "rust-call" fn call_mut(&mut self, (x,): (isize,)) -> isize {
x * x
}
}
+impl FnOnce<(isize,)> for S {
+ type Output = isize;
+
+ extern "rust-call" fn call_once(mut self, args: (isize,)) -> isize { self.call_mut(args) }
+}
+
fn call_it<F:Fn(isize)->isize>(f: &F, x: isize) -> isize {
f.call((x,))
}
fn main() {
let x = call_it(&S, 22);
//~^ ERROR not implemented
- //~| ERROR not implemented
}
}
impl<A,R,F : FnMut(&mut FnMut(A) -> R, A) -> R> FnMut<(A,)> for YCombinator<F,A,R> {
- type Output = R;
-
extern "rust-call" fn call_mut(&mut self, (arg,): (A,)) -> R {
(self.func)(self, arg)
//~^ ERROR cannot borrow `*self` as mutable more than once at a time
}
}
+impl<A,R,F : FnMut(&mut FnMut(A) -> R, A) -> R> FnOnce<(A,)> for YCombinator<F,A,R> {
+ type Output = R;
+ extern "rust-call" fn call_once(mut self, args: (A,)) -> R {
+ self.call_mut(args)
+ }
+}
+
fn main() {
let mut counter = 0;
let factorial = |recur: &mut FnMut(u32) -> u32, arg: u32| -> u32 {
}
fn b() {
- let y = call_it_mut(&mut square, 22); //~ ERROR not implemented
+ let y = call_it_mut(&mut square, 22);
+ //~^ ERROR not implemented
+ //~| ERROR not implemented
}
fn c() {
- let z = call_it_once(square, 22); //~ ERROR not implemented
+ let z = call_it_once(square, 22);
+ //~^ ERROR not implemented
+ //~| ERROR not implemented
}
fn main() { }
}
fn b() {
- let y = call_it_mut(&mut square, 22); //~ ERROR not implemented
+ let y = call_it_mut(&mut square, 22);
+ //~^ ERROR not implemented
+ //~| ERROR not implemented
}
fn c() {
- let z = call_it_once(square, 22); //~ ERROR not implemented
+ let z = call_it_once(square, 22);
+ //~^ ERROR not implemented
+ //~| ERROR not implemented
}
fn main() { }
}
fn b() {
- let y = call_it_mut(&mut square, 22); //~ ERROR not implemented
+ let y = call_it_mut(&mut square, 22);
+ //~^ ERROR not implemented
+ //~| ERROR not implemented
}
fn c() {
- let z = call_it_once(square, 22); //~ ERROR not implemented
+ let z = call_it_once(square, 22);
+ //~^ ERROR not implemented
+ //~| ERROR not implemented
}
fn main() { }
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// aux-build:unreachable-variant.rs
+// aux-build:unreachable_variant.rs
-extern crate "unreachable-variant" as other;
+extern crate unreachable_variant as other;
fn main() {
let _x = other::super_sekrit::sooper_sekrit::baz; //~ ERROR is private
// Issue #14893. Tests that casts from vectors don't behave strangely in the
// presence of the `_` type shorthand notation.
+// Update: after a change to the way casts are done, we have more type information
+// around and so the errors here are no longer exactly the same.
struct X {
y: [u8; 2],
fn main() {
let x1 = X { y: [0, 0] };
- let p1: *const u8 = &x1.y as *const _; //~ ERROR mismatched types
+ // No longer a type mismatch - the `_` can be fully resolved by type inference.
+ let p1: *const u8 = &x1.y as *const _;
let t1: *const [u8; 2] = &x1.y as *const _;
let h1: *const [u8; 2] = &x1.y as *const [u8; 2];
let mut x1 = X { y: [0, 0] };
+ // This is still an error since we don't allow casts from &mut [T; n] to *mut T.
let p1: *mut u8 = &mut x1.y as *mut _; //~ ERROR mismatched types
let t1: *mut [u8; 2] = &mut x1.y as *mut _;
let h1: *mut [u8; 2] = &mut x1.y as *mut [u8; 2];
// option. This file may not be copied, modified, or distributed
// except according to those terms.
+// ignore-aarch64
// min-lldb-version: 310
// compile-flags:-g
// ignore-windows failing on 64-bit bots FIXME #17638
// ignore-lldb
+// ignore-aarch64
// compile-flags:-g
// gdb-command:run
// gdb-command:next
-// gdb-check:[...]33[...]s
+// gdb-check:[...]34[...]s
// gdb-command:continue
#![omit_gdb_pretty_printer_section]
let slice2 = &*vec2;
// Trait Objects
- let box_trait = (box 0) as Box<Trait1>;
- let ref_trait = &0 as &Trait1;
- let mut mut_int1 = 0;
+ let box_trait = (box 0_isize) as Box<Trait1>;
+ let ref_trait = &0_isize as &Trait1;
+ let mut mut_int1 = 0_isize;
let mut_ref_trait = (&mut mut_int1) as &mut Trait1;
- let generic_box_trait = (box 0) as Box<Trait2<i32, Mod1::Struct2>>;
- let generic_ref_trait = (&0) as &Trait2<Struct1, Struct1>;
+ let generic_box_trait = (box 0_isize) as Box<Trait2<i32, Mod1::Struct2>>;
+ let generic_ref_trait = (&0_isize) as &Trait2<Struct1, Struct1>;
- let mut generic_mut_ref_trait_impl = 0;
+ let mut generic_mut_ref_trait_impl = 0_isize;
let generic_mut_ref_trait = (&mut generic_mut_ref_trait_impl) as
&mut Trait2<Mod1::Mod2::Struct3, GenericStruct<usize, isize>>;
extern crate
"foo"suffix //~ ERROR extern crate name with a suffix is illegal
+ //~^ WARNING: obsolete syntax
as foo;
extern
+++ /dev/null
-// 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.
-
-// Tests that the proper help is displayed in the error message
-
-extern crate foo as bar;
-//~^ ERROR expected `;`, found `as`
-//~^^ HELP perhaps you meant to enclose the crate name `foo` in a string?
// Verifies that the expected token errors for `extern crate` are
// raised
-extern crate foo {} //~ERROR expected `;`, found `{`
+extern crate foo {} //~ERROR expected one of `;` or `as`, found `{`
#[prelude_import]
use std::prelude::v1::*;
#[macro_use]
-extern crate "std" as std;
+extern crate std as std;
// 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.
fn main() {
let x: Box<Tr+ Sync>;
- Box::new(1) as Box<Tr+ Sync>;
+ Box::new(1isize) as Box<Tr+ Sync>;
}
#![feature(asm)]
#[cfg(foo = r#"just parse this"#)]
-extern crate r##"blah"## as blah;
+extern crate blah as blah;
fn main() { unsafe { asm!(r###"blah"###); } }
pub fn dummy() {
// force the vtable to be created
- let _x = &1 as &Foo;
+ let _x = &1u as &Foo;
}
| grep "invalid character.*in crate name:"
cp foo.rs $(TMPDIR)/-foo.rs
$(RUSTC) $(TMPDIR)/-foo.rs 2>&1 \
- | grep "crate name cannot start with a hyphen:"
+ | grep "soon cannot contain hyphens:"
}
pub fn main() {
- let x: Box<_> = box() (box 3 as Box<double>);
+ let x: Box<_> = box() (box 3u as Box<double>);
assert_eq!(x.double(), 6);
}
// except according to those terms.
pub fn main() {
- let x = 3;
+ let x: int = 3;
println!("&x={:x}", (&x as *const int as uint));
}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// aux-build:coherence-lib.rs
+// aux-build:coherence_lib.rs
// pretty-expanded FIXME #23616
-extern crate "coherence-lib" as lib;
+extern crate coherence_lib as lib;
use lib::Remote1;
pub struct BigInt;
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// aux-build:coherence-lib.rs
+// aux-build:coherence_lib.rs
// pretty-expanded FIXME #23616
-extern crate "coherence-lib" as lib;
+extern crate coherence_lib as lib;
use lib::Remote1;
pub struct BigInt;
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// aux-build:coherence-lib.rs
+// aux-build:coherence_lib.rs
// pretty-expanded FIXME #23616
-extern crate "coherence-lib" as lib;
+extern crate coherence_lib as lib;
use lib::Remote1;
pub trait Local {
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// aux-build:coherence-lib.rs
+// aux-build:coherence_lib.rs
// pretty-expanded FIXME #23616
-extern crate "coherence-lib" as lib;
+extern crate coherence_lib as lib;
use lib::Remote;
struct Foo<T>(T);
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// aux-build:coherence-lib.rs
+// aux-build:coherence_lib.rs
// Test that it's ok for T to appear first in the self-type, as long
// as it's covered somewhere.
// pretty-expanded FIXME #23616
-extern crate "coherence-lib" as lib;
+extern crate coherence_lib as lib;
use lib::{Remote,Pair};
pub struct Cover<T>(T);
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// aux-build:coherence-lib.rs
+// aux-build:coherence_lib.rs
// Test that it's ok for T to appear second in the self-type, as long
// as it's covered somewhere.
// pretty-expanded FIXME #23616
-extern crate "coherence-lib" as lib;
+extern crate coherence_lib as lib;
use lib::{Remote,Pair};
pub struct Cover<T>(T);
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// aux-build:coherence-lib.rs
+// aux-build:coherence_lib.rs
// pretty-expanded FIXME #23616
-extern crate "coherence-lib" as lib;
+extern crate coherence_lib as lib;
use lib::Remote1;
struct Foo<T>(T);
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// aux-build:coherence-lib.rs
+// aux-build:coherence_lib.rs
// pretty-expanded FIXME #23616
-extern crate "coherence-lib" as lib;
+extern crate coherence_lib as lib;
use lib::Remote1;
struct Foo<T>(T);
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// aux-build:coherence-lib.rs
+// aux-build:coherence_lib.rs
// pretty-expanded FIXME #23616
-extern crate "coherence-lib" as lib;
+extern crate coherence_lib as lib;
use lib::Remote;
struct Local;
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// aux-build:coherence-lib.rs
+// aux-build:coherence_lib.rs
// pretty-expanded FIXME #23616
-extern crate "coherence-lib" as lib;
+extern crate coherence_lib as lib;
use lib::Remote;
struct Local<T>(T);
--- /dev/null
+// 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.
+
+#![feature(core, debug_builders)]
+
+pub trait DeclaredTrait {
+ type Type;
+}
+
+impl DeclaredTrait for i32 {
+ type Type = i32;
+}
+
+pub trait WhereTrait {
+ type Type;
+}
+
+impl WhereTrait for i32 {
+ type Type = i32;
+}
+
+// Make sure we don't add a bound that just shares a name with an associated
+// type.
+pub mod module {
+ pub type Type = i32;
+}
+
+#[derive(PartialEq, Debug)]
+struct PrivateStruct<T>(T);
+
+#[derive(PartialEq, Debug)]
+struct TupleStruct<A, B: DeclaredTrait, C>(
+ module::Type,
+ Option<module::Type>,
+ A,
+ PrivateStruct<A>,
+ B,
+ B::Type,
+ Option<B::Type>,
+ <B as DeclaredTrait>::Type,
+ Option<<B as DeclaredTrait>::Type>,
+ C,
+ C::Type,
+ Option<C::Type>,
+ <C as WhereTrait>::Type,
+ Option<<C as WhereTrait>::Type>,
+ <i32 as DeclaredTrait>::Type,
+) where C: WhereTrait;
+
+#[derive(PartialEq, Debug)]
+pub struct Struct<A, B: DeclaredTrait, C> where C: WhereTrait {
+ m1: module::Type,
+ m2: Option<module::Type>,
+ a1: A,
+ a2: PrivateStruct<A>,
+ b: B,
+ b1: B::Type,
+ b2: Option<B::Type>,
+ b3: <B as DeclaredTrait>::Type,
+ b4: Option<<B as DeclaredTrait>::Type>,
+ c: C,
+ c1: C::Type,
+ c2: Option<C::Type>,
+ c3: <C as WhereTrait>::Type,
+ c4: Option<<C as WhereTrait>::Type>,
+ d: <i32 as DeclaredTrait>::Type,
+}
+
+#[derive(PartialEq, Debug)]
+enum Enum<A, B: DeclaredTrait, C> where C: WhereTrait {
+ Unit,
+ Seq(
+ module::Type,
+ Option<module::Type>,
+ A,
+ PrivateStruct<A>,
+ B,
+ B::Type,
+ Option<B::Type>,
+ <B as DeclaredTrait>::Type,
+ Option<<B as DeclaredTrait>::Type>,
+ C,
+ C::Type,
+ Option<C::Type>,
+ <C as WhereTrait>::Type,
+ Option<<C as WhereTrait>::Type>,
+ <i32 as DeclaredTrait>::Type,
+ ),
+ Map {
+ m1: module::Type,
+ m2: Option<module::Type>,
+ a1: A,
+ a2: PrivateStruct<A>,
+ b: B,
+ b1: B::Type,
+ b2: Option<B::Type>,
+ b3: <B as DeclaredTrait>::Type,
+ b4: Option<<B as DeclaredTrait>::Type>,
+ c: C,
+ c1: C::Type,
+ c2: Option<C::Type>,
+ c3: <C as WhereTrait>::Type,
+ c4: Option<<C as WhereTrait>::Type>,
+ d: <i32 as DeclaredTrait>::Type,
+ },
+}
+
+fn main() {
+ let e: TupleStruct<
+ i32,
+ i32,
+ i32,
+ > = TupleStruct(
+ 0,
+ None,
+ 0,
+ PrivateStruct(0),
+ 0,
+ 0,
+ None,
+ 0,
+ None,
+ 0,
+ 0,
+ None,
+ 0,
+ None,
+ 0,
+ );
+ assert_eq!(e, e);
+
+ let e: Struct<
+ i32,
+ i32,
+ i32,
+ > = Struct {
+ m1: 0,
+ m2: None,
+ a1: 0,
+ a2: PrivateStruct(0),
+ b: 0,
+ b1: 0,
+ b2: None,
+ b3: 0,
+ b4: None,
+ c: 0,
+ c1: 0,
+ c2: None,
+ c3: 0,
+ c4: None,
+ d: 0,
+ };
+ assert_eq!(e, e);
+
+ let e = Enum::Unit::<i32, i32, i32>;
+ assert_eq!(e, e);
+
+ let e: Enum<
+ i32,
+ i32,
+ i32,
+ > = Enum::Seq(
+ 0,
+ None,
+ 0,
+ PrivateStruct(0),
+ 0,
+ 0,
+ None,
+ 0,
+ None,
+ 0,
+ 0,
+ None,
+ 0,
+ None,
+ 0,
+ );
+ assert_eq!(e, e);
+
+ let e: Enum<
+ i32,
+ i32,
+ i32,
+ > = Enum::Map {
+ m1: 0,
+ m2: None,
+ a1: 0,
+ a2: PrivateStruct(0),
+ b: 0,
+ b1: 0,
+ b2: None,
+ b3: 0,
+ b4: None,
+ c: 0,
+ c1: 0,
+ c2: None,
+ c3: 0,
+ c4: None,
+ d: 0,
+ };
+ assert_eq!(e, e);
+}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-#![feature(std_misc, libc)]
+#![feature(libc)]
extern crate libc;
-use std::thread::Thread;
+use std::thread;
mod rustrt {
extern crate libc;
pub fn main() {
// Make sure we're on a task with small Rust stacks (main currently
// has a large stack)
- let _t = Thread::spawn(move|| {
+ thread::scoped(move|| {
let result = count(1000);
println!("result = {}", result);
assert_eq!(result, 1000);
- });
+ }).join();
}
+++ /dev/null
-// 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.
-
-// Given `<expr> as Box<Trait>`, we should be able to infer that a
-// `Box<_>` is the expected type.
-
-// pretty-expanded FIXME #23616
-
-trait Foo { fn foo(&self) -> u32; }
-impl Foo for u32 { fn foo(&self) -> u32 { *self } }
-
-// (another impl to ensure trait-matching cannot just choose from a singleton set)
-impl Foo for () { fn foo(&self) -> u32 { -176 } }
-
-trait Boxed { fn make() -> Self; }
-impl Boxed for Box<u32> { fn make() -> Self { Box::new(7) } }
-
-// (another impl to ensure trait-matching cannot just choose from a singleton set)
-impl Boxed for () { fn make() -> Self { () } }
-
-fn boxed_foo() {
- let b7 = Boxed::make() as Box<Foo>;
- assert_eq!(b7.foo(), 7);
-}
-
-trait Refed<'a,T> { fn make(&'a T) -> Self; }
-impl<'a> Refed<'a, u32> for &'a u32 { fn make(x: &'a u32) -> Self { x } }
-
-// (another impl to ensure trait-matching cannot just choose from a singleton set)
-impl<'a,'b> Refed<'a, ()> for &'b () { fn make(_: &'a ()) -> Self { static U: () = (); &U } }
-
-fn refed_foo() {
- let a = 8;
- let b7 = Refed::make(&a) as &Foo;
- assert_eq!(b7.foo(), 8);
-}
-
-fn check_subtyping_works() {
- fn inner<'short, 'long:'short>(_s: &'short u32,
- l: &'long u32) -> &'short (Foo+'short) {
- Refed::make(l) as &Foo
- }
-
- let a = 9;
- let b = 10;
- let r = inner(&b, &a);
- assert_eq!(r.foo(), 9);
-}
-
-pub fn main() {
- boxed_foo();
- refed_foo();
- check_subtyping_works();
-}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// aux-build:issue-12612-1.rs
-// aux-build:issue-12612-2.rs
+// aux-build:issue_12612_1.rs
+// aux-build:issue_12612_2.rs
// pretty-expanded FIXME #23616
-extern crate "issue-12612-1" as foo;
-extern crate "issue-12612-2" as bar;
+extern crate issue_12612_1 as foo;
+extern crate issue_12612_2 as bar;
mod test {
use bar::baz;
struct Foo<T>(T);
impl<T: Copy> Fn<()> for Foo<T> {
- type Output = T;
extern "rust-call" fn call(&self, _: ()) -> T {
match *self {
Foo(t) => t
}
}
+impl<T: Copy> FnMut<()> for Foo<T> {
+ extern "rust-call" fn call_mut(&mut self, _: ()) -> T {
+ self.call(())
+ }
+}
+
+impl<T: Copy> FnOnce<()> for Foo<T> {
+ type Output = T;
+
+ extern "rust-call" fn call_once(self, _: ()) -> T {
+ self.call(())
+ }
+}
+
fn main() {
let t: u8 = 1;
println!("{}", Foo(t)());
struct Bar;
impl<'a> std::ops::Fn<(&'a (Foo+'a),)> for Bar {
- type Output = ();
extern "rust-call" fn call(&self, _: (&'a Foo,)) {}
}
+impl<'a> std::ops::FnMut<(&'a (Foo+'a),)> for Bar {
+ extern "rust-call" fn call_mut(&mut self, a: (&'a Foo,)) { self.call(a) }
+}
+
+impl<'a> std::ops::FnOnce<(&'a (Foo+'a),)> for Bar {
+ type Output = ();
+ extern "rust-call" fn call_once(self, a: (&'a Foo,)) { self.call(a) }
+}
+
struct Baz;
impl Foo for Baz {}
}
impl<'b> Fn<(&'b mut (Response+'b),)> for SendFile {
+ extern "rust-call" fn call(&self, (_res,): (&'b mut (Response+'b),)) {}
+}
+
+impl<'b> FnMut<(&'b mut (Response+'b),)> for SendFile {
+ extern "rust-call" fn call_mut(&mut self, (_res,): (&'b mut (Response+'b),)) {
+ self.call((_res,))
+ }
+}
+
+impl<'b> FnOnce<(&'b mut (Response+'b),)> for SendFile {
type Output = ();
- extern "rust-call" fn call(&self, (_res,): (&'b mut (Response+'b),)) {}
+ extern "rust-call" fn call_once(self, (_res,): (&'b mut (Response+'b),)) {
+ self.call((_res,))
+ }
}
impl<Rq: Request, Rs: Response> Ingot<Rq, Rs> for HelloWorld {
assert_eq!(cc().unwrap(), 3);
assert_eq!(dd().unwrap(), 3);
- let i = box 32 as Box<A>;
+ let i = box 32i as Box<A>;
assert_eq!(i.aaa(), 3);
- let i = box 32 as Box<A>;
+ let i = box 32i as Box<A>;
assert_eq!(i.bbb(), 3);
- let i = box 32 as Box<A>;
+ let i = box 32i as Box<A>;
assert_eq!(i.ccc().unwrap(), 3);
- let i = box 32 as Box<A>;
+ let i = box 32i as Box<A>;
assert_eq!(i.ddd().unwrap(), 3);
}
}
-struct Foo<B>(B);
+struct Foo<B: Bar>(B);
#[unsafe_destructor]
impl<B: Bar> Drop for Foo<B> {
use serialize::{Encoder, Encodable};
use serialize::json;
-struct Foo<T> {
+struct Foo<T: Encodable> {
v: T,
}
struct Foo { foo: u32 }
impl FnMut<()> for Foo {
- type Output = u32;
extern "rust-call" fn call_mut(&mut self, _: ()) -> u32 { self.foo }
}
-impl FnMut<(u32,)> for Foo {
+impl FnOnce<()> for Foo {
type Output = u32;
+ extern "rust-call" fn call_once(mut self, _: ()) -> u32 { self.call_mut(()) }
+}
+
+/////////////////////////////////////////////////////////////////////////
+
+impl FnMut<(u32,)> for Foo {
extern "rust-call" fn call_mut(&mut self, (x,): (u32,)) -> u32 { self.foo + x }
}
-impl FnMut<(u32,u32)> for Foo {
+impl FnOnce<(u32,)> for Foo {
type Output = u32;
+ extern "rust-call" fn call_once(mut self, args: (u32,)) -> u32 { self.call_mut(args) }
+}
+
+/////////////////////////////////////////////////////////////////////////
+
+impl FnMut<(u32,u32)> for Foo {
extern "rust-call" fn call_mut(&mut self, (x, y): (u32, u32)) -> u32 { self.foo + x + y }
}
+impl FnOnce<(u32,u32)> for Foo {
+ type Output = u32;
+ extern "rust-call" fn call_once(mut self, args: (u32,u32)) -> u32 { self.call_mut(args) }
+}
+
fn main() {
let mut f = box Foo { foo: 42 } as Box<FnMut() -> u32>;
assert_eq!(f.call_mut(()), 42);
struct Foo;
impl<'a> Fn<(&'a (),)> for Foo {
+ extern "rust-call" fn call(&self, (_,): (&(),)) {}
+}
+
+impl<'a> FnMut<(&'a (),)> for Foo {
+ extern "rust-call" fn call_mut(&mut self, (_,): (&(),)) {}
+}
+
+impl<'a> FnOnce<(&'a (),)> for Foo {
type Output = ();
- extern "rust-call" fn call(&self, (_,): (&(),)) {}
+ extern "rust-call" fn call_once(self, (_,): (&(),)) {}
}
fn main() {}
--- /dev/null
+// 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.
+
+#![feature(core)]
+
+use std::simd::i32x4;
+fn main() {
+ let foo = i32x4(1,2,3,4);
+ let bar = i32x4(40,30,20,10);
+ let baz = foo + bar;
+ assert!(baz.0 == 41 && baz.1 == 32 && baz.2 == 23 && baz.3 == 14);
+}
}
}
- pub struct send_packet<T> {
+ pub struct send_packet<T:Send> {
p: Option<*const packet<T>>,
}
}
}
- pub struct recv_packet<T> {
+ pub struct recv_packet<T:Send> {
p: Option<*const packet<T>>,
}
struct Y(int);
#[derive(Debug)]
-struct Z<T> {
+struct Z<T: X+std::fmt::Debug> {
x: T
}
}
pub fn main() {
- let inner = 5;
+ let inner: int = 5;
let outer = Outer::new(&inner as &Inner);
outer.inner.print();
}
impl X for int {}
pub struct Z<'a>(Enum<&'a (X+'a)>);
- fn foo() { let x = 42; let z = Z(Enum::A(&x as &X)); let _ = z; }
+ fn foo() { let x: int = 42; let z = Z(Enum::A(&x as &X)); let _ = z; }
}
mod b {
}
fn bar() {
- let x = 42;
+ let x: int = 42;
let _y = Y { x: Some(&x as &X) };
}
}
pub trait X { fn f(&self); }
impl X for int { fn f(&self) {} }
pub struct Z<'a>(Option<&'a (X+'a)>);
- fn main() { let x = 42; let z = Z(Some(&x as &X)); let _ = z; }
+ fn main() { let x: int = 42; let z = Z(Some(&x as &X)); let _ = z; }
}
pub fn main() {}
--- /dev/null
+// 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.
+
+// Regression test for #23698: The reassignment checker only cared
+// about the last assigment in a match arm body
+
+// Use an extra function to make sure no extra assignments
+// are introduced by macros in the match statement
+fn check_eq(x: i32, y: i32) {
+ assert_eq!(x, y);
+}
+
+#[allow(unused_assignments)]
+fn main() {
+ let mut x = Box::new(1);
+ match x {
+ y => {
+ x = Box::new(2);
+ let _tmp = 1; // This assignment used to throw off the reassignment checker
+ check_eq(*y, 1);
+ }
+ }
+}
fn main() {
let x: [int; 4] = [1,2,3,4];
- let xptr = x.as_slice() as *const _;
+ let xptr = x.as_slice() as *const [int];
xptr.foo();
}
}
fn main() {
- let x = box 22 as Box<Wrap>;
+ let x = box 22isize as Box<Wrap>;
println!("x={}", x.get());
let y = x.wrap();
}
}
pub fn main() {
- let mut x = 22;
+ let mut x: uint = 22;
let obj = &mut x as &mut Foo;
do_it_mut(obj);
do_it_imm(obj, 23);
struct G<A>(PhantomData<A>);
impl<'a, A: Add<i32, Output=i32>> Fn<(A,)> for G<A> {
- type Output = i32;
-
extern "rust-call" fn call(&self, (arg,): (A,)) -> i32 {
arg.add(1)
}
}
+impl<'a, A: Add<i32, Output=i32>> FnMut<(A,)> for G<A> {
+ extern "rust-call" fn call_mut(&mut self, args: (A,)) -> i32 { self.call(args) }
+}
+
+impl<'a, A: Add<i32, Output=i32>> FnOnce<(A,)> for G<A> {
+ type Output = i32;
+ extern "rust-call" fn call_once(self, args: (A,)) -> i32 { self.call(args) }
+}
+
fn main() {
// ICE trigger
(G(PhantomData))(1);
}
impl FnMut<(i32,)> for S1 {
- type Output = i32;
extern "rust-call" fn call_mut(&mut self, (z,): (i32,)) -> i32 {
self.x * self.y * z
}
}
+impl FnOnce<(i32,)> for S1 {
+ type Output = i32;
+ extern "rust-call" fn call_once(mut self, args: (i32,)) -> i32 {
+ self.call_mut(args)
+ }
+}
+
struct S2 {
x: i32,
y: i32,
}
impl Fn<(i32,)> for S2 {
- type Output = i32;
extern "rust-call" fn call(&self, (z,): (i32,)) -> i32 {
self.x * self.y * z
}
}
+impl FnMut<(i32,)> for S2 {
+ extern "rust-call" fn call_mut(&mut self, args: (i32,)) -> i32 { self.call(args) }
+}
+
+impl FnOnce<(i32,)> for S2 {
+ type Output = i32;
+ extern "rust-call" fn call_once(self, args: (i32,)) -> i32 { self.call(args) }
+}
+
struct S3 {
x: i32,
y: i32,
}
impl FnMut<()> for S {
- type Output = i32;
extern "rust-call" fn call_mut(&mut self, (): ()) -> i32 {
self.x * self.y
}
}
+impl FnOnce<()> for S {
+ type Output = i32;
+ extern "rust-call" fn call_once(mut self, args: ()) -> i32 { self.call_mut(args) }
+}
+
fn main() {
let mut s = S {
x: 3,
}
impl<'t> MakerTrait for Box<Trait<'t>+'static> {
- fn mk() -> Box<Trait<'t>+'static> { box() (4,5) as Box<Trait> }
+ fn mk() -> Box<Trait<'t>+'static> {
+ let tup: Box<(int, int)> = box() (4,5);
+ tup as Box<Trait>
+ }
}
enum List<'l> {
// Be sure that when a SIGPIPE would have been received that the entire process
// doesn't die in a ball of fire, but rather it's gracefully handled.
+// ignore-aarch64
// pretty-expanded FIXME #23616
use std::env;
// pretty-expanded FIXME #23616
pub fn main() {
- let foo = 1;
+ let foo: int = 1;
assert_eq!(&foo as *const int, &foo as *const int);
}
pub fn main() {
let (tx, rx) = channel::<uint>();
- let x: Box<_> = box 1;
+ let x: Box<int> = box 1;
let x_in_parent = &(*x) as *const int as uint;
let _t = Thread::spawn(move || {
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-// aux-build:trait-safety-lib.rs
+// aux-build:trait_safety_lib.rs
// Simple smoke test that unsafe traits can be compiled across crates.
// pretty-expanded FIXME #23616
-extern crate "trait-safety-lib" as lib;
+extern crate trait_safety_lib as lib;
use lib::Foo;
--- /dev/null
+// 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.
+
+// Test that all coercions can actually be done using casts (modulo the lints).
+
+#![allow(trivial_casts, trivial_numeric_casts)]
+
+trait Foo {
+ fn foo(&self) {}
+}
+
+pub struct Bar;
+
+impl Foo for Bar {}
+
+pub fn main() {
+ // Numeric
+ let _ = 42_i32 as i32;
+ let _ = 42_u8 as u8;
+
+ // & to * pointers
+ let x: &u32 = &42;
+ let _ = x as *const u32;
+
+ let x: &mut u32 = &mut 42;
+ let _ = x as *mut u32;
+
+ // unsize array
+ let x: &[u32; 3] = &[42, 43, 44];
+ let _ = x as &[u32];
+ let _ = x as *const [u32];
+
+ let x: &mut [u32; 3] = &mut [42, 43, 44];
+ let _ = x as &mut [u32];
+ let _ = x as *mut [u32];
+
+ let x: Box<[u32; 3]> = Box::new([42, 43, 44]);
+ let _ = x as Box<[u32]>;
+
+ // unsize trait
+ let x: &Bar = &Bar;
+ let _ = x as &Foo;
+ let _ = x as *const Foo;
+
+ let x: &mut Bar = &mut Bar;
+ let _ = x as &mut Foo;
+ let _ = x as *mut Foo;
+
+ let x: Box<Bar> = Box::new(Bar);
+ let _ = x as Box<Foo>;
+
+ // functions
+ fn baz(_x: i32) {}
+ let _ = &baz as &Fn(i32);
+ let x = |_x: i32| {};
+ let _ = &x as &Fn(i32);
+}
+
+// subtyping
+pub fn test_subtyping<'a, 'b: 'a>(a: &'a Bar, b: &'b Bar) {
+ let _ = a as &'a Bar;
+ let _ = b as &'a Bar;
+ let _ = b as &'b Bar;
+}
// pretty-expanded FIXME #23616
struct TestStruct {
- x: *const int
+ x: *const isize
}
unsafe impl Sync for TestStruct {}
-static CONSTEXPR: TestStruct = TestStruct{x: &413 as *const _};
+static CONSTEXPR: TestStruct = TestStruct{ x: &413 };
pub fn main() {
let x: Vec<_> = (0..5).collect();
- let expected: &[uint] = &[0,1,2,3,4];
+ let expected: &[usize] = &[0,1,2,3,4];
assert_eq!(x, expected);
let x = (0..5).collect::<Vec<_>>();
let y: _ = "hello";
assert_eq!(y.len(), 5);
- let ptr = &5;
+ let ptr: &usize = &5;
let ptr2 = ptr as *const _;
- assert_eq!(ptr as *const uint as uint, ptr2 as uint);
+ assert_eq!(ptr as *const usize as usize, ptr2 as usize);
}
struct S;
impl Fn<(i32,)> for S {
- type Output = i32;
extern "rust-call" fn call(&self, (x,): (i32,)) -> i32 {
x * x
}
}
+impl FnMut<(i32,)> for S {
+ extern "rust-call" fn call_mut(&mut self, args: (i32,)) -> i32 { self.call(args) }
+}
+
+impl FnOnce<(i32,)> for S {
+ type Output = i32;
+ extern "rust-call" fn call_once(self, args: (i32,)) -> i32 { self.call(args) }
+}
+
fn call_it<F:Fn(i32)->i32>(f: &F, x: i32) -> i32 {
f(x)
}
struct S;
impl FnMut<(i32,)> for S {
- type Output = i32;
-
extern "rust-call" fn call_mut(&mut self, (x,): (i32,)) -> i32 {
x * x
}
}
+impl FnOnce<(i32,)> for S {
+ type Output = i32;
+
+ extern "rust-call" fn call_once(mut self, args: (i32,)) -> i32 { self.call_mut(args) }
+}
+
fn call_it_mut<F:FnMut(i32)->i32>(f: &mut F, x: i32) -> i32 {
f(x)
}
}
impl<A,R,F : Fn(&Fn(A) -> R, A) -> R> Fn<(A,)> for YCombinator<F,A,R> {
- type Output = R;
-
extern "rust-call" fn call(&self, (arg,): (A,)) -> R {
(self.func)(self, arg)
}
}
+impl<A,R,F : Fn(&Fn(A) -> R, A) -> R> FnMut<(A,)> for YCombinator<F,A,R> {
+ extern "rust-call" fn call_mut(&mut self, args: (A,)) -> R { self.call(args) }
+}
+
+impl<A,R,F : Fn(&Fn(A) -> R, A) -> R> FnOnce<(A,)> for YCombinator<F,A,R> {
+ type Output = R;
+ extern "rust-call" fn call_once(self, args: (A,)) -> R { self.call(args) }
+}
+
fn main() {
let factorial = |recur: &Fn(u32) -> u32, arg: u32| -> u32 {
if arg == 0 {1} else {arg * recur(arg-1)}
struct S;
impl FnMut<(i32,)> for S {
- type Output = i32;
-
extern "rust-call" fn call_mut(&mut self, (x,): (i32,)) -> i32 {
x * x
}
}
+impl FnOnce<(i32,)> for S {
+ type Output = i32;
+
+ extern "rust-call" fn call_once(mut self, args: (i32,)) -> i32 { self.call_mut(args) }
+}
+
fn call_it<F:FnMut(i32)->i32>(mut f: F, x: i32) -> i32 {
f(x) + 3
}
// The subslice used to go out of bounds for zero-sized array items, check that this doesn't
// happen anymore
match x {
- [_, y..] => assert_eq!(&x[1] as *const _, &y[0] as *const _)
+ [_, y..] => assert_eq!(&x[1] as *const (), &y[0] as *const ())
}
}