Auto merge of #22755 - Manishearth:rollup, r=Manishearth
This commit is contained in:
commit
dccdde4007
113 changed files with 1401 additions and 948 deletions
|
@ -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`.
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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};
|
||||
|
|
|
@ -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> {
|
||||
|
|
|
@ -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(())
|
||||
|
|
|
@ -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 }
|
||||
|
|
|
@ -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")]
|
||||
|
|
|
@ -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,
|
||||
//! }
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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>;
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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: "",
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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())
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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(..) |
|
||||
|
|
|
@ -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) => {
|
||||
|
|
|
@ -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: {}",
|
||||
|
|
|
@ -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 => {
|
||||
}
|
||||
|
|
|
@ -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])
|
||||
|
|
|
@ -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 => {
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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) => {
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -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 => {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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(¶m_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(¶m_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)
|
||||
}
|
||||
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 \
|
||||
|
|
|
@ -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))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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"),
|
||||
}
|
||||
|
|
|
@ -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())
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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())));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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"),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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(()) }
|
||||
}
|
||||
|
|
|
@ -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")]
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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) }
|
||||
}
|
||||
|
||||
|
|
|
@ -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)));
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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! {
|
||||
|
|
|
@ -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) }
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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() }
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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 })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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())
|
||||
}
|
||||
|
|
|
@ -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
|
||||
///
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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| {
|
||||
|
|
|
@ -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))
|
||||
}
|
||||
|
|
|
@ -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])
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 ()
|
||||
|
|
|
@ -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.
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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]`
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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() {}
|
||||
}
|
||||
}
|
||||
|
|
25
src/test/compile-fail/move-in-guard-1.rs
Normal file
25
src/test/compile-fail/move-in-guard-1.rs
Normal 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 }
|
25
src/test/compile-fail/move-in-guard-2.rs
Normal file
25
src/test/compile-fail/move-in-guard-2.rs
Normal 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 }
|
29
src/test/compile-fail/object-safety-by-value-self-use.rs
Normal file
29
src/test/compile-fail/object-safety-by-value-self-use.rs
Normal 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() { }
|
||||
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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() {
|
||||
}
|
||||
|
|
|
@ -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() {
|
||||
}
|
||||
|
|
|
@ -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})}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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`
|
||||
}
|
||||
|
|
|
@ -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() {
|
||||
}
|
|
@ -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
Loading…
Add table
Reference in a new issue