diff options
| -rw-r--r-- | src/compiletest/compiletest.rs | 2 | ||||
| -rw-r--r-- | src/doc/trpl/SUMMARY.md | 1 | ||||
| -rw-r--r-- | src/doc/trpl/associated-constants.md | 79 | ||||
| -rw-r--r-- | src/libcollections/slice.rs | 12 | ||||
| -rw-r--r-- | src/libcollections/vec.rs | 5 | ||||
| -rw-r--r-- | src/libcollectionstest/vec.rs | 5 | ||||
| -rw-r--r-- | src/libcore/cell.rs | 59 | ||||
| -rw-r--r-- | src/libcore/fmt/mod.rs | 6 | ||||
| -rw-r--r-- | src/libcore/hash/sip.rs | 3 | ||||
| -rw-r--r-- | src/libcoretest/cell.rs | 24 | ||||
| -rw-r--r-- | src/librustc_trans/trans/_match.rs | 35 | ||||
| -rw-r--r-- | src/libstd/collections/hash/map.rs | 1 | ||||
| -rw-r--r-- | src/libstd/net/ip.rs | 28 | ||||
| -rw-r--r-- | src/libstd/sync/mutex.rs | 44 | ||||
| -rw-r--r-- | src/libstd/sync/rwlock.rs | 53 | ||||
| -rw-r--r-- | src/libtest/lib.rs | 59 | ||||
| -rw-r--r-- | src/test/compile-fail/bad-sized.rs | 4 | ||||
| -rw-r--r-- | src/test/run-pass/issue-23261.rs | 70 | ||||
| -rw-r--r-- | src/test/run-pass/out-of-stack.rs | 1 |
19 files changed, 386 insertions, 105 deletions
diff --git a/src/compiletest/compiletest.rs b/src/compiletest/compiletest.rs index d014512666f..2ee391a9374 100644 --- a/src/compiletest/compiletest.rs +++ b/src/compiletest/compiletest.rs @@ -269,7 +269,7 @@ pub fn test_opts(config: &Config) -> test::TestOpts { run_ignored: config.run_ignored, logfile: config.logfile.clone(), run_tests: true, - run_benchmarks: true, + bench_benchmarks: true, nocapture: env::var("RUST_TEST_NOCAPTURE").is_ok(), color: test::AutoColor, } diff --git a/src/doc/trpl/SUMMARY.md b/src/doc/trpl/SUMMARY.md index 695dc42cb64..4dc77aaec5b 100644 --- a/src/doc/trpl/SUMMARY.md +++ b/src/doc/trpl/SUMMARY.md @@ -64,5 +64,6 @@ * [Benchmark Tests](benchmark-tests.md) * [Box Syntax and Patterns](box-syntax-and-patterns.md) * [Slice Patterns](slice-patterns.md) + * [Associated Constants](associated-constants.md) * [Glossary](glossary.md) * [Academic Research](academic-research.md) diff --git a/src/doc/trpl/associated-constants.md b/src/doc/trpl/associated-constants.md new file mode 100644 index 00000000000..1c097be6d68 --- /dev/null +++ b/src/doc/trpl/associated-constants.md @@ -0,0 +1,79 @@ +% Associated Constants + +With the `associated_consts` feature, you can define constants like this: + +```rust +#![feature(associated_consts)] + +trait Foo { + const ID: i32; +} + +impl Foo for i32 { + const ID: i32 = 1; +} + +fn main() { + assert_eq!(1, i32::ID); +} +``` + +Any implementor of `Foo` will have to define `ID`. Without the definition: + +```rust,ignore +#![feature(associated_consts)] + +trait Foo { + const ID: i32; +} + +impl Foo for i32 { +} +``` + +gives + +```text +error: not all trait items implemented, missing: `ID` [E0046] + impl Foo for i32 { + } +``` + +A default value can be implemented as well: + +```rust +#![feature(associated_consts)] + +trait Foo { + const ID: i32 = 1; +} + +impl Foo for i32 { +} + +impl Foo for i64 { + const ID: i32 = 5; +} + +fn main() { + assert_eq!(1, i32::ID); + assert_eq!(5, i64::ID); +} +``` + +As you can see, when implementing `Foo`, you can leave it unimplemented, as +with `i32`. It will then use the default value. But, as in `i64`, we can also +add our own definition. + +Associated constants don’t have to be associated with a trait. An `impl` block +for a `struct` works fine too: + +```rust +#![feature(associated_consts)] + +struct Foo; + +impl Foo { + pub const FOO: u32 = 3; +} +``` diff --git a/src/libcollections/slice.rs b/src/libcollections/slice.rs index 6622d8a9c40..729b0ebc3ce 100644 --- a/src/libcollections/slice.rs +++ b/src/libcollections/slice.rs @@ -1004,11 +1004,7 @@ pub trait SliceConcatExt<T: ?Sized, U> { /// # Examples /// /// ``` - /// let v = vec!["hello", "world"]; - /// - /// let s: String = v.concat(); - /// - /// println!("{}", s); // prints "helloworld" + /// assert_eq!(["hello", "world"].concat(), "helloworld"); /// ``` #[stable(feature = "rust1", since = "1.0.0")] fn concat(&self) -> U; @@ -1018,11 +1014,7 @@ pub trait SliceConcatExt<T: ?Sized, U> { /// # Examples /// /// ``` - /// let v = vec!["hello", "world"]; - /// - /// let s: String = v.connect(" "); - /// - /// println!("{}", s); // prints "hello world" + /// assert_eq!(["hello", "world"].connect(" "), "hello world"); /// ``` #[stable(feature = "rust1", since = "1.0.0")] fn connect(&self, sep: &T) -> U; diff --git a/src/libcollections/vec.rs b/src/libcollections/vec.rs index 33de6b79736..935648099a7 100644 --- a/src/libcollections/vec.rs +++ b/src/libcollections/vec.rs @@ -1777,6 +1777,11 @@ impl<T> Iterator for IntoIter<T> { let exact = diff / (if size == 0 {1} else {size}); (exact, Some(exact)) } + + #[inline] + fn count(self) -> usize { + self.size_hint().0 + } } #[stable(feature = "rust1", since = "1.0.0")] diff --git a/src/libcollectionstest/vec.rs b/src/libcollectionstest/vec.rs index 8a8da0d9faa..ac9cf198d67 100644 --- a/src/libcollectionstest/vec.rs +++ b/src/libcollectionstest/vec.rs @@ -542,6 +542,11 @@ fn test_split_off() { assert_eq!(vec2, [5, 6]); } +#[test] +fn test_into_iter_count() { + assert_eq!(vec![1, 2, 3].into_iter().count(), 3); +} + #[bench] fn bench_new(b: &mut Bencher) { b.iter(|| { diff --git a/src/libcore/cell.rs b/src/libcore/cell.rs index 9ff447a87f1..c717b608a24 100644 --- a/src/libcore/cell.rs +++ b/src/libcore/cell.rs @@ -144,7 +144,7 @@ use clone::Clone; use cmp::PartialEq; use default::Default; -use marker::{Copy, Send, Sync}; +use marker::{Copy, Send, Sync, Sized}; use ops::{Deref, DerefMut, Drop}; use option::Option; use option::Option::{None, Some}; @@ -266,9 +266,9 @@ impl<T:PartialEq + Copy> PartialEq for Cell<T> { /// /// See the [module-level documentation](index.html) for more. #[stable(feature = "rust1", since = "1.0.0")] -pub struct RefCell<T> { - value: UnsafeCell<T>, +pub struct RefCell<T: ?Sized> { borrow: Cell<BorrowFlag>, + value: UnsafeCell<T>, } /// An enumeration of values returned from the `state` method on a `RefCell<T>`. @@ -328,7 +328,9 @@ impl<T> RefCell<T> { debug_assert!(self.borrow.get() == UNUSED); unsafe { self.value.into_inner() } } +} +impl<T: ?Sized> RefCell<T> { /// Query the current state of this `RefCell` /// /// The returned value can be dispatched on to determine if a call to @@ -449,7 +451,7 @@ impl<T> RefCell<T> { } #[stable(feature = "rust1", since = "1.0.0")] -unsafe impl<T> Send for RefCell<T> where T: Send {} +unsafe impl<T: ?Sized> Send for RefCell<T> where T: Send {} #[stable(feature = "rust1", since = "1.0.0")] impl<T: Clone> Clone for RefCell<T> { @@ -469,7 +471,7 @@ impl<T:Default> Default for RefCell<T> { } #[stable(feature = "rust1", since = "1.0.0")] -impl<T: PartialEq> PartialEq for RefCell<T> { +impl<T: ?Sized + PartialEq> PartialEq for RefCell<T> { #[inline] fn eq(&self, other: &RefCell<T>) -> bool { *self.borrow() == *other.borrow() @@ -519,7 +521,7 @@ impl<'b> Clone for BorrowRef<'b> { /// /// See the [module-level documentation](index.html) for more. #[stable(feature = "rust1", since = "1.0.0")] -pub struct Ref<'b, T:'b> { +pub struct Ref<'b, T: ?Sized + 'b> { // FIXME #12808: strange name to try to avoid interfering with // field accesses of the contained type via Deref _value: &'b T, @@ -527,7 +529,7 @@ pub struct Ref<'b, T:'b> { } #[stable(feature = "rust1", since = "1.0.0")] -impl<'b, T> Deref for Ref<'b, T> { +impl<'b, T: ?Sized> Deref for Ref<'b, T> { type Target = T; #[inline] @@ -582,7 +584,7 @@ impl<'b> BorrowRefMut<'b> { /// /// See the [module-level documentation](index.html) for more. #[stable(feature = "rust1", since = "1.0.0")] -pub struct RefMut<'b, T:'b> { +pub struct RefMut<'b, T: ?Sized + 'b> { // FIXME #12808: strange name to try to avoid interfering with // field accesses of the contained type via Deref _value: &'b mut T, @@ -590,7 +592,7 @@ pub struct RefMut<'b, T:'b> { } #[stable(feature = "rust1", since = "1.0.0")] -impl<'b, T> Deref for RefMut<'b, T> { +impl<'b, T: ?Sized> Deref for RefMut<'b, T> { type Target = T; #[inline] @@ -600,7 +602,7 @@ impl<'b, T> Deref for RefMut<'b, T> { } #[stable(feature = "rust1", since = "1.0.0")] -impl<'b, T> DerefMut for RefMut<'b, T> { +impl<'b, T: ?Sized> DerefMut for RefMut<'b, T> { #[inline] fn deref_mut<'a>(&'a mut self) -> &'a mut T { self._value @@ -633,7 +635,7 @@ impl<'b, T> DerefMut for RefMut<'b, T> { /// recommended to access its fields directly, `get` should be used instead. #[lang="unsafe_cell"] #[stable(feature = "rust1", since = "1.0.0")] -pub struct UnsafeCell<T> { +pub struct UnsafeCell<T: ?Sized> { /// Wrapped value /// /// This field should not be accessed directly, it is made public for static @@ -642,7 +644,7 @@ pub struct UnsafeCell<T> { pub value: T, } -impl<T> !Sync for UnsafeCell<T> {} +impl<T: ?Sized> !Sync for UnsafeCell<T> {} impl<T> UnsafeCell<T> { /// Constructs a new instance of `UnsafeCell` which will wrap the specified @@ -664,7 +666,12 @@ impl<T> UnsafeCell<T> { UnsafeCell { value: value } } - /// Gets a mutable pointer to the wrapped value. + /// Unwraps the value. + /// + /// # Unsafety + /// + /// This function is unsafe because there is no guarantee that this or other threads are + /// currently inspecting the inner value. /// /// # Examples /// @@ -673,22 +680,15 @@ impl<T> UnsafeCell<T> { /// /// let uc = UnsafeCell::new(5); /// - /// let five = uc.get(); + /// let five = unsafe { uc.into_inner() }; /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - pub fn get(&self) -> *mut T { - // FIXME(#23542) Replace with type ascription. - #![allow(trivial_casts)] - &self.value as *const T as *mut T - } + pub unsafe fn into_inner(self) -> T { self.value } +} - /// Unwraps the value. - /// - /// # Unsafety - /// - /// This function is unsafe because there is no guarantee that this or other threads are - /// currently inspecting the inner value. +impl<T: ?Sized> UnsafeCell<T> { + /// Gets a mutable pointer to the wrapped value. /// /// # Examples /// @@ -697,9 +697,14 @@ impl<T> UnsafeCell<T> { /// /// let uc = UnsafeCell::new(5); /// - /// let five = unsafe { uc.into_inner() }; + /// let five = uc.get(); /// ``` #[inline] #[stable(feature = "rust1", since = "1.0.0")] - pub unsafe fn into_inner(self) -> T { self.value } + pub fn get(&self) -> *mut T { + // FIXME(#23542) Replace with type ascription. + #![allow(trivial_casts)] + &self.value as *const T as *mut T + } + } diff --git a/src/libcore/fmt/mod.rs b/src/libcore/fmt/mod.rs index 73778bfd038..f8a1ef96bcc 100644 --- a/src/libcore/fmt/mod.rs +++ b/src/libcore/fmt/mod.rs @@ -1062,7 +1062,7 @@ impl<T: Copy + Debug> Debug for Cell<T> { } #[stable(feature = "rust1", since = "1.0.0")] -impl<T: Debug> Debug for RefCell<T> { +impl<T: ?Sized + Debug> Debug for RefCell<T> { fn fmt(&self, f: &mut Formatter) -> Result { match self.borrow_state() { BorrowState::Unused | BorrowState::Reading => { @@ -1074,14 +1074,14 @@ impl<T: Debug> Debug for RefCell<T> { } #[stable(feature = "rust1", since = "1.0.0")] -impl<'b, T: Debug> Debug for Ref<'b, T> { +impl<'b, T: ?Sized + Debug> Debug for Ref<'b, T> { fn fmt(&self, f: &mut Formatter) -> Result { Debug::fmt(&**self, f) } } #[stable(feature = "rust1", since = "1.0.0")] -impl<'b, T: Debug> Debug for RefMut<'b, T> { +impl<'b, T: ?Sized + Debug> Debug for RefMut<'b, T> { fn fmt(&self, f: &mut Formatter) -> Result { Debug::fmt(&*(self.deref()), f) } diff --git a/src/libcore/hash/sip.rs b/src/libcore/hash/sip.rs index be419e2cdad..a92b72e0f00 100644 --- a/src/libcore/hash/sip.rs +++ b/src/libcore/hash/sip.rs @@ -111,6 +111,7 @@ impl SipHasher { state } + #[inline] fn reset(&mut self) { self.length = 0; self.v0 = self.k0 ^ 0x736f6d6570736575; @@ -120,6 +121,7 @@ impl SipHasher { self.ntail = 0; } + #[inline] fn write(&mut self, msg: &[u8]) { let length = msg.len(); self.length += length; @@ -173,6 +175,7 @@ impl Hasher for SipHasher { self.write(msg) } + #[inline] fn finish(&self) -> u64 { let mut v0 = self.v0; let mut v1 = self.v1; diff --git a/src/libcoretest/cell.rs b/src/libcoretest/cell.rs index 85dd1039003..0bd0b66318f 100644 --- a/src/libcoretest/cell.rs +++ b/src/libcoretest/cell.rs @@ -159,3 +159,27 @@ fn refcell_default() { let cell: RefCell<u64> = Default::default(); assert_eq!(0, *cell.borrow()); } + +#[test] +fn unsafe_cell_unsized() { + let cell: &UnsafeCell<[i32]> = &UnsafeCell::new([1, 2, 3]); + { + let val: &mut [i32] = unsafe { &mut *cell.get() }; + val[0] = 4; + val[2] = 5; + } + let comp: &mut [i32] = &mut [4, 2, 5]; + assert_eq!(unsafe { &mut *cell.get() }, comp); +} + +#[test] +fn refcell_unsized() { + let cell: &RefCell<[i32]> = &RefCell::new([1, 2, 3]); + { + let b = &mut *cell.borrow_mut(); + b[0] = 4; + b[2] = 5; + } + let comp: &mut [i32] = &mut [4, 2, 5]; + assert_eq!(&*cell.borrow(), comp); +} diff --git a/src/librustc_trans/trans/_match.rs b/src/librustc_trans/trans/_match.rs index 060dde02c2d..84d464e8f07 100644 --- a/src/librustc_trans/trans/_match.rs +++ b/src/librustc_trans/trans/_match.rs @@ -210,6 +210,7 @@ use trans::consts; use trans::datum::*; use trans::debuginfo::{self, DebugLoc, ToDebugLoc}; use trans::expr::{self, Dest}; +use trans::monomorphize; use trans::tvec; use trans::type_of; use middle::ty::{self, Ty}; @@ -1076,9 +1077,39 @@ fn compile_submatch_continue<'a, 'p, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, let adt_vals = if any_irrefutable_adt_pat(bcx.tcx(), m, col) { let repr = adt::represent_type(bcx.ccx(), left_ty); let arg_count = adt::num_args(&*repr, 0); - let field_vals: Vec<ValueRef> = (0..arg_count).map(|ix| - adt::trans_field_ptr(bcx, &*repr, val, 0, ix) + let (arg_count, struct_val) = if type_is_sized(bcx.tcx(), left_ty) { + (arg_count, val) + } else { + // For an unsized ADT (i.e. DST struct), we need to treat + // the last field specially: instead of simply passing a + // ValueRef pointing to that field, as with all the others, + // we skip it and instead construct a 'fat ptr' below. + (arg_count - 1, Load(bcx, expr::get_dataptr(bcx, val))) + }; + let mut field_vals: Vec<ValueRef> = (0..arg_count).map(|ix| + adt::trans_field_ptr(bcx, &*repr, struct_val, 0, ix) ).collect(); + + match left_ty.sty { + ty::ty_struct(def_id, substs) if !type_is_sized(bcx.tcx(), left_ty) => { + // The last field is technically unsized but + // since we can only ever match that field behind + // a reference we construct a fat ptr here. + let fields = ty::lookup_struct_fields(bcx.tcx(), def_id); + let unsized_ty = fields.iter().last().map(|field| { + let fty = ty::lookup_field_type(bcx.tcx(), def_id, field.id, substs); + monomorphize::normalize_associated_type(bcx.tcx(), &fty) + }).unwrap(); + let llty = type_of::type_of(bcx.ccx(), unsized_ty); + let scratch = alloca_no_lifetime(bcx, llty, "__struct_field_fat_ptr"); + let data = adt::trans_field_ptr(bcx, &*repr, struct_val, 0, arg_count); + let len = Load(bcx, expr::get_len(bcx, val)); + Store(bcx, data, expr::get_dataptr(bcx, scratch)); + Store(bcx, len, expr::get_len(bcx, scratch)); + field_vals.push(scratch); + } + _ => {} + } Some(field_vals) } else if any_uniq_pat(m, col) || any_region_pat(m, col) { Some(vec!(Load(bcx, val))) diff --git a/src/libstd/collections/hash/map.rs b/src/libstd/collections/hash/map.rs index ec130e8233a..f82c1653be1 100644 --- a/src/libstd/collections/hash/map.rs +++ b/src/libstd/collections/hash/map.rs @@ -1600,6 +1600,7 @@ impl RandomState { reason = "hashing an hash maps may be altered")] impl HashState for RandomState { type Hasher = SipHasher; + #[inline] fn hasher(&self) -> SipHasher { SipHasher::new_with_keys(self.k0, self.k1) } diff --git a/src/libstd/net/ip.rs b/src/libstd/net/ip.rs index 9fd69840f7f..bd0408b21d2 100644 --- a/src/libstd/net/ip.rs +++ b/src/libstd/net/ip.rs @@ -113,10 +113,13 @@ impl Ipv4Addr { /// Returns true if the address appears to be globally routable. /// - /// Non-globally-routable networks include the private networks (10.0.0.0/8, - /// 172.16.0.0/12 and 192.168.0.0/16), the loopback network (127.0.0.0/8), - /// the link-local network (169.254.0.0/16), the broadcast address (255.255.255.255/32) and - /// the test networks used for documentation (192.0.2.0/24, 198.51.100.0/24 and 203.0.113.0/24). + /// The following return false: + /// + /// - private address (10.0.0.0/8, 172.16.0.0/12 and 192.168.0.0/16) + /// - the loopback address (127.0.0.0/8) + /// - the link-local address (169.254.0.0/16) + /// - the broadcast address (255.255.255.255/32) + /// - test addresses used for documentation (192.0.2.0/24, 198.51.100.0/24 and 203.0.113.0/24) pub fn is_global(&self) -> bool { !self.is_private() && !self.is_loopback() && !self.is_link_local() && !self.is_broadcast() && !self.is_documentation() @@ -284,9 +287,11 @@ impl Ipv6Addr { /// Returns true if the address appears to be globally routable. /// - /// Non-globally-routable networks include the loopback address; the - /// link-local, site-local, and unique local unicast addresses; and the - /// interface-, link-, realm-, admin- and site-local multicast addresses. + /// The following return false: + /// + /// - the loopback address + /// - link-local, site-local, and unique local unicast addresses + /// - interface-, link-, realm-, admin- and site-local multicast addresses pub fn is_global(&self) -> bool { match self.multicast_scope() { Some(Ipv6MulticastScope::Global) => true, @@ -315,9 +320,12 @@ impl Ipv6Addr { /// Returns true if the address is a globally routable unicast address. /// - /// Non-globally-routable unicast addresses include the loopback address, - /// the link-local addresses, the deprecated site-local addresses and the - /// unique local addresses. + /// The following return false: + /// + /// - the loopback address + /// - the link-local addresses + /// - the (deprecated) site-local addresses + /// - unique local addresses pub fn is_unicast_global(&self) -> bool { !self.is_multicast() && !self.is_loopback() && !self.is_unicast_link_local() diff --git a/src/libstd/sync/mutex.rs b/src/libstd/sync/mutex.rs index 30c7407a96d..222aff9188a 100644 --- a/src/libstd/sync/mutex.rs +++ b/src/libstd/sync/mutex.rs @@ -112,7 +112,7 @@ use sys_common::poison::{self, TryLockError, TryLockResult, LockResult}; /// *guard += 1; /// ``` #[stable(feature = "rust1", since = "1.0.0")] -pub struct Mutex<T> { +pub struct Mutex<T: ?Sized> { // Note that this static mutex is in a *box*, not inlined into the struct // itself. Once a native mutex has been used once, its address can never // change (it can't be moved). This mutex type can be safely moved at any @@ -124,9 +124,9 @@ pub struct Mutex<T> { // these are the only places where `T: Send` matters; all other // functionality works fine on a single thread. -unsafe impl<T: Send> Send for Mutex<T> { } +unsafe impl<T: ?Sized + Send> Send for Mutex<T> { } -unsafe impl<T: Send> Sync for Mutex<T> { } +unsafe impl<T: ?Sized + Send> Sync for Mutex<T> { } /// The static mutex type is provided to allow for static allocation of mutexes. /// @@ -164,7 +164,7 @@ pub struct StaticMutex { /// `Deref` and `DerefMut` implementations #[must_use] #[stable(feature = "rust1", since = "1.0.0")] -pub struct MutexGuard<'a, T: 'a> { +pub struct MutexGuard<'a, T: ?Sized + 'a> { // funny underscores due to how Deref/DerefMut currently work (they // disregard field privacy). __lock: &'a StaticMutex, @@ -172,7 +172,7 @@ pub struct MutexGuard<'a, T: 'a> { __poison: poison::Guard, } -impl<'a, T> !marker::Send for MutexGuard<'a, T> {} +impl<'a, T: ?Sized> !marker::Send for MutexGuard<'a, T> {} /// Static initialization of a mutex. This constant can be used to initialize /// other mutex constants. @@ -192,7 +192,9 @@ impl<T> Mutex<T> { data: UnsafeCell::new(t), } } +} +impl<T: ?Sized> Mutex<T> { /// Acquires a mutex, blocking the current task until it is able to do so. /// /// This function will block the local task until it is available to acquire @@ -245,7 +247,7 @@ impl<T> Mutex<T> { } #[stable(feature = "rust1", since = "1.0.0")] -impl<T> Drop for Mutex<T> { +impl<T: ?Sized> Drop for Mutex<T> { fn drop(&mut self) { // This is actually safe b/c we know that there is no further usage of // this mutex (it's up to the user to arrange for a mutex to get @@ -255,12 +257,12 @@ impl<T> Drop for Mutex<T> { } #[stable(feature = "rust1", since = "1.0.0")] -impl<T: fmt::Debug + 'static> fmt::Debug for Mutex<T> { +impl<T: ?Sized + fmt::Debug + 'static> fmt::Debug for Mutex<T> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self.try_lock() { - Ok(guard) => write!(f, "Mutex {{ data: {:?} }}", *guard), + Ok(guard) => write!(f, "Mutex {{ data: {:?} }}", &*guard), Err(TryLockError::Poisoned(err)) => { - write!(f, "Mutex {{ data: Poisoned({:?}) }}", **err.get_ref()) + write!(f, "Mutex {{ data: Poisoned({:?}) }}", &**err.get_ref()) }, Err(TryLockError::WouldBlock) => write!(f, "Mutex {{ <locked> }}") } @@ -310,7 +312,7 @@ impl StaticMutex { } } -impl<'mutex, T> MutexGuard<'mutex, T> { +impl<'mutex, T: ?Sized> MutexGuard<'mutex, T> { fn new(lock: &'mutex StaticMutex, data: &'mutex UnsafeCell<T>) -> LockResult<MutexGuard<'mutex, T>> { @@ -325,7 +327,7 @@ impl<'mutex, T> MutexGuard<'mutex, T> { } #[stable(feature = "rust1", since = "1.0.0")] -impl<'mutex, T> Deref for MutexGuard<'mutex, T> { +impl<'mutex, T: ?Sized> Deref for MutexGuard<'mutex, T> { type Target = T; fn deref<'a>(&'a self) -> &'a T { @@ -333,14 +335,14 @@ impl<'mutex, T> Deref for MutexGuard<'mutex, T> { } } #[stable(feature = "rust1", since = "1.0.0")] -impl<'mutex, T> DerefMut for MutexGuard<'mutex, T> { +impl<'mutex, T: ?Sized> DerefMut for MutexGuard<'mutex, T> { fn deref_mut<'a>(&'a mut self) -> &'a mut T { unsafe { &mut *self.__data.get() } } } #[stable(feature = "rust1", since = "1.0.0")] -impl<'a, T> Drop for MutexGuard<'a, T> { +impl<'a, T: ?Sized> Drop for MutexGuard<'a, T> { #[inline] fn drop(&mut self) { unsafe { @@ -350,11 +352,11 @@ impl<'a, T> Drop for MutexGuard<'a, T> { } } -pub fn guard_lock<'a, T>(guard: &MutexGuard<'a, T>) -> &'a sys::Mutex { +pub fn guard_lock<'a, T: ?Sized>(guard: &MutexGuard<'a, T>) -> &'a sys::Mutex { &guard.__lock.lock } -pub fn guard_poison<'a, T>(guard: &MutexGuard<'a, T>) -> &'a poison::Flag { +pub fn guard_poison<'a, T: ?Sized>(guard: &MutexGuard<'a, T>) -> &'a poison::Flag { &guard.__lock.poison } @@ -528,4 +530,16 @@ mod tests { let lock = arc.lock().unwrap(); assert_eq!(*lock, 2); } + + #[test] + fn test_mutex_unsized() { + let mutex: &Mutex<[i32]> = &Mutex::new([1, 2, 3]); + { + let b = &mut *mutex.lock().unwrap(); + b[0] = 4; + b[2] = 5; + } + let comp: &[i32] = &[4, 2, 5]; + assert_eq!(&*mutex.lock().unwrap(), comp); + } } diff --git a/src/libstd/sync/rwlock.rs b/src/libstd/sync/rwlock.rs index a133bb01b61..9294fb64783 100644 --- a/src/libstd/sync/rwlock.rs +++ b/src/libstd/sync/rwlock.rs @@ -60,13 +60,13 @@ use sys_common::rwlock as sys; /// } // write lock is dropped here /// ``` #[stable(feature = "rust1", since = "1.0.0")] -pub struct RwLock<T> { +pub struct RwLock<T: ?Sized> { inner: Box<StaticRwLock>, data: UnsafeCell<T>, } -unsafe impl<T: Send + Sync> Send for RwLock<T> {} -unsafe impl<T: Send + Sync> Sync for RwLock<T> {} +unsafe impl<T: ?Sized + Send + Sync> Send for RwLock<T> {} +unsafe impl<T: ?Sized + Send + Sync> Sync for RwLock<T> {} /// Structure representing a statically allocated RwLock. /// @@ -111,24 +111,24 @@ pub const RW_LOCK_INIT: StaticRwLock = StaticRwLock { /// dropped. #[must_use] #[stable(feature = "rust1", since = "1.0.0")] -pub struct RwLockReadGuard<'a, T: 'a> { +pub struct RwLockReadGuard<'a, T: ?Sized + 'a> { __lock: &'a StaticRwLock, __data: &'a UnsafeCell<T>, } -impl<'a, T> !marker::Send for RwLockReadGuard<'a, T> {} +impl<'a, T: ?Sized> !marker::Send for RwLockReadGuard<'a, T> {} /// RAII structure used to release the exclusive write access of a lock when /// dropped. #[must_use] #[stable(feature = "rust1", since = "1.0.0")] -pub struct RwLockWriteGuard<'a, T: 'a> { +pub struct RwLockWriteGuard<'a, T: ?Sized + 'a> { __lock: &'a StaticRwLock, __data: &'a UnsafeCell<T>, __poison: poison::Guard, } -impl<'a, T> !marker::Send for RwLockWriteGuard<'a, T> {} +impl<'a, T: ?Sized> !marker::Send for RwLockWriteGuard<'a, T> {} impl<T> RwLock<T> { /// Creates a new instance of an `RwLock<T>` which is unlocked. @@ -144,7 +144,9 @@ impl<T> RwLock<T> { pub fn new(t: T) -> RwLock<T> { RwLock { inner: box RW_LOCK_INIT, data: UnsafeCell::new(t) } } +} +impl<T: ?Sized> RwLock<T> { /// Locks this rwlock with shared read access, blocking the current thread /// until it can be acquired. /// @@ -250,19 +252,19 @@ impl<T> RwLock<T> { } #[stable(feature = "rust1", since = "1.0.0")] -impl<T> Drop for RwLock<T> { +impl<T: ?Sized> Drop for RwLock<T> { fn drop(&mut self) { unsafe { self.inner.lock.destroy() } } } #[stable(feature = "rust1", since = "1.0.0")] -impl<T: fmt::Debug> fmt::Debug for RwLock<T> { +impl<T: ?Sized + fmt::Debug> fmt::Debug for RwLock<T> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self.try_read() { - Ok(guard) => write!(f, "RwLock {{ data: {:?} }}", *guard), + Ok(guard) => write!(f, "RwLock {{ data: {:?} }}", &*guard), Err(TryLockError::Poisoned(err)) => { - write!(f, "RwLock {{ data: Poisoned({:?}) }}", **err.get_ref()) + write!(f, "RwLock {{ data: Poisoned({:?}) }}", &**err.get_ref()) }, Err(TryLockError::WouldBlock) => write!(f, "RwLock {{ <locked> }}") } @@ -341,8 +343,7 @@ impl StaticRwLock { } } -impl<'rwlock, T> RwLockReadGuard<'rwlock, T> { - +impl<'rwlock, T: ?Sized> RwLockReadGuard<'rwlock, T> { fn new(lock: &'rwlock StaticRwLock, data: &'rwlock UnsafeCell<T>) -> LockResult<RwLockReadGuard<'rwlock, T>> { poison::map_result(lock.poison.borrow(), |_| { @@ -353,8 +354,8 @@ impl<'rwlock, T> RwLockReadGuard<'rwlock, T> { }) } } -impl<'rwlock, T> RwLockWriteGuard<'rwlock, T> { +impl<'rwlock, T: ?Sized> RwLockWriteGuard<'rwlock, T> { fn new(lock: &'rwlock StaticRwLock, data: &'rwlock UnsafeCell<T>) -> LockResult<RwLockWriteGuard<'rwlock, T>> { poison::map_result(lock.poison.borrow(), |guard| { @@ -368,33 +369,35 @@ impl<'rwlock, T> RwLockWriteGuard<'rwlock, T> { } #[stable(feature = "rust1", since = "1.0.0")] -impl<'rwlock, T> Deref for RwLockReadGuard<'rwlock, T> { +impl<'rwlock, T: ?Sized> Deref for RwLockReadGuard<'rwlock, T> { type Target = T; fn deref(&self) -> &T { unsafe { &*self.__data.get() } } } + #[stable(feature = "rust1", since = "1.0.0")] -impl<'rwlock, T> Deref for RwLockWriteGuard<'rwlock, T> { +impl<'rwlock, T: ?Sized> Deref for RwLockWriteGuard<'rwlock, T> { type Target = T; fn deref(&self) -> &T { unsafe { &*self.__data.get() } } } + #[stable(feature = "rust1", since = "1.0.0")] -impl<'rwlock, T> DerefMut for RwLockWriteGuard<'rwlock, T> { +impl<'rwlock, T: ?Sized> DerefMut for RwLockWriteGuard<'rwlock, T> { fn deref_mut(&mut self) -> &mut T { unsafe { &mut *self.__data.get() } } } #[stable(feature = "rust1", since = "1.0.0")] -impl<'a, T> Drop for RwLockReadGuard<'a, T> { +impl<'a, T: ?Sized> Drop for RwLockReadGuard<'a, T> { fn drop(&mut self) { unsafe { self.__lock.lock.read_unlock(); } } } #[stable(feature = "rust1", since = "1.0.0")] -impl<'a, T> Drop for RwLockWriteGuard<'a, T> { +impl<'a, T: ?Sized> Drop for RwLockWriteGuard<'a, T> { fn drop(&mut self) { self.__lock.poison.done(&self.__poison); unsafe { self.__lock.lock.write_unlock(); } @@ -562,4 +565,16 @@ mod tests { let lock = arc.read().unwrap(); assert_eq!(*lock, 2); } + + #[test] + fn test_rwlock_unsized() { + let rw: &RwLock<[i32]> = &RwLock::new([1, 2, 3]); + { + let b = &mut *rw.write().unwrap(); + b[0] = 4; + b[2] = 5; + } + let comp: &[i32] = &[4, 2, 5]; + assert_eq!(&*rw.read().unwrap(), comp); + } } diff --git a/src/libtest/lib.rs b/src/libtest/lib.rs index b68b1d28b35..9cbfe283cbd 100644 --- a/src/libtest/lib.rs +++ b/src/libtest/lib.rs @@ -139,7 +139,7 @@ impl TestDesc { } /// Represents a benchmark function. -pub trait TDynBenchFn { +pub trait TDynBenchFn: Send { fn run(&self, harness: &mut Bencher); } @@ -285,7 +285,7 @@ pub struct TestOpts { pub filter: Option<String>, pub run_ignored: bool, pub run_tests: bool, - pub run_benchmarks: bool, + pub bench_benchmarks: bool, pub logfile: Option<PathBuf>, pub nocapture: bool, pub color: ColorConfig, @@ -298,7 +298,7 @@ impl TestOpts { filter: None, run_ignored: false, run_tests: false, - run_benchmarks: false, + bench_benchmarks: false, logfile: None, nocapture: false, color: AutoColor, @@ -377,8 +377,8 @@ pub fn parse_opts(args: &[String]) -> Option<OptRes> { let logfile = matches.opt_str("logfile"); let logfile = logfile.map(|s| PathBuf::from(&s)); - let run_benchmarks = matches.opt_present("bench"); - let run_tests = ! run_benchmarks || + let bench_benchmarks = matches.opt_present("bench"); + let run_tests = ! bench_benchmarks || matches.opt_present("test"); let mut nocapture = matches.opt_present("nocapture"); @@ -400,7 +400,7 @@ pub fn parse_opts(args: &[String]) -> Option<OptRes> { filter: filter, run_ignored: run_ignored, run_tests: run_tests, - run_benchmarks: run_benchmarks, + bench_benchmarks: bench_benchmarks, logfile: logfile, nocapture: nocapture, color: color, @@ -778,7 +778,11 @@ fn run_tests<F>(opts: &TestOpts, mut callback: F) -> io::Result<()> where F: FnMut(TestEvent) -> io::Result<()>, { - let filtered_tests = filter_tests(opts, tests); + let mut filtered_tests = filter_tests(opts, tests); + if !opts.bench_benchmarks { + filtered_tests = convert_benchmarks_to_tests(filtered_tests); + } + let filtered_descs = filtered_tests.iter() .map(|t| t.desc.clone()) .collect(); @@ -824,13 +828,15 @@ fn run_tests<F>(opts: &TestOpts, pending -= 1; } - // All benchmarks run at the end, in serial. - // (this includes metric fns) - for b in filtered_benchs_and_metrics { - try!(callback(TeWait(b.desc.clone(), b.testfn.padding()))); - run_test(opts, !opts.run_benchmarks, b, tx.clone()); - let (test, result, stdout) = rx.recv().unwrap(); - try!(callback(TeResult(test, result, stdout))); + if opts.bench_benchmarks { + // All benchmarks run at the end, in serial. + // (this includes metric fns) + for b in filtered_benchs_and_metrics { + try!(callback(TeWait(b.desc.clone(), b.testfn.padding()))); + run_test(opts, false, b, tx.clone()); + let (test, result, stdout) = rx.recv().unwrap(); + try!(callback(TeResult(test, result, stdout))); + } } Ok(()) } @@ -893,6 +899,22 @@ pub fn filter_tests(opts: &TestOpts, tests: Vec<TestDescAndFn>) -> Vec<TestDescA filtered } +pub fn convert_benchmarks_to_tests(tests: Vec<TestDescAndFn>) -> Vec<TestDescAndFn> { + // convert benchmarks to tests, if we're not benchmarking them + tests.into_iter().map(|x| { + let testfn = match x.testfn { + DynBenchFn(bench) => { + DynTestFn(Box::new(move || bench::run_once(|b| bench.run(b)))) + } + StaticBenchFn(benchfn) => { + DynTestFn(Box::new(move || bench::run_once(|b| benchfn(b)))) + } + f => f + }; + TestDescAndFn { desc: x.desc, testfn: testfn } + }).collect() +} + pub fn run_test(opts: &TestOpts, force_ignore: bool, test: TestDescAndFn, @@ -1159,6 +1181,15 @@ pub mod bench { mb_s: mb_s as usize } } + + pub fn run_once<F>(f: F) where F: FnOnce(&mut Bencher) { + let mut bs = Bencher { + iterations: 0, + dur: Duration::nanoseconds(0), + bytes: 0 + }; + bs.bench_n(1, f); + } } #[cfg(test)] diff --git a/src/test/compile-fail/bad-sized.rs b/src/test/compile-fail/bad-sized.rs index fca74e457c2..8c13ff70515 100644 --- a/src/test/compile-fail/bad-sized.rs +++ b/src/test/compile-fail/bad-sized.rs @@ -8,14 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::cell::RefCell; - trait Trait {} pub fn main() { let x: Vec<Trait + Sized> = Vec::new(); //~^ ERROR the trait `core::marker::Sized` is not implemented //~^^ ERROR the trait `core::marker::Sized` is not implemented - let x: Vec<Box<RefCell<Trait + Sized>>> = Vec::new(); - //~^ ERROR the trait `core::marker::Sized` is not implemented } diff --git a/src/test/run-pass/issue-23261.rs b/src/test/run-pass/issue-23261.rs new file mode 100644 index 00000000000..fc806f5429a --- /dev/null +++ b/src/test/run-pass/issue-23261.rs @@ -0,0 +1,70 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or +// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license +// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// Matching on a DST struct should not trigger an LLVM assertion. + +struct Foo<T: ?Sized> { + a: i32, + inner: T +} + +trait Get { + fn get(&self) -> i32; +} + +impl Get for i32 { + fn get(&self) -> i32 { + *self + } +} + +fn check_val(val: &Foo<[u8]>) { + match *val { + Foo { a, .. } => { + assert_eq!(a, 32); + } + } +} + +fn check_dst_val(val: &Foo<[u8]>) { + match *val { + Foo { ref inner, .. } => { + assert_eq!(inner, [1, 2, 3]); + } + } +} + +fn check_both(val: &Foo<[u8]>) { + match *val { + Foo { a, ref inner } => { + assert_eq!(a, 32); + assert_eq!(inner, [1, 2, 3]); + } + } +} + +fn check_trait_obj(val: &Foo<Get>) { + match *val { + Foo { a, ref inner } => { + assert_eq!(a, 32); + assert_eq!(inner.get(), 32); + } + } +} + +fn main() { + let foo: &Foo<[u8]> = &Foo { a: 32, inner: [1, 2, 3] }; + check_val(foo); + check_dst_val(foo); + check_both(foo); + + let foo: &Foo<Get> = &Foo { a: 32, inner: 32 }; + check_trait_obj(foo); +} diff --git a/src/test/run-pass/out-of-stack.rs b/src/test/run-pass/out-of-stack.rs index d90b88cbfd5..cff46f80cf4 100644 --- a/src/test/run-pass/out-of-stack.rs +++ b/src/test/run-pass/out-of-stack.rs @@ -9,6 +9,7 @@ // except according to those terms. // ignore-android: FIXME (#20004) +// ignore-musl #![feature(asm)] |
