diff --git a/src/doc/reference.md b/src/doc/reference.md index 357ff813fef3f..31524579df7c0 100644 --- a/src/doc/reference.md +++ b/src/doc/reference.md @@ -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`. diff --git a/src/doc/rust.css b/src/doc/rust.css index c2a25cd7a584e..cd158283180a2 100644 --- a/src/doc/rust.css +++ b/src/doc/rust.css @@ -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; diff --git a/src/doc/trpl/pointers.md b/src/doc/trpl/pointers.md index 332f299a67f3c..0f46b4da0d6f9 100644 --- a/src/doc/trpl/pointers.md +++ b/src/doc/trpl/pointers.md @@ -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 diff --git a/src/doc/trpl/static-and-dynamic-dispatch.md b/src/doc/trpl/static-and-dynamic-dispatch.md index 1baf41329f561..fc1ab9bf9e8dc 100644 --- a/src/doc/trpl/static-and-dynamic-dispatch.md +++ b/src/doc/trpl/static-and-dynamic-dispatch.md @@ -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 diff --git a/src/libcollections/borrow.rs b/src/libcollections/borrow.rs index e92f38741c9a0..f3c44a84ee50a 100644 --- a/src/libcollections/borrow.rs +++ b/src/libcollections/borrow.rs @@ -132,7 +132,7 @@ impl 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 { diff --git a/src/libcollections/fmt.rs b/src/libcollections/fmt.rs index 1b5018f4ad73d..98673af3c68a8 100644 --- a/src/libcollections/fmt.rs +++ b/src/libcollections/fmt.rs @@ -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}; diff --git a/src/libcore/fmt/float.rs b/src/libcore/fmt/float.rs index 7f7264a04684b..f92e631c1f25c 100644 --- a/src/libcore/fmt/float.rs +++ b/src/libcore/fmt/float.rs @@ -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( // 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( struct Filler<'a> { buf: &'a mut [u8], - end: &'a mut uint, + end: &'a mut usize, } impl<'a> fmt::Write for Filler<'a> { diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs index a2c1bbc03317e..0bf44dd77aaa1 100644 --- a/src/libcore/fmt/mod.rs +++ b/src/libcore/fmt/mod.rs @@ -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, - precision: Option, + width: Option, + precision: Option, 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 { - if self.formatter as uint == ArgumentV1::show_uint as uint { - Some(unsafe { *(self.value as *const _ as *const uint) }) + fn as_usize(&self) -> Option { + 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 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 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 { + fn getcount(&mut self, cnt: &rt::v1::Count) -> Option { 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(&mut self, padding: uint, default: Alignment, + fn with_padding(&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 { self.width } + pub fn width(&self) -> Option { self.width } /// Optionally specified precision for numeric types #[unstable(feature = "core", reason = "method was just created")] - pub fn precision(&self) -> Option { self.precision } + pub fn precision(&self) -> Option { 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 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 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 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(()) diff --git a/src/libcore/fmt/num.rs b/src/libcore/fmt/num.rs index 1222126b5e0cd..0175e21c8da61 100644 --- a/src/libcore/fmt/num.rs +++ b/src/libcore/fmt/num.rs @@ -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 } diff --git a/src/libcore/fmt/rt/v1.rs b/src/libcore/fmt/rt/v1.rs index 0c9bb6316e0d8..c35611acb8142 100644 --- a/src/libcore/fmt/rt/v1.rs +++ b/src/libcore/fmt/rt/v1.rs @@ -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")] diff --git a/src/libcore/hash/mod.rs b/src/libcore/hash/mod.rs index ed48903a7c255..edc4b7e10ee49 100644 --- a/src/libcore/hash/mod.rs +++ b/src/libcore/hash/mod.rs @@ -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, //! } diff --git a/src/libcore/hash/sip.rs b/src/libcore/hash/sip.rs index 6f24fc7067344..39bcbacdff182 100644 --- a/src/libcore/hash/sip.rs +++ b/src/libcore/hash/sip.rs @@ -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, diff --git a/src/libcore/iter.rs b/src/libcore/iter.rs index 2d50bbb641363..09089f2d04c5f 100644 --- a/src/libcore/iter.rs +++ b/src/libcore/iter.rs @@ -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 { /// 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; diff --git a/src/libcore/ops.rs b/src/libcore/ops.rs index fbd7f840da6e1..c382ac46d5db9 100644 --- a/src/libcore/ops.rs +++ b/src/libcore/ops.rs @@ -184,6 +184,7 @@ macro_rules! forward_ref_binop { #[lang="add"] #[stable(feature = "rust1", since = "1.0.0")] pub trait Add { + /// 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 { + /// 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 { + /// 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 { + /// 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 { + /// 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 { + /// 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 { + /// 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 { + /// 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 { + /// 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 { + /// 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 { + /// The returned type after indexing type Output: ?Sized; /// The method for the indexing (`Foo[Bar]`) operation @@ -1047,6 +1060,7 @@ impl fmt::Debug for RangeTo { #[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 { + /// 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 { #[stable(feature = "rust1", since = "1.0.0")] #[rustc_paren_sugar] pub trait FnMut { + /// 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 { #[stable(feature = "rust1", since = "1.0.0")] #[rustc_paren_sugar] pub trait FnOnce { + /// The returned type after the call operator is used. type Output; /// This is called when the call operator is used. diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs index 16b84dcf18e24..b44cc899787f5 100644 --- a/src/libcore/ptr.rs +++ b/src/libcore/ptr.rs @@ -249,6 +249,7 @@ pub unsafe fn write(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 diff --git a/src/libfmt_macros/lib.rs b/src/libfmt_macros/lib.rs index be77622ac1db7..4e25e51e9a466 100644 --- a/src/libfmt_macros/lib.rs +++ b/src/libfmt_macros/lib.rs @@ -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 { + fn integer(&mut self) -> Option { 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: "", diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs index 3c06bae177cef..8a00622486ddc 100644 --- a/src/librustc/lint/builtin.rs +++ b/src/librustc/lint/builtin.rs @@ -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) { diff --git a/src/librustc/metadata/tyencode.rs b/src/librustc/metadata/tyencode.rs index e1e9d49dd0585..11609ebe675ef 100644 --- a/src/librustc/metadata/tyencode.rs +++ b/src/librustc/metadata/tyencode.rs @@ -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(); diff --git a/src/librustc/middle/cfg/construct.rs b/src/librustc/middle/cfg/construct.rs index d95dfb6feaec4..52eedc460eb87 100644 --- a/src/librustc/middle/cfg/construct.rs +++ b/src/librustc/middle/cfg/construct.rs @@ -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, graph: CFGGraph, fn_exit: CFGIndex, loop_scopes: Vec, @@ -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], - 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); } diff --git a/src/librustc/middle/cfg/graphviz.rs b/src/librustc/middle/cfg/graphviz.rs index 14c6ff01e0e66..0c5eca3c12968 100644 --- a/src/librustc/middle/cfg/graphviz.rs +++ b/src/librustc/middle/cfg/graphviz.rs @@ -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()) diff --git a/src/librustc/middle/cfg/mod.rs b/src/librustc/middle/cfg/mod.rs index 0ca146a295e13..e8a99f59b1e95 100644 --- a/src/librustc/middle/cfg/mod.rs +++ b/src/librustc/middle/cfg/mod.rs @@ -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, 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) } } diff --git a/src/librustc/middle/dataflow.rs b/src/librustc/middle/dataflow.rs index cf33cd7136578..1718df702553f 100644 --- a/src/librustc/middle/dataflow.rs +++ b/src/librustc/middle/dataflow.rs @@ -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, + nodeid_to_index: NodeMap>, // 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 { - 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>) -> &'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 { + cfg: &cfg::CFG) -> NodeMap> { 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, + fn add_entries_from_fn_decl(index: &mut NodeMap>, 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, + index: &'a mut NodeMap>, } 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(&self, id: ast::NodeId, f: F) -> bool where + pub fn each_bit_on_entry(&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(&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(&self, id: ast::NodeId, f: F) -> bool where + pub fn each_gen_bit(&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(&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); diff --git a/src/librustc/middle/fast_reject.rs b/src/librustc/middle/fast_reject.rs index b33e5a802f158..7584a2e44cc7c 100644 --- a/src/librustc/middle/fast_reject.rs +++ b/src/librustc/middle/fast_reject.rs @@ -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, } } diff --git a/src/librustc/middle/infer/freshen.rs b/src/librustc/middle/infer/freshen.rs index 1b7e6c33c0575..e41b949d5df1d 100644 --- a/src/librustc/middle/infer/freshen.rs +++ b/src/librustc/middle/infer/freshen.rs @@ -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(..) | diff --git a/src/librustc/middle/pat_util.rs b/src/librustc/middle/pat_util.rs index 01dc55c3eeec0..a7df2f4a5dafb 100644 --- a/src/librustc/middle/pat_util.rs +++ b/src/librustc/middle/pat_util.rs @@ -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) => { diff --git a/src/librustc/middle/traits/coherence.rs b/src/librustc/middle/traits/coherence.rs index 9ef4a436b8d02..4d45bb841f49f 100644 --- a/src/librustc/middle/traits/coherence.rs +++ b/src/librustc/middle/traits/coherence.rs @@ -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: {}", diff --git a/src/librustc/middle/traits/object_safety.rs b/src/librustc/middle/traits/object_safety.rs index f10f7eb3951c7..64835a666faef 100644 --- a/src/librustc/middle/traits/object_safety.rs +++ b/src/librustc/middle/traits/object_safety.rs @@ -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 { - // The method's first parameter must be something that derefs to - // `&self`. For now, we only accept `&self` and `Box`. - 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`. + match method.explicit_self { ty::StaticExplicitSelfCategory => { return Some(MethodViolationCode::StaticMethod); } + ty::ByValueExplicitSelfCategory | ty::ByReferenceExplicitSelfCategory(..) | ty::ByBoxExplicitSelfCategory => { } diff --git a/src/librustc/middle/traits/select.rs b/src/librustc/middle/traits/select.rs index daf7e50e1bc9a..8086ca71e019e 100644 --- a/src/librustc/middle/traits/select.rs +++ b/src/librustc/middle/traits/select.rs @@ -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]) diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index a461297dd9553..3d059e27c5207 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -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> { } } -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> { 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_projection(_) | ty_param(_) | ty_infer(_) | - ty_open(_) | ty_err => { } } diff --git a/src/librustc/middle/ty_fold.rs b/src/librustc/middle/ty_fold.rs index 92b0ea905accf..d2469c052ac51 100644 --- a/src/librustc/middle/ty_fold.rs +++ b/src/librustc/middle/ty_fold.rs @@ -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)) diff --git a/src/librustc/middle/ty_walk.rs b/src/librustc/middle/ty_walk.rs index 40dfd479364a6..3336e7ee8bf71 100644 --- a/src/librustc/middle/ty_walk.rs +++ b/src/librustc/middle/ty_walk.rs @@ -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) => { diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index 23b63bc26657c..15b3c6d9d0602 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -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() diff --git a/src/librustc_back/target/openbsd_base.rs b/src/librustc_back/target/openbsd_base.rs index 42220a87bd414..759147b939cb8 100644 --- a/src/librustc_back/target/openbsd_base.rs +++ b/src/librustc_back/target/openbsd_base.rs @@ -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() diff --git a/src/librustc_borrowck/borrowck/mod.rs b/src/librustc_borrowck/borrowck/mod.rs index fd7880212f10b..b0a03408b51e1 100644 --- a/src/librustc_borrowck/borrowck/mod.rs +++ b/src/librustc_borrowck/borrowck/mod.rs @@ -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 => { diff --git a/src/librustc_borrowck/graphviz.rs b/src/librustc_borrowck/graphviz.rs index 4465000d8d81e..a2c9930c0ed2f 100644 --- a/src/librustc_borrowck/graphviz.rs +++ b/src/librustc_borrowck/graphviz.rs @@ -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; diff --git a/src/librustc_trans/trans/_match.rs b/src/librustc_trans/trans/_match.rs index 1a24b3fabf898..26e1a981f1bae 100644 --- a/src/librustc_trans/trans/_match.rs +++ b/src/librustc_trans/trans/_match.rs @@ -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) diff --git a/src/librustc_trans/trans/adt.rs b/src/librustc_trans/trans/adt.rs index 903de94020770..3ea14d3c58929 100644 --- a/src/librustc_trans/trans/adt.rs +++ b/src/librustc_trans/trans/adt.rs @@ -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() } } diff --git a/src/librustc_trans/trans/base.rs b/src/librustc_trans/trans/base.rs index 35b6ca7f0f511..b18b7b75d32fc 100644 --- a/src/librustc_trans/trans/base.rs +++ b/src/librustc_trans/trans/base.rs @@ -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) // 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(); diff --git a/src/librustc_trans/trans/common.rs b/src/librustc_trans/trans/common.rs index e92960ec7cdca..a3ba506fc46a2 100644 --- a/src/librustc_trans/trans/common.rs +++ b/src/librustc_trans/trans/common.rs @@ -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) } diff --git a/src/librustc_trans/trans/consts.rs b/src/librustc_trans/trans/consts.rs index 3c0024712b23a..19046d84d6972 100644 --- a/src/librustc_trans/trans/consts.rs +++ b/src/librustc_trans/trans/consts.rs @@ -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)) diff --git a/src/librustc_trans/trans/datum.rs b/src/librustc_trans/trans/datum.rs index e0598583a1954..8262dbf55ddae 100644 --- a/src/librustc_trans/trans/datum.rs +++ b/src/librustc_trans/trans/datum.rs @@ -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) diff --git a/src/librustc_trans/trans/debuginfo.rs b/src/librustc_trans/trans/debuginfo.rs index b5cba9b67406c..162881f58c74e 100644 --- a/src/librustc_trans/trans/debuginfo.rs +++ b/src/librustc_trans/trans/debuginfo.rs @@ -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 \ diff --git a/src/librustc_trans/trans/expr.rs b/src/librustc_trans/trans/expr.rs index 78992959a6f22..9e9ee4537524b 100644 --- a/src/librustc_trans/trans/expr.rs +++ b/src/librustc_trans/trans/expr.rs @@ -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)) } } diff --git a/src/librustc_trans/trans/glue.rs b/src/librustc_trans/trans/glue.rs index 20956bf795b85..c14683aeade05 100644 --- a/src/librustc_trans/trans/glue.rs +++ b/src/librustc_trans/trans/glue.rs @@ -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), diff --git a/src/librustc_trans/trans/meth.rs b/src/librustc_trans/trans/meth.rs index 7644ecf2cfde6..3411f12886d22 100644 --- a/src/librustc_trans/trans/meth.rs +++ b/src/librustc_trans/trans/meth.rs @@ -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() } } diff --git a/src/librustc_trans/trans/tvec.rs b/src/librustc_trans/trans/tvec.rs index 7b59e0258ee22..d3acd23e6416d 100644 --- a/src/librustc_trans/trans/tvec.rs +++ b/src/librustc_trans/trans/tvec.rs @@ -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"), } diff --git a/src/librustc_trans/trans/type_.rs b/src/librustc_trans/trans/type_.rs index 0c69a7132a77b..d5ec18e641b79 100644 --- a/src/librustc_trans/trans/type_.rs +++ b/src/librustc_trans/trans/type_.rs @@ -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()) diff --git a/src/librustc_trans/trans/type_of.rs b/src/librustc_trans/trans/type_of.rs index b53ea79804c08..97278eb0512e2 100644 --- a/src/librustc_trans/trans/type_of.rs +++ b/src/librustc_trans/trans/type_of.rs @@ -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 = 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) } } diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index ff397d994304d..581279c2c9ca8 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -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 + 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); +} diff --git a/src/librustc_typeck/check/implicator.rs b/src/librustc_typeck/check/implicator.rs index 998a4504088a3..f65e585d23edd 100644 --- a/src/librustc_typeck/check/implicator.rs +++ b/src/librustc_typeck/check/implicator.rs @@ -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()))); - } } } diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs index 53976df75d616..d7db21f3a2f76 100644 --- a/src/librustc_typeck/check/method/confirm.rs +++ b/src/librustc_typeck/check/method/confirm.rs @@ -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); diff --git a/src/librustc_typeck/check/vtable.rs b/src/librustc_typeck/check/vtable.rs index 3666b69d1c678..630530cf11f84 100644 --- a/src/librustc_typeck/check/vtable.rs +++ b/src/librustc_typeck/check/vtable.rs @@ -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, diff --git a/src/librustc_typeck/coherence/mod.rs b/src/librustc_typeck/coherence/mod.rs index 7215ab01b02de..7dac1eeb6f117 100644 --- a/src/librustc_typeck/coherence/mod.rs +++ b/src/librustc_typeck/coherence/mod.rs @@ -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 } diff --git a/src/librustc_typeck/variance.rs b/src/librustc_typeck/variance.rs index 93d9ce3df84ed..90ca6a798056b 100644 --- a/src/librustc_typeck/variance.rs +++ b/src/librustc_typeck/variance.rs @@ -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); } diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index d8ef3194e837e..a3e0cecdd4826 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1619,7 +1619,6 @@ impl<'tcx> Clean 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"), } } diff --git a/src/libstd/ascii.rs b/src/libstd/ascii.rs index 4d38d17576ddb..94457a5d71441 100644 --- a/src/libstd/ascii.rs +++ b/src/libstd/ascii.rs @@ -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; diff --git a/src/libstd/collections/hash/state.rs b/src/libstd/collections/hash/state.rs index 7e6dd45b51e48..3a06d2d03bf3f 100644 --- a/src/libstd/collections/hash/state.rs +++ b/src/libstd/collections/hash/state.rs @@ -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. diff --git a/src/libstd/io/impls.rs b/src/libstd/io/impls.rs index 7f3ce7924c1ca..82b69ddebff68 100644 --- a/src/libstd/io/impls.rs +++ b/src/libstd/io/impls.rs @@ -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 { (**self).read(buf) } + + fn read_to_end(&mut self, buf: &mut Vec) -> 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 { (**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) -> io::Result<()> { + (**self).read_until(byte, buf) + } + + fn read_line(&mut self, buf: &mut String) -> io::Result<()> { (**self).read_line(buf) } } impl Read for Box { @@ -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 { 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(()) } } diff --git a/src/libstd/prelude/v1.rs b/src/libstd/prelude/v1.rs index d2dc33451200f..dad0ff0a15e29 100644 --- a/src/libstd/prelude/v1.rs +++ b/src/libstd/prelude/v1.rs @@ -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")] diff --git a/src/libstd/sync/barrier.rs b/src/libstd/sync/barrier.rs index b036177af153a..f697d10d5dfab 100644 --- a/src/libstd/sync/barrier.rs +++ b/src/libstd/sync/barrier.rs @@ -33,13 +33,13 @@ use sync::{Mutex, Condvar}; pub struct Barrier { lock: Mutex, 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(); diff --git a/src/libstd/sync/condvar.rs b/src/libstd/sync/condvar.rs index 52561d482c39d..aa87abc6e9aac 100644 --- a/src/libstd/sync/condvar.rs +++ b/src/libstd/sync/condvar.rs @@ -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(); diff --git a/src/libstd/sync/mpsc/blocking.rs b/src/libstd/sync/mpsc/blocking.rs index 69b1e242b154d..2e4155ea35128 100644 --- a/src/libstd/sync/mpsc/blocking.rs +++ b/src/libstd/sync/mpsc/blocking.rs @@ -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) } } diff --git a/src/libstd/sync/mpsc/mod.rs b/src/libstd/sync/mpsc/mod.rs index b437549a04492..7bd1f3542eb13 100644 --- a/src/libstd/sync/mpsc/mod.rs +++ b/src/libstd/sync/mpsc/mod.rs @@ -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::(); +//! let (tx, rx) = channel::(); //! 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::(0); +//! let (tx, rx) = sync_channel::(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::(); +//! let (tx, rx) = channel::(); //! 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::(); +//! let (tx, rx) = channel::(); //! let mut timer = Timer::new().unwrap(); //! //! loop { @@ -525,7 +525,7 @@ pub fn channel() -> (Sender, Receiver) { /// assert_eq!(rx.recv().unwrap(), 2); /// ``` #[stable(feature = "rust1", since = "1.0.0")] -pub fn sync_channel(bound: uint) -> (SyncSender, Receiver) { +pub fn sync_channel(bound: usize) -> (SyncSender, Receiver) { 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::(); + let (tx, rx) = channel::(); tx.send(1).unwrap(); assert_eq!(rx.recv().unwrap(), 1); } @@ -1058,7 +1058,7 @@ mod test { #[test] fn smoke_shared() { - let (tx, rx) = channel::(); + let (tx, rx) = channel::(); 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::(); + let (tx, rx) = channel::(); let _t = thread::spawn(move|| { tx.send(1).unwrap(); }); @@ -1077,21 +1077,21 @@ mod test { #[test] fn smoke_port_gone() { - let (tx, rx) = channel::(); + let (tx, rx) = channel::(); drop(rx); assert!(tx.send(1).is_err()); } #[test] fn smoke_shared_port_gone() { - let (tx, rx) = channel::(); + let (tx, rx) = channel::(); drop(rx); assert!(tx.send(1).is_err()) } #[test] fn smoke_shared_port_gone2() { - let (tx, rx) = channel::(); + let (tx, rx) = channel::(); drop(rx); let tx2 = tx.clone(); drop(tx); @@ -1100,7 +1100,7 @@ mod test { #[test] fn port_gone_concurrent() { - let (tx, rx) = channel::(); + let (tx, rx) = channel::(); let _t = thread::spawn(move|| { rx.recv().unwrap(); }); @@ -1109,7 +1109,7 @@ mod test { #[test] fn port_gone_concurrent_shared() { - let (tx, rx) = channel::(); + let (tx, rx) = channel::(); 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::(); + let (tx, rx) = channel::(); drop(tx); assert!(rx.recv().is_err()); } @@ -1135,7 +1135,7 @@ mod test { #[test] fn chan_gone_concurrent() { - let (tx, rx) = channel::(); + let (tx, rx) = channel::(); 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::(); + let (tx, rx) = channel::(); 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::(); + static AMT: u32 = 10000; + static NTHREADS: u32 = 8; + let (tx, rx) = channel::(); 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::(); + let (tx2, rx2) = channel::(); 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::(); + let (tx, rx) = channel::(); 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::(); - let (tx2, rx2) = channel::(); + let (tx1, rx1) = channel::(); + let (tx2, rx2) = channel::(); 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::(); + let (_tx, rx) = channel::(); drop(rx); } #[test] fn oneshot_single_thread_close_chan_first() { // Simple test of closing without sending - let (tx, _rx) = channel::(); + let (tx, _rx) = channel::(); 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::>(); + let (tx, rx) = channel::>(); 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::(); + let (tx, rx) = channel::(); drop(tx); rx.recv().unwrap(); }).join(); @@ -1267,42 +1267,42 @@ mod test { #[test] fn oneshot_single_thread_send_then_recv() { - let (tx, rx) = channel::>(); + let (tx, rx) = channel::>(); tx.send(box 10).unwrap(); assert!(rx.recv().unwrap() == box 10); } #[test] fn oneshot_single_thread_try_send_open() { - let (tx, rx) = channel::(); + let (tx, rx) = channel::(); assert!(tx.send(10).is_ok()); assert!(rx.recv().unwrap() == 10); } #[test] fn oneshot_single_thread_try_send_closed() { - let (tx, rx) = channel::(); + let (tx, rx) = channel::(); drop(rx); assert!(tx.send(10).is_err()); } #[test] fn oneshot_single_thread_try_recv_open() { - let (tx, rx) = channel::(); + let (tx, rx) = channel::(); tx.send(10).unwrap(); assert!(rx.recv() == Ok(10)); } #[test] fn oneshot_single_thread_try_recv_closed() { - let (tx, rx) = channel::(); + let (tx, rx) = channel::(); drop(tx); assert!(rx.recv().is_err()); } #[test] fn oneshot_single_thread_peek_data() { - let (tx, rx) = channel::(); + let (tx, rx) = channel::(); 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::(); + let (tx, rx) = channel::(); 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::(); + let (_tx, rx) = channel::(); assert_eq!(rx.try_recv(), Err(TryRecvError::Empty)); } #[test] fn oneshot_multi_task_recv_then_send() { - let (tx, rx) = channel::>(); + let (tx, rx) = channel::>(); 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::>(); + let (tx, rx) = channel::>(); 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::(); + let (tx, rx) = channel::(); 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::(); + let (tx, rx) = channel::(); 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::(); + let (tx, rx) = channel::(); 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>, i: int) { + fn send(tx: Sender>, i: i32) { if i == 10 { return } thread::spawn(move|| { @@ -1414,7 +1414,7 @@ mod test { }); } - fn recv(rx: Receiver>, i: int) { + fn recv(rx: Receiver>, 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::(); - let (total_tx, total_rx) = channel::(); + let (tx, rx) = channel::(); + let (total_tx, total_rx) = channel::(); 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::(); + let (tx, rx) = channel::(); 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::(); + let (tx1, rx1) = channel::(); 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::(1); + let (tx, rx) = sync_channel::(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::(1); + let (tx, rx) = sync_channel::(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::(0); + let (tx, rx) = sync_channel::(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::(0); + let (tx, rx) = sync_channel::(0); drop(rx); assert!(tx.send(1).is_err()); } #[test] fn smoke_shared_port_gone2() { - let (tx, rx) = sync_channel::(0); + let (tx, rx) = sync_channel::(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::(0); + let (tx, rx) = sync_channel::(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::(0); + let (tx, rx) = sync_channel::(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::(0); + let (tx, rx) = sync_channel::(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::(0); + let (tx, rx) = sync_channel::(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::(0); + let (tx, rx) = sync_channel::(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::(0); + static AMT: u32 = 1000; + static NTHREADS: u32 = 8; + let (tx, rx) = sync_channel::(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::(0); + let (_tx, rx) = sync_channel::(0); drop(rx); } #[test] fn oneshot_single_thread_close_chan_first() { // Simple test of closing without sending - let (tx, _rx) = sync_channel::(0); + let (tx, _rx) = sync_channel::(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::>(0); + let (tx, rx) = sync_channel::>(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::(0); + let (tx, rx) = sync_channel::(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::>(1); + let (tx, rx) = sync_channel::>(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::(1); + let (tx, rx) = sync_channel::(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::(0); + let (tx, rx) = sync_channel::(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::(0); + let (tx, _rx) = sync_channel::(0); assert_eq!(tx.try_send(10), Err(TrySendError::Full(10))); } #[test] fn oneshot_single_thread_try_recv_open() { - let (tx, rx) = sync_channel::(1); + let (tx, rx) = sync_channel::(1); tx.send(10).unwrap(); assert!(rx.recv() == Ok(10)); } #[test] fn oneshot_single_thread_try_recv_closed() { - let (tx, rx) = sync_channel::(0); + let (tx, rx) = sync_channel::(0); drop(tx); assert!(rx.recv().is_err()); } #[test] fn oneshot_single_thread_peek_data() { - let (tx, rx) = sync_channel::(1); + let (tx, rx) = sync_channel::(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::(0); + let (tx, rx) = sync_channel::(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::(0); + let (_tx, rx) = sync_channel::(0); assert_eq!(rx.try_recv(), Err(TryRecvError::Empty)); } #[test] fn oneshot_multi_task_recv_then_send() { - let (tx, rx) = sync_channel::>(0); + let (tx, rx) = sync_channel::>(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::>(0); + let (tx, rx) = sync_channel::>(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::(0); + let (tx, rx) = sync_channel::(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::(0); + let (tx, rx) = sync_channel::(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::(0); + let (tx, rx) = sync_channel::(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::>(0); + let (tx, rx) = sync_channel::>(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::>(0); + let (tx, rx) = sync_channel::>(0); send(tx, 0); recv(rx, 0); - fn send(tx: SyncSender>, i: int) { + fn send(tx: SyncSender>, i: i32) { if i == 10 { return } thread::spawn(move|| { @@ -1878,7 +1878,7 @@ mod sync_tests { }); } - fn recv(rx: Receiver>, i: int) { + fn recv(rx: Receiver>, 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::(0); - let (total_tx, total_rx) = sync_channel::(0); + let (tx, rx) = sync_channel::(0); + let (total_tx, total_rx) = sync_channel::(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::(0); + let (tx, rx) = sync_channel::(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::(1); + let (tx1, rx1) = sync_channel::(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::(0); + let (tx, rx) = sync_channel::(0); let _t = thread::spawn(move|| { rx.recv().unwrap(); }); assert_eq!(tx.send(1), Ok(())); } #[test] fn send2() { - let (tx, rx) = sync_channel::(0); + let (tx, rx) = sync_channel::(0); let _t = thread::spawn(move|| { drop(rx); }); assert!(tx.send(1).is_err()); } #[test] fn send3() { - let (tx, rx) = sync_channel::(1); + let (tx, rx) = sync_channel::(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::(0); + let (tx, rx) = sync_channel::(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::(0); + let (tx, _rx) = sync_channel::(0); assert_eq!(tx.try_send(1), Err(TrySendError::Full(1))); } #[test] fn try_send2() { - let (tx, _rx) = sync_channel::(1); + let (tx, _rx) = sync_channel::(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::(1); + let (tx, rx) = sync_channel::(1); assert_eq!(tx.try_send(1), Ok(())); drop(rx); assert_eq!(tx.try_send(1), Err(TrySendError::Disconnected(1))); diff --git a/src/libstd/sync/mpsc/oneshot.rs b/src/libstd/sync/mpsc/oneshot.rs index eb45681fa626d..f287712d9d45d 100644 --- a/src/libstd/sync/mpsc/oneshot.rs +++ b/src/libstd/sync/mpsc/oneshot.rs @@ -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 Packet { // 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 Packet { // 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 Packet { 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 Packet { 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 Packet { // 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 Packet { // 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 { - 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 Packet { // 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 Packet { // 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 Packet { // We woke ourselves up from select. ptr => unsafe { - drop(SignalToken::cast_from_uint(ptr)); + drop(SignalToken::cast_from_usize(ptr)); Ok(false) } } diff --git a/src/libstd/sync/mpsc/select.rs b/src/libstd/sync/mpsc/select.rs index db8efe19dc1df..8de5bbc620665 100644 --- a/src/libstd/sync/mpsc/select.rs +++ b/src/libstd/sync/mpsc/select.rs @@ -71,7 +71,7 @@ use sync::mpsc::blocking::{self, SignalToken}; pub struct Select { head: *mut Handle<'static, ()>, tail: *mut Handle<'static, ()>, - next_id: Cell, + next_id: Cell, } 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::(); - let (tx2, rx2) = channel::(); + let (tx1, rx1) = channel::(); + let (tx2, rx2) = channel::(); 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::(); - let (_tx2, rx2) = channel::(); - let (_tx3, rx3) = channel::(); - let (_tx4, rx4) = channel::(); - let (tx5, rx5) = channel::(); + let (_tx1, rx1) = channel::(); + let (_tx2, rx2) = channel::(); + let (_tx3, rx3) = channel::(); + let (_tx4, rx4) = channel::(); + let (tx5, rx5) = channel::(); tx5.send(4).unwrap(); select! { _foo = rx1.recv() => { panic!("1") }, @@ -411,8 +411,8 @@ mod test { #[test] fn closed() { - let (_tx1, rx1) = channel::(); - let (tx2, rx2) = channel::(); + let (_tx1, rx1) = channel::(); + let (tx2, rx2) = channel::(); drop(tx2); select! { @@ -423,9 +423,9 @@ mod test { #[test] fn unblocks() { - let (tx1, rx1) = channel::(); - let (_tx2, rx2) = channel::(); - let (tx3, rx3) = channel::(); + let (tx1, rx1) = channel::(); + let (_tx2, rx2) = channel::(); + let (tx3, rx3) = channel::(); 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::(); - let (tx2, rx2) = channel::(); + let (tx1, rx1) = channel::(); + let (tx2, rx2) = channel::(); 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::(); - let (tx2, rx2) = channel::(); + static AMT: i32 = 10000; + let (tx1, rx1) = channel::(); + let (tx2, rx2) = channel::(); let (tx3, rx3) = channel::<()>(); let _t = thread::spawn(move|| { @@ -500,8 +500,8 @@ mod test { #[test] fn cloning() { - let (tx1, rx1) = channel::(); - let (_tx2, rx2) = channel::(); + let (tx1, rx1) = channel::(); + let (_tx2, rx2) = channel::(); let (tx3, rx3) = channel::<()>(); let _t = thread::spawn(move|| { @@ -522,8 +522,8 @@ mod test { #[test] fn cloning2() { - let (tx1, rx1) = channel::(); - let (_tx2, rx2) = channel::(); + let (tx1, rx1) = channel::(); + let (_tx2, rx2) = channel::(); let (tx3, rx3) = channel::<()>(); let _t = thread::spawn(move|| { @@ -716,7 +716,7 @@ mod test { #[test] fn sync1() { - let (tx, rx) = sync_channel::(1); + let (tx, rx) = sync_channel::(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::(0); + let (tx, rx) = sync_channel::(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::(0); - let (tx2, rx2): (Sender, Receiver) = channel(); + let (tx1, rx1) = sync_channel::(0); + let (tx2, rx2): (Sender, Receiver) = channel(); let _t = thread::spawn(move|| { tx1.send(1).unwrap(); }); let _t = thread::spawn(move|| { tx2.send(2).unwrap(); }); select! { diff --git a/src/libstd/sync/mpsc/shared.rs b/src/libstd/sync/mpsc/shared.rs index 729e7991f97cf..8d14824d37fee 100644 --- a/src/libstd/sync/mpsc/shared.rs +++ b/src/libstd/sync/mpsc/shared.rs @@ -101,7 +101,7 @@ impl Packet { 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 Packet { // 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 Packet { } 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 Packet { 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) } } //////////////////////////////////////////////////////////////////////////// diff --git a/src/libstd/sync/mpsc/spsc_queue.rs b/src/libstd/sync/mpsc/spsc_queue.rs index 7b5c614536df9..ce40fa2672ab3 100644 --- a/src/libstd/sync/mpsc/spsc_queue.rs +++ b/src/libstd/sync/mpsc/spsc_queue.rs @@ -69,7 +69,7 @@ pub struct Queue { // 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 Queue { /// 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 { + pub unsafe fn new(bound: usize) -> Queue { 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(); diff --git a/src/libstd/sync/mpsc/stream.rs b/src/libstd/sync/mpsc/stream.rs index 2d528662f64fc..5a1e05f9c1565 100644 --- a/src/libstd/sync/mpsc/stream.rs +++ b/src/libstd/sync/mpsc/stream.rs @@ -43,7 +43,7 @@ pub struct Packet { queue: spsc::Queue>, // 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 Packet { 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 Packet { // 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 Packet { } 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> { @@ -350,7 +350,7 @@ impl Packet { } // 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); diff --git a/src/libstd/sync/mpsc/sync.rs b/src/libstd/sync/mpsc/sync.rs index 36b50b0d4af01..33c1614e1b297 100644 --- a/src/libstd/sync/mpsc/sync.rs +++ b/src/libstd/sync/mpsc/sync.rs @@ -64,7 +64,7 @@ struct State { queue: Queue, // queue of senders waiting to send data blocker: Blocker, // currently blocked task on this channel buf: Buffer, // 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 { buf: Vec>, - start: uint, - size: uint, + start: usize, + size: usize, } #[derive(Debug)] @@ -137,7 +137,7 @@ fn wakeup(token: SignalToken, guard: MutexGuard>) { } impl Packet { - pub fn new(cap: uint) -> Packet { + pub fn new(cap: usize) -> Packet { Packet { channels: AtomicUsize::new(1), lock: Mutex::new(State { @@ -442,8 +442,8 @@ impl Buffer { 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() } } //////////////////////////////////////////////////////////////////////////////// diff --git a/src/libstd/sync/mutex.rs b/src/libstd/sync/mutex.rs index b71cc0c265364..02b2db572ec4f 100644 --- a/src/libstd/sync/mutex.rs +++ b/src/libstd/sync/mutex.rs @@ -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>, + i: Arc>, } impl Drop for Unwinder { fn drop(&mut self) { diff --git a/src/libstd/sync/task_pool.rs b/src/libstd/sync/task_pool.rs index a45048be24c06..31f3dfd877cfb 100644 --- a/src/libstd/sync/task_pool.rs +++ b/src/libstd/sync/task_pool.rs @@ -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::(); @@ -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() { diff --git a/src/libstd/sys/unix/fs2.rs b/src/libstd/sys/unix/fs2.rs index 92a47c6c3850d..c6b9c2cba5227 100644 --- a/src/libstd/sys/unix/fs2.rs +++ b/src/libstd/sys/unix/fs2.rs @@ -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, + dirp: Dir, + root: Arc, } +struct Dir(*mut libc::DIR); + +unsafe impl Send for Dir {} +unsafe impl Sync for Dir {} + pub struct DirEntry { - buf: Vec, - dirent: *mut libc::dirent_t, - root: Rc, + buf: Vec, // actually *mut libc::dirent_t + root: Arc, } #[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 { - 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 }) } } } diff --git a/src/libstd/sys/windows/fs2.rs b/src/libstd/sys/windows/fs2.rs index 8abcd90efe857..117f819eeeb3f 100644 --- a/src/libstd/sys/windows/fs2.rs +++ b/src/libstd/sys/windows/fs2.rs @@ -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, first: Option, } -pub struct DirEntry { path: PathBuf } +struct FindNextFileHandle(libc::HANDLE); + +unsafe impl Send for FindNextFileHandle {} +unsafe impl Sync for FindNextFileHandle {} + +pub struct DirEntry { + root: Arc, + 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 { + fn new(root: &Arc, wfd: &libc::WIN32_FIND_DATAW) -> Option { 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(&::from_wide(filename)) } } @@ -312,7 +323,11 @@ pub fn readdir(p: &Path) -> io::Result { 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()) } diff --git a/src/libstd/thread.rs b/src/libstd/thread.rs index 1f70e1526a096..6aad2bbcc7f08 100644 --- a/src/libstd/thread.rs +++ b/src/libstd/thread.rs @@ -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 /// diff --git a/src/libstd/thread_local/mod.rs b/src/libstd/thread_local/mod.rs index cdd71d440fe4f..d65156dae9604 100644 --- a/src/libstd/thread_local/mod.rs +++ b/src/libstd/thread_local/mod.rs @@ -74,7 +74,7 @@ pub mod __impl { /// use std::cell::RefCell; /// use std::thread; /// -/// thread_local!(static FOO: RefCell = RefCell::new(1)); +/// thread_local!(static FOO: RefCell = 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; 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 = UnsafeCell { value: 1 }); + thread_local!(static FOO: UnsafeCell = UnsafeCell { value: 1 }); FOO.with(|f| unsafe { assert_eq!(*f.get(), 1); @@ -632,7 +632,7 @@ mod tests { thread_local!(static K2: UnsafeCell> = 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> { + fn map() -> RefCell> { let mut m = HashMap::new(); m.insert(1, 2); RefCell::new(m) } - thread_local!(static FOO: RefCell> = map()); + thread_local!(static FOO: RefCell> = 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> = RefCell::new(vec![1, 2, 3])); + thread_local!(static FOO: RefCell> = RefCell::new(vec![1, 2, 3])); FOO.with(|vec| { assert_eq!(vec.borrow().len(), 3); diff --git a/src/libstd/thread_local/scoped.rs b/src/libstd/thread_local/scoped.rs index 01220e7bc1fe1..a2a5d8b81f404 100644 --- a/src/libstd/thread_local/scoped.rs +++ b/src/libstd/thread_local/scoped.rs @@ -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 Key { /// # 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 Key { /// # 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); + scoped_thread_local!(static BAR: Cell); BAR.set(&Cell::new(1), || { BAR.with(|slot| { diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs index c79b510ae2dde..656d507ed69b8 100644 --- a/src/libsyntax/ext/build.rs +++ b/src/libsyntax/ext/build.rs @@ -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 { - self.expr_lit(sp, ast::LitInt(u as u64, ast::UnsignedIntLit(ast::TyU8))) - } fn expr_u32(&self, sp: Span, u: u32) -> P { self.expr_lit(sp, ast::LitInt(u as u64, ast::UnsignedIntLit(ast::TyU32))) } + fn expr_u8(&self, sp: Span, u: u8) -> P { + self.expr_lit(sp, ast::LitInt(u as u64, ast::UnsignedIntLit(ast::TyU8))) + } fn expr_bool(&self, sp: Span, value: bool) -> P { self.expr_lit(sp, ast::LitBool(value)) } diff --git a/src/libsyntax/ext/format.rs b/src/libsyntax/ext/format.rs index 1c2374e31f130..91262556abd70 100644 --- a/src/libsyntax/ext/format.rs +++ b/src/libsyntax/ext/format.rs @@ -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]) } }; diff --git a/src/test/auxiliary/cci_class_cast.rs b/src/test/auxiliary/cci_class_cast.rs index dd272bf639b97..96a06968c5fa3 100644 --- a/src/test/auxiliary/cci_class_cast.rs +++ b/src/test/auxiliary/cci_class_cast.rs @@ -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) } diff --git a/src/test/compile-fail/coherence-blanket-conflicts-with-blanket-implemented.rs b/src/test/compile-fail/coherence-blanket-conflicts-with-blanket-implemented.rs index d4decb713498d..98a9c713e84c3 100644 --- a/src/test/compile-fail/coherence-blanket-conflicts-with-blanket-implemented.rs +++ b/src/test/compile-fail/coherence-blanket-conflicts-with-blanket-implemented.rs @@ -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; diff --git a/src/test/compile-fail/coherence-blanket-conflicts-with-blanket-unimplemented.rs b/src/test/compile-fail/coherence-blanket-conflicts-with-blanket-unimplemented.rs index b1ee1762b6e71..57d25a3bf586d 100644 --- a/src/test/compile-fail/coherence-blanket-conflicts-with-blanket-unimplemented.rs +++ b/src/test/compile-fail/coherence-blanket-conflicts-with-blanket-unimplemented.rs @@ -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 diff --git a/src/test/compile-fail/coherence-blanket-conflicts-with-specific-cross-crate.rs b/src/test/compile-fail/coherence-blanket-conflicts-with-specific-cross-crate.rs index 1f6bb08871c76..b3ef79c6cc01e 100644 --- a/src/test/compile-fail/coherence-blanket-conflicts-with-specific-cross-crate.rs +++ b/src/test/compile-fail/coherence-blanket-conflicts-with-specific-cross-crate.rs @@ -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; diff --git a/src/test/compile-fail/coherence-blanket-conflicts-with-specific-multidispatch.rs b/src/test/compile-fail/coherence-blanket-conflicts-with-specific-multidispatch.rs index c3563792ce3c7..7b60a5ecbd71f 100644 --- a/src/test/compile-fail/coherence-blanket-conflicts-with-specific-multidispatch.rs +++ b/src/test/compile-fail/coherence-blanket-conflicts-with-specific-multidispatch.rs @@ -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 diff --git a/src/test/compile-fail/coherence-blanket-conflicts-with-specific.rs b/src/test/compile-fail/coherence-blanket-conflicts-with-specific.rs index 980e4256d2b85..d218b64af0527 100644 --- a/src/test/compile-fail/coherence-blanket-conflicts-with-specific.rs +++ b/src/test/compile-fail/coherence-blanket-conflicts-with-specific.rs @@ -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 diff --git a/src/test/compile-fail/coherence-tuple-conflict.rs b/src/test/compile-fail/coherence-tuple-conflict.rs index 9673fb6a21392..87b007fdd6982 100644 --- a/src/test/compile-fail/coherence-tuple-conflict.rs +++ b/src/test/compile-fail/coherence-tuple-conflict.rs @@ -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 diff --git a/src/test/compile-fail/fn-trait-formatting.rs b/src/test/compile-fail/fn-trait-formatting.rs index 71e1f7091b2c9..d682ef7d70c9d 100644 --- a/src/test/compile-fail/fn-trait-formatting.rs +++ b/src/test/compile-fail/fn-trait-formatting.rs @@ -15,8 +15,7 @@ fn needs_fn(x: F) where F: Fn(isize) -> isize {} fn main() { let _: () = (box |_: isize| {}) as Box; - //~^ ERROR object-safe - //~| ERROR mismatched types + //~^ ERROR mismatched types //~| expected `()` //~| found `Box` //~| expected () diff --git a/src/test/compile-fail/infinite-instantiation.rs b/src/test/compile-fail/infinite-instantiation.rs index 2642ac6204ce4..d39efa3c2ab78 100644 --- a/src/test/compile-fail/infinite-instantiation.rs +++ b/src/test/compile-fail/infinite-instantiation.rs @@ -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; } -impl to_opt for usize { +impl ToOpt for usize { fn to_option(&self) -> Option { Some(*self) } } -impl to_opt for Option { +impl ToOpt for Option { fn to_option(&self) -> Option> { Some((*self).clone()) } } -fn function(counter: usize, t: T) { +fn function(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. } } diff --git a/src/test/compile-fail/issue-17441.rs b/src/test/compile-fail/issue-17441.rs index 321b8b260daa9..9f76f360f26ba 100644 --- a/src/test/compile-fail/issue-17441.rs +++ b/src/test/compile-fail/issue-17441.rs @@ -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` as `core::fmt::Show` - //~^^ HELP did you mean `Box`? - 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` as `core::fmt::Debug` + //~^^ HELP did you mean `Box`? + 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]` diff --git a/src/test/compile-fail/issue-18959.rs b/src/test/compile-fail/issue-18959.rs index 368f3c16f5188..8fb543fb96703 100644 --- a/src/test/compile-fail/issue-18959.rs +++ b/src/test/compile-fail/issue-18959.rs @@ -17,7 +17,11 @@ impl Foo for Thing { fn foo(&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; diff --git a/src/test/compile-fail/lint-missing-doc.rs b/src/test/compile-fail/lint-missing-doc.rs index 73a58741bbbbc..cb2d4e10e6e71 100644 --- a/src/test/compile-fail/lint-missing-doc.rs +++ b/src/test/compile-fail/lint-missing-doc.rs @@ -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() {} } } diff --git a/src/test/compile-fail/move-in-guard-1.rs b/src/test/compile-fail/move-in-guard-1.rs new file mode 100644 index 0000000000000..5d29d0e1fd083 --- /dev/null +++ b/src/test/compile-fail/move-in-guard-1.rs @@ -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 or the MIT license +// , 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) -> bool { false } diff --git a/src/test/compile-fail/move-in-guard-2.rs b/src/test/compile-fail/move-in-guard-2.rs new file mode 100644 index 0000000000000..23af25797975f --- /dev/null +++ b/src/test/compile-fail/move-in-guard-2.rs @@ -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 or the MIT license +// , 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) -> bool { false } diff --git a/src/test/compile-fail/object-safety-by-value-self-use.rs b/src/test/compile-fail/object-safety-by-value-self-use.rs new file mode 100644 index 0000000000000..1b20a902c9d52 --- /dev/null +++ b/src/test/compile-fail/object-safety-by-value-self-use.rs @@ -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 or the MIT license +// , 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) { + t.bar() //~ ERROR cannot move a value of type Bar +} + +fn main() { } + diff --git a/src/test/compile-fail/object-safety-by-value-self.rs b/src/test/compile-fail/object-safety-by-value-self.rs index 5ebcc8516ca05..976717249e8eb 100644 --- a/src/test/compile-fail/object-safety-by-value-self.rs +++ b/src/test/compile-fail/object-safety-by-value-self.rs @@ -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: &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: &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: &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: &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 make_quux(t: &T) -> &Quux { + t +} + +fn make_quux_explicit(t: &T) -> &Quux { + t as &Quux } -fn main() { +#[rustc_error] +fn main() { //~ ERROR compilation successful } diff --git a/src/test/compile-fail/object-safety-generics.rs b/src/test/compile-fail/object-safety-generics.rs index 0ca706404c1f3..fd20accfa1e6b 100644 --- a/src/test/compile-fail/object-safety-generics.rs +++ b/src/test/compile-fail/object-safety-generics.rs @@ -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(&self, t: T); } +trait Quux { + fn bar(&self, t: T) + where Self : Sized; +} + fn make_bar(t: &T) -> &Bar { t //~^ ERROR `Bar` is not object-safe @@ -27,5 +33,13 @@ fn make_bar_explicit(t: &T) -> &Bar { //~| NOTE method `bar` has generic type parameters } +fn make_quux(t: &T) -> &Quux { + t +} + +fn make_quux_explicit(t: &T) -> &Quux { + t as &Quux +} + fn main() { } diff --git a/src/test/compile-fail/object-safety-mentions-Self.rs b/src/test/compile-fail/object-safety-mentions-Self.rs index df0f44c139158..b546774ccbd8c 100644 --- a/src/test/compile-fail/object-safety-mentions-Self.rs +++ b/src/test/compile-fail/object-safety-mentions-Self.rs @@ -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: &T) -> &Bar { t //~^ ERROR `Bar` is not object-safe @@ -43,5 +48,13 @@ fn make_baz_explicit(t: &T) -> &Baz { //~| NOTE method `bar` references the `Self` type in its arguments or return type } +fn make_quux(t: &T) -> &Quux { + t +} + +fn make_quux_explicit(t: &T) -> &Quux { + t as &Quux +} + fn main() { } diff --git a/src/test/compile-fail/recursion.rs b/src/test/compile-fail/recursion.rs index ffc21a5ce6123..55f3b99533653 100644 --- a/src/test/compile-fail/recursion.rs +++ b/src/test/compile-fail/recursion.rs @@ -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 {head:isize, tail:T} @@ -28,9 +27,8 @@ impl Dot for Cons { } fn test (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})} } } diff --git a/src/test/compile-fail/trait-test-2.rs b/src/test/compile-fail/trait-test-2.rs index d8b3176787c04..b09b10ffa0aad 100644 --- a/src/test/compile-fail/trait-test-2.rs +++ b/src/test/compile-fail/trait-test-2.rs @@ -18,4 +18,5 @@ fn main() { 10.dup::(); //~ ERROR does not take type parameters 10.blah::(); //~ ERROR incorrect number of type parameters (box 10 as Box).dup(); //~ ERROR cannot convert to a trait object + //~^ ERROR the trait `bar` is not implemented for the type `bar` } diff --git a/src/test/compile-fail/typeck-builtin-bound-type-parameters.rs b/src/test/compile-fail/typeck-builtin-bound-type-parameters.rs new file mode 100644 index 0000000000000..fb6c43a19059a --- /dev/null +++ b/src/test/compile-fail/typeck-builtin-bound-type-parameters.rs @@ -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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn foo1, U>(x: T) {} +//~^ ERROR: wrong number of type arguments: expected 0, found 1 + +trait Trait: Copy {} +//~^ ERROR: wrong number of type arguments: expected 0, found 1 + +struct MyStruct1>; +//~^ 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() { +} diff --git a/src/test/compile-fail/use-after-move-implicity-coerced-object.rs b/src/test/compile-fail/use-after-move-implicity-coerced-object.rs index d8a82d8fbf046..1998f8ab15529 100644 --- a/src/test/compile-fail/use-after-move-implicity-coerced-object.rs +++ b/src/test/compile-fail/use-after-move-implicity-coerced-object.rs @@ -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) } diff --git a/src/test/parse-fail/trailing-plus-in-bounds.rs b/src/test/parse-fail/trailing-plus-in-bounds.rs index e8f9ed4d2cfc8..8febbf8309ea7 100644 --- a/src/test/parse-fail/trailing-plus-in-bounds.rs +++ b/src/test/parse-fail/trailing-plus-in-bounds.rs @@ -8,11 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::fmt::Show; +use std::fmt::Debug; fn main() { - let x: Box = box 3 as Box; + let x: Box = box 3 as Box; //~^ ERROR at least one type parameter bound must be specified //~^^ ERROR at least one type parameter bound must be specified } - diff --git a/src/test/run-make/graphviz-flowgraph/f07.dot-expected.dot b/src/test/run-make/graphviz-flowgraph/f07.dot-expected.dot index bee4a120d5909..51c6b14e1deed 100644 --- a/src/test/run-make/graphviz-flowgraph/f07.dot-expected.dot +++ b/src/test/run-make/graphviz-flowgraph/f07.dot-expected.dot @@ -22,12 +22,12 @@ digraph block { N3 -> N4; N4 -> N5; N5 -> N6; - N6 -> N8; - N8 -> N9; + N6 -> N9; N9 -> N10; N10 -> N11; N11 -> N12; - N12 -> N13; + N12 -> N8; + N8 -> N13; N13 -> N14; N14 -> N15; N15 -> N7; diff --git a/src/test/run-make/graphviz-flowgraph/f13.dot-expected.dot b/src/test/run-make/graphviz-flowgraph/f13.dot-expected.dot index 76e6651351562..fb7d2ad97bd5f 100644 --- a/src/test/run-make/graphviz-flowgraph/f13.dot-expected.dot +++ b/src/test/run-make/graphviz-flowgraph/f13.dot-expected.dot @@ -32,16 +32,16 @@ digraph block { N6 -> N7; N7 -> N8; N8 -> N9; - N9 -> N11; - N11 -> N12; - N12 -> N13; + N9 -> N12; + N12 -> N11; + N11 -> N13; N13 -> N14; N14 -> N15; N15 -> N10; - N11 -> N16; - N16 -> N17; + N9 -> N17; N17 -> N18; - N18 -> N19; + N18 -> N16; + N16 -> N19; N19 -> N20; N20 -> N21; N21 -> N22; diff --git a/src/test/run-pass/class-separate-impl.rs b/src/test/run-pass/class-separate-impl.rs index 575c32baeac24..daff321efcfd9 100644 --- a/src/test/run-pass/class-separate-impl.rs +++ b/src/test/run-pass/class-separate-impl.rs @@ -54,7 +54,7 @@ fn cat(in_x : uint, in_y : int, in_name: String) -> cat { } } -impl fmt::String for cat { +impl fmt::Display for cat { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{}", self.name) } diff --git a/src/test/run-pass/coherence-multidispatch-tuple.rs b/src/test/run-pass/coherence-multidispatch-tuple.rs index 04a69bbf3a2bc..b16b033c22fcc 100644 --- a/src/test/run-pass/coherence-multidispatch-tuple.rs +++ b/src/test/run-pass/coherence-multidispatch-tuple.rs @@ -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 an impl for homogeneous pairs does not conflict with a diff --git a/src/test/run-pass/issue-22577.rs b/src/test/run-pass/issue-22577.rs new file mode 100644 index 0000000000000..1ecdd39ca7af5 --- /dev/null +++ b/src/test/run-pass/issue-22577.rs @@ -0,0 +1,29 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::{fs, net}; + +fn assert_both() {} + +fn main() { + assert_both::(); + assert_both::(); + assert_both::(); + assert_both::(); + assert_both::(); + assert_both::(); + assert_both::(); + + assert_both::(); + assert_both::(); + assert_both::(); + assert_both::(); + assert_both::(); +} diff --git a/src/test/run-pass/issue-3563-3.rs b/src/test/run-pass/issue-3563-3.rs index f4b85e03eaeac..be4d475229591 100644 --- a/src/test/run-pass/issue-3563-3.rs +++ b/src/test/run-pass/issue-3563-3.rs @@ -101,7 +101,7 @@ impl AsciiArt { // Allows AsciiArt to be converted to a string using the libcore ToString trait. // Note that the %s fmt! specifier will not call this automatically. -impl fmt::String for AsciiArt { +impl fmt::Display for AsciiArt { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { // Convert each line into a string. let lines = self.lines.iter() diff --git a/src/test/run-pass/move-guard-const.rs b/src/test/run-pass/move-guard-const.rs new file mode 100644 index 0000000000000..64c4f1fdbaeab --- /dev/null +++ b/src/test/run-pass/move-guard-const.rs @@ -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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![feature(box_syntax)] + +fn main() { + let x = box 1; + + let v = (1, 2); + + match v { + (2, 1) if take(x) => (), + (1, 2) if take(x) => (), + _ => (), + } +} + +fn take(_: T) -> bool { false } diff --git a/src/test/run-pass/object-safety-sized-self-by-value-self.rs b/src/test/run-pass/object-safety-sized-self-by-value-self.rs new file mode 100644 index 0000000000000..ae092333134ea --- /dev/null +++ b/src/test/run-pass/object-safety-sized-self-by-value-self.rs @@ -0,0 +1,46 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Check that a trait is still object-safe (and usable) if it has +// methods with by-value self so long as they require `Self : Sized`. + +trait Counter { + fn tick(&mut self) -> u32; + fn get(self) -> u32 where Self : Sized; +} + +struct CCounter { + c: u32 +} + +impl Counter for CCounter { + fn tick(&mut self) -> u32 { self.c += 1; self.c } + fn get(self) -> u32 where Self : Sized { self.c } +} + +fn tick1(mut c: C) -> u32 { + tick2(&mut c); + c.get() +} + +fn tick2(c: &mut Counter) { + tick3(c); +} + +fn tick3(c: &mut C) { + c.tick(); + c.tick(); +} + +fn main() { + let mut c = CCounter { c: 0 }; + let value = tick1(c); + assert_eq!(value, 2); +} diff --git a/src/test/run-pass/object-safety-sized-self-generic-method.rs b/src/test/run-pass/object-safety-sized-self-generic-method.rs new file mode 100644 index 0000000000000..1a42c4b6ef664 --- /dev/null +++ b/src/test/run-pass/object-safety-sized-self-generic-method.rs @@ -0,0 +1,46 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Check that a trait is still object-safe (and usable) if it has +// generic methods so long as they require `Self : Sized`. + +trait Counter { + fn tick(&mut self) -> u32; + fn with(&self, f: F) where Self : Sized; +} + +struct CCounter { + c: u32 +} + +impl Counter for CCounter { + fn tick(&mut self) -> u32 { self.c += 1; self.c } + fn with(&self, f: F) { f(self.c); } +} + +fn tick1(c: &mut C) { + tick2(c); + c.with(|i| ()); +} + +fn tick2(c: &mut Counter) { + tick3(c); +} + +fn tick3(c: &mut C) { + c.tick(); + c.tick(); +} + +fn main() { + let mut c = CCounter { c: 0 }; + tick1(&mut c); + assert_eq!(c.tick(), 3); +} diff --git a/src/test/run-pass/object-safety-sized-self-return-Self.rs b/src/test/run-pass/object-safety-sized-self-return-Self.rs new file mode 100644 index 0000000000000..7f075bbb6c2f2 --- /dev/null +++ b/src/test/run-pass/object-safety-sized-self-return-Self.rs @@ -0,0 +1,47 @@ +// 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Check that a trait is still object-safe (and usable) if it has +// methods that return `Self` so long as they require `Self : Sized`. + +trait Counter { + fn new() -> Self where Self : Sized; + fn tick(&mut self) -> u32; +} + +struct CCounter { + c: u32 +} + +impl Counter for CCounter { + fn new() -> CCounter { CCounter { c: 0 } } + fn tick(&mut self) -> u32 { self.c += 1; self.c } +} + +fn preticked() -> C { + let mut c: C = Counter::new(); + tick(&mut c); + c +} + +fn tick(c: &mut Counter) { + tick_generic(c); +} + +fn tick_generic(c: &mut C) { + c.tick(); + c.tick(); +} + +fn main() { + let mut c = preticked::(); + tick(&mut c); + assert_eq!(c.tick(), 5); +}