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

This commit is contained in:
bors 2015-02-24 09:33:17 +00:00
commit dccdde4007
113 changed files with 1401 additions and 948 deletions

View file

@ -2165,7 +2165,7 @@ fn needs_foo_or_bar() {
// This function is only included when compiling for a unixish OS with a 32-bit
// architecture
#[cfg(all(unix, target_word_size = "32"))]
#[cfg(all(unix, target_pointer_width = "32"))]
fn on_32bit_unix() {
// ...
}
@ -2193,9 +2193,9 @@ The following configurations must be defined by the implementation:
* `target_os = "..."`. Operating system of the target, examples include
`"win32"`, `"macos"`, `"linux"`, `"android"`, `"freebsd"`, `"dragonfly"`,
`"bitrig"` or `"openbsd"`.
* `target_word_size = "..."`. Target word size in bits. This is set to `"32"`
for targets with 32-bit pointers, and likewise set to `"64"` for 64-bit
pointers.
* `target_pointer_width = "..."`. Target pointer width in bits. This is set
to `"32"` for targets with 32-bit pointers, and likewise set to `"64"` for
64-bit pointers.
* `unix`. See `target_family`.
* `windows`. See `target_family`.

View file

@ -56,6 +56,7 @@
/* General structure */
body {
background-color: white;
margin: 0 auto;
padding: 0 15px;
font-family: "Source Serif Pro", Georgia, Times, "Times New Roman", serif;

View file

@ -361,16 +361,16 @@ duration a *lifetime*. Let's try a more complex example:
```{rust}
fn main() {
let x = &mut 5;
let mut x = 5;
if *x < 10 {
if x < 10 {
let y = &x;
println!("Oh no: {}", y);
return;
}
*x -= 1;
x -= 1;
println!("Oh no: {}", x);
}
@ -382,17 +382,18 @@ mutated, and therefore, lets us pass. This wouldn't work:
```{rust,ignore}
fn main() {
let x = &mut 5;
let mut x = 5;
if *x < 10 {
if x < 10 {
let y = &x;
*x -= 1;
x -= 1;
println!("Oh no: {}", y);
return;
}
*x -= 1;
x -= 1;
println!("Oh no: {}", x);
}
@ -401,12 +402,12 @@ fn main() {
It gives this error:
```text
test.rs:5:8: 5:10 error: cannot assign to `*x` because it is borrowed
test.rs:5 *x -= 1;
^~
test.rs:4:16: 4:18 note: borrow of `*x` occurs here
test.rs:4 let y = &x;
^~
test.rs:7:9: 7:15 error: cannot assign to `x` because it is borrowed
test.rs:7 x -= 1;
^~~~~~
test.rs:5:18: 5:19 note: borrow of `x` occurs here
test.rs:5 let y = &x;
^
```
As you might guess, this kind of analysis is complex for a human, and therefore

View file

@ -93,8 +93,8 @@ dynamic dispatch is sometimes more efficient.
However, the common case is that it is more efficient to use static dispatch,
and one can always have a thin statically-dispatched wrapper function that does
a dynamic, but not vice versa, meaning static calls are more flexible. The
standard library tries to be statically dispatched where possible for this
a dynamic dispatch, but not vice versa, meaning static calls are more flexible.
The standard library tries to be statically dispatched where possible for this
reason.
## Dynamic dispatch

View file

@ -132,7 +132,7 @@ impl<T> ToOwned for T where T: Clone {
/// ```rust
/// use std::borrow::Cow;
///
/// fn abs_all(input: &mut Cow<[int]>) {
/// fn abs_all(input: &mut Cow<[i32]>) {
/// for i in 0..input.len() {
/// let v = input[i];
/// if v < 0 {

View file

@ -404,7 +404,7 @@
#![stable(feature = "rust1", since = "1.0.0")]
pub use core::fmt::{Formatter, Result, Write, rt};
pub use core::fmt::{Show, String, Octal, Binary};
pub use core::fmt::{Octal, Binary};
pub use core::fmt::{Display, Debug};
pub use core::fmt::{LowerHex, UpperHex, Pointer};
pub use core::fmt::{LowerExp, UpperExp};

View file

@ -40,10 +40,10 @@ pub enum ExponentFormat {
pub enum SignificantDigits {
/// At most the given number of digits will be printed, truncating any
/// trailing zeroes.
DigMax(uint),
DigMax(usize),
/// Precisely the given number of digits will be printed.
DigExact(uint)
DigExact(usize)
}
/// How to emit the sign of a number.
@ -240,27 +240,27 @@ pub fn float_to_str_bytes_common<T: Float, U, F>(
// If reached left end of number, have to
// insert additional digit:
if i < 0
|| buf[i as uint] == b'-'
|| buf[i as uint] == b'+' {
for j in (i as uint + 1..end).rev() {
|| buf[i as usize] == b'-'
|| buf[i as usize] == b'+' {
for j in (i as usize + 1..end).rev() {
buf[j + 1] = buf[j];
}
buf[(i + 1) as uint] = value2ascii(1);
buf[(i + 1) as usize] = value2ascii(1);
end += 1;
break;
}
// Skip the '.'
if buf[i as uint] == b'.' { i -= 1; continue; }
if buf[i as usize] == b'.' { i -= 1; continue; }
// Either increment the digit,
// or set to 0 if max and carry the 1.
let current_digit = ascii2value(buf[i as uint]);
let current_digit = ascii2value(buf[i as usize]);
if current_digit < (radix - 1) {
buf[i as uint] = value2ascii(current_digit+1);
buf[i as usize] = value2ascii(current_digit+1);
break;
} else {
buf[i as uint] = value2ascii(0);
buf[i as usize] = value2ascii(0);
i -= 1;
}
}
@ -311,7 +311,7 @@ pub fn float_to_str_bytes_common<T: Float, U, F>(
struct Filler<'a> {
buf: &'a mut [u8],
end: &'a mut uint,
end: &'a mut usize,
}
impl<'a> fmt::Write for Filler<'a> {

View file

@ -110,11 +110,14 @@ pub trait Write {
/// traits.
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Formatter<'a> {
flags: uint,
#[cfg(not(stage0))]
flags: u32,
#[cfg(stage0)]
flags: usize,
fill: char,
align: rt::v1::Alignment,
width: Option<uint>,
precision: Option<uint>,
width: Option<usize>,
precision: Option<usize>,
buf: &'a mut (Write+'a),
curarg: slice::Iter<'a, ArgumentV1<'a>>,
@ -140,7 +143,7 @@ pub struct ArgumentV1<'a> {
impl<'a> ArgumentV1<'a> {
#[inline(never)]
fn show_uint(x: &uint, f: &mut Formatter) -> Result {
fn show_usize(x: &usize, f: &mut Formatter) -> Result {
Display::fmt(x, f)
}
@ -156,15 +159,22 @@ impl<'a> ArgumentV1<'a> {
}
}
#[cfg(stage0)]
#[doc(hidden)]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn from_uint(x: &uint) -> ArgumentV1 {
ArgumentV1::new(x, ArgumentV1::show_uint)
ArgumentV1::new(x, ArgumentV1::show_usize)
}
#[cfg(not(stage0))]
#[doc(hidden)]
#[stable(feature = "rust1", since = "1.0.0")]
pub fn from_usize(x: &usize) -> ArgumentV1 {
ArgumentV1::new(x, ArgumentV1::show_usize)
}
fn as_uint(&self) -> Option<uint> {
if self.formatter as uint == ArgumentV1::show_uint as uint {
Some(unsafe { *(self.value as *const _ as *const uint) })
fn as_usize(&self) -> Option<usize> {
if self.formatter as usize == ArgumentV1::show_usize as usize {
Some(unsafe { *(self.value as *const _ as *const usize) })
} else {
None
}
@ -194,7 +204,7 @@ impl<'a> Arguments<'a> {
/// The `pieces` array must be at least as long as `fmt` to construct
/// a valid Arguments structure. Also, any `Count` within `fmt` that is
/// `CountIsParam` or `CountIsNextParam` has to point to an argument
/// created with `argumentuint`. However, failing to do so doesn't cause
/// created with `argumentusize`. However, failing to do so doesn't cause
/// unsafety, but will ignore invalid .
#[doc(hidden)] #[inline]
#[stable(feature = "rust1", since = "1.0.0")]
@ -246,16 +256,6 @@ impl<'a> Display for Arguments<'a> {
}
}
/// Format trait for the `:?` format. Useful for debugging, all types
/// should implement this.
#[deprecated(since = "1.0.0", reason = "renamed to Debug")]
#[unstable(feature = "old_fmt")]
pub trait Show {
/// Formats the value using the given formatter.
#[stable(feature = "rust1", since = "1.0.0")]
fn fmt(&self, &mut Formatter) -> Result;
}
/// Format trait for the `:?` format. Useful for debugging, all types
/// should implement this.
#[stable(feature = "rust1", since = "1.0.0")]
@ -269,22 +269,6 @@ pub trait Debug {
fn fmt(&self, &mut Formatter) -> Result;
}
#[allow(deprecated)]
impl<T: Show + ?Sized> Debug for T {
#[allow(deprecated)]
fn fmt(&self, f: &mut Formatter) -> Result { Show::fmt(self, f) }
}
/// When a value can be semantically expressed as a String, this trait may be
/// used. It corresponds to the default format, `{}`.
#[deprecated(since = "1.0.0", reason = "renamed to Display")]
#[unstable(feature = "old_fmt")]
pub trait String {
/// Formats the value using the given formatter.
#[stable(feature = "rust1", since = "1.0.0")]
fn fmt(&self, &mut Formatter) -> Result;
}
/// When a value can be semantically expressed as a String, this trait may be
/// used. It corresponds to the default format, `{}`.
#[rustc_on_unimplemented = "`{Self}` cannot be formatted with the default \
@ -297,12 +281,6 @@ pub trait Display {
fn fmt(&self, &mut Formatter) -> Result;
}
#[allow(deprecated)]
impl<T: String + ?Sized> Display for T {
#[allow(deprecated)]
fn fmt(&self, f: &mut Formatter) -> Result { String::fmt(self, f) }
}
/// Format trait for the `o` character
#[stable(feature = "rust1", since = "1.0.0")]
pub trait Octal {
@ -434,15 +412,15 @@ impl<'a> Formatter<'a> {
(value.formatter)(value.value, self)
}
fn getcount(&mut self, cnt: &rt::v1::Count) -> Option<uint> {
fn getcount(&mut self, cnt: &rt::v1::Count) -> Option<usize> {
match *cnt {
rt::v1::Count::Is(n) => Some(n),
rt::v1::Count::Implied => None,
rt::v1::Count::Param(i) => {
self.args[i].as_uint()
self.args[i].as_usize()
}
rt::v1::Count::NextParam => {
self.curarg.next().and_then(|arg| arg.as_uint())
self.curarg.next().and_then(|arg| arg.as_usize())
}
}
}
@ -476,12 +454,12 @@ impl<'a> Formatter<'a> {
let mut sign = None;
if !is_positive {
sign = Some('-'); width += 1;
} else if self.flags & (1 << (FlagV1::SignPlus as uint)) != 0 {
} else if self.flags & (1 << (FlagV1::SignPlus as u32)) != 0 {
sign = Some('+'); width += 1;
}
let mut prefixed = false;
if self.flags & (1 << (FlagV1::Alternate as uint)) != 0 {
if self.flags & (1 << (FlagV1::Alternate as u32)) != 0 {
prefixed = true; width += prefix.char_len();
}
@ -511,7 +489,7 @@ impl<'a> Formatter<'a> {
}
// The sign and prefix goes before the padding if the fill character
// is zero
Some(min) if self.flags & (1 << (FlagV1::SignAwareZeroPad as uint)) != 0 => {
Some(min) if self.flags & (1 << (FlagV1::SignAwareZeroPad as u32)) != 0 => {
self.fill = '0';
try!(write_prefix(self));
self.with_padding(min - width, Alignment::Right, |f| {
@ -581,7 +559,7 @@ impl<'a> Formatter<'a> {
/// Runs a callback, emitting the correct padding either before or
/// afterwards depending on whether right or left alignment is requested.
fn with_padding<F>(&mut self, padding: uint, default: Alignment,
fn with_padding<F>(&mut self, padding: usize, default: Alignment,
f: F) -> Result
where F: FnOnce(&mut Formatter) -> Result,
{
@ -627,6 +605,11 @@ impl<'a> Formatter<'a> {
write(self.buf, fmt)
}
#[cfg(not(stage0))]
/// Flags for formatting (packed version of rt::Flag)
#[stable(feature = "rust1", since = "1.0.0")]
pub fn flags(&self) -> u32 { self.flags }
#[cfg(stage0)]
/// Flags for formatting (packed version of rt::Flag)
#[stable(feature = "rust1", since = "1.0.0")]
pub fn flags(&self) -> usize { self.flags }
@ -641,11 +624,11 @@ impl<'a> Formatter<'a> {
/// Optionally specified integer width that the output should be
#[unstable(feature = "core", reason = "method was just created")]
pub fn width(&self) -> Option<uint> { self.width }
pub fn width(&self) -> Option<usize> { self.width }
/// Optionally specified precision for numeric types
#[unstable(feature = "core", reason = "method was just created")]
pub fn precision(&self) -> Option<uint> { self.precision }
pub fn precision(&self) -> Option<usize> { self.precision }
}
#[stable(feature = "rust1", since = "1.0.0")]
@ -731,9 +714,9 @@ impl Display for char {
#[stable(feature = "rust1", since = "1.0.0")]
impl<T> Pointer for *const T {
fn fmt(&self, f: &mut Formatter) -> Result {
f.flags |= 1 << (FlagV1::Alternate as uint);
let ret = LowerHex::fmt(&(*self as uint), f);
f.flags &= !(1 << (FlagV1::Alternate as uint));
f.flags |= 1 << (FlagV1::Alternate as u32);
let ret = LowerHex::fmt(&(*self as u32), f);
f.flags &= !(1 << (FlagV1::Alternate as u32));
ret
}
}
@ -889,7 +872,7 @@ impl<'a> Debug for &'a (any::Any+'a) {
#[stable(feature = "rust1", since = "1.0.0")]
impl<T: Debug> Debug for [T] {
fn fmt(&self, f: &mut Formatter) -> Result {
if f.flags & (1 << (FlagV1::Alternate as uint)) == 0 {
if f.flags & (1 << (FlagV1::Alternate as u32)) == 0 {
try!(write!(f, "["));
}
let mut is_first = true;
@ -901,7 +884,7 @@ impl<T: Debug> Debug for [T] {
}
try!(write!(f, "{:?}", *x))
}
if f.flags & (1 << (FlagV1::Alternate as uint)) == 0 {
if f.flags & (1 << (FlagV1::Alternate as u32)) == 0 {
try!(write!(f, "]"));
}
Ok(())

View file

@ -214,7 +214,7 @@ macro_rules! integer {
show! { $Uint with $SU }
}
}
integer! { int, uint, "i", "u" }
integer! { isize, usize, "i", "u" }
integer! { i8, u8 }
integer! { i16, u16 }
integer! { i32, u32 }

View file

@ -32,8 +32,12 @@ pub struct FormatSpec {
pub fill: char,
#[stable(feature = "rust1", since = "1.0.0")]
pub align: Alignment,
#[cfg(stage0)]
#[stable(feature = "rust1", since = "1.0.0")]
pub flags: uint,
pub flags: usize,
#[cfg(not(stage0))]
#[stable(feature = "rust1", since = "1.0.0")]
pub flags: u32,
#[stable(feature = "rust1", since = "1.0.0")]
pub precision: Count,
#[stable(feature = "rust1", since = "1.0.0")]

View file

@ -20,7 +20,7 @@
//!
//! #[derive(Hash)]
//! struct Person {
//! id: uint,
//! id: u32,
//! name: String,
//! phone: u64,
//! }
@ -38,7 +38,7 @@
//! use std::hash::{hash, Hash, Hasher, SipHasher};
//!
//! struct Person {
//! id: uint,
//! id: u32,
//! name: String,
//! phone: u64,
//! }

View file

@ -34,13 +34,13 @@ use super::Hasher;
pub struct SipHasher {
k0: u64,
k1: u64,
length: uint, // how many bytes we've processed
length: usize, // how many bytes we've processed
v0: u64, // hash state
v1: u64,
v2: u64,
v3: u64,
tail: u64, // unprocessed bytes le
ntail: uint, // how many bytes in tail are valid
ntail: usize, // how many bytes in tail are valid
}
// sadly, these macro definitions can't appear later,

View file

@ -86,6 +86,7 @@ use usize;
#[rustc_on_unimplemented = "`{Self}` is not an iterator; maybe try calling `.iter()` or a similar \
method"]
pub trait Iterator {
/// The type of the elements being iterated
#[stable(feature = "rust1", since = "1.0.0")]
type Item;
@ -122,9 +123,11 @@ pub trait FromIterator<A> {
/// Conversion into an `Iterator`
#[stable(feature = "rust1", since = "1.0.0")]
pub trait IntoIterator {
/// The type of the elements being iterated
#[stable(feature = "rust1", since = "1.0.0")]
type Item;
/// A container for iterating over elements of type Item
#[stable(feature = "rust1", since = "1.0.0")]
type IntoIter: Iterator<Item=Self::Item>;

View file

@ -184,6 +184,7 @@ macro_rules! forward_ref_binop {
#[lang="add"]
#[stable(feature = "rust1", since = "1.0.0")]
pub trait Add<RHS=Self> {
/// The resulting type after applying the `+` operator
#[stable(feature = "rust1", since = "1.0.0")]
type Output;
@ -237,6 +238,7 @@ add_impl! { usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 }
#[lang="sub"]
#[stable(feature = "rust1", since = "1.0.0")]
pub trait Sub<RHS=Self> {
/// The resulting type after applying the `-` operator
#[stable(feature = "rust1", since = "1.0.0")]
type Output;
@ -290,6 +292,7 @@ sub_impl! { usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 }
#[lang="mul"]
#[stable(feature = "rust1", since = "1.0.0")]
pub trait Mul<RHS=Self> {
/// The resulting type after applying the `*` operator
#[stable(feature = "rust1", since = "1.0.0")]
type Output;
@ -343,6 +346,7 @@ mul_impl! { usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 }
#[lang="div"]
#[stable(feature = "rust1", since = "1.0.0")]
pub trait Div<RHS=Self> {
/// The resulting type after applying the `/` operator
#[stable(feature = "rust1", since = "1.0.0")]
type Output;
@ -396,6 +400,7 @@ div_impl! { usize u8 u16 u32 u64 isize i8 i16 i32 i64 f32 f64 }
#[lang="rem"]
#[stable(feature = "rust1", since = "1.0.0")]
pub trait Rem<RHS=Self> {
/// The resulting type after applying the `%` operator
#[stable(feature = "rust1", since = "1.0.0")]
type Output = Self;
@ -468,6 +473,7 @@ rem_float_impl! { f64, fmod }
#[lang="neg"]
#[stable(feature = "rust1", since = "1.0.0")]
pub trait Neg {
/// The resulting type after applying the `-` operator
#[stable(feature = "rust1", since = "1.0.0")]
type Output;
@ -544,6 +550,7 @@ neg_uint_impl! { u64, i64 }
#[lang="not"]
#[stable(feature = "rust1", since = "1.0.0")]
pub trait Not {
/// The resulting type after applying the `!` operator
#[stable(feature = "rust1", since = "1.0.0")]
type Output;
@ -597,6 +604,7 @@ not_impl! { bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 }
#[lang="bitand"]
#[stable(feature = "rust1", since = "1.0.0")]
pub trait BitAnd<RHS=Self> {
/// The resulting type after applying the `&` operator
#[stable(feature = "rust1", since = "1.0.0")]
type Output;
@ -650,6 +658,7 @@ bitand_impl! { bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 }
#[lang="bitor"]
#[stable(feature = "rust1", since = "1.0.0")]
pub trait BitOr<RHS=Self> {
/// The resulting type after applying the `|` operator
#[stable(feature = "rust1", since = "1.0.0")]
type Output;
@ -703,6 +712,7 @@ bitor_impl! { bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 }
#[lang="bitxor"]
#[stable(feature = "rust1", since = "1.0.0")]
pub trait BitXor<RHS=Self> {
/// The resulting type after applying the `^` operator
#[stable(feature = "rust1", since = "1.0.0")]
type Output;
@ -756,6 +766,7 @@ bitxor_impl! { bool usize u8 u16 u32 u64 isize i8 i16 i32 i64 }
#[lang="shl"]
#[stable(feature = "rust1", since = "1.0.0")]
pub trait Shl<RHS> {
/// The resulting type after applying the `<<` operator
#[stable(feature = "rust1", since = "1.0.0")]
type Output;
@ -827,6 +838,7 @@ shl_impl_all! { u8 u16 u32 u64 usize i8 i16 i32 i64 isize }
#[lang="shr"]
#[stable(feature = "rust1", since = "1.0.0")]
pub trait Shr<RHS> {
/// The resulting type after applying the `>>` operator
#[stable(feature = "rust1", since = "1.0.0")]
type Output;
@ -900,6 +912,7 @@ shr_impl_all! { u8 u16 u32 u64 usize i8 i16 i32 i64 isize }
#[rustc_on_unimplemented = "the type `{Self}` cannot be indexed by `{Idx}`"]
#[stable(feature = "rust1", since = "1.0.0")]
pub trait Index<Idx: ?Sized> {
/// The returned type after indexing
type Output: ?Sized;
/// The method for the indexing (`Foo[Bar]`) operation
@ -1047,6 +1060,7 @@ impl<Idx: fmt::Debug> fmt::Debug for RangeTo<Idx> {
#[lang="deref"]
#[stable(feature = "rust1", since = "1.0.0")]
pub trait Deref {
/// The resulting type after dereferencing
#[stable(feature = "rust1", since = "1.0.0")]
type Target: ?Sized;
@ -1122,6 +1136,7 @@ impl<'a, T: ?Sized> DerefMut for &'a mut T {
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_paren_sugar]
pub trait Fn<Args> {
/// The returned type after the call operator is used.
type Output;
/// This is called when the call operator is used.
@ -1133,6 +1148,7 @@ pub trait Fn<Args> {
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_paren_sugar]
pub trait FnMut<Args> {
/// The returned type after the call operator is used.
type Output;
/// This is called when the call operator is used.
@ -1144,6 +1160,7 @@ pub trait FnMut<Args> {
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_paren_sugar]
pub trait FnOnce<Args> {
/// The returned type after the call operator is used.
type Output;
/// This is called when the call operator is used.

View file

@ -249,6 +249,7 @@ pub unsafe fn write<T>(dst: *mut T, src: T) {
/// Methods on raw pointers
#[stable(feature = "rust1", since = "1.0.0")]
pub trait PtrExt: Sized {
/// The type which is being pointed at
type Target;
/// Returns true if the pointer is null.
@ -284,6 +285,7 @@ pub trait PtrExt: Sized {
/// Methods on mutable raw pointers
#[stable(feature = "rust1", since = "1.0.0")]
pub trait MutPtrExt {
/// The type which is being pointed at
type Target;
/// Returns `None` if the pointer is null, or else returns a mutable

View file

@ -24,7 +24,6 @@
html_root_url = "http://doc.rust-lang.org/nightly/",
html_playground_url = "http://play.rust-lang.org/")]
#![feature(int_uint)]
#![feature(staged_api)]
#![feature(unicode)]
@ -65,7 +64,7 @@ pub struct FormatSpec<'a> {
/// Optionally specified alignment
pub align: Alignment,
/// Packed version of various flags provided
pub flags: uint,
pub flags: u32,
/// The integer precision to use
pub precision: Count<'a>,
/// The string width requested for the resulting format
@ -82,7 +81,7 @@ pub enum Position<'a> {
/// The argument will be in the next position. This is the default.
ArgumentNext,
/// The argument is located at a specific index.
ArgumentIs(uint),
ArgumentIs(usize),
/// The argument has a name.
ArgumentNamed(&'a str),
}
@ -121,11 +120,11 @@ pub enum Flag {
#[derive(Copy, PartialEq)]
pub enum Count<'a> {
/// The count is specified explicitly.
CountIs(uint),
CountIs(usize),
/// The count is specified by the argument with the given name.
CountIsName(&'a str),
/// The count is specified by the argument at the given index.
CountIsParam(uint),
CountIsParam(usize),
/// The count is specified by the next parameter.
CountIsNextParam,
/// The count is implied and cannot be explicitly specified.
@ -237,7 +236,7 @@ impl<'a> Parser<'a> {
/// Parses all of a string which is to be considered a "raw literal" in a
/// format string. This is everything outside of the braces.
fn string(&mut self, start: uint) -> &'a str {
fn string(&mut self, start: usize) -> &'a str {
loop {
// we may not consume the character, so clone the iterator
match self.cur.clone().next() {
@ -314,13 +313,13 @@ impl<'a> Parser<'a> {
}
// Sign flags
if self.consume('+') {
spec.flags |= 1 << (FlagSignPlus as uint);
spec.flags |= 1 << (FlagSignPlus as u32);
} else if self.consume('-') {
spec.flags |= 1 << (FlagSignMinus as uint);
spec.flags |= 1 << (FlagSignMinus as u32);
}
// Alternate marker
if self.consume('#') {
spec.flags |= 1 << (FlagAlternate as uint);
spec.flags |= 1 << (FlagAlternate as u32);
}
// Width and precision
let mut havewidth = false;
@ -333,7 +332,7 @@ impl<'a> Parser<'a> {
spec.width = CountIsParam(0);
havewidth = true;
} else {
spec.flags |= 1 << (FlagSignAwareZeroPad as uint);
spec.flags |= 1 << (FlagSignAwareZeroPad as u32);
}
}
if !havewidth {
@ -413,7 +412,7 @@ impl<'a> Parser<'a> {
/// Optionally parses an integer at the current position. This doesn't deal
/// with overflow at all, it's just accumulating digits.
fn integer(&mut self) -> Option<uint> {
fn integer(&mut self) -> Option<usize> {
let mut cur = 0;
let mut found = false;
loop {
@ -617,7 +616,7 @@ mod tests {
format: FormatSpec {
fill: None,
align: AlignUnknown,
flags: (1 << FlagSignMinus as uint),
flags: (1 << FlagSignMinus as u32),
precision: CountImplied,
width: CountImplied,
ty: "",
@ -628,7 +627,7 @@ mod tests {
format: FormatSpec {
fill: None,
align: AlignUnknown,
flags: (1 << FlagSignPlus as uint) | (1 << FlagAlternate as uint),
flags: (1 << FlagSignPlus as u32) | (1 << FlagAlternate as u32),
precision: CountImplied,
width: CountImplied,
ty: "",

View file

@ -1577,6 +1577,14 @@ impl LintPass for MissingDoc {
tm.span, "a type method");
}
fn check_trait_method(&mut self, cx: &Context, it: &ast::TraitItem) {
if let ast::TraitItem::TypeTraitItem(ref ty) = *it {
let assoc_ty = &ty.ty_param;
self.check_missing_docs_attrs(cx, Some(assoc_ty.id), &ty.attrs,
assoc_ty.span, "an associated type");
}
}
fn check_struct_field(&mut self, cx: &Context, sf: &ast::StructField) {
if let ast::NamedField(_, vis) = sf.node.kind {
if vis == ast::Public || self.in_variant {
@ -1848,7 +1856,7 @@ impl LintPass for UnconditionalRecursion {
continue
}
visited.insert(cfg_id);
let node_id = cfg.graph.node_data(idx).id;
let node_id = cfg.graph.node_data(idx).id();
// is this a recursive call?
if node_id != ast::DUMMY_NODE_ID && checker(cx.tcx, impl_node_id, id, name, node_id) {

View file

@ -153,9 +153,6 @@ pub fn enc_ty<'a, 'tcx>(w: &mut SeekableMemWriter, cx: &ctxt<'a, 'tcx>, t: Ty<'t
ty::ty_err => {
mywrite!(w, "e");
}
ty::ty_open(_) => {
cx.diag.handler().bug("unexpected type in enc_sty (ty_open)");
}
}
let end = w.tell().unwrap();

View file

@ -11,16 +11,15 @@
use middle::cfg::*;
use middle::def;
use middle::graph;
use middle::pat_util;
use middle::region::CodeExtent;
use middle::ty;
use syntax::ast;
use syntax::ast_util;
use syntax::ptr::P;
use util::nodemap::NodeMap;
struct CFGBuilder<'a, 'tcx: 'a> {
tcx: &'a ty::ctxt<'tcx>,
exit_map: NodeMap<CFGIndex>,
graph: CFGGraph,
fn_exit: CFGIndex,
loop_scopes: Vec<LoopScope>,
@ -36,17 +35,16 @@ struct LoopScope {
pub fn construct(tcx: &ty::ctxt,
blk: &ast::Block) -> CFG {
let mut graph = graph::Graph::new();
let entry = add_initial_dummy_node(&mut graph);
let entry = graph.add_node(CFGNodeData::Entry);
// `fn_exit` is target of return exprs, which lies somewhere
// outside input `blk`. (Distinguishing `fn_exit` and `block_exit`
// also resolves chicken-and-egg problem that arises if you try to
// have return exprs jump to `block_exit` during construction.)
let fn_exit = add_initial_dummy_node(&mut graph);
let fn_exit = graph.add_node(CFGNodeData::Exit);
let block_exit;
let mut cfg_builder = CFGBuilder {
exit_map: NodeMap(),
graph: graph,
fn_exit: fn_exit,
tcx: tcx,
@ -54,17 +52,12 @@ pub fn construct(tcx: &ty::ctxt,
};
block_exit = cfg_builder.block(blk, entry);
cfg_builder.add_contained_edge(block_exit, fn_exit);
let CFGBuilder {exit_map, graph, ..} = cfg_builder;
CFG {exit_map: exit_map,
graph: graph,
let CFGBuilder {graph, ..} = cfg_builder;
CFG {graph: graph,
entry: entry,
exit: fn_exit}
}
fn add_initial_dummy_node(g: &mut CFGGraph) -> CFGIndex {
g.add_node(CFGNodeData { id: ast::DUMMY_NODE_ID })
}
impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
fn block(&mut self, blk: &ast::Block, pred: CFGIndex) -> CFGIndex {
let mut stmts_exit = pred;
@ -74,19 +67,19 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
let expr_exit = self.opt_expr(&blk.expr, stmts_exit);
self.add_node(blk.id, &[expr_exit])
self.add_ast_node(blk.id, &[expr_exit])
}
fn stmt(&mut self, stmt: &ast::Stmt, pred: CFGIndex) -> CFGIndex {
match stmt.node {
ast::StmtDecl(ref decl, id) => {
let exit = self.decl(&**decl, pred);
self.add_node(id, &[exit])
self.add_ast_node(id, &[exit])
}
ast::StmtExpr(ref expr, id) | ast::StmtSemi(ref expr, id) => {
let exit = self.expr(&**expr, pred);
self.add_node(id, &[exit])
self.add_ast_node(id, &[exit])
}
ast::StmtMac(..) => {
@ -115,33 +108,33 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
ast::PatLit(..) |
ast::PatRange(..) |
ast::PatWild(_) => {
self.add_node(pat.id, &[pred])
self.add_ast_node(pat.id, &[pred])
}
ast::PatBox(ref subpat) |
ast::PatRegion(ref subpat, _) |
ast::PatIdent(_, _, Some(ref subpat)) => {
let subpat_exit = self.pat(&**subpat, pred);
self.add_node(pat.id, &[subpat_exit])
self.add_ast_node(pat.id, &[subpat_exit])
}
ast::PatEnum(_, Some(ref subpats)) |
ast::PatTup(ref subpats) => {
let pats_exit = self.pats_all(subpats.iter(), pred);
self.add_node(pat.id, &[pats_exit])
self.add_ast_node(pat.id, &[pats_exit])
}
ast::PatStruct(_, ref subpats, _) => {
let pats_exit =
self.pats_all(subpats.iter().map(|f| &f.node.pat), pred);
self.add_node(pat.id, &[pats_exit])
self.add_ast_node(pat.id, &[pats_exit])
}
ast::PatVec(ref pre, ref vec, ref post) => {
let pre_exit = self.pats_all(pre.iter(), pred);
let vec_exit = self.pats_all(vec.iter(), pre_exit);
let post_exit = self.pats_all(post.iter(), vec_exit);
self.add_node(pat.id, &[post_exit])
self.add_ast_node(pat.id, &[post_exit])
}
ast::PatMac(_) => {
@ -157,28 +150,11 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
pats.fold(pred, |pred, pat| self.pat(&**pat, pred))
}
fn pats_any(&mut self,
pats: &[P<ast::Pat>],
pred: CFGIndex) -> CFGIndex {
//! Handles case where just one of the patterns must match.
if pats.len() == 1 {
self.pat(&*pats[0], pred)
} else {
let collect = self.add_dummy_node(&[]);
for pat in pats {
let pat_exit = self.pat(&**pat, pred);
self.add_contained_edge(pat_exit, collect);
}
collect
}
}
fn expr(&mut self, expr: &ast::Expr, pred: CFGIndex) -> CFGIndex {
match expr.node {
ast::ExprBlock(ref blk) => {
let blk_exit = self.block(&**blk, pred);
self.add_node(expr.id, &[blk_exit])
self.add_ast_node(expr.id, &[blk_exit])
}
ast::ExprIf(ref cond, ref then, None) => {
@ -198,7 +174,7 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
//
let cond_exit = self.expr(&**cond, pred); // 1
let then_exit = self.block(&**then, cond_exit); // 2
self.add_node(expr.id, &[cond_exit, then_exit]) // 3,4
self.add_ast_node(expr.id, &[cond_exit, then_exit]) // 3,4
}
ast::ExprIf(ref cond, ref then, Some(ref otherwise)) => {
@ -219,7 +195,7 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
let cond_exit = self.expr(&**cond, pred); // 1
let then_exit = self.block(&**then, cond_exit); // 2
let else_exit = self.expr(&**otherwise, cond_exit); // 3
self.add_node(expr.id, &[then_exit, else_exit]) // 4, 5
self.add_ast_node(expr.id, &[then_exit, else_exit]) // 4, 5
}
ast::ExprIfLet(..) => {
@ -247,7 +223,7 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
// Is the condition considered part of the loop?
let loopback = self.add_dummy_node(&[pred]); // 1
let cond_exit = self.expr(&**cond, loopback); // 2
let expr_exit = self.add_node(expr.id, &[cond_exit]); // 3
let expr_exit = self.add_ast_node(expr.id, &[cond_exit]); // 3
self.loop_scopes.push(LoopScope {
loop_id: expr.id,
continue_index: loopback,
@ -283,7 +259,7 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
// may cause additional edges.
let loopback = self.add_dummy_node(&[pred]); // 1
let expr_exit = self.add_node(expr.id, &[]); // 2
let expr_exit = self.add_ast_node(expr.id, &[]); // 2
self.loop_scopes.push(LoopScope {
loop_id: expr.id,
continue_index: loopback,
@ -296,45 +272,7 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
}
ast::ExprMatch(ref discr, ref arms, _) => {
//
// [pred]
// |
// v 1
// [discr]
// |
// v 2
// [cond1]
// / \
// | \
// v 3 \
// [pat1] \
// | |
// v 4 |
// [guard1] |
// | |
// | |
// v 5 v
// [body1] [cond2]
// | / \
// | ... ...
// | | |
// v 6 v v
// [.....expr.....]
//
let discr_exit = self.expr(&**discr, pred); // 1
let expr_exit = self.add_node(expr.id, &[]);
let mut cond_exit = discr_exit;
for arm in arms {
cond_exit = self.add_dummy_node(&[cond_exit]); // 2
let pats_exit = self.pats_any(&arm.pats,
cond_exit); // 3
let guard_exit = self.opt_expr(&arm.guard,
pats_exit); // 4
let body_exit = self.expr(&*arm.body, guard_exit); // 5
self.add_contained_edge(body_exit, expr_exit); // 6
}
expr_exit
self.match_(expr.id, &discr, &arms, pred)
}
ast::ExprBinary(op, ref l, ref r) if ast_util::lazy_binop(op.node) => {
@ -354,30 +292,30 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
//
let l_exit = self.expr(&**l, pred); // 1
let r_exit = self.expr(&**r, l_exit); // 2
self.add_node(expr.id, &[l_exit, r_exit]) // 3,4
self.add_ast_node(expr.id, &[l_exit, r_exit]) // 3,4
}
ast::ExprRet(ref v) => {
let v_exit = self.opt_expr(v, pred);
let b = self.add_node(expr.id, &[v_exit]);
let b = self.add_ast_node(expr.id, &[v_exit]);
self.add_returning_edge(expr, b);
self.add_node(ast::DUMMY_NODE_ID, &[])
self.add_unreachable_node()
}
ast::ExprBreak(label) => {
let loop_scope = self.find_scope(expr, label);
let b = self.add_node(expr.id, &[pred]);
let b = self.add_ast_node(expr.id, &[pred]);
self.add_exiting_edge(expr, b,
loop_scope, loop_scope.break_index);
self.add_node(ast::DUMMY_NODE_ID, &[])
self.add_unreachable_node()
}
ast::ExprAgain(label) => {
let loop_scope = self.find_scope(expr, label);
let a = self.add_node(expr.id, &[pred]);
let a = self.add_ast_node(expr.id, &[pred]);
self.add_exiting_edge(expr, a,
loop_scope, loop_scope.continue_index);
self.add_node(ast::DUMMY_NODE_ID, &[])
self.add_unreachable_node()
}
ast::ExprVec(ref elems) => {
@ -454,7 +392,7 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
let &(_, ref expr, _) = a;
&**expr
}), post_inputs);
self.add_node(expr.id, &[post_outputs])
self.add_ast_node(expr.id, &[post_outputs])
}
ast::ExprMac(..) |
@ -481,7 +419,7 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
let func_or_rcvr_exit = self.expr(func_or_rcvr, pred);
let ret = self.straightline(call_expr, func_or_rcvr_exit, args);
if return_ty.diverges() {
self.add_node(ast::DUMMY_NODE_ID, &[])
self.add_unreachable_node()
} else {
ret
}
@ -508,20 +446,126 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
//! Handles case of an expression that evaluates `subexprs` in order
let subexprs_exit = self.exprs(subexprs, pred);
self.add_node(expr.id, &[subexprs_exit])
self.add_ast_node(expr.id, &[subexprs_exit])
}
fn match_(&mut self, id: ast::NodeId, discr: &ast::Expr,
arms: &[ast::Arm], pred: CFGIndex) -> CFGIndex {
// The CFG for match expression is quite complex, so no ASCII
// art for it (yet).
//
// The CFG generated below matches roughly what trans puts
// out. Each pattern and guard is visited in parallel, with
// arms containing multiple patterns generating multiple nodes
// for the same guard expression. The guard expressions chain
// into each other from top to bottom, with a specific
// exception to allow some additional valid programs
// (explained below). Trans differs slightly in that the
// pattern matching may continue after a guard but the visible
// behaviour should be the same.
//
// What is going on is explained in further comments.
// Visit the discriminant expression
let discr_exit = self.expr(discr, pred);
// Add a node for the exit of the match expression as a whole.
let expr_exit = self.add_ast_node(id, &[]);
// Keep track of the previous guard expressions
let mut prev_guards = Vec::new();
// Track if the previous pattern contained bindings or wildcards
let mut prev_has_bindings = false;
for arm in arms {
// Add an exit node for when we've visited all the
// patterns and the guard (if there is one) in the arm.
let arm_exit = self.add_dummy_node(&[]);
for pat in &arm.pats {
// Visit the pattern, coming from the discriminant exit
let mut pat_exit = self.pat(&**pat, discr_exit);
// If there is a guard expression, handle it here
if let Some(ref guard) = arm.guard {
// Add a dummy node for the previous guard
// expression to target
let guard_start = self.add_dummy_node(&[pat_exit]);
// Visit the guard expression
let guard_exit = self.expr(&**guard, guard_start);
let this_has_bindings = pat_util::pat_contains_bindings_or_wild(
&self.tcx.def_map, &**pat);
// If both this pattern and the previous pattern
// were free of bindings, they must consist only
// of "constant" patterns. Note we cannot match an
// all-constant pattern, fail the guard, and then
// match *another* all-constant pattern. This is
// because if the previous pattern matches, then
// we *cannot* match this one, unless all the
// constants are the same (which is rejected by
// `check_match`).
//
// We can use this to be smarter about the flow
// along guards. If the previous pattern matched,
// then we know we will not visit the guard in
// this one (whether or not the guard succeeded),
// if the previous pattern failed, then we know
// the guard for that pattern will not have been
// visited. Thus, it is not possible to visit both
// the previous guard and the current one when
// both patterns consist only of constant
// sub-patterns.
//
// However, if the above does not hold, then all
// previous guards need to be wired to visit the
// current guard pattern.
if prev_has_bindings || this_has_bindings {
while let Some(prev) = prev_guards.pop() {
self.add_contained_edge(prev, guard_start);
}
}
prev_has_bindings = this_has_bindings;
// Push the guard onto the list of previous guards
prev_guards.push(guard_exit);
// Update the exit node for the pattern
pat_exit = guard_exit;
}
// Add an edge from the exit of this pattern to the
// exit of the arm
self.add_contained_edge(pat_exit, arm_exit);
}
// Visit the body of this arm
let body_exit = self.expr(&arm.body, arm_exit);
// Link the body to the exit of the expression
self.add_contained_edge(body_exit, expr_exit);
}
expr_exit
}
fn add_dummy_node(&mut self, preds: &[CFGIndex]) -> CFGIndex {
self.add_node(ast::DUMMY_NODE_ID, preds)
self.add_node(CFGNodeData::Dummy, preds)
}
fn add_node(&mut self, id: ast::NodeId, preds: &[CFGIndex]) -> CFGIndex {
assert!(!self.exit_map.contains_key(&id));
let node = self.graph.add_node(CFGNodeData {id: id});
if id != ast::DUMMY_NODE_ID {
assert!(!self.exit_map.contains_key(&id));
self.exit_map.insert(id, node);
}
fn add_ast_node(&mut self, id: ast::NodeId, preds: &[CFGIndex]) -> CFGIndex {
assert!(id != ast::DUMMY_NODE_ID);
self.add_node(CFGNodeData::AST(id), preds)
}
fn add_unreachable_node(&mut self) -> CFGIndex {
self.add_node(CFGNodeData::Unreachable, &[])
}
fn add_node(&mut self, data: CFGNodeData, preds: &[CFGIndex]) -> CFGIndex {
let node = self.graph.add_node(data);
for &pred in preds {
self.add_contained_edge(pred, node);
}

View file

@ -65,10 +65,10 @@ impl<'a, 'ast> dot::Labeller<'a, Node<'a>, Edge<'a>> for LabelledCFG<'a, 'ast> {
dot::LabelText::LabelStr("entry".into_cow())
} else if i == self.cfg.exit {
dot::LabelText::LabelStr("exit".into_cow())
} else if n.data.id == ast::DUMMY_NODE_ID {
} else if n.data.id() == ast::DUMMY_NODE_ID {
dot::LabelText::LabelStr("(dummy_node)".into_cow())
} else {
let s = self.ast_map.node_to_string(n.data.id);
let s = self.ast_map.node_to_string(n.data.id());
// left-aligns the lines
let s = replace_newline_with_backslash_l(s);
dot::LabelText::EscStr(s.into_cow())

View file

@ -14,21 +14,33 @@
use middle::graph;
use middle::ty;
use syntax::ast;
use util::nodemap::NodeMap;
mod construct;
pub mod graphviz;
pub struct CFG {
pub exit_map: NodeMap<CFGIndex>,
pub graph: CFGGraph,
pub entry: CFGIndex,
pub exit: CFGIndex,
}
#[derive(Copy)]
pub struct CFGNodeData {
pub id: ast::NodeId
#[derive(Copy, PartialEq)]
pub enum CFGNodeData {
AST(ast::NodeId),
Entry,
Exit,
Dummy,
Unreachable,
}
impl CFGNodeData {
pub fn id(&self) -> ast::NodeId {
if let CFGNodeData::AST(id) = *self {
id
} else {
ast::DUMMY_NODE_ID
}
}
}
pub struct CFGEdgeData {
@ -50,6 +62,6 @@ impl CFG {
}
pub fn node_is_reachable(&self, id: ast::NodeId) -> bool {
self.graph.depth_traverse(self.entry).any(|node| node.id == id)
self.graph.depth_traverse(self.entry).any(|node| node.id() == id)
}
}

View file

@ -53,7 +53,7 @@ pub struct DataFlowContext<'a, 'tcx: 'a, O> {
// mapping from node to cfg node index
// FIXME (#6298): Shouldn't this go with CFG?
nodeid_to_index: NodeMap<CFGIndex>,
nodeid_to_index: NodeMap<Vec<CFGIndex>>,
// Bit sets per cfg node. The following three fields (`gens`, `kills`,
// and `on_entry`) all have the same structure. For each id in
@ -88,11 +88,9 @@ struct PropagationContext<'a, 'b: 'a, 'tcx: 'b, O: 'a> {
changed: bool
}
fn to_cfgidx_or_die(id: ast::NodeId, index: &NodeMap<CFGIndex>) -> CFGIndex {
let opt_cfgindex = index.get(&id).cloned();
opt_cfgindex.unwrap_or_else(|| {
panic!("nodeid_to_index does not have entry for NodeId {}", id);
})
fn get_cfg_indices<'a>(id: ast::NodeId, index: &'a NodeMap<Vec<CFGIndex>>) -> &'a [CFGIndex] {
let opt_indices = index.get(&id);
opt_indices.map(|v| &v[..]).unwrap_or(&[])
}
impl<'a, 'tcx, O:DataFlowOperator> DataFlowContext<'a, 'tcx, O> {
@ -114,9 +112,13 @@ impl<'a, 'tcx, O:DataFlowOperator> pprust::PpAnn for DataFlowContext<'a, 'tcx, O
pprust::NodePat(pat) => pat.id
};
if self.has_bitset_for_nodeid(id) {
assert!(self.bits_per_id > 0);
let cfgidx = to_cfgidx_or_die(id, &self.nodeid_to_index);
if !self.has_bitset_for_nodeid(id) {
return Ok(());
}
assert!(self.bits_per_id > 0);
let indices = get_cfg_indices(id, &self.nodeid_to_index);
for &cfgidx in indices {
let (start, end) = self.compute_id_range(cfgidx);
let on_entry = &self.on_entry[start.. end];
let entry_str = bits_to_string(on_entry);
@ -144,7 +146,7 @@ impl<'a, 'tcx, O:DataFlowOperator> pprust::PpAnn for DataFlowContext<'a, 'tcx, O
}
fn build_nodeid_to_index(decl: Option<&ast::FnDecl>,
cfg: &cfg::CFG) -> NodeMap<CFGIndex> {
cfg: &cfg::CFG) -> NodeMap<Vec<CFGIndex>> {
let mut index = NodeMap();
// FIXME (#6298): Would it be better to fold formals from decl
@ -157,28 +159,38 @@ fn build_nodeid_to_index(decl: Option<&ast::FnDecl>,
}
cfg.graph.each_node(|node_idx, node| {
if node.data.id != ast::DUMMY_NODE_ID {
index.insert(node.data.id, node_idx);
if let cfg::CFGNodeData::AST(id) = node.data {
match index.entry(id).get() {
Ok(v) => v.push(node_idx),
Err(e) => {
e.insert(vec![node_idx]);
}
}
}
true
});
return index;
fn add_entries_from_fn_decl(index: &mut NodeMap<CFGIndex>,
fn add_entries_from_fn_decl(index: &mut NodeMap<Vec<CFGIndex>>,
decl: &ast::FnDecl,
entry: CFGIndex) {
//! add mappings from the ast nodes for the formal bindings to
//! the entry-node in the graph.
struct Formals<'a> {
entry: CFGIndex,
index: &'a mut NodeMap<CFGIndex>,
index: &'a mut NodeMap<Vec<CFGIndex>>,
}
let mut formals = Formals { entry: entry, index: index };
visit::walk_fn_decl(&mut formals, decl);
impl<'a, 'v> visit::Visitor<'v> for Formals<'a> {
fn visit_pat(&mut self, p: &ast::Pat) {
self.index.insert(p.id, self.entry);
match self.index.entry(p.id).get() {
Ok(v) => v.push(self.entry),
Err(e) => {
e.insert(vec![self.entry]);
}
}
visit::walk_pat(self, p)
}
}
@ -230,10 +242,12 @@ impl<'a, 'tcx, O:DataFlowOperator> DataFlowContext<'a, 'tcx, O> {
assert!(self.nodeid_to_index.contains_key(&id));
assert!(self.bits_per_id > 0);
let cfgidx = to_cfgidx_or_die(id, &self.nodeid_to_index);
let (start, end) = self.compute_id_range(cfgidx);
let gens = &mut self.gens[start.. end];
set_bit(gens, bit);
let indices = get_cfg_indices(id, &self.nodeid_to_index);
for &cfgidx in indices {
let (start, end) = self.compute_id_range(cfgidx);
let gens = &mut self.gens[start.. end];
set_bit(gens, bit);
}
}
pub fn add_kill(&mut self, id: ast::NodeId, bit: uint) {
@ -243,10 +257,12 @@ impl<'a, 'tcx, O:DataFlowOperator> DataFlowContext<'a, 'tcx, O> {
assert!(self.nodeid_to_index.contains_key(&id));
assert!(self.bits_per_id > 0);
let cfgidx = to_cfgidx_or_die(id, &self.nodeid_to_index);
let (start, end) = self.compute_id_range(cfgidx);
let kills = &mut self.kills[start.. end];
set_bit(kills, bit);
let indices = get_cfg_indices(id, &self.nodeid_to_index);
for &cfgidx in indices {
let (start, end) = self.compute_id_range(cfgidx);
let kills = &mut self.kills[start.. end];
set_bit(kills, bit);
}
}
fn apply_gen_kill(&self, cfgidx: CFGIndex, bits: &mut [uint]) {
@ -279,7 +295,7 @@ impl<'a, 'tcx, O:DataFlowOperator> DataFlowContext<'a, 'tcx, O> {
}
pub fn each_bit_on_entry<F>(&self, id: ast::NodeId, f: F) -> bool where
pub fn each_bit_on_entry<F>(&self, id: ast::NodeId, mut f: F) -> bool where
F: FnMut(uint) -> bool,
{
//! Iterates through each bit that is set on entry to `id`.
@ -287,8 +303,13 @@ impl<'a, 'tcx, O:DataFlowOperator> DataFlowContext<'a, 'tcx, O> {
if !self.has_bitset_for_nodeid(id) {
return true;
}
let cfgidx = to_cfgidx_or_die(id, &self.nodeid_to_index);
self.each_bit_for_node(Entry, cfgidx, f)
let indices = get_cfg_indices(id, &self.nodeid_to_index);
for &cfgidx in indices {
if !self.each_bit_for_node(Entry, cfgidx, |i| f(i)) {
return false;
}
}
return true;
}
pub fn each_bit_for_node<F>(&self, e: EntryOrExit, cfgidx: CFGIndex, f: F) -> bool where
@ -320,7 +341,7 @@ impl<'a, 'tcx, O:DataFlowOperator> DataFlowContext<'a, 'tcx, O> {
self.each_bit(slice, f)
}
pub fn each_gen_bit<F>(&self, id: ast::NodeId, f: F) -> bool where
pub fn each_gen_bit<F>(&self, id: ast::NodeId, mut f: F) -> bool where
F: FnMut(uint) -> bool,
{
//! Iterates through each bit in the gen set for `id`.
@ -334,12 +355,17 @@ impl<'a, 'tcx, O:DataFlowOperator> DataFlowContext<'a, 'tcx, O> {
return true;
}
let cfgidx = to_cfgidx_or_die(id, &self.nodeid_to_index);
let (start, end) = self.compute_id_range(cfgidx);
let gens = &self.gens[start.. end];
debug!("{} each_gen_bit(id={}, gens={})",
self.analysis_name, id, bits_to_string(gens));
self.each_bit(gens, f)
let indices = get_cfg_indices(id, &self.nodeid_to_index);
for &cfgidx in indices {
let (start, end) = self.compute_id_range(cfgidx);
let gens = &self.gens[start.. end];
debug!("{} each_gen_bit(id={}, gens={})",
self.analysis_name, id, bits_to_string(gens));
if !self.each_bit(gens, |i| f(i)) {
return false;
}
}
return true;
}
fn each_bit<F>(&self, words: &[uint], mut f: F) -> bool where
@ -400,13 +426,15 @@ impl<'a, 'tcx, O:DataFlowOperator> DataFlowContext<'a, 'tcx, O> {
let mut changed = false;
for &node_id in &edge.data.exiting_scopes {
let opt_cfg_idx = self.nodeid_to_index.get(&node_id).cloned();
let opt_cfg_idx = self.nodeid_to_index.get(&node_id);
match opt_cfg_idx {
Some(cfg_idx) => {
let (start, end) = self.compute_id_range(cfg_idx);
let kills = &self.kills[start.. end];
if bitwise(&mut orig_kills, kills, &Union) {
changed = true;
Some(indices) => {
for &cfg_idx in indices {
let (start, end) = self.compute_id_range(cfg_idx);
let kills = &self.kills[start.. end];
if bitwise(&mut orig_kills, kills, &Union) {
changed = true;
}
}
}
None => {
@ -482,7 +510,7 @@ impl<'a, 'b, 'tcx, O:DataFlowOperator> PropagationContext<'a, 'b, 'tcx, O> {
cfg.graph.each_node(|node_index, node| {
debug!("DataFlowContext::walk_cfg idx={:?} id={} begin in_out={}",
node_index, node.data.id, bits_to_string(in_out));
node_index, node.data.id(), bits_to_string(in_out));
let (start, end) = self.dfcx.compute_id_range(node_index);

View file

@ -93,7 +93,7 @@ pub fn simplify_type(tcx: &ty::ctxt,
None
}
}
ty::ty_open(_) | ty::ty_infer(_) | ty::ty_err => None,
ty::ty_infer(_) | ty::ty_err => None,
}
}

View file

@ -135,7 +135,6 @@ impl<'a, 'tcx> TypeFolder<'tcx> for TypeFreshener<'a, 'tcx> {
t
}
ty::ty_open(..) |
ty::ty_bool |
ty::ty_char |
ty::ty_int(..) |

View file

@ -119,6 +119,21 @@ pub fn pat_contains_bindings(dm: &DefMap, pat: &ast::Pat) -> bool {
contains_bindings
}
/// Checks if the pattern contains any patterns that bind something to
/// an ident or wildcard, e.g. `foo`, or `Foo(_)`, `foo @ Bar(..)`,
pub fn pat_contains_bindings_or_wild(dm: &DefMap, pat: &ast::Pat) -> bool {
let mut contains_bindings = false;
walk_pat(pat, |p| {
if pat_is_binding_or_wild(dm, p) {
contains_bindings = true;
false // there's at least one binding/wildcard, can short circuit now.
} else {
true
}
});
contains_bindings
}
pub fn simple_identifier<'a>(pat: &'a ast::Pat) -> Option<&'a ast::Ident> {
match pat.node {
ast::PatIdent(ast::BindByValue(_), ref path1, None) => {

View file

@ -194,7 +194,6 @@ fn ty_is_local_constructor<'tcx>(tcx: &ty::ctxt<'tcx>, ty: Ty<'tcx>) -> bool {
ty::ty_closure(..) |
ty::ty_infer(..) |
ty::ty_open(..) |
ty::ty_err => {
tcx.sess.bug(
&format!("ty_is_local invoked on unexpected type: {}",

View file

@ -42,9 +42,6 @@ pub enum ObjectSafetyViolation<'tcx> {
/// Reasons a method might not be object-safe.
#[derive(Copy,Clone,Debug)]
pub enum MethodViolationCode {
/// e.g., `fn(self)`
ByValueSelf,
/// e.g., `fn foo()`
StaticMethod,
@ -157,6 +154,16 @@ fn supertraits_reference_self<'tcx>(tcx: &ty::ctxt<'tcx>,
fn trait_has_sized_self<'tcx>(tcx: &ty::ctxt<'tcx>,
trait_def_id: ast::DefId)
-> bool
{
let trait_def = ty::lookup_trait_def(tcx, trait_def_id);
let trait_predicates = ty::lookup_predicates(tcx, trait_def_id);
generics_require_sized_self(tcx, &trait_def.generics, &trait_predicates)
}
fn generics_require_sized_self<'tcx>(tcx: &ty::ctxt<'tcx>,
generics: &ty::Generics<'tcx>,
predicates: &ty::GenericPredicates<'tcx>)
-> bool
{
let sized_def_id = match tcx.lang_items.sized_trait() {
Some(def_id) => def_id,
@ -164,12 +171,8 @@ fn trait_has_sized_self<'tcx>(tcx: &ty::ctxt<'tcx>,
};
// Search for a predicate like `Self : Sized` amongst the trait bounds.
let trait_def = ty::lookup_trait_def(tcx, trait_def_id);
let free_substs = ty::construct_free_substs(tcx, &trait_def.generics, ast::DUMMY_NODE_ID);
let trait_predicates = ty::lookup_predicates(tcx, trait_def_id);
let predicates = trait_predicates.instantiate(tcx, &free_substs).predicates.into_vec();
let free_substs = ty::construct_free_substs(tcx, generics, ast::DUMMY_NODE_ID);
let predicates = predicates.instantiate(tcx, &free_substs).predicates.into_vec();
elaborate_predicates(tcx, predicates)
.any(|predicate| {
match predicate {
@ -192,17 +195,21 @@ fn object_safety_violations_for_method<'tcx>(tcx: &ty::ctxt<'tcx>,
method: &ty::Method<'tcx>)
-> Option<MethodViolationCode>
{
// The method's first parameter must be something that derefs to
// `&self`. For now, we only accept `&self` and `Box<Self>`.
match method.explicit_self {
ty::ByValueExplicitSelfCategory => {
return Some(MethodViolationCode::ByValueSelf);
}
// Any method that has a `Self : Sized` requisite is otherwise
// exempt from the regulations.
if generics_require_sized_self(tcx, &method.generics, &method.predicates) {
return None;
}
// The method's first parameter must be something that derefs (or
// autorefs) to `&self`. For now, we only accept `self`, `&self`
// and `Box<Self>`.
match method.explicit_self {
ty::StaticExplicitSelfCategory => {
return Some(MethodViolationCode::StaticMethod);
}
ty::ByValueExplicitSelfCategory |
ty::ByReferenceExplicitSelfCategory(..) |
ty::ByBoxExplicitSelfCategory => {
}

View file

@ -1626,25 +1626,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
Ok(AmbiguousBuiltin)
}
ty::ty_open(ty) => {
// these only crop up in trans, and represent an
// "opened" unsized/existential type (one that has
// been dereferenced)
match bound {
ty::BoundCopy => {
Ok(If(vec!(ty)))
}
ty::BoundSized => {
Err(Unimplemented)
}
ty::BoundSync |
ty::BoundSend => {
self.tcx().sess.bug("Send/Sync shouldn't occur in builtin_bounds()");
}
}
}
ty::ty_err => {
Ok(If(Vec::new()))
}
@ -1718,8 +1699,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
Some(vec![referent_ty])
}
ty::ty_open(element_ty) => {Some(vec![element_ty])},
ty::ty_ptr(ty::mt { ty: element_ty, ..}) |
ty::ty_rptr(_, ty::mt { ty: element_ty, ..}) => {
Some(vec![element_ty])

View file

@ -930,7 +930,7 @@ impl<'tcx> ctxt<'tcx> {
sty_debug_print!(
self,
ty_enum, ty_uniq, ty_vec, ty_ptr, ty_rptr, ty_bare_fn, ty_trait,
ty_struct, ty_closure, ty_tup, ty_param, ty_open, ty_infer, ty_projection);
ty_struct, ty_closure, ty_tup, ty_param, ty_infer, ty_projection);
println!("Substs interner: #{}", self.substs_interner.borrow().len());
println!("BareFnTy interner: #{}", self.bare_fn_interner.borrow().len());
@ -1374,12 +1374,6 @@ pub enum sty<'tcx> {
ty_projection(ProjectionTy<'tcx>),
ty_param(ParamTy), // type parameter
ty_open(Ty<'tcx>), // A deref'ed fat pointer, i.e., a dynamically sized value
// and its size. Only ever used in trans. It is not necessary
// earlier since we don't need to distinguish a DST with its
// size (e.g., in a deref) vs a DST with the size elsewhere (
// e.g., in a field).
ty_infer(InferTy), // something used only during inference/typeck
ty_err, // Also only used during inference/typeck, to represent
// the type of an erroneous expression (helps cut down
@ -2689,7 +2683,7 @@ impl FlagComputation {
self.add_bounds(bounds);
}
&ty_uniq(tt) | &ty_vec(tt, _) | &ty_open(tt) => {
&ty_uniq(tt) | &ty_vec(tt, _) => {
self.add_ty(tt)
}
@ -2964,8 +2958,6 @@ pub fn mk_param_from_def<'tcx>(cx: &ctxt<'tcx>, def: &TypeParameterDef) -> Ty<'t
mk_param(cx, def.space, def.index, def.name)
}
pub fn mk_open<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> { mk_t(cx, ty_open(ty)) }
impl<'tcx> TyS<'tcx> {
/// Iterator that walks `self` and any types reachable from
/// `self`, in depth-first order. Note that just walks the types
@ -3164,7 +3156,6 @@ pub fn sequence_element_type<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> {
match ty.sty {
ty_vec(ty, _) => ty,
ty_str => mk_mach_uint(cx, ast::TyU8),
ty_open(ty) => sequence_element_type(cx, ty),
_ => cx.sess.bug(&format!("sequence_element_type called on non-sequence value: {}",
ty_to_string(cx, ty))),
}
@ -3583,12 +3574,6 @@ pub fn type_contents<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> TypeContents {
TC::All
}
ty_open(ty) => {
let result = tc_ty(cx, ty, cache);
assert!(!result.is_sized(cx));
result.unsafe_pointer() | TC::Nonsized
}
ty_infer(_) |
ty_err => {
cx.sess.bug("asked to compute contents of error type");
@ -3747,7 +3732,7 @@ pub fn is_instantiable<'tcx>(cx: &ctxt<'tcx>, r_ty: Ty<'tcx>) -> bool {
ty_vec(_, None) => {
false
}
ty_uniq(typ) | ty_open(typ) => {
ty_uniq(typ) => {
type_requires(cx, seen, r_ty, typ)
}
ty_rptr(_, ref mt) => {
@ -4106,14 +4091,6 @@ pub fn deref<'tcx>(ty: Ty<'tcx>, explicit: bool) -> Option<mt<'tcx>> {
}
}
pub fn close_type<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> {
match ty.sty {
ty_open(ty) => mk_rptr(cx, cx.mk_region(ReStatic), mt {ty: ty, mutbl:ast::MutImmutable}),
_ => cx.sess.bug(&format!("Trying to close a non-open type {}",
ty_to_string(cx, ty)))
}
}
pub fn type_content<'tcx>(ty: Ty<'tcx>) -> Ty<'tcx> {
match ty.sty {
ty_uniq(ty) => ty,
@ -4122,14 +4099,6 @@ pub fn type_content<'tcx>(ty: Ty<'tcx>) -> Ty<'tcx> {
}
}
// Extract the unsized type in an open type (or just return ty if it is not open).
pub fn unopen_type<'tcx>(ty: Ty<'tcx>) -> Ty<'tcx> {
match ty.sty {
ty_open(ty) => ty,
_ => ty
}
}
// Returns the type of ty[i]
pub fn index<'tcx>(ty: Ty<'tcx>) -> Option<Ty<'tcx>> {
match ty.sty {
@ -4802,7 +4771,6 @@ pub fn ty_sort_string<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> String {
}
}
ty_err => "type error".to_string(),
ty_open(_) => "opened DST".to_string(),
}
}
@ -6328,16 +6296,15 @@ pub fn hash_crate_independent<'tcx>(tcx: &ctxt<'tcx>, ty: Ty<'tcx>, svh: &Svh) -
hash!(p.idx);
hash!(token::get_name(p.name));
}
ty_open(_) => byte!(22),
ty_infer(_) => unreachable!(),
ty_err => byte!(23),
ty_err => byte!(21),
ty_closure(d, r, _) => {
byte!(24);
byte!(22);
did(state, d);
region(state, *r);
}
ty_projection(ref data) => {
byte!(25);
byte!(23);
did(state, data.trait_ref.def_id);
hash!(token::get_name(data.item_name));
}
@ -6666,7 +6633,6 @@ pub fn accumulate_lifetimes_in_type(accumulator: &mut Vec<ty::Region>,
ty_projection(_) |
ty_param(_) |
ty_infer(_) |
ty_open(_) |
ty_err => {
}
}

View file

@ -626,9 +626,6 @@ pub fn super_fold_ty<'tcx, T: TypeFolder<'tcx>>(this: &mut T,
ty::ty_vec(typ, sz) => {
ty::ty_vec(typ.fold_with(this), sz)
}
ty::ty_open(typ) => {
ty::ty_open(typ.fold_with(this))
}
ty::ty_enum(tid, ref substs) => {
let substs = substs.fold_with(this);
ty::ty_enum(tid, this.tcx().mk_substs(substs))

View file

@ -28,7 +28,7 @@ impl<'tcx> TypeWalker<'tcx> {
ty::ty_bool | ty::ty_char | ty::ty_int(_) | ty::ty_uint(_) | ty::ty_float(_) |
ty::ty_str | ty::ty_infer(_) | ty::ty_param(_) | ty::ty_err => {
}
ty::ty_uniq(ty) | ty::ty_vec(ty, _) | ty::ty_open(ty) => {
ty::ty_uniq(ty) | ty::ty_vec(ty, _) => {
self.stack.push(ty);
}
ty::ty_ptr(ref mt) | ty::ty_rptr(_, ref mt) => {

View file

@ -20,7 +20,7 @@ use middle::ty::{ReSkolemized, ReVar, BrEnv};
use middle::ty::{mt, Ty, ParamTy};
use middle::ty::{ty_bool, ty_char, ty_struct, ty_enum};
use middle::ty::{ty_err, ty_str, ty_vec, ty_float, ty_bare_fn};
use middle::ty::{ty_param, ty_ptr, ty_rptr, ty_tup, ty_open};
use middle::ty::{ty_param, ty_ptr, ty_rptr, ty_tup};
use middle::ty::{ty_closure};
use middle::ty::{ty_uniq, ty_trait, ty_int, ty_uint, ty_infer};
use middle::ty;
@ -369,8 +369,6 @@ pub fn ty_to_string<'tcx>(cx: &ctxt<'tcx>, typ: &ty::TyS<'tcx>) -> String {
buf.push_str(&mt_to_string(cx, tm));
buf
}
ty_open(typ) =>
format!("opened<{}>", ty_to_string(cx, typ)),
ty_tup(ref elems) => {
let strs = elems
.iter()

View file

@ -20,6 +20,11 @@ pub fn opts() -> TargetOptions {
linker_is_gnu: true,
has_rpath: true,
pre_link_args: vec!(
// GNU-style linkers will use this to omit linking to libraries
// which don't actually fulfill any relocations, but only for
// libraries which follow this flag. Thus, use it before
// specifying libraries to link to.
"-Wl,--as-needed".to_string(),
),
position_independent_executables: true,
.. Default::default()

View file

@ -612,13 +612,26 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
};
let (suggestion, _) =
move_suggestion(param_env, expr_span, expr_ty, ("moved by default", ""));
self.tcx.sess.span_note(
expr_span,
&format!("`{}` moved here{} because it has type `{}`, which is {}",
ol,
moved_lp_msg,
expr_ty.user_string(self.tcx),
suggestion));
// If the two spans are the same, it's because the expression will be evaluated
// multiple times. Avoid printing the same span and adjust the wording so it makes
// more sense that it's from multiple evalutations.
if expr_span == use_span {
self.tcx.sess.note(
&format!("`{}` was previously moved here{} because it has type `{}`, \
which is {}",
ol,
moved_lp_msg,
expr_ty.user_string(self.tcx),
suggestion));
} else {
self.tcx.sess.span_note(
expr_span,
&format!("`{}` moved here{} because it has type `{}`, which is {}",
ol,
moved_lp_msg,
expr_ty.user_string(self.tcx),
suggestion));
}
}
move_data::MovePat => {

View file

@ -52,7 +52,7 @@ pub struct DataflowLabeller<'a, 'tcx: 'a> {
impl<'a, 'tcx> DataflowLabeller<'a, 'tcx> {
fn dataflow_for(&self, e: EntryOrExit, n: &Node<'a>) -> String {
let id = n.1.data.id;
let id = n.1.data.id();
debug!("dataflow_for({:?}, id={}) {:?}", e, id, self.variants);
let mut sets = "".to_string();
let mut seen_one = false;

View file

@ -678,7 +678,7 @@ fn bind_subslice_pat(bcx: Block,
}
fn extract_vec_elems<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
left_ty: Ty,
left_ty: Ty<'tcx>,
before: uint,
after: uint,
val: ValueRef)

View file

@ -699,7 +699,7 @@ fn struct_llfields<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, st: &Struct<'tcx>,
st.fields.iter().filter(|&ty| !dst || type_is_sized(cx.tcx(), *ty))
.map(|&ty| type_of::sizing_type_of(cx, ty)).collect()
} else {
st.fields.iter().map(|&ty| type_of::type_of(cx, ty)).collect()
st.fields.iter().map(|&ty| type_of::in_memory_type_of(cx, ty)).collect()
}
}

View file

@ -676,8 +676,7 @@ pub fn iter_structural_ty<'blk, 'tcx, F>(cx: Block<'blk, 'tcx>,
let val = if common::type_is_sized(cx.tcx(), field_ty) {
llfld_a
} else {
let boxed_ty = ty::mk_open(cx.tcx(), field_ty);
let scratch = datum::rvalue_scratch_datum(cx, boxed_ty, "__fat_ptr_iter");
let scratch = datum::rvalue_scratch_datum(cx, field_ty, "__fat_ptr_iter");
Store(cx, llfld_a, GEPi(cx, scratch.val, &[0, abi::FAT_PTR_ADDR]));
Store(cx, info.unwrap(), GEPi(cx, scratch.val, &[0, abi::FAT_PTR_EXTRA]));
scratch.val
@ -1353,7 +1352,7 @@ fn build_cfg(tcx: &ty::ctxt, id: ast::NodeId) -> (ast::NodeId, Option<cfg::CFG>)
// the clobbering of the existing value in the return slot.
fn has_nested_returns(tcx: &ty::ctxt, cfg: &cfg::CFG, blk_id: ast::NodeId) -> bool {
for n in cfg.graph.depth_traverse(cfg.entry) {
match tcx.map.find(n.id) {
match tcx.map.find(n.id()) {
Some(ast_map::NodeExpr(ex)) => {
if let ast::ExprRet(Some(ref ret_expr)) = ex.node {
let mut visitor = FindNestedReturn::new();

View file

@ -120,14 +120,16 @@ pub fn erase_regions<'tcx,T>(cx: &ty::ctxt<'tcx>, value: &T) -> T
// Is the type's representation size known at compile time?
pub fn type_is_sized<'tcx>(tcx: &ty::ctxt<'tcx>, ty: Ty<'tcx>) -> bool {
let param_env = ty::empty_parameter_environment(tcx);
ty::type_is_sized(&param_env, DUMMY_SP, ty)
}
pub fn lltype_is_sized<'tcx>(cx: &ty::ctxt<'tcx>, ty: Ty<'tcx>) -> bool {
match ty.sty {
ty::ty_open(_) => true,
_ => type_is_sized(cx, ty),
// FIXME(#4287) This can cause errors due to polymorphic recursion,
// a better span should be provided, if available.
let err_count = tcx.sess.err_count();
let is_sized = ty::type_is_sized(&param_env, DUMMY_SP, ty);
// Those errors aren't fatal, but an incorrect result can later
// trip over asserts in both rustc's trans and LLVM.
if err_count < tcx.sess.err_count() {
tcx.sess.abort_if_errors();
}
is_sized
}
pub fn type_is_fat_ptr<'tcx>(cx: &ty::ctxt<'tcx>, ty: Ty<'tcx>) -> bool {
@ -211,9 +213,7 @@ pub fn type_needs_unwind_cleanup<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ty: Ty<
}
}
pub fn type_needs_drop<'tcx>(cx: &ty::ctxt<'tcx>,
ty: Ty<'tcx>)
-> bool {
pub fn type_needs_drop<'tcx>(cx: &ty::ctxt<'tcx>, ty: Ty<'tcx>) -> bool {
ty::type_contents(cx, ty).needs_drop(cx)
}

View file

@ -146,8 +146,8 @@ fn const_deref<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
(const_deref_ptr(cx, v), mt.ty)
} else {
// Derefing a fat pointer does not change the representation,
// just the type to ty_open.
(v, ty::mk_open(cx.tcx(), mt.ty))
// just the type to the unsized contents.
(v, mt.ty)
}
}
None => {
@ -290,15 +290,7 @@ pub fn const_expr<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
// an optimisation, it is necessary for mutable vectors to
// work properly.
ty = match ty::deref(ty, true) {
Some(mt) => {
if type_is_sized(cx.tcx(), mt.ty) {
mt.ty
} else {
// Derefing a fat pointer does not change the representation,
// just the type to ty_open.
ty::mk_open(cx.tcx(), mt.ty)
}
}
Some(mt) => mt.ty,
None => {
cx.sess().bug(&format!("unexpected dereferenceable type {}",
ty_to_string(cx.tcx(), ty)))
@ -319,11 +311,12 @@ pub fn const_expr<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
llconst = addr_of(cx, llconst, "autoref", e.id);
}
Some(box ty::AutoUnsize(ref k)) => {
let unsized_ty = ty::unsize_ty(cx.tcx(), ty, k, e.span);
let info = expr::unsized_info(cx, k, e.id, ty, param_substs,
|t| ty::mk_imm_rptr(cx.tcx(), cx.tcx().mk_region(ty::ReStatic), t));
let base = ptrcast(llconst, type_of::type_of(cx, unsized_ty).ptr_to());
let unsized_ty = ty::unsize_ty(cx.tcx(), ty, k, e.span);
let ptr_ty = type_of::in_memory_type_of(cx, unsized_ty).ptr_to();
let base = ptrcast(llconst, ptr_ty);
let prev_const = cx.const_unsized().borrow_mut()
.insert(base, llconst);
assert!(prev_const.is_none() || prev_const == Some(llconst));
@ -477,16 +470,10 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
};
let (arr, len) = match bt.sty {
ty::ty_vec(_, Some(u)) => (bv, C_uint(cx, u)),
ty::ty_open(ty) => match ty.sty {
ty::ty_vec(_, None) | ty::ty_str => {
let e1 = const_get_elt(cx, bv, &[0]);
(const_deref_ptr(cx, e1), const_get_elt(cx, bv, &[1]))
},
_ => cx.sess().span_bug(base.span,
&format!("index-expr base must be a vector \
or string type, found {}",
ty_to_string(cx.tcx(), bt)))
},
ty::ty_vec(_, None) | ty::ty_str => {
let e1 = const_get_elt(cx, bv, &[0]);
(const_deref_ptr(cx, e1), const_get_elt(cx, bv, &[1]))
}
ty::ty_rptr(_, mt) => match mt.ty.sty {
ty::ty_vec(_, Some(u)) => {
(const_deref_ptr(cx, bv), C_uint(cx, u))

View file

@ -492,8 +492,6 @@ impl<'tcx> Datum<'tcx, Expr> {
-> DatumBlock<'blk, 'tcx, Lvalue> {
debug!("to_lvalue_datum self: {}", self.to_string(bcx.ccx()));
assert!(lltype_is_sized(bcx.tcx(), self.ty),
"Trying to convert unsized value to lval");
self.match_kind(
|l| DatumBlock::new(bcx, l),
|r| {
@ -549,15 +547,10 @@ impl<'tcx> Datum<'tcx, Lvalue> {
-> Datum<'tcx, Lvalue> where
F: FnOnce(ValueRef) -> ValueRef,
{
let val = match self.ty.sty {
_ if type_is_sized(bcx.tcx(), self.ty) => gep(self.val),
ty::ty_open(_) => {
let base = Load(bcx, expr::get_dataptr(bcx, self.val));
gep(base)
}
_ => bcx.tcx().sess.bug(
&format!("Unexpected unsized type in get_element: {}",
bcx.ty_to_string(self.ty)))
let val = if type_is_sized(bcx.tcx(), self.ty) {
gep(self.val)
} else {
gep(Load(bcx, expr::get_dataptr(bcx, self.val)))
};
Datum {
val: val,
@ -566,7 +559,8 @@ impl<'tcx> Datum<'tcx, Lvalue> {
}
}
pub fn get_vec_base_and_len(&self, bcx: Block) -> (ValueRef, ValueRef) {
pub fn get_vec_base_and_len<'blk>(&self, bcx: Block<'blk, 'tcx>)
-> (ValueRef, ValueRef) {
//! Converts a vector into the slice pair.
tvec::get_base_and_len(bcx, self.val, self.ty)

View file

@ -3828,7 +3828,6 @@ fn push_debuginfo_type_name<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
}
ty::ty_err |
ty::ty_infer(_) |
ty::ty_open(_) |
ty::ty_projection(..) |
ty::ty_param(_) => {
cx.sess().bug(&format!("debuginfo: Trying to create type name for \

View file

@ -451,8 +451,6 @@ fn apply_adjustments<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
let datum_ty = datum.ty;
let unsized_ty = ty::unsize_ty(tcx, datum_ty, k, expr.span);
debug!("unsized_ty={}", unsized_ty.repr(bcx.tcx()));
let dest_ty = ty::mk_open(tcx, unsized_ty);
debug!("dest_ty={}", unsized_ty.repr(bcx.tcx()));
let info = unsized_info(bcx.ccx(), k, expr.id, datum_ty, bcx.fcx.param_substs,
|t| ty::mk_imm_rptr(tcx, tcx.mk_region(ty::ReStatic), t));
@ -462,20 +460,16 @@ fn apply_adjustments<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
datum.to_lvalue_datum(bcx, "into_fat_ptr", expr.id));
// Compute the base pointer. This doesn't change the pointer value,
// but merely its type.
let base = match *k {
ty::UnsizeStruct(..) | ty::UnsizeVtable(..) => {
PointerCast(bcx, lval.val, type_of::type_of(bcx.ccx(), unsized_ty).ptr_to())
}
ty::UnsizeLength(..) => {
GEPi(bcx, lval.val, &[0, 0])
}
};
let ptr_ty = type_of::in_memory_type_of(bcx.ccx(), unsized_ty).ptr_to();
let base = PointerCast(bcx, lval.val, ptr_ty);
let scratch = rvalue_scratch_datum(bcx, dest_ty, "__fat_ptr");
Store(bcx, base, get_dataptr(bcx, scratch.val));
Store(bcx, info, get_len(bcx, scratch.val));
let llty = type_of::type_of(bcx.ccx(), unsized_ty);
// HACK(eddyb) get around issues with lifetime intrinsics.
let scratch = alloca_no_lifetime(bcx, llty, "__fat_ptr");
Store(bcx, base, get_dataptr(bcx, scratch));
Store(bcx, info, get_len(bcx, scratch));
DatumBlock::new(bcx, scratch.to_expr_datum())
DatumBlock::new(bcx, Datum::new(scratch, unsized_ty, LvalueExpr))
}
fn unsize_unique_vec<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
@ -711,7 +705,7 @@ fn trans_field<'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>,
let _icx = push_ctxt("trans_rec_field");
let base_datum = unpack_datum!(bcx, trans_to_lvalue(bcx, base, "field"));
let bare_ty = ty::unopen_type(base_datum.ty);
let bare_ty = base_datum.ty;
let repr = adt::represent_type(bcx.ccx(), bare_ty);
with_field_tys(bcx.tcx(), bare_ty, None, move |discr, field_tys| {
let ix = get_idx(bcx.tcx(), field_tys);
@ -723,7 +717,7 @@ fn trans_field<'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>,
if type_is_sized(bcx.tcx(), d.ty) {
DatumBlock { datum: d.to_expr_datum(), bcx: bcx }
} else {
let scratch = rvalue_scratch_datum(bcx, ty::mk_open(bcx.tcx(), d.ty), "");
let scratch = rvalue_scratch_datum(bcx, d.ty, "");
Store(bcx, d.val, get_dataptr(bcx, scratch.val));
let info = Load(bcx, get_len(bcx, base_datum.val));
Store(bcx, info, get_len(bcx, scratch.val));
@ -809,7 +803,7 @@ fn trans_index<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
if type_is_sized(bcx.tcx(), elt_ty) {
Datum::new(datum.to_llscalarish(bcx), elt_ty, LvalueExpr)
} else {
Datum::new(datum.val, ty::mk_open(bcx.tcx(), elt_ty), LvalueExpr)
Datum::new(datum.val, elt_ty, LvalueExpr)
}
}
None => {
@ -1671,7 +1665,7 @@ fn trans_uniq_expr<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
fn ref_fat_ptr<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
lval: Datum<'tcx, Lvalue>)
-> DatumBlock<'blk, 'tcx, Expr> {
let dest_ty = ty::close_type(bcx.tcx(), lval.ty);
let dest_ty = ty::mk_imm_rptr(bcx.tcx(), bcx.tcx().mk_region(ty::ReStatic), lval.ty);
let scratch = rvalue_scratch_datum(bcx, dest_ty, "__fat_ptr");
memcpy_ty(bcx, scratch.val, lval.val, scratch.ty);
@ -1685,16 +1679,13 @@ fn trans_addr_of<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
let _icx = push_ctxt("trans_addr_of");
let mut bcx = bcx;
let sub_datum = unpack_datum!(bcx, trans_to_lvalue(bcx, subexpr, "addr_of"));
match sub_datum.ty.sty {
ty::ty_open(_) => {
// Opened DST value, close to a fat pointer
ref_fat_ptr(bcx, sub_datum)
}
_ => {
// Sized value, ref to a thin pointer
let ty = expr_ty(bcx, expr);
immediate_rvalue_bcx(bcx, sub_datum.val, ty).to_expr_datumblock()
}
if !type_is_sized(bcx.tcx(), sub_datum.ty) {
// DST lvalue, close to a fat pointer
ref_fat_ptr(bcx, sub_datum)
} else {
// Sized value, ref to a thin pointer
let ty = expr_ty(bcx, expr);
immediate_rvalue_bcx(bcx, sub_datum.val, ty).to_expr_datumblock()
}
}
@ -2234,16 +2225,15 @@ fn deref_once<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
if type_is_sized(bcx.tcx(), content_ty) {
deref_owned_pointer(bcx, expr, datum, content_ty)
} else {
// A fat pointer and an opened DST value have the same
// representation just different types. Since there is no
// temporary for `*e` here (because it is unsized), we cannot
// emulate the sized object code path for running drop glue and
// free. Instead, we schedule cleanup for `e`, turning it into
// an lvalue.
// A fat pointer and a DST lvalue have the same representation
// just different types. Since there is no temporary for `*e`
// here (because it is unsized), we cannot emulate the sized
// object code path for running drop glue and free. Instead,
// we schedule cleanup for `e`, turning it into an lvalue.
let datum = unpack_datum!(
bcx, datum.to_lvalue_datum(bcx, "deref", expr.id));
let datum = Datum::new(datum.val, ty::mk_open(bcx.tcx(), content_ty), LvalueExpr);
let datum = Datum::new(datum.val, content_ty, LvalueExpr);
DatumBlock::new(bcx, datum)
}
}
@ -2260,11 +2250,9 @@ fn deref_once<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
// owner (or, in the case of *T, by the user).
DatumBlock::new(bcx, Datum::new(ptr, content_ty, LvalueExpr))
} else {
// A fat pointer and an opened DST value have the same representation
// A fat pointer and a DST lvalue have the same representation
// just different types.
DatumBlock::new(bcx, Datum::new(datum.val,
ty::mk_open(bcx.tcx(), content_ty),
LvalueExpr))
DatumBlock::new(bcx, Datum::new(datum.val, content_ty, LvalueExpr))
}
}

View file

@ -34,7 +34,7 @@ use trans::expr;
use trans::machine::*;
use trans::tvec;
use trans::type_::Type;
use trans::type_of::{type_of, sizing_type_of, align_of};
use trans::type_of::{self, type_of, sizing_type_of, align_of};
use middle::ty::{self, Ty};
use util::ppaux::{ty_to_short_str, Repr};
use util::ppaux;
@ -265,8 +265,7 @@ fn trans_struct_drop<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
assert_eq!(params.len(), 1);
let self_arg = if type_is_fat_ptr(bcx.tcx(), self_ty) {
// The dtor expects a fat pointer, so make one, even if we have to fake it.
let boxed_ty = ty::mk_open(bcx.tcx(), t);
let scratch = datum::rvalue_scratch_datum(bcx, boxed_ty, "__fat_ptr_drop_self");
let scratch = datum::rvalue_scratch_datum(bcx, t, "__fat_ptr_drop_self");
Store(bcx, value, GEPi(bcx, scratch.val, &[0, abi::FAT_PTR_ADDR]));
Store(bcx,
// If we just had a thin pointer, make a fat pointer by sticking
@ -284,20 +283,18 @@ fn trans_struct_drop<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
// Add all the fields as a value which needs to be cleaned at the end of
// this scope. Iterate in reverse order so a Drop impl doesn't reverse
// the order in which fields get dropped.
for (i, ty) in st.fields.iter().enumerate().rev() {
for (i, &ty) in st.fields.iter().enumerate().rev() {
let llfld_a = adt::struct_field_ptr(variant_cx, &*st, value, i, false);
let val = if type_is_sized(bcx.tcx(), *ty) {
let val = if type_is_sized(bcx.tcx(), ty) {
llfld_a
} else {
let boxed_ty = ty::mk_open(bcx.tcx(), *ty);
let scratch = datum::rvalue_scratch_datum(bcx, boxed_ty, "__fat_ptr_drop_field");
let scratch = datum::rvalue_scratch_datum(bcx, ty, "__fat_ptr_drop_field");
Store(bcx, llfld_a, GEPi(bcx, scratch.val, &[0, abi::FAT_PTR_ADDR]));
Store(bcx, info.unwrap(), GEPi(bcx, scratch.val, &[0, abi::FAT_PTR_EXTRA]));
scratch.val
};
variant_cx.fcx.schedule_drop_mem(cleanup::CustomScope(field_scope),
val, *ty);
variant_cx.fcx.schedule_drop_mem(cleanup::CustomScope(field_scope), val, ty);
}
let dtor_ty = ty::mk_ctor_fn(bcx.tcx(),
@ -502,7 +499,10 @@ pub fn declare_tydesc<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>)
// tydescs.
assert!(!ccx.finished_tydescs().get());
let llty = type_of(ccx, t);
// This really shouldn't be like this, size/align will be wrong for
// unsized types (i.e. [T] will have the size/align of T).
// But we need it until we split this out into a "type name" intrinsic.
let llty = type_of::in_memory_type_of(ccx, t);
if ccx.sess().count_type_sizes() {
println!("{}\t{}", llsize_of_real(ccx, llty),

View file

@ -818,9 +818,6 @@ fn emit_vtable_methods<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
param_substs,
substs.clone()).val;
// currently, at least, by-value self is not object safe
assert!(m.explicit_self != ty::ByValueExplicitSelfCategory);
Some(fn_ref).into_iter()
}
}

View file

@ -372,38 +372,31 @@ pub fn get_fixed_base_and_len(bcx: Block,
(base, len)
}
fn get_slice_base_and_len(bcx: Block,
llval: ValueRef)
-> (ValueRef, ValueRef) {
let base = Load(bcx, GEPi(bcx, llval, &[0, abi::FAT_PTR_ADDR]));
let len = Load(bcx, GEPi(bcx, llval, &[0, abi::FAT_PTR_EXTRA]));
(base, len)
}
/// Converts a vector into the slice pair. The vector should be stored in `llval` which should be
/// by-reference. If you have a datum, you would probably prefer to call
/// `Datum::get_base_and_len()` which will handle any conversions for you.
pub fn get_base_and_len(bcx: Block,
llval: ValueRef,
vec_ty: Ty)
-> (ValueRef, ValueRef) {
pub fn get_base_and_len<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
llval: ValueRef,
vec_ty: Ty<'tcx>)
-> (ValueRef, ValueRef) {
let ccx = bcx.ccx();
match vec_ty.sty {
ty::ty_vec(_, Some(n)) => get_fixed_base_and_len(bcx, llval, n),
ty::ty_open(ty) => match ty.sty {
ty::ty_vec(_, None) | ty::ty_str => get_slice_base_and_len(bcx, llval),
_ => ccx.sess().bug("unexpected type in get_base_and_len")
},
ty::ty_vec(_, None) | ty::ty_str => {
let base = Load(bcx, expr::get_dataptr(bcx, llval));
let len = Load(bcx, expr::get_len(bcx, llval));
(base, len)
}
// Only used for pattern matching.
ty::ty_uniq(ty) | ty::ty_rptr(_, ty::mt{ty, ..}) => match ty.sty {
ty::ty_vec(_, None) | ty::ty_str => get_slice_base_and_len(bcx, llval),
ty::ty_vec(_, Some(n)) => {
let base = GEPi(bcx, Load(bcx, llval), &[0, 0]);
(base, C_uint(ccx, n))
}
_ => ccx.sess().bug("unexpected type in get_base_and_len"),
ty::ty_uniq(ty) | ty::ty_rptr(_, ty::mt{ty, ..}) => {
let inner = if type_is_sized(bcx.tcx(), ty) {
Load(bcx, llval)
} else {
llval
};
get_base_and_len(bcx, inner, ty)
},
_ => ccx.sess().bug("unexpected type in get_base_and_len"),
}

View file

@ -232,14 +232,6 @@ impl Type {
Type::glue_fn(ccx, Type::i8p(ccx)).ptr_to().ptr_to()
}
pub fn opaque_trait(ccx: &CrateContext) -> Type {
Type::struct_(ccx, &[Type::opaque_trait_data(ccx).ptr_to(), Type::vtable_ptr(ccx)], false)
}
pub fn opaque_trait_data(ccx: &CrateContext) -> Type {
Type::i8(ccx)
}
pub fn kind(&self) -> TypeKind {
unsafe {
llvm::LLVMGetTypeKind(self.to_ref())

View file

@ -10,8 +10,6 @@
#![allow(non_camel_case_types)]
pub use self::named_ty::*;
use middle::subst;
use trans::adt;
use trans::common::*;
@ -183,9 +181,8 @@ pub fn sizing_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Typ
}
let llsizingty = match t.sty {
_ if !lltype_is_sized(cx.tcx(), t) => {
cx.sess().bug(&format!("trying to take the sizing type of {}, an unsized type",
ppaux::ty_to_string(cx.tcx(), t)))
_ if !type_is_sized(cx.tcx(), t) => {
Type::struct_(cx, &[Type::i8p(cx), Type::i8p(cx)], false)
}
ty::ty_bool => Type::bool(cx),
@ -232,15 +229,11 @@ pub fn sizing_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Typ
}
}
ty::ty_open(_) => {
Type::struct_(cx, &[Type::i8p(cx), Type::i8p(cx)], false)
}
ty::ty_projection(..) | ty::ty_infer(..) | ty::ty_param(..) | ty::ty_err(..) => {
cx.sess().bug(&format!("fictitious type {} in sizing_type_of()",
ppaux::ty_to_string(cx.tcx(), t)))
}
ty::ty_vec(_, None) | ty::ty_trait(..) | ty::ty_str => panic!("unreachable")
ty::ty_vec(_, None) | ty::ty_trait(..) | ty::ty_str => unreachable!()
};
cx.llsizingtypes().borrow_mut().insert(t, llsizingty);
@ -270,25 +263,37 @@ pub fn arg_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Type {
}
}
// NB: If you update this, be sure to update `sizing_type_of()` as well.
pub fn type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Type {
fn type_of_unsize_info<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Type {
// It is possible to end up here with a sized type. This happens with a
// struct which might be unsized, but is monomorphised to a sized type.
// In this case we'll fake a fat pointer with no unsize info (we use 0).
// However, its still a fat pointer, so we need some type use.
if type_is_sized(cx.tcx(), t) {
return Type::i8p(cx);
}
match unsized_part_of_type(cx.tcx(), t).sty {
ty::ty_str | ty::ty_vec(..) => Type::uint_from_ty(cx, ast::TyUs(false)),
ty::ty_trait(_) => Type::vtable_ptr(cx),
_ => panic!("Unexpected type returned from unsized_part_of_type : {}",
t.repr(cx.tcx()))
}
}
/// Get the LLVM type corresponding to a Rust type, i.e. `middle::ty::Ty`.
/// This is the right LLVM type for an alloca containg a value of that type,
/// and the pointee of an Lvalue Datum (which is always a LLVM pointer).
/// For unsized types, the returned type is a fat pointer, thus the resulting
/// LLVM type for a `Trait` Lvalue is `{ i8*, void(i8*)** }*`, which is a double
/// indirection to the actual data, unlike a `i8` Lvalue, which is just `i8*`.
/// This is needed due to the treatment of immediate values, as a fat pointer
/// is too large for it to be placed in SSA value (by our rules).
/// For the raw type without far pointer indirection, see `in_memory_type_of`.
pub fn type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, ty: Ty<'tcx>) -> Type {
let ty = if !type_is_sized(cx.tcx(), ty) {
ty::mk_imm_ptr(cx.tcx(), ty)
} else {
ty
};
in_memory_type_of(cx, ty)
}
/// Get the LLVM type corresponding to a Rust type, i.e. `middle::ty::Ty`.
/// This is the right LLVM type for a field/array element of that type,
/// and is the same as `type_of` for all Sized types.
/// Unsized types, however, are represented by a "minimal unit", e.g.
/// `[T]` becomes `T`, while `str` and `Trait` turn into `i8` - this
/// is useful for indexing slices, as `&[T]`'s data pointer is `T*`.
/// If the type is an unsized struct, the regular layout is generated,
/// with the inner-most trailing unsized field using the "minimal unit"
/// of that field's type - this is useful for taking the address of
/// that field and ensuring the struct has the right alignment.
/// For the LLVM type of a value as a whole, see `type_of`.
/// NB: If you update this, be sure to update `sizing_type_of()` as well.
pub fn in_memory_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Type {
// Check the cache.
match cx.lltypes().borrow().get(&t) {
Some(&llty) => return llty,
@ -307,7 +312,7 @@ pub fn type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Type {
let t_norm = erase_regions(cx.tcx(), &t);
if t != t_norm {
let llty = type_of(cx, t_norm);
let llty = in_memory_type_of(cx, t_norm);
debug!("--> normalized {} {:?} to {} {:?} llty={}",
t.repr(cx.tcx()),
t,
@ -331,10 +336,10 @@ pub fn type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Type {
// of the enum's variants refers to the enum itself.
let repr = adt::represent_type(cx, t);
let tps = substs.types.get_slice(subst::TypeSpace);
let name = llvm_type_name(cx, an_enum, did, tps);
let name = llvm_type_name(cx, did, tps);
adt::incomplete_type_of(cx, &*repr, &name[..])
}
ty::ty_closure(did, _, ref substs) => {
ty::ty_closure(..) => {
// Only create the named struct, but don't fill it in. We
// fill it in *after* placing it into the type cache.
let repr = adt::represent_type(cx, t);
@ -342,41 +347,47 @@ pub fn type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Type {
// inherited from their environment, so we use entire
// contents of the VecPerParamSpace to to construct the llvm
// name
let name = llvm_type_name(cx, a_closure, did, substs.types.as_slice());
adt::incomplete_type_of(cx, &*repr, &name[..])
adt::incomplete_type_of(cx, &*repr, "closure")
}
ty::ty_uniq(ty) | ty::ty_rptr(_, ty::mt{ty, ..}) | ty::ty_ptr(ty::mt{ty, ..}) => {
match ty.sty {
ty::ty_str => {
if !type_is_sized(cx.tcx(), ty) {
if let ty::ty_str = ty.sty {
// This means we get a nicer name in the output (str is always
// unsized).
cx.tn().find_type("str_slice").unwrap()
} else {
let ptr_ty = in_memory_type_of(cx, ty).ptr_to();
let unsized_part = unsized_part_of_type(cx.tcx(), ty);
let info_ty = match unsized_part.sty {
ty::ty_str | ty::ty_vec(..) => {
Type::uint_from_ty(cx, ast::TyUs(false))
}
ty::ty_trait(_) => Type::vtable_ptr(cx),
_ => panic!("Unexpected type returned from \
unsized_part_of_type: {} for ty={}",
unsized_part.repr(cx.tcx()), ty.repr(cx.tcx()))
};
Type::struct_(cx, &[ptr_ty, info_ty], false)
}
ty::ty_trait(..) => Type::opaque_trait(cx),
_ if !type_is_sized(cx.tcx(), ty) => {
let p_ty = type_of(cx, ty).ptr_to();
Type::struct_(cx, &[p_ty, type_of_unsize_info(cx, ty)], false)
}
_ => type_of(cx, ty).ptr_to(),
} else {
in_memory_type_of(cx, ty).ptr_to()
}
}
ty::ty_vec(ty, Some(size)) => {
let size = size as u64;
let llty = type_of(cx, ty);
let llty = in_memory_type_of(cx, ty);
ensure_array_fits_in_address_space(cx, llty, size, t);
Type::array(&llty, size)
}
ty::ty_vec(ty, None) => {
type_of(cx, ty)
}
ty::ty_trait(..) => {
Type::opaque_trait_data(cx)
}
ty::ty_str => Type::i8(cx),
// Unsized slice types (and str) have the type of their element, and
// traits have the type of u8. This is so that the data pointer inside
// fat pointers is of the right type (e.g. for array accesses), even
// when taking the address of an unsized field in a struct.
ty::ty_vec(ty, None) => in_memory_type_of(cx, ty),
ty::ty_str | ty::ty_trait(..) => Type::i8(cx),
ty::ty_bare_fn(..) => {
type_of_fn_from_ty(cx, t).ptr_to()
@ -388,7 +399,7 @@ pub fn type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Type {
}
ty::ty_struct(did, ref substs) => {
if ty::type_is_simd(cx.tcx(), t) {
let llet = type_of(cx, ty::simd_type(cx.tcx(), t));
let llet = in_memory_type_of(cx, ty::simd_type(cx.tcx(), t));
let n = ty::simd_size(cx.tcx(), t) as u64;
ensure_array_fits_in_address_space(cx, llet, n, t);
Type::vector(&llet, n)
@ -398,29 +409,11 @@ pub fn type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Type {
// infinite recursion with recursive struct types.
let repr = adt::represent_type(cx, t);
let tps = substs.types.get_slice(subst::TypeSpace);
let name = llvm_type_name(cx, a_struct, did, tps);
let name = llvm_type_name(cx, did, tps);
adt::incomplete_type_of(cx, &*repr, &name[..])
}
}
ty::ty_open(t) => match t.sty {
ty::ty_struct(..) => {
let p_ty = type_of(cx, t).ptr_to();
Type::struct_(cx, &[p_ty, type_of_unsize_info(cx, t)], false)
}
ty::ty_vec(ty, None) => {
let p_ty = type_of(cx, ty).ptr_to();
Type::struct_(cx, &[p_ty, type_of_unsize_info(cx, t)], false)
}
ty::ty_str => {
let p_ty = Type::i8p(cx);
Type::struct_(cx, &[p_ty, type_of_unsize_info(cx, t)], false)
}
ty::ty_trait(..) => Type::opaque_trait(cx),
_ => cx.sess().bug(&format!("ty_open with sized type: {}",
ppaux::ty_to_string(cx.tcx(), t)))
},
ty::ty_infer(..) => cx.sess().bug("type_of with ty_infer"),
ty::ty_projection(..) => cx.sess().bug("type_of with ty_projection"),
ty::ty_param(..) => cx.sess().bug("type_of with ty_param"),
@ -444,7 +437,7 @@ pub fn type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Type {
_ => ()
}
return llty;
llty
}
pub fn align_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>)
@ -453,37 +446,22 @@ pub fn align_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>)
machine::llalign_of_min(cx, llty)
}
// Want refinements! (Or case classes, I guess
#[derive(Copy)]
pub enum named_ty {
a_struct,
an_enum,
a_closure,
}
pub fn llvm_type_name<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
what: named_ty,
did: ast::DefId,
tps: &[Ty<'tcx>])
-> String {
let name = match what {
a_struct => "struct",
an_enum => "enum",
a_closure => return "closure".to_string(),
};
fn llvm_type_name<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
did: ast::DefId,
tps: &[Ty<'tcx>])
-> String {
let base = ty::item_path_str(cx.tcx(), did);
let strings: Vec<String> = tps.iter().map(|t| t.repr(cx.tcx())).collect();
let tstr = if strings.is_empty() {
base
} else {
format!("{}<{:?}>", base, strings)
format!("{}<{}>", base, strings.connect(", "))
};
if did.krate == 0 {
format!("{}.{}", name, tstr)
tstr
} else {
format!("{}.{}[{}{}]", name, tstr, "#", did.krate)
format!("{}.{}", did.krate, tstr)
}
}

View file

@ -305,9 +305,9 @@ fn create_region_substs<'tcx>(
rscope.anon_regions(span, expected_num_region_params);
if supplied_num_region_params != 0 || anon_regions.is_err() {
span_err!(tcx.sess, span, E0107,
"wrong number of lifetime parameters: expected {}, found {}",
expected_num_region_params, supplied_num_region_params);
report_lifetime_number_error(tcx, span,
supplied_num_region_params,
expected_num_region_params);
}
match anon_regions {
@ -355,31 +355,14 @@ fn create_substs_for_ast_path<'tcx>(
.count();
let mut type_substs = types_provided;
check_type_argument_count(this.tcx(), span, supplied_ty_param_count,
required_ty_param_count, formal_ty_param_count);
if supplied_ty_param_count < required_ty_param_count {
let expected = if required_ty_param_count < formal_ty_param_count {
"expected at least"
} else {
"expected"
};
span_err!(this.tcx().sess, span, E0243,
"wrong number of type arguments: {} {}, found {}",
expected,
required_ty_param_count,
supplied_ty_param_count);
while type_substs.len() < required_ty_param_count {
type_substs.push(tcx.types.err);
}
} else if supplied_ty_param_count > formal_ty_param_count {
let expected = if required_ty_param_count < formal_ty_param_count {
"expected at most"
} else {
"expected"
};
span_err!(this.tcx().sess, span, E0244,
"wrong number of type arguments: {} {}, found {}",
expected,
formal_ty_param_count,
supplied_ty_param_count);
type_substs.truncate(formal_ty_param_count);
}
assert!(type_substs.len() >= required_ty_param_count &&
@ -1847,7 +1830,16 @@ pub fn partition_bounds<'a>(tcx: &ty::ctxt,
if ty::try_add_builtin_trait(tcx,
trait_did,
&mut builtin_bounds) {
// FIXME(#20302) -- we should check for things like Copy<T>
let segments = &b.trait_ref.path.segments;
let parameters = &segments[segments.len() - 1].parameters;
if parameters.types().len() > 0 {
check_type_argument_count(tcx, b.trait_ref.path.span,
parameters.types().len(), 0, 0);
}
if parameters.lifetimes().len() > 0{
report_lifetime_number_error(tcx, b.trait_ref.path.span,
parameters.lifetimes().len(), 0);
}
continue; // success
}
}
@ -1880,3 +1872,34 @@ fn prohibit_projections<'tcx>(tcx: &ty::ctxt<'tcx>,
"associated type bindings are not allowed here");
}
}
fn check_type_argument_count(tcx: &ty::ctxt, span: Span, supplied: usize,
required: usize, accepted: usize) {
if supplied < required {
let expected = if required < accepted {
"expected at least"
} else {
"expected"
};
span_err!(tcx.sess, span, E0243,
"wrong number of type arguments: {} {}, found {}",
expected, required, supplied);
} else if supplied > accepted {
let expected = if required < accepted {
"expected at most"
} else {
"expected"
};
span_err!(tcx.sess, span, E0244,
"wrong number of type arguments: {} {}, found {}",
expected,
accepted,
supplied);
}
}
fn report_lifetime_number_error(tcx: &ty::ctxt, span: Span, number: usize, expected: usize) {
span_err!(tcx.sess, span, E0107,
"wrong number of lifetime parameters: expected {}, found {}",
expected, number);
}

View file

@ -161,12 +161,6 @@ impl<'a, 'tcx> Implicator<'a, 'tcx> {
// entering the fn check. We should do this after
// the fn check, then we can call this case a bug().
}
ty::ty_open(_) => {
self.tcx().sess.bug(
&format!("Unexpected type encountered while doing wf check: {}",
ty.repr(self.tcx())));
}
}
}

View file

@ -404,26 +404,9 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> {
all_substs.repr(self.tcx()));
// Instantiate the bounds on the method with the
// type/early-bound-regions substitutions performed. The only
// late-bound-regions that can appear in bounds are from the
// impl, and those were already instantiated above.
//
// FIXME(DST). Super hack. For a method on a trait object
// `Trait`, the generic signature requires that
// `Self:Trait`. Since, for an object, we bind `Self` to the
// type `Trait`, this leads to an obligation
// `Trait:Trait`. Until such time we DST is fully implemented,
// that obligation is not necessarily satisfied. (In the
// future, it would be.) But we know that the true `Self` DOES implement
// the trait. So we just delete this requirement. Hack hack hack.
let mut method_predicates = pick.method_ty.predicates.instantiate(self.tcx(), &all_substs);
match pick.kind {
probe::ObjectPick(..) => {
assert_eq!(method_predicates.predicates.get_slice(subst::SelfSpace).len(), 1);
method_predicates.predicates.pop(subst::SelfSpace);
}
_ => { }
}
// type/early-bound-regions substitutions performed. There can
// be no late-bound regions appearing here.
let method_predicates = pick.method_ty.predicates.instantiate(self.tcx(), &all_substs);
let method_predicates = self.fcx.normalize_associated_types_in(self.span,
&method_predicates);

View file

@ -133,14 +133,6 @@ pub fn check_object_safety<'tcx>(tcx: &ty::ctxt<'tcx>,
in the supertrait listing");
}
ObjectSafetyViolation::Method(method, MethodViolationCode::ByValueSelf) => {
tcx.sess.span_note(
span,
&format!("method `{}` has a receiver type of `Self`, \
which cannot be used with a trait object",
method.name.user_string(tcx)));
}
ObjectSafetyViolation::Method(method, MethodViolationCode::StaticMethod) => {
tcx.sess.span_note(
span,

View file

@ -25,7 +25,7 @@ use middle::ty::{ParameterEnvironment, TypeTraitItemId, lookup_item_type};
use middle::ty::{Ty, ty_bool, ty_char, ty_enum, ty_err};
use middle::ty::{ty_param, TypeScheme, ty_ptr};
use middle::ty::{ty_rptr, ty_struct, ty_trait, ty_tup};
use middle::ty::{ty_str, ty_vec, ty_float, ty_infer, ty_int, ty_open};
use middle::ty::{ty_str, ty_vec, ty_float, ty_infer, ty_int};
use middle::ty::{ty_uint, ty_closure, ty_uniq, ty_bare_fn};
use middle::ty::{ty_projection};
use middle::ty;
@ -75,7 +75,7 @@ fn get_base_type_def_id<'a, 'tcx>(inference_context: &InferCtxt<'a, 'tcx>,
ty_bool | ty_char | ty_int(..) | ty_uint(..) | ty_float(..) |
ty_str(..) | ty_vec(..) | ty_bare_fn(..) | ty_tup(..) |
ty_param(..) | ty_err | ty_open(..) |
ty_param(..) | ty_err |
ty_ptr(_) | ty_rptr(_, _) | ty_projection(..) => {
None
}

View file

@ -849,7 +849,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
self.add_constraints_from_mt(generics, mt, variance);
}
ty::ty_uniq(typ) | ty::ty_vec(typ, _) | ty::ty_open(typ) => {
ty::ty_uniq(typ) | ty::ty_vec(typ, _) => {
self.add_constraints_from_ty(generics, typ, variance);
}

View file

@ -1619,7 +1619,6 @@ impl<'tcx> Clean<Type> for ty::Ty<'tcx> {
ty::ty_closure(..) => Tuple(vec![]), // FIXME(pcwalton)
ty::ty_infer(..) => panic!("ty_infer"),
ty::ty_open(..) => panic!("ty_open"),
ty::ty_err => panic!("ty_err"),
}
}

View file

@ -37,6 +37,7 @@ pub trait OwnedAsciiExt {
/// Extension methods for ASCII-subset only operations on string slices
#[stable(feature = "rust1", since = "1.0.0")]
pub trait AsciiExt {
/// Container type for copied ASCII characters.
#[stable(feature = "rust1", since = "1.0.0")]
type Owned;

View file

@ -27,6 +27,7 @@ use marker;
/// to `Default` when asked to create a hasher.
#[unstable(feature = "std_misc", reason = "hasher stuff is unclear")]
pub trait HashState {
/// Type of the hasher that will be created.
type Hasher: hash::Hasher;
/// Creates a new hasher based on the given state of this object.

View file

@ -12,9 +12,11 @@ use core::prelude::*;
use boxed::Box;
use cmp;
use io::{self, SeekFrom, Read, Write, Seek, BufRead};
use io::{self, SeekFrom, Read, Write, Seek, BufRead, Error, ErrorKind};
use fmt;
use mem;
use slice;
use string::String;
use vec::Vec;
// =============================================================================
@ -22,9 +24,20 @@ use vec::Vec;
impl<'a, R: Read + ?Sized> Read for &'a mut R {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> { (**self).read(buf) }
fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<()> { (**self).read_to_end(buf) }
fn read_to_string(&mut self, buf: &mut String) -> io::Result<()> {
(**self).read_to_string(buf)
}
}
impl<'a, W: Write + ?Sized> Write for &'a mut W {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> { (**self).write(buf) }
fn write_all(&mut self, buf: &[u8]) -> io::Result<()> { (**self).write_all(buf) }
fn write_fmt(&mut self, fmt: fmt::Arguments) -> io::Result<()> { (**self).write_fmt(fmt) }
fn flush(&mut self) -> io::Result<()> { (**self).flush() }
}
impl<'a, S: Seek + ?Sized> Seek for &'a mut S {
@ -32,7 +45,14 @@ impl<'a, S: Seek + ?Sized> Seek for &'a mut S {
}
impl<'a, B: BufRead + ?Sized> BufRead for &'a mut B {
fn fill_buf(&mut self) -> io::Result<&[u8]> { (**self).fill_buf() }
fn consume(&mut self, amt: usize) { (**self).consume(amt) }
fn read_until(&mut self, byte: u8, buf: &mut Vec<u8>) -> io::Result<()> {
(**self).read_until(byte, buf)
}
fn read_line(&mut self, buf: &mut String) -> io::Result<()> { (**self).read_line(buf) }
}
impl<R: Read + ?Sized> Read for Box<R> {
@ -76,6 +96,15 @@ impl<'a> Write for &'a mut [u8] {
*self = b;
Ok(amt)
}
fn write_all(&mut self, data: &[u8]) -> io::Result<()> {
if try!(self.write(data)) == data.len() {
Ok(())
} else {
Err(Error::new(ErrorKind::WriteZero, "failed to write whole buffer", None))
}
}
fn flush(&mut self) -> io::Result<()> { Ok(()) }
}
@ -84,5 +113,11 @@ impl Write for Vec<u8> {
self.push_all(buf);
Ok(buf.len())
}
fn write_all(&mut self, buf: &[u8]) -> io::Result<()> {
try!(self.write(buf));
Ok(())
}
fn flush(&mut self) -> io::Result<()> { Ok(()) }
}

View file

@ -23,7 +23,6 @@
#[doc(no_inline)] pub use mem::drop;
// Reexported types and traits
#[stable(feature = "rust1", since = "1.0.0")]
#[doc(no_inline)] pub use boxed::Box;
#[stable(feature = "rust1", since = "1.0.0")]
@ -45,9 +44,7 @@
#[stable(feature = "rust1", since = "1.0.0")]
#[doc(no_inline)] pub use result::Result::{self, Ok, Err};
#[stable(feature = "rust1", since = "1.0.0")]
#[doc(no_inline)] pub use slice::AsSlice;
#[stable(feature = "rust1", since = "1.0.0")]
#[doc(no_inline)] pub use slice::{SliceExt, SliceConcatExt};
#[doc(no_inline)] pub use slice::{SliceExt, SliceConcatExt, AsSlice};
#[stable(feature = "rust1", since = "1.0.0")]
#[doc(no_inline)] pub use str::{Str, StrExt};
#[stable(feature = "rust1", since = "1.0.0")]

View file

@ -33,13 +33,13 @@ use sync::{Mutex, Condvar};
pub struct Barrier {
lock: Mutex<BarrierState>,
cvar: Condvar,
num_threads: uint,
num_threads: usize,
}
// The inner state of a double barrier
struct BarrierState {
count: uint,
generation_id: uint,
count: usize,
generation_id: usize,
}
/// A result returned from wait.
@ -54,7 +54,7 @@ impl Barrier {
/// A barrier will block `n`-1 threads which call `wait` and then wake up
/// all threads at once when the `n`th thread calls `wait`.
#[stable(feature = "rust1", since = "1.0.0")]
pub fn new(n: uint) -> Barrier {
pub fn new(n: usize) -> Barrier {
Barrier {
lock: Mutex::new(BarrierState {
count: 0,
@ -115,7 +115,7 @@ mod tests {
#[test]
fn test_barrier() {
const N: uint = 10;
const N: usize = 10;
let barrier = Arc::new(Barrier::new(N));
let (tx, rx) = channel();

View file

@ -327,7 +327,7 @@ impl StaticCondvar {
}
fn verify(&self, mutex: &sys_mutex::Mutex) {
let addr = mutex as *const _ as uint;
let addr = mutex as *const _ as usize;
match self.mutex.compare_and_swap(0, addr, Ordering::SeqCst) {
// If we got out 0, then we have successfully bound the mutex to
// this cvar.
@ -388,7 +388,7 @@ mod tests {
#[test]
fn notify_all() {
const N: uint = 10;
const N: usize = 10;
let data = Arc::new((Mutex::new(0), Condvar::new()));
let (tx, rx) = channel();

View file

@ -61,17 +61,17 @@ impl SignalToken {
wake
}
/// Convert to an unsafe uint value. Useful for storing in a pipe's state
/// Convert to an unsafe usize value. Useful for storing in a pipe's state
/// flag.
#[inline]
pub unsafe fn cast_to_uint(self) -> uint {
pub unsafe fn cast_to_usize(self) -> usize {
mem::transmute(self.inner)
}
/// Convert from an unsafe uint value. Useful for retrieving a pipe's state
/// Convert from an unsafe usize value. Useful for retrieving a pipe's state
/// flag.
#[inline]
pub unsafe fn cast_from_uint(signal_ptr: uint) -> SignalToken {
pub unsafe fn cast_from_usize(signal_ptr: usize) -> SignalToken {
SignalToken { inner: mem::transmute(signal_ptr) }
}

View file

@ -94,7 +94,7 @@
//!
//! // The call to recv() will return an error because the channel has already
//! // hung up (or been deallocated)
//! let (tx, rx) = channel::<int>();
//! let (tx, rx) = channel::<i32>();
//! drop(tx);
//! assert!(rx.recv().is_err());
//! ```
@ -105,7 +105,7 @@
//! use std::thread;
//! use std::sync::mpsc::sync_channel;
//!
//! let (tx, rx) = sync_channel::<int>(0);
//! let (tx, rx) = sync_channel::<i32>(0);
//! thread::spawn(move|| {
//! // This will wait for the parent task to start receiving
//! tx.send(53).unwrap();
@ -123,7 +123,7 @@
//! use std::old_io::timer::Timer;
//! use std::time::Duration;
//!
//! let (tx, rx) = channel::<int>();
//! let (tx, rx) = channel::<i32>();
//! let mut timer = Timer::new().unwrap();
//! let timeout = timer.oneshot(Duration::seconds(10));
//!
@ -147,7 +147,7 @@
//! use std::old_io::timer::Timer;
//! use std::time::Duration;
//!
//! let (tx, rx) = channel::<int>();
//! let (tx, rx) = channel::<i32>();
//! let mut timer = Timer::new().unwrap();
//!
//! loop {
@ -525,7 +525,7 @@ pub fn channel<T: Send>() -> (Sender<T>, Receiver<T>) {
/// assert_eq!(rx.recv().unwrap(), 2);
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
pub fn sync_channel<T: Send>(bound: uint) -> (SyncSender<T>, Receiver<T>) {
pub fn sync_channel<T: Send>(bound: usize) -> (SyncSender<T>, Receiver<T>) {
let a = Arc::new(UnsafeCell::new(sync::Packet::new(bound)));
(SyncSender::new(a.clone()), Receiver::new(Flavor::Sync(a)))
}
@ -1028,7 +1028,7 @@ mod test {
use super::*;
use thread;
pub fn stress_factor() -> uint {
pub fn stress_factor() -> usize {
match env::var("RUST_TEST_STRESS") {
Ok(val) => val.parse().unwrap(),
Err(..) => 1,
@ -1037,7 +1037,7 @@ mod test {
#[test]
fn smoke() {
let (tx, rx) = channel::<int>();
let (tx, rx) = channel::<i32>();
tx.send(1).unwrap();
assert_eq!(rx.recv().unwrap(), 1);
}
@ -1058,7 +1058,7 @@ mod test {
#[test]
fn smoke_shared() {
let (tx, rx) = channel::<int>();
let (tx, rx) = channel::<i32>();
tx.send(1).unwrap();
assert_eq!(rx.recv().unwrap(), 1);
let tx = tx.clone();
@ -1068,7 +1068,7 @@ mod test {
#[test]
fn smoke_threads() {
let (tx, rx) = channel::<int>();
let (tx, rx) = channel::<i32>();
let _t = thread::spawn(move|| {
tx.send(1).unwrap();
});
@ -1077,21 +1077,21 @@ mod test {
#[test]
fn smoke_port_gone() {
let (tx, rx) = channel::<int>();
let (tx, rx) = channel::<i32>();
drop(rx);
assert!(tx.send(1).is_err());
}
#[test]
fn smoke_shared_port_gone() {
let (tx, rx) = channel::<int>();
let (tx, rx) = channel::<i32>();
drop(rx);
assert!(tx.send(1).is_err())
}
#[test]
fn smoke_shared_port_gone2() {
let (tx, rx) = channel::<int>();
let (tx, rx) = channel::<i32>();
drop(rx);
let tx2 = tx.clone();
drop(tx);
@ -1100,7 +1100,7 @@ mod test {
#[test]
fn port_gone_concurrent() {
let (tx, rx) = channel::<int>();
let (tx, rx) = channel::<i32>();
let _t = thread::spawn(move|| {
rx.recv().unwrap();
});
@ -1109,7 +1109,7 @@ mod test {
#[test]
fn port_gone_concurrent_shared() {
let (tx, rx) = channel::<int>();
let (tx, rx) = channel::<i32>();
let tx2 = tx.clone();
let _t = thread::spawn(move|| {
rx.recv().unwrap();
@ -1119,7 +1119,7 @@ mod test {
#[test]
fn smoke_chan_gone() {
let (tx, rx) = channel::<int>();
let (tx, rx) = channel::<i32>();
drop(tx);
assert!(rx.recv().is_err());
}
@ -1135,7 +1135,7 @@ mod test {
#[test]
fn chan_gone_concurrent() {
let (tx, rx) = channel::<int>();
let (tx, rx) = channel::<i32>();
let _t = thread::spawn(move|| {
tx.send(1).unwrap();
tx.send(1).unwrap();
@ -1145,7 +1145,7 @@ mod test {
#[test]
fn stress() {
let (tx, rx) = channel::<int>();
let (tx, rx) = channel::<i32>();
let t = thread::spawn(move|| {
for _ in 0..10000 { tx.send(1).unwrap(); }
});
@ -1157,9 +1157,9 @@ mod test {
#[test]
fn stress_shared() {
static AMT: uint = 10000;
static NTHREADS: uint = 8;
let (tx, rx) = channel::<int>();
static AMT: u32 = 10000;
static NTHREADS: u32 = 8;
let (tx, rx) = channel::<i32>();
let t = thread::spawn(move|| {
for _ in 0..AMT * NTHREADS {
@ -1184,7 +1184,7 @@ mod test {
#[test]
fn send_from_outside_runtime() {
let (tx1, rx1) = channel::<()>();
let (tx2, rx2) = channel::<int>();
let (tx2, rx2) = channel::<i32>();
let t1 = thread::spawn(move|| {
tx1.send(()).unwrap();
for _ in 0..40 {
@ -1203,7 +1203,7 @@ mod test {
#[test]
fn recv_from_outside_runtime() {
let (tx, rx) = channel::<int>();
let (tx, rx) = channel::<i32>();
let t = thread::spawn(move|| {
for _ in 0..40 {
assert_eq!(rx.recv().unwrap(), 1);
@ -1217,8 +1217,8 @@ mod test {
#[test]
fn no_runtime() {
let (tx1, rx1) = channel::<int>();
let (tx2, rx2) = channel::<int>();
let (tx1, rx1) = channel::<i32>();
let (tx2, rx2) = channel::<i32>();
let t1 = thread::spawn(move|| {
assert_eq!(rx1.recv().unwrap(), 1);
tx2.send(2).unwrap();
@ -1234,21 +1234,21 @@ mod test {
#[test]
fn oneshot_single_thread_close_port_first() {
// Simple test of closing without sending
let (_tx, rx) = channel::<int>();
let (_tx, rx) = channel::<i32>();
drop(rx);
}
#[test]
fn oneshot_single_thread_close_chan_first() {
// Simple test of closing without sending
let (tx, _rx) = channel::<int>();
let (tx, _rx) = channel::<i32>();
drop(tx);
}
#[test]
fn oneshot_single_thread_send_port_close() {
// Testing that the sender cleans up the payload if receiver is closed
let (tx, rx) = channel::<Box<int>>();
let (tx, rx) = channel::<Box<i32>>();
drop(rx);
assert!(tx.send(box 0).is_err());
}
@ -1257,7 +1257,7 @@ mod test {
fn oneshot_single_thread_recv_chan_close() {
// Receiving on a closed chan will panic
let res = thread::spawn(move|| {
let (tx, rx) = channel::<int>();
let (tx, rx) = channel::<i32>();
drop(tx);
rx.recv().unwrap();
}).join();
@ -1267,42 +1267,42 @@ mod test {
#[test]
fn oneshot_single_thread_send_then_recv() {
let (tx, rx) = channel::<Box<int>>();
let (tx, rx) = channel::<Box<i32>>();
tx.send(box 10).unwrap();
assert!(rx.recv().unwrap() == box 10);
}
#[test]
fn oneshot_single_thread_try_send_open() {
let (tx, rx) = channel::<int>();
let (tx, rx) = channel::<i32>();
assert!(tx.send(10).is_ok());
assert!(rx.recv().unwrap() == 10);
}
#[test]
fn oneshot_single_thread_try_send_closed() {
let (tx, rx) = channel::<int>();
let (tx, rx) = channel::<i32>();
drop(rx);
assert!(tx.send(10).is_err());
}
#[test]
fn oneshot_single_thread_try_recv_open() {
let (tx, rx) = channel::<int>();
let (tx, rx) = channel::<i32>();
tx.send(10).unwrap();
assert!(rx.recv() == Ok(10));
}
#[test]
fn oneshot_single_thread_try_recv_closed() {
let (tx, rx) = channel::<int>();
let (tx, rx) = channel::<i32>();
drop(tx);
assert!(rx.recv().is_err());
}
#[test]
fn oneshot_single_thread_peek_data() {
let (tx, rx) = channel::<int>();
let (tx, rx) = channel::<i32>();
assert_eq!(rx.try_recv(), Err(TryRecvError::Empty));
tx.send(10).unwrap();
assert_eq!(rx.try_recv(), Ok(10));
@ -1310,7 +1310,7 @@ mod test {
#[test]
fn oneshot_single_thread_peek_close() {
let (tx, rx) = channel::<int>();
let (tx, rx) = channel::<i32>();
drop(tx);
assert_eq!(rx.try_recv(), Err(TryRecvError::Disconnected));
assert_eq!(rx.try_recv(), Err(TryRecvError::Disconnected));
@ -1318,13 +1318,13 @@ mod test {
#[test]
fn oneshot_single_thread_peek_open() {
let (_tx, rx) = channel::<int>();
let (_tx, rx) = channel::<i32>();
assert_eq!(rx.try_recv(), Err(TryRecvError::Empty));
}
#[test]
fn oneshot_multi_task_recv_then_send() {
let (tx, rx) = channel::<Box<int>>();
let (tx, rx) = channel::<Box<i32>>();
let _t = thread::spawn(move|| {
assert!(rx.recv().unwrap() == box 10);
});
@ -1334,7 +1334,7 @@ mod test {
#[test]
fn oneshot_multi_task_recv_then_close() {
let (tx, rx) = channel::<Box<int>>();
let (tx, rx) = channel::<Box<i32>>();
let _t = thread::spawn(move|| {
drop(tx);
});
@ -1347,7 +1347,7 @@ mod test {
#[test]
fn oneshot_multi_thread_close_stress() {
for _ in 0..stress_factor() {
let (tx, rx) = channel::<int>();
let (tx, rx) = channel::<i32>();
let _t = thread::spawn(move|| {
drop(rx);
});
@ -1358,7 +1358,7 @@ mod test {
#[test]
fn oneshot_multi_thread_send_close_stress() {
for _ in 0..stress_factor() {
let (tx, rx) = channel::<int>();
let (tx, rx) = channel::<i32>();
let _t = thread::spawn(move|| {
drop(rx);
});
@ -1371,7 +1371,7 @@ mod test {
#[test]
fn oneshot_multi_thread_recv_close_stress() {
for _ in 0..stress_factor() {
let (tx, rx) = channel::<int>();
let (tx, rx) = channel::<i32>();
thread::spawn(move|| {
let res = thread::spawn(move|| {
rx.recv().unwrap();
@ -1405,7 +1405,7 @@ mod test {
send(tx, 0);
recv(rx, 0);
fn send(tx: Sender<Box<int>>, i: int) {
fn send(tx: Sender<Box<i32>>, i: i32) {
if i == 10 { return }
thread::spawn(move|| {
@ -1414,7 +1414,7 @@ mod test {
});
}
fn recv(rx: Receiver<Box<int>>, i: int) {
fn recv(rx: Receiver<Box<i32>>, i: i32) {
if i == 10 { return }
thread::spawn(move|| {
@ -1451,8 +1451,8 @@ mod test {
#[test]
fn test_nested_recv_iter() {
let (tx, rx) = channel::<int>();
let (total_tx, total_rx) = channel::<int>();
let (tx, rx) = channel::<i32>();
let (total_tx, total_rx) = channel::<i32>();
let _t = thread::spawn(move|| {
let mut acc = 0;
@ -1471,7 +1471,7 @@ mod test {
#[test]
fn test_recv_iter_break() {
let (tx, rx) = channel::<int>();
let (tx, rx) = channel::<i32>();
let (count_tx, count_rx) = channel();
let _t = thread::spawn(move|| {
@ -1496,7 +1496,7 @@ mod test {
#[test]
fn try_recv_states() {
let (tx1, rx1) = channel::<int>();
let (tx1, rx1) = channel::<i32>();
let (tx2, rx2) = channel::<()>();
let (tx3, rx3) = channel::<()>();
let _t = thread::spawn(move|| {
@ -1550,7 +1550,7 @@ mod sync_tests {
use thread;
use super::*;
pub fn stress_factor() -> uint {
pub fn stress_factor() -> usize {
match env::var("RUST_TEST_STRESS") {
Ok(val) => val.parse().unwrap(),
Err(..) => 1,
@ -1559,7 +1559,7 @@ mod sync_tests {
#[test]
fn smoke() {
let (tx, rx) = sync_channel::<int>(1);
let (tx, rx) = sync_channel::<i32>(1);
tx.send(1).unwrap();
assert_eq!(rx.recv().unwrap(), 1);
}
@ -1572,7 +1572,7 @@ mod sync_tests {
#[test]
fn smoke_shared() {
let (tx, rx) = sync_channel::<int>(1);
let (tx, rx) = sync_channel::<i32>(1);
tx.send(1).unwrap();
assert_eq!(rx.recv().unwrap(), 1);
let tx = tx.clone();
@ -1582,7 +1582,7 @@ mod sync_tests {
#[test]
fn smoke_threads() {
let (tx, rx) = sync_channel::<int>(0);
let (tx, rx) = sync_channel::<i32>(0);
let _t = thread::spawn(move|| {
tx.send(1).unwrap();
});
@ -1591,14 +1591,14 @@ mod sync_tests {
#[test]
fn smoke_port_gone() {
let (tx, rx) = sync_channel::<int>(0);
let (tx, rx) = sync_channel::<i32>(0);
drop(rx);
assert!(tx.send(1).is_err());
}
#[test]
fn smoke_shared_port_gone2() {
let (tx, rx) = sync_channel::<int>(0);
let (tx, rx) = sync_channel::<i32>(0);
drop(rx);
let tx2 = tx.clone();
drop(tx);
@ -1607,7 +1607,7 @@ mod sync_tests {
#[test]
fn port_gone_concurrent() {
let (tx, rx) = sync_channel::<int>(0);
let (tx, rx) = sync_channel::<i32>(0);
let _t = thread::spawn(move|| {
rx.recv().unwrap();
});
@ -1616,7 +1616,7 @@ mod sync_tests {
#[test]
fn port_gone_concurrent_shared() {
let (tx, rx) = sync_channel::<int>(0);
let (tx, rx) = sync_channel::<i32>(0);
let tx2 = tx.clone();
let _t = thread::spawn(move|| {
rx.recv().unwrap();
@ -1626,7 +1626,7 @@ mod sync_tests {
#[test]
fn smoke_chan_gone() {
let (tx, rx) = sync_channel::<int>(0);
let (tx, rx) = sync_channel::<i32>(0);
drop(tx);
assert!(rx.recv().is_err());
}
@ -1642,7 +1642,7 @@ mod sync_tests {
#[test]
fn chan_gone_concurrent() {
let (tx, rx) = sync_channel::<int>(0);
let (tx, rx) = sync_channel::<i32>(0);
thread::spawn(move|| {
tx.send(1).unwrap();
tx.send(1).unwrap();
@ -1652,7 +1652,7 @@ mod sync_tests {
#[test]
fn stress() {
let (tx, rx) = sync_channel::<int>(0);
let (tx, rx) = sync_channel::<i32>(0);
thread::spawn(move|| {
for _ in 0..10000 { tx.send(1).unwrap(); }
});
@ -1663,9 +1663,9 @@ mod sync_tests {
#[test]
fn stress_shared() {
static AMT: uint = 1000;
static NTHREADS: uint = 8;
let (tx, rx) = sync_channel::<int>(0);
static AMT: u32 = 1000;
static NTHREADS: u32 = 8;
let (tx, rx) = sync_channel::<i32>(0);
let (dtx, drx) = sync_channel::<()>(0);
thread::spawn(move|| {
@ -1692,21 +1692,21 @@ mod sync_tests {
#[test]
fn oneshot_single_thread_close_port_first() {
// Simple test of closing without sending
let (_tx, rx) = sync_channel::<int>(0);
let (_tx, rx) = sync_channel::<i32>(0);
drop(rx);
}
#[test]
fn oneshot_single_thread_close_chan_first() {
// Simple test of closing without sending
let (tx, _rx) = sync_channel::<int>(0);
let (tx, _rx) = sync_channel::<i32>(0);
drop(tx);
}
#[test]
fn oneshot_single_thread_send_port_close() {
// Testing that the sender cleans up the payload if receiver is closed
let (tx, rx) = sync_channel::<Box<int>>(0);
let (tx, rx) = sync_channel::<Box<i32>>(0);
drop(rx);
assert!(tx.send(box 0).is_err());
}
@ -1715,7 +1715,7 @@ mod sync_tests {
fn oneshot_single_thread_recv_chan_close() {
// Receiving on a closed chan will panic
let res = thread::spawn(move|| {
let (tx, rx) = sync_channel::<int>(0);
let (tx, rx) = sync_channel::<i32>(0);
drop(tx);
rx.recv().unwrap();
}).join();
@ -1725,48 +1725,48 @@ mod sync_tests {
#[test]
fn oneshot_single_thread_send_then_recv() {
let (tx, rx) = sync_channel::<Box<int>>(1);
let (tx, rx) = sync_channel::<Box<i32>>(1);
tx.send(box 10).unwrap();
assert!(rx.recv().unwrap() == box 10);
}
#[test]
fn oneshot_single_thread_try_send_open() {
let (tx, rx) = sync_channel::<int>(1);
let (tx, rx) = sync_channel::<i32>(1);
assert_eq!(tx.try_send(10), Ok(()));
assert!(rx.recv().unwrap() == 10);
}
#[test]
fn oneshot_single_thread_try_send_closed() {
let (tx, rx) = sync_channel::<int>(0);
let (tx, rx) = sync_channel::<i32>(0);
drop(rx);
assert_eq!(tx.try_send(10), Err(TrySendError::Disconnected(10)));
}
#[test]
fn oneshot_single_thread_try_send_closed2() {
let (tx, _rx) = sync_channel::<int>(0);
let (tx, _rx) = sync_channel::<i32>(0);
assert_eq!(tx.try_send(10), Err(TrySendError::Full(10)));
}
#[test]
fn oneshot_single_thread_try_recv_open() {
let (tx, rx) = sync_channel::<int>(1);
let (tx, rx) = sync_channel::<i32>(1);
tx.send(10).unwrap();
assert!(rx.recv() == Ok(10));
}
#[test]
fn oneshot_single_thread_try_recv_closed() {
let (tx, rx) = sync_channel::<int>(0);
let (tx, rx) = sync_channel::<i32>(0);
drop(tx);
assert!(rx.recv().is_err());
}
#[test]
fn oneshot_single_thread_peek_data() {
let (tx, rx) = sync_channel::<int>(1);
let (tx, rx) = sync_channel::<i32>(1);
assert_eq!(rx.try_recv(), Err(TryRecvError::Empty));
tx.send(10).unwrap();
assert_eq!(rx.try_recv(), Ok(10));
@ -1774,7 +1774,7 @@ mod sync_tests {
#[test]
fn oneshot_single_thread_peek_close() {
let (tx, rx) = sync_channel::<int>(0);
let (tx, rx) = sync_channel::<i32>(0);
drop(tx);
assert_eq!(rx.try_recv(), Err(TryRecvError::Disconnected));
assert_eq!(rx.try_recv(), Err(TryRecvError::Disconnected));
@ -1782,13 +1782,13 @@ mod sync_tests {
#[test]
fn oneshot_single_thread_peek_open() {
let (_tx, rx) = sync_channel::<int>(0);
let (_tx, rx) = sync_channel::<i32>(0);
assert_eq!(rx.try_recv(), Err(TryRecvError::Empty));
}
#[test]
fn oneshot_multi_task_recv_then_send() {
let (tx, rx) = sync_channel::<Box<int>>(0);
let (tx, rx) = sync_channel::<Box<i32>>(0);
let _t = thread::spawn(move|| {
assert!(rx.recv().unwrap() == box 10);
});
@ -1798,7 +1798,7 @@ mod sync_tests {
#[test]
fn oneshot_multi_task_recv_then_close() {
let (tx, rx) = sync_channel::<Box<int>>(0);
let (tx, rx) = sync_channel::<Box<i32>>(0);
let _t = thread::spawn(move|| {
drop(tx);
});
@ -1811,7 +1811,7 @@ mod sync_tests {
#[test]
fn oneshot_multi_thread_close_stress() {
for _ in 0..stress_factor() {
let (tx, rx) = sync_channel::<int>(0);
let (tx, rx) = sync_channel::<i32>(0);
let _t = thread::spawn(move|| {
drop(rx);
});
@ -1822,7 +1822,7 @@ mod sync_tests {
#[test]
fn oneshot_multi_thread_send_close_stress() {
for _ in 0..stress_factor() {
let (tx, rx) = sync_channel::<int>(0);
let (tx, rx) = sync_channel::<i32>(0);
let _t = thread::spawn(move|| {
drop(rx);
});
@ -1835,7 +1835,7 @@ mod sync_tests {
#[test]
fn oneshot_multi_thread_recv_close_stress() {
for _ in 0..stress_factor() {
let (tx, rx) = sync_channel::<int>(0);
let (tx, rx) = sync_channel::<i32>(0);
let _t = thread::spawn(move|| {
let res = thread::spawn(move|| {
rx.recv().unwrap();
@ -1853,7 +1853,7 @@ mod sync_tests {
#[test]
fn oneshot_multi_thread_send_recv_stress() {
for _ in 0..stress_factor() {
let (tx, rx) = sync_channel::<Box<int>>(0);
let (tx, rx) = sync_channel::<Box<i32>>(0);
let _t = thread::spawn(move|| {
tx.send(box 10).unwrap();
});
@ -1864,12 +1864,12 @@ mod sync_tests {
#[test]
fn stream_send_recv_stress() {
for _ in 0..stress_factor() {
let (tx, rx) = sync_channel::<Box<int>>(0);
let (tx, rx) = sync_channel::<Box<i32>>(0);
send(tx, 0);
recv(rx, 0);
fn send(tx: SyncSender<Box<int>>, i: int) {
fn send(tx: SyncSender<Box<i32>>, i: i32) {
if i == 10 { return }
thread::spawn(move|| {
@ -1878,7 +1878,7 @@ mod sync_tests {
});
}
fn recv(rx: Receiver<Box<int>>, i: int) {
fn recv(rx: Receiver<Box<i32>>, i: i32) {
if i == 10 { return }
thread::spawn(move|| {
@ -1915,8 +1915,8 @@ mod sync_tests {
#[test]
fn test_nested_recv_iter() {
let (tx, rx) = sync_channel::<int>(0);
let (total_tx, total_rx) = sync_channel::<int>(0);
let (tx, rx) = sync_channel::<i32>(0);
let (total_tx, total_rx) = sync_channel::<i32>(0);
let _t = thread::spawn(move|| {
let mut acc = 0;
@ -1935,7 +1935,7 @@ mod sync_tests {
#[test]
fn test_recv_iter_break() {
let (tx, rx) = sync_channel::<int>(0);
let (tx, rx) = sync_channel::<i32>(0);
let (count_tx, count_rx) = sync_channel(0);
let _t = thread::spawn(move|| {
@ -1960,7 +1960,7 @@ mod sync_tests {
#[test]
fn try_recv_states() {
let (tx1, rx1) = sync_channel::<int>(1);
let (tx1, rx1) = sync_channel::<i32>(1);
let (tx2, rx2) = sync_channel::<()>(1);
let (tx3, rx3) = sync_channel::<()>(1);
let _t = thread::spawn(move|| {
@ -2007,21 +2007,21 @@ mod sync_tests {
#[test]
fn send1() {
let (tx, rx) = sync_channel::<int>(0);
let (tx, rx) = sync_channel::<i32>(0);
let _t = thread::spawn(move|| { rx.recv().unwrap(); });
assert_eq!(tx.send(1), Ok(()));
}
#[test]
fn send2() {
let (tx, rx) = sync_channel::<int>(0);
let (tx, rx) = sync_channel::<i32>(0);
let _t = thread::spawn(move|| { drop(rx); });
assert!(tx.send(1).is_err());
}
#[test]
fn send3() {
let (tx, rx) = sync_channel::<int>(1);
let (tx, rx) = sync_channel::<i32>(1);
assert_eq!(tx.send(1), Ok(()));
let _t =thread::spawn(move|| { drop(rx); });
assert!(tx.send(1).is_err());
@ -2029,7 +2029,7 @@ mod sync_tests {
#[test]
fn send4() {
let (tx, rx) = sync_channel::<int>(0);
let (tx, rx) = sync_channel::<i32>(0);
let tx2 = tx.clone();
let (done, donerx) = channel();
let done2 = done.clone();
@ -2048,20 +2048,20 @@ mod sync_tests {
#[test]
fn try_send1() {
let (tx, _rx) = sync_channel::<int>(0);
let (tx, _rx) = sync_channel::<i32>(0);
assert_eq!(tx.try_send(1), Err(TrySendError::Full(1)));
}
#[test]
fn try_send2() {
let (tx, _rx) = sync_channel::<int>(1);
let (tx, _rx) = sync_channel::<i32>(1);
assert_eq!(tx.try_send(1), Ok(()));
assert_eq!(tx.try_send(1), Err(TrySendError::Full(1)));
}
#[test]
fn try_send3() {
let (tx, rx) = sync_channel::<int>(1);
let (tx, rx) = sync_channel::<i32>(1);
assert_eq!(tx.try_send(1), Ok(()));
drop(rx);
assert_eq!(tx.try_send(1), Err(TrySendError::Disconnected(1)));

View file

@ -22,7 +22,7 @@
///
/// # Implementation
///
/// Oneshots are implemented around one atomic uint variable. This variable
/// Oneshots are implemented around one atomic usize variable. This variable
/// indicates both the state of the port/chan but also contains any tasks
/// blocked on the port. All atomic operations happen on this one word.
///
@ -45,9 +45,9 @@ use core::mem;
use sync::atomic::{AtomicUsize, Ordering};
// Various states you can find a port in.
const EMPTY: uint = 0; // initial state: no data, no blocked receiver
const DATA: uint = 1; // data ready for receiver to take
const DISCONNECTED: uint = 2; // channel is disconnected OR upgraded
const EMPTY: usize = 0; // initial state: no data, no blocked receiver
const DATA: usize = 1; // data ready for receiver to take
const DISCONNECTED: usize = 2; // channel is disconnected OR upgraded
// Any other value represents a pointer to a SignalToken value. The
// protocol ensures that when the state moves *to* a pointer,
// ownership of the token is given to the packet, and when the state
@ -123,7 +123,7 @@ impl<T: Send> Packet<T> {
// There is a thread waiting on the other end. We leave the 'DATA'
// state inside so it'll pick it up on the other end.
ptr => unsafe {
SignalToken::cast_from_uint(ptr).signal();
SignalToken::cast_from_usize(ptr).signal();
Ok(())
}
}
@ -143,7 +143,7 @@ impl<T: Send> Packet<T> {
// like we're not empty, then immediately go through to `try_recv`.
if self.state.load(Ordering::SeqCst) == EMPTY {
let (wait_token, signal_token) = blocking::tokens();
let ptr = unsafe { signal_token.cast_to_uint() };
let ptr = unsafe { signal_token.cast_to_usize() };
// race with senders to enter the blocking state
if self.state.compare_and_swap(EMPTY, ptr, Ordering::SeqCst) == EMPTY {
@ -151,7 +151,7 @@ impl<T: Send> Packet<T> {
debug_assert!(self.state.load(Ordering::SeqCst) != EMPTY);
} else {
// drop the signal token, since we never blocked
drop(unsafe { SignalToken::cast_from_uint(ptr) });
drop(unsafe { SignalToken::cast_from_usize(ptr) });
}
}
@ -220,7 +220,7 @@ impl<T: Send> Packet<T> {
DISCONNECTED => { self.upgrade = prev; UpDisconnected }
// If someone's waiting, we gotta wake them up
ptr => UpWoke(unsafe { SignalToken::cast_from_uint(ptr) })
ptr => UpWoke(unsafe { SignalToken::cast_from_usize(ptr) })
}
}
@ -230,7 +230,7 @@ impl<T: Send> Packet<T> {
// If someone's waiting, we gotta wake them up
ptr => unsafe {
SignalToken::cast_from_uint(ptr).signal();
SignalToken::cast_from_usize(ptr).signal();
}
}
}
@ -283,15 +283,15 @@ impl<T: Send> Packet<T> {
// Attempts to start selection on this port. This can either succeed, fail
// because there is data, or fail because there is an upgrade pending.
pub fn start_selection(&mut self, token: SignalToken) -> SelectionResult<T> {
let ptr = unsafe { token.cast_to_uint() };
let ptr = unsafe { token.cast_to_usize() };
match self.state.compare_and_swap(EMPTY, ptr, Ordering::SeqCst) {
EMPTY => SelSuccess,
DATA => {
drop(unsafe { SignalToken::cast_from_uint(ptr) });
drop(unsafe { SignalToken::cast_from_usize(ptr) });
SelCanceled
}
DISCONNECTED if self.data.is_some() => {
drop(unsafe { SignalToken::cast_from_uint(ptr) });
drop(unsafe { SignalToken::cast_from_usize(ptr) });
SelCanceled
}
DISCONNECTED => {
@ -300,7 +300,7 @@ impl<T: Send> Packet<T> {
// propagate upwards whether the upgrade can receive
// data
GoUp(upgrade) => {
SelUpgraded(unsafe { SignalToken::cast_from_uint(ptr) }, upgrade)
SelUpgraded(unsafe { SignalToken::cast_from_usize(ptr) }, upgrade)
}
// If the other end disconnected without sending an
@ -308,7 +308,7 @@ impl<T: Send> Packet<T> {
// disconnected).
up => {
self.upgrade = up;
drop(unsafe { SignalToken::cast_from_uint(ptr) });
drop(unsafe { SignalToken::cast_from_usize(ptr) });
SelCanceled
}
}
@ -360,7 +360,7 @@ impl<T: Send> Packet<T> {
// We woke ourselves up from select.
ptr => unsafe {
drop(SignalToken::cast_from_uint(ptr));
drop(SignalToken::cast_from_usize(ptr));
Ok(false)
}
}

View file

@ -71,7 +71,7 @@ use sync::mpsc::blocking::{self, SignalToken};
pub struct Select {
head: *mut Handle<'static, ()>,
tail: *mut Handle<'static, ()>,
next_id: Cell<uint>,
next_id: Cell<usize>,
}
impl !marker::Send for Select {}
@ -82,7 +82,7 @@ impl !marker::Send for Select {}
pub struct Handle<'rx, T:'rx> {
/// The ID of this handle, used to compare against the return value of
/// `Select::wait()`
id: uint,
id: usize,
selector: &'rx Select,
next: *mut Handle<'static, ()>,
prev: *mut Handle<'static, ()>,
@ -154,12 +154,12 @@ impl Select {
/// the matching `id` will have some sort of event available on it. The
/// event could either be that data is available or the corresponding
/// channel has been closed.
pub fn wait(&self) -> uint {
pub fn wait(&self) -> usize {
self.wait2(true)
}
/// Helper method for skipping the preflight checks during testing
fn wait2(&self, do_preflight_checks: bool) -> uint {
fn wait2(&self, do_preflight_checks: bool) -> usize {
// Note that this is currently an inefficient implementation. We in
// theory have knowledge about all receivers in the set ahead of time,
// so this method shouldn't really have to iterate over all of them yet
@ -254,7 +254,7 @@ impl Select {
impl<'rx, T: Send> Handle<'rx, T> {
/// Retrieve the id of this handle.
#[inline]
pub fn id(&self) -> uint { self.id }
pub fn id(&self) -> usize { self.id }
/// Block to receive a value on the underlying receiver, returning `Some` on
/// success or `None` if the channel disconnects. This function has the same
@ -369,8 +369,8 @@ mod test {
#[test]
fn smoke() {
let (tx1, rx1) = channel::<int>();
let (tx2, rx2) = channel::<int>();
let (tx1, rx1) = channel::<i32>();
let (tx2, rx2) = channel::<i32>();
tx1.send(1).unwrap();
select! {
foo = rx1.recv() => { assert_eq!(foo.unwrap(), 1); },
@ -394,11 +394,11 @@ mod test {
#[test]
fn smoke2() {
let (_tx1, rx1) = channel::<int>();
let (_tx2, rx2) = channel::<int>();
let (_tx3, rx3) = channel::<int>();
let (_tx4, rx4) = channel::<int>();
let (tx5, rx5) = channel::<int>();
let (_tx1, rx1) = channel::<i32>();
let (_tx2, rx2) = channel::<i32>();
let (_tx3, rx3) = channel::<i32>();
let (_tx4, rx4) = channel::<i32>();
let (tx5, rx5) = channel::<i32>();
tx5.send(4).unwrap();
select! {
_foo = rx1.recv() => { panic!("1") },
@ -411,8 +411,8 @@ mod test {
#[test]
fn closed() {
let (_tx1, rx1) = channel::<int>();
let (tx2, rx2) = channel::<int>();
let (_tx1, rx1) = channel::<i32>();
let (tx2, rx2) = channel::<i32>();
drop(tx2);
select! {
@ -423,9 +423,9 @@ mod test {
#[test]
fn unblocks() {
let (tx1, rx1) = channel::<int>();
let (_tx2, rx2) = channel::<int>();
let (tx3, rx3) = channel::<int>();
let (tx1, rx1) = channel::<i32>();
let (_tx2, rx2) = channel::<i32>();
let (tx3, rx3) = channel::<i32>();
let _t = thread::spawn(move|| {
for _ in 0..20 { thread::yield_now(); }
@ -447,8 +447,8 @@ mod test {
#[test]
fn both_ready() {
let (tx1, rx1) = channel::<int>();
let (tx2, rx2) = channel::<int>();
let (tx1, rx1) = channel::<i32>();
let (tx2, rx2) = channel::<i32>();
let (tx3, rx3) = channel::<()>();
let _t = thread::spawn(move|| {
@ -473,9 +473,9 @@ mod test {
#[test]
fn stress() {
static AMT: int = 10000;
let (tx1, rx1) = channel::<int>();
let (tx2, rx2) = channel::<int>();
static AMT: i32 = 10000;
let (tx1, rx1) = channel::<i32>();
let (tx2, rx2) = channel::<i32>();
let (tx3, rx3) = channel::<()>();
let _t = thread::spawn(move|| {
@ -500,8 +500,8 @@ mod test {
#[test]
fn cloning() {
let (tx1, rx1) = channel::<int>();
let (_tx2, rx2) = channel::<int>();
let (tx1, rx1) = channel::<i32>();
let (_tx2, rx2) = channel::<i32>();
let (tx3, rx3) = channel::<()>();
let _t = thread::spawn(move|| {
@ -522,8 +522,8 @@ mod test {
#[test]
fn cloning2() {
let (tx1, rx1) = channel::<int>();
let (_tx2, rx2) = channel::<int>();
let (tx1, rx1) = channel::<i32>();
let (_tx2, rx2) = channel::<i32>();
let (tx3, rx3) = channel::<()>();
let _t = thread::spawn(move|| {
@ -716,7 +716,7 @@ mod test {
#[test]
fn sync1() {
let (tx, rx) = sync_channel::<int>(1);
let (tx, rx) = sync_channel::<i32>(1);
tx.send(1).unwrap();
select! {
n = rx.recv() => { assert_eq!(n.unwrap(), 1); }
@ -725,7 +725,7 @@ mod test {
#[test]
fn sync2() {
let (tx, rx) = sync_channel::<int>(0);
let (tx, rx) = sync_channel::<i32>(0);
let _t = thread::spawn(move|| {
for _ in 0..100 { thread::yield_now() }
tx.send(1).unwrap();
@ -737,8 +737,8 @@ mod test {
#[test]
fn sync3() {
let (tx1, rx1) = sync_channel::<int>(0);
let (tx2, rx2): (Sender<int>, Receiver<int>) = channel();
let (tx1, rx1) = sync_channel::<i32>(0);
let (tx2, rx2): (Sender<i32>, Receiver<i32>) = channel();
let _t = thread::spawn(move|| { tx1.send(1).unwrap(); });
let _t = thread::spawn(move|| { tx2.send(2).unwrap(); });
select! {

View file

@ -101,7 +101,7 @@ impl<T: Send> Packet<T> {
token.map(|token| {
assert_eq!(self.cnt.load(Ordering::SeqCst), 0);
assert_eq!(self.to_wake.load(Ordering::SeqCst), 0);
self.to_wake.store(unsafe { token.cast_to_uint() }, Ordering::SeqCst);
self.to_wake.store(unsafe { token.cast_to_usize() }, Ordering::SeqCst);
self.cnt.store(-1, Ordering::SeqCst);
// This store is a little sketchy. What's happening here is that
@ -241,7 +241,7 @@ impl<T: Send> Packet<T> {
// Returns true if blocking should proceed.
fn decrement(&mut self, token: SignalToken) -> StartResult {
assert_eq!(self.to_wake.load(Ordering::SeqCst), 0);
let ptr = unsafe { token.cast_to_uint() };
let ptr = unsafe { token.cast_to_usize() };
self.to_wake.store(ptr, Ordering::SeqCst);
let steals = self.steals;
@ -258,7 +258,7 @@ impl<T: Send> Packet<T> {
}
self.to_wake.store(0, Ordering::SeqCst);
drop(unsafe { SignalToken::cast_from_uint(ptr) });
drop(unsafe { SignalToken::cast_from_usize(ptr) });
Abort
}
@ -380,7 +380,7 @@ impl<T: Send> Packet<T> {
let ptr = self.to_wake.load(Ordering::SeqCst);
self.to_wake.store(0, Ordering::SeqCst);
assert!(ptr != 0);
unsafe { SignalToken::cast_from_uint(ptr) }
unsafe { SignalToken::cast_from_usize(ptr) }
}
////////////////////////////////////////////////////////////////////////////

View file

@ -69,7 +69,7 @@ pub struct Queue<T> {
// Cache maintenance fields. Additions and subtractions are stored
// separately in order to allow them to use nonatomic addition/subtraction.
cache_bound: uint,
cache_bound: usize,
cache_additions: AtomicUsize,
cache_subtractions: AtomicUsize,
}
@ -107,7 +107,7 @@ impl<T: Send> Queue<T> {
/// cache (if desired). If the value is 0, then the cache has
/// no bound. Otherwise, the cache will never grow larger than
/// `bound` (although the queue itself could be much larger.
pub unsafe fn new(bound: uint) -> Queue<T> {
pub unsafe fn new(bound: usize) -> Queue<T> {
let n1 = Node::new();
let n2 = Node::new();
(*n1).next.store(n2, Ordering::Relaxed);
@ -319,7 +319,7 @@ mod test {
stress_bound(1);
}
unsafe fn stress_bound(bound: uint) {
unsafe fn stress_bound(bound: usize) {
let q = Arc::new(Queue::new(bound));
let (tx, rx) = channel();

View file

@ -43,7 +43,7 @@ pub struct Packet<T> {
queue: spsc::Queue<Message<T>>, // internal queue for all message
cnt: AtomicIsize, // How many items are on this channel
steals: int, // How many times has a port received without blocking?
steals: isize, // How many times has a port received without blocking?
to_wake: AtomicUsize, // SignalToken for the blocked thread to wake up
port_dropped: AtomicBool, // flag if the channel has been destroyed.
@ -146,7 +146,7 @@ impl<T: Send> Packet<T> {
let ptr = self.to_wake.load(Ordering::SeqCst);
self.to_wake.store(0, Ordering::SeqCst);
assert!(ptr != 0);
unsafe { SignalToken::cast_from_uint(ptr) }
unsafe { SignalToken::cast_from_usize(ptr) }
}
// Decrements the count on the channel for a sleeper, returning the sleeper
@ -154,7 +154,7 @@ impl<T: Send> Packet<T> {
// steals into account.
fn decrement(&mut self, token: SignalToken) -> Result<(), SignalToken> {
assert_eq!(self.to_wake.load(Ordering::SeqCst), 0);
let ptr = unsafe { token.cast_to_uint() };
let ptr = unsafe { token.cast_to_usize() };
self.to_wake.store(ptr, Ordering::SeqCst);
let steals = self.steals;
@ -171,7 +171,7 @@ impl<T: Send> Packet<T> {
}
self.to_wake.store(0, Ordering::SeqCst);
Err(unsafe { SignalToken::cast_from_uint(ptr) })
Err(unsafe { SignalToken::cast_from_usize(ptr) })
}
pub fn recv(&mut self) -> Result<T, Failure<T>> {
@ -350,7 +350,7 @@ impl<T: Send> Packet<T> {
}
// increment the count on the channel (used for selection)
fn bump(&mut self, amt: int) -> int {
fn bump(&mut self, amt: isize) -> isize {
match self.cnt.fetch_add(amt, Ordering::SeqCst) {
DISCONNECTED => {
self.cnt.store(DISCONNECTED, Ordering::SeqCst);

View file

@ -64,7 +64,7 @@ struct State<T> {
queue: Queue, // queue of senders waiting to send data
blocker: Blocker, // currently blocked task on this channel
buf: Buffer<T>, // storage for buffered messages
cap: uint, // capacity of this channel
cap: usize, // capacity of this channel
/// A curious flag used to indicate whether a sender failed or succeeded in
/// blocking. This is used to transmit information back to the task that it
@ -101,8 +101,8 @@ unsafe impl Send for Node {}
/// A simple ring-buffer
struct Buffer<T> {
buf: Vec<Option<T>>,
start: uint,
size: uint,
start: usize,
size: usize,
}
#[derive(Debug)]
@ -137,7 +137,7 @@ fn wakeup<T>(token: SignalToken, guard: MutexGuard<State<T>>) {
}
impl<T: Send> Packet<T> {
pub fn new(cap: uint) -> Packet<T> {
pub fn new(cap: usize) -> Packet<T> {
Packet {
channels: AtomicUsize::new(1),
lock: Mutex::new(State {
@ -442,8 +442,8 @@ impl<T> Buffer<T> {
result.take().unwrap()
}
fn size(&self) -> uint { self.size }
fn cap(&self) -> uint { self.buf.len() }
fn size(&self) -> usize { self.size }
fn cap(&self) -> usize { self.buf.len() }
}
////////////////////////////////////////////////////////////////////////////////

View file

@ -50,7 +50,7 @@ use sys_common::mutex as sys;
/// use std::thread;
/// use std::sync::mpsc::channel;
///
/// const N: uint = 10;
/// const N: usize = 10;
///
/// // Spawn a few threads to increment a shared variable (non-atomically), and
/// // let the main thread know once all increments are done.
@ -377,9 +377,9 @@ mod test {
#[test]
fn lots_and_lots() {
static M: StaticMutex = MUTEX_INIT;
static mut CNT: uint = 0;
static J: uint = 1000;
static K: uint = 3;
static mut CNT: u32 = 0;
static J: u32 = 1000;
static K: u32 = 3;
fn inc() {
for _ in 0..J {
@ -501,7 +501,7 @@ mod test {
let arc2 = arc.clone();
let _ = thread::spawn(move|| -> () {
struct Unwinder {
i: Arc<Mutex<int>>,
i: Arc<Mutex<i32>>,
}
impl Drop for Unwinder {
fn drop(&mut self) {

View file

@ -89,7 +89,7 @@ impl TaskPool {
/// # Panics
///
/// This function will panic if `threads` is 0.
pub fn new(threads: uint) -> TaskPool {
pub fn new(threads: usize) -> TaskPool {
assert!(threads >= 1);
let (tx, rx) = channel::<Thunk>();
@ -142,7 +142,7 @@ mod test {
use super::*;
use sync::mpsc::channel;
const TEST_TASKS: uint = 4;
const TEST_TASKS: usize = 4;
#[test]
fn test_works() {

View file

@ -18,7 +18,7 @@ use libc::{self, c_int, c_void, size_t, off_t, c_char, mode_t};
use mem;
use path::{Path, PathBuf};
use ptr;
use rc::Rc;
use sync::Arc;
use sys::fd::FileDesc;
use sys::{c, cvt, cvt_r};
use sys_common::FromInner;
@ -31,14 +31,18 @@ pub struct FileAttr {
}
pub struct ReadDir {
dirp: *mut libc::DIR,
root: Rc<PathBuf>,
dirp: Dir,
root: Arc<PathBuf>,
}
struct Dir(*mut libc::DIR);
unsafe impl Send for Dir {}
unsafe impl Sync for Dir {}
pub struct DirEntry {
buf: Vec<u8>,
dirent: *mut libc::dirent_t,
root: Rc<PathBuf>,
buf: Vec<u8>, // actually *mut libc::dirent_t
root: Arc<PathBuf>,
}
#[derive(Clone)]
@ -109,7 +113,7 @@ impl Iterator for ReadDir {
let mut entry_ptr = ptr::null_mut();
loop {
if unsafe { libc::readdir_r(self.dirp, ptr, &mut entry_ptr) != 0 } {
if unsafe { libc::readdir_r(self.dirp.0, ptr, &mut entry_ptr) != 0 } {
return Some(Err(Error::last_os_error()))
}
if entry_ptr.is_null() {
@ -118,7 +122,6 @@ impl Iterator for ReadDir {
let entry = DirEntry {
buf: buf,
dirent: entry_ptr,
root: self.root.clone()
};
if entry.name_bytes() == b"." || entry.name_bytes() == b".." {
@ -130,9 +133,9 @@ impl Iterator for ReadDir {
}
}
impl Drop for ReadDir {
impl Drop for Dir {
fn drop(&mut self) {
let r = unsafe { libc::closedir(self.dirp) };
let r = unsafe { libc::closedir(self.0) };
debug_assert_eq!(r, 0);
}
}
@ -147,9 +150,13 @@ impl DirEntry {
fn rust_list_dir_val(ptr: *mut libc::dirent_t) -> *const c_char;
}
unsafe {
CStr::from_ptr(rust_list_dir_val(self.dirent)).to_bytes()
CStr::from_ptr(rust_list_dir_val(self.dirent())).to_bytes()
}
}
fn dirent(&self) -> *mut libc::dirent_t {
self.buf.as_ptr() as *mut _
}
}
impl OpenOptions {
@ -279,14 +286,14 @@ pub fn mkdir(p: &Path) -> io::Result<()> {
}
pub fn readdir(p: &Path) -> io::Result<ReadDir> {
let root = Rc::new(p.to_path_buf());
let root = Arc::new(p.to_path_buf());
let p = try!(cstr(p));
unsafe {
let ptr = libc::opendir(p.as_ptr());
if ptr.is_null() {
Err(Error::last_os_error())
} else {
Ok(ReadDir { dirp: ptr, root: root })
Ok(ReadDir { dirp: Dir(ptr), root: root })
}
}
}

View file

@ -19,6 +19,7 @@ use libc::{self, HANDLE};
use mem;
use path::{Path, PathBuf};
use ptr;
use sync::Arc;
use sys::handle::Handle as RawHandle;
use sys::{c, cvt};
use vec::Vec;
@ -27,12 +28,20 @@ pub struct File { handle: RawHandle }
pub struct FileAttr { data: c::WIN32_FILE_ATTRIBUTE_DATA }
pub struct ReadDir {
handle: libc::HANDLE,
root: PathBuf,
handle: FindNextFileHandle,
root: Arc<PathBuf>,
first: Option<libc::WIN32_FIND_DATAW>,
}
pub struct DirEntry { path: PathBuf }
struct FindNextFileHandle(libc::HANDLE);
unsafe impl Send for FindNextFileHandle {}
unsafe impl Sync for FindNextFileHandle {}
pub struct DirEntry {
root: Arc<PathBuf>,
data: libc::WIN32_FIND_DATAW,
}
#[derive(Clone, Default)]
pub struct OpenOptions {
@ -61,7 +70,7 @@ impl Iterator for ReadDir {
unsafe {
let mut wfd = mem::zeroed();
loop {
if libc::FindNextFileW(self.handle, &mut wfd) == 0 {
if libc::FindNextFileW(self.handle.0, &mut wfd) == 0 {
if libc::GetLastError() ==
c::ERROR_NO_MORE_FILES as libc::DWORD {
return None
@ -77,15 +86,15 @@ impl Iterator for ReadDir {
}
}
impl Drop for ReadDir {
impl Drop for FindNextFileHandle {
fn drop(&mut self) {
let r = unsafe { libc::FindClose(self.handle) };
let r = unsafe { libc::FindClose(self.0) };
debug_assert!(r != 0);
}
}
impl DirEntry {
fn new(root: &Path, wfd: &libc::WIN32_FIND_DATAW) -> Option<DirEntry> {
fn new(root: &Arc<PathBuf>, wfd: &libc::WIN32_FIND_DATAW) -> Option<DirEntry> {
match &wfd.cFileName[0..3] {
// check for '.' and '..'
[46, 0, ..] |
@ -93,13 +102,15 @@ impl DirEntry {
_ => {}
}
let filename = super::truncate_utf16_at_nul(&wfd.cFileName);
let filename: OsString = OsStringExt::from_wide(filename);
Some(DirEntry { path: root.join(&filename) })
Some(DirEntry {
root: root.clone(),
data: *wfd,
})
}
pub fn path(&self) -> PathBuf {
self.path.clone()
let filename = super::truncate_utf16_at_nul(&self.data.cFileName);
self.root.join(&<OsString as OsStringExt>::from_wide(filename))
}
}
@ -312,7 +323,11 @@ pub fn readdir(p: &Path) -> io::Result<ReadDir> {
let mut wfd = mem::zeroed();
let find_handle = libc::FindFirstFileW(path.as_ptr(), &mut wfd);
if find_handle != libc::INVALID_HANDLE_VALUE {
Ok(ReadDir { handle: find_handle, root: root, first: Some(wfd) })
Ok(ReadDir {
handle: FindNextFileHandle(find_handle),
root: Arc::new(root),
first: Some(wfd),
})
} else {
Err(Error::last_os_error())
}

View file

@ -342,12 +342,15 @@ impl Builder {
}
}
/// Spawn a new, returning a join handle for it.
/// Spawn a new thread, returning a `JoinHandle` for it.
///
/// The child thread may outlive the parent (unless the parent thread
/// is the main thread; the whole process is terminated when the main
/// thread finishes.) The join handle can be used to block on
/// termination of the child thread, including recovering its panics.
/// The join handle will implicitly *detach* the child thread upon being
/// dropped. In this case, the child thread may outlive the parent (unless
/// the parent thread is the main thread; the whole process is terminated when
/// the main thread finishes.) Additionally, the join handle provides a `join`
/// method that can be used to join the child thread. If the child thread
/// panics, `join` will return an `Err` containing the argument given to
/// `panic`.
///
/// # Panics
///

View file

@ -74,7 +74,7 @@ pub mod __impl {
/// use std::cell::RefCell;
/// use std::thread;
///
/// thread_local!(static FOO: RefCell<uint> = RefCell::new(1));
/// thread_local!(static FOO: RefCell<u32> = RefCell::new(1));
///
/// FOO.with(|f| {
/// assert_eq!(*f.borrow(), 1);
@ -503,7 +503,7 @@ mod imp {
unsafe fn ptr(&'static self) -> Option<*mut T> {
let ptr = self.os.get() as *mut Value<T>;
if !ptr.is_null() {
if ptr as uint == 1 {
if ptr as usize == 1 {
return None
}
return Some(&mut (*ptr).value as *mut T);
@ -563,7 +563,7 @@ mod tests {
#[test]
fn smoke_no_dtor() {
thread_local!(static FOO: UnsafeCell<int> = UnsafeCell { value: 1 });
thread_local!(static FOO: UnsafeCell<i32> = UnsafeCell { value: 1 });
FOO.with(|f| unsafe {
assert_eq!(*f.get(), 1);
@ -632,7 +632,7 @@ mod tests {
thread_local!(static K2: UnsafeCell<Option<S2>> = UnsafeCell {
value: None
});
static mut HITS: uint = 0;
static mut HITS: u32 = 0;
impl Drop for S1 {
fn drop(&mut self) {
@ -723,8 +723,8 @@ mod dynamic_tests {
#[test]
fn smoke() {
fn square(i: int) -> int { i * i }
thread_local!(static FOO: int = square(3));
fn square(i: i32) -> i32 { i * i }
thread_local!(static FOO: i32 = square(3));
FOO.with(|f| {
assert_eq!(*f, 9);
@ -733,12 +733,12 @@ mod dynamic_tests {
#[test]
fn hashmap() {
fn map() -> RefCell<HashMap<int, int>> {
fn map() -> RefCell<HashMap<i32, i32>> {
let mut m = HashMap::new();
m.insert(1, 2);
RefCell::new(m)
}
thread_local!(static FOO: RefCell<HashMap<int, int>> = map());
thread_local!(static FOO: RefCell<HashMap<i32, i32>> = map());
FOO.with(|map| {
assert_eq!(map.borrow()[1], 2);
@ -747,7 +747,7 @@ mod dynamic_tests {
#[test]
fn refcell_vec() {
thread_local!(static FOO: RefCell<Vec<uint>> = RefCell::new(vec![1, 2, 3]));
thread_local!(static FOO: RefCell<Vec<u32>> = RefCell::new(vec![1, 2, 3]));
FOO.with(|vec| {
assert_eq!(vec.borrow().len(), 3);

View file

@ -24,7 +24,7 @@
//! # Example
//!
//! ```
//! scoped_thread_local!(static FOO: uint);
//! scoped_thread_local!(static FOO: u32);
//!
//! // Initially each scoped slot is empty.
//! assert!(!FOO.is_set());
@ -140,7 +140,7 @@ impl<T> Key<T> {
/// # Example
///
/// ```
/// scoped_thread_local!(static FOO: uint);
/// scoped_thread_local!(static FOO: u32);
///
/// FOO.set(&100, || {
/// let val = FOO.with(|v| *v);
@ -192,7 +192,7 @@ impl<T> Key<T> {
/// # Example
///
/// ```no_run
/// scoped_thread_local!(static FOO: uint);
/// scoped_thread_local!(static FOO: u32);
///
/// FOO.with(|slot| {
/// // work with `slot`
@ -269,11 +269,11 @@ mod tests {
use cell::Cell;
use prelude::v1::*;
scoped_thread_local!(static FOO: uint);
scoped_thread_local!(static FOO: u32);
#[test]
fn smoke() {
scoped_thread_local!(static BAR: uint);
scoped_thread_local!(static BAR: u32);
assert!(!BAR.is_set());
BAR.set(&1, || {
@ -287,7 +287,7 @@ mod tests {
#[test]
fn cell_allowed() {
scoped_thread_local!(static BAR: Cell<uint>);
scoped_thread_local!(static BAR: Cell<u32>);
BAR.set(&Cell::new(1), || {
BAR.with(|slot| {

View file

@ -702,12 +702,12 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
self.expr_lit(sp, ast::LitInt(i as u64, ast::SignedIntLit(ast::TyIs(false),
ast::Sign::new(i))))
}
fn expr_u8(&self, sp: Span, u: u8) -> P<ast::Expr> {
self.expr_lit(sp, ast::LitInt(u as u64, ast::UnsignedIntLit(ast::TyU8)))
}
fn expr_u32(&self, sp: Span, u: u32) -> P<ast::Expr> {
self.expr_lit(sp, ast::LitInt(u as u64, ast::UnsignedIntLit(ast::TyU32)))
}
fn expr_u8(&self, sp: Span, u: u8) -> P<ast::Expr> {
self.expr_lit(sp, ast::LitInt(u as u64, ast::UnsignedIntLit(ast::TyU8)))
}
fn expr_bool(&self, sp: Span, value: bool) -> P<ast::Expr> {
self.expr_lit(sp, ast::LitBool(value))
}

View file

@ -417,7 +417,7 @@ impl<'a, 'b> Context<'a, 'b> {
parse::AlignUnknown => align("Unknown"),
};
let align = self.ecx.expr_path(align);
let flags = self.ecx.expr_usize(sp, arg.format.flags);
let flags = self.ecx.expr_u32(sp, arg.format.flags);
let prec = self.trans_count(arg.format.precision);
let width = self.trans_count(arg.format.width);
let path = self.ecx.path_global(sp, Context::rtpath(self.ecx, "FormatSpec"));
@ -610,7 +610,7 @@ impl<'a, 'b> Context<'a, 'b> {
ecx.ident_of_std("core"),
ecx.ident_of("fmt"),
ecx.ident_of("ArgumentV1"),
ecx.ident_of("from_uint")], vec![arg])
ecx.ident_of("from_usize")], vec![arg])
}
};

View file

@ -17,7 +17,7 @@ pub mod kitty {
pub name : String,
}
impl fmt::String for cat {
impl fmt::Display for cat {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.name)
}

View file

@ -8,7 +8,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use std::fmt::Show;
use std::fmt::Debug;
use std::default::Default;
use std::marker::MarkerTrait;

View file

@ -8,7 +8,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use std::fmt::Show;
use std::fmt::Debug;
use std::default::Default;
// Test that two blanket impls conflict (at least without negative

View file

@ -13,7 +13,7 @@
extern crate go_trait;
use go_trait::{Go,GoMut};
use std::fmt::Show;
use std::fmt::Debug;
use std::default::Default;
struct MyThingy;

View file

@ -8,7 +8,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use std::fmt::Show;
use std::fmt::Debug;
use std::default::Default;
// Test that a blank impl for all T conflicts with an impl for some

View file

@ -8,7 +8,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use std::fmt::Show;
use std::fmt::Debug;
use std::default::Default;
// Test that a blank impl for all T conflicts with an impl for some

View file

@ -8,7 +8,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use std::fmt::Show;
use std::fmt::Debug;
use std::default::Default;
// Test that a blank impl for all T conflicts with an impl for some

View file

@ -15,8 +15,7 @@ fn needs_fn<F>(x: F) where F: Fn(isize) -> isize {}
fn main() {
let _: () = (box |_: isize| {}) as Box<FnOnce(isize)>;
//~^ ERROR object-safe
//~| ERROR mismatched types
//~^ ERROR mismatched types
//~| expected `()`
//~| found `Box<core::ops::FnOnce(isize)>`
//~| expected ()

View file

@ -1,4 +1,4 @@
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
@ -8,28 +8,34 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// error-pattern: reached the recursion limit during monomorphization
// issue 2258
//~^^^^^^^^^^ ERROR overflow
//
// We get an error message at the top of file (dummy span).
// This is not helpful, but also kind of annoying to prevent,
// so for now just live with it.
// This test case was originally for issue #2258.
trait to_opt {
trait ToOpt {
fn to_option(&self) -> Option<Self>;
}
impl to_opt for usize {
impl ToOpt for usize {
fn to_option(&self) -> Option<usize> {
Some(*self)
}
}
impl<T:Clone> to_opt for Option<T> {
impl<T:Clone> ToOpt for Option<T> {
fn to_option(&self) -> Option<Option<T>> {
Some((*self).clone())
}
}
fn function<T:to_opt + Clone>(counter: usize, t: T) {
fn function<T:ToOpt + Clone>(counter: usize, t: T) {
if counter > 0_usize {
function(counter - 1_usize, t.to_option());
// FIXME(#4287) Error message should be here. It should be
// a type error to instantiate `test` at a type other than T.
}
}

View file

@ -14,11 +14,11 @@ fn main() {
let _foo = &[1_usize, 2] as [usize];
//~^ ERROR cast to unsized type: `&[usize; 2]` as `[usize]`
//~^^ HELP consider using an implicit coercion to `&[usize]` instead
let _bar = box 1_usize as std::fmt::Show;
//~^ ERROR cast to unsized type: `Box<usize>` as `core::fmt::Show`
//~^^ HELP did you mean `Box<core::fmt::Show>`?
let _baz = 1_usize as std::fmt::Show;
//~^ ERROR cast to unsized type: `usize` as `core::fmt::Show`
let _bar = box 1_usize as std::fmt::Debug;
//~^ ERROR cast to unsized type: `Box<usize>` as `core::fmt::Debug`
//~^^ HELP did you mean `Box<core::fmt::Debug>`?
let _baz = 1_usize as std::fmt::Debug;
//~^ ERROR cast to unsized type: `usize` as `core::fmt::Debug`
//~^^ HELP consider using a box or reference as appropriate
let _quux = [1_usize, 2] as [usize];
//~^ ERROR cast to unsized type: `[usize; 2]` as `[usize]`

View file

@ -17,7 +17,11 @@ impl Foo for Thing {
fn foo<T>(&self, _: &T) {}
}
#[inline(never)] fn foo(b: &Bar) { b.foo(&0_usize) }
#[inline(never)]
fn foo(b: &Bar) {
b.foo(&0usize)
//~^ ERROR the trait `Foo` is not implemented for the type `Bar`
}
fn main() {
let mut thing = Thing;

View file

@ -17,15 +17,15 @@
#![doc="More garbage"]
type Typedef = String;
pub type PubTypedef = String; //~ ERROR: missing documentation
pub type PubTypedef = String; //~ ERROR: missing documentation for a type alias
struct Foo {
a: isize,
b: isize,
}
pub struct PubFoo { //~ ERROR: missing documentation
pub a: isize, //~ ERROR: missing documentation
pub struct PubFoo { //~ ERROR: missing documentation for a struct
pub a: isize, //~ ERROR: missing documentation for a struct field
b: isize,
}
@ -36,11 +36,11 @@ pub struct PubFoo2 {
}
mod module_no_dox {}
pub mod pub_module_no_dox {} //~ ERROR: missing documentation
pub mod pub_module_no_dox {} //~ ERROR: missing documentation for a module
/// dox
pub fn foo() {}
pub fn foo2() {} //~ ERROR: missing documentation
pub fn foo2() {} //~ ERROR: missing documentation for a function
fn foo3() {}
#[allow(missing_docs)] pub fn foo4() {}
@ -58,9 +58,9 @@ trait B {
fn foo_with_impl(&self) {}
}
pub trait C { //~ ERROR: missing documentation
fn foo(&self); //~ ERROR: missing documentation
fn foo_with_impl(&self) {} //~ ERROR: missing documentation
pub trait C { //~ ERROR: missing documentation for a trait
fn foo(&self); //~ ERROR: missing documentation for a type method
fn foo_with_impl(&self) {} //~ ERROR: missing documentation for a method
}
#[allow(missing_docs)]
@ -68,13 +68,26 @@ pub trait D {
fn dummy(&self) { }
}
/// dox
pub trait E {
type AssociatedType; //~ ERROR: missing documentation for an associated type
type AssociatedTypeDef = Self; //~ ERROR: missing documentation for an associated type
/// dox
type DocumentedType;
/// dox
type DocumentedTypeDef = Self;
/// dox
fn dummy(&self) {}
}
impl Foo {
pub fn foo() {}
fn bar() {}
}
impl PubFoo {
pub fn foo() {} //~ ERROR: missing documentation
pub fn foo() {} //~ ERROR: missing documentation for a method
/// dox
pub fn foo1() {}
fn foo2() {}
@ -111,9 +124,9 @@ enum Baz {
BarB
}
pub enum PubBaz { //~ ERROR: missing documentation
PubBazA { //~ ERROR: missing documentation
a: isize, //~ ERROR: missing documentation
pub enum PubBaz { //~ ERROR: missing documentation for an enum
PubBazA { //~ ERROR: missing documentation for a variant
a: isize, //~ ERROR: missing documentation for a struct field
},
}
@ -139,14 +152,14 @@ pub fn baz() {}
mod internal_impl {
/// dox
pub fn documented() {}
pub fn undocumented1() {} //~ ERROR: missing documentation
pub fn undocumented2() {} //~ ERROR: missing documentation
pub fn undocumented1() {} //~ ERROR: missing documentation for a function
pub fn undocumented2() {} //~ ERROR: missing documentation for a function
fn undocumented3() {}
/// dox
pub mod globbed {
/// dox
pub fn also_documented() {}
pub fn also_undocumented1() {} //~ ERROR: missing documentation
pub fn also_undocumented1() {} //~ ERROR: missing documentation for a function
fn also_undocumented2() {}
}
}

View file

@ -0,0 +1,25 @@
// 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(box_syntax)]
pub fn main() {
let x = box 1;
let v = (1, 2);
match v {
(1, _) if take(x) => (),
(_, 2) if take(x) => (), //~ ERROR use of moved value: `x`
_ => (),
}
}
fn take<T>(_: T) -> bool { false }

View file

@ -0,0 +1,25 @@
// 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(box_syntax)]
pub fn main() {
let x = box 1;
let v = (1, 2);
match v {
(1, _) |
(_, 2) if take(x) => (), //~ ERROR use of moved value: `x`
_ => (),
}
}
fn take<T>(_: T) -> bool { false }

View file

@ -0,0 +1,29 @@
// 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 while a trait with by-value self is object-safe, we
// can't actually invoke it from an object (yet...?).
#![feature(rustc_attrs)]
trait Bar {
fn bar(self);
}
trait Baz {
fn baz(self: Self);
}
fn use_bar(t: Box<Bar>) {
t.bar() //~ ERROR cannot move a value of type Bar
}
fn main() { }

View file

@ -8,8 +8,10 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// Check that we correctly prevent users from making trait objects
// from traits with a `fn(self)` method.
// Check that a trait with by-value self is considered object-safe.
#![feature(rustc_attrs)]
#![allow(dead_code)]
trait Bar {
fn bar(self);
@ -19,29 +21,35 @@ trait Baz {
fn baz(self: Self);
}
trait Quux {
// Legal because of the where clause:
fn baz(self: Self) where Self : Sized;
}
fn make_bar<T:Bar>(t: &T) -> &Bar {
t
//~^ ERROR `Bar` is not object-safe
//~| NOTE method `bar` has a receiver type of `Self`
t // legal
}
fn make_bar_explicit<T:Bar>(t: &T) -> &Bar {
t as &Bar
//~^ ERROR `Bar` is not object-safe
//~| NOTE method `bar` has a receiver type of `Self`
t as &Bar // legal
}
fn make_baz<T:Baz>(t: &T) -> &Baz {
t
//~^ ERROR `Baz` is not object-safe
//~| NOTE method `baz` has a receiver type of `Self`
t // legal
}
fn make_baz_explicit<T:Baz>(t: &T) -> &Baz {
t as &Baz
//~^ ERROR `Baz` is not object-safe
//~| NOTE method `baz` has a receiver type of `Self`
t as &Baz // legal
}
fn main() {
fn make_quux<T:Quux>(t: &T) -> &Quux {
t
}
fn make_quux_explicit<T:Quux>(t: &T) -> &Quux {
t as &Quux
}
#[rustc_error]
fn main() { //~ ERROR compilation successful
}

View file

@ -9,12 +9,18 @@
// except according to those terms.
// Check that we correctly prevent users from making trait objects
// from traits with generic methods.
// from traits with generic methods, unless `where Self : Sized` is
// present.
trait Bar {
fn bar<T>(&self, t: T);
}
trait Quux {
fn bar<T>(&self, t: T)
where Self : Sized;
}
fn make_bar<T:Bar>(t: &T) -> &Bar {
t
//~^ ERROR `Bar` is not object-safe
@ -27,5 +33,13 @@ fn make_bar_explicit<T:Bar>(t: &T) -> &Bar {
//~| NOTE method `bar` has generic type parameters
}
fn make_quux<T:Quux>(t: &T) -> &Quux {
t
}
fn make_quux_explicit<T:Quux>(t: &T) -> &Quux {
t as &Quux
}
fn main() {
}

View file

@ -9,7 +9,8 @@
// except according to those terms.
// Check that we correctly prevent users from making trait objects
// form traits that make use of `Self` in an argument or return position.
// form traits that make use of `Self` in an argument or return
// position, unless `where Self : Sized` is present..
trait Bar {
fn bar(&self, x: &Self);
@ -19,6 +20,10 @@ trait Baz {
fn bar(&self) -> Self;
}
trait Quux {
fn get(&self, s: &Self) -> Self where Self : Sized;
}
fn make_bar<T:Bar>(t: &T) -> &Bar {
t
//~^ ERROR `Bar` is not object-safe
@ -43,5 +48,13 @@ fn make_baz_explicit<T:Baz>(t: &T) -> &Baz {
//~| NOTE method `bar` references the `Self` type in its arguments or return type
}
fn make_quux<T:Quux>(t: &T) -> &Quux {
t
}
fn make_quux_explicit<T:Quux>(t: &T) -> &Quux {
t as &Quux
}
fn main() {
}

View file

@ -1,4 +1,4 @@
// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
// Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
@ -10,10 +10,9 @@
//~^^^^^^^^^^ ERROR overflow
//
// We also get a second error message at the top of file (dummy
// span). This is not helpful, but also kind of annoying to prevent,
// so for now just live with it, since we also get a second message
// that is more helpful.
// We get an error message at the top of file (dummy span).
// This is not helpful, but also kind of annoying to prevent,
// so for now just live with it.
enum Nil {NilValue}
struct Cons<T> {head:isize, tail:T}
@ -28,9 +27,8 @@ impl<T:Dot> Dot for Cons<T> {
}
fn test<T:Dot> (n:isize, i:isize, first:T, second:T) ->isize {
match n { 0 => {first.dot(second)}
//~^ ERROR: reached the recursion limit during monomorphization
// Error message should be here. It should be a type error
// to instantiate `test` at a type other than T. (See #4287)
// FIXME(#4287) Error message should be here. It should be
// a type error to instantiate `test` at a type other than T.
_ => {test (n-1, i+1, Cons {head:2*i+1, tail:first}, Cons{head:i*i, tail:second})}
}
}

View file

@ -18,4 +18,5 @@ fn main() {
10.dup::<i32>(); //~ ERROR does not take type parameters
10.blah::<i32, i32>(); //~ ERROR incorrect number of type parameters
(box 10 as Box<bar>).dup(); //~ ERROR cannot convert to a trait object
//~^ ERROR the trait `bar` is not implemented for the type `bar`
}

View file

@ -0,0 +1,28 @@
// 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.
fn foo1<T:Copy<U>, U>(x: T) {}
//~^ ERROR: wrong number of type arguments: expected 0, found 1
trait Trait: Copy<Send> {}
//~^ ERROR: wrong number of type arguments: expected 0, found 1
struct MyStruct1<T: Copy<T>>;
//~^ ERROR wrong number of type arguments: expected 0, found 1
struct MyStruct2<'a, T: Copy<'a>>;
//~^ ERROR: wrong number of lifetime parameters: expected 0, found 1
fn foo2<'a, T:Copy<'a, U>, U>(x: T) {}
//~^ ERROR: wrong number of type arguments: expected 0, found 1
//~^^ ERROR: wrong number of lifetime parameters: expected 0, found 1
fn main() {
}

View file

@ -18,7 +18,7 @@ struct Number {
n: i64
}
impl fmt::String for Number {
impl fmt::Display for Number {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.n)
}

Some files were not shown because too many files have changed in this diff Show more